diff --git a/.devcontainer/portability-centos-stream-8-python3.9-minimal/devcontainer.json b/.devcontainer/portability-centos-stream-8-python3.9-minimal/devcontainer.json deleted file mode 100644 index 5fa562346cb..00000000000 --- a/.devcontainer/portability-centos-stream-8-python3.9-minimal/devcontainer.json +++ /dev/null @@ -1,25 +0,0 @@ -// The command "tox -e update_docker_platforms" -// creates .devcontainer/portability-*-*/devcontainer.json -// from .devcontainer/portability-devcontainer.json.in -// See https://aka.ms/devcontainer.json for format details. -{ - "name": "centos-stream-8-python3.9-minimal (≥ 8-core)", - "build": { - "dockerfile": "portability-Dockerfile", - // See tox.ini for definitions - "args": { - "SYSTEM_FACTOR": "centos-stream-8-python3.9", - "PACKAGE_FACTOR": "minimal", - "DOCKER_TARGET": "with-targets", - "DOCKER_TAG": "dev" - } - }, - "containerEnv": { - "MAKE": "make -j4" - }, - "onCreateCommand": ".devcontainer/onCreate.sh", - "updateContentCommand": ".devcontainer/portability-updateContent.sh", - "extensions": [ - "ms-python.python" - ] -} diff --git a/.devcontainer/portability-centos-stream-8-python3.9-minimal/portability-Dockerfile b/.devcontainer/portability-centos-stream-8-python3.9-minimal/portability-Dockerfile deleted file mode 120000 index 692e2a79d64..00000000000 --- a/.devcontainer/portability-centos-stream-8-python3.9-minimal/portability-Dockerfile +++ /dev/null @@ -1 +0,0 @@ -../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-centos-stream-8-python3.9-standard/devcontainer.json b/.devcontainer/portability-centos-stream-8-python3.9-standard/devcontainer.json deleted file mode 100644 index 0c76ce86244..00000000000 --- a/.devcontainer/portability-centos-stream-8-python3.9-standard/devcontainer.json +++ /dev/null @@ -1,25 +0,0 @@ -// The command "tox -e update_docker_platforms" -// creates .devcontainer/portability-*-*/devcontainer.json -// from .devcontainer/portability-devcontainer.json.in -// See https://aka.ms/devcontainer.json for format details. -{ - "name": "centos-stream-8-python3.9-standard (≥ 8-core)", - "build": { - "dockerfile": "portability-Dockerfile", - // See tox.ini for definitions - "args": { - "SYSTEM_FACTOR": "centos-stream-8-python3.9", - "PACKAGE_FACTOR": "standard", - "DOCKER_TARGET": "with-targets", - "DOCKER_TAG": "dev" - } - }, - "containerEnv": { - "MAKE": "make -j4" - }, - "onCreateCommand": ".devcontainer/onCreate.sh", - "updateContentCommand": ".devcontainer/portability-updateContent.sh", - "extensions": [ - "ms-python.python" - ] -} diff --git a/.devcontainer/portability-centos-stream-8-python3.9-standard/portability-Dockerfile b/.devcontainer/portability-centos-stream-8-python3.9-standard/portability-Dockerfile deleted file mode 120000 index 692e2a79d64..00000000000 --- a/.devcontainer/portability-centos-stream-8-python3.9-standard/portability-Dockerfile +++ /dev/null @@ -1 +0,0 @@ -../portability-Dockerfile \ No newline at end of file diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index 6860bd6e460..0ce9a1f142b 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -118,7 +118,6 @@ jobs: "linuxmint-21.2", "fedora-38", "fedora-39", - "centos-stream-8-python3.9", "centos-stream-9-python3.9", "almalinux-8-python3.9", "gentoo-python3.10", diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 9dfb8d7d221..01d05b25b5d 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -130,10 +130,10 @@ jobs: new_version=$(docker exec BUILD cat src/VERSION.txt) mkdir -p docs/ docker cp BUILD:/sage/local/share/doc/sage/html docs/ - # Wipe out chronic diffs between old doc and new doc + # Wipe out chronic diffs of old doc against new doc (cd docs && \ find . -name "*.html" | xargs sed -i -e '/class="sidebar-brand-text"/ s/Sage [0-9a-z.]* /Sage '"$new_version"' /' \ - -e '/This is documentation for/ s/ built with GitHub PR [^.]*././' \ + -e '/;,\;; d') # Create git repo from old doc @@ -166,7 +166,13 @@ jobs: docker cp BUILD:/sage/local/share/doc/sage/html docs docker cp BUILD:/sage/local/share/doc/sage/index.html docs (cd docs && git commit -a -m 'new') + # Wipe out chronic diffs of new doc against old doc + (cd docs && \ + find . -name "*.html" | xargs sed -i -e '/This is documentation for/ s/ built with GitHub PR .*. Doc/. Doc/' \ + -e '/>>'"'"', `<<<'"')dnl" >> $a done + eval $(sage-package properties --format=shell :all:) spkg_configures="" # initialize SAGE_ENABLE... options for standard packages for pkgname in $(sage-package list :standard:); do @@ -62,28 +61,36 @@ AS_VAR_SET_IF([SAGE_ENABLE_$pkgname], [], [AS_VAR_SET([SAGE_ENABLE_$pkgname], [y done # --enable-SPKG options for pkgname in $(sage-package list :optional: :experimental:); do + eval DIR=\$path_$pkgname pkgtype=\$type_$pkgname pkgsource=\$source_$pkgname + case "$pkgname:$pkgsource" in + *:pip) # Issue #29629: Temporary solution for Sage 9.1: Do not provide # --enable-SPKG options for installing pip packages - if [ ! -f build/pkgs/$pkgname/requirements.txt ]; then - pkgtype="$(cat build/pkgs/$pkgname/type)" - # Issue #29124: Do not provide --enable-_recommended and similar - case "$pkgname" in - _*) ;; - *) spkg_configures="$spkg_configures + ;; + _*:*) + # Issue #29124: Do not provide --enable-_recommended and similar + ;; + *:none) + # Issue #31163: Just an optional dummy package + spkg_configures="$spkg_configures AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed])" - if [ -f build/pkgs/$pkgname/spkg-install -o -f build/pkgs/$pkgname/spkg-install.in ]; then - # Issue #31163: Not just an optional dummy package - spkg_configures="$spkg_configures -SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(grep -v ^= build/pkgs/$pkgname/SPKG.rst | head -n1 2>/dev/null || echo $pkgname)])" - fi - ;; - esac - fi + ;; + *:*) + spkg_configures="$spkg_configures +AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed])" + spkg_configures="$spkg_configures +SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(grep -v ^= "$DIR/SPKG.rst" | head -n1 2>/dev/null || echo $pkgname)])" + ;; + esac done + cat >> m4/sage_spkg_configures.m4 <> m4/sage_spkg_configures.m4 - cat >> m4/sage_spkg_configures.m4 <>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(sage-get-system-packages install-requires ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions.m4 - echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(sage-get-system-packages install-requires-toml ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions_toml.m4 - fi + eval DIR=\$path_$pkgname pkgtype=\$type_$pkgname SPKG_SOURCE=\$source_$pkgname SPKG_TREE_VAR=\$trees_$pkgname + if test -f "$DIR/requirements.txt" -o -f "$DIR/version_requirements.txt"; then + # A Python package + echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(sage-get-system-packages install-requires ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions.m4 + INSTALL_REQUIRES_TOML= + echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(sage-get-system-packages install-requires-toml ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions_toml.m4 + echo "m4_define([SPKG_INSTALL_REQUIRES_${pkgname}], [[$(echo $(sage-get-system-packages install-requires-toml ${pkgname} | sed 's/"/\\"/g'))]])dnl" >> m4/sage_spkg_configures.m4 fi spkg_finalizes="$spkg_finalizes SAGE_SPKG_FINALIZE([$pkgname], [$pkgtype], [$SPKG_SOURCE], [$SPKG_TREE_VAR])" done - echo "$spkg_finalizes" >> m4/sage_spkg_configures.m4 for a in m4/sage_spkg_versions.m4 m4/sage_spkg_versions_toml.m4; do echo 'changequote(>>>`<<<, >>>'"'"'<<<)dnl' >> $a done + cat >> m4/sage_spkg_configures.m4 <&2 "bootstrap:$LINENO: Nothing to do for $pkgname"; fi) || exit 1 + eval DIR=\$path_$pkgname + (cd "$DIR" && if [ -x bootstrap ]; then ./bootstrap; else echo >&2 "bootstrap:$LINENO: Nothing to do for $pkgname"; fi) || exit 1 done if [ $# != 0 ]; then @@ -196,10 +187,10 @@ SAGE_SPKG_FINALIZE([$pkgname], [$pkgtype], [$SPKG_SOURCE], [$SPKG_TREE_VAR])" bootstrap_download () { SAGE_DL_LOGLEVEL="" [ "${BOOTSTRAP_QUIET}" = "yes" ] && SAGE_DL_LOGLEVEL="--log=WARNING" - sage-download-file ${SAGE_DL_LOGLEVEL} configure-$CONFVERSION.tar.gz + CONFBALL=$(sage-package download $SAGE_DL_LOGLEVEL configure) if [ $? -ne 0 ]; then - echo >&2 "Error: downloading configure-$CONFVERSION.tar.gz failed" + echo >&2 "Error: downloading configure tarball failed" exit 1 fi @@ -255,16 +246,8 @@ save () { build/pkgs/setuptools/version_requirements.txt \ build/pkgs/wheel/version_requirements.txt - # Update version - echo "$NEWCONFVERSION" >$PKG/package-version.txt - - # Compute checksum - if [ "${BOOTSTRAP_QUIET}" = "no" ]; then - sage-package fix-checksum configure - else - # Hide the "Updating checksum..." message - sage-package fix-checksum configure > /dev/null - fi + # Update version; this re-computes the checksum + sage-package update configure "$NEWCONFVERSION" } @@ -304,7 +287,6 @@ do done shift $(($OPTIND - 1)) export BOOTSTRAP_QUIET -CONFBALL="upstream/configure-$CONFVERSION.tar.gz" if [ $DOWNLOAD$SAVE = yesyes ]; then echo >&2 "$0: refusing to download and save." @@ -331,15 +313,16 @@ mkdir -p config 2>/dev/null if [ $ALWAYSDOWNLOAD = yes ]; then if [ -n "$CONFTARBALL_URL" ]; then - URL="$CONFTARBALL_URL"/configure-$CONFVERSION.tar.gz + CONFTARBALL=$(sage-package tarball configure) + URL="$CONFTARBALL_URL"/"$CONFTARBALL" SAGE_DL_LOGLEVEL="" [ "${BOOTSTRAP_QUIET}" = "yes" ] && SAGE_DL_LOGLEVEL="--log=WARNING" - sage-download-file ${SAGE_DL_LOGLEVEL} "$URL" upstream/configure-$CONFVERSION.tar.gz + sage-download-file ${SAGE_DL_LOGLEVEL} "$URL" upstream/"$CONFTARBALL" if [ $? -ne 0 ]; then - echo >&2 "Error: downloading configure-$CONFVERSION.tar.gz from $CONFTARBALL_URL failed" + echo >&2 "Error: downloading $CONFTARBALL from $CONFTARBALL_URL failed" exit 1 fi - echo >&2 "Downloaded configure-$CONFVERSION.tar.gz from $CONFTARBALL_URL " + echo >&2 "Downloaded $CONFTARBALL from $CONFTARBALL_URL " else bootstrap_download || exit $? fi diff --git a/bootstrap-conda b/bootstrap-conda index 62d7557a9b5..c64e2a72b6c 100755 --- a/bootstrap-conda +++ b/bootstrap-conda @@ -18,10 +18,11 @@ SAGELIB_PACKAGES= SAGELIB_OPTIONAL_PACKAGES= DEVELOP_PACKAGES= +eval $(sage-package properties --format=shell :all:) + for PKG_BASE in $(sage-package list --has-file distros/conda.txt --exclude _sagemath); do - PKG_SCRIPTS=build/pkgs/$PKG_BASE + eval PKG_SCRIPTS=\$path_$PKG_BASE PKG_TYPE=\$type_$PKG_BASE SYSTEM_PACKAGES_FILE=$PKG_SCRIPTS/distros/conda.txt - PKG_TYPE=$(cat $PKG_SCRIPTS/type) PKG_SYSTEM_PACKAGES=$(echo $(${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE)) if [ -n "$PKG_SYSTEM_PACKAGES" ]; then if [ -f $PKG_SCRIPTS/spkg-configure.m4 ]; then @@ -133,12 +134,11 @@ echo >&2 $0:$LINENO: generate conda environment files echo >&4 " - pip:" echo >&5 " - pip:" for PKG_BASE in $(sage-package list :standard: :optional: --has-file requirements.txt --no-file distros/conda.txt --no-file src; sage-package list :standard: :optional: --has-file version_requirements.txt --no-file requirements.txt --no-file distros/conda.txt --no-file src); do - PKG_SCRIPTS=build/pkgs/$PKG_BASE + eval PKG_SCRIPTS=\$path_$PKG_BASE PKG_TYPE=\$type_$PKG_BASE SYSTEM_PACKAGES_FILE=$PKG_SCRIPTS/requirements.txt if [ ! -f $SYSTEM_PACKAGES_FILE ]; then SYSTEM_PACKAGES_FILE=$PKG_SCRIPTS/version_requirements.txt fi - PKG_TYPE=$(cat $PKG_SCRIPTS/type) if grep -q SAGERUNTIME $PKG_SCRIPTS/dependencies $PKG_SCRIPTS/dependencies_order_only 2>/dev/null; then : # cannot install packages that depend on the Sage library else diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages index 0a90232ed6e..f28e0356375 100755 --- a/build/bin/sage-get-system-packages +++ b/build/bin/sage-get-system-packages @@ -15,26 +15,40 @@ fi case "$SYSTEM" in install-requires) # Collect from src/pyproject.toml or from version_requirements.txt (falling back to requirements.txt) and output it in the format - # needed by setup.cfg [options] version_requirements= - SYSTEM_PACKAGES_FILE_NAMES="version_requirements.txt requirements.txt" - STRIP_COMMENTS="sed s/#.*//;/^[[:space:]]*$/d;" - FROM_PYPROJECT_TOML=1 + # needed by setup.cfg [options] install_requires= + SYSTEM_PACKAGES_FILE_NAMES="src/pyproject.toml version_requirements.txt requirements.txt" + # also normalizes quotes from "" to ''. + STRIP_COMMENTS="sed s/#.*//;/^[[:space:]]*$/d;s/\"/'/g;" COLLECT= ;; install-requires-toml) # Collect from src/pyproject.toml or from version_requirements.txt (falling back to requirements.txt) and output it in the format # needed by pyproject.toml [build-system] requires= - SYSTEM_PACKAGES_FILE_NAMES="version_requirements.txt requirements.txt" - STRIP_COMMENTS="sed s/#.*//;/^[[:space:]]*$/d;s/^/'/;s/$/',/;" - FROM_PYPROJECT_TOML=1 + SYSTEM_PACKAGES_FILE_NAMES="src/pyproject.toml version_requirements.txt requirements.txt" + # also normalizes quotes from '' to "". + STRIP_COMMENTS="sed s/#.*//;/^[[:space:]]*$/d;s/'/\"/g;s/^/'/;s/$/',/;" COLLECT= ;; pip) - SYSTEM_PACKAGES_FILE_NAMES="requirements.txt version_requirements.txt" + SYSTEM_PACKAGES_FILE_NAMES="requirements.txt src/pyproject.toml version_requirements.txt" STRIP_COMMENTS='sed s/#.*//;s/[[:space:]]//g;' - FROM_PYPROJECT_TOML=1 COLLECT=echo ;; + versions) + # For use in sage-spkg-info + SYSTEM_PACKAGES_FILE_NAMES="package-version.txt requirements.txt src/pyproject.toml version_requirements.txt" + strip_comments () { + TEXT=$(sed "s/#.*//;/^[[:space:]]*$/d;s/\"/'/g;s/^/ /;" "$@") + if [ -n "$(echo $TEXT)" ]; then + echo "$NAME::" + echo + echo "$TEXT" + echo + fi + } + STRIP_COMMENTS=strip_comments + COLLECT= + ;; *) if [ "$SYSTEM" = auto ]; then SYSTEM=$(sage-guess-package-system 2>/dev/null) @@ -45,7 +59,6 @@ case "$SYSTEM" in fi SYSTEM_PACKAGES_FILE_NAMES="distros/$SYSTEM.txt" STRIP_COMMENTS="sed s/#.*//;s/\${PYTHON_MINOR}/${PYTHON_MINOR}/g" - FROM_PYPROJECT_TOML=0 COLLECT=echo ;; esac @@ -57,19 +70,10 @@ case "$SPKGS" in esac for PKG_BASE in $SPKGS; do - if [ $FROM_PYPROJECT_TOML -eq 1 ]; then - if [ -f "$SAGE_ROOT/src/pyproject.toml" ]; then - # Extract from the "requires" block in src/pyproject.toml - # Packages are in the format "'sage-conf ~= 10.3b3'," - PACKAGE_INFO=$(sed -n '/requires *= *\[/,/^\]/s/^ *'\''\('$PKG_BASE'.*\)'\'',/\1/p' "$SAGE_ROOT/src/pyproject.toml") - if [ -n "$PACKAGE_INFO" ]; then - echo "$PACKAGE_INFO" | ${STRIP_COMMENTS} - continue - fi - fi - fi - case "$SYSTEM:$ENABLE_SYSTEM_SITE_PACKAGES" in + versions*) + # Show everything. + ;; install-requires*|pip*) # This is output for installation of packages into a Python environment. # So it's OK to use any Python packages. @@ -93,14 +97,30 @@ for PKG_BASE in $SPKGS; do esac for NAME in $SYSTEM_PACKAGES_FILE_NAMES; do - SYSTEM_PACKAGES_FILE="$SAGE_ROOT"/build/pkgs/$PKG_BASE/$NAME - if [ -f $SYSTEM_PACKAGES_FILE ]; then - if [ -z "$COLLECT" ]; then - ${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE - else - $COLLECT $(${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE) - fi - break - fi + case $NAME in + *pyproject.toml) + SYSTEM_PACKAGES_FILE="$SAGE_ROOT"/$NAME + if [ -f "$SYSTEM_PACKAGES_FILE" ]; then + # Extract from the "requires" block in src/pyproject.toml + # Packages are in the format "'sage-conf ~= 10.3b3'," + PACKAGE_INFO=$(sed -n '/requires *= *\[/,/^\]/s/^ *'\''\('$PKG_BASE'.*\)'\'',/\1/p' "$SAGE_ROOT/src/pyproject.toml") + if [ -n "$PACKAGE_INFO" ]; then + echo "$PACKAGE_INFO" | ${STRIP_COMMENTS} + [ $SYSTEM = versions ] || break + fi + fi + ;; + *) + SYSTEM_PACKAGES_FILE="$SAGE_ROOT"/build/pkgs/$PKG_BASE/$NAME + if [ -f $SYSTEM_PACKAGES_FILE ]; then + if [ -z "$COLLECT" ]; then + ${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE + else + $COLLECT $(${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE) + fi + [ $SYSTEM = versions ] || break + fi + ;; + esac done done diff --git a/build/bin/sage-spkg-info b/build/bin/sage-spkg-info index dd289fee4d3..29d833a29bf 100755 --- a/build/bin/sage-spkg-info +++ b/build/bin/sage-spkg-info @@ -54,14 +54,7 @@ echo echo "Version Information" echo "-------------------" echo -for a in package-version.txt requirements.txt version_requirements.txt; do - if [ -f "$PKG_SCRIPTS"/"$a" ]; then - echo "$a::" - echo - sed 's/^/ /' "$PKG_SCRIPTS/$a" - echo - fi -done +sage-get-system-packages versions $PKG_BASE echo echo "Equivalent System Packages" echo "--------------------------" diff --git a/build/pkgs/anyio/checksums.ini b/build/pkgs/anyio/checksums.ini index edc3a769889..6559f060ac2 100644 --- a/build/pkgs/anyio/checksums.ini +++ b/build/pkgs/anyio/checksums.ini @@ -1,4 +1,4 @@ tarball=anyio-VERSION-py3-none-any.whl -sha1=bb08368bb19e1aff2f4190e39300e43fee52103e -sha256=cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f +sha1=f5bd548b3a14c9c93622bf04f7c6464e3f44966a +sha256=c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7 upstream_url=https://pypi.io/packages/py3/a/anyio/anyio-VERSION-py3-none-any.whl diff --git a/build/pkgs/anyio/dependencies b/build/pkgs/anyio/dependencies index 5be99073470..1703c203525 100644 --- a/build/pkgs/anyio/dependencies +++ b/build/pkgs/anyio/dependencies @@ -1,4 +1,4 @@ -idna sniffio | $(PYTHON_TOOLCHAIN) $(PYTHON) +idna sniffio exceptiongroup typing_extensions | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/anyio/package-version.txt b/build/pkgs/anyio/package-version.txt index fcdb2e109f6..fdc6698807a 100644 --- a/build/pkgs/anyio/package-version.txt +++ b/build/pkgs/anyio/package-version.txt @@ -1 +1 @@ -4.0.0 +4.4.0 diff --git a/build/pkgs/appnope/checksums.ini b/build/pkgs/appnope/checksums.ini index e9ee40864d3..4e49f102dd5 100644 --- a/build/pkgs/appnope/checksums.ini +++ b/build/pkgs/appnope/checksums.ini @@ -1,4 +1,4 @@ tarball=appnope-VERSION.tar.gz -sha1=dd705054af5f6c80d0ce9e1b444428c7b1b07daa -sha256=02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24 +sha1=4dcd80020b345a184d6da6063a69e25b1d353323 +sha256=1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee upstream_url=https://pypi.io/packages/source/a/appnope/appnope-VERSION.tar.gz diff --git a/build/pkgs/appnope/package-version.txt b/build/pkgs/appnope/package-version.txt index b1e80bb2480..845639eef26 100644 --- a/build/pkgs/appnope/package-version.txt +++ b/build/pkgs/appnope/package-version.txt @@ -1 +1 @@ -0.1.3 +0.1.4 diff --git a/build/pkgs/attrs/checksums.ini b/build/pkgs/attrs/checksums.ini index 01a3de82ed3..7d271509d6d 100644 --- a/build/pkgs/attrs/checksums.ini +++ b/build/pkgs/attrs/checksums.ini @@ -1,4 +1,4 @@ tarball=attrs-VERSION-py3-none-any.whl -sha1=d916b1ecad441ce7f07d86034085475f6c231830 -sha256=1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 +sha1=563b272af703f8960b76f6637d009fa5fc5864d3 +sha256=99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 upstream_url=https://pypi.io/packages/py3/a/attrs/attrs-VERSION-py3-none-any.whl diff --git a/build/pkgs/attrs/dependencies b/build/pkgs/attrs/dependencies index 47296a7bace..b09cbab3e0e 100644 --- a/build/pkgs/attrs/dependencies +++ b/build/pkgs/attrs/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) +importlib_metadata | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/attrs/package-version.txt b/build/pkgs/attrs/package-version.txt index f8aed3e0b7a..11ebcd0e4f9 100644 --- a/build/pkgs/attrs/package-version.txt +++ b/build/pkgs/attrs/package-version.txt @@ -1 +1 @@ -23.1.0 +23.2.0 diff --git a/build/pkgs/cachetools/checksums.ini b/build/pkgs/cachetools/checksums.ini index 9c2aa8528b0..29f982e9277 100644 --- a/build/pkgs/cachetools/checksums.ini +++ b/build/pkgs/cachetools/checksums.ini @@ -1,4 +1,4 @@ tarball=cachetools-VERSION-py3-none-any.whl -sha1=f7deaa4b10ae6d8955c83b0573e5b80f84e5d87a -sha256=95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590 +sha1=4210b349f838f75d64da22fbef7e5dc8e494c5f6 +sha256=0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945 upstream_url=https://pypi.io/packages/py3/c/cachetools/cachetools-VERSION-py3-none-any.whl diff --git a/build/pkgs/cachetools/dependencies b/build/pkgs/cachetools/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/cachetools/dependencies +++ b/build/pkgs/cachetools/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cachetools/package-version.txt b/build/pkgs/cachetools/package-version.txt index c7cb1311a64..74664af7400 100644 --- a/build/pkgs/cachetools/package-version.txt +++ b/build/pkgs/cachetools/package-version.txt @@ -1 +1 @@ -5.3.1 +5.3.3 diff --git a/build/pkgs/certifi/checksums.ini b/build/pkgs/certifi/checksums.ini index 1a07649c990..ecb9291cd62 100644 --- a/build/pkgs/certifi/checksums.ini +++ b/build/pkgs/certifi/checksums.ini @@ -1,4 +1,4 @@ tarball=certifi-VERSION-py3-none-any.whl -sha1=9e99fff8d517d9c5b8d8fe6fe66bc31fa55b0fec -sha256=e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474 +sha1=4acb42f49aed94aeb687b33d3dcb6b564ff36fac +sha256=dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 upstream_url=https://pypi.io/packages/py3/c/certifi/certifi-VERSION-py3-none-any.whl diff --git a/build/pkgs/certifi/dependencies b/build/pkgs/certifi/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/certifi/dependencies +++ b/build/pkgs/certifi/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/certifi/package-version.txt b/build/pkgs/certifi/package-version.txt index 7b4ca80e8a8..fa996f67f93 100644 --- a/build/pkgs/certifi/package-version.txt +++ b/build/pkgs/certifi/package-version.txt @@ -1 +1 @@ -2023.11.17 +2024.2.2 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index da9cfbb1ff9..4a0731816fb 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,3 +1,3 @@ tarball=configure-VERSION.tar.gz -sha1=f3e560bbf33add8504ba9f7ba93fff9e82e3e445 -sha256=bef93be1bb978fa34cd5aaa9c041d1a97a33ff35f88c9df2f9c25e6764770c56 +sha1=44fc3d7b5ad99c9b59153bf24d2a982eb690d5c2 +sha256=4e9e0fada9495365f673f83de311d7dbbc1fbcf9e5f7163209cf396c4ccd5479 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index ca5926f5634..1a9044b121d 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -5c12765f7e585b58ab0cd99f7998cfa615f85247 +b7e60e161981964b92657e427662fa6e69938428 diff --git a/build/pkgs/debugpy/SPKG.rst b/build/pkgs/debugpy/SPKG.rst index f99081496dd..b4df549df07 100644 --- a/build/pkgs/debugpy/SPKG.rst +++ b/build/pkgs/debugpy/SPKG.rst @@ -1,10 +1,10 @@ -debugpy: An implementation of the Debug Adapter Protocol for Python -=================================================================== +debugpy: Implementation of the Debug Adapter Protocol for Python +================================================================ Description ----------- -An implementation of the Debug Adapter Protocol for Python +Implementation of the Debug Adapter Protocol for Python License ------- diff --git a/build/pkgs/debugpy/checksums.ini b/build/pkgs/debugpy/checksums.ini index 9ffea011e6e..1879bd6e197 100644 --- a/build/pkgs/debugpy/checksums.ini +++ b/build/pkgs/debugpy/checksums.ini @@ -1,4 +1,4 @@ -tarball=debugpy-VERSION.zip -sha1=af611dc5c401424196c27363379fc483814efe26 -sha256=12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0 -upstream_url=https://pypi.io/packages/source/d/debugpy/debugpy-VERSION.zip +tarball=debugpy-VERSION-py2.py3-none-any.whl +sha1=cc85be805ef4f25e85bae65cf5b04badca032bb6 +sha256=28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242 +upstream_url=https://pypi.io/packages/py2.py3/d/debugpy/debugpy-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/debugpy/dependencies b/build/pkgs/debugpy/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/debugpy/dependencies +++ b/build/pkgs/debugpy/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/debugpy/package-version.txt b/build/pkgs/debugpy/package-version.txt index 27f9cd322bb..a8fdfda1c78 100644 --- a/build/pkgs/debugpy/package-version.txt +++ b/build/pkgs/debugpy/package-version.txt @@ -1 +1 @@ -1.8.0 +1.8.1 diff --git a/build/pkgs/debugpy/spkg-install.in b/build/pkgs/debugpy/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/debugpy/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/e_antic/checksums.ini b/build/pkgs/e_antic/checksums.ini index f0afbce6ac8..2df790ac90f 100644 --- a/build/pkgs/e_antic/checksums.ini +++ b/build/pkgs/e_antic/checksums.ini @@ -1,4 +1,4 @@ tarball=e-antic-VERSION.tar.gz -sha1=587052e189f9a7a145ac3144e6b7f11fca54b1ff -sha256=a38d2ab62c1b00fa2ee78f39039cc4d9d8e83de5fa5e2a18529ad34ab8976fe1 +sha1=f20808a3f4857ecec58929f811b73c2a7664e666 +sha256=8328e6490129dfec7f4aa478ebd54dc07686bd5e5e7f5f30dcf20c0f11b67f60 upstream_url=https://github.com/flatsurf/e-antic/releases/download/VERSION/e-antic-VERSION.tar.gz diff --git a/build/pkgs/e_antic/package-version.txt b/build/pkgs/e_antic/package-version.txt index 227cea21564..e9307ca5751 100644 --- a/build/pkgs/e_antic/package-version.txt +++ b/build/pkgs/e_antic/package-version.txt @@ -1 +1 @@ -2.0.0 +2.0.2 diff --git a/build/pkgs/exceptiongroup/checksums.ini b/build/pkgs/exceptiongroup/checksums.ini index ef04b565062..62cef9ee502 100644 --- a/build/pkgs/exceptiongroup/checksums.ini +++ b/build/pkgs/exceptiongroup/checksums.ini @@ -1,4 +1,4 @@ tarball=exceptiongroup-VERSION-py3-none-any.whl -sha1=e69c438e6d15111c4f7cc18224b31a42a58663da -sha256=4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 +sha1=4114f66482c6e55856d9bd6a4780ce716bd550cd +sha256=5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad upstream_url=https://pypi.io/packages/py3/e/exceptiongroup/exceptiongroup-VERSION-py3-none-any.whl diff --git a/build/pkgs/exceptiongroup/dependencies b/build/pkgs/exceptiongroup/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/exceptiongroup/dependencies +++ b/build/pkgs/exceptiongroup/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/exceptiongroup/package-version.txt b/build/pkgs/exceptiongroup/package-version.txt index 26aaba0e866..6085e946503 100644 --- a/build/pkgs/exceptiongroup/package-version.txt +++ b/build/pkgs/exceptiongroup/package-version.txt @@ -1 +1 @@ -1.2.0 +1.2.1 diff --git a/build/pkgs/filelock/SPKG.rst b/build/pkgs/filelock/SPKG.rst index d39b439be2e..ebebf9cfbdc 100644 --- a/build/pkgs/filelock/SPKG.rst +++ b/build/pkgs/filelock/SPKG.rst @@ -1,10 +1,10 @@ -filelock: A platform independent file lock -========================================== +filelock: Platform independent file lock +======================================== Description ----------- -A platform independent file lock. +Platform independent file lock License ------- diff --git a/build/pkgs/filelock/checksums.ini b/build/pkgs/filelock/checksums.ini index 330f4d53a36..e6fc5ecc6f5 100644 --- a/build/pkgs/filelock/checksums.ini +++ b/build/pkgs/filelock/checksums.ini @@ -1,4 +1,4 @@ tarball=filelock-VERSION-py3-none-any.whl -sha1=f1fa92751023660a10b248f8559d09f3c461403f -sha256=57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c +sha1=475b56870663924527abcf2f91b7d8dd7a7ab0ee +sha256=43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f upstream_url=https://pypi.io/packages/py3/f/filelock/filelock-VERSION-py3-none-any.whl diff --git a/build/pkgs/filelock/package-version.txt b/build/pkgs/filelock/package-version.txt index c10780c628a..f982feb41bd 100644 --- a/build/pkgs/filelock/package-version.txt +++ b/build/pkgs/filelock/package-version.txt @@ -1 +1 @@ -3.13.1 +3.14.0 diff --git a/build/pkgs/glpk/package-version.txt b/build/pkgs/glpk/package-version.txt index 496a5a8b3ea..11729725c0e 100644 --- a/build/pkgs/glpk/package-version.txt +++ b/build/pkgs/glpk/package-version.txt @@ -1 +1 @@ -5.0.p0 +5.0.p1 diff --git a/build/pkgs/glpk/patches/error_recovery.patch b/build/pkgs/glpk/patches/error_recovery.patch deleted file mode 100644 index a383e25769b..00000000000 --- a/build/pkgs/glpk/patches/error_recovery.patch +++ /dev/null @@ -1,16 +0,0 @@ -From: Jeroen Demeyer -Allow error recovery. See discussion at -https://github.com/sagemath/sage/issues/20710#comment:18 - -diff --git a/src/env/error.c b/src/env/error.c -index a898b76..154de0f 100644 ---- a/src/env/error.c -+++ b/src/env/error.c -@@ -48,6 +48,7 @@ static void errfunc(const char *fmt, ...) - va_end(arg); - xprintf("Error detected in file %s at line %d\n", - env->err_file, env->err_line); -+ env->err_st = 0; - if (env->err_hook != NULL) - env->err_hook(env->err_info); - abort(); diff --git a/build/pkgs/httpcore/SPKG.rst b/build/pkgs/httpcore/SPKG.rst index fed1a457967..a116180ec5f 100644 --- a/build/pkgs/httpcore/SPKG.rst +++ b/build/pkgs/httpcore/SPKG.rst @@ -1,10 +1,10 @@ -httpcore: A minimal low-level HTTP client. -========================================== +httpcore: Minimal low-level HTTP client +======================================= Description ----------- -A minimal low-level HTTP client. +Minimal low-level HTTP client License ------- diff --git a/build/pkgs/httpcore/checksums.ini b/build/pkgs/httpcore/checksums.ini index 627dc72c115..21cb43c4bf6 100644 --- a/build/pkgs/httpcore/checksums.ini +++ b/build/pkgs/httpcore/checksums.ini @@ -1,4 +1,4 @@ tarball=httpcore-VERSION-py3-none-any.whl -sha1=e83eb30232906df8ac673d6c49c657957dc00ce1 -sha256=ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73 +sha1=52c8337dcf474d63f5b053e0f65cf79714ae69fe +sha256=421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5 upstream_url=https://pypi.io/packages/py3/h/httpcore/httpcore-VERSION-py3-none-any.whl diff --git a/build/pkgs/httpcore/dependencies b/build/pkgs/httpcore/dependencies index 36787c2193d..b47892606c1 100644 --- a/build/pkgs/httpcore/dependencies +++ b/build/pkgs/httpcore/dependencies @@ -1,4 +1,4 @@ -h11 | $(PYTHON_TOOLCHAIN) $(PYTHON) +certifi h11 | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/httpcore/package-version.txt b/build/pkgs/httpcore/package-version.txt index ee90284c27f..90a27f9cea6 100644 --- a/build/pkgs/httpcore/package-version.txt +++ b/build/pkgs/httpcore/package-version.txt @@ -1 +1 @@ -1.0.4 +1.0.5 diff --git a/build/pkgs/httpcore/spkg-configure.m4 b/build/pkgs/httpcore/spkg-configure.m4 new file mode 100644 index 00000000000..8ef9c0cbd4d --- /dev/null +++ b/build/pkgs/httpcore/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([httpcore], [ + SAGE_PYTHON_PACKAGE_CHECK([httpcore]) +]) diff --git a/build/pkgs/httpx/spkg-configure.m4 b/build/pkgs/httpx/spkg-configure.m4 new file mode 100644 index 00000000000..024f1a0c12c --- /dev/null +++ b/build/pkgs/httpx/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([httpx], [ + SAGE_PYTHON_PACKAGE_CHECK([httpx]) +]) diff --git a/build/pkgs/idna/checksums.ini b/build/pkgs/idna/checksums.ini index 0381d537291..b3a22afe657 100644 --- a/build/pkgs/idna/checksums.ini +++ b/build/pkgs/idna/checksums.ini @@ -1,4 +1,4 @@ tarball=idna-VERSION-py3-none-any.whl -sha1=352c6bd8ee12319953116397718c1a8ab6887259 -sha256=c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f +sha1=ccb2491074ec1b6ffda6e6c11c1c668f885ed20a +sha256=82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 upstream_url=https://pypi.io/packages/py3/i/idna/idna-VERSION-py3-none-any.whl diff --git a/build/pkgs/idna/dependencies b/build/pkgs/idna/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/idna/dependencies +++ b/build/pkgs/idna/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/idna/package-version.txt b/build/pkgs/idna/package-version.txt index d70c8f8d89f..475ba515c04 100644 --- a/build/pkgs/idna/package-version.txt +++ b/build/pkgs/idna/package-version.txt @@ -1 +1 @@ -3.6 +3.7 diff --git a/build/pkgs/jinja2/checksums.ini b/build/pkgs/jinja2/checksums.ini index fa9f5daf853..8f1cd2ceb6a 100644 --- a/build/pkgs/jinja2/checksums.ini +++ b/build/pkgs/jinja2/checksums.ini @@ -1,4 +1,4 @@ -tarball=Jinja2-VERSION-py3-none-any.whl -sha1=2a4d66fe16c565145c8bec1b22d57ab1e7028613 -sha256=7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa -upstream_url=https://pypi.io/packages/py3/j/jinja2/Jinja2-VERSION-py3-none-any.whl +tarball=jinja2-VERSION-py3-none-any.whl +sha1=57760ed83d9ad15fcdf63ad1ffa14941333ef655 +sha256=bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d +upstream_url=https://pypi.io/packages/py3/j/jinja2/jinja2-VERSION-py3-none-any.whl diff --git a/build/pkgs/jinja2/dependencies b/build/pkgs/jinja2/dependencies index 151ae9767d1..9236c02b29e 100644 --- a/build/pkgs/jinja2/dependencies +++ b/build/pkgs/jinja2/dependencies @@ -1,4 +1,4 @@ - markupsafe docutils | $(PYTHON_TOOLCHAIN) $(PYTHON) +markupsafe | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jinja2/package-version.txt b/build/pkgs/jinja2/package-version.txt index ff365e06b95..0aec50e6ede 100644 --- a/build/pkgs/jinja2/package-version.txt +++ b/build/pkgs/jinja2/package-version.txt @@ -1 +1 @@ -3.1.3 +3.1.4 diff --git a/build/pkgs/markupsafe/checksums.ini b/build/pkgs/markupsafe/checksums.ini index 53502ada131..8b2cb02af26 100644 --- a/build/pkgs/markupsafe/checksums.ini +++ b/build/pkgs/markupsafe/checksums.ini @@ -1,4 +1,4 @@ tarball=MarkupSafe-VERSION.tar.gz -sha1=ffca1ac960cedaf0cb419b5c97b64aab12220d04 -sha256=3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f +sha1=08593f9490b9be070aa2337e7311a392d33944dd +sha256=d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b upstream_url=https://pypi.io/packages/source/m/markupsafe/MarkupSafe-VERSION.tar.gz diff --git a/build/pkgs/markupsafe/package-version.txt b/build/pkgs/markupsafe/package-version.txt index 7d2ed7c7020..cd57a8b95d6 100644 --- a/build/pkgs/markupsafe/package-version.txt +++ b/build/pkgs/markupsafe/package-version.txt @@ -1 +1 @@ -2.1.4 +2.1.5 diff --git a/build/pkgs/nest_asyncio/checksums.ini b/build/pkgs/nest_asyncio/checksums.ini index 2e37d5585ca..48626a85ae1 100644 --- a/build/pkgs/nest_asyncio/checksums.ini +++ b/build/pkgs/nest_asyncio/checksums.ini @@ -1,4 +1,4 @@ -tarball=nest_asyncio-VERSION.tar.gz -sha1=e7d8036f6558011c5ae0c649e0af21eb530044d3 -sha256=25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb -upstream_url=https://pypi.io/packages/source/n/nest_asyncio/nest_asyncio-VERSION.tar.gz +tarball=nest_asyncio-VERSION-py3-none-any.whl +sha1=675b145491553e6a725884081244860a635552cd +sha256=87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c +upstream_url=https://pypi.io/packages/py3/n/nest_asyncio/nest_asyncio-VERSION-py3-none-any.whl diff --git a/build/pkgs/nest_asyncio/dependencies b/build/pkgs/nest_asyncio/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/nest_asyncio/dependencies +++ b/build/pkgs/nest_asyncio/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/nest_asyncio/package-version.txt b/build/pkgs/nest_asyncio/package-version.txt index 1cc9c180e26..dc1e644a101 100644 --- a/build/pkgs/nest_asyncio/package-version.txt +++ b/build/pkgs/nest_asyncio/package-version.txt @@ -1 +1 @@ -1.5.8 +1.6.0 diff --git a/build/pkgs/nest_asyncio/spkg-install.in b/build/pkgs/nest_asyncio/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/nest_asyncio/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/normaliz/checksums.ini b/build/pkgs/normaliz/checksums.ini index acb6e5cde7f..c281052483f 100644 --- a/build/pkgs/normaliz/checksums.ini +++ b/build/pkgs/normaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=normaliz-VERSION.tar.gz -sha1=d3c4e554c6a5ccf4fd04147e7744a63e3def1766 -sha256=365e1d1e2a338dc4df1947a440e606bb66dd261307e617905e8eca64eaafcf6e +sha1=ca5c9debcc3b1a02165659cf619935c37fa4faa4 +sha256=0aeb58fbbca362ed759f338a85e74156ed411e2846cc395f52d23ae90022ec91 upstream_url=https://github.com/Normaliz/Normaliz/releases/download/vVERSION/normaliz-VERSION.tar.gz diff --git a/build/pkgs/normaliz/package-version.txt b/build/pkgs/normaliz/package-version.txt index 2377fe517a0..7d4ef04f654 100644 --- a/build/pkgs/normaliz/package-version.txt +++ b/build/pkgs/normaliz/package-version.txt @@ -1 +1 @@ -3.10.1.p0 +3.10.3 diff --git a/build/pkgs/normaliz/patches/411.patch b/build/pkgs/normaliz/patches/411.patch deleted file mode 100644 index d9e52bd78bf..00000000000 --- a/build/pkgs/normaliz/patches/411.patch +++ /dev/null @@ -1,21 +0,0 @@ -commit ecdb62c90a3767b440800dcf2c49589e890a53b1 -Author: Matthias Koeppe -Date: Tue Aug 8 17:03:32 2023 -0700 - - full_cone.cpp: Remove debug output - -diff --git a/source/libnormaliz/full_cone.cpp b/source/libnormaliz/full_cone.cpp -index 0fd906b3..cb2cce2b 100644 ---- a/source/libnormaliz/full_cone.cpp -+++ b/source/libnormaliz/full_cone.cpp -@@ -3447,8 +3447,8 @@ void Full_Cone::build_cone_dynamic() { - // if they aren't in a hyperplane anyway - if(IntHullNorm.size() > 0){ - #pragma omp parallel for -- for(size_t i = 0; i< OriGens.nr_of_rows(); ++i){ -- cout << "i " << i << " -- " << OriGensFloat[i]; -+ for (size_t i = 0; i< OriGens.nr_of_rows(); ++i){ -+ // cout << "i " << i << " -- " << OriGensFloat[i]; - nmz_float norm = v_scalar_product(OriGensFloat[i], IntHullNormFloat); - v_scalar_division(OriGensFloat[i], norm); - } diff --git a/build/pkgs/normaliz/patches/flint3_d-torrance.patch b/build/pkgs/normaliz/patches/flint3_d-torrance.patch deleted file mode 100644 index 5a6e36c51c4..00000000000 --- a/build/pkgs/normaliz/patches/flint3_d-torrance.patch +++ /dev/null @@ -1,55 +0,0 @@ ---- a/source/libnormaliz/vector_operations.h -+++ b/source/libnormaliz/vector_operations.h -@@ -547,7 +547,10 @@ - - fmpq_poly_fit_length(flp, n); - for (size_t i = 0; i < poly_vector.size(); ++i) { -- fmpq_poly_set_coeff_mpq(flp, (slong)i, poly_vector[i].get_mpq_t()); -+ fmpq_t fcurrent_coeff; -+ fmpq_init(fcurrent_coeff); -+ fmpq_set_mpq(fcurrent_coeff, poly_vector[i].get_mpq_t()); -+ fmpq_poly_set_coeff_fmpq(flp, (slong)i, fcurrent_coeff); - } - } - -@@ -560,8 +563,11 @@ - poly_vector.resize(length); - for (slong i = 0; i < length; i++) { - mpq_t current_coeff; -+ fmpq_t fcurrent_coeff; - mpq_init(current_coeff); -- fmpq_poly_get_coeff_mpq(current_coeff, flp, (slong)i); -+ fmpq_init(fcurrent_coeff); -+ fmpq_poly_get_coeff_fmpq(fcurrent_coeff, flp, (slong)i); -+ fmpq_get_mpq(current_coeff, fcurrent_coeff); - poly_vector[i] = mpq_class(current_coeff); - } - } ---- a/source/libnormaliz/HilbertSeries.cpp -+++ b/source/libnormaliz/HilbertSeries.cpp -@@ -72,7 +72,10 @@ - slong n = (slong)nmzp.size(); - fmpz_poly_fit_length(flp, n); - for (size_t i = 0; i < nmzp.size(); ++i) { -- fmpz_poly_set_coeff_mpz(flp, (slong)i, nmzp[i].get_mpz_t()); -+ fmpz_t fc; -+ fmpz_init(fc); -+ fmpz_set_mpz(fc, nmzp[i].get_mpz_t()); -+ fmpz_poly_set_coeff_fmpz(flp, (slong)i, fc); - } - } - -@@ -80,9 +83,12 @@ - size_t n = (size_t)fmpz_poly_length(flp); - nmzp.resize(n); - mpz_t c; -+ fmpz_t fc; - mpz_init(c); -+ fmpz_init(fc); - for (size_t i = 0; i < nmzp.size(); ++i) { -- fmpz_poly_get_coeff_mpz(c, flp, i); -+ fmpz_poly_get_coeff_fmpz(fc, flp, i); -+ fmpz_get_mpz(c, fc); - nmzp[i] = mpz_class(c); - } - mpz_clear(c); diff --git a/build/pkgs/parso/SPKG.rst b/build/pkgs/parso/SPKG.rst index 4c279026db9..141fdc09499 100644 --- a/build/pkgs/parso/SPKG.rst +++ b/build/pkgs/parso/SPKG.rst @@ -1,5 +1,5 @@ -parso: A Python parser -====================== +parso: Python Parser +==================== Description ----------- @@ -7,3 +7,14 @@ Description Parso is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python versions). Parso is also able to list multiple syntax errors in your python file. + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/parso/ + diff --git a/build/pkgs/parso/checksums.ini b/build/pkgs/parso/checksums.ini index caae59d79e8..d15402d82de 100644 --- a/build/pkgs/parso/checksums.ini +++ b/build/pkgs/parso/checksums.ini @@ -1,4 +1,4 @@ -tarball=parso-VERSION.tar.gz -sha1=1a34ea6e597a6498ef5c154195f9ffe8dda3d254 -sha256=8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0 -upstream_url=https://pypi.io/packages/source/p/parso/parso-VERSION.tar.gz +tarball=parso-VERSION-py2.py3-none-any.whl +sha1=091d37e09a601d854e18f4d42aeb478392bb7e63 +sha256=a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18 +upstream_url=https://pypi.io/packages/py2.py3/p/parso/parso-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/parso/dependencies b/build/pkgs/parso/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/parso/dependencies +++ b/build/pkgs/parso/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/parso/package-version.txt b/build/pkgs/parso/package-version.txt index ee94dd834b5..b60d71966ae 100644 --- a/build/pkgs/parso/package-version.txt +++ b/build/pkgs/parso/package-version.txt @@ -1 +1 @@ -0.8.3 +0.8.4 diff --git a/build/pkgs/parso/spkg-install.in b/build/pkgs/parso/spkg-install.in deleted file mode 100644 index 058b1344dc2..00000000000 --- a/build/pkgs/parso/spkg-install.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src - -sdh_pip_install . diff --git a/build/pkgs/platformdirs/checksums.ini b/build/pkgs/platformdirs/checksums.ini index 28576a25b7f..201a01de014 100644 --- a/build/pkgs/platformdirs/checksums.ini +++ b/build/pkgs/platformdirs/checksums.ini @@ -1,4 +1,4 @@ tarball=platformdirs-VERSION-py3-none-any.whl -sha1=487a4610a037c90b242aafbe1e3f8b6ebb3ba1c8 -sha256=0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 +sha1=81890edbdf2f709f83001cb5bcfd71c3978225ce +sha256=2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee upstream_url=https://pypi.io/packages/py3/p/platformdirs/platformdirs-VERSION-py3-none-any.whl diff --git a/build/pkgs/platformdirs/package-version.txt b/build/pkgs/platformdirs/package-version.txt index 6aba2b245a8..af8c8ec7c13 100644 --- a/build/pkgs/platformdirs/package-version.txt +++ b/build/pkgs/platformdirs/package-version.txt @@ -1 +1 @@ -4.2.0 +4.2.2 diff --git a/build/pkgs/polymake/checksums.ini b/build/pkgs/polymake/checksums.ini index b76cd23ad88..3173f176491 100644 --- a/build/pkgs/polymake/checksums.ini +++ b/build/pkgs/polymake/checksums.ini @@ -1,4 +1,4 @@ tarball=polymake-VERSION-minimal.tar.bz2 -sha1=0445f1a6d174906317a07c4bef299d0b4502c779 -sha256=5df6f0acd700119bd0c4b5766762852ffbd857765b5dcc88802ff5d2108add23 +sha1=aa1a153fac97a9faad61842f4a4232fbf444155f +sha256=bd5a667ffca4bf7eb8d51134030ce3df3b16dd9d0e800fafdb1ce835867640d9 upstream_url=https://polymake.org/lib/exe/fetch.php/download/polymake-VERSION-minimal.tar.bz2 diff --git a/build/pkgs/polymake/package-version.txt b/build/pkgs/polymake/package-version.txt index b849ff8ebf1..f5885845348 100644 --- a/build/pkgs/polymake/package-version.txt +++ b/build/pkgs/polymake/package-version.txt @@ -1 +1 @@ -4.11 +4.12 diff --git a/build/pkgs/prompt_toolkit/version_requirements.txt b/build/pkgs/prompt_toolkit/version_requirements.txt index e3e1de9a3ea..b33ff7f30e1 100644 --- a/build/pkgs/prompt_toolkit/version_requirements.txt +++ b/build/pkgs/prompt_toolkit/version_requirements.txt @@ -1 +1 @@ -prompt_toolkit >=3.0.38 +prompt_toolkit >=3.0.43 diff --git a/build/pkgs/pycparser/checksums.ini b/build/pkgs/pycparser/checksums.ini index 1e113dfcbf8..4d250e61a00 100644 --- a/build/pkgs/pycparser/checksums.ini +++ b/build/pkgs/pycparser/checksums.ini @@ -1,4 +1,4 @@ -tarball=pycparser-VERSION.tar.gz -sha1=359c718c6ece361047f61846b9fa4ea0239576dc -sha256=e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 -upstream_url=https://pypi.io/packages/source/p/pycparser/pycparser-VERSION.tar.gz +tarball=pycparser-VERSION-py3-none-any.whl +sha1=34702512290f3bfd4850bcc95dfaf1ae972a8929 +sha256=c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc +upstream_url=https://pypi.io/packages/py3/p/pycparser/pycparser-VERSION-py3-none-any.whl diff --git a/build/pkgs/pycparser/dependencies b/build/pkgs/pycparser/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/pycparser/dependencies +++ b/build/pkgs/pycparser/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pycparser/package-version.txt b/build/pkgs/pycparser/package-version.txt index 2ef40bd8c62..4699fb07e80 100644 --- a/build/pkgs/pycparser/package-version.txt +++ b/build/pkgs/pycparser/package-version.txt @@ -1 +1 @@ -2.21 +2.22 diff --git a/build/pkgs/pycparser/spkg-install.in b/build/pkgs/pycparser/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/pycparser/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/pygments/checksums.ini b/build/pkgs/pygments/checksums.ini index c534a4a9a4d..5a54fdd0b9a 100644 --- a/build/pkgs/pygments/checksums.ini +++ b/build/pkgs/pygments/checksums.ini @@ -1,4 +1,4 @@ tarball=pygments-VERSION-py3-none-any.whl -sha1=053e17b72ffea04e200d7b34edbe0f96b4b68e4b -sha256=b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c +sha1=edb9fdfbc4cf53d356a02beee8822dd8e9529f35 +sha256=b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a upstream_url=https://pypi.io/packages/py3/p/pygments/pygments-VERSION-py3-none-any.whl diff --git a/build/pkgs/pygments/dependencies b/build/pkgs/pygments/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/pygments/dependencies +++ b/build/pkgs/pygments/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pygments/package-version.txt b/build/pkgs/pygments/package-version.txt index 94dc0ec9104..cf8690732fe 100644 --- a/build/pkgs/pygments/package-version.txt +++ b/build/pkgs/pygments/package-version.txt @@ -1 +1 @@ -2.17.2 +2.18.0 diff --git a/build/pkgs/pynormaliz/checksums.ini b/build/pkgs/pynormaliz/checksums.ini index 25b41b1c0ab..154f2bfb4c0 100644 --- a/build/pkgs/pynormaliz/checksums.ini +++ b/build/pkgs/pynormaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=PyNormaliz-VERSION.tar.gz -sha1=08617ca50ce0e0317a3377381bf37c1a0ab826c1 -sha256=359218cf35f400c43f338a132b7887f6a2affb05057c4e7eaa315a9f2b6a8b39 +sha1=4ce4fef4db61a0408bc84747294922fc49afc090 +sha256=95d29fff9380ea2948166fd2b4c730985e0881043fa41f3e44ff9f402b97f0b4 upstream_url=https://pypi.io/packages/source/p/pynormaliz/PyNormaliz-VERSION.tar.gz diff --git a/build/pkgs/pynormaliz/package-version.txt b/build/pkgs/pynormaliz/package-version.txt index fae0ceb2953..a4b5a6f4a49 100644 --- a/build/pkgs/pynormaliz/package-version.txt +++ b/build/pkgs/pynormaliz/package-version.txt @@ -1 +1 @@ -2.18.p0 +2.20 diff --git a/build/pkgs/pyparsing/checksums.ini b/build/pkgs/pyparsing/checksums.ini index 7c946098d45..931d057f6b8 100644 --- a/build/pkgs/pyparsing/checksums.ini +++ b/build/pkgs/pyparsing/checksums.ini @@ -1,4 +1,4 @@ tarball=pyparsing-VERSION-py3-none-any.whl -sha1=c44cd9476ad90a48af0f27d8f7966136b2a93fc6 -sha256=32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb +sha1=bf1ab91fb997ccee2793e1e7f22a56a25f5e3a93 +sha256=f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742 upstream_url=https://pypi.io/packages/py3/p/pyparsing/pyparsing-VERSION-py3-none-any.whl diff --git a/build/pkgs/pyparsing/package-version.txt b/build/pkgs/pyparsing/package-version.txt index 94ff29cc4de..ef538c28109 100644 --- a/build/pkgs/pyparsing/package-version.txt +++ b/build/pkgs/pyparsing/package-version.txt @@ -1 +1 @@ -3.1.1 +3.1.2 diff --git a/build/pkgs/python3/SPKG.rst b/build/pkgs/python3/SPKG.rst index 55757b972e6..b102c79fbbb 100644 --- a/build/pkgs/python3/SPKG.rst +++ b/build/pkgs/python3/SPKG.rst @@ -15,6 +15,9 @@ You can also use ``--with-python=/path/to/python3_binary`` to tell Sage to use a number of Python modules to be available within the Python in question. Currently, as of Sage 10.3, these modules are as follows: ``sqlite3``, ``ctypes``, ``math``, ``hashlib``, ``socket``, ``zlib``, ``ssl``, ``ensurepip``. +For Python >= 3.12, also ``setuptools`` is required; for older Python versions, +``distutils.core`` is required. These modules will be checked for by the ``configure`` +script. Use the ``configure`` option ``--without-system-python3`` if you want Python 3 built from scratch. diff --git a/build/pkgs/python3/checksums.ini b/build/pkgs/python3/checksums.ini index f0f0ce6eb75..73dddf24722 100644 --- a/build/pkgs/python3/checksums.ini +++ b/build/pkgs/python3/checksums.ini @@ -1,4 +1,4 @@ tarball=Python-VERSION.tar.xz -sha1=a368aeed7a3325e47b55168452c356a8eb27ab50 -sha256=9e06008c8901924395bc1da303eac567a729ae012baa182ab39269f650383bb3 +sha1=c221421f3ba734daaf013dbdc7b48aa725cea18e +sha256=f6d419a6d8743ab26700801b4908d26d97e8b986e14f95de31b32de2b0e79554 upstream_url=https://www.python.org/ftp/python/VERSION/Python-VERSION.tar.xz diff --git a/build/pkgs/python3/package-version.txt b/build/pkgs/python3/package-version.txt index b6d8b7612f0..455808f8e19 100644 --- a/build/pkgs/python3/package-version.txt +++ b/build/pkgs/python3/package-version.txt @@ -1 +1 @@ -3.11.8 +3.12.4 diff --git a/build/pkgs/python3/patches/0001-bpo-22699-Allow-compiling-on-debian-ubuntu-with-a-di.patch b/build/pkgs/python3/patches/0001-bpo-22699-Allow-compiling-on-debian-ubuntu-with-a-di.patch deleted file mode 100644 index ec3d84c8499..00000000000 --- a/build/pkgs/python3/patches/0001-bpo-22699-Allow-compiling-on-debian-ubuntu-with-a-di.patch +++ /dev/null @@ -1,64 +0,0 @@ -From aef4a7749dec9ecf942647af39d7a1303c758131 Mon Sep 17 00:00:00 2001 -From: Isuru Fernando -Date: Thu, 16 Sep 2021 15:46:09 -0500 -Subject: [PATCH 08/24] bpo-22699: Allow compiling on debian/ubuntu with a - different compiler - -This PR fixes one issue mentioned in the bpo -https://bugs.python.org/issue22699#msg364685 with a slightly better -patch than given ---- - setup.py | 19 ++++++++++++++++++- - 1 file changed, 18 insertions(+), 1 deletion(-) - -diff --git a/setup.py b/setup.py -index 554699608d..d5bbeb90d5 100644 ---- a/setup.py -+++ b/setup.py -@@ -667,9 +667,30 @@ def check_extension_import(self, ext): - def add_multiarch_paths(self): - # Debian/Ubuntu multiarch support. - # https://wiki.ubuntu.com/MultiarchSpec -- tmpfile = os.path.join(self.build_temp, 'multiarch') - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) -+ -+ tmpfile_sysroot = os.path.join(self.build_temp, 'sysroot') -+ ret_sysroot = run_command( -+ '%s -print-sysroot > %s 2> /dev/null' % (CC, tmpfile_sysroot)) -+ -+ try: -+ if ret_sysroot == 0: -+ with open(tmpfile_sysroot) as fp: -+ sysroot = fp.readline().strip() -+ # if the sysroot is not /, then we are not using -+ # the compiler from debian/ubuntu -+ if sysroot not in ['', '/']: -+ add_dir_to_list(self.compiler.library_dirs, -+ sysroot + '/usr/lib/') -+ add_dir_to_list(self.compiler.include_dirs, -+ sysroot + '/usr/include/') -+ return -+ finally: -+ os.unlink(tmpfile_sysroot) -+ -+ tmpfile = os.path.join(self.build_temp, 'multiarch') -+ - ret = run_command( - '%s -print-multiarch > %s 2> /dev/null' % (CC, tmpfile)) - multiarch_path_component = '' ---- a/setup.py 2021-09-28 23:49:53.193868987 -0700 -+++ b/setup.py 2021-09-28 23:50:13.554098642 -0700 -@@ -738,7 +738,8 @@ - for env_var, arg_name, dir_list in ( - ('LDFLAGS', '-R', self.compiler.runtime_library_dirs), - ('LDFLAGS', '-L', self.compiler.library_dirs), -- ('CPPFLAGS', '-I', self.compiler.include_dirs)): -+ ('CPPFLAGS', '-I', self.compiler.include_dirs), -+ ('CPPFLAGS', '-isystem', self.compiler.include_dirs)): - env_val = sysconfig.get_config_var(env_var) - if env_val: - parser = argparse.ArgumentParser() --- -2.30.2 - diff --git a/build/pkgs/python3/patches/linux_linking_issue_25229.patch b/build/pkgs/python3/patches/linux_linking_issue_25229.patch deleted file mode 100644 index 43131a27913..00000000000 --- a/build/pkgs/python3/patches/linux_linking_issue_25229.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -ru a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py ---- a/Lib/distutils/unixccompiler.py 2018-06-27 05:07:35.000000000 +0200 -+++ b/Lib/distutils/unixccompiler.py 2018-06-28 09:32:52.719006731 +0200 -@@ -234,7 +234,7 @@ - return ["-Wl,+s", "-L" + dir] - return ["+s", "-L" + dir] - else: -- if self._is_gcc(compiler): -+ if sys.platform[:5] == "linux" or self._is_gcc(compiler): - # gcc on non-GNU systems does not need -Wl, but can - # use it anyway. Since distutils has always passed in - # -Wl whenever gcc was used in the past it is probably diff --git a/build/pkgs/python3/spkg-configure.m4 b/build/pkgs/python3/spkg-configure.m4 index d67601a98ae..a51e2394e51 100644 --- a/build/pkgs/python3/spkg-configure.m4 +++ b/build/pkgs/python3/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([python3], [ m4_pushdef([MIN_VERSION], [3.9.0]) m4_pushdef([MIN_NONDEPRECATED_VERSION], [3.9.0]) - m4_pushdef([LT_STABLE_VERSION], [3.12.0]) + m4_pushdef([LT_STABLE_VERSION], [3.13.0]) m4_pushdef([LT_VERSION], [3.13.0]) AC_ARG_WITH([python], [AS_HELP_STRING([--with-python=PYTHON3], diff --git a/build/pkgs/r/SPKG.rst b/build/pkgs/r/SPKG.rst index 584294e891a..393860a2064 100644 --- a/build/pkgs/r/SPKG.rst +++ b/build/pkgs/r/SPKG.rst @@ -24,3 +24,14 @@ Upstream Contact - https://www.r-project.org - R mailing list, #R in IRC + + +Special Installation Instructions +--------------------------------- + +In the Sage distribution, ``r`` is a "dummy" package: +It is here to provide information about equivalent system packages. +R cannot be installed using the Sage distribution. +Please install it manually, either using one of the system package +commands shown here or following the upstream instructions +at https://www.r-project.org diff --git a/build/pkgs/r/distros/conda.txt b/build/pkgs/r/distros/conda.txt index 4c235733c5f..741d5f82d93 100644 --- a/build/pkgs/r/distros/conda.txt +++ b/build/pkgs/r/distros/conda.txt @@ -1,2 +1,3 @@ r r-essentials +r-lattice diff --git a/build/pkgs/requests/checksums.ini b/build/pkgs/requests/checksums.ini index 8b0dc85bd89..d7a9d3b8c66 100644 --- a/build/pkgs/requests/checksums.ini +++ b/build/pkgs/requests/checksums.ini @@ -1,4 +1,4 @@ tarball=requests-VERSION-py3-none-any.whl -sha1=60b928b15e05d04a33b880a0232e44258c777740 -sha256=58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f +sha1=e82ece8f17ba4237cc5a4fd641349e45e1d3ddfd +sha256=fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c upstream_url=https://pypi.io/packages/py3/r/requests/requests-VERSION-py3-none-any.whl diff --git a/build/pkgs/requests/dependencies b/build/pkgs/requests/dependencies index 668fe014f12..6d09b791ef2 100644 --- a/build/pkgs/requests/dependencies +++ b/build/pkgs/requests/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) idna urllib3 certifi charset_normalizer $(PYTHON) +charset_normalizer idna urllib3 certifi | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/requests/package-version.txt b/build/pkgs/requests/package-version.txt index bafceb320ec..544fe5d4382 100644 --- a/build/pkgs/requests/package-version.txt +++ b/build/pkgs/requests/package-version.txt @@ -1 +1 @@ -2.31.0 +2.32.2 diff --git a/build/pkgs/rpy2/SPKG.rst b/build/pkgs/rpy2/SPKG.rst index 3ba34445021..ba81ab6c098 100644 --- a/build/pkgs/rpy2/SPKG.rst +++ b/build/pkgs/rpy2/SPKG.rst @@ -12,12 +12,16 @@ License ------- - GPL 2+ -- Note that we have deleted references to Mozilla PL as an option, - which we are allowed to do by the full rpy2 license in order to - remain GPL-compatible - Upstream Contact ---------------- -- https://rpy2.bitbucket.io +- https://github.com/rpy2/rpy2 + +Special Installation Instructions +--------------------------------- + +In the Sage distribution, ``rpy2`` is a "semi-standard" package: It will be +automatically installed by the Sage distribution if a suitable system +installation of R is detected by ``configure``. (Note that Sage no longer +ships and installs its own copy of R.) diff --git a/build/pkgs/sage_conf/version_requirements.txt b/build/pkgs/sage_conf/version_requirements.txt index bf5142c02e5..dca9dbbf204 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.4b9 +sage-conf ~= 10.4rc0 diff --git a/build/pkgs/sage_docbuild/version_requirements.txt b/build/pkgs/sage_docbuild/version_requirements.txt index 3bc4e773ff1..008698c16c6 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.4b9 +sage-docbuild ~= 10.4rc0 diff --git a/build/pkgs/sage_setup/version_requirements.txt b/build/pkgs/sage_setup/version_requirements.txt index d04bde41fdd..e20cf38ff03 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.4b9 +sage-setup ~= 10.4rc0 diff --git a/build/pkgs/sage_sws2rst/version_requirements.txt b/build/pkgs/sage_sws2rst/version_requirements.txt index d3698b0a9ae..62965fc6d95 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.4b9 +sage-sws2rst ~= 10.4rc0 diff --git a/build/pkgs/sagelib/version_requirements.txt b/build/pkgs/sagelib/version_requirements.txt index 1dd1a4f846b..bf2e7bc9cda 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.4b9 +sagemath-standard ~= 10.4rc0 diff --git a/build/pkgs/sagemath_bliss/version_requirements.txt b/build/pkgs/sagemath_bliss/version_requirements.txt index bc95834828a..da26126cba2 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.4b9 +sagemath-bliss ~= 10.4rc0 diff --git a/build/pkgs/sagemath_categories/type b/build/pkgs/sagemath_categories/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/sagemath_categories/type +++ b/build/pkgs/sagemath_categories/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/sagemath_categories/version_requirements.txt b/build/pkgs/sagemath_categories/version_requirements.txt index 08fa02e2044..ba9c2395040 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.4b9 +sagemath-categories ~= 10.4rc0 diff --git a/build/pkgs/sagemath_coxeter3/version_requirements.txt b/build/pkgs/sagemath_coxeter3/version_requirements.txt index 13e0b652f36..d9b7a8503be 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.4b9 +sagemath-coxeter3 ~= 10.4rc0 diff --git a/build/pkgs/sagemath_environment/type b/build/pkgs/sagemath_environment/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/sagemath_environment/type +++ b/build/pkgs/sagemath_environment/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/sagemath_environment/version_requirements.txt b/build/pkgs/sagemath_environment/version_requirements.txt index 72433ad30cd..3f7a3473daa 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.4b9 +sagemath-environment ~= 10.4rc0 diff --git a/build/pkgs/sagemath_mcqd/version_requirements.txt b/build/pkgs/sagemath_mcqd/version_requirements.txt index 76e1fd5907c..5fd55401260 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.4b9 +sagemath-mcqd ~= 10.4rc0 diff --git a/build/pkgs/sagemath_meataxe/version_requirements.txt b/build/pkgs/sagemath_meataxe/version_requirements.txt index db6dcee5827..b1217ec6b0a 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.4b9 +sagemath-meataxe ~= 10.4rc0 diff --git a/build/pkgs/sagemath_objects/type b/build/pkgs/sagemath_objects/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/sagemath_objects/type +++ b/build/pkgs/sagemath_objects/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/sagemath_objects/version_requirements.txt b/build/pkgs/sagemath_objects/version_requirements.txt index a48fb049cb7..a7052900eec 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.4b9 +sagemath-objects ~= 10.4rc0 diff --git a/build/pkgs/sagemath_repl/type b/build/pkgs/sagemath_repl/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/sagemath_repl/type +++ b/build/pkgs/sagemath_repl/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/sagemath_repl/version_requirements.txt b/build/pkgs/sagemath_repl/version_requirements.txt index 661b369f395..3615095a834 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.4b9 +sagemath-repl ~= 10.4rc0 diff --git a/build/pkgs/sagemath_sirocco/version_requirements.txt b/build/pkgs/sagemath_sirocco/version_requirements.txt index af89ffdd30f..066d5854f62 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.4b9 +sagemath-sirocco ~= 10.4rc0 diff --git a/build/pkgs/sagemath_tdlib/version_requirements.txt b/build/pkgs/sagemath_tdlib/version_requirements.txt index 13e940295b6..74cf6d8910c 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.4b9 +sagemath-tdlib ~= 10.4rc0 diff --git a/build/pkgs/send2trash/checksums.ini b/build/pkgs/send2trash/checksums.ini index d99aecb6b2f..8617b6b9b6b 100644 --- a/build/pkgs/send2trash/checksums.ini +++ b/build/pkgs/send2trash/checksums.ini @@ -1,4 +1,4 @@ -tarball=Send2Trash-VERSION.tar.gz -sha1=211092dcefa5468582f7d083472ad7f1880cc019 -sha256=c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312 -upstream_url=https://pypi.io/packages/source/s/send2trash/Send2Trash-VERSION.tar.gz +tarball=Send2Trash-VERSION-py3-none-any.whl +sha1=e24d3494febe78a4a1c8ecbfde78ed52e78cf299 +sha256=0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9 +upstream_url=https://pypi.io/packages/py3/s/send2trash/Send2Trash-VERSION-py3-none-any.whl diff --git a/build/pkgs/send2trash/dependencies b/build/pkgs/send2trash/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/send2trash/dependencies +++ b/build/pkgs/send2trash/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/send2trash/package-version.txt b/build/pkgs/send2trash/package-version.txt index 53adb84c822..a7ee35a3ea7 100644 --- a/build/pkgs/send2trash/package-version.txt +++ b/build/pkgs/send2trash/package-version.txt @@ -1 +1 @@ -1.8.2 +1.8.3 diff --git a/build/pkgs/send2trash/spkg-install.in b/build/pkgs/send2trash/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/send2trash/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/sniffio/checksums.ini b/build/pkgs/sniffio/checksums.ini index 8379b1841d0..c3a342052ec 100644 --- a/build/pkgs/sniffio/checksums.ini +++ b/build/pkgs/sniffio/checksums.ini @@ -1,4 +1,4 @@ tarball=sniffio-VERSION-py3-none-any.whl -sha1=16f883fd7e31aa383df8901002f9ce5cec7606e5 -sha256=eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 +sha1=bd8d1ec2b285eed542c53ca22232e6e9e468c389 +sha256=2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 upstream_url=https://pypi.io/packages/py3/s/sniffio/sniffio-VERSION-py3-none-any.whl diff --git a/build/pkgs/sniffio/dependencies b/build/pkgs/sniffio/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/sniffio/dependencies +++ b/build/pkgs/sniffio/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sniffio/package-version.txt b/build/pkgs/sniffio/package-version.txt index f0bb29e7638..3a3cd8cc8b0 100644 --- a/build/pkgs/sniffio/package-version.txt +++ b/build/pkgs/sniffio/package-version.txt @@ -1 +1 @@ -1.3.0 +1.3.1 diff --git a/build/pkgs/sympy/SPKG.rst b/build/pkgs/sympy/SPKG.rst index 12ccea9393b..45138f58d5b 100644 --- a/build/pkgs/sympy/SPKG.rst +++ b/build/pkgs/sympy/SPKG.rst @@ -24,16 +24,5 @@ New BSD: http://www.opensource.org/licenses/bsd-license.php Upstream Contact ---------------- -sympy mailinglist: http://groups.google.com/group/sympy +https://pypi.org/project/sympy/ -Dependencies ------------- - -- Python 2.5 or later - - -Special Update/Build Instructions ---------------------------------- - -- A simple script can be used to ease the updating of the SPKG. See the - README. diff --git a/build/pkgs/sympy/checksums.ini b/build/pkgs/sympy/checksums.ini index 4a8b9107b71..30e67c20de6 100644 --- a/build/pkgs/sympy/checksums.ini +++ b/build/pkgs/sympy/checksums.ini @@ -1,4 +1,4 @@ -tarball=sympy-VERSION.tar.gz -sha1=604968f191e2d69053b8310066d089f73a1bd109 -sha256=ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8 -upstream_url=https://github.com/sympy/sympy/releases/download/sympy-VERSION/sympy-VERSION.tar.gz +tarball=sympy-VERSION-py3-none-any.whl +sha1=80fa00ab605295d61992ca3faa76771a62944527 +sha256=9b2cbc7f1a640289430e13d2a56f02f867a1da0190f2f99d8968c2f74da0e515 +upstream_url=https://pypi.io/packages/py3/s/sympy/sympy-VERSION-py3-none-any.whl diff --git a/build/pkgs/sympy/dependencies b/build/pkgs/sympy/dependencies index 6480ac46289..d5cdd780fb4 100644 --- a/build/pkgs/sympy/dependencies +++ b/build/pkgs/sympy/dependencies @@ -1,4 +1,4 @@ - mpmath | $(PYTHON_TOOLCHAIN) $(PYTHON) +mpmath | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sympy/package-version.txt b/build/pkgs/sympy/package-version.txt index 809bdcb851d..f8f4f03b3dc 100644 --- a/build/pkgs/sympy/package-version.txt +++ b/build/pkgs/sympy/package-version.txt @@ -1 +1 @@ -1.12 +1.12.1 diff --git a/build/pkgs/sympy/spkg-install.in b/build/pkgs/sympy/spkg-install.in deleted file mode 100644 index 058b1344dc2..00000000000 --- a/build/pkgs/sympy/spkg-install.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src - -sdh_pip_install . diff --git a/build/pkgs/tdlib/SPKG.rst b/build/pkgs/tdlib/SPKG.rst index ebcdd1213e0..9f4c30a3d01 100644 --- a/build/pkgs/tdlib/SPKG.rst +++ b/build/pkgs/tdlib/SPKG.rst @@ -1,32 +1,23 @@ -tdlib: Algorithms for computing tree decompositions -=================================================== +tdlib: Algorithms for computing tree decompositions of graphs +============================================================= Description ----------- -Providing algorithms concerning treedecompositions +This library, now known as treedec, +provides algorithms concerning tree decompositions. -website: https://github.com/freetdi/tdlib License ------- -GNU General Public License v2 - - -SPKG Maintainers ----------------- - -Lukas Larisch (lukas.larisch@kaust.edu.sa) +- GNU General Public License v2 +- GNU General Public License v3 Upstream Contact ---------------- -- Lukas Larisch (lukas.larisch@kaust.edu.sa) -- git-repo: https://github.com/freetdi/tdlib - -Dependencies ------------- - -- None +- https://gitlab.com/freetdi/treedec +- https://github.com/freetdi/tdlib +- https://github.com/felix-salfelder diff --git a/build/pkgs/tdlib/checksums.ini b/build/pkgs/tdlib/checksums.ini index 6f3275ad092..36ade31259e 100644 --- a/build/pkgs/tdlib/checksums.ini +++ b/build/pkgs/tdlib/checksums.ini @@ -1,3 +1,4 @@ -tarball=tdlib-VERSION.tar.gz -sha1=8e200d0e3ac009030f3ada6658d20717e433220f -sha256=5a40375e738e9e6dbd37f53e54deb1efa6b58f154d83b7bfeaee9f47d47b444b +tarball=treedec-VERSION.tar.gz +sha1=355930ce66a14afed89d32ead280bfdd801d53d7 +sha256=16f9683af4c33e3e79fe36439cb4bb4b63216ad88d59f5dc00dd3fb9256aa4ae +upstream_url=https://www.algok.uni-bamberg.de/treedec/treedec-VERSION.tar.gz diff --git a/build/pkgs/tdlib/dependencies b/build/pkgs/tdlib/dependencies new file mode 100644 index 00000000000..d568ea3cf53 --- /dev/null +++ b/build/pkgs/tdlib/dependencies @@ -0,0 +1 @@ +boost_cropped diff --git a/build/pkgs/tdlib/package-version.txt b/build/pkgs/tdlib/package-version.txt index af2629893df..998ed53f13a 100644 --- a/build/pkgs/tdlib/package-version.txt +++ b/build/pkgs/tdlib/package-version.txt @@ -1 +1 @@ -0.3.1.p0 +0.9.3.p0 diff --git a/build/pkgs/tdlib/patches/0001-src-exact_cutset.hpp-Suppress-incomplete-message.patch b/build/pkgs/tdlib/patches/0001-src-exact_cutset.hpp-Suppress-incomplete-message.patch new file mode 100644 index 00000000000..9369b84d496 --- /dev/null +++ b/build/pkgs/tdlib/patches/0001-src-exact_cutset.hpp-Suppress-incomplete-message.patch @@ -0,0 +1,25 @@ +From f9bea896a49ef909aeb910c140661ab06b3b6a0b Mon Sep 17 00:00:00 2001 +From: Matthias Koeppe +Date: Fri, 7 Jun 2024 12:21:28 -0700 +Subject: [PATCH] src/exact_cutset.hpp: Suppress 'incomplete' message + +--- + src/exact_cutset.hpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/exact_cutset.hpp b/src/exact_cutset.hpp +index 782bb96..2caa7bd 100755 +--- a/src/exact_cutset.hpp ++++ b/src/exact_cutset.hpp +@@ -994,7 +994,7 @@ bool exact_cutset::try_it(T_t &T, unsigned bagsize) + }else{ + // incomplete(); //no// + // messes up random tests, send to cerr instead +- std::cerr << "incomplete ../../src/exact_cutset.hpp:978:try_it\n"; ++ // std::cerr << "incomplete ../../src/exact_cutset.hpp:978:try_it\n"; + } + + typename boost::graph_traits::vertex_iterator vIt, vEnd; +-- +2.42.0 + diff --git a/build/pkgs/tdlib/spkg-install.in b/build/pkgs/tdlib/spkg-install.in index 9ee5b9f1566..09c5e4899a0 100644 --- a/build/pkgs/tdlib/spkg-install.in +++ b/build/pkgs/tdlib/spkg-install.in @@ -1,5 +1,5 @@ cd src -sdh_configure +sdh_configure --with-python=no sdh_make sdh_make_install -j1 diff --git a/build/pkgs/traitlets/checksums.ini b/build/pkgs/traitlets/checksums.ini index 4be4683da86..ad86191465c 100644 --- a/build/pkgs/traitlets/checksums.ini +++ b/build/pkgs/traitlets/checksums.ini @@ -1,4 +1,4 @@ -tarball=traitlets-VERSION.tar.gz -sha1=9f4cb2a04ffba7029ad67bbec3d39a23e9095db2 -sha256=fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772 -upstream_url=https://pypi.io/packages/source/t/traitlets/traitlets-VERSION.tar.gz +tarball=traitlets-VERSION-py3-none-any.whl +sha1=a6c667ce2b3adf2ab3562f144067f02326383c25 +sha256=b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f +upstream_url=https://pypi.io/packages/py3/t/traitlets/traitlets-VERSION-py3-none-any.whl diff --git a/build/pkgs/traitlets/dependencies b/build/pkgs/traitlets/dependencies index 85237293d1c..644ad35f773 100644 --- a/build/pkgs/traitlets/dependencies +++ b/build/pkgs/traitlets/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) ipython_genutils hatchling $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/traitlets/package-version.txt b/build/pkgs/traitlets/package-version.txt index 0a70cf03ca9..487fc4986a9 100644 --- a/build/pkgs/traitlets/package-version.txt +++ b/build/pkgs/traitlets/package-version.txt @@ -1 +1 @@ -5.14.0 +5.14.3 diff --git a/build/pkgs/traitlets/spkg-install.in b/build/pkgs/traitlets/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/traitlets/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/typing_extensions/checksums.ini b/build/pkgs/typing_extensions/checksums.ini index 2c1dd61052d..c22c17569af 100644 --- a/build/pkgs/typing_extensions/checksums.ini +++ b/build/pkgs/typing_extensions/checksums.ini @@ -1,4 +1,4 @@ tarball=typing_extensions-VERSION-py3-none-any.whl -sha1=84d6a73b5a5d303c9187a861d5eedd50da42e7a3 -sha256=8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 +sha1=049c6031f754e1c33932ce1c2ad78b857a70a244 +sha256=b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594 upstream_url=https://pypi.io/packages/py3/t/typing_extensions/typing_extensions-VERSION-py3-none-any.whl diff --git a/build/pkgs/typing_extensions/package-version.txt b/build/pkgs/typing_extensions/package-version.txt index 88f181192c4..815588ef140 100644 --- a/build/pkgs/typing_extensions/package-version.txt +++ b/build/pkgs/typing_extensions/package-version.txt @@ -1 +1 @@ -4.8.0 +4.12.0 diff --git a/build/pkgs/virtualenv/checksums.ini b/build/pkgs/virtualenv/checksums.ini index 386df56a132..c83cfa5112d 100644 --- a/build/pkgs/virtualenv/checksums.ini +++ b/build/pkgs/virtualenv/checksums.ini @@ -1,4 +1,4 @@ tarball=virtualenv-VERSION-py3-none-any.whl -sha1=9c942063d76d85361f0567b59cce8238c57f1183 -sha256=4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3 +sha1=f18ea5b827ba66a1724769371c6912601ec4d647 +sha256=a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b upstream_url=https://pypi.io/packages/py3/v/virtualenv/virtualenv-VERSION-py3-none-any.whl diff --git a/build/pkgs/virtualenv/dependencies b/build/pkgs/virtualenv/dependencies index 148ef28948e..16beaa039a1 100644 --- a/build/pkgs/virtualenv/dependencies +++ b/build/pkgs/virtualenv/dependencies @@ -1,4 +1,4 @@ -distlib filelock platformdirs | pip $(PYTHON) +distlib filelock importlib_metadata platformdirs | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/virtualenv/package-version.txt b/build/pkgs/virtualenv/package-version.txt index 242a1e92b72..608d0b1c8b7 100644 --- a/build/pkgs/virtualenv/package-version.txt +++ b/build/pkgs/virtualenv/package-version.txt @@ -1 +1 @@ -20.25.0 +20.26.2 diff --git a/build/pkgs/zipp/checksums.ini b/build/pkgs/zipp/checksums.ini index aef55046c00..1af443d7f19 100644 --- a/build/pkgs/zipp/checksums.ini +++ b/build/pkgs/zipp/checksums.ini @@ -1,4 +1,4 @@ tarball=zipp-VERSION-py3-none-any.whl -sha1=8dd92e1b777b02ec6e1ebe72926d32a82c58b246 -sha256=0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 +sha1=22cf149f293964ac7538ad41af8caa9aacf8fe1a +sha256=96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec upstream_url=https://pypi.io/packages/py3/z/zipp/zipp-VERSION-py3-none-any.whl diff --git a/build/pkgs/zipp/package-version.txt b/build/pkgs/zipp/package-version.txt index 3f67e25cea1..419f3009654 100644 --- a/build/pkgs/zipp/package-version.txt +++ b/build/pkgs/zipp/package-version.txt @@ -1 +1 @@ -3.17.0 +3.19.0 diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 018e5a2d5b5..2b8b44959b1 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -441,6 +441,7 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre if not version: version = pypi_version.version if dependencies is None: + log.info('Requires-Python: {0}'.format(pypi_version.requires_python)) requires_dist = pypi_version.requires_dist if requires_dist: dependencies = [] diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index bc607ebb6e6..c063af0c816 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -31,7 +31,7 @@ def __new__(cls, package_name): if package_name.startswith("pypi/") or package_name.startswith("generic/"): package_name = "pkg:" + package_name if package_name.startswith("pkg:"): - package_name = package_name.replace('_', '-') + package_name = package_name.replace('_', '-').lower() if package_name.startswith("pkg:generic/"): # fast path try: pkg = cls(package_name[len("pkg:generic/"):].replace('-', '_')) diff --git a/build/sage_bootstrap/pypi.py b/build/sage_bootstrap/pypi.py index 9427e9c8808..215feb69343 100644 --- a/build/sage_bootstrap/pypi.py +++ b/build/sage_bootstrap/pypi.py @@ -114,6 +114,13 @@ def requires_dist(self): """ return self.json['info']['requires_dist'] + @property + def requires_python(self): + """ + Return the requires_python attribute + """ + return self.json['info']['requires_python'] + def update(self, package=None): if package is None: package = Package(self.name) diff --git a/m4/sage_python_package_check.m4 b/m4/sage_python_package_check.m4 index 6465a67d7c0..921639e3735 100644 --- a/m4/sage_python_package_check.m4 +++ b/m4/sage_python_package_check.m4 @@ -8,8 +8,8 @@ # Determine if the system copy of a python package can be used by sage. # # This macro uses setuptools.version's pkg_resources to check that the -# "version_requirements.txt" file for the named package is satisfied, and -# it can typically fail in four ways: +# "version_requirements.txt" file (or entry in "src/pyproject.toml") for +# the named package is satisfied, and it can typically fail in four ways: # # 1. If --enable-system-site-packages was not passed to ./configure, # @@ -19,8 +19,9 @@ # # 4. If setuptools is not available to the system python, # -# 5. If the contents of version_requirements.txt are not met (wrong -# version, no version, etc.) by the system python. +# 5. If the contents of version_requirements.txt (or entry in +# "src/pyproject.toml") are not met (wrong version, no version, +# etc.) by the system python. # # In any of those cases, we set sage_spkg_install_$package to "yes" # so that the corresponding SPKG is installed. Otherwise, we do @@ -56,29 +57,17 @@ AC_DEFUN([SAGE_PYTHON_PACKAGE_CHECK], [ config.venv dnl 2>&AS_MESSAGE_LOG_FD], [ AC_MSG_RESULT(yes) - dnl strip all comments from version_requirements.txt; this should leave - dnl only a single line containing the version specification for this - dnl package. Afterwards, convert all double-quotes to single quotes. - dnl Both work, but only single quotes are documented. However, at the - dnl time of writing, double quotes are more compatible with our toml - dnl generation in ./bootstrap. Converting them from double- to single- - dnl quotes on-the-fly here lets us support both (in this macro, at - dnl least). - SAGE_PKG_VERSPEC=$(sed \ - -e '/^#/d' \ - -e "s/\"/'/g" \ - "./build/pkgs/$1/version_requirements.txt" - ) - AC_MSG_CHECKING([for python package $1 ("${SAGE_PKG_VERSPEC}")]) + dnl SAGE_PKG_VERSPEC is in the format of a toml list, but + dnl without surrounding brackets, of single-quoted strings, + dnl with any double-quotes escaped by backslash. + AS_VAR_SET([SAGE_PKG_VERSPEC], ["SPKG_INSTALL_REQUIRES_]$1["]) + AC_MSG_CHECKING([for python package $1 (${SAGE_PKG_VERSPEC%,})]) WITH_SAGE_PYTHONUSERBASE([dnl - dnl double-quote SAGE_PKG_VERSPEC because platform-specific - dnl dependencies like python_version<'3.11' will have single - dnl quotes in them. (We normalized the quotes earlier with sed.) AS_IF( - [config.venv/bin/python3 -c dnl - "import pkg_resources; dnl - pkg_resources.require(\"${SAGE_PKG_VERSPEC}\".splitlines())" dnl + [config.venv/bin/python3 -c dnl + "import pkg_resources; dnl + pkg_resources.require((${SAGE_PKG_VERSPEC}))" dnl 2>&AS_MESSAGE_LOG_FD], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no); sage_spkg_install_$1=yes] diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 28480d720dd..231193ce8fb 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -75,7 +75,15 @@ m4_include([m4/sage_spkg_configures.m4]) dnl ========================================================================== AC_DEFUN([SAGE_SPKG_COLLECT_INIT], [ +AS_BOX([Build status for each package: ]) >& AS_MESSAGE_FD +AS_BOX([Build status for each package: ]) >& AS_MESSAGE_LOG_FD dnl Intialize the collection variables. +SPKGS="$1" +dnl Obtain versions at configure time. +AS_IF([properties=$($SAGE_BOOTSTRAP_PYTHON build/bin/sage-package properties --format=shell $SPKGS 2>& AS_MESSAGE_LOG_FD) && eval $properties], [], [ + AC_MSG_ERROR([Package directory missing. Re-run bootstrap.])dnl +]) + # To deal with ABI incompatibilities when gcc is upgraded, every package # (except gcc) should depend on gcc if gcc is already installed. # See https://github.com/sagemath/sage/issues/24703 @@ -86,20 +94,6 @@ else fi AC_SUBST([SAGE_GCC_DEP]) -AS_BOX([Build status for each package: ]) >& AS_MESSAGE_FD -AS_BOX([Build status for each package: ]) >& AS_MESSAGE_LOG_FD - -# Usage: newest_version $pkg -# Print version number of latest package $pkg -newest_version() { - SPKG=$[1] - if test -f "$SAGE_ROOT/build/pkgs/$SPKG/package-version.txt" ; then - cat "$SAGE_ROOT/build/pkgs/$SPKG/package-version.txt" - else - echo none - fi -} - # Packages that are actually built/installed as opposed to packages that are # not required on this platform or that can be taken from the underlying system # installation. Note that this contains packages that are not actually going to @@ -157,16 +151,15 @@ AC_DEFUN([SAGE_SPKG_FINALIZE], [dnl dnl depending on the package type and other criteria (such as whether or not it dnl needs to be installed) dnl - DIR="$SAGE_ROOT"/build/pkgs/SPKG_NAME - AS_IF([test ! -d "$DIR"], [dnl - AC_MSG_ERROR([Directory $DIR is missing. Re-run bootstrap.])dnl - ]) - dnl - SPKG_VERSION=$(newest_version SPKG_NAME) + SPKG_VERSION=$[version_with_patchlevel_]SPKG_NAME dnl dnl Determine package source dnl m4_case(SPKG_SOURCE, + [wheel], [dnl Treat it the same as a normal package + m4_define([SPKG_SOURCE], [normal])dnl + m4_define([in_sdist], [yes])dnl + ], [normal], [dnl m4_define([in_sdist], [yes])dnl ], [dnl pip/script/none (dummy package) @@ -206,7 +199,7 @@ AC_DEFUN([SAGE_SPKG_FINALIZE], [dnl AS_IF([test -r "$f"], [dnl AS_IF([test "$is_installed" = "yes"], [dnl m4_case(SPKG_SOURCE, [normal], [dnl - dnl Only issue the multiple installation record test for normal packages, + dnl Only issue the multiple installation record test for normal/wheel packages, dnl not for script packages. AC_MSG_ERROR(m4_normalize([ multiple installation records for SPKG_NAME: @@ -346,6 +339,7 @@ AC_DEFUN([SAGE_SPKG_FINALIZE], [dnl dnl dnl Determine package dependencies dnl + DIR=$[path_]SPKG_NAME AS_IF([test -f "$DIR/dependencies"], [dnl dnl - the # symbol is treated as comment which is removed AS_VAR_SET([DEPS], [`sed 's/^ *//; s/ *#.*//; q' $DIR/dependencies`]) diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-bliss/README.rst b/pkgs/sagemath-bliss/README.rst index 72526111226..b1a27056fd4 100644 --- a/pkgs/sagemath-bliss/README.rst +++ b/pkgs/sagemath-bliss/README.rst @@ -8,18 +8,15 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. About this pip-installable source distribution diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-categories/README.rst b/pkgs/sagemath-categories/README.rst index 398b5f81a91..01e974442f8 100644 --- a/pkgs/sagemath-categories/README.rst +++ b/pkgs/sagemath-categories/README.rst @@ -8,27 +8,25 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. -About this experimental pip-installable source distribution ------------------------------------------------------------ +About this pip-installable distribution package +----------------------------------------------- -This pip-installable source distribution `sagemath-categories` is an -experimental distribution of a small part of the Sage Library. Use at your own -risk. It provides a small subset of the modules of the Sage library -("sagelib", `sagemath-standard`). It is a superset of the `sagemath-objects` +The pip-installable distribution package `sagemath-categories` is a +distribution of a small part of the Sage Library. + +It provides a small subset of the modules of the Sage library +("sagelib", `sagemath-standard`) that is a superset of `sagemath-objects` (providing Sage objects, the element/parent framework, categories, the coercion system and the related metaclasses), making various additional categories available without introducing dependencies on additional mathematical diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-coxeter3/README.rst b/pkgs/sagemath-coxeter3/README.rst index c75e83995a3..4df12768344 100644 --- a/pkgs/sagemath-coxeter3/README.rst +++ b/pkgs/sagemath-coxeter3/README.rst @@ -8,18 +8,15 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. About this pip-installable source distribution diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-environment/README.rst b/pkgs/sagemath-environment/README.rst index a8003060bd9..9c36dbc67df 100644 --- a/pkgs/sagemath-environment/README.rst +++ b/pkgs/sagemath-environment/README.rst @@ -8,26 +8,24 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. -About this experimental pip-installable source distribution ------------------------------------------------------------ +About this pip-installable distribution package +----------------------------------------------- -This pip-installable source distribution `sagemath-environment` is an -experimental distribution of a small part of the Sage Library. Use at your own -risk. It provides a small, fundamental subset of the modules of the Sage +The pip-installable distribution package `sagemath-environment` is a +distribution of a small part of the Sage Library. + +It provides a small, fundamental subset of the modules of the Sage library ("sagelib", `sagemath-standard`), providing the connection to the system and software environment. It also includes the `sage` script for launching the Sage REPL and accessing various developer tools (see `sage diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-mcqd/README.rst b/pkgs/sagemath-mcqd/README.rst index 4fcf37ec1a3..a0da3415874 100644 --- a/pkgs/sagemath-mcqd/README.rst +++ b/pkgs/sagemath-mcqd/README.rst @@ -8,18 +8,15 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. About this pip-installable source distribution diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-meataxe/README.rst b/pkgs/sagemath-meataxe/README.rst index e38540cc304..69c03deee6f 100644 --- a/pkgs/sagemath-meataxe/README.rst +++ b/pkgs/sagemath-meataxe/README.rst @@ -8,18 +8,15 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. About this pip-installable source distribution diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-objects/README.rst b/pkgs/sagemath-objects/README.rst index e2959d72eae..11f2444e982 100644 --- a/pkgs/sagemath-objects/README.rst +++ b/pkgs/sagemath-objects/README.rst @@ -8,26 +8,24 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. -About this experimental pip-installable source distribution ------------------------------------------------------------ +About this pip-installable distribution package +----------------------------------------------- -This pip-installable source distribution `sagemath-objects` is an experimental -distribution of a small part of the Sage Library. Use at your own risk. It -provides a small, fundamental subset of the modules of the Sage library +The pip-installable distribution package `sagemath-objects` is a +distribution of a small part of the Sage Library. + +It provides a small, fundamental subset of the modules of the Sage library ("sagelib", `sagemath-standard`), making Sage objects, the element/parent framework, categories, the coercion system and the related metaclasses available. diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-repl/README.rst b/pkgs/sagemath-repl/README.rst index 115614a5d7e..53c3ac0e2de 100644 --- a/pkgs/sagemath-repl/README.rst +++ b/pkgs/sagemath-repl/README.rst @@ -8,25 +8,23 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. -About this experimental pip-installable source distribution ------------------------------------------------------------ +About this pip-installable distribution package +----------------------------------------------- -This pip-installable source distribution `sagemath-repl` is an experimental -distribution of a small part of the Sage Library. Use at your own risk. It -provides a small, fundamental subset of the modules of the Sage library +The pip-installable source distribution `sagemath-repl` is a +distribution of a small part of the Sage Library. + +It provides a small, fundamental subset of the modules of the Sage library ("sagelib", `sagemath-standard`), providing the IPython kernel, Sage preparser, and doctester. diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-sirocco/README.rst b/pkgs/sagemath-sirocco/README.rst index 824ca3b03a6..31d70482784 100644 --- a/pkgs/sagemath-sirocco/README.rst +++ b/pkgs/sagemath-sirocco/README.rst @@ -8,18 +8,15 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. About this pip-installable source distribution diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/pkgs/sagemath-tdlib/README.rst b/pkgs/sagemath-tdlib/README.rst index fb1729a073c..2f7d210e52f 100644 --- a/pkgs/sagemath-tdlib/README.rst +++ b/pkgs/sagemath-tdlib/README.rst @@ -8,18 +8,15 @@ About SageMath "Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, and MATLAB" - Copyright (C) 2005-2023 The Sage Development Team + Copyright (C) 2005-2024 The Sage Development Team https://www.sagemath.org SageMath fully supports all major Linux distributions, recent versions of macOS, and Windows (Windows Subsystem for Linux). -The traditional and recommended way to install SageMath is from source via -Sage-the-distribution (https://www.sagemath.org/download-source.html). -Sage-the-distribution first builds a large number of open source packages from -source (unless it finds suitable versions installed in the system) and then -installs the Sage Library (sagelib, implemented in Python and Cython). +See https://doc.sagemath.org/html/en/installation/index.html +for general installation instructions. About this pip-installable source distribution diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/src/VERSION.txt b/src/VERSION.txt index 88de6ab407c..ab84d34dabd 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.4.beta9 +10.4.rc0 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index e07f9f4e32b..b0b4139bf29 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.4.beta9' -SAGE_RELEASE_DATE='2024-06-09' -SAGE_VERSION_BANNER='SageMath version 10.4.beta9, Release Date: 2024-06-09' +SAGE_VERSION='10.4.rc0' +SAGE_RELEASE_DATE='2024-06-22' +SAGE_VERSION_BANNER='SageMath version 10.4.rc0, Release Date: 2024-06-22' diff --git a/src/doc/en/developer/portability_platform_table.rst b/src/doc/en/developer/portability_platform_table.rst index 6b8c0724001..67ebb9f7c0b 100644 --- a/src/doc/en/developer/portability_platform_table.rst +++ b/src/doc/en/developer/portability_platform_table.rst @@ -1618,60 +1618,6 @@ .. |codespace-centos-7-devtoolset-gcc_11-maximal| image:: https://github.com/codespaces/badge.svg :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-7-devtoolset-gcc_11-maximal%2Fdevcontainer.json -.. |image-centos-stream-8-python3.9-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-system-packages - -.. |image-centos-stream-8-python3.9-minimal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-minimal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-minimal-configured - -.. |image-centos-stream-8-python3.9-minimal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%23677895 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-targets-pre - -.. |image-centos-stream-8-python3.9-minimal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%236686c1 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-targets - -.. |image-centos-stream-8-python3.9-minimal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%236495ed - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-minimal-with-targets-optional - -.. |codespace-centos-stream-8-python3.9-minimal| image:: https://github.com/codespaces/badge.svg - :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-stream-8-python3.9-minimal%2Fdevcontainer.json - -.. |image-centos-stream-8-python3.9-standard-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-system-packages - -.. |image-centos-stream-8-python3.9-standard-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-standard-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-standard-configured - -.. |image-centos-stream-8-python3.9-standard-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%235d8a4c - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-targets-pre - -.. |image-centos-stream-8-python3.9-standard-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%2350ab2e - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-targets - -.. |image-centos-stream-8-python3.9-standard-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%2344cc11 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-standard-with-targets-optional - -.. |codespace-centos-stream-8-python3.9-standard| image:: https://github.com/codespaces/badge.svg - :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-stream-8-python3.9-standard%2Fdevcontainer.json - -.. |image-centos-stream-8-python3.9-maximal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-system-packages - -.. |image-centos-stream-8-python3.9-maximal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-maximal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-maximal-configured - -.. |image-centos-stream-8-python3.9-maximal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%238f6b8d - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-targets-pre - -.. |image-centos-stream-8-python3.9-maximal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%23b46eb2 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-targets - -.. |image-centos-stream-8-python3.9-maximal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%23da70d6 - :target: https://ghcr.io/sagemath/sage/sage-centos-stream-8-python3.9-maximal-with-targets-optional - -.. |codespace-centos-stream-8-python3.9-maximal| image:: https://github.com/codespaces/badge.svg - :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-stream-8-python3.9-maximal%2Fdevcontainer.json - .. |image-centos-stream-9-python3.9-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-9-python3.9-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 :target: https://ghcr.io/sagemath/sage/sage-centos-stream-9-python3.9-minimal-with-system-packages @@ -2712,17 +2658,6 @@ * -    ‑*maximal* - |image-centos-7-devtoolset-gcc_11-maximal-with-system-packages| |image-centos-7-devtoolset-gcc_11-maximal-with-targets-pre| - - * - **centos**-stream-8-python3.9 - -    ‑*minimal* - - |image-centos-stream-8-python3.9-minimal-with-system-packages| |image-centos-stream-8-python3.9-minimal-with-targets-pre| |image-centos-stream-8-python3.9-minimal-with-targets| |image-centos-stream-8-python3.9-minimal-with-targets-optional| - - |codespace-centos-stream-8-python3.9-minimal| - * -    ‑*standard* - - |image-centos-stream-8-python3.9-standard-with-system-packages| |image-centos-stream-8-python3.9-standard-with-targets-pre| |image-centos-stream-8-python3.9-standard-with-targets| |image-centos-stream-8-python3.9-standard-with-targets-optional| - - |codespace-centos-stream-8-python3.9-standard| - * -    ‑*maximal* - - |image-centos-stream-8-python3.9-maximal-with-system-packages| |image-centos-stream-8-python3.9-maximal-with-targets-pre| - - * - **centos**-stream-9-python3.9    ‑*minimal* diff --git a/src/doc/en/reference/algebras/index.rst b/src/doc/en/reference/algebras/index.rst index 6f50276a5ed..621767627b5 100644 --- a/src/doc/en/reference/algebras/index.rst +++ b/src/doc/en/reference/algebras/index.rst @@ -79,6 +79,7 @@ Hecke algebras :maxdepth: 1 sage/algebras/hecke_algebras/ariki_koike_algebra + sage/algebras/hecke_algebras/ariki_koike_specht_modules sage/algebras/iwahori_hecke_algebra sage/algebras/nil_coxeter_algebra sage/algebras/yokonuma_hecke_algebra diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 3d314f9c466..b7725c7848b 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -154,6 +154,12 @@ REFERENCES: equilibria for two-person games*. http://www.maths.lse.ac.uk/personal/stengel/TEXTE/nashsurvey.pdf (2002) +.. [AHK1994] Sheldon B. Akers, Doy Horel and Balakrishnan Krishnamurthy, + *The star graph: An attractive alternative to the previous n-cube*. + In Interconnection Networks for High-Performance Parallel + Computers, pp. 145-152, 1994. IEEE. + :doi:`10.5555/201173.201191` + .. [AHK2015] Karim Adiprasito, June Huh, and Eric Katz. *Hodge theory for combinatorial geometries*. :arxiv:`1511.02888`. @@ -1451,6 +1457,11 @@ REFERENCES: rationalité d'une série génératrice associée aux arbres*, RAIRO, Inf. Théor. 16, 113--128 (1982) +.. [CC1995] Wei-Kuo Chiang, Rong-Jaye Chen: *The (n, k)-star graph: A + generalized star graph*. Information Processing Letters + 56(5): 259-264, 1995. + :doi:`10.1016/0020-0190(95)00162-1` + .. [CC2013] Mahir Bilen Can and Yonah Cherniavsky. *Omitting parentheses from the cyclic notation*. (2013). :arxiv:`1308.0936v2`. @@ -2315,6 +2326,9 @@ REFERENCES: .. [DPVAR2000] \J. Daemen, M. Peeters, G. Van Assche, and V. Rijmen, *Nessie proposal: NOEKEON*; in First Open NESSIE Workshop, (2000). +.. [DR2001] \J. Du and H. Rui. *Specht modules for Ariki–Koike algebras*, + Comm. Alg., **29** (2001), 4710-4719. + .. [DR2002] Joan Daemen, Vincent Rijmen. *The Design of Rijndael*. Springer-Verlag Berlin Heidelberg, 2002. @@ -2683,6 +2697,10 @@ REFERENCES: *Quantization of Lie Groups and Lie Algebras*. Leningrad Math. J. vol. **1** (1990), no. 1. +.. [Fru1977] Roberto Frucht. *A Canonical Representation of Trivalent + Hamiltonian Graphs*. Journal of Graph Theory, 1:45-60, 1977. + :doi:`10.1002/jgt.3190010111` + .. [FS1978] Dominique Foata, Marcel-Paul Schuetzenberger. *Major Index and Inversion Number of Permutations*. Mathematische Nachrichten, volume 83, Issue 1, pages 143-159, 1978. @@ -3039,6 +3057,11 @@ REFERENCES: 4-polytopes with 8 vertices", J. Comb. Th. 2, 437-465 (1967) +.. [Gru2003] Branko Grünbaum. *Convex Polytopes* (2nd ed),. + volume 221 of Graduate Texts in Mathematics, Springer, 2003. + (1st ed, 1967, Wiley New York). + :doi:`10.1007/978-1-4613-0019-9` + .. [GS1984] \A. M. Garsia, Dennis Stanton. *Group actions on Stanley-Reisner rings and invariants of permutation groups*. Adv. in Math. **51** (1984), 107-201. @@ -4222,6 +4245,14 @@ REFERENCES: Simons Symposia, Springer, 2021. :arxiv:`2002.05234` +.. [Led1965] Joshua Lederberg. *DENDRAL-64: A System for Computer + Construction, Enumeration and Notation of Organic + Molecules as Tree Structures and Cyclic + Graphs. Part II. Topology of Cyclic Graphs*. Interim + Report to the National Aeronautics and Space + Administration. Grant NsG 81-60. December 15, 1965. + https://ntrs.nasa.gov/api/citations/19660004785/downloads/19660004785.pdf + .. [Lee2016] Kwankyu Lee, *Decoding of differential AG codes*, Advances in Mathematics of Communications, vol. 10, no. 2 (2016), pp. 307-–319. @@ -4621,13 +4652,20 @@ REFERENCES: Providence, RI, 1999. xiv+188 pp. ISBN: 0-8218-1926-7 :mathscinet:`MR1711316` -.. [Mat2002] Jiří Matousek, "Lectures on Discrete Geometry", Springer, - 2002 +.. [Mathas2002] Andrew Mathas. + *The representation theory of the Ariki-Koike and + cyclotomic* `q`-*Schur algebras*. + Representation Theory of Algebraic Groups and Quantum Groups, + Adv. Stud. Pure Math., vol. 40, Math. Soc. Japan, Tokyo (2004), + pp. 261-320. :arxiv:`math/0204025`. .. [Mathas2004] Andrew Mathas. *Matrix units and generic degrees for the Ariki-Koike algebras*. J. Algebra. **281** (2004) pp. 695-730. +.. [Mat2002] Jiří Matousek, "Lectures on Discrete Geometry", Springer, + 2002 + .. [Mas1995] Mason, Geoffrey. *The quantum double of a finite group and its role in conformal field theory*. Groups '93 Galway/St. Andrews, Vol. 2, 405-417, London Math. Soc. Lecture Note Ser., 212, Cambridge, 1995. @@ -6383,6 +6421,11 @@ REFERENCES: Journal of Combinatorial Theory, Series A 16.3 (1974), pp 313–333. :doi:`10.1016/0097-3165(74)90056-9` +.. [TVY2020] \N. V. Tsilevich, A. M. Vershik, and S. Yuzvinsky. + *The intrinsic hyperplane arrangement in an arbitrary irreducible + representation of the symmetric group*, Arnold Math. J. **6** + no. 2 (2020) pp. 173-187. + .. [TW1980] \A.D. Thomas and G.V. Wood, Group Tables (Exeter: Shiva Publishing, 1980) @@ -6579,6 +6622,9 @@ REFERENCES: *Coboundary categories and local rules*, The Electronic Journal of Combinatorics, *25* (2018) +.. [West2001] Douglas B. West. *Introduction to Graph Theory*. 2nd + Edition, Prentice Hall, 2001, p. 150–151. + .. [WFYTP2008] \D. Watanable, S. Furuya, H. Yoshida, K. Takaragi, and B. Preneel, *A new keystream generator MUGI*; in FSE, (2002), pp. 179-194. diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py index 100a3d335f3..72744da3904 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py @@ -39,7 +39,8 @@ class FiniteDimensionalAlgebraIdeal(Ideal_generic): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.ideal(A([0,1])) Ideal (e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 """ @@ -47,9 +48,10 @@ def __init__(self, A, gens=None, given_by_matrix=False): """ EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: I = A.ideal(A([0,1])) - sage: TestSuite(I).run(skip="_test_category") # Currently ideals are not using the category framework + sage: TestSuite(I).run(skip="_test_category") # Currently ideals are not using the category framework """ k = A.base_ring() n = A.degree() @@ -76,7 +78,8 @@ def _richcmp_(self, other, op): TESTS:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: I = A.ideal(A([1,1])) sage: J = A.ideal(A([0,1])) sage: I == J @@ -86,7 +89,8 @@ def _richcmp_(self, other, op): sage: I == I + J True - sage: A2 = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A2 = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A is A2 True sage: A == A2 @@ -130,7 +134,8 @@ def __contains__(self, elt): """ EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: J = A.ideal(A([0,1])) sage: A([0,1]) in J True @@ -147,7 +152,8 @@ def basis_matrix(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: I = A.ideal(A([1,1])) sage: I.basis_matrix() [1 0] @@ -162,7 +168,8 @@ def vector_space(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: I = A.ideal(A([1,1])) sage: I.vector_space() Vector space of degree 2 and dimension 2 over Finite Field of size 3 diff --git a/src/sage/algebras/free_algebra_quotient_element.py b/src/sage/algebras/free_algebra_quotient_element.py index c4ade5274b2..0523ff4b9dc 100644 --- a/src/sage/algebras/free_algebra_quotient_element.py +++ b/src/sage/algebras/free_algebra_quotient_element.py @@ -38,6 +38,10 @@ def is_FreeAlgebraQuotientElement(x): sage: H, (i,j,k) = sage.algebras.free_algebra_quotient.hamilton_quatalg(QQ) sage: sage.algebras.free_algebra_quotient_element.is_FreeAlgebraQuotientElement(i) + doctest:warning... + DeprecationWarning: The function is_FreeAlgebraQuotientElement is deprecated; + use 'isinstance(..., FreeAlgebraQuotientElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True Of course this is testing the data type:: @@ -47,6 +51,10 @@ def is_FreeAlgebraQuotientElement(x): sage: sage.algebras.free_algebra_quotient_element.is_FreeAlgebraQuotientElement(H(1)) True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_FreeAlgebraQuotientElement is deprecated; " + "use 'isinstance(..., FreeAlgebraQuotientElement)' instead.") return isinstance(x, FreeAlgebraQuotientElement) diff --git a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py index 30078e8ecdf..3bc2e541f7e 100644 --- a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py +++ b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py @@ -192,6 +192,8 @@ class ArikiKoikeAlgebra(Parent, UniqueRepresentation): default is the generators of `\ZZ[u_1, \ldots, u_r]` - ``R`` -- (optional) a commutative ring containing ``q`` and ``u``; the default is the parent of `q` and `u_1, \ldots, u_r` + - ``use_fraction_field`` -- (default: ``False``) whether to use the + fraction field or not EXAMPLES: @@ -268,7 +270,7 @@ class ArikiKoikeAlgebra(Parent, UniqueRepresentation): True """ @staticmethod - def __classcall_private__(cls, r, n, q=None, u=None, R=None): + def __classcall_private__(cls, r, n, q=None, u=None, R=None, use_fraction_field=False): r""" Standardize input to ensure a unique representation. @@ -311,11 +313,12 @@ def __classcall_private__(cls, r, n, q=None, u=None, R=None): R = cm.common_parent(q.parent(), *[val.parent() for val in u]) elif q is None: q = 'q' - u = [R(val) for val in u] if R not in Rings().Commutative(): raise TypeError("base ring must be a commutative ring") + if use_fraction_field: + R = R.fraction_field() q = R(q) - u = tuple(u) + u = tuple([R(val) for val in u]) return super().__classcall__(cls, r, n, q, u, R) def __init__(self, r, n, q, u, R): @@ -414,6 +417,21 @@ def a_realization(self): """ return self.LT() + def specht_module(self, la): + r""" + Return the Specht module of ``self`` corresponding to the shape ``la``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(4, 6) + sage: AK.specht_module([[2], [], [1,1,1], [1]]) + Specht module of shape ([2], [], [1, 1, 1], [1]) for + Ariki-Koike algebra of rank 4 and order 6 with q=q and u=(u0, u1, u2, u3) + over ... over Integer Ring + """ + from sage.algebras.hecke_algebras.ariki_koike_specht_modules import SpechtModule + return SpechtModule(self, la) + class _BasesCategory(Category_realization_of_parent): r""" The category of bases of a Ariki-Koike algebra. @@ -566,6 +584,24 @@ def some_elements(self): elts += [self.L(2)**(self._r//2)] return elts + def specht_module(self, la): + r""" + Return the Specht module of ``self`` corresponding + to the shape ``la``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(4, 3) + sage: LT = AK.LT() + sage: S1 = LT.specht_module([[1], [], [1,1], []]) + sage: T = AK.T() + sage: S2 = T.specht_module([[1], [], [1,1], []]) + sage: S1 is S2 + True + """ + from sage.algebras.hecke_algebras.ariki_koike_specht_modules import SpechtModule + return SpechtModule(self.realization_of(), la) + # ----------------------------------------------------- # Basis classes # ----------------------------------------------------- @@ -1186,6 +1222,18 @@ def __init__(self, algebra): _Basis.__init__(self, algebra, prefix='T') self._assign_names(['T%s' % i for i in range(self._n)]) + def _basis_to_word(self, t): + """ + Return the basis element indexed by ``m`` to a word. + """ + redword = [] + for i, k in enumerate(t[0]): + if not k: + continue + redword.extend(list(range(i, 0, -1)) + [0]*k) + redword.extend(t[1].reduced_word()) + return redword + def _repr_term(self, t): r""" Return a string representation of the basis element indexed by ``m``. @@ -1196,13 +1244,8 @@ def _repr_term(self, t): sage: T._repr_term( ((1,0,2), Permutation([3,2,1])) ) 'T[0,2,1,0,0,2,1,2]' """ - redword = [] - for i,k in enumerate(t[0]): - if k == 0: - continue - redword += list(reversed(range(1,i+1))) + [0]*k - redword += t[1].reduced_word() - if len(redword) == 0: + redword = self._basis_to_word(t) + if not redword: return "1" return (self._print_options['prefix'] + '[%s]' % ','.join('%d' % i for i in redword)) @@ -1215,15 +1258,10 @@ def _latex_term(self, t): sage: T = algebras.ArikiKoike(4, 3).T() sage: T._latex_term( ((1,0,2), Permutation([3,2,1])) ) - 'T_{0}T_{1}T_{0}T_{0}T_{2}T_{1}T_{2}' + 'T_{0}T_{2}T_{1}T_{0}T_{0}T_{2}T_{1}T_{2}' """ - redword = [] - for i,k in enumerate(t[0]): - if k == 0: - continue - redword += list(reversed(range(1,i))) + [0]*k - redword += t[1].reduced_word() - if len(redword) == 0: + redword = self._basis_to_word(t) + if not redword: return "1" return ''.join("%s_{%d}" % (self._print_options['prefix'], i) for i in redword) @@ -1529,7 +1567,7 @@ def product_on_basis(self, m1, m2): # Compute t1 * T * sprod def compute(T, sprod): - if not T: # T=1, so just do t1 * sprod, each of which is in order + if not T: # T=1, so just do t1 * sprod, each of which is in order return self._from_dict({(t1, s): sprod[s] for s in sprod}, remove_zeros=False, coerce=False) diff --git a/src/sage/algebras/hecke_algebras/ariki_koike_specht_modules.py b/src/sage/algebras/hecke_algebras/ariki_koike_specht_modules.py new file mode 100644 index 00000000000..2bb7974ab35 --- /dev/null +++ b/src/sage/algebras/hecke_algebras/ariki_koike_specht_modules.py @@ -0,0 +1,473 @@ +r""" +Ariki-Koike Algebra Representations + +AUTHORS: + +- Travis Scrimshaw (2023-12-28): Initial version +""" + +#***************************************************************************** +# Copyright (C) 2023 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/ +#***************************************************************************** + +from sage.misc.misc_c import prod +from sage.misc.latex import latex +from sage.categories.modules import Modules +from sage.rings.integer_ring import ZZ +from sage.combinat.free_module import CombinatorialFreeModule +from sage.combinat.partition_tuple import PartitionTuples +from sage.combinat.permutation import Permutations +from sage.combinat.tableau_tuple import StandardTableauTuples + + +class SpechtModule(CombinatorialFreeModule): + r""" + Specht module of the Ariki-Koike algebra. + + Let `H_{r,n}(q, u)` be the Ariki-Koike algebra with parameters `q` + and `u = (u_1, \ldots, u_r)` (note our indexing convention for + the `u` parameters differs from + :mod:`sage.algebras.hecke_algebras.ariki_koike_algebra`) over a + commutative ring `R`. Let `\lambda` be a partition tuple of level + `r` and size `n`. The *Specht module* of shape `\lambda` is the (right) + `H_{r,n}(q,u)`-representation `S^{\lambda}` given as free `R`-module + with basis given by the standard tableau (tuples) of shape `\lambda`. + + We will now describe the right action of the Ariki-Koike algebra, + but we first need to set some notation and definitions. + Let `t` be a standard tableau tuple of level `r` and size `n`. + Define the *residue* of `i` in `t` to be `r_t(i) = q^{c-r} u_k`, + where `i` is in cell `(r, c)` of the `k`-th tableau. + + The action of `L_i` is given by `t \cdot L_i = r_T(i) t`. For `T_i`, + we need to consider the following cases. If `i, i+1` are in the same + row (resp. column), then `t \cdot T_i = q t` (resp. `t \cdot T_i = -t`). + Otherwise if we swap `i, i+1`, the resulting tableau tuple `s` is again + standard and the action is given by + + .. MATH:: + + t \cdot T_i = \frac{(q - 1) r_t(i)}{r_s(i) - r_t(i)} t + + \frac{q r_t(i) - r_s(i)}{r_s(i) - r_t(i)} s. + + Note that `r_s(i) = r_t(i+1)`. + + Over a field of characteristic `0`, the set of Specht modules for all + partition tuples of level `r` and size `n` form the complete set + of irreducible modules for `H_{r,n}(q, u)` [AK1994]_. (The condition + on the base ring can be weakened; see Theorem 3.2 of [Mathas2002]_.) + + EXAMPLES: + + We construct the Specht module `S^{(2,1,21)}` for `H_{3,6}(q, u)` with + generic parameters `q, u` over `\GF(3)` and perform some basic + computations. We change the tableaux to use the compact representation + to condense the output:: + + sage: TableauTuples.options.display = 'compact' + + sage: R = PolynomialRing(GF(3), 'u', 3) + sage: u = R.gens() + sage: q = R['q'].gen() + sage: H = algebras.ArikiKoike(3, 6, q, u, use_fraction_field=True) + sage: LT = H.LT() + sage: T0, T1, T2, T3, T4, T5 = LT.T() + sage: S = H.specht_module([[2], [1], [2,1]]) + sage: S.dimension() + 120 + sage: elt = S.an_element(); elt + S[1,2|3|4,5/6] - S[1,3|2|4,5/6] + S[1,3|4|2,5/6] + sage: elt * LT.L(3) + u1*S[1,2|3|4,5/6] + (-u0*q)*S[1,3|2|4,5/6] + u0*q*S[1,3|4|2,5/6] + sage: elt * T2 + (((-u0-u1)*q-u1)/(-u0*q+u1))*S[1,2|3|4,5/6] + + (((-u0+u2)*q)/(u0*q-u2))*S[1,2|4|3,5/6] + + ((-u0*q^2-u0*q-u1)/(-u0*q+u1))*S[1,3|2|4,5/6] + + ((u0*q^2-u0*q)/(u0*q-u2))*S[1,3|4|2,5/6] + sage: (elt * T3) * T2 == elt * (T3 * T2) + True + sage: elt * T2 * T3 * T2 == elt * T3 * T2 * T3 + True + sage: elt * T0 * T1 * T0 * T1 == elt * T1 * T0 * T1 * T0 + True + sage: elt * T2 * T5 == elt * T5 * T2 + True + + sage: TableauTuples.options._reset() + + REFERENCES: + + - [AK1994]_ + - [DJM1998]_ + - [DR2001]_ + - [Mathas2002]_ + - [Mathas2004]_ + """ + @staticmethod + def __classcall_private__(cls, AK, la): + """ + Normalize input to ensure a unique representation. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 6) + sage: S1 = AK.specht_module([[3], [1], [1,1]]) + sage: S2 = AK.specht_module(PartitionTuple([[3], [1], [1,1]])) + sage: S1 is S2 + True + """ + la = PartitionTuples(AK._r, AK._n)(la) + return super().__classcall__(cls, AK, la) + + def __init__(self, AK, la): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 6, use_fraction_field=True) + sage: S = AK.specht_module([[3], [1], [1,1]]) + sage: TestSuite(S).run() # long time + sage: Sp = AK.specht_module([[], [2,1,1], [2]]) + sage: TestSuite(Sp).run() # long time + """ + self._shape = la + self._AK = AK + self._q = AK.q() + self._u = AK.u() + self._Pn = Permutations(la.size()) + indices = StandardTableauTuples(la) + R = AK.base_ring() + cat = Modules(R).FiniteDimensional().WithBasis() + CombinatorialFreeModule.__init__(self, R, indices, category=cat, prefix='S') + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 8) + sage: AK.specht_module([[3], [], [2,2,1]]) + Specht module of shape ([3], [], [2, 2, 1]) for + Ariki-Koike algebra of rank 3 and order 8 with q=q and u=(u0, u1, u2) + over ... over Integer Ring + """ + return "Specht module of shape {} for {}".format(self._shape, self._AK) + + def _latex_(self): + r""" + Return a latex representation of ``self``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 8) + sage: S = AK.specht_module([[3], [], [2,2,1]]) + sage: latex(S) + S^{{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} + \raisebox{-.6ex}{$\begin{array}[b]{*{3}c}\cline{1-3} + \lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-3} + \end{array}$},\emptyset,\raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\cline{1-2} + \lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2} + \lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2} + \lr{\phantom{x}}\\\cline{1-1} + \end{array}$} + }}_{\mathcal{H}_{3,8}(q)} + """ + return "S^{{{}}}_{{{}}}".format(latex(self._shape), latex(self._AK)) + + def _test_representation(self, **options): + r""" + Test that the relations of the Ariki-Koike algebra are satisfied. + + EXAMPLES:: + + sage: q = ZZ['q'].fraction_field().gen() + sage: AK = algebras.ArikiKoike(2, 4, q, [q^2+1, q-3], q.parent()) + sage: S = AK.specht_module([[2,1], [1]]) + sage: S._test_representation(elements=S.basis()) + """ + tester = self._tester(**options) + n = self._shape.size() + q = self._q + from sage.misc.misc import some_tuples + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + + # Build the polynomial for testing the T0 action + z = PolynomialRing(self.base_ring(), 'DUMMY').gen() + T0_poly = -prod(z - val for val in self._u) + + def apply_T0_power(b, exp): + for i in range(exp): + b = b.T(0) + return b + + AKelts = self._AK.some_elements() + for b in tester.some_elements(): + t0 = self.linear_combination((apply_T0_power(b, exp), c) + for exp, c in enumerate(T0_poly)) + tester.assertEqual(t0, self.zero()) + + tester.assertEqual(b.T([0, 1, 0, 1]), b.T([1, 0, 1, 0])) + tester.assertEqual(b.T(1).T(1), (q-1)*b.T(1) + q*b) + for i in range(2, n): + tester.assertEqual(b.T(i).T(i), (q-1)*b.T(i) + q*b) + tester.assertEqual(b.T(i).T(0), b.T(0).T(i)) + if i < n - 1: + tester.assertEqual(b.T([i, i+1, i]), b.T([i+1, i, i+1])) + for j in range(i+2, n): + tester.assertEqual(b.T([i, j]), b.T([j, i])) + + for (x, y) in some_tuples(AKelts, 2, tester._max_runs): + tester.assertEqual(b*(x*y), (b*x)*y) + + def _L_on_basis(self, i, t): + """ + Return the action of `L_i` on the basis element indexed by + the standard tableau tuple ``t``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 10) + sage: S = AK.specht_module([[2,1], [], [3,2,2]]) + sage: P = S.basis().keys() + sage: t = P([[[2,4],[8]], [], [[1,3,7],[5,6],[9,10]]]) + sage: S._L_on_basis(1, t) + u2*S[([[2, 4], [8]], [], [[1, 3, 7], [5, 6], [9, 10]])] + sage: S._L_on_basis(4, t) + u0*q*S[([[2, 4], [8]], [], [[1, 3, 7], [5, 6], [9, 10]])] + sage: S._L_on_basis(6, t) + u2*S[([[2, 4], [8]], [], [[1, 3, 7], [5, 6], [9, 10]])] + sage: S._L_on_basis(8, t) + (u0*q^-1)*S[([[2, 4], [8]], [], [[1, 3, 7], [5, 6], [9, 10]])] + sage: S._L_on_basis(9, t) + (u2*q^-2)*S[([[2, 4], [8]], [], [[1, 3, 7], [5, 6], [9, 10]])] + """ + c = t.cells_containing(i)[0] + if len(c) == 2: # it is of level 1 and a regular tableau + c = (0,) + c + res = self._q**(c[2]-c[1]) * self._u[c[0]] + R = self.base_ring() + return self.element_class(self, {t: R(res)}) + + def _T_on_basis(self, i, t): + r""" + Return the action of `T_i` on the basis element indexed by + the standard tableau tuple ``t``. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 10, use_fraction_field=True) + sage: S = AK.specht_module([[2,1], [], [3,2,2]]) + sage: P = S.basis().keys() + sage: t = P([[[2,4],[8]], [], [[1,5,7],[3,6],[9,10]]]) + sage: S._T_on_basis(0, t) == S._L_on_basis(1, t) + True + sage: S._T_on_basis(1, t) + ((u2*q-u0)/(u0-u2))*S[([[1, 4], [8]], [], [[2, 5, 7], [3, 6], [9, 10]])] + + ((u0*q-u0)/(u0-u2))*S[([[2, 4], [8]], [], [[1, 5, 7], [3, 6], [9, 10]])] + sage: S._T_on_basis(2, t) + ((u2*q-u2)/(-u0*q+u2))*S[([[2, 4], [8]], [], [[1, 5, 7], [3, 6], [9, 10]])] + + ((u0*q^2-u2)/(-u0*q+u2))*S[([[3, 4], [8]], [], [[1, 5, 7], [2, 6], [9, 10]])] + sage: S._T_on_basis(5, t) + -S[([[2, 4], [8]], [], [[1, 5, 7], [3, 6], [9, 10]])] + sage: S._T_on_basis(7, t) + ((u2*q^4-u0)/(-u2*q^3+u0))*S[([[2, 4], [7]], [], [[1, 5, 8], [3, 6], [9, 10]])] + + ((u0*q-u0)/(-u2*q^3+u0))*S[([[2, 4], [8]], [], [[1, 5, 7], [3, 6], [9, 10]])] + sage: S._T_on_basis(9, t) + q*S[([[2, 4], [8]], [], [[1, 5, 7], [3, 6], [9, 10]])] + """ + R = self.base_ring() + if i == 0: + return self._L_on_basis(1, t) + + ct = t.cells_containing(i)[0] + cs = t.cells_containing(i+1)[0] + if len(ct) == 2: # it is of level 1 and a regular tableau + ct = (0,) + ct + cs = (0,) + cs + + if ct[0] == cs[0] and ct[2] == cs[2]: # same column + return self.element_class(self, {t: -R.one()}) + + if ct[0] == cs[0] and ct[1] == cs[1]: # same row + return self.element_class(self, {t: self._q}) + + # result is standard + s = t.symmetric_group_action_on_entries(self._Pn.simple_reflection(i)) + assert s.parent() is t.parent() + + def res(cell): + return self._q**(cell[2]-cell[1]) * self._u[cell[0]] + + # Note that the residue of i in t is given by the cell c + # and of i in s corresponds to cell cp because the + # corresponding action of the permutation on t. + one = self.base_ring().one() + denom = res(cs) - res(ct) + coefft = (self._q - one) * res(cs) / denom + coeffs = (self._q * res(ct) - res(cs)) / denom + return self.element_class(self, {t: R(coefft), s: R(coeffs)}) + + def ariki_koike_algebra(self): + r""" + Return the Ariki-Koike algebra that ``self`` is a representation of. + + EXAMPLES:: + + sage: AK = algebras.ArikiKoike(3, 6) + sage: S = AK.specht_module([[2], [], [3,1]]) + sage: S.ariki_koike_algebra() is AK + True + """ + return self._AK + + class Element(CombinatorialFreeModule.Element): + def _acted_upon_(self, scalar, self_on_left): + r""" + Return the action of ``scalar`` on ``self``. + + EXAMPLES:: + + sage: TableauTuples.options.display = 'compact' + sage: AK = algebras.ArikiKoike(4, 6, use_fraction_field=True) + sage: q = AK.q() + sage: LT = AK.LT() + sage: T = AK.T() + sage: S = AK.specht_module([[], [2], [1], [2,1]]) + sage: elt = S.an_element() + sage: 5 * elt + 5*S[-|1,2|3|4,5/6] + 10*S[-|1,3|2|4,5/6] + 5*S[-|1,3|4|2,5/6] + + 15*S[-|2,3|1|4,5/6] + sage: elt * (q - 2) + (q-2)*S[-|1,2|3|4,5/6] + (2*q-4)*S[-|1,3|2|4,5/6] + + (q-2)*S[-|1,3|4|2,5/6] + (3*q-6)*S[-|2,3|1|4,5/6] + sage: elt * LT.an_element() == elt * T(LT.an_element()) + True + sage: T.an_element() * elt + Traceback (most recent call last): + ... + TypeError: unsupported operand parent(s) for *: 'Ariki-Koike algebra ... over Integer Ring' + sage: TableauTuples.options._reset() + + TESTS:: + + sage: AK = algebras.ArikiKoike(2, 4, use_fraction_field=True) + sage: LT = AK.LT() + sage: T = AK.T() + sage: S = AK.specht_module([[1], [2,1]]) + sage: B = list(LT.basis())[::55] + sage: all(b * x == b * T(x) for b in S.basis() for x in B) # long time + True + """ + ret = super()._acted_upon_(scalar, self_on_left) + if ret is not None: + return ret + if not self_on_left: # only a right action + return None + P = self.parent() + if scalar not in P._AK: + return None + scalar = P._AK(scalar) + if scalar.parent() is P._AK.LT(): + return P.linear_combination((self.L(sum(([i]*val for i, val in enumerate(m[0], start=1)), [])).T(m[1].reduced_word()), c) + for m, c in scalar) + elif scalar.parent() is P._AK.T(): + AKT = P._AK.T() + return P.linear_combination((self.T(AKT._basis_to_word(m)), c) + for m, c in scalar) + return self * P._AK.LT()(scalar) + + def L(self, i): + r""" + Return the (right) action of `L_i` on ``self``. + + INPUT: + + - ``i`` -- an integer or a list of integers + + EXAMPLES:: + + sage: TableauTuples.options.display = 'compact' # compact tableau printing + sage: AK = algebras.ArikiKoike(3, 6, use_fraction_field=True) + sage: S = AK.specht_module([[2], [], [3,1]]) + sage: elt = S.an_element(); elt + S[1,2|-|3,4,5/6] + 2*S[1,3|-|2,4,5/6] + + 3*S[2,3|-|1,4,5/6] + S[2,4|-|1,3,5/6] + sage: elt.L(1) + u0*S[1,2|-|3,4,5/6] + 2*u0*S[1,3|-|2,4,5/6] + + 3*u2*S[2,3|-|1,4,5/6] + u2*S[2,4|-|1,3,5/6] + sage: elt.L(2) + u0*q*S[1,2|-|3,4,5/6] + 2*u2*S[1,3|-|2,4,5/6] + + 3*u0*S[2,3|-|1,4,5/6] + u0*S[2,4|-|1,3,5/6] + sage: elt.L(6) + u2/q*S[1,2|-|3,4,5/6] + 2*u2/q*S[1,3|-|2,4,5/6] + + 3*u2/q*S[2,3|-|1,4,5/6] + u2/q*S[2,4|-|1,3,5/6] + sage: elt.L([3,3,3]) + u2^3*S[1,2|-|3,4,5/6] + 2*u0^3*q^3*S[1,3|-|2,4,5/6] + + 3*u0^3*q^3*S[2,3|-|1,4,5/6] + u2^3*q^3*S[2,4|-|1,3,5/6] + sage: LT = AK.LT() + sage: elt.L([3,3,3]) == elt * (LT.L(3)^3) + True + sage: TableauTuples.options._reset() # reset + """ + if not self: # action on 0 is 0 + return self + if i not in ZZ: + ret = self + for val in i: + ret = ret.L(val) + return ret + P = self.parent() + return P.linear_combination((P._L_on_basis(i, t), c) for t, c in self) + + def T(self, i): + r""" + Return the (right) action of `T_i` on ``self``. + + INPUT: + + - ``i`` -- an integer or a list of integers + + EXAMPLES:: + + sage: TableauTuples.options.display = 'compact' # compact tableau printing + sage: AK = algebras.ArikiKoike(3, 10, use_fraction_field=True) + sage: q = AK.q() + sage: S = AK.specht_module([[2,1], [], [3,2,2]]) + sage: P = S.basis().keys() + sage: t = P([[[2,4],[8]], [], [[1,5,7],[3,6],[9,10]]]) + sage: b = S.basis()[t] + sage: b.T(2) + ((u2*q-u2)/(-u0*q+u2))*S[2,4/8|-|1,5,7/3,6/9,10] + + ((u0*q^2-u2)/(-u0*q+u2))*S[3,4/8|-|1,5,7/2,6/9,10] + sage: b.T(6) + ((-q)/(q+1))*S[2,4/8|-|1,5,6/3,7/9,10] + + (q^2/(q+1))*S[2,4/8|-|1,5,7/3,6/9,10] + sage: b.T([2,1,2]) == b.T([1,2,1]) + True + sage: b.T(9) + q*S[2,4/8|-|1,5,7/3,6/9,10] + sage: all(b.T([i,i]) == (q-1)*b.T(i) + q*b for i in range(1,10)) + True + sage: b.T(0) + u2*S[2,4/8|-|1,5,7/3,6/9,10] + sage: b.T([0,1,0,1]) == b.T([1,0,1,0]) + True + sage: TableauTuples.options._reset() # reset + """ + if not self: # action on 0 is 0 + return self + if i not in ZZ: + ret = self + for val in i: + ret = ret.T(val) + return ret + P = self.parent() + return P.linear_combination((P._T_on_basis(i, t), c) for t, c in self) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 885ab854170..93e22abd6fd 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -51,7 +51,7 @@ from sage.rings.rational import Rational from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.ideal import Ideal_fractional -from sage.rings.rational_field import is_RationalField, QQ +from sage.rings.rational_field import RationalField, QQ from sage.rings.infinity import infinity from sage.rings.number_field.number_field_base import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -429,7 +429,7 @@ def is_division_algebra(self) -> bool: ... NotImplementedError: base field must be rational numbers """ - if not is_RationalField(self.base_ring()): + if not isinstance(self.base_ring(), RationalField): raise NotImplementedError("base field must be rational numbers") return self.discriminant() != 1 @@ -453,7 +453,7 @@ def is_matrix_ring(self) -> bool: NotImplementedError: base field must be rational numbers """ - if not is_RationalField(self.base_ring()): + if not isinstance(self.base_ring(), RationalField): raise NotImplementedError("base field must be rational numbers") return self.discriminant() == 1 @@ -678,7 +678,7 @@ def __init__(self, base_ring, a, b, names='i,j,k'): Parent.__init__(self, base=base_ring, names=names, category=cat) self._a = a self._b = b - if is_RationalField(base_ring) and a.denominator() == 1 == b.denominator(): + if isinstance(base_ring, RationalField) and a.denominator() == 1 == b.denominator(): self.Element = QuaternionAlgebraElement_rational_field elif (isinstance(base_ring, NumberField) and base_ring.degree() > 2 and base_ring.is_absolute() and a.denominator() == 1 == b.denominator() and base_ring.defining_polynomial().is_monic()): @@ -1066,7 +1066,7 @@ def is_definite(self): ... ValueError: base field must be rational numbers """ - if not is_RationalField(self.base_ring()): + if not isinstance(self.base_ring(), RationalField): raise ValueError("base field must be rational numbers") a, b = self.invariants() return a < 0 and b < 0 @@ -1218,7 +1218,7 @@ def discriminant(self): sage: QuaternionAlgebra(QQ[sqrt(2)], 3, 19).discriminant() # needs sage.symbolic Fractional ideal (1) """ - if not is_RationalField(self.base_ring()): + if not isinstance(self.base_ring(), RationalField): try: F = self.base_ring() return F.hilbert_conductor(self._a, self._b) @@ -1245,7 +1245,7 @@ def ramified_primes(self): sage: QuaternionAlgebra(QQ, -58, -69).ramified_primes() [3, 23, 29] """ - if not is_RationalField(self.base_ring()): + if not isinstance(self.base_ring(), RationalField): raise ValueError("base field must be the rational numbers") a, b = self._a, self._b @@ -2517,7 +2517,7 @@ def attempt_isomorphism(self, other): if other.quaternion_algebra() != Q: raise TypeError('not an order in the same quaternion algebra') - if not is_RationalField(Q.base_ring()): + if not isinstance(Q.base_ring(), RationalField): raise NotImplementedError('only implemented for orders in a rational quaternion algebra') if not Q.is_definite(): raise NotImplementedError('only implemented for definite quaternion orders') diff --git a/src/sage/arith/functions.pyx b/src/sage/arith/functions.pyx index 6e8f3db88a5..92dbc709897 100644 --- a/src/sage/arith/functions.pyx +++ b/src/sage/arith/functions.pyx @@ -39,17 +39,17 @@ def lcm(a, b=None): EXAMPLES:: - sage: lcm(97,100) + sage: lcm(97, 100) 9700 - sage: LCM(97,100) + sage: LCM(97, 100) 9700 - sage: LCM(0,2) + sage: LCM(0, 2) 0 - sage: LCM(-3,-5) + sage: LCM(-3, -5) 15 sage: LCM([1,2,3,4,5]) 60 - sage: v = LCM(range(1,10000)) # *very* fast! + sage: v = LCM(range(1, 10000)) # *very* fast! sage: len(str(v)) 4349 diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 310f2b0b189..28f81d7b798 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -3748,9 +3748,9 @@ def binomial(x, m, **kwds): Some floating point cases -- see :issue:`7562`, :issue:`9633`, and :issue:`12448`:: - sage: binomial(1., 3) + sage: binomial(1., 3) # needs sage.rings.real_mpfr 0.000000000000000 - sage: binomial(-2., 3) + sage: binomial(-2., 3) # needs sage.rings.real_mpfr -4.00000000000000 sage: binomial(0.5r, 5) 0.02734375 diff --git a/src/sage/arith/srange.pyx b/src/sage/arith/srange.pyx index 59c39d8fc2a..51855f9646d 100644 --- a/src/sage/arith/srange.pyx +++ b/src/sage/arith/srange.pyx @@ -234,16 +234,21 @@ def srange(*args, **kwds): sage: srange(1, 10, 1/2) [1, 3/2, 2, 5/2, 3, 7/2, 4, 9/2, 5, 11/2, 6, 13/2, 7, 15/2, 8, 17/2, 9, 19/2] + + sage: # needs sage.rings.real_mpfr sage: srange(1, 5, 0.5) - [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] + [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, + 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] sage: srange(0, 1, 0.4) [0.000000000000000, 0.400000000000000, 0.800000000000000] sage: srange(1.0, 5.0, include_endpoint=True) - [1.00000000000000, 2.00000000000000, 3.00000000000000, 4.00000000000000, 5.00000000000000] + [1.00000000000000, 2.00000000000000, 3.00000000000000, 4.00000000000000, + 5.00000000000000] sage: srange(1.0, 1.1) [1.00000000000000] sage: srange(1.0, 1.0) [] + sage: V = VectorSpace(QQ, 2) # needs sage.modules sage: srange(V([0,0]), V([5,5]), step=V([2,2])) # needs sage.modules [(0, 0), (2, 2), (4, 4)] @@ -264,7 +269,8 @@ def srange(*args, **kwds): sage: srange(0.5, 0.9, 0.1, universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999] sage: srange(0, 1.1, 0.1, universe=RDF, include_endpoint=True) - [0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 1.1] + [0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, + 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 1.1] sage: srange(0, 0.2, 0.1, universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2] sage: srange(0, 0.3, 0.1, universe=RDF, include_endpoint=True) @@ -275,9 +281,10 @@ def srange(*args, **kwds): sage: Q = RationalField() sage: srange(1, 10, Q('1/2')) [1, 3/2, 2, 5/2, 3, 7/2, 4, 9/2, 5, 11/2, 6, 13/2, 7, 15/2, 8, 17/2, 9, 19/2] - sage: srange(1, 5, 0.5) - [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] - sage: srange(0, 1, 0.4) + sage: srange(1, 5, 0.5) # needs sage.rings.real_mpfr + [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, + 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] + sage: srange(0, 1, 0.4) # needs sage.rings.real_mpfr [0.000000000000000, 0.400000000000000, 0.800000000000000] Negative steps are also allowed:: @@ -512,7 +519,7 @@ def ellipsis_range(*args, step=None): Examples in which the step determines the parent of the elements:: - sage: [1..3, step=0.5] + sage: [1..3, step=0.5] # needs sage.rings.real_mpfr [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000] sage: v = [1..5, step=1/1]; v [1, 2, 3, 4, 5] diff --git a/src/sage/categories/category_singleton.pyx b/src/sage/categories/category_singleton.pyx index 446c3f5ee33..d907eedb9e8 100644 --- a/src/sage/categories/category_singleton.pyx +++ b/src/sage/categories/category_singleton.pyx @@ -219,13 +219,14 @@ class Category_singleton(Category): , , , + , , , , , , , - <... 'object'>] + ] sage: R() is R() True sage: R() is R().__class__() diff --git a/src/sage/categories/chain_complexes.py b/src/sage/categories/chain_complexes.py index 640285f1633..6e6448f3d38 100644 --- a/src/sage/categories/chain_complexes.py +++ b/src/sage/categories/chain_complexes.py @@ -81,8 +81,8 @@ def homology(self, n=None): :: sage: # needs sage.combinat sage.modules - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) - sage: C = A.cdg_algebra({z: x*y}) + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.libs.singular + sage: C = A.cdg_algebra({z: x*y}) # needs sage.libs.singular sage: C.homology(0) Free module generated by {[1]} over Rational Field sage: C.homology(1) @@ -110,8 +110,8 @@ def differential(self, *args, **kwargs): :: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.combinat sage.modules - sage: C = A.cdg_algebra({z: x*y}) # needs sage.combinat sage.modules + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.combinat sage.libs.singular sage.modules + sage: C = A.cdg_algebra({z: x*y}) # needs sage.combinat sage.libs.singular sage.modules sage: C.differential() # needs sage.combinat sage.modules Differential of Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (2, 2, 3) over Rational Field @@ -183,8 +183,8 @@ class HomologyFunctor(Functor): :: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.combinat sage.modules - sage: C = A.cdg_algebra({z: x*y}) # needs sage.combinat sage.modules + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.combinat sage.libs.singular sage.modules + sage: C = A.cdg_algebra({z: x*y}) # needs sage.combinat sage.libs.singular sage.modules sage: H = HomologyFunctor(ChainComplexes(QQ), 2) sage: H(C) # needs sage.combinat sage.modules Free module generated by {[x], [y]} over Rational Field diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 8b9e20ad03e..25261db6645 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -937,22 +937,27 @@ def simple_projections(self, side='right', length_increasing=True): from sage.sets.family import Family return Family(self.index_set(), lambda i: self.simple_projection(i, side=side, length_increasing=length_increasing)) - def sign_representation(self, base_ring=None, side="twosided"): + def sign_representation(self, base_ring=None): r""" Return the sign representation of ``self`` over ``base_ring``. INPUT: - ``base_ring`` -- (optional) the base ring; the default is `\ZZ` - - ``side`` -- ignored EXAMPLES:: - sage: W = WeylGroup(["A", 1, 1]) # needs sage.combinat sage.groups - sage: W.sign_representation() # needs sage.combinat sage.groups + sage: W = WeylGroup(['D', 4]) # needs sage.combinat sage.groups + sage: W.sign_representation(QQ) # needs sage.combinat sage.groups Sign representation of - Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space) - over Integer Ring + Weyl Group of type ['D', 4] (as a matrix group acting on the ambient space) + over Rational Field + + sage: # optional - gap3 + sage: W = CoxeterGroup(['B',3], implementation="coxeter3") + sage: W.sign_representation() + Sign representation of Coxeter group of type ['B', 3] + implemented by Coxeter3 over Integer Ring """ if base_ring is None: from sage.rings.integer_ring import ZZ diff --git a/src/sage/categories/examples/lie_algebras.py b/src/sage/categories/examples/lie_algebras.py index 14dfce40c03..b8a3f9c8e21 100644 --- a/src/sage/categories/examples/lie_algebras.py +++ b/src/sage/categories/examples/lie_algebras.py @@ -71,7 +71,7 @@ def __classcall_private__(cls, gens): EXAMPLES:: - sage: # needs sage.combinat + sage: # needs sage.combinat sage.groups sage: S3 = SymmetricGroupAlgebra(QQ, 3) sage: L1 = LieAlgebras(QQ).example() sage: gens = list(S3.algebra_generators()) @@ -85,8 +85,8 @@ def __init__(self, gens): """ EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # needs sage.combinat - sage: TestSuite(L).run() # needs sage.combinat + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: TestSuite(L).run() # needs sage.combinat sage.groups """ if not gens: raise ValueError("need at least one generator") diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index a7474d07602..1a069f4d5e9 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -99,25 +99,31 @@ def __contains__(self, x): in other doctests, we introduced a strong reference to all previously created uncollected objects in :issue:`19244`. :: + sage: # needs sage.libs.pari sage: import gc sage: _ = gc.collect() - sage: permstore = [X for X in gc.get_objects() if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)] + sage: permstore = [X for X in gc.get_objects() + ....: if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)] sage: n = len(permstore) - sage: for i in prime_range(100): # needs sage.libs.pari + sage: for i in prime_range(100): ....: R = ZZ.quotient(i) ....: t = R in Fields() First, we show that there are now more quotient rings in cache than before:: - sage: len([X for X in gc.get_objects() if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)]) > n + sage: # needs sage.libs.pari + sage: len([X for X in gc.get_objects() + ....: if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)]) > n True When we delete the last quotient ring created in the loop and then do a garbage collection, all newly created rings vanish:: + sage: # needs sage.libs.pari sage: del R sage: _ = gc.collect() - sage: len([X for X in gc.get_objects() if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)]) - n + sage: len([X for X in gc.get_objects() + ....: if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)]) - n 0 """ @@ -624,15 +630,15 @@ def gcd(self,other): For field of characteristic zero, the gcd of integers is considered as if they were elements of the integer ring:: - sage: gcd(15.0,12.0) + sage: gcd(15.0,12.0) # needs sage.rings.real_mpfr 3.00000000000000 But for other floating point numbers, the gcd is just `0.0` or `1.0`:: - sage: gcd(3.2, 2.18) + sage: gcd(3.2, 2.18) # needs sage.rings.real_mpfr 1.00000000000000 - sage: gcd(0.0, 0.0) + sage: gcd(0.0, 0.0) # needs sage.rings.real_mpfr 0.000000000000000 AUTHOR: @@ -678,15 +684,15 @@ def lcm(self, other): For field of characteristic zero, the lcm of integers is considered as if they were elements of the integer ring:: - sage: lcm(15.0,12.0) + sage: lcm(15.0, 12.0) # needs sage.rings.real_mpfr 60.0000000000000 But for others floating point numbers, it is just `0.0` or `1.0`:: - sage: lcm(3.2, 2.18) + sage: lcm(3.2, 2.18) # needs sage.rings.real_mpfr 1.00000000000000 - sage: lcm(0.0, 0.0) + sage: lcm(0.0, 0.0) # needs sage.rings.real_mpfr 0.000000000000000 AUTHOR: @@ -748,13 +754,13 @@ def xgcd(self, other): the result is a floating point version of the standard gcd on `\ZZ`:: - sage: xgcd(12.0, 8.0) + sage: xgcd(12.0, 8.0) # needs sage.rings.real_mpfr (4.00000000000000, 1.00000000000000, -1.00000000000000) - sage: xgcd(3.1, 2.98714) + sage: xgcd(3.1, 2.98714) # needs sage.rings.real_mpfr (1.00000000000000, 0.322580645161290, 0.000000000000000) - sage: xgcd(0.0, 1.1) + sage: xgcd(0.0, 1.1) # needs sage.rings.real_mpfr (1.00000000000000, 0.000000000000000, 0.909090909090909) """ P = self.parent() @@ -787,7 +793,7 @@ def factor(self): sage: x = GF(7)(5) sage: x.factor() 5 - sage: RR(0).factor() + sage: RR(0).factor() # needs sage.rings.real_mpfr Traceback (most recent call last): ... ArithmeticError: factorization of 0.000000000000000 is not defined diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index a86754c9493..c5566fc0f20 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -686,6 +686,7 @@ def _repr_matrix(self): EXAMPLES:: + sage: # needs sage.modules sage: M = matrix(ZZ, [[1, 0, 0], [0, 1, 0]], ....: column_keys=['a', 'b', 'c'], ....: row_keys=['v', 'w']); M @@ -714,6 +715,7 @@ def _ascii_art_matrix(self): EXAMPLES:: + sage: # needs sage.modules sage: M = matrix(ZZ, [[1, 0, 0], [0, 1, 0]], ....: column_keys=['a', 'b', 'c'], ....: row_keys=['v', 'w']); M @@ -745,6 +747,7 @@ def _unicode_art_matrix(self): EXAMPLES:: + sage: # needs sage.modules sage: M = matrix(ZZ, [[1, 0, 0], [0, 1, 0]], ....: column_keys=['a', 'b', 'c'], ....: row_keys=['v', 'w']); M @@ -910,6 +913,7 @@ def characteristic_polynomial(self): EXAMPLES:: + sage: # needs sage.modules sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) sage: phi.characteristic_polynomial() x^2 - 3*x + 2 @@ -919,7 +923,6 @@ def characteristic_polynomial(self): x^2 - 3*x + 2 sage: phi.charpoly('T') T^2 - 3*T + 2 - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) sage: M = matrix(ZZ, [[1, 0], [1, 2]]) sage: psi = W.module_morphism(matrix=M, codomain=W) @@ -939,12 +942,12 @@ def determinant(self): EXAMPLES:: + sage: # needs sage.modules sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) sage: phi.determinant() 2 sage: phi.det() 2 - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) sage: M = matrix(ZZ, [[1, 0], [1, 2]]) sage: psi = W.module_morphism(matrix=M, codomain=W) @@ -966,12 +969,12 @@ def fcp(self): EXAMPLES:: + sage: # needs sage.modules sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) sage: phi.fcp() # needs sage.libs.pari (x - 2) * (x - 1) sage: phi.fcp('T') # needs sage.libs.pari (T - 2) * (T - 1) - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) sage: M = matrix(ZZ, [[1, 0], [1, 2]]) sage: psi = W.module_morphism(matrix=M, codomain=W) @@ -995,6 +998,7 @@ def minimal_polynomial(self): Compute the minimal polynomial, and check it. :: + sage: # needs sage.modules sage: V = GF(7)^3 sage: H = V.Hom(V)([[0,1,2], [-1,0,3], [2,4,1]]); H Vector space morphism represented by the matrix: @@ -1015,7 +1019,7 @@ def minimal_polynomial(self): Domain: Vector space of dimension 3 over Finite Field of size 7 Codomain: Vector space of dimension 3 over Finite Field of size 7 - sage: # needs sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings sage: k = GF(9, 'c') sage: V = CombinatorialFreeModule(k, ['x', 'y', 'z', 'w']) sage: A = matrix(k, 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) @@ -1038,10 +1042,10 @@ def trace(self): EXAMPLES:: + sage: # needs sage.modules sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) sage: phi.trace() 3 - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) sage: M = matrix(ZZ, [[1, 0], [1, 2]]) sage: psi = W.module_morphism(matrix=M, codomain=W) diff --git a/src/sage/categories/finite_groups.py b/src/sage/categories/finite_groups.py index a88a56e96cf..8ef8541bdbf 100644 --- a/src/sage/categories/finite_groups.py +++ b/src/sage/categories/finite_groups.py @@ -95,11 +95,11 @@ def cardinality(self): We need to use a finite group which uses this default implementation of cardinality:: - sage: G = groups.misc.SemimonomialTransformation(GF(5), 3); G + sage: G = groups.misc.SemimonomialTransformation(GF(5), 3); G # needs sage.rings.number_field Semimonomial transformation group over Finite Field of size 5 of degree 3 - sage: G.cardinality.__module__ + sage: G.cardinality.__module__ # needs sage.rings.number_field 'sage.categories.finite_groups' - sage: G.cardinality() + sage: G.cardinality() # needs sage.rings.number_field 384 """ if hasattr(self, 'order'): @@ -173,7 +173,7 @@ def conjugacy_classes_representatives(self): EXAMPLES:: sage: G = SymmetricGroup(3) - sage: G.conjugacy_classes_representatives() + sage: G.conjugacy_classes_representatives() # needs sage.combinat [(), (1,2), (1,2,3)] """ return [C.representative() for C in self.conjugacy_classes()] @@ -232,7 +232,7 @@ def __init_extra__(self): sage: A in Algebras.Semisimple False - sage: G = groups.misc.AdditiveCyclic(4) + sage: G = groups.misc.AdditiveCyclic(4) # needs sage.rings.number_field sage: Cat = CommutativeAdditiveGroups().Finite() sage: A = G.algebra(GF(5), category=Cat) sage: A in Algebras.Semisimple diff --git a/src/sage/categories/functor.pyx b/src/sage/categories/functor.pyx index 5e3262c8dd3..2ca369c2ef5 100644 --- a/src/sage/categories/functor.pyx +++ b/src/sage/categories/functor.pyx @@ -96,15 +96,15 @@ cdef class Functor(SageObject): Category of rings sage: F.codomain() Category of commutative additive groups - sage: from sage.categories.functor import is_Functor - sage: is_Functor(F) + sage: from sage.categories.functor import Functor + sage: isinstance(F, Functor) True sage: I = IdentityFunctor(abgrps) sage: I The identity functor on Category of commutative additive groups sage: I.domain() Category of commutative additive groups - sage: is_Functor(I) + sage: isinstance(I, Functor) True Note that by default, an instance of the class Functor is coercion @@ -422,12 +422,9 @@ cdef class Functor(SageObject): def is_Functor(x): """ - Test whether the argument is a functor - - NOTE: + Test whether the argument is a functor. - There is a deprecation warning when using it from top level. - Therefore we import it in our doc test. + This function is deprecated. EXAMPLES:: @@ -436,6 +433,10 @@ def is_Functor(x): sage: F1 FractionField sage: is_Functor(F1) + doctest:warning... + DeprecationWarning: The function is_Functor is deprecated; + use 'isinstance(..., Functor)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_Functor(FractionField) False @@ -446,6 +447,10 @@ def is_Functor(x): True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_Functor is deprecated; " + "use 'isinstance(..., Functor)' instead.") return isinstance(x, Functor) diff --git a/src/sage/categories/group_algebras.py b/src/sage/categories/group_algebras.py index 5c490a6a026..b0700b004de 100644 --- a/src/sage/categories/group_algebras.py +++ b/src/sage/categories/group_algebras.py @@ -129,7 +129,7 @@ def __init_extra__(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.combinat sage.groups sage.modules sage: A = GroupAlgebra(SymmetricGroup(4), QQ) sage: B = GroupAlgebra(SymmetricGroup(3), ZZ) sage: A.has_coerce_map_from(B) @@ -173,7 +173,7 @@ def group(self): sage: GroupAlgebras(QQ).example(GL(3, GF(11))).group() # needs sage.groups sage.modules General Linear Group of degree 3 over Finite Field of size 11 - sage: SymmetricGroup(10).algebra(QQ).group() # needs sage.groups sage.modules + sage: SymmetricGroup(10).algebra(QQ).group() # needs sage.combinat sage.groups sage.modules Symmetric group of order 10! as a permutation group """ return self.basis().keys() @@ -201,7 +201,7 @@ def center_basis(self): EXAMPLES:: - sage: SymmetricGroup(3).algebra(QQ).center_basis() # needs sage.groups sage.modules + sage: SymmetricGroup(3).algebra(QQ).center_basis() # needs sage.combinat sage.groups sage.modules ((), (2,3) + (1,2) + (1,3), (1,2,3) + (1,3,2)) .. SEEALSO:: @@ -319,12 +319,12 @@ def is_integral_domain(self, proof=True): sage: # needs sage.groups sage.modules sage: S2 = SymmetricGroup(2) - sage: GroupAlgebra(S2).is_integral_domain() + sage: GroupAlgebra(S2).is_integral_domain() # needs sage.combinat False sage: S1 = SymmetricGroup(1) - sage: GroupAlgebra(S1).is_integral_domain() + sage: GroupAlgebra(S1).is_integral_domain() # needs sage.combinat True - sage: GroupAlgebra(S1, IntegerModRing(4)).is_integral_domain() + sage: GroupAlgebra(S1, IntegerModRing(4)).is_integral_domain() # needs sage.combinat False sage: GroupAlgebra(AbelianGroup(1)).is_integral_domain() True @@ -400,7 +400,7 @@ def central_form(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.combinat sage.groups sage.modules sage: QS3 = SymmetricGroup(3).algebra(QQ) sage: A = QS3([2,3,1]) + QS3([3,1,2]) sage: A.central_form() diff --git a/src/sage/categories/groups.py b/src/sage/categories/groups.py index 2ed6590887a..ae0721c0a55 100644 --- a/src/sage/categories/groups.py +++ b/src/sage/categories/groups.py @@ -70,7 +70,7 @@ def free(index_set=None, names=None, **kwds): EXAMPLES:: - sage: # needs sage.groups + sage: # needs sage.combinat sage.groups sage: Groups.free(index_set=ZZ) Free group indexed by Integer Ring sage: Groups().free(ZZ) @@ -273,7 +273,7 @@ def cayley_table(self, names='letters', elements=None): :: sage: M = SL(2, 2) # needs sage.modules - sage: M.cayley_table() # needs sage.modules + sage: M.cayley_table() # needs sage.libs.gap sage.modules * a b c d e f +------------ a| a b c d e f @@ -477,8 +477,8 @@ def conjugacy_class(self): ) sage: G = SL(2, GF(2)) # needs sage.modules - sage: g = G.gens()[0] # needs sage.modules - sage: g.conjugacy_class() # needs sage.modules + sage: g = G.gens()[0] # needs sage.groups sage.modules + sage: g.conjugacy_class() # needs sage.groups sage.modules Conjugacy class of [1 1] [0 1] in Special Linear Group of degree 2 over Finite Field of size 2 @@ -515,7 +515,7 @@ def free(index_set=None, names=None, **kwds): EXAMPLES:: - sage: # needs sage.groups + sage: # needs sage.combinat sage.groups sage: Groups.Commutative.free(index_set=ZZ) Free abelian group indexed by Integer Ring sage: Groups().Commutative().free(ZZ) @@ -592,13 +592,13 @@ def group_generators(self): We check the other portion of :issue:`16718` is fixed:: - sage: len(C.j_classes()) # needs sage.groups + sage: len(C.j_classes()) # needs sage.graphs sage.groups 1 An example with an infinitely generated group (a better output is needed):: - sage: # needs sage.groups + sage: # needs sage.combinat sage.groups sage: G = Groups.free([1,2]) sage: H = Groups.free(ZZ) sage: C = cartesian_product([G, H]) @@ -631,17 +631,17 @@ def lift(i, gen): def order(self): r""" - Return the cardinality of self. + Return the cardinality of ``self``. EXAMPLES:: - sage: C = cartesian_product([SymmetricGroup(10), SL(2, GF(3))]) # needs sage.groups sage.rings.finite_rings - sage: C.order() # needs sage.groups sage.rings.finite_rings + sage: C = cartesian_product([SymmetricGroup(10), SL(2, GF(3))]) # needs sage.groups sage.modules + sage: C.order() # needs sage.groups sage.modules 87091200 TESTS:: - sage: C.order.__module__ # needs sage.groups sage.rings.finite_rings + sage: C.order.__module__ # needs sage.groups sage.modules 'sage.categories.groups' .. TODO:: diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 38f6364a9f0..23848497247 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -1867,7 +1867,7 @@ def merge(self, other): LaurentPolynomialFunctor sage: F1.merge(F2)(LaurentPolynomialRing(GF(2), 'a')) # needs sage.modules Multivariate Laurent Polynomial Ring in a, t over Finite Field of size 2 - sage: F1.merge(F1)(LaurentPolynomialRing(GF(2), 'a')) # needs sage.modules + sage: F1.merge(F1)(LaurentPolynomialRing(GF(2), 'a')) Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in a over Finite Field of size 2 @@ -3926,7 +3926,7 @@ def __init__(self, S, action=operator.mul, side='left', """ EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.combinat sage.groups sage.modules sage: G = SymmetricGroup(3); G.rename('S3') sage: M = FreeModule(ZZ, [1,2,3], prefix='M'); M.rename('M') sage: action = lambda g, x: M.term(g(x)) @@ -3976,14 +3976,20 @@ class BlackBoxConstructionFunctor(ConstructionFunctor): EXAMPLES:: sage: from sage.categories.pushout import BlackBoxConstructionFunctor + + sage: # needs sage.libs.gap + sage: from sage.interfaces.gap import gap sage: FG = BlackBoxConstructionFunctor(gap) - sage: FS = BlackBoxConstructionFunctor(singular) sage: FG BlackBoxConstructionFunctor - sage: FG(ZZ) # needs sage.libs.gap + sage: FG(ZZ) Integers - sage: FG(ZZ).parent() # needs sage.libs.gap + sage: FG(ZZ).parent() Gap + sage: FG == loads(dumps(FG)) + True + + sage: FS = BlackBoxConstructionFunctor(singular) sage: FS(QQ['t']) # needs sage.libs.singular polynomial ring, over a field, global ordering // coefficients: QQ @@ -3993,8 +3999,6 @@ class BlackBoxConstructionFunctor(ConstructionFunctor): // block 2 : ordering C sage: FG == FS # needs sage.libs.gap sage.libs.singular False - sage: FG == loads(dumps(FG)) # needs sage.libs.gap - True """ rank = 100 diff --git a/src/sage/categories/quantum_group_representations.py b/src/sage/categories/quantum_group_representations.py index 23755cc3aef..07dad6d28d6 100644 --- a/src/sage/categories/quantum_group_representations.py +++ b/src/sage/categories/quantum_group_representations.py @@ -53,7 +53,7 @@ def example(self): sage: from sage.categories.quantum_group_representations import QuantumGroupRepresentations sage: Cat = QuantumGroupRepresentations(ZZ['q'].fraction_field()) - sage: Cat.example() # needs sage.combinat sage.modules + sage: Cat.example() # needs sage.combinat sage.graphs sage.modules V((2, 1, 0)) """ from sage.algebras.quantum_groups.representations import AdjointRepresentation @@ -98,7 +98,7 @@ def e_on_basis(self, i, b): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() @@ -149,7 +149,7 @@ def f_on_basis(self, i, b): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() @@ -213,7 +213,7 @@ def K_on_basis(self, i, b, power=1): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() @@ -246,7 +246,7 @@ def tensor(*factors): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() @@ -285,7 +285,7 @@ def e(self, i): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation sage: C = crystals.Tableaux(['G',2], shape=[1,1]) sage: R = ZZ['q'].fraction_field() @@ -312,7 +312,7 @@ def f(self, i): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1) sage: R = ZZ['q'].fraction_field() @@ -346,7 +346,7 @@ def K(self, i, power=1): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation sage: K = crystals.KirillovReshetikhin(['D',4,2], 1,1) sage: R = ZZ['q'].fraction_field() @@ -397,7 +397,7 @@ def cartan_type(self): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation sage: C = crystals.Tableaux(['C',2], shape=[1]) sage: R = ZZ['q'].fraction_field() @@ -417,7 +417,7 @@ def _test_representation(self, tester=None, **options): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: C = crystals.Tableaux(['G',2], shape=[1,1]) @@ -428,8 +428,8 @@ def _test_representation(self, tester=None, **options): We verify that ``C`` does not define a minuscule representation:: - sage: M = MinusculeRepresentation(R, C) # needs sage.combinat sage.modules - sage: M._test_representation() # needs sage.combinat sage.modules + sage: M = MinusculeRepresentation(R, C) # needs sage.combinat sage.graphs sage.modules + sage: M._test_representation() # needs sage.combinat sage.graphs sage.modules Traceback (most recent call last): ... AssertionError: [e,f] = (K-K^-1)/(q_i-q_i^-1) -- i: 1 j: 1 @@ -500,7 +500,7 @@ def cartan_type(self): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation sage: C = crystals.Tableaux(['C',4], shape=[1]) sage: R = ZZ['q'].fraction_field() @@ -516,7 +516,7 @@ def index_set(self): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation sage: C = crystals.Tableaux(['C',4], shape=[1]) sage: R = ZZ['q'].fraction_field() @@ -532,7 +532,7 @@ def q(self): EXAMPLES:: - sage: # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation sage: C = crystals.Tableaux(['C',4], shape=[1]) sage: R = ZZ['q'].fraction_field() diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index 8699dcf8b43..51eb9b14453 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -137,6 +137,7 @@ class Sets(Category_singleton): + @@ -144,7 +145,7 @@ class Sets(Category_singleton): - <... 'object'> + We run some generic checks on P:: diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index e7d0a77fc0c..e714a4571c4 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -9,21 +9,20 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from sage.functions.generalized import sign -from sage.matrix.special import identity_matrix -from sage.misc.cachefunc import cached_method -from sage.misc.lazy_import import lazy_import from sage.categories.category_singleton import Category_singleton from sage.categories.category_with_axiom import CategoryWithAxiom -from sage.categories.sets_cat import Sets from sage.categories.homsets import HomsetsCategory -from sage.matrix.constructor import matrix +from sage.categories.sets_cat import Sets +from sage.functions.generalized import sign +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.rings.infinity import Infinity from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ lazy_import('sage.matrix.constructor', 'matrix') +lazy_import('sage.matrix.special', 'identity_matrix') class SimplicialSets(Category_singleton): @@ -362,10 +361,10 @@ def _universal_cover_dict(self): TESTS:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # needs sage.groups - sage: RP2._universal_cover_dict() # needs sage.groups + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # needs sage.graphs sage.groups + sage: RP2._universal_cover_dict() # needs sage.graphs sage.groups (Finitely presented group < e | e^2 >, {f: e}) - sage: RP2.nondegenerate_simplices() # needs sage.groups + sage: RP2.nondegenerate_simplices() # needs sage.graphs sage.groups [1, f, f * f] """ from sage.groups.free_group import FreeGroup @@ -407,14 +406,14 @@ def universal_cover_map(self): EXAMPLES:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # needs sage.groups - sage: phi = RP2.universal_cover_map(); phi # needs sage.groups + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # needs sage.graphs sage.groups + sage: phi = RP2.universal_cover_map(); phi # needs sage.graphs sage.groups Simplicial set morphism: From: Simplicial set with 6 non-degenerate simplices To: RP^2 Defn: [(1, 1), (1, e), (f, 1), (f, e), (f * f, 1), (f * f, e)] --> [1, 1, f, f, f * f, f * f] - sage: phi.domain().face_data() # needs sage.groups + sage: phi.domain().face_data() # needs sage.graphs sage.groups {(1, 1): None, (1, e): None, (f, 1): ((1, e), (1, 1)), @@ -563,7 +562,7 @@ def universal_cover(self): EXAMPLES:: - sage: # needs sage.groups + sage: # needs sage.graphs sage.groups sage: RP3 = simplicial_sets.RealProjectiveSpace(3) sage: C = RP3.universal_cover(); C Simplicial set with 8 non-degenerate simplices @@ -590,6 +589,7 @@ def _canonical_twisting_operator(self): EXAMPLES:: + sage: # needs sage.graphs sage: X = simplicial_sets.Torus() sage: d = X._canonical_twisting_operator() sage: d @@ -658,6 +658,7 @@ def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augment EXAMPLES:: + sage: # needs sage.graphs sage: W = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) sage: W.nondegenerate_simplices() [*, sigma_1, sigma_2] @@ -672,6 +673,7 @@ def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augment :: + sage: # needs sage.graphs sage: X = simplicial_sets.Torus() sage: C = X.twisted_chain_complex() sage: C.differential(1) @@ -685,6 +687,7 @@ def twisted_chain_complex(self, twisting_operator=None, dimensions=None, augment :: + sage: # needs sage.graphs sage: Y = simplicial_sets.RealProjectiveSpace(2) sage: C = Y.twisted_chain_complex() sage: C.differential(1) @@ -829,6 +832,7 @@ def twisted_homology(self, n, reduced=False): EXAMPLES:: + sage: # needs sage.graphs sage: X = simplicial_sets.Sphere(1).wedge(simplicial_sets.Sphere(2)) sage: X.twisted_homology(1) Quotient module by Submodule of Ambient free module of rank 0 over the integral domain Multivariate Polynomial Ring in f1, f1inv over Integer Ring @@ -841,6 +845,7 @@ def twisted_homology(self, n, reduced=False): :: + sage: # needs sage.graphs sage: Y = simplicial_sets.Torus() sage: Y.twisted_homology(1) Quotient module by Submodule of Ambient free module of rank 5 over the integral domain Multivariate Polynomial Ring in f2, f2inv, f3, f3inv over Integer Ring @@ -875,6 +880,7 @@ def twisted_homology(self, n, reduced=False): TESTS:: + sage: # needs sage.graphs sage: X = simplicial_sets.PresentationComplex(groups.presentation.FGAbelian((3,2))) sage: TW2 = X.twisted_homology(2, reduced=True) sage: M = TW2.relations_matrix() diff --git a/src/sage/categories/weyl_groups.py b/src/sage/categories/weyl_groups.py index a6578c4ec6a..aa2d4cd6f11 100644 --- a/src/sage/categories/weyl_groups.py +++ b/src/sage/categories/weyl_groups.py @@ -572,9 +572,10 @@ def stanley_symmetric_function(self): - [Pon2010]_ """ - import sage.combinat.sf from sage.rings.rational_field import QQ - m = sage.combinat.sf.sf.SymmetricFunctions(QQ).monomial() + from sage.combinat.sf.sf import SymmetricFunctions + + m = SymmetricFunctions(QQ).monomial() return m.from_polynomial_exp(self.stanley_symmetric_function_as_polynomial()) @cached_in_parent_method diff --git a/src/sage/combinat/SJT.py b/src/sage/combinat/SJT.py new file mode 100644 index 00000000000..03883eeb401 --- /dev/null +++ b/src/sage/combinat/SJT.py @@ -0,0 +1,246 @@ +r""" +The Steinhaus-Johnson-Trotter algorithm generates all permutations of a list in +an order such that each permutation is obtained by transposing two adjacent +elements from the previous permutation. + +Each element of the list has a direction (initialized at -1) that changes at +each permutation and that is used to determine which elements to transpose. Thus +in addition to the permutation itself, the direction of each element is also +stored. + +Note that the permutations are not generated in lexicographic order. + +AUTHORS: + +- Martin Grenouilloux (2024-05-22): initial version +""" + +# **************************************************************************** +# Copyright (C) 2024 Martin Grenouilloux +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** +from sage.combinat.combinat import CombinatorialElement + +class SJT(CombinatorialElement): + r""" + A representation of a list permuted using the Steinhaus-Johnson-Trotter + algorithm. + + Each element of the list has a direction (initialized at -1) that changes at + each permutation and that is used to determine which elements to transpose. + The directions have three possible values: + + - ``-1``: element tranposes to the left + + - ``1``: element transposes to the right + + - ``0``: element does not move + + Thus in addition to the permutation itself, the direction of each element is + also stored. + + Note that the permutations are not generated in lexicographic order. + + .. WARNING:: + + An ``SJT`` object should always be created with identity permutation for + the algorithm to behave properly. If the identity permutation is not + provided, it expects a coherent list of directions according to the + provided input. This list is not checked. + + .. TODO:: + + Implement the previous permutation for the Steinhaus-Johnson-Trotter + algorithm. + + EXAMPLES:: + + sage: from sage.combinat.SJT import SJT + sage: s = SJT([1, 2, 3, 4]); s + [1, 2, 3, 4] + sage: s = s.next(); s + [1, 2, 4, 3] + sage: p = Permutation(s._list, algorithm='sjt', sjt=s) + sage: p + [1, 2, 4, 3] + sage: p.next() + [1, 4, 2, 3] + + TESTS:: + + sage: from sage.combinat.SJT import SJT + sage: s = SJT([1, 2, 3, 4]); s + [1, 2, 3, 4] + sage: s = SJT([1]); s + [1] + sage: s = s.next(); s + False + sage: s = SJT([]); s + [] + sage: s = s.next(); s + False + """ + def __init__(self, l, directions=None) -> None: + r""" + Transpose two elements at positions ``a`` and ``b`` in ``perm`` and + their corresponding directions as well following the + Steinhaus-Johnson-Trotter algorithm. + + Each permutation is obtained by transposing two adjacent elements from + the previous permutation. + + INPUT: + + - ``l`` -- list; a list of ordered ``int``. + + - ``directions`` -- list (default: ``None``); a list of directions for + each element in the permuted list. Used when constructing permutations + from a pre-defined internal state. + + EXAMPLES:: + + sage: from sage.combinat.SJT import SJT + sage: s = SJT([1, 2, 3, 4]); s + [1, 2, 3, 4] + sage: s = s.next(); s + [1, 2, 4, 3] + sage: p = Permutation(s._list, algorithm='sjt', sjt=s) + sage: p + [1, 2, 4, 3] + sage: p.next() + [1, 4, 2, 3] + + TESTS:: + + sage: from sage.combinat.SJT import SJT + sage: s = SJT([1, 3, 2, 4]) + Traceback (most recent call last): + ... + ValueError: no internal state directions were given for non-identity + starting permutation for Steinhaus-Johnson-Trotter algorithm + sage: s = SJT([]); s + [] + sage: s = s.next(); s + False + """ + # The permuted list. + self._list = l + + # The length of the permuted list. Return early on empty list. + self._n = len(l) + if self._n == 0: + return + + if directions is None: + if not all(l[i] <= l[i+1] for i in range(self._n - 1)): + raise ValueError("no internal state directions were given for " + "non-identity starting permutation for " + "Steinhaus-Johnson-Trotter algorithm") + self._directions = [-1] * self._n + + # The first element has null direction. + self._directions[0] = 0 + else: + self._directions = directions + + def __idx_largest_element_non_zero_direction(self, perm, directions): + r""" + Find the largest element in ``perm`` with a non null direction. + """ + largest = 0 + index = None + for i in range(self._n): + if directions[i] != 0: + e = perm[i] + if e > largest: + index = i + largest = e + + return index + + def next(self): + r""" + Produce the next permutation of ``self`` following the + Steinhaus-Johnson-Trotter algorithm. + + OUTPUT: the list of the next permutation + + EXAMPLES:: + + sage: from sage.combinat.SJT import SJT + sage: s = SJT([1, 2, 3, 4]) + sage: s = s.next(); s + [1, 2, 4, 3] + sage: s = s.next(); s + [1, 4, 2, 3] + + TESTS:: + + sage: from sage.combinat.SJT import SJT + sage: s = SJT([1, 2, 3]) + sage: s.next() + [1, 3, 2] + + sage: s = SJT([1]) + sage: s.next() + False + """ + # Return on empty list. + if self._n == 0: + return False + + # Copying lists of permutation and directions to avoid changing internal + # state of the algorithm if ``next()`` is called without reassigning. + perm = self._list[:] + directions = self._directions[:] + + # Assume that the element to move is n (which will be in most cases). + selected_elt = self._n + xi = perm.index(selected_elt) + direction = directions[xi] + + # If this element has null direction, find the largest whose is + # non-null. + if direction == 0: + xi = self.__idx_largest_element_non_zero_direction(perm, directions) + if xi is None: + # We have created every permutation. Detected when all elements + # have null direction. + return False + direction = directions[xi] + selected_elt = perm[xi] + + new_pos = xi + direction + + # Proceed to transpose elements and corresponding directions. + perm[xi], perm[new_pos] = perm[new_pos], perm[xi] + directions[xi], directions[new_pos] = \ + directions[new_pos], directions[xi] + + # If the transposition results in the largest element being on one edge + # or if the following element in its direction is greater than it, then + # then set its direction to 0 + if new_pos == 0 or new_pos == self._n - 1 or \ + perm[new_pos + direction] > selected_elt: + directions[new_pos] = 0 + + # After each permutation, update each element's direction. If one + # element is greater than selected element, change its direction towards + # the selected element. This loops has no reason to be if selected + # element is n and this will be the case most of the time. + if selected_elt != self._n: + for i in range(self._n): + if perm[i] > selected_elt: + if i < new_pos: + directions[i] = 1 + if i > new_pos: + directions[i] = -1 + + return SJT(perm, directions) + + __next__ = next diff --git a/src/sage/combinat/finite_state_machine_generators.py b/src/sage/combinat/finite_state_machine_generators.py index 11cd2d1b3ab..ae708a195ca 100644 --- a/src/sage/combinat/finite_state_machine_generators.py +++ b/src/sage/combinat/finite_state_machine_generators.py @@ -268,8 +268,8 @@ def Word(self, word, input_alphabet=None): TESTS:: - sage: from sage.rings.integer import is_Integer - sage: all(is_Integer(s.label()) for s in A.states()) + sage: from sage.rings.integer import Integer + sage: all(isinstance(s.label(), Integer) for s in A.states()) True """ letters = list(word) diff --git a/src/sage/combinat/ncsf_qsym/all.py b/src/sage/combinat/ncsf_qsym/all.py index 5d61e9a9beb..9ea6d381f82 100644 --- a/src/sage/combinat/ncsf_qsym/all.py +++ b/src/sage/combinat/ncsf_qsym/all.py @@ -11,5 +11,10 @@ from sage.misc.namespace_package import install_doc install_doc(__package__, __doc__) -from sage.combinat.ncsf_qsym.qsym import QuasiSymmetricFunctions -from sage.combinat.ncsf_qsym.ncsf import NonCommutativeSymmetricFunctions +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.combinat.ncsf_qsym.qsym', 'QuasiSymmetricFunctions') +lazy_import('sage.combinat.ncsf_qsym.ncsf', 'NonCommutativeSymmetricFunctions') + +del install_doc +del lazy_import diff --git a/src/sage/combinat/ncsym/all.py b/src/sage/combinat/ncsym/all.py index cdeeec1ae41..864a6ac6960 100644 --- a/src/sage/combinat/ncsym/all.py +++ b/src/sage/combinat/ncsym/all.py @@ -11,5 +11,10 @@ from sage.misc.namespace_package import install_doc install_doc(__package__, __doc__) -from sage.combinat.ncsym.ncsym import SymmetricFunctionsNonCommutingVariables -from sage.combinat.ncsym.dual import SymmetricFunctionsNonCommutingVariablesDual +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.combinat.ncsym.ncsym', 'SymmetricFunctionsNonCommutingVariables') +lazy_import('sage.combinat.ncsym.dual', 'SymmetricFunctionsNonCommutingVariablesDual') + +del install_doc +del lazy_import diff --git a/src/sage/combinat/nu_tamari_lattice.py b/src/sage/combinat/nu_tamari_lattice.py index 56cfa020194..036de27126d 100644 --- a/src/sage/combinat/nu_tamari_lattice.py +++ b/src/sage/combinat/nu_tamari_lattice.py @@ -173,13 +173,13 @@ def delta_swap(p, k, delta): raise ValueError("the index is greater than the length of the path") # if delta is None: # delta = [len(_) for _ in str(p._nu).split(sep='1')[1:]] - if k == 0 or p[k-1] == 1: + if k == 0 or p[k - 1] == 1: raise ValueError("there is no such covering move") found = False i = p[:k].count(1) j = k alt = 0 - while not found and j <= p.length()-1: + while not found and j <= p.length() - 1: if p[j]: alt += delta[i] i += 1 @@ -188,9 +188,10 @@ def delta_swap(p, k, delta): if alt == 0: found = True j += 1 - q = p[:k-1] + p[k:j] + [p[k-1]] + p[j:] + q = p[:k - 1] + p[k:j] + [p[k - 1]] + p[j:] return NuDyckWord(q, p._nu) + def AltNuTamariLattice(nu, delta=None): r""" Return the `(\delta,\nu)`-Tamari lattice (or alt `\nu`-Tamari lattice). @@ -253,12 +254,12 @@ def AltNuTamariLattice(nu, delta=None): - [CC2023]_ """ - if not( (isinstance(nu, (list, tuple)) and all(x in [0, 1] for x in nu)) or - (isinstance(nu, str) and all(x in ['0', '1'] for x in nu)) ): + if not ((isinstance(nu, (list, tuple)) and all(x in [0, 1] for x in nu)) or + (isinstance(nu, str) and all(x in ['0', '1'] for x in nu))): raise ValueError("nu must be a list or a string of 0s and 1s") nu = [int(a) for a in nu] # transforms nu in a sequence of 0s and 1s if it is a list - nu = ''.join([str(a) for a in nu]) + nu = ''.join(str(a) for a in nu) # produces delta if delta is None, and check that delta is valid otherwise deltamax = [len(a) for a in nu.split(sep='1')[1:]] if delta is None: @@ -270,4 +271,4 @@ def covers(p): return [delta_swap(p, k, delta=delta) for k in range(1, p.length()) if not p[k - 1] and p[k]] return LatticePoset({p: covers(p) for p in NuDyckWords(nu)}, - check=False) \ No newline at end of file + check=False) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 3621b2d21ec..8f3222f804b 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -710,8 +710,8 @@ def _repr_exp_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ', '.join('{}{}'.format(m + 1, '' if e == 1 else '^%s' % e) - for (m,e) in enumerate(exp) if e > 0) + return ', '.join('{}{}'.format(m, '' if e == 1 else '^%s' % e) + for m, e in enumerate(exp, start=1) if e) def _repr_exp_high(self): """ @@ -731,7 +731,7 @@ def _repr_exp_high(self): exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) return ', '.join('{}{}'.format(M - m, '' if e == 1 else '^%s' % e) - for m, e in enumerate(exp) if e > 0) + for m, e in enumerate(exp) if e) def _repr_compact_low(self): """ @@ -748,8 +748,8 @@ def _repr_compact_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ','.join('{}{}'.format(m + 1, '' if e == 1 else '^%s' % e) - for (m,e) in enumerate(exp) if e > 0) + return ','.join('{}{}'.format(m, '' if e == 1 else '^%s' % e) + for m, e in enumerate(exp, start=1) if e) def _repr_compact_high(self): """ @@ -767,8 +767,8 @@ def _repr_compact_high(self): return '-' exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('{}{}'.format(M - m, '' if e == 1 else '^%s' % e) - for (m,e) in enumerate(exp) if e > 0) + return ','.join('{}{}'.format(M - m, '' if e == 1 else '^%s' % e) + for m, e in enumerate(exp) if e) def _repr_diagram(self): r""" @@ -793,7 +793,7 @@ def _repr_diagram(self): """ return self.ferrers_diagram() - def level(self): + def level(self) -> int: """ Return the level of ``self``, which is always 1. @@ -807,7 +807,7 @@ def level(self): """ return 1 - def components(self): + def components(self) -> list: """ Return a list containing the shape of ``self``. @@ -819,9 +819,9 @@ def components(self): sage: Partition([3,2]).components() [[3, 2]] """ - return [ self ] + return [self] - def _latex_(self): + def _latex_(self) -> str: r""" Return a LaTeX version of ``self``. @@ -870,7 +870,7 @@ def _latex_(self): """ return self.parent().options._dispatch(self, '_latex_', 'latex') - def _latex_young_diagram(self): + def _latex_young_diagram(self) -> str: r""" LaTeX output as a Young diagram. @@ -890,9 +890,10 @@ def _latex_young_diagram(self): return "{\\emptyset}" from sage.combinat.output import tex_from_array - return tex_from_array([ ["\\phantom{x}"]*row_size for row_size in self._list ]) + return tex_from_array([["\\phantom{x}"] * row_size + for row_size in self._list]) - def _latex_diagram(self): + def _latex_diagram(self) -> str: r""" LaTeX output as a Ferrers' diagram. @@ -913,9 +914,10 @@ def _latex_diagram(self): entry = self.parent().options("latex_diagram_str") from sage.combinat.output import tex_from_array - return tex_from_array([ [entry]*row_size for row_size in self._list ], False) + return tex_from_array([[entry] * row_size + for row_size in self._list], False) - def _latex_list(self): + def _latex_list(self) -> str: r""" LaTeX output as a list. @@ -928,7 +930,7 @@ def _latex_list(self): """ return repr(self._list) - def _latex_exp_low(self): + def _latex_exp_low(self) -> str: r""" LaTeX output in exponential notation (lowest first). @@ -943,7 +945,7 @@ def _latex_exp_low(self): return "{\\emptyset}" exp = self.to_exp() return '%s' % ','.join('{}{}'.format(m + 1, '' if e == 1 else '^{%s}' % e) - for (m,e) in enumerate(exp) if e > 0) + for (m, e) in enumerate(exp) if e > 0) def _latex_exp_high(self): r""" @@ -960,10 +962,10 @@ def _latex_exp_high(self): return "{\\emptyset}" exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('{}{}'.format(M - m, '' if e == 1 else '^{%s}' % e) - for (m,e) in enumerate(exp) if e > 0) + return ','.join('{}{}'.format(M - m, '' if e == 1 else '^{%s}' % e) + for m, e in enumerate(exp) if e) - def ferrers_diagram(self): + def ferrers_diagram(self) -> str: r""" Return the Ferrers diagram of ``self``. @@ -976,18 +978,18 @@ def ferrers_diagram(self): ***** ** * - sage: Partitions.options(diagram_str='#') + sage: Partitions.options(diagram_str='▉') sage: print(mu.ferrers_diagram()) - ##### - ##### - ## - # + ▉▉▉▉▉ + ▉▉▉▉▉ + ▉▉ + ▉ sage: Partitions.options.convention="french" sage: print(mu.ferrers_diagram()) - # - ## - ##### - ##### + ▉ + ▉▉ + ▉▉▉▉▉ + ▉▉▉▉▉ sage: print(Partition([]).ferrers_diagram()) - sage: Partitions.options(diagram_str='-') @@ -1000,10 +1002,9 @@ def ferrers_diagram(self): return '-' if diag_str != '-' else "(/)" if self.parent().options.convention == "English": return '\n'.join(diag_str * p for p in self) - else: - return '\n'.join(diag_str * p for p in reversed(self)) + return '\n'.join(diag_str * p for p in reversed(self)) - def pp(self): + def pp(self) -> None: r""" Print the Ferrers diagram. @@ -1102,8 +1103,8 @@ def power(self, k): """ res = [] for i in self: - g = gcd(i, k) - res.extend( [ZZ(i//g)]*int(g) ) + g = int(gcd(i, k)) + res.extend([i // g] * g) res.sort(reverse=True) return Partition(res) @@ -1128,16 +1129,16 @@ def __next__(self): next_p = p[:] + [1]*(n - len(p)) - #Check to see if we are at the last (all ones) partition - if p == [1]*n: + # Check to see if we are at the last (all ones) partition + if p == [1] * n: return False # - #If we are not, then run the ZS1 algorithm. + # If we are not, then run the ZS1 algorithm. # - #Let h be the number of non-one entries in the - #partition + # Let h be the number of non-one entries in the + # partition h = 0 for i in next_p: if i != 1: @@ -1251,7 +1252,7 @@ def sign(self): - :wikipedia:`Zolotarev%27s_lemma` """ - return (-1)**(self.size()-self.length()) + return (-1)**(self.size() - self.length()) def k_size(self, k): r""" @@ -1338,8 +1339,7 @@ def horizontal_piece(xy, bdy): stop_x = bdy[-1][0] y = start_y # y never changes h_piece = [(x, y) for x in range(start_x, stop_x)] - h_piece = list(reversed(h_piece)) - return h_piece + return list(reversed(h_piece)) bdy = [] for i, part in enumerate(self): (cell_x, cell_y) = (part - 1, i) @@ -1456,7 +1456,7 @@ def k_column_lengths(self, k): """ return self.k_boundary(k).column_lengths() - def has_rectangle(self, h, w): + def has_rectangle(self, h, w) -> bool: r""" Return ``True`` if the Ferrer's diagram of ``self`` has ``h`` (*or more*) rows of length ``w`` (*exactly*). @@ -1502,10 +1502,9 @@ def has_rectangle(self, h, w): """ assert h >= 1 assert w >= 1 - num_rows_of_len_w = self.to_exp(w)[w - 1] - return num_rows_of_len_w >= h + return self.to_exp(w)[w - 1] >= h - def has_k_rectangle(self, k): + def has_k_rectangle(self, k) -> bool: r""" Return ``True`` if the Ferrer's diagram of ``self`` contains `k-i+1` rows (*or more*) of length `i` (*exactly*) for any `i` in `[1, k]`. @@ -1552,10 +1551,10 @@ def has_k_rectangle(self, k): :meth:`is_k_irreducible`, :meth:`is_k_reducible`, :meth:`has_rectangle` """ - return any(self.has_rectangle(a, b) for (a, b) in - [(k-i+1, i) for i in range(1, k+1)]) + return any(self.has_rectangle(k - i + 1, i) + for i in range(1, k + 1)) - def is_k_bounded(self, k): + def is_k_bounded(self, k) -> bool: r""" Return ``True`` if the partition ``self`` is bounded by ``k``. @@ -1824,13 +1823,13 @@ def down(self): l = len(p) for i in range(l-1): if p[i] > p[i+1]: - yield Partition(p[:i] + [ p[i]-1 ] + p[i+1:]) + yield Partition(p[:i] + [p[i]-1] + p[i+1:]) if l >= 1: last = p[-1] if last == 1: yield Partition(p[:-1]) else: - yield Partition(p[:-1] + [ p[-1] - 1 ]) + yield Partition(p[:-1] + [p[-1] - 1]) def down_list(self): """ @@ -2073,7 +2072,7 @@ def frobenius_coordinates(self): else: b = [x for x in (val-i-1 for i, val in enumerate(muconj)) if x >= 0] a = [x for x in (mu[i]-i-1 for i in range(len(b))) if x >= 0] - return (a,b) + return (a, b) def frobenius_rank(self): r""" @@ -2149,9 +2148,9 @@ def beta_numbers(self, length=None): length = true_length elif length < true_length: raise ValueError("length must be at least the length of the partition") - beta = [l + length - i - 1 for (i, l) in enumerate(self)] + beta = [l + length - i for i, l in enumerate(self, start=1)] if length > true_length: - beta.extend(list(range(length-true_length-1,-1,-1))) + beta.extend(range(length - true_length - 1, -1, -1)) return beta def crank(self): @@ -2316,7 +2315,7 @@ def dominates(self, p2): sum2 = 0 min_length = min(len(p1), len(p2)) if min_length == 0: - return not p2 # equivalent to len(p1) >= len(p2) = 0 + return not p2 # equivalent to len(p1) >= len(p2) = 0 for i in range(min_length): sum1 += p1[i] @@ -2350,7 +2349,7 @@ def generalized_pochhammer_symbol(self, a, alpha): 12 """ res = 1 - for (i,j) in self.cells(): + for (i, j) in self.cells(): res *= (a - (i-1)/alpha + j-1) return res @@ -2698,11 +2697,11 @@ def suter_diagonal_slide(self, n, exp=1): ValueError: the hook length must be less than n """ # Check for valid input - if len(self) > 0 and len(self) + self._list[0] > n: # >, not >=, since we double count the (0,0) cell + if len(self) > 0 and len(self) + self._list[0] > n: # >, not >=, since we double count the (0,0) cell raise ValueError("the hook length must be less than n") ret = self # Arbitrary exp - exp = exp % n # It is at most order n + exp = exp % n # It is at most order n if exp > n / 2: exp -= n while exp != 0: @@ -2717,7 +2716,7 @@ def suter_diagonal_slide(self, n, exp=1): res += [1] * (n - leng - ret._list[0]) ret = Partition(res) exp -= 1 - else: # exp < 0 since if exp == 0, we would exit the while loop + else: # exp < 0 since if exp == 0, we would exit the while loop # inverse map \sigma_n^{-1} if leng == 0: # Taking extra care about the empty partition. ret = Partition([n - 1]) @@ -2852,13 +2851,13 @@ def garnir_tableau(self, *cell): raise ValueError('(row+1, col) must be inside the diagram') g = self.initial_tableau().to_list() a = g[row][col] - g[row][col:] = list(range(a+col+1,g[row+1][col]+1)) - g[row+1][:col+1] = list(range(a,a+col+1)) + g[row][col:] = list(range(a+col+1, g[row+1][col]+1)) + g[row+1][:col+1] = list(range(a, a+col+1)) g = tableau.Tableau(g) g._garnir_cell = (row, col) return g - def top_garnir_tableau(self,e,cell): + def top_garnir_tableau(self, e, cell): r""" Return the most dominant *standard* tableau which dominates the corresponding Garnir tableau and has the same ``e``-residue. @@ -2916,7 +2915,7 @@ def top_garnir_tableau(self,e,cell): - [KMR2012]_ """ - (row,col) = cell + (row, col) = cell if row+1 >= len(self) or col >= self[row+1]: raise ValueError(f'({row+1},{col})=(row+1,col) must be inside the diagram') @@ -3070,10 +3069,10 @@ 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 ) + gens.append(list(range(1, self.size() + 1))) # to ensure we get a subgroup of Sym_n + return PermutationGroup(gens) def young_subgroup_generators(self): r""" @@ -3097,7 +3096,7 @@ def young_subgroup_generators(self): gens = [] m = 0 for row in self: - gens.extend(list(range(m + 1, m + row))) + gens.extend(range(m + 1, m + row)) m += row return gens @@ -3459,7 +3458,7 @@ def dominated_partitions(self, rows=None): sage: Partition([3,2,1]).dominated_partitions(rows=3) [[3, 2, 1], [2, 2, 2]] """ - #Naive implementation because iteration is so fast + # Naive implementation because iteration is so fast n = sum(self) P = Partitions_n(n) if rows: @@ -3554,7 +3553,7 @@ def hook_length(self, i, j): sage: cell = [0,0]; Partition([3,3]).hook_length(*cell) 4 """ - return self.leg_length(i,j)+self.arm_length(i,j)+1 + return self.leg_length(i, j) + self.arm_length(i, j) + 1 def hooks(self): """ @@ -3995,7 +3994,7 @@ def block(self, e, multicharge=(0,)): """ block = {} Ie = IntegerModRing(e) - for (r,c) in self.cells(): + for (r, c) in self.cells(): i = Ie(multicharge[0] + c - r) block[i] = block.get(i, 0) + 1 return block @@ -4112,7 +4111,7 @@ def is_restricted(self, e, multicharge=(0,)): False """ return (not self - or ( self[-1] < e and all(self[r]-self[r+1] < e for r in range(len(self)-1)) )) + or (self[-1] < e and all(self[r] - self[r+1] < e for r in range(len(self) - 1)))) def is_regular(self, e, multicharge=(0,)) -> bool: """ @@ -4177,7 +4176,7 @@ def corners(self) -> list: if p.is_empty(): return [] - lcors = [[0,p[0]-1]] + lcors = [[0, p[0]-1]] nn = len(p) if nn == 1: return [tuple(c) for c in lcors] @@ -4187,7 +4186,7 @@ def corners(self) -> list: if p[i] == p[i-1]: lcors[lcors_index][0] += 1 else: - lcors.append([i,p[i]-1]) + lcors.append([i, p[i]-1]) lcors_index += 1 return [tuple(c) for c in lcors] @@ -4253,7 +4252,7 @@ def outside_corners(self): """ p = self._list if not p: - return [(0,0)] + return [(0, 0)] res = [(0, p[0])] res.extend((n, j) for n, (i, j) in enumerate(zip(p[:-1], p[1:]), start=1) if i != j) res.append((len(p), 0)) @@ -4445,25 +4444,25 @@ def core(self, length): [] """ p = self - #Normalize the length + # Normalize the length remainder = len(p) % length part = p[:] + [0]*remainder - #Add the canonical vector to the partition + # Add the canonical vector to the partition part = [part[i-1] + len(part)-i for i in range(1, len(part)+1)] for e in range(length): k = e - for i in reversed(range(1,len(part)+1)): + for i in reversed(range(1, len(part)+1)): if part[i-1] % length == e: part[i-1] = k k += length part.sort() part.reverse() - #Remove the canonical vector + # Remove the canonical vector part = [part[i-1]-len(part)+i for i in range(1, len(part)+1)] - #Select the r-core + # Select the r-core return Partition([x for x in part if x != 0]) def quotient(self, length): @@ -4511,15 +4510,15 @@ def quotient(self, length): True """ p = self - #Normalize the length + # Normalize the length remainder = len(p) % length part = p[:] + [0]*(length-remainder) - #Add the canonical vector to the partition + # Add the canonical vector to the partition part = [part[i-1] + len(part)-i for i in range(1, len(part)+1)] result = [None]*length - #Reducing vector + # Reducing vector for e in range(length): k = e tmp = [] @@ -4533,7 +4532,7 @@ def quotient(self, length): result[e] = a from .partition_tuple import PartitionTuple - return PartitionTuple(result) #tuple(map(Partition, result)) + return PartitionTuple(result) # tuple(map(Partition, result)) def is_core(self, k): r""" @@ -4632,7 +4631,7 @@ def add_cell(self, i, j=None): else: j = self[i] - if (i,j) in self.outside_corners(): + if (i, j) in self.outside_corners(): pl = self.to_list() if i == len(pl): pl.append(1) @@ -4668,13 +4667,13 @@ def remove_cell(self, i, j=None): if j is None: j = self[i] - 1 - if (i,j) not in self.corners(): - raise ValueError("[%d,%d] is not a corner of the partition" % (i,j)) + if (i, j) not in self.corners(): + raise ValueError("[%d,%d] is not a corner of the partition" % (i, j)) if self[i] == 1: return Partition(self[:-1]) else: - return Partition(self[:i] + [ self[i:i+1][0] - 1 ] + self[i+1:]) + return Partition(self[:i] + [self[i:i+1][0] - 1] + self[i+1:]) def k_irreducible(self, k): r""" @@ -4704,7 +4703,7 @@ def k_irreducible(self, k): [2, 1] """ pexp = self.to_exp() - return Partition(sum(([r+1] for r in range(len(pexp)-1,-1,-1) for m in range(pexp[r] % (k-r))),[])) + return Partition(sum(([r+1] for r in range(len(pexp)-1, -1, -1) for m in range(pexp[r] % (k-r))), [])) def k_skew(self, k): r""" @@ -4732,20 +4731,20 @@ def k_skew(self, k): """ if len(self) == 0: - return SkewPartition([[],[]]) + return SkewPartition([[], []]) if self[0] > k: raise ValueError(f"the partition must be {k}-bounded") - #Find the k-skew diagram of the partition formed - #by removing the first row + # Find the k-skew diagram of the partition formed + # by removing the first row s = Partition(self[1:]).k_skew(k) s_inner = list(s.inner()) s_outer = list(s.outer()) s_conj_rl = s.conjugate().row_lengths() - #Find the leftmost column with less than + # Find the leftmost column with less than # or equal to kdiff cells kdiff = k - self[0] @@ -4759,9 +4758,9 @@ def k_skew(self, k): spot = i break - outer = [ self[0] + spot ] + s_outer[:] + outer = [self[0] + spot] + s_outer[:] if spot > 0: - inner = [ spot ] + s_inner[:] + inner = [spot] + s_inner[:] else: inner = s_inner[:] @@ -4784,7 +4783,7 @@ def to_core(self, k): True """ from sage.combinat.core import Core - return Core(self.k_skew(k)[0],k+1) + return Core(self.k_skew(k)[0], k+1) def from_kbounded_to_reduced_word(self, k): r""" @@ -4815,9 +4814,9 @@ def from_kbounded_to_reduced_word(self, k): result = [] while not p.is_empty(): corners = p.corners() - c = p.content(corners[0][0],corners[0][1]) % (k+1) + c = p.content(corners[0][0], corners[0][1]) % (k+1) result.append(Integer(c)) - list = [x for x in corners if p.content(x[0],x[1]) % (k+1) == c] + list = [x for x in corners if p.content(x[0], x[1]) % (k+1) == c] for x in list: p = p.remove_cell(x[0]) return result @@ -4843,7 +4842,7 @@ def from_kbounded_to_grassmannian(self, k): [0 1 0] [0 0 1] """ - return WeylGroup(['A', k,1 ]).from_reduced_word(self.from_kbounded_to_reduced_word(k)) + return WeylGroup(['A', k, 1]).from_reduced_word(self.from_kbounded_to_reduced_word(k)) def to_list(self): r""" @@ -5070,7 +5069,7 @@ def horizontal_border_strip_cells(self, k): mapping.append(len(L)) shelf.append(L[-1]) - L.append(0) # add room on the bottom + L.append(0) # add room on the bottom # list all of the positions for cells # filling each self from the top to bottom for iv in IntegerListsBackend_invlex(k, length=len(shelf), ceiling=shelf, check=False)._iter(): @@ -5177,8 +5176,8 @@ def arms_legs_coeff(self, i, j): QQqt = PolynomialRing(QQ, ['q', 't']) (q, t) = QQqt.gens() if i < len(self) and j < self[i]: - res = (1-q**self.arm_length(i,j) * t**(self.leg_length(i,j)+1)) - res /= (1-q**(self.arm_length(i,j)+1) * t**self.leg_length(i,j)) + res = 1 - q**self.arm_length(i, j) * t**(self.leg_length(i, j)+1) + res /= 1 - q**(self.arm_length(i, j)+1) * t**self.leg_length(i, j) return res return ZZ.one() @@ -5288,7 +5287,7 @@ def jacobi_trudi(self): sage: jt.det() h[3, 2, 1] - h[3, 3] - h[4, 1, 1] + h[5, 1] """ - return SkewPartition([ self, [] ]).jacobi_trudi() + return SkewPartition([self, []]).jacobi_trudi() def character_polynomial(self): r""" @@ -5328,23 +5327,23 @@ def character_polynomial(self): P = PolynomialRing(QQ, k, 'x') x = P.gens() - #Expand s_mu in the power sum basis + # Expand s_mu in the power sum basis from sage.combinat.sf.sf import SymmetricFunctions Sym = SymmetricFunctions(QQ) s = Sym.schur() p = Sym.power() ps_mu = p(s(self)) - #Replace each p_i by i*x_i-1 - items = ps_mu.monomial_coefficients().items() #items contains a list of (partition, coeff) pairs - partition_to_monomial = lambda part: prod([ (i*x[i-1]-1) for i in part ]) - res = [ [partition_to_monomial(mc[0]), mc[1]] for mc in items ] + # Replace each p_i by i*x_i-1 + items = ps_mu.monomial_coefficients().items() # items contains a list of (partition, coeff) pairs + partition_to_monomial = lambda part: prod([i*x[i-1] - 1 for i in part]) + res = [[partition_to_monomial(mc[0]), mc[1]] for mc in items] - #Write things in the monomial basis - res = [ prod(pair) for pair in res ] - res = sum( res ) + # Write things in the monomial basis + res = [prod(pair) for pair in res] + res = sum(res) - #Apply the umbral operator and return the result + # Apply the umbral operator and return the result from sage.combinat.misc import umbral_operation return umbral_operation(res) @@ -5450,30 +5449,30 @@ def dimension(self, smaller=None, k=1): def inv_factorial(i): if i < 0: return 0 - else: - return 1/factorial(i) - len_range = list(range(larger.length())) + return 1/factorial(i) + + len_range = range(larger.length()) from sage.matrix.constructor import matrix - M = matrix(QQ,[[inv_factorial(larger.get_part(i)-smaller.get_part(j)-i+j) for i in len_range] for j in len_range]) + M = matrix(QQ, [[inv_factorial(larger.get_part(i)-smaller.get_part(j)-i+j) for i in len_range] for j in len_range]) return factorial(larger.size()-smaller.size())*M.determinant() else: larger_core = larger.core(k) smaller_core = smaller.core(k) - if smaller_core != larger_core: # easy case + if smaller_core != larger_core: # easy case return 0 larger_quotients = larger.quotient(k) smaller_quotients = smaller.quotient(k) - def multinomial_with_partitions(sizes,path_counts): - # count the number of ways of performing the k paths in parallel, - # if we know the total length allotted for each of the paths (sizes), and the number - # of paths for each component. A multinomial picks the ordering of the components where - # each step is taken. + def multinomial_with_partitions(sizes, path_counts): + # count the number of ways of performing the k paths in parallel, + # if we know the total length allotted for each of the paths (sizes), and the number + # of paths for each component. A multinomial picks the ordering of the components where + # each step is taken. return prod(path_counts) * multinomial(sizes) sizes = [larger_quotients[i].size()-smaller_quotients[i].size() for i in range(k)] path_counts = [larger_quotients[i].dimension(smaller_quotients[i]) for i in range(k)] - return multinomial_with_partitions(sizes,path_counts) + return multinomial_with_partitions(sizes, path_counts) def plancherel_measure(self): r""" @@ -5541,7 +5540,7 @@ def outline(self, variable=None): outside_contents = [self.content(*c) for c in self.outside_corners()] inside_contents = [self.content(*c) for c in self.corners()] return sum(abs(variable+c) for c in outside_contents)\ - - sum(abs(variable+c) for c in inside_contents) + - sum(abs(variable+c) for c in inside_contents) def dual_equivalence_graph(self, directed=False, coloring=None): r""" @@ -5829,6 +5828,7 @@ def tabloid_module(self, base_ring=None): R = SymmetricGroupAlgebra(base_ring, sum(self)) return TabloidModule(R, self) + ############## # Partitions # ############## @@ -6158,7 +6158,7 @@ def __classcall_private__(cls, n=None, **kwargs): """ if n == infinity: raise ValueError("n cannot be infinite") - if isinstance(n, (int,Integer)): + if isinstance(n, (int, Integer)): if len(kwargs) == 0: return Partitions_n(n) @@ -6187,7 +6187,7 @@ def __classcall_private__(cls, n=None, **kwargs): return RestrictedPartitions_n(n, kwargs['restricted']) # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute - kwargs['name'] = "Partitions of the integer {} satisfying constraints {}".format(n, ", ".join( ["{}={}".format(key, kwargs[key]) for key in sorted(kwargs)] )) + kwargs['name'] = "Partitions of the integer {} satisfying constraints {}".format(n, ", ".join(["{}={}".format(key, kwargs[key]) for key in sorted(kwargs)])) # min_part is at least 1, and it is 1 by default kwargs['min_part'] = max(1, kwargs.get('min_part', 1)) @@ -6209,7 +6209,7 @@ def __classcall_private__(cls, n=None, **kwargs): inner = [x for x in kwargs['inner'] if x > 0] kwargs['floor'] = inner kwargs['min_length'] = max(len(inner), - kwargs.get('min_length',0)) + kwargs.get('min_length', 0)) del kwargs['inner'] return Partitions_with_constraints(n, **kwargs) elif n is None or n is NN or n is NonNegativeIntegers(): @@ -6345,11 +6345,11 @@ class options(GlobalOptions): 'case_sensitive': False} diagram_str = {'default': "*", 'description': 'The character used for the cells when printing Ferrers diagrams', - 'checker': lambda char: isinstance(char,str)} + 'checker': lambda char: isinstance(char, str)} latex_diagram_str = {'default': "\\ast", 'description': 'The character used for the cells when latexing Ferrers diagrams', - 'checker': lambda char: isinstance(char,str)} - convention = {'link_to': (tableau.Tableaux.options,'convention')} + 'checker': lambda char: isinstance(char, str)} + convention = {'link_to': (tableau.Tableaux.options, 'convention')} notation = {'alt_name': 'convention'} def __reversed__(self): @@ -6690,7 +6690,7 @@ def from_zero_one(self, seq): True """ tmp = [i for i in range(len(seq)) if seq[i] == 0] - return self.element_class(self,[tmp[i]-i for i in range(len(tmp)-1,-1,-1)]) + return self.element_class(self, [tmp[i]-i for i in range(len(tmp)-1, -1, -1)]) def from_core_and_quotient(self, core, quotient): """ @@ -6737,15 +6737,15 @@ def from_core_and_quotient(self, core, quotient): length = len(components) k = length*max(len(q) for q in components) + len(core) # k needs to be large enough. this seems to me like the smallest it can be - v = [core[i]-i for i in range(len(core))] + [ -i for i in range(len(core),k) ] - w = [ [x for x in v if (x-i) % length == 0] for i in range(1, length+1) ] + v = [core[i]-i for i in range(len(core))] + [-i for i in range(len(core), k)] + w = [[x for x in v if (x-i) % length == 0] for i in range(1, length+1)] new_w = [] for i in range(length): lw = len(w[i]) lq = len(components[i]) # k needs to be chosen so lw >= lq - new_w += [ w[i][j] + length*components[i][j] for j in range(lq)] - new_w += [ w[i][j] for j in range(lq,lw)] + new_w += [w[i][j] + length*components[i][j] for j in range(lq)] + new_w += [w[i][j] for j in range(lq, lw)] new_w.sort(reverse=True) return self.element_class(self, [new_w[i]+i for i in range(len(new_w))]) @@ -6849,7 +6849,7 @@ def __contains__(self, x): """ return x in _Partitions and sum(x) == self.n - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation of ``self``. @@ -6878,7 +6878,7 @@ def _an_element_(self): elif self.n == 1: lst = [1] else: - lst = [self.n-1, 1] + lst = [self.n - 1, 1] return self.element_class(self, lst) def cardinality(self, algorithm='flint'): @@ -7047,7 +7047,7 @@ def random_element_uniform(self): - Florent Hivert (2009-11-23) """ n = self.n - res = [] # A dictionary of multiplicities could be faster. + res = [] # A dictionary of multiplicities could be faster. while n > 0: # Choose a pair d,j = 1,2..., with d*j <= n with probability # d*numpart(n-d*j) / n / numpart(n) @@ -7858,7 +7858,7 @@ def first(self): mu = list(self._starting) + [1] * (self.n - k) return next(Partition(mu)) - #if self._starting.size() > self.n: + # if self._starting.size() > self.n: return self.element_class(self, Partitions(self.n, outer=self._starting).first()) def next(self, part): @@ -8044,7 +8044,7 @@ def __contains__(self, x): True """ return x in _Partitions and len(x) <= self.h \ - and (len(x) == 0 or x[0] <= self.w) + and (len(x) == 0 or x[0] <= self.w) def list(self): """ @@ -9444,14 +9444,14 @@ def number_of_partitions_length(n, k, algorithm='hybrid'): ########## -# trac 14225: Partitions() is frequently used, but only weakly cached. Hence, -# establish a strong reference to it. +# issue 14225: Partitions() is frequently used, but only weakly cached. +# Hence, establish a strong reference to it. _Partitions = Partitions() # Rather than caching an under-used function I have cached the default # number_of_partitions functions which is currently using FLINT. -# AM trac #13072 +# AM issue #13072 try: from sage.libs.flint.arith_sage import number_of_partitions as flint_number_of_partitions cached_number_of_partitions = cached_function(flint_number_of_partitions) diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 4f0cd8e97df..1ca90eff943 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -250,6 +250,7 @@ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.sets_with_grading import SetsWithGrading from sage.combinat.backtrack import GenericBacktracker +from sage.combinat.SJT import SJT from sage.combinat.combinat import CombinatorialElement, catalan_number from sage.combinat.combinatorial_map import combinatorial_map from sage.combinat.composition import Composition @@ -308,9 +309,22 @@ class Permutation(CombinatorialElement): the permutation obtained from the pair using the inverse of the Robinson-Schensted algorithm. - - ``check`` (boolean) -- whether to check that input is correct. Slows - the function down, but ensures that nothing bad happens. This is set to - ``True`` by default. + - ``check`` -- boolean (default: ``True``); whether to check that input is + correct. Slows the function down, but ensures that nothing bad happens. + This is set to ``True`` by default. + + - ``algorithm`` -- string (default: ``lex``); the algorithm used to generate + the permutations. Supported algorithms are: + + - ``lex``: lexicographic order generation, this is the default algorithm. + + - ``sjt``: Steinhaus-Johnson-Trotter algorithm to generate permutations + using only transposition of two elements in the list. It is highly + recommended to set ``check=True`` (default value). + + - ``sjt`` -- SJT (default: ``None``); the ``SJT`` object holding the + permutation internal state. This should only be specified when + initializing with non-identity permutation. .. WARNING:: @@ -378,6 +392,27 @@ class Permutation(CombinatorialElement): sage: type(p) + Generate permutations using the Steinhaus-Johnson Trotter algorithm. The + output is not in lexicographic order:: + + sage: p = Permutation([1, 2, 3, 4], algorithm='sjt'); p + [1, 2, 3, 4] + sage: p = p.next(); p + [1, 2, 4, 3] + sage: p = p.next(); p + [1, 4, 2, 3] + sage: p = Permutation([1, 2, 3], algorithm='sjt') + sage: for _ in range(6): + ....: p = p.next() + sage: p + False + + sage: Permutation([1, 3, 2, 4], algorithm='sjt') + Traceback (most recent call last): + ... + ValueError: no internal state directions were given for non-identity + starting permutation for Steinhaus-Johnson-Trotter algorithm + Construction from a string in cycle notation:: sage: p = Permutation( '(4,5)' ); p @@ -427,6 +462,11 @@ class Permutation(CombinatorialElement): sage: Permutation( [1] ) [1] + sage: Permutation([1, 2, 3, 4], algorithm='blah') + Traceback (most recent call last): + ... + ValueError: unsupported algorithm blah; expected 'lex' or 'sjt' + From a pair of empty tableaux :: sage: Permutation( ([], []) ) # needs sage.combinat @@ -436,7 +476,7 @@ class Permutation(CombinatorialElement): """ @staticmethod @rename_keyword(deprecation=35233, check_input='check') - def __classcall_private__(cls, l, check=True): + def __classcall_private__(cls, l, algorithm='lex', sjt=None, check=True): """ Return a permutation in the general permutations parent. @@ -487,10 +527,10 @@ def __classcall_private__(cls, l, check=True): raise ValueError("cannot convert l (= %s) to a Permutation" % l) # otherwise, it gets processed by CombinatorialElement's __init__. - return Permutations()(l, check=check) + return Permutations()(l, algorithm, sjt, check) @rename_keyword(deprecation=35233, check_input='check') - def __init__(self, parent, l, check=True): + def __init__(self, parent, l, algorithm='lex', sjt=None, check=True): """ Constructor. Checks that INPUT is not a mess, and calls :class:`CombinatorialElement`. It should not, because @@ -500,11 +540,23 @@ def __init__(self, parent, l, check=True): - ``l`` -- a list of ``int`` variables - - ``check`` (boolean) -- whether to check that input is - correct. Slows the function down, but ensures that nothing bad + - ``check`` -- boolean (default: ``True``); whether to check that input + is correct. Slows the function down, but ensures that nothing bad happens. - This is set to ``True`` by default. + - ``algorithm`` -- string (default: ``lex``); the algorithm used to + generate the permutations. Supported algorithms are: + + - ``lex``: lexicographic order generation, this is the default + algorithm. + + - ``sjt``: Steinhaus-Johnson-Trotter algorithm to generate + permutations using only transposition of two elements in the list. + It is highly recommended to set ``check=True`` (default value). + + - ``sjt`` -- SJT (default: ``None``); the ``SJT`` object holding the + permutation internal state. This should only be specified when + initializing with non-identity permutation. TESTS:: @@ -521,12 +573,30 @@ def __init__(self, parent, l, check=True): sage: Permutation([1,2,4,5]) Traceback (most recent call last): ... - ValueError: The permutation has length 4 but its maximal element is + ValueError: the permutation has length 4 but its maximal element is 5. Some element may be repeated, or an element is missing, but there is something wrong with its length. + + sage: Permutation([1, 3, 2], algorithm='sjt') + Traceback (most recent call last): + ... + ValueError: no internal state directions were given for non-identity + starting permutation for Steinhaus-Johnson-Trotter algorithm + + sage: Permutation([1, 3, 2], algorithm='sjt', check=False) + Traceback (most recent call last): + ... + ValueError: no internal state directions were given for non-identity + starting permutation for Steinhaus-Johnson-Trotter algorithm """ l = list(l) + self._algorithm = algorithm.lower() + + if self._algorithm != "lex" and self._algorithm != "sjt": + raise ValueError("unsupported algorithm %s; expected 'lex' or 'sjt'" + % self._algorithm) + if check and len(l) > 0: # Make a copy to sort later lst = list(l) @@ -538,18 +608,19 @@ def __init__(self, parent, l, check=True): except TypeError: raise ValueError("the elements must be integer variables") if i < 1: - raise ValueError("the elements must be strictly positive integers") + raise ValueError("the elements must be strictly positive " + "integers") lst.sort() # Is the maximum element of the permutation the length of input, # or is some integer missing ? if int(lst[-1]) != len(lst): - raise ValueError("The permutation has length "+str(len(lst)) + + raise ValueError("the permutation has length "+str(len(lst)) + " but its maximal element is " + - str(int(lst[-1]))+". Some element " + - "may be repeated, or an element is missing" + - ", but there is something wrong with its length.") + str(int(lst[-1])) + ". Some element may be " + + "repeated, or an element is missing, but " + + "there is something wrong with its length.") # Do the elements appear only once ? previous = lst[0]-1 @@ -559,6 +630,9 @@ def __init__(self, parent, l, check=True): raise ValueError("an element appears twice in the input") previous = i + if self._algorithm == "sjt": + self._sjt = SJT(l) if sjt is None else sjt + CombinatorialElement.__init__(self, parent, l) def __setstate__(self, state): @@ -761,9 +835,18 @@ def cycle_string(self, singletons=False) -> str: def __next__(self): r""" - Return the permutation that follows ``self`` in lexicographic order on - the symmetric group containing ``self``. If ``self`` is the last - permutation, then ``next`` returns ``False``. + Return the permutation that follows ``self`` on the symmetric group + containing ``self``. If ``self`` is the last permutation, then ``next`` + returns ``False``. If the ``algorithm`` parameter is specified, the + permutations will be generated according to it. Supported algorithms + are: + + - ``lex``: lexicographic order generation, this is the default + algorithm. + + - ``sjt``: Steinhaus-Johnson-Trotter algorithm to generate + permutations using only transposition of two elements in the list. + It is highly recommended to set ``check=True`` (default value). EXAMPLES:: @@ -773,13 +856,41 @@ def __next__(self): sage: p = Permutation([4,3,2,1]) sage: next(p) False + sage: p = Permutation([1, 2, 3], algorithm='sjt') + sage: p = next(p); p + [1, 3, 2] + sage: p = next(p); p + [3, 1, 2] TESTS:: sage: p = Permutation([]) sage: next(p) False + sage: p = Permutation([], algorithm='sjt') + sage: next(p) + False + sage: p = Permutation([1], algorithm='sjt') + sage: next(p) + False + sage: l = [1, 2, 3, 4] + sage: s = set() + sage: p = Permutation(l, algorithm='sjt') + sage: for _ in range(factorial(len(l))): + ....: s.add(p) + ....: p = p.next() + sage: p + False + sage: assert(len(s)) == factorial(len(l)) """ + if self._algorithm == "sjt": + # Ensure the same permutation is yielded when called multiple times + # without reassigning + sjt = self._sjt.next() + if sjt is False: + return False + return Permutations()(sjt._list, algorithm='sjt', sjt=sjt) + p = self[:] n = len(self) first = -1 @@ -818,6 +929,7 @@ def prev(self): Return the permutation that comes directly before ``self`` in lexicographic order on the symmetric group containing ``self``. If ``self`` is the first permutation, then it returns ``False``. + Does not support the Steinhaus-Johnson-Trotter algorithm for the moment. EXAMPLES:: @@ -834,11 +946,26 @@ def prev(self): sage: p.prev() False + sage: p = Permutation([1,2,3], algorithm='sjt') + sage: p.prev() + Traceback (most recent call last): + ... + NotImplementedError: previous permutation for SJT algorithm is not + yet implemented + Check that :issue:`16913` is fixed:: sage: Permutation([1,4,3,2]).prev() [1, 4, 2, 3] + + .. TODO:: + + Implement the previous permutation for the Steinhaus-Johnson-Trotter + algorithm. """ + if self._algorithm == "sjt": + raise NotImplementedError("previous permutation for SJT algorithm " + "is not yet implemented") p = self[:] n = len(self) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index f56f3f2d3b4..9c5689bcb81 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -3615,7 +3615,7 @@ def adjunct(self, other, a, b): sage: PP.atoms() [(0, 1), (0, 2), (1, 'a')] sage: PP.coatoms() - [(0, 3), (0, 1)] + [(0, 1), (0, 3)] TESTS:: diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 9fdbf6855de..f462becaa17 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -6551,7 +6551,7 @@ def random_maximal_chain(self): sage: set_random_seed(0) # results are reproduceable sage: P = posets.BooleanLattice(4) sage: P.random_maximal_chain() - [0, 2, 10, 11, 15] + [0, 4, 5, 7, 15] TESTS:: @@ -6618,7 +6618,7 @@ def random_linear_extension(self): sage: set_random_seed(0) # results are reproduceable sage: P = posets.BooleanLattice(4) sage: P.random_linear_extension() - [0, 2, 8, 1, 9, 4, 5, 10, 6, 12, 14, 13, 3, 7, 11, 15] + [0, 4, 1, 2, 3, 8, 10, 5, 12, 9, 13, 11, 6, 14, 7, 15] TESTS:: diff --git a/src/sage/combinat/root_system/all.py b/src/sage/combinat/root_system/all.py index 9c50eb57af1..bb55e491b44 100644 --- a/src/sage/combinat/root_system/all.py +++ b/src/sage/combinat/root_system/all.py @@ -122,9 +122,9 @@ from sage.misc.lazy_import import lazy_import from sage.combinat.root_system.cartan_type import CartanType -from sage.combinat.root_system.dynkin_diagram import DynkinDiagram -from sage.combinat.root_system.cartan_matrix import CartanMatrix -from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix +lazy_import('sage.combinat.root_system.dynkin_diagram', 'DynkinDiagram') +lazy_import('sage.combinat.root_system.cartan_matrix', 'CartanMatrix') +lazy_import('sage.combinat.root_system.coxeter_matrix', 'CoxeterMatrix') from sage.combinat.root_system.coxeter_type import CoxeterType from sage.combinat.root_system.root_system import RootSystem, WeylDim lazy_import('sage.combinat.root_system.weyl_group', ['WeylGroup', @@ -138,5 +138,9 @@ 'WeightRing']) from sage.combinat.root_system.branching_rules import BranchingRule, branching_rule_from_plethysm, branching_rule -lazy_import('sage.combinat.root_system.non_symmetric_macdonald_polynomials', 'NonSymmetricMacdonaldPolynomials') -lazy_import('sage.combinat.root_system.integrable_representations', 'IntegrableRepresentation') +lazy_import('sage.combinat.root_system.non_symmetric_macdonald_polynomials', + 'NonSymmetricMacdonaldPolynomials') +lazy_import('sage.combinat.root_system.integrable_representations', + 'IntegrableRepresentation') +del lazy_import +del install_doc diff --git a/src/sage/combinat/sf/jack.py b/src/sage/combinat/sf/jack.py index 8c62cfb08df..e70959f8dfc 100644 --- a/src/sage/combinat/sf/jack.py +++ b/src/sage/combinat/sf/jack.py @@ -36,7 +36,7 @@ from sage.rings.rational_field import QQ from sage.arith.misc import gcd from sage.arith.functions import lcm -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.misc.misc_c import prod from sage.categories.morphism import SetMorphism from sage.categories.homset import Hom, End @@ -481,7 +481,7 @@ def normalize_coefficients(self, c): 6/(t^2 + 3*t + 2) """ BR = self.base_ring() - if is_FractionField(BR) and BR.base_ring() == QQ: + if isinstance(BR, FractionField_generic) and BR.base_ring() == QQ: denom = c.denominator() numer = c.numerator() diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index ab61f4f37f7..99ef16b740d 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -50,6 +50,7 @@ from sage.misc.persist import register_unpickle_override lazy_import('sage.matrix.special', 'zero_matrix') +lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup') class SkewTableau(ClonableList, @@ -1139,6 +1140,81 @@ def to_list(self): """ return [list(row) for row in self] + def row_stabilizer(self): + """ + Return the :func:`PermutationGroup` corresponding to the row stabilizer of + ``self``. + + This assumes that every integer from `1` to the size of ``self`` + appears exactly once in ``self``. + + EXAMPLES:: + + sage: # needs sage.groups + sage: rs = SkewTableau([[None,1,2,3],[4,5]]).row_stabilizer() + sage: rs.order() == factorial(3) * factorial(2) + True + sage: PermutationGroupElement([(1,3,2),(4,5)]) in rs + True + sage: PermutationGroupElement([(1,4)]) in rs + False + sage: rs = SkewTableau([[None,1,2],[3]]).row_stabilizer() + sage: PermutationGroupElement([(1,2),(3,)]) in rs + True + sage: rs.one().domain() + [1, 2, 3] + sage: rs = SkewTableau([[None,None,1],[None,2],[3]]).row_stabilizer() + sage: rs.order() + 1 + sage: rs = SkewTableau([[None,None,2,4,5],[1,3]]).row_stabilizer() + sage: rs.order() + 12 + sage: rs = SkewTableau([]).row_stabilizer() + sage: rs.order() + 1 + """ + # Ensure that the permutations involve all elements of the + # tableau, by including the identity permutation on the set [1..k]. + k = self.size() + gens = [list(range(1, k + 1))] + for row in self: + for j in range(len(row) - 1): + if row[j] is not None: + gens.append((row[j], row[j + 1])) + return PermutationGroup(gens) + + def column_stabilizer(self): + """ + Return the :func:`PermutationGroup` corresponding to the column stabilizer + of ``self``. + + This assumes that every integer from `1` to the size of ``self`` + appears exactly once in ``self``. + + EXAMPLES:: + + sage: # needs sage.groups + sage: cs = SkewTableau([[None,2,3],[1,5],[4]]).column_stabilizer() + sage: cs.order() == factorial(2) * factorial(2) + True + sage: PermutationGroupElement([(1,3,2),(4,5)]) in cs + False + sage: PermutationGroupElement([(1,4)]) in cs + True + """ + # Ensure that the permutations involve all elements of the + # tableau, by including the identity permutation on the set [1..k]. + k = self.size() + gens = [list(range(1, k + 1))] + ell = len(self) + while ell > 1: + ell -= 1 + for i, val in enumerate(self[ell]): + top_neighbor = self[ell-1][i] + if top_neighbor is not None: + gens.append((val, top_neighbor)) + return PermutationGroup(gens) + def shuffle(self, t2): r""" Shuffle the standard tableaux ``self`` and ``t2``. diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index a0c6dad9172..5b8462754ef 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -850,6 +850,102 @@ def simple_module(self): return self return SimpleModule(self) + def intrinsic_arrangement(self, base_ring=None): + r""" + Return the intrinsic arrangement of ``self``. + + Consider the Specht module `S^{\lambda}` with `\lambda` a + (integer) partition of `n` (i.e., `S^{\lambda}` is an `S_n`-module). + The *intrinsic arrangement* of `S^{\lambda}` is the central hyperplane + arrangement in `S^{\lambda}` given by the hyperplanes `H_{\alpha}`, + indexed by a set partition `\alpha` of `\{1, \ldots, n\}` of size + `\lambda`, defined by + + .. MATH:: + + H_{\alpha} := \bigoplus_{\tau \in T_{\alpha}} (S^{\lambda})^{\tau}, + + where `T_{\alpha}` is some set of generating transpositions + of the Young subgroup `S_{\alpha}` and `V^{\tau}` denotes the + `\tau`-invariant subspace of `V`. (These hyperplanes do not + depend on the choice of `T_{\alpha}`.) + + This was introduced in [TVY2020]_ as a generalization of the + braid arrangement, which is the case when `\lambda = (n-1, 1)` + (equivalently, for the irreducible representation of `S_n` + given by the type `A_{n-1}` root system). + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(QQ, 4) + sage: SM = SGA.specht_module([2, 1, 1]) + sage: A = SM.intrinsic_arrangement() + sage: A.hyperplanes() + (Hyperplane T0 - T1 - 3*T2 + 0, + Hyperplane T0 - T1 + T2 + 0, + Hyperplane T0 + 3*T1 + T2 + 0, + Hyperplane 3*T0 + T1 - T2 + 0) + sage: A.is_free() + False + + We reproduce Example 3 of [TVY2020]_:: + + sage: SGA = SymmetricGroupAlgebra(QQ, 5) + sage: for la in Partitions(5): + ....: SM = SGA.specht_module(la) + ....: A = SM.intrinsic_arrangement() + ....: print(la, A.characteristic_polynomial()) + [5] 1 + [4, 1] x^4 - 10*x^3 + 35*x^2 - 50*x + 24 + [3, 2] x^5 - 15*x^4 + 90*x^3 - 260*x^2 + 350*x - 166 + [3, 1, 1] x^6 - 10*x^5 + 45*x^4 - 115*x^3 + 175*x^2 - 147*x + 51 + [2, 2, 1] x^5 - 10*x^4 + 45*x^3 - 105*x^2 + 120*x - 51 + [2, 1, 1, 1] x^4 - 5*x^3 + 10*x^2 - 10*x + 4 + [1, 1, 1, 1, 1] 1 + + sage: A = SGA.specht_module([4, 1]).intrinsic_arrangement() + sage: A.characteristic_polynomial().factor() + (x - 4) * (x - 3) * (x - 2) * (x - 1) + """ + from sage.geometry.hyperplane_arrangement.arrangement import HyperplaneArrangements + from sage.combinat.set_partition import SetPartitions + if base_ring is None: + base_ring = self.base_ring() + + if self.dimension() == 1: # corner case + HA = HyperplaneArrangements(base_ring, 'T') + return HA() + + SGA = self._semigroup_algebra + G = self._semigroup + + def t(i, j): + ret = [i for i in range(1, SGA.n+1)] + ret[i-1] = j + ret[j-1] = i + return SGA(G(ret)) + + # Construct the hyperplanes + fixed_spaces = {} + norms = [] + for alpha in SetPartitions(SGA.n, self._diagram.conjugate()): + span = [] + for a in alpha: + a = list(a) + for i in range(len(a)-1): + elt = t(a[i], a[i+1]) + if elt not in fixed_spaces: + fixed_spaces[elt] = self.annihilator_basis([elt - SGA.one()], side='left') + span.extend(fixed_spaces[elt]) + H = self.echelon_form(span) + N = matrix([v.to_vector() for v in H]).right_kernel_matrix() + assert N.nrows() == 1 + norms.append(N[0]) + + # Convert the data to an arrangement + HA = HyperplaneArrangements(base_ring, tuple([f'T{i}' for i in range(self.dimension())])) + return HA([[0] + list(N) for N in norms]) + class MaximalSpechtSubmodule(SymmetricGroupRepresentation, SubmoduleWithBasis): r""" diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 963dc8a221b..1706f848f10 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -18,6 +18,7 @@ from sage.combinat.permutation_cython import (left_action_same_n, right_action_same_n) from sage.combinat.partition import _Partitions, Partitions, Partitions_n from sage.combinat.tableau import Tableau, StandardTableaux_size, StandardTableaux_shape, StandardTableaux +from sage.combinat.skew_tableau import SkewTableau from sage.algebras.group_algebra import GroupAlgebra_class from sage.algebras.cellular_basis import CellularBasis from sage.categories.weyl_groups import WeylGroups @@ -139,7 +140,7 @@ def SymmetricGroupAlgebra(R, W, category=None): This allows for mixed expressions:: - sage: x4 = 3*QS4([3, 1, 4, 2]) + sage: x4 = 3 * QS4([3, 1, 4, 2]) sage: x3 + x4 2*[2, 3, 1, 4] + [3, 1, 2, 4] + 3*[3, 1, 4, 2] @@ -2367,6 +2368,72 @@ def _row_stabilizer(self, la): G = self.group() return self.sum_of_monomials(G(list(w.tuple())) for w in la.young_subgroup()) + @cached_method + def _column_antistabilizer(self, la): + """ + Return the column antistabilizer element of a canonical standard tableau + of shape ``la``. + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(QQ, 3) + sage: for la in Partitions(3): + ....: print(la, SGA._column_antistabilizer(la)) + [3] [1, 2, 3] + [2, 1] [1, 2, 3] - [3, 2, 1] + [1, 1, 1] [1, 2, 3] - [1, 3, 2] - [2, 1, 3] + [2, 3, 1] + [3, 1, 2] - [3, 2, 1] + """ + T = [] + total = 1 # make it 1-based + for r in la: + T.append(list(range(total, total+r))) + total += r + T = Tableau(T) + G = self.group() + R = self.base_ring() + return self._from_dict({G(list(w.tuple())): R(w.sign()) for w in T.column_stabilizer()}, + remove_zeros=False) + + @cached_method + def _young_symmetrizer(self, la): + """ + Return the Young symmetrizer of shape ``la`` of ``self``. + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(QQ, 3) + sage: for la in Partitions(3): + ....: print(la, SGA._young_symmetrizer(la)) + [3] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1] + [2, 1] [1, 2, 3] + [2, 1, 3] - [3, 1, 2] - [3, 2, 1] + [1, 1, 1] [1, 2, 3] - [1, 3, 2] - [2, 1, 3] + [2, 3, 1] + [3, 1, 2] - [3, 2, 1] + """ + return self._column_antistabilizer(la) * self._row_stabilizer(la) + + def young_symmetrizer(self, la): + """ + Return the Young symmetrizer of shape ``la`` of ``self``. + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(3)) + sage: SGA.young_symmetrizer([2,1]) + () + (1,2) - (1,3,2) - (1,3) + sage: SGA = SymmetricGroupAlgebra(QQ, 4) + sage: SGA.young_symmetrizer([2,1,1]) + [1, 2, 3, 4] - [1, 2, 4, 3] + [2, 1, 3, 4] - [2, 1, 4, 3] + - [3, 1, 2, 4] + [3, 1, 4, 2] - [3, 2, 1, 4] + [3, 2, 4, 1] + + [4, 1, 2, 3] - [4, 1, 3, 2] + [4, 2, 1, 3] - [4, 2, 3, 1] + sage: SGA.young_symmetrizer([5,1,1]) + Traceback (most recent call last): + ... + ValueError: the partition [5, 1, 1] is not of size 4 + """ + la = _Partitions(la) + if la.size() != self.n: + raise ValueError("the partition {} is not of size {}".format(la, self.n)) + return self._young_symmetrizer(la) + def kazhdan_lusztig_cellular_basis(self): r""" Return the Kazhdan-Lusztig basis (at `q = 1`) of ``self`` @@ -2542,23 +2609,32 @@ def pi_ik(itab, ktab): algebra. This assumes that ``itab`` and ``ktab`` are tableaux (possibly - given just as lists of lists) of the same shape. + given just as lists of lists) of the same shape. Both + tableaux are allowed to be skew. EXAMPLES:: sage: from sage.combinat.symmetric_group_algebra import pi_ik sage: pi_ik([[1,3],[2]], [[1,2],[3]]) [1, 3, 2] + + The same with skew tableaux:: + + sage: from sage.combinat.symmetric_group_algebra import pi_ik + sage: pi_ik([[None,1,3],[2]], [[None,1,2],[3]]) + [1, 3, 2] """ - it = Tableau(itab) - kt = Tableau(ktab) + it = SkewTableau(itab) + kt = SkewTableau(ktab) + n = kt.size() - p = [None] * kt.size() + p = [None] * n for i in range(len(kt)): for j in range(len(kt[i])): - p[it[i][j] - 1] = kt[i][j] + if it[i][j] is not None: + p[it[i][j] - 1] = kt[i][j] - QSn = SymmetricGroupAlgebra(QQ, it.size()) + QSn = SymmetricGroupAlgebra(QQ, n) p = Permutation(p) return QSn(p) @@ -2637,8 +2713,13 @@ def a(tableau, star=0, base_ring=QQ): [1, 2, 3, 4, 5] + [1, 3, 2, 4, 5] + [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1] sage: a([[1,4], [2,3]], base_ring=ZZ) [1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1] + + The same with a skew tableau:: + + sage: a([[None,1,4], [2,3]], base_ring=ZZ) + [1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1] """ - t = Tableau(tableau) + t = SkewTableau(tableau) if star: t = t.restrict(t.size() - star) @@ -2654,7 +2735,7 @@ def a(tableau, star=0, base_ring=QQ): # being [1] rather than [] (which seems to have its origins in # permutation group code). # TODO: Fix this. - if len(tableau) == 0: + if n <= 1: return sgalg.one() rd = dict((P(h), one) for h in rs) @@ -2708,6 +2789,11 @@ def b(tableau, star=0, base_ring=QQ): sage: b([[1, 4], [2, 3]], base_ring=Integers(5)) [1, 2, 3, 4] + 4*[1, 2, 4, 3] + 4*[2, 1, 3, 4] + [2, 1, 4, 3] + The same with a skew tableau:: + + sage: b([[None, 2, 4], [1, 3], [5]]) + [1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1] + With the ``l2r`` setting for multiplication, the unnormalized Young symmetrizer ``e(tableau)`` should be the product ``b(tableau) * a(tableau)`` for every ``tableau``. Let us check @@ -2717,7 +2803,7 @@ def b(tableau, star=0, base_ring=QQ): sage: all( e(t) == b(t) * a(t) for t in StandardTableaux(5) ) True """ - t = Tableau(tableau) + t = SkewTableau(tableau) if star: t = t.restrict(t.size() - star) @@ -2733,7 +2819,7 @@ def b(tableau, star=0, base_ring=QQ): # being [1] rather than [] (which seems to have its origins in # permutation group code). # TODO: Fix this. - if len(tableau) == 0: + if n <= 1: return sgalg.one() cd = dict((P(v), v.sign() * one) for v in cs) @@ -2793,6 +2879,12 @@ def e(tableau, star=0): sage: QS3.antipode(e([[1,2],[3]])) [1, 2, 3] + [2, 1, 3] - [2, 3, 1] - [3, 2, 1] + And here is an example for a skew tableau:: + + sage: e([[None, 2, 1], [4, 3]]) + [1, 2, 3, 4] + [1, 2, 4, 3] - [1, 3, 2, 4] - [1, 4, 2, 3] + + [2, 1, 3, 4] + [2, 1, 4, 3] - [2, 3, 1, 4] - [2, 4, 1, 3] + .. SEEALSO:: :func:`e_hat` @@ -2802,7 +2894,7 @@ def e(tableau, star=0): # a way to compute them over other base rings as well. Be careful # with the cache. - t = Tableau(tableau) + t = SkewTableau(tableau) if star: t = t.restrict(t.size() - star) @@ -2830,8 +2922,8 @@ def e(tableau, star=0): # being [1] rather than [] (which seems to have its origins in # permutation group code). # TODO: Fix this. - if not tableau: - res = QSn.one() + if n <= 1: + return QSn.one() e_cache[t] = res @@ -2889,7 +2981,10 @@ def e_hat(tab, star=0): :func:`e` """ - t = Tableau(tab) + t = SkewTableau(tab) + # This is for consistency's sake. This method is NOT meant + # to be applied to skew tableaux, since the meaning of + # \kappa is unclear in that case. if star: t = t.restrict(t.size() - star) if t in ehat_cache: @@ -2912,8 +3007,8 @@ def e_ik(itab, ktab, star=0): sage: e_ik([[1,2,3]], [[1,2,3]], star=1) [1, 2] + [2, 1] """ - it = Tableau(itab) - kt = Tableau(ktab) + it = SkewTableau(itab) + kt = SkewTableau(ktab) if star: it = it.restrict(it.size() - star) kt = kt.restrict(kt.size() - star) diff --git a/src/sage/combinat/words/all.py b/src/sage/combinat/words/all.py index 8d5798c549c..66a2fa38719 100644 --- a/src/sage/combinat/words/all.py +++ b/src/sage/combinat/words/all.py @@ -43,11 +43,16 @@ from sage.misc.namespace_package import install_doc install_doc(__package__, __doc__) +from sage.misc.lazy_import import lazy_import + from sage.combinat.words.alphabet import Alphabet, build_alphabet from sage.combinat.words.morphism import WordMorphism -from sage.combinat.words.paths import WordPaths +lazy_import('sage.combinat.words.paths', 'WordPaths') from sage.combinat.words.word import Word from sage.combinat.words.word_options import WordOptions from sage.combinat.words.word_generators import words from sage.combinat.words.words import Words, FiniteWords, InfiniteWords from sage.combinat.words.lyndon_word import LyndonWord, LyndonWords, StandardBracketedLyndonWords + +del install_doc +del lazy_import diff --git a/src/sage/databases/symbolic_data.py b/src/sage/databases/symbolic_data.py index 4d63d26cdc1..0c6c4fbfc0a 100644 --- a/src/sage/databases/symbolic_data.py +++ b/src/sage/databases/symbolic_data.py @@ -153,7 +153,7 @@ def _dom2ideal(node): name = self.__genpath + name + ".xml" open(name) except OSError: - raise AttributeError("No ideal matching '%s' found in database." % orig_name) + raise AttributeError(f"no ideal matching '{orig_name}' found in database") dom = parse(name) res = _dom2ideal(dom) @@ -184,7 +184,7 @@ def __getattr__(self, name): sage: sd.Cyclic5 # optional - database_symbolic_data Traceback (most recent call last): ... - AttributeError: No ideal matching 'Cyclic5' found in database. + AttributeError: no ideal matching 'Cyclic5' found in database... sage: sd.Cyclic_5 # optional - database_symbolic_data Ideal (v + w + x + y + z, diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index 069e03c197d..7e9eab2ff2e 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -1579,6 +1579,7 @@ def report_unexpected_exception(self, out, test, example, exc_info): EXAMPLES:: + sage: from sage.interfaces.sage0 import sage0 sage: sage0.quit() sage: _ = sage0.eval("import doctest, sys, os, multiprocessing, subprocess") sage: _ = sage0.eval("from sage.doctest.parsing import SageOutputChecker") diff --git a/src/sage/dynamics/arithmetic_dynamics/affine_ds.py b/src/sage/dynamics/arithmetic_dynamics/affine_ds.py index a1e4bc1700d..2b9dd28b13b 100644 --- a/src/sage/dynamics/arithmetic_dynamics/affine_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/affine_ds.py @@ -45,7 +45,7 @@ class initialization directly. from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.fraction_field import FractionField -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.rings.quotient_ring import is_QuotientRing from sage.schemes.affine.affine_morphism import SchemeMorphism_polynomial_affine_space from sage.schemes.affine.affine_morphism import SchemeMorphism_polynomial_affine_space_field @@ -261,7 +261,7 @@ def __classcall_private__(cls, morphism_or_polys, domain=None): polys = [morphism_or_polys] PR = get_coercion_model().common_parent(*polys) - fraction_field = any(is_FractionField(poly.parent()) for poly in polys) + fraction_field = any(isinstance(poly.parent(), FractionField_generic) for poly in polys) if fraction_field: K = PR.base_ring().fraction_field() # Replace base ring with its fraction field diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 4b3ebd0d89a..a04cf57a28d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -87,8 +87,8 @@ class initialization directly. from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.finite_rings.integer_mod_ring import Zmod -from sage.rings.fraction_field import (FractionField, is_FractionField, FractionField_1poly_field) -from sage.rings.fraction_field_element import is_FractionFieldElement, FractionFieldElement +from sage.rings.fraction_field import FractionField, FractionField_generic, FractionField_1poly_field +from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.function_field.function_field import is_FunctionField from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ @@ -394,11 +394,11 @@ def __classcall_private__(cls, morphism_or_polys, domain=None, names=None): # homogenize! f = morphism_or_polys aff_CR = f.parent() - if (not is_PolynomialRing(aff_CR) and not is_FractionField(aff_CR) + if (not is_PolynomialRing(aff_CR) and not isinstance(aff_CR, FractionField_generic) and not (is_MPolynomialRing(aff_CR) and aff_CR.ngens() == 1)): msg = '{} is not a single variable polynomial or rational function' raise ValueError(msg.format(f)) - if is_FractionField(aff_CR): + if isinstance(aff_CR, FractionField_generic): polys = [f.numerator(),f.denominator()] else: polys = [f, aff_CR(1)] @@ -889,7 +889,7 @@ def dynatomic_polynomial(self, period): # do it again to divide out by denominators of coefficients PHI = QR2[0].sage() PHI = PHI.numerator()._maxima_().divide(PHI.denominator())[0].sage() - if not is_FractionFieldElement(PHI): + if not isinstance(PHI, FractionFieldElement): from sage.symbolic.expression_conversions import polynomial PHI = polynomial(PHI, ring=self.coordinate_ring()) except (TypeError, NotImplementedError): #something Maxima, or the conversion, can't handle @@ -3533,7 +3533,7 @@ def affine_preperiodic_model(self, m, n, return_conjugation=False): if hyperplane_found: break else: - if is_PolynomialRing(R) or is_MPolynomialRing(R) or is_FractionField(R): + if is_PolynomialRing(R) or is_MPolynomialRing(R) or isinstance(R, FractionField_generic): # for polynomial rings, we can get an infinite family of hyperplanes # by increasing the degree var = R.gen() @@ -3702,7 +3702,7 @@ def automorphism_group(self, **kwds): raise NotImplementedError("rational function of degree 1 not implemented") f = self.dehomogenize(1) R = PolynomialRing(f.base_ring(),'x') - if is_FractionFieldElement(f[0]): + if isinstance(f[0], FractionFieldElement): F = (f[0].numerator().univariate_polynomial(R))/f[0].denominator().univariate_polynomial(R) else: F = f[0].univariate_polynomial(R) @@ -4880,7 +4880,7 @@ def periodic_points(self, n, minimal=True, formal=False, R=None, algorithm='vari if isinstance(R, FractionField_1poly_field) or is_FunctionField(R): raise NotImplementedError('periodic points not implemented for fraction function fields; ' 'clear denominators and use the polynomial ring instead') - if is_FractionField(R): + if isinstance(R, FractionField_generic): if is_MPolynomialRing(R.ring()): raise NotImplementedError('periodic points not implemented for fraction function fields; ' 'clear denominators and use the polynomial ring instead') @@ -5784,7 +5784,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', X = X.change_ring(F) else: F = base_ring - if is_FractionField(base_ring): + if isinstance(base_ring, FractionField_generic): if is_MPolynomialRing(base_ring.ring()) or is_PolynomialRing(base_ring.ring()): f.normalize_coordinates() f_ring = f.change_ring(base_ring.ring()) @@ -5886,7 +5886,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', return sigmas base_ring = dom.base_ring() - if is_FractionField(base_ring): + if isinstance(base_ring, FractionField_generic): base_ring = base_ring.ring() if (is_PolynomialRing(base_ring) or is_MPolynomialRing(base_ring)): base_ring = base_ring.base_ring() diff --git a/src/sage/dynamics/complex_dynamics/mandel_julia.py b/src/sage/dynamics/complex_dynamics/mandel_julia.py index 00eb7d473eb..8ceb38d0cec 100644 --- a/src/sage/dynamics/complex_dynamics/mandel_julia.py +++ b/src/sage/dynamics/complex_dynamics/mandel_julia.py @@ -51,7 +51,7 @@ from sage.schemes.projective.projective_space import ProjectiveSpace from sage.misc.prandom import randint from sage.calculus.var import var -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.categories.function_fields import FunctionFields lazy_import('sage.dynamics.arithmetic_dynamics.generic_ds', 'DynamicalSystem') @@ -243,14 +243,14 @@ def mandelbrot_plot(f=None, **kwds): P = f.parent() if P.base_ring() is CC or P.base_ring() is CDF: - if is_FractionField(P): + if isinstance(P, FractionField_generic): raise NotImplementedError("coefficients must be polynomials in the parameter") gen_list = list(P.gens()) parameter = gen_list.pop(gen_list.index(parameter)) variable = gen_list.pop() elif P.base_ring().base_ring() is CC or P.base_ring().base_ring() is CDF: - if is_FractionField(P.base_ring()): + if isinstance(P.base_ring(), FractionField_generic): raise NotImplementedError("coefficients must be polynomials in the parameter") phi = P.flattening_morphism() f = phi(f) diff --git a/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx b/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx index 2cb446886e1..479589dc0e3 100644 --- a/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +++ b/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx @@ -34,7 +34,7 @@ from sage.ext.fast_callable import fast_callable from sage.calculus.all import symbolic_expression from sage.symbolic.ring import SR from sage.calculus.var import var -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.categories.function_fields import FunctionFields from cypari2.handle_error import PariError from math import sqrt @@ -709,14 +709,14 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, P = f.parent() if P.base_ring() is CC: - if is_FractionField(P): + if isinstance(P, FractionField_generic): raise NotImplementedError("coefficients must be polynomials in the parameter") gen_list = list(P.gens()) parameter = gen_list.pop(gen_list.index(parameter)) variable = gen_list.pop() elif P.base_ring().base_ring() is CC: - if is_FractionField(P.base_ring()): + if isinstance(P.base_ring(), FractionField_generic): raise NotImplementedError("coefficients must be polynomials in the parameter") phi = P.flattening_morphism() f = phi(f) diff --git a/src/sage/features/__init__.py b/src/sage/features/__init__.py index a5d5ff3c409..df76ec9da99 100644 --- a/src/sage/features/__init__.py +++ b/src/sage/features/__init__.py @@ -606,7 +606,7 @@ class FileFeature(Feature): To work with the file described by the feature, use the method :meth:`absolute_filename`. A :class:`FeatureNotPresentError` is raised if the file cannot be found:: - sage: Executable(name="does-not-exist", executable="does-not-exist-xxxxyxyyxyy").absolute_path() + sage: Executable(name="does-not-exist", executable="does-not-exist-xxxxyxyyxyy").absolute_filename() Traceback (most recent call last): ... sage.features.FeatureNotPresentError: does-not-exist is not available. @@ -654,32 +654,6 @@ def absolute_filename(self) -> str: # the distribution sagemath-environment. raise NotImplementedError - def absolute_path(self): - r""" - Deprecated alias for :meth:`absolute_filename`. - - Deprecated to make way for a method of this name returning a ``Path``. - - EXAMPLES:: - - sage: from sage.features import Executable - sage: Executable(name="sh", executable="sh").absolute_path() - doctest:warning... - DeprecationWarning: method absolute_path has been replaced by absolute_filename - See https://github.com/sagemath/sage/issues/31292 for details. - '/...bin/sh' - """ - try: - from sage.misc.superseded import deprecation - except ImportError: - # The import can fail because sage.misc.superseded is provided by - # the distribution sagemath-objects, which is not an - # install-requires of the distribution sagemath-environment. - pass - else: - deprecation(31292, 'method absolute_path has been replaced by absolute_filename') - return self.absolute_filename() - class Executable(FileFeature): r""" @@ -764,7 +738,7 @@ def absolute_filename(self) -> str: A :class:`FeatureNotPresentError` is raised if the file cannot be found:: - sage: Executable(name="does-not-exist", executable="does-not-exist-xxxxyxyyxyy").absolute_path() + sage: Executable(name="does-not-exist", executable="does-not-exist-xxxxyxyyxyy").absolute_filename() Traceback (most recent call last): ... sage.features.FeatureNotPresentError: does-not-exist is not available. diff --git a/src/sage/features/join_feature.py b/src/sage/features/join_feature.py index afb41e7f227..fd993e90e1b 100644 --- a/src/sage/features/join_feature.py +++ b/src/sage/features/join_feature.py @@ -98,36 +98,6 @@ def _is_present(self): return test return FeatureTestResult(self, True) - def is_functional(self): - r""" - Test whether the join feature is functional. - - This method is deprecated. Use :meth:`Feature.is_present` instead. - - EXAMPLES:: - - sage: from sage.features.latte import Latte - sage: Latte().is_functional() # optional - latte_int - doctest:warning... - DeprecationWarning: method JoinFeature.is_functional; use is_present instead - See https://github.com/sagemath/sage/issues/33114 for details. - FeatureTestResult('latte_int', True) - """ - try: - from sage.misc.superseded import deprecation - except ImportError: - # The import can fail because sage.misc.superseded is provided by - # the distribution sagemath-objects, which is not an - # install-requires of the distribution sagemath-environment. - pass - else: - deprecation(33114, 'method JoinFeature.is_functional; use is_present instead') - for f in self._features: - test = f.is_functional() - if not test: - return test - return FeatureTestResult(self, True) - def hide(self): r""" Hide this feature and all its joined features. diff --git a/src/sage/features/standard.py b/src/sage/features/standard.py index 94272802aad..c4055263e79 100644 --- a/src/sage/features/standard.py +++ b/src/sage/features/standard.py @@ -33,5 +33,6 @@ def all_features(): PythonModule('ptyprocess', spkg='ptyprocess', type='standard'), PythonModule('pyparsing', spkg='pyparsing', type='standard'), PythonModule('requests', spkg='requests', type='standard'), + PythonModule('rpy2', spkg='rpy2', type='standard'), PythonModule('scipy', spkg='scipy', type='standard'), PythonModule('sympy', spkg='sympy', type='standard')] diff --git a/src/sage/functions/transcendental.py b/src/sage/functions/transcendental.py index 1c657f5b8b3..3dcb446e706 100644 --- a/src/sage/functions/transcendental.py +++ b/src/sage/functions/transcendental.py @@ -28,10 +28,10 @@ lazy_import('sage.combinat.combinat', 'bernoulli_polynomial') lazy_import('sage.rings.cc', 'CC') -lazy_import('sage.rings.complex_mpfr', ['ComplexField', 'is_ComplexNumber']) +lazy_import('sage.rings.complex_mpfr', ['ComplexField', 'ComplexNumber']) lazy_import('sage.rings.polynomial.polynomial_real_mpfr_dense', 'PolynomialRealDense') lazy_import('sage.rings.real_double', 'RDF') -lazy_import('sage.rings.real_mpfr', ['RR', 'RealField', 'is_RealNumber']) +lazy_import('sage.rings.real_mpfr', ['RR', 'RealField', 'RealNumber']) lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') lazy_import('mpmath', 'zeta', as_='_mpmath_zeta') @@ -452,7 +452,7 @@ def zeta_symmetric(s): - I copied the definition of xi from http://web.viu.ca/pughg/RiemannZeta/RiemannZetaLong.html """ - if not (is_ComplexNumber(s) or is_RealNumber(s)): + if not (isinstance(s, ComplexNumber) or isinstance(s, RealNumber)): s = ComplexField()(s) R = s.parent() @@ -544,7 +544,7 @@ def _eval_(self, x): sage: dickman_rho(0) # needs sage.symbolic 1.00000000000000 """ - if not is_RealNumber(x): + if not isinstance(x, RealNumber): try: x = RR(x) except (TypeError, ValueError): diff --git a/src/sage/game_theory/matching_game.py b/src/sage/game_theory/matching_game.py index 11c04f6e5b1..8efa2c2acfa 100644 --- a/src/sage/game_theory/matching_game.py +++ b/src/sage/game_theory/matching_game.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs """ Matching games @@ -124,7 +125,7 @@ class MatchingGame(SageObject): Matchings have a natural representations as bipartite graphs:: - sage: plot(m) + sage: plot(m) # needs sage.plot Graphics object consisting of 13 graphics primitives The above plots the bipartite graph associated with the matching. @@ -508,14 +509,14 @@ def plot(self): sage: revr = {3: (0, 1), ....: 4: (1, 0)} sage: g = MatchingGame([suit, revr]) - sage: plot(g) + sage: plot(g) # needs sage.plot Traceback (most recent call last): ... ValueError: game has not been solved yet sage: g.solve() {0: 3, 1: 4} - sage: plot(g) + sage: plot(g) # needs sage.plot Graphics object consisting of 7 graphics primitives """ pl = self.bipartite_graph() diff --git a/src/sage/game_theory/normal_form_game.py b/src/sage/game_theory/normal_form_game.py index e2220fc7f0a..2b1e592c4e8 100644 --- a/src/sage/game_theory/normal_form_game.py +++ b/src/sage/game_theory/normal_form_game.py @@ -157,11 +157,11 @@ `(Ay)_i`, ie element in position `i` of the matrix/vector multiplication `Ay`) :: - sage: y = var('y') + sage: y = var('y') # needs sage.symbolic sage: A = matrix([[1, -1], [-1, 1]]) - sage: p = plot((A * vector([y, 1 - y]))[0], y, 0, 1, color='blue', + sage: p = plot((A * vector([y, 1 - y]))[0], y, 0, 1, color='blue', # needs sage.symbolic ....: legend_label='$u_1(r_1, (y, 1-y))$', axes_labels=['$y$', '']) - sage: p += plot((A * vector([y, 1 - y]))[1], y, 0, 1, color='red', + sage: p += plot((A * vector([y, 1 - y]))[1], y, 0, 1, color='red', # needs sage.symbolic ....: legend_label='$u_1(r_2, (y, 1-y))$'); p Graphics object consisting of 2 graphics primitives diff --git a/src/sage/games/all.py b/src/sage/games/all.py index be1a1f2cbfc..d2b0648440e 100644 --- a/src/sage/games/all.py +++ b/src/sage/games/all.py @@ -1,2 +1,6 @@ -from sage.games.sudoku import Sudoku, sudoku -from sage.games.hexad import Minimog + +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.games.sudoku', ['Sudoku', 'sudoku']) +lazy_import('sage.games.hexad', ['Minimog']) +del lazy_import diff --git a/src/sage/geometry/fan.py b/src/sage/geometry/fan.py index ccbb9488470..864a9237ee7 100644 --- a/src/sage/geometry/fan.py +++ b/src/sage/geometry/fan.py @@ -134,13 +134,13 @@ sage: [cone.ambient_ray_indices() for cone in fan1.cones(2)] [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (0, 4), - (2, 4), (3, 4), (1, 5), (3, 5), (4, 5), (0, 5)] + (2, 4), (3, 4), (0, 5), (1, 5), (3, 5), (4, 5)] In fact, you do not have to type ``.cones``:: sage: [cone.ambient_ray_indices() for cone in fan1(2)] [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (0, 4), - (2, 4), (3, 4), (1, 5), (3, 5), (4, 5), (0, 5)] + (2, 4), (3, 4), (0, 5), (1, 5), (3, 5), (4, 5)] You may also need to know the inclusion relations between all of the cones of the fan. In this case check out @@ -1914,7 +1914,7 @@ def _subdivide_stellar(self, new_rays, verbose): sage: C = Cone([(1,0,0), (0,1,0), (1,0,1), (0,1,1)]) sage: F = Fan([C]).make_simplicial() sage: [cone.ambient_ray_indices() for cone in F] - [(0, 2, 3), (0, 1, 3)] + [(0, 1, 3), (0, 2, 3)] """ cones = self.generating_cones() for n, ray in enumerate(new_rays): @@ -2139,7 +2139,7 @@ def cone_lattice(self): ....: print([f.ambient_ray_indices() for f in l]) [()] [(0,), (1,), (2,), (3,)] - [(0, 2), (1, 2), (0, 3), (1, 3)] + [(0, 2), (1, 2), (1, 3), (0, 3)] Let's also consider the cone lattice of a fan generated by a single cone:: diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 17ae3a25738..533f7ac1151 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -952,11 +952,19 @@ def characteristic_polynomial(self): ....: m_perm = matrix(m_perm).transpose() ....: charpoly = H(m_perm.rows()).characteristic_polynomial() ....: assert charpoly == expected_charpoly + + Check the corner case of the empty arrangement:: + + sage: E = H() + sage: E.characteristic_polynomial() + 1 """ from sage.rings.polynomial.polynomial_ring import polygen x = polygen(QQ, 'x') if self.rank() == 1: return x**(self.dimension() - 1) * (x - len(self)) + if self.rank() == 0: + return x ** 0 H = self[0] R = self.restriction(H) diff --git a/src/sage/geometry/integral_points.pxi b/src/sage/geometry/integral_points.pxi index 649eb281a1c..327855b6a57 100644 --- a/src/sage/geometry/integral_points.pxi +++ b/src/sage/geometry/integral_points.pxi @@ -948,7 +948,7 @@ cdef class Inequality_int: 'integer: (2, 3, 7) x + -5 >= 0' """ s = 'integer: (' - s += ', '.join([str(self.A[i]) for i in range(self.dim)]) + s += ', '.join(str(self.A[i]) for i in range(self.dim)) s += ') x + ' + str(self.b) + ' >= 0' return s diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index 8c2d0418595..d37888416b5 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -1163,7 +1163,7 @@ def _repr_(self): """ s = 'Sublattice ' s += '<' - s += ', '.join(map(str,self.basis())) + s += ', '.join(map(str, self.basis())) s += '>' return s @@ -1186,7 +1186,7 @@ def _latex_(self): \\left(0,\\,4,\\,8\\right)_{L}\\right\\rangle' """ s = '\\left\\langle' - s += ', '.join([ b._latex_() for b in self.basis() ]) + s += ', '.join(b._latex_() for b in self.basis()) s += '\\right\\rangle' return s diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index 770ee23fc68..1f8e5a59c73 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -5022,8 +5022,8 @@ cdef inline bint _reorganize_edge(object v, object u, const int modus) noexcept: - ``modus`` -- integer representing the modus of the iterator: - ``0`` -- outgoing edges - ``1`` -- ingoing edges - - ``3`` -- unsorted edges of an undirected graph - - ``4`` -- sorted edges of an undirected graph + - ``2`` -- unsorted edges of an undirected graph + - ``3`` -- sorted edges of an undirected graph OUTPUT: Boolean according the modus: @@ -5034,12 +5034,11 @@ cdef inline bint _reorganize_edge(object v, object u, const int modus) noexcept: """ if modus == 0: return False - if modus == 1 or modus == 2: - return True + elif modus == 3: + try: + if v <= u: + return False + except TypeError: + pass - try: - if v <= u: - return False - except TypeError: - pass return True diff --git a/src/sage/graphs/base/dense_graph.pyx b/src/sage/graphs/base/dense_graph.pyx index 9aff72e066c..abcd0809af1 100644 --- a/src/sage/graphs/base/dense_graph.pyx +++ b/src/sage/graphs/base/dense_graph.pyx @@ -97,6 +97,16 @@ from ``CGraph`` (for explanation, refer to the documentation there):: It also contains the following variables:: cdef binary_matrix_t edges + +.. NOTE:: + + As the edges are stored as the adjacency matrix of the graph, enumerating + the edges of the graph has complexity `O(n^2)` and enumerating the neighbors + of a vertex has complexity `O(n)` (where `n` in the size of the bitset + active_vertices). + So, the class ``DenseGraph`` should be used for graphs such that the number + of edges is close to the square of the number of vertices. + """ # **************************************************************************** diff --git a/src/sage/graphs/base/sparse_graph.pxd b/src/sage/graphs/base/sparse_graph.pxd index 540a8827801..b47c5df8210 100644 --- a/src/sage/graphs/base/sparse_graph.pxd +++ b/src/sage/graphs/base/sparse_graph.pxd @@ -40,8 +40,9 @@ cdef class SparseGraph(CGraph): cpdef int out_degree(self, int u) noexcept cpdef int in_degree(self, int u) noexcept - cdef int out_neighbors_BTNode_unsafe(self, int u, SparseGraphBTNode *** p_pointers) noexcept - cdef int in_neighbors_BTNode_unsafe(self, int u, SparseGraphBTNode *** p_pointers) noexcept + cdef inline int _neighbors_unsafe (self, int u, bint out, int *neighbors, int size) except -2 + + cdef inline int _neighbors_BTNode_unsafe (self, int u, bint out, SparseGraphBTNode **res, int size) except -2 cdef inline SparseGraphBTNode* next_out_neighbor_BTNode_unsafe(self, int u, int v) noexcept: """ @@ -50,6 +51,13 @@ cdef class SparseGraph(CGraph): If ``v`` is ``-1`` return the first neighbor of ``u``. Return ``NULL`` in case there does not exist such an out-neighbor. + + .. WARNING:: + + Repeated calls to this function until NULL is returned DOES NOT + yield a linear time algorithm in the number of neighbors of u. + To list the neighbors of a vertex in linear time, one should use + _neighbors_BTNode_unsafe. """ return self.next_neighbor_BTNode_unsafe(self.vertices, u, v) @@ -60,6 +68,13 @@ cdef class SparseGraph(CGraph): If ``u`` is ``-1`` return the first neighbor of ``v``. Return ``NULL`` in case there does not exist such an in-neighbor. + + .. WARNING:: + + Repeated calls to this function until NULL is returned DOES NOT + yield a linear time algorithm in the number of neighbors of u. + To list the neighbors of a vertex in linear time, one should use + _neighbors_BTNode_unsafe. """ return self.next_neighbor_BTNode_unsafe(self.vertices_rev, v, u) diff --git a/src/sage/graphs/base/sparse_graph.pyx b/src/sage/graphs/base/sparse_graph.pyx index ba230427466..3e736bc6461 100644 --- a/src/sage/graphs/base/sparse_graph.pyx +++ b/src/sage/graphs/base/sparse_graph.pyx @@ -135,6 +135,8 @@ It also contains the following variables:: cdef int hash_length cdef int hash_mask cdef SparseGraphBTNode **vertices + cdef SparseGraphBTNode **vertices_rev + cdef bint _directed For each vertex ``u``, a hash table of length ``hash_length`` is instantiated. An arc ``(u, v)`` is stored at ``u * hash_length + hash(v)`` of the array @@ -192,6 +194,7 @@ for both of these uses. from libc.string cimport memset from cysignals.memory cimport check_malloc, check_allocarray, sig_free +from memory_allocator cimport MemoryAllocator from sage.data_structures.bitset_base cimport * from sage.data_structures.bitset cimport * @@ -610,42 +613,35 @@ cdef class SparseGraph(CGraph): # Neighbor functions ################################### - cdef int out_neighbors_BTNode_unsafe(self, int u, SparseGraphBTNode *** p_pointers) noexcept: - """ - List the out-neighbors of a vertex as BTNodes - - Technically, this function transforms a binary tree into a list. The - information it returns is a list of pointers toward a - ``SparseGraphBTNode``, thus a ``SparseGraphBTNode **``. - - INPUT: - - - ``u`` -- the vertex to consider - - - ``p_pointers`` -- a pointer toward a ``SparseGraphBTNode **``, i.e. a - ``SparseGraphBTNode ***``. When the function terminates, - ``p_pointers[0]`` points toward a filled ``SparseGraphBTNode **``. It - returns the length of this array. - - .. NOTE:: + cdef inline int _neighbors_BTNode_unsafe (self, int u, bint out, SparseGraphBTNode **res, int size) except -2: + r""" + .. WARNING:: - Don't forget to free ``p_pointers[0]`` ! + This method is for internal use only. """ - cdef int num_nbrs = 0 - cdef int degree = self.out_degrees[u] - if degree == 0: - p_pointers[0] = NULL - return 0 - cdef SparseGraphBTNode **pointers = check_allocarray(degree, sizeof(SparseGraphBTNode *)) - p_pointers[0] = pointers - - cdef SparseGraphBTNode* v = self.next_out_neighbor_BTNode_unsafe(u, -1) - while v: - pointers[num_nbrs] = v - num_nbrs += 1 - v = self.next_out_neighbor_BTNode_unsafe(u, v.vertex) + cdef SparseGraphBTNode** vertices = self.vertices if out else self.vertices_rev + cdef int i + cdef int n = 0 + cdef int nr = 0 + cdef SparseGraphBTNode *c - return num_nbrs + for i in range(u * self.hash_length, (u+1) * self.hash_length): + if not vertices[i]: + continue + else: + res[n] = vertices[i] + nr = 1 + while nr > 0 and n < size: + c = res[n] + n += 1 + nr -= 1 + if c.left: + res[n+nr] = c.left + nr += 1 + if c.right: + res[n+nr] = c.right + nr += 1 + return -1 if nr > 0 else n cdef inline int next_out_neighbor_unsafe(self, int u, int v, int* l) except -2: """ @@ -656,6 +652,13 @@ cdef class SparseGraph(CGraph): Return ``-1`` in case there does not exist such an out-neighbor. Set ``l`` to be the label of the first arc. + + .. WARNING:: + + Repeated calls to this function until -1 is returned DOES NOT yield + a linear time algorithm in the number of neighbors of v. + To list the neighbors of a vertex in linear time, one should use + out_neighbors_unsafe. """ cdef SparseGraphBTNode* next_bt = self.next_out_neighbor_BTNode_unsafe(u, v) if next_bt: @@ -677,6 +680,13 @@ cdef class SparseGraph(CGraph): If ``vertices`` is ``self.vertices`` the out-neighbor is given. If ``vertices`` is ``self.vertices_rev`` the in-neighbor is given. + + .. WARNING:: + + Repeated calls to this function until NULL is returned DOES NOT + yield a linear time algorithm in the number of neighbors of u. + To list the neighbors of a vertex in linear time, one should use + _neighbors_BTNode_unsafe. """ cdef int i cdef int start_i = (u * self.hash_length) + (v & self.hash_mask) @@ -732,43 +742,6 @@ cdef class SparseGraph(CGraph): """ return self.out_degrees[u] - cdef int in_neighbors_BTNode_unsafe(self, int v, SparseGraphBTNode *** p_pointers) noexcept: - """ - List the in-neighbors of a vertex as BTNodes - - Technically, this function transforms a binary tree into a list. The - information it returns is a list of pointers toward a - ``SparseGraphBTNode``, thus a ``SparseGraphBTNode **``. - - INPUT: - - - ``u`` -- the vertex to consider - - - ``p_pointers`` -- a pointer toward a ``SparseGraphBTNode **``, i.e. a - ``SparseGraphBTNode ***``. When the function terminates, - ``p_pointers[0]`` points toward a filled ``SparseGraphBTNode **``. It - returns the length of this array. - - .. NOTE:: - - Don't forget to free ``p_pointers[0]`` ! - """ - cdef int num_nbrs = 0 - cdef int degree = self.in_degrees[v] - if degree == 0: - p_pointers[0] = NULL - return 0 - cdef SparseGraphBTNode **pointers = check_allocarray(degree, sizeof(SparseGraphBTNode *)) - p_pointers[0] = pointers - - cdef SparseGraphBTNode* u = self.next_in_neighbor_BTNode_unsafe(v, -1) - while u: - pointers[num_nbrs] = u - num_nbrs += 1 - u = self.next_in_neighbor_BTNode_unsafe(v, u.vertex) - - return num_nbrs - cdef inline int next_in_neighbor_unsafe(self, int v, int u, int* l) except -2: """ Return the next in-neighbor of ``v`` that is greater than ``u``. @@ -778,6 +751,13 @@ cdef class SparseGraph(CGraph): Return ``-1`` in case there does not exist such an in-neighbor. Set ``l`` to be the label of the first arc. + + .. WARNING:: + + Repeated calls to this function until -1 is returned DOES NOT yield + a linear time algorithm in the number of neighbors of v. + To list the neighbors of a vertex in linear time, one should use + in_neighbors_unsafe. """ cdef SparseGraphBTNode* next_bt = self.next_in_neighbor_BTNode_unsafe(v, u) if next_bt: @@ -789,6 +769,27 @@ cdef class SparseGraph(CGraph): else: return -1 + cdef inline int _neighbors_unsafe(self, int u, bint out, int *neighbors, int size) except -2: + r""" + .. WARNING:: + + This method is for internal use only. + """ + cdef int r + cdef SparseGraphBTNode **nodes = check_allocarray(size, sizeof(SparseGraphBTNode *)) + + r = self._neighbors_BTNode_unsafe(u, out, nodes, size) + for i in range(r if r >= 0 else size): + neighbors[i] = nodes[i].vertex + sig_free(nodes) + return r + + cdef int out_neighbors_unsafe(self, int u, int *neighbors, int size) except -2: + return self._neighbors_unsafe(u, 1, neighbors, size) + + cdef int in_neighbors_unsafe(self, int u, int *neighbors, int size) except -2: + return self._neighbors_unsafe(u, 0, neighbors, size) + cpdef int in_degree(self, int v) noexcept: """ Returns the in-degree of ``v`` @@ -1449,3 +1450,214 @@ cdef class SparseGraphBackend(CGraphBackend): if not directed and self._directed and v_int != u_int: self._cg.del_arc_label(v_int, u_int, ll_int) self._cg.add_arc_label(v_int, u_int, l_int) + + def _iterator_edges(self, object vertices, const bint labels, const int modus=0): + """ + Iterate over the edges incident to a sequence of vertices. + + INPUT: + + - ``vertices`` -- a list of vertex labels + + - ``labels`` -- boolean, whether to return labels as well + + - ``modus`` -- integer representing the modus of the iterator: + - ``0`` -- outgoing edges + - ``1`` -- ingoing edges + - ``2`` -- unsorted edges of an undirected graph + - ``3`` -- sorted edges of an undirected graph + + EXAMPLES:: + + sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9) + sage: G.add_edge(1, 2, None, False) + sage: list(G._iterator_edges(range(9), False, 3)) + [(1, 2)] + sage: list(G._iterator_edges(range(9), True, 3)) + [(1, 2, None)] + + :: + + sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9) + sage: G.add_edge(1, 2, None, True) + sage: list(G.iterator_in_edges([1], False)) + [] + sage: list(G.iterator_in_edges([2], False)) + [(1, 2)] + sage: list(G.iterator_in_edges([2], True)) + [(1, 2, None)] + + :: + + sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9) + sage: G.add_edge(1, 2, None, True) + sage: list(G.iterator_out_edges([2], False)) + [] + sage: list(G.iterator_out_edges([1], False)) + [(1, 2)] + sage: list(G.iterator_out_edges([1], True)) + [(1, 2, None)] + """ + cdef object u, v, l, v_copy + cdef int u_int, v_int, l_int, foo + cdef CGraph cg = self.cg() + cdef list b_vertices_2, all_arc_labels + cdef FrozenBitset b_vertices + cdef bint out = modus == 0 + + cdef int vertices_case + cdef object it + + cdef int r + cdef int maxdegree = 0 + cdef int *degrees = NULL + if out: + degrees = cg.out_degrees + else: + degrees = cg.in_degrees + for v_int in range(cg.active_vertices.size): + if bitset_in(cg.active_vertices, v_int): + maxdegree = max(degrees[v_int], maxdegree) + cdef MemoryAllocator mem = MemoryAllocator() + cdef SparseGraphBTNode **neighbors = mem.allocarray(maxdegree, sizeof(SparseGraphBTNode *)) + + if not isinstance(vertices, list): + # ALL edges + it = self.iterator_verts(None) + vertices_case = 0 + + elif not vertices: + return + + elif len(vertices) == 1: + # One vertex + vertices_case = 1 + v_int = -1 + + else: + # Several vertices (nonempty list) + vertices_case = 2 + b_vertices_2 = [self.get_vertex_checked(v) for v in vertices] + try: + b_vertices = FrozenBitset(foo for foo in b_vertices_2 if foo >= 0) + except ValueError: + # Avoiding "Bitset must not be empty" + # in case none of the vertices is active. + return + it = iter(b_vertices) + + while True: + # Think of this as a loop through ``vertices``. + # We pick the next vertex according to three cases. + + if vertices_case == 0: + # ALL edges + try: + v = next(it) + v_int = self.get_vertex(v) + except StopIteration: + return + + elif vertices_case == 1: + # One vertex + if v_int != -1: + # Only visit one vertex once. + return + v = vertices[0] + v_int = self.get_vertex_checked(v) + if v_int == -1: + return + + else: + # Several vertices (nonempty list) + try: + v_int = -1 + while v_int == -1: + v_int = next(it) + v = self.vertex_label(v_int) + except StopIteration: + return + + # WARNING + # If you modify this, you must keep in mind the documentation in the + # corresponding method in `generic_graph.py` in the method `edge_iterator`. + # E.g. code assumes that you can use an iterator to relabel or delete arcs. + + r = self._cg._neighbors_BTNode_unsafe(v_int, out, neighbors, maxdegree) + for i in range(r): + u_int = neighbors[i].vertex + if neighbors[i].number: + l_int = 0 + else: + l_int = neighbors[i].labels.label + if (modus < 2 or # Do not delete duplicates. + vertices_case == 1 or # Only one vertex, so no duplicates. + u_int >= v_int or # We visit if u_int >= v_int ... + (vertices_case == 2 and + u_int < b_vertices.capacity() and + not bitset_in(b_vertices._bitset, u_int))): # ... or if u_int is not in ``vertices``. + u = self.vertex_label(u_int) + if labels: + l = self.edge_labels[l_int] if l_int else None + + # Yield the arc/arcs. + v_copy = v + if _reorganize_edge(v, u, modus): + u, v = v, u + + if not self._multiple_edges: + if labels: + yield (v, u, l) + else: + yield (v, u) + else: + if out: + all_arc_labels = cg.all_arcs(v_int, u_int) + else: + all_arc_labels = cg.all_arcs(u_int, v_int) + + for l_int in all_arc_labels: + if labels: + l = self.edge_labels[l_int] if l_int else None + yield (v, u, l) + else: + yield (v, u) + v = v_copy + +############################## +# Functions to simplify edge iterator. +############################## + +cdef inline bint _reorganize_edge(object v, object u, const int modus) noexcept: + """ + Return ``True`` if ``v`` and ``u`` should be exchanged according to the modus. + + INPUT: + + - ``v`` -- vertex + + - ``u`` -- vertex + + - ``modus`` -- integer representing the modus of the iterator: + - ``0`` -- outgoing edges + - ``1`` -- ingoing edges + - ``2`` -- unsorted edges of an undirected graph + - ``3`` -- sorted edges of an undirected graph + + OUTPUT: Boolean according the modus: + + - ``modus == 0`` -- ``False`` + - ``modus == 1`` -- ``True`` + - ``modus == 2`` -- ``True + - ``modus == 3`` -- ``False if v <= u else True`` + """ + if modus == 0: + return False + elif modus == 3: + try: + if v <= u: + return False + except TypeError: + pass + + return True diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index f74e1b28dec..898b69568d0 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -231,11 +231,13 @@ cdef int init_short_digraph(short_digraph g, G, edge_labelled=False, complexity of some methods. More precisely: - When set to ``True``, the time complexity for initializing ``g`` is in - `O(m + m\log{m})` and deciding if ``g`` has edge `(u, v)` can be done in + `O(n + m\log{m})` for ``SparseGraph`` and `O(n^2\log{m})` for + ``DenseGraph``, and deciding if ``g`` has edge `(u, v)` can be done in time `O(\log{m})` using binary search. - When set to ``False``, the time complexity for initializing ``g`` is - reduced to `O(n + m)` but the time complexity for deciding if ``g`` has + reduced to `O(n + m)` for ``SparseGraph`` and `O(n^2)` for + ``DenseGraph``, but the time complexity for deciding if ``g`` has edge `(u, v)` increases to `O(m)`. """ g.edge_labels = NULL diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index 575c67b2386..c8a321ece81 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -507,8 +507,11 @@ def geodetic_closure(G, S): each vertex `u \in S`, the algorithm first performs a breadth first search from `u` to get distances, and then identifies the vertices of `G` lying on a shortest path from `u` to any `v\in S` using a reversal traversal from - vertices in `S`. This algorithm has time complexity in `O(|S|(n + m))` and - space complexity in `O(n + m)`. + vertices in `S`. This algorithm has time complexity in + `O(|S|(n + m) + (n + m\log{m}))` for ``SparseGraph``, + `O(|S|(n + m) + n^2\log{m})` for ``DenseGraph`` and space complexity in + `O(n + m)` (the extra `\log` factor is due to ``init_short_digraph`` being + called with ``sort_neighbors=True``). INPUT: @@ -678,10 +681,10 @@ def is_geodetic(G): Check whether the input (di)graph is geodetic. A graph `G` is *geodetic* if there exists only one shortest path between - every pair of its vertices. This can be checked in time `O(nm)` in - unweighted (di)graphs with `n` nodes and `m` edges. Examples of geodetic - graphs are trees, cliques and odd cycles. See the - :wikipedia:`Geodetic_graph` for more details. + every pair of its vertices. This can be checked in time `O(nm)` for + ``SparseGraph`` and `O(nm+n^2)` for ``DenseGraph`` in unweighted (di)graphs + with `n` nodes and `m` edges. Examples of geodetic graphs are trees, cliques + and odd cycles. See the :wikipedia:`Geodetic_graph` for more details. (Di)graphs with multiple edges are not considered geodetic. diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 6f4e8cac30c..1b650b73a1b 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -1202,8 +1202,31 @@ def neighbor_in_iterator(self, vertex): ....: print(a) 1 4 + + TESTS: + + With multiple edges, check that the neighbors are listed only once:: + + sage: D = DiGraph([[0, 1, 2], [(0, 1), (0, 1), (1, 2) ]],multiedges=True) + sage: list(D.neighbor_in_iterator(0)) + [] + sage: list(D.neighbor_in_iterator(1)) + [0] + sage: list(D.neighbor_in_iterator(2)) + [1] + + Check that the iterator lists ``vertex`` in the presence of loop(s): + + sage: D = DiGraph([[0, 1, 2], [(0, 0), (0, 0), (1, 1)]],multiedges=True, loops=True) + sage: list(D.neighbor_in_iterator(0)) + [0] + sage: list(D.neighbor_in_iterator(1)) + [1] + sage: list(D.neighbor_in_iterator(2)) + [] + """ - return iter(set(self._backend.iterator_in_nbrs(vertex))) + yield from self._backend.iterator_in_nbrs(vertex) def neighbors_in(self, vertex): """ @@ -1233,8 +1256,31 @@ def neighbor_out_iterator(self, vertex): 1 2 3 + + TESTS: + + With multiple edges, check that the neighbors are listed only once:: + + sage: D = DiGraph([[0, 1, 2], [(0, 1), (0, 1), (1, 2) ]],multiedges=True) + sage: list(D.neighbor_out_iterator(0)) + [1] + sage: list(D.neighbor_out_iterator(1)) + [2] + sage: list(D.neighbor_out_iterator(2)) + [] + + Check that the iterator lists ``vertex`` in the presence of loop(s): + + sage: D = DiGraph([[0, 1, 2], [(0, 0), (0, 0), (1, 1)]],multiedges=True, loops=True) + sage: list(D.neighbor_out_iterator(0)) + [0] + sage: list(D.neighbor_out_iterator(1)) + [1] + sage: list(D.neighbor_out_iterator(2)) + [] + """ - return iter(set(self._backend.iterator_out_nbrs(vertex))) + yield from self._backend.iterator_out_nbrs(vertex) def neighbors_out(self, vertex): """ @@ -3061,30 +3107,30 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False, sage: g = graphs.PetersenGraph().to_directed() sage: g.all_simple_cycles(max_length=4) [[0, 1, 0], [0, 4, 0], [0, 5, 0], [1, 2, 1], [1, 6, 1], [2, 3, 2], - [2, 7, 2], [3, 8, 3], [3, 4, 3], [4, 9, 4], [5, 8, 5], [5, 7, 5], + [2, 7, 2], [3, 4, 3], [3, 8, 3], [4, 9, 4], [5, 7, 5], [5, 8, 5], [6, 8, 6], [6, 9, 6], [7, 9, 7]] sage: g.all_simple_cycles(max_length=6) [[0, 1, 0], [0, 4, 0], [0, 5, 0], [1, 2, 1], [1, 6, 1], [2, 3, 2], - [2, 7, 2], [3, 8, 3], [3, 4, 3], [4, 9, 4], [5, 8, 5], [5, 7, 5], + [2, 7, 2], [3, 4, 3], [3, 8, 3], [4, 9, 4], [5, 7, 5], [5, 8, 5], [6, 8, 6], [6, 9, 6], [7, 9, 7], [0, 1, 2, 3, 4, 0], [0, 1, 2, 7, 5, 0], [0, 1, 6, 8, 5, 0], [0, 1, 6, 9, 4, 0], - [0, 4, 9, 6, 1, 0], [0, 4, 9, 7, 5, 0], [0, 4, 3, 8, 5, 0], - [0, 4, 3, 2, 1, 0], [0, 5, 8, 3, 4, 0], [0, 5, 8, 6, 1, 0], - [0, 5, 7, 9, 4, 0], [0, 5, 7, 2, 1, 0], [1, 2, 3, 8, 6, 1], + [0, 4, 3, 2, 1, 0], [0, 4, 3, 8, 5, 0], [0, 4, 9, 6, 1, 0], + [0, 4, 9, 7, 5, 0], [0, 5, 7, 2, 1, 0], [0, 5, 7, 9, 4, 0], + [0, 5, 8, 3, 4, 0], [0, 5, 8, 6, 1, 0], [1, 2, 3, 8, 6, 1], [1, 2, 7, 9, 6, 1], [1, 6, 8, 3, 2, 1], [1, 6, 9, 7, 2, 1], - [2, 3, 8, 5, 7, 2], [2, 3, 4, 9, 7, 2], [2, 7, 9, 4, 3, 2], - [2, 7, 5, 8, 3, 2], [3, 8, 6, 9, 4, 3], [3, 4, 9, 6, 8, 3], - [5, 8, 6, 9, 7, 5], [5, 7, 9, 6, 8, 5], [0, 1, 2, 3, 8, 5, 0], + [2, 3, 4, 9, 7, 2], [2, 3, 8, 5, 7, 2], [2, 7, 5, 8, 3, 2], + [2, 7, 9, 4, 3, 2], [3, 4, 9, 6, 8, 3], [3, 8, 6, 9, 4, 3], + [5, 7, 9, 6, 8, 5], [5, 8, 6, 9, 7, 5], [0, 1, 2, 3, 8, 5, 0], [0, 1, 2, 7, 9, 4, 0], [0, 1, 6, 8, 3, 4, 0], - [0, 1, 6, 9, 7, 5, 0], [0, 4, 9, 6, 8, 5, 0], - [0, 4, 9, 7, 2, 1, 0], [0, 4, 3, 8, 6, 1, 0], - [0, 4, 3, 2, 7, 5, 0], [0, 5, 8, 3, 2, 1, 0], - [0, 5, 8, 6, 9, 4, 0], [0, 5, 7, 9, 6, 1, 0], - [0, 5, 7, 2, 3, 4, 0], [1, 2, 3, 4, 9, 6, 1], + [0, 1, 6, 9, 7, 5, 0], [0, 4, 3, 2, 7, 5, 0], + [0, 4, 3, 8, 6, 1, 0], [0, 4, 9, 6, 8, 5, 0], + [0, 4, 9, 7, 2, 1, 0], [0, 5, 7, 2, 3, 4, 0], + [0, 5, 7, 9, 6, 1, 0], [0, 5, 8, 3, 2, 1, 0], + [0, 5, 8, 6, 9, 4, 0], [1, 2, 3, 4, 9, 6, 1], [1, 2, 7, 5, 8, 6, 1], [1, 6, 8, 5, 7, 2, 1], [1, 6, 9, 4, 3, 2, 1], [2, 3, 8, 6, 9, 7, 2], - [2, 7, 9, 6, 8, 3, 2], [3, 8, 5, 7, 9, 4, 3], - [3, 4, 9, 7, 5, 8, 3]] + [2, 7, 9, 6, 8, 3, 2], [3, 4, 9, 7, 5, 8, 3], + [3, 8, 5, 7, 9, 4, 3]] The complete graph (without loops) on `4` vertices:: @@ -3102,52 +3148,52 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False, sage: g = graphs.CompleteGraph(20).to_directed() sage: g.all_simple_cycles(max_length=2) - [[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], - [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], - [0, 12, 0], [0, 13, 0], [0, 14, 0], [0, 15, 0], [0, 16, 0], - [0, 17, 0], [0, 18, 0], [0, 19, 0], [1, 2, 1], [1, 3, 1], - [1, 4, 1], [1, 5, 1], [1, 6, 1], [1, 7, 1], [1, 8, 1], [1, 9, 1], - [1, 10, 1], [1, 11, 1], [1, 12, 1], [1, 13, 1], [1, 14, 1], - [1, 15, 1], [1, 16, 1], [1, 17, 1], [1, 18, 1], [1, 19, 1], - [2, 3, 2], [2, 4, 2], [2, 5, 2], [2, 6, 2], [2, 7, 2], [2, 8, 2], - [2, 9, 2], [2, 10, 2], [2, 11, 2], [2, 12, 2], [2, 13, 2], - [2, 14, 2], [2, 15, 2], [2, 16, 2], [2, 17, 2], [2, 18, 2], - [2, 19, 2], [3, 4, 3], [3, 5, 3], [3, 6, 3], [3, 7, 3], [3, 8, 3], - [3, 9, 3], [3, 10, 3], [3, 11, 3], [3, 12, 3], [3, 13, 3], - [3, 14, 3], [3, 15, 3], [3, 16, 3], [3, 17, 3], [3, 18, 3], - [3, 19, 3], [4, 5, 4], [4, 6, 4], [4, 7, 4], [4, 8, 4], [4, 9, 4], - [4, 10, 4], [4, 11, 4], [4, 12, 4], [4, 13, 4], [4, 14, 4], - [4, 15, 4], [4, 16, 4], [4, 17, 4], [4, 18, 4], [4, 19, 4], - [5, 6, 5], [5, 7, 5], [5, 8, 5], [5, 9, 5], [5, 10, 5], - [5, 11, 5], [5, 12, 5], [5, 13, 5], [5, 14, 5], [5, 15, 5], - [5, 16, 5], [5, 17, 5], [5, 18, 5], [5, 19, 5], [6, 7, 6], - [6, 8, 6], [6, 9, 6], [6, 10, 6], [6, 11, 6], [6, 12, 6], - [6, 13, 6], [6, 14, 6], [6, 15, 6], [6, 16, 6], [6, 17, 6], - [6, 18, 6], [6, 19, 6], [7, 8, 7], [7, 9, 7], [7, 10, 7], - [7, 11, 7], [7, 12, 7], [7, 13, 7], [7, 14, 7], [7, 15, 7], - [7, 16, 7], [7, 17, 7], [7, 18, 7], [7, 19, 7], [8, 9, 8], - [8, 10, 8], [8, 11, 8], [8, 12, 8], [8, 13, 8], [8, 14, 8], - [8, 15, 8], [8, 16, 8], [8, 17, 8], [8, 18, 8], [8, 19, 8], - [9, 10, 9], [9, 11, 9], [9, 12, 9], [9, 13, 9], [9, 14, 9], - [9, 15, 9], [9, 16, 9], [9, 17, 9], [9, 18, 9], [9, 19, 9], - [10, 11, 10], [10, 12, 10], [10, 13, 10], [10, 14, 10], - [10, 15, 10], [10, 16, 10], [10, 17, 10], [10, 18, 10], - [10, 19, 10], [11, 12, 11], [11, 13, 11], [11, 14, 11], - [11, 15, 11], [11, 16, 11], [11, 17, 11], [11, 18, 11], - [11, 19, 11], [12, 13, 12], [12, 14, 12], [12, 15, 12], + [[0, 16, 0], [0, 1, 0], [0, 17, 0], [0, 2, 0], [0, 18, 0], + [0, 3, 0], [0, 19, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], + [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], [0, 12, 0], + [0, 13, 0], [0, 14, 0], [0, 15, 0], [1, 16, 1], [1, 17, 1], + [1, 2, 1], [1, 18, 1], [1, 3, 1], [1, 19, 1], [1, 4, 1], [1, 5, 1], + [1, 6, 1], [1, 7, 1], [1, 8, 1], [1, 9, 1], [1, 10, 1], [1, 11, 1], + [1, 12, 1], [1, 13, 1], [1, 14, 1], [1, 15, 1], [2, 16, 2], + [2, 17, 2], [2, 18, 2], [2, 3, 2], [2, 19, 2], [2, 4, 2], + [2, 5, 2], [2, 6, 2], [2, 7, 2], [2, 8, 2], [2, 9, 2], [2, 10, 2], + [2, 11, 2], [2, 12, 2], [2, 13, 2], [2, 14, 2], [2, 15, 2], + [3, 16, 3], [3, 17, 3], [3, 18, 3], [3, 19, 3], [3, 4, 3], + [3, 5, 3], [3, 6, 3], [3, 7, 3], [3, 8, 3], [3, 9, 3], [3, 10, 3], + [3, 11, 3], [3, 12, 3], [3, 13, 3], [3, 14, 3], [3, 15, 3], + [4, 16, 4], [4, 17, 4], [4, 18, 4], [4, 19, 4], [4, 5, 4], + [4, 6, 4], [4, 7, 4], [4, 8, 4], [4, 9, 4], [4, 10, 4], [4, 11, 4], + [4, 12, 4], [4, 13, 4], [4, 14, 4], [4, 15, 4], [5, 16, 5], + [5, 17, 5], [5, 18, 5], [5, 19, 5], [5, 6, 5], [5, 7, 5], + [5, 8, 5], [5, 9, 5], [5, 10, 5], [5, 11, 5], [5, 12, 5], + [5, 13, 5], [5, 14, 5], [5, 15, 5], [6, 16, 6], [6, 17, 6], + [6, 18, 6], [6, 19, 6], [6, 7, 6], [6, 8, 6], [6, 9, 6], + [6, 10, 6], [6, 11, 6], [6, 12, 6], [6, 13, 6], [6, 14, 6], + [6, 15, 6], [7, 16, 7], [7, 17, 7], [7, 18, 7], [7, 19, 7], + [7, 8, 7], [7, 9, 7], [7, 10, 7], [7, 11, 7], [7, 12, 7], + [7, 13, 7], [7, 14, 7], [7, 15, 7], [8, 16, 8], [8, 17, 8], + [8, 18, 8], [8, 19, 8], [8, 9, 8], [8, 10, 8], [8, 11, 8], + [8, 12, 8], [8, 13, 8], [8, 14, 8], [8, 15, 8], [9, 16, 9], + [9, 17, 9], [9, 18, 9], [9, 19, 9], [9, 10, 9], [9, 11, 9], + [9, 12, 9], [9, 13, 9], [9, 14, 9], [9, 15, 9], [10, 16, 10], + [10, 17, 10], [10, 18, 10], [10, 19, 10], [10, 11, 10], + [10, 12, 10], [10, 13, 10], [10, 14, 10], [10, 15, 10], + [11, 16, 11], [11, 17, 11], [11, 18, 11], [11, 19, 11], + [11, 12, 11], [11, 13, 11], [11, 14, 11], [11, 15, 11], [12, 16, 12], [12, 17, 12], [12, 18, 12], [12, 19, 12], - [13, 14, 13], [13, 15, 13], [13, 16, 13], [13, 17, 13], - [13, 18, 13], [13, 19, 13], [14, 15, 14], [14, 16, 14], - [14, 17, 14], [14, 18, 14], [14, 19, 14], [15, 16, 15], - [15, 17, 15], [15, 18, 15], [15, 19, 15], [16, 17, 16], - [16, 18, 16], [16, 19, 16], [17, 18, 17], [17, 19, 17], - [18, 19, 18]] + [12, 13, 12], [12, 14, 12], [12, 15, 12], [13, 16, 13], + [13, 17, 13], [13, 18, 13], [13, 19, 13], [13, 14, 13], + [13, 15, 13], [14, 16, 14], [14, 17, 14], [14, 18, 14], + [14, 19, 14], [14, 15, 14], [15, 16, 15], [15, 17, 15], + [15, 18, 15], [15, 19, 15], [16, 17, 16], [16, 18, 16], + [16, 19, 16], [17, 18, 17], [17, 19, 17], [18, 19, 18]] + sage: g = graphs.CompleteGraph(20).to_directed() sage: g.all_simple_cycles(max_length=2, starting_vertices=[0]) - [[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], + [[0, 16, 0], [0, 1, 0], [0, 17, 0], [0, 2, 0], [0, 18, 0], + [0, 3, 0], [0, 19, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], - [0, 12, 0], [0, 13, 0], [0, 14, 0], [0, 15, 0], [0, 16, 0], - [0, 17, 0], [0, 18, 0], [0, 19, 0]] + [0, 12, 0], [0, 13, 0], [0, 14, 0], [0, 15, 0]] One may prefer to distinguish equivalent cycles having distinct starting vertices (compare the following examples):: diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index 7d89a1ce02f..7ae9fe248fa 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -78,9 +78,9 @@ class DiGraphGenerators: A class consisting of constructors for several common digraphs, including orderly generation of isomorphism class representatives. - A list of all graphs and graph structures in this database is - available via tab completion. Type "digraphs." and then hit tab to - see which graphs are available. + A list of all graphs and graph structures in this database is available via + tab completion. Type ``digraphs.`` and then hit :kbd:`Tab` to see which + digraphs are available. The docstrings include educational information about each named digraph with the hopes that this class can be used as a reference. @@ -567,7 +567,7 @@ def tournaments_nauty(self, n, - ``options`` -- string; anything else that should be forwarded as input to Nauty's genbg. See its documentation for more information : - ``_. + ``_. EXAMPLES:: @@ -639,7 +639,7 @@ def nauty_directg(self, graphs, options="", debug=False): r""" Return an iterator yielding digraphs using nauty's ``directg`` program. - Description from directg --help: + Description from ``directg --help``: Read undirected graphs and orient their edges in all possible ways. Edges can be oriented in either or both directions (3 possibilities). Isomorphic directed graphs derived from the same input are suppressed. @@ -651,8 +651,8 @@ def nauty_directg(self, graphs, options="", debug=False): :class:`Graph`. The graph6 string of these graphs is used as an input for ``directg``. - - ``options`` (str) -- a string passed to directg as if it was run at - a system command line. Available options from directg --help:: + - ``options`` -- a string passed to ``directg`` as if it was run at + a system command line. Available options from ``directg --help``:: -e | -e: specify a value or range of the total number of arcs -o orient each edge in only one direction, never both @@ -664,8 +664,8 @@ def nauty_directg(self, graphs, options="", debug=False): the part number (first is 0) and the second is the number of parts. Splitting is done per input graph independently. - - ``debug`` -- boolean (default: ``False``); if ``True`` - directg standard error and standard output are displayed. + - ``debug`` -- boolean (default: ``False``); if ``True`` ``directg`` + standard error and standard output are displayed. EXAMPLES:: @@ -807,7 +807,8 @@ def Circuit(self, n): r""" Return the circuit on `n` vertices. - The circuit is an oriented ``CycleGraph``. + The circuit is an oriented + :meth:`~sage.graphs.graph_generators.GraphGenerators.CycleGraph`. EXAMPLES: @@ -838,8 +839,8 @@ def Circulant(self, n, integers): - ``n`` -- integer; number of vertices - ``integers`` -- iterable container (list, set, etc.) of integers such - that there is an edge from `i` to `j` if and only if ``(j-i)%n in - integers`` + that there is an edge from `i` to `j` if and only if `(j-i) \pmod{n}` + is an integer EXAMPLES:: diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index ea70f890005..85a1d1ee263 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -1750,6 +1750,11 @@ def diameter(G, algorithm=None, source=None): error if the initial vertex is not in `G`. This parameter is not used when ``algorithm=='standard'``. + .. NOTE:: + As the graph is first converted to a short_digraph, all complexity + have an extra `O(m+n)` for ``SparseGraph`` and `O(n^2)` for + ``DenseGraph``. + EXAMPLES:: sage: from sage.graphs.distances_all_pairs import diameter @@ -2278,6 +2283,14 @@ def szeged_index(G, algorithm=None): By default (``None``), the ``"low"`` algorithm is used for graphs and the ``"high"`` algorithm for digraphs. + .. NOTE:: + As the graph is converted to a short_digraph, the complexity for the + case ``algorithm == "high"`` has an extra `O(m+n)` for ``SparseGraph`` + and `O(n^2)` for ``DenseGraph``. If ``algorithm == "low"``, the extra + complexity is `O(n + m\log{m})` for ``SparseGraph`` and `O(n^2\log{m})` + for ``DenseGraph`` (because ``init_short_digraph`` is called with + ``sort_neighbors=True``). + EXAMPLES: True for any connected graph [KRG1996]_:: @@ -2351,7 +2364,7 @@ def szeged_index(G, algorithm=None): if G.is_directed() and not G.is_strongly_connected(): raise ValueError("the Szeged index is defined for " "strongly connected digraphs only") - if G.is_directed() and algorithm is "low": + if G.is_directed() and algorithm == "low": raise ValueError("the 'low' algorithm cannot be used on digraphs") if algorithm is None: @@ -2360,7 +2373,7 @@ def szeged_index(G, algorithm=None): elif algorithm not in ["low", "high"]: raise ValueError(f"unknown algorithm '{algorithm}'") - if algorithm is "low" and (G.has_loops() or G.has_multiple_edges()): + if algorithm == "low" and (G.has_loops() or G.has_multiple_edges()): raise ValueError("the 'low' algorithm is for simple connected " "undirected graphs only") @@ -2370,7 +2383,7 @@ def szeged_index(G, algorithm=None): cdef short_digraph sd cdef uint64_t s - if algorithm is "low": + if algorithm == "low": init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G), sort_neighbors=True) s = c_szeged_index_low_memory(sd) else: diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 1d542bc17f6..9776b561748 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -101,7 +101,7 @@ def ButterflyGraph(): .. SEEALSO:: - - :meth:`GraphGenerators.FriendshipGraph` + - :meth:`~sage.graphs.graph_generators.GraphGenerators.FriendshipGraph` EXAMPLES: @@ -161,7 +161,7 @@ def CircularLadderGraph(n): displayed as an inner and outer cycle pair, with the first `n` nodes drawn on the inner circle. The first (0) node is drawn at the top of the inner-circle, moving clockwise after that. The outer circle is drawn with - the `(n+1)`th node at the top, then counterclockwise as well. + the `(n+1)`-th node at the top, then counterclockwise as well. When `n == 2`, we rotate the outer circle by an angle of `\pi/8` to ensure that all edges are visible (otherwise the 4 vertices of the graph would be placed on a single line). @@ -401,15 +401,28 @@ def CompleteGraph(n): 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): - """ - Constructs and returns a correlation graph with a node corresponding to each sequence in `seqs`. + r""" + Return a correlation graph with a node per sequence in ``seqs``. - Edges are added between nodes where the corresponding sequences have a correlation coeffecient greater than alpha. + Edges are added between nodes where the corresponding sequences have a + correlation coeffecient greater than alpha. - If include_anticorrelation is true, then edges are also added between nodes with correlation coeffecient less than -alpha. + If ``include_anticorrelation`` is ``True``, then edges are also added + between nodes with correlation coefficient less than ``-alpha``. - EXAMPLES: + INPUT: + + - ``seqs`` -- list of sequences, taht is a list of lists + + - ``alpha`` -- float; threshold on the correlation coefficient between two + sequences for adding an edge + + - ``include_anticorrelation`` -- boolean; whether to add edges between nodes + with correlation coefficient less than ``-alpha`` or not + + EXAMPLES:: sage: # needs numpy sage: from sage.graphs.generators.basic import CorrelationGraph @@ -423,7 +436,6 @@ 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)] - """ from numpy import corrcoef from sage.matrix.constructor import Matrix @@ -442,6 +454,7 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): # call graph constructor return Graph(adjacency_matrix, format="adjacency_matrix", name="Correlation Graph") + def CompleteBipartiteGraph(p, q, set_position=True): r""" Return a Complete Bipartite Graph on `p + q` vertices. @@ -858,7 +871,6 @@ def Toroidal6RegularGrid2dGraph(p, q): ... ValueError: parameters p and q must be integers larger than 3 """ - if p <= 3 or q <= 3: raise ValueError("parameters p and q must be integers larger than 3") @@ -1148,6 +1160,90 @@ def LadderGraph(n): return G +def MoebiusLadderGraph(n): + r""" + Return a Möbius ladder graph with `2n` nodes + + A Möbius ladder graph of order `2n` is a ladder graph of the same order + that is connected at the ends with a single twist, i.e., a ladder graph + bent around so that top meets bottom with a single twist. Alternatively, + it can be described as a single cycle graph (of order `2n`) with the + addition of edges (called `rungs`) joining the antipodal pairs of nodes. + Also, note that the Möbius ladder graph ``graphs.MoebiusLadderGraph(n)`` is + precisely the same graph as the circulant graph + ``graphs.CirculantGraph(2 * n, [1, n])``. + + PLOTTING: + + Upon construction, the position dictionary is filled to override the + spring-layout algorithm. By convention, each Möbius ladder graph will be + displayed with the first (0) node at the top, with the rest following in a + counterclockwise manner. + + INPUT: + + - ``n`` -- a non negative integer; number of nodes is `2n` + + OUTPUT: + + - ``G`` -- a Möbius ladder graph of order `2n`; note that a + :class:`ValueError` is returned if `n < 0` + + EXAMPLES: + + Construct and show a Möbius ladder graph with 26 nodes:: + + sage: g = graphs.MoebiusLadderGraph(13) + sage: g.show() # long time # needs sage.plot + + Create several Möbius ladder graphs in a Sage graphics array:: + + sage: # needs sage.plots + sage: g = [] + sage: j = [] + sage: for i in range(9): + ....: k = graphs.MoebiusLadderGraph(i+3) + ....: g.append(k) + sage: for i in range(3): + ....: n = [] + ....: for m in range(3): + ....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) + ....: j.append(n) + sage: G = graphics_array(j) + sage: G.show() # long time + + TESTS: + + The input parameter must be a non negative integer:: + + sage: G = graphs.MoebiusLadderGraph(-1) + Traceback (most recent call last): + ... + ValueError: parameter n must be a non negative integer + + REFERENCES: + + - :wikipedia:`Möbius_ladder` + + .. SEEALSO:: + :meth:`~sage.graphs.graph_generators.GraphGenerators.LadderGraph`, + :meth:`~sage.graphs.graph_generators.GraphGenerators.CircularLadderGraph`, + :meth:`~sage.graphs.graph_generators.GraphGenerators.CirculantGraph` + + AUTHORS: + + - Janmenjaya Panda (2024-05-26) + """ + if n < 0: + raise ValueError("parameter n must be a non negative integer") + + G = Graph(2 * n, 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): r""" Return a path graph with `n` nodes. diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index 79828c57e98..23a52f57e5d 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -591,8 +591,9 @@ def UstimenkoGraph(const int m, const int q): Return the Ustimenko graph with parameters `(m, q)`. This is the distance 1 or 2 graph of the dual polar graph `C_{m-1}(q)`. - The graph is distance-regular with classical with parameters - `(d,q^2, qbinom(3,1,q) -1, qbinom(m+1,1,q) -1)` + The graph is distance-regular with parameters + `(d,q^2, \binom{3}{1}_q -1, \binom{m+1}{1}_q -1)`, + where `\binom{n}{k}_q` is the `q`-binomial coefficient. INPUT: @@ -833,7 +834,7 @@ def HermitianFormsGraph(const int n, const int r): r""" Return the Hermitian forms graph with the given parameters. - We build a graph whose vertices are all ``n``x``n`` Hermitian matrices + We build a graph whose vertices are all `n \times n` Hermitian matrices over ``GF(r^2)``. Two vertices are adjacent if the difference of the two vertices has rank 1. diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 724d94eedeb..c7e1c031ebf 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -414,16 +414,16 @@ def EgawaGraph(p, s): def HammingGraph(n, q, X=None): r""" - Returns the Hamming graph with parameters ``n``, ``q`` over ``X``. + Return the Hamming graph with parameters `n`, `q` over `X`. Hamming graphs are graphs over the cartesian product of n copies - of ``X``, where `q = |X|`, where the vertices, labelled with the + of `X`, where `q = |X|`, where the vertices, labelled with the corresponding tuple in `X^n`, are connected if the Hamming distance between their labels is 1. All Hamming graphs are regular, vertex-transitive and distance-regular. Hamming graphs with parameters `(1,q)` represent the complete graph - with q vertices over the set ``X``. + with q vertices over the set `X`. INPUT: @@ -443,8 +443,7 @@ def HammingGraph(n, q, X=None): EXAMPLES: - Every Hamming graph is distance-regular, regular and - vertex-transitive. :: + Every Hamming graph is distance-regular, regular and vertex-transitive:: sage: g = graphs.HammingGraph(3, 7) sage: g.is_distance_regular() @@ -454,15 +453,15 @@ def HammingGraph(n, q, X=None): sage: g.is_vertex_transitive() # needs sage.groups True - A Hamming graph with parameters (1,q) is isomorphic to the - Complete graph with parameter q. :: + A Hamming graph with parameters `(1,q)` is isomorphic to the + Complete graph with parameter `q`:: sage: g = graphs.HammingGraph(1, 23) sage: g.is_isomorphic(graphs.CompleteGraph(23)) True - If a parameter ``q`` is provided which is not equal to ``X``'s - cardinality, an exception is raised. :: + If a parameter `q` is provided which is not equal to `X`'s + cardinality, an exception is raised:: sage: X = ['a','b','c','d','e'] sage: g = graphs.HammingGraph(2, 3, X) @@ -597,11 +596,12 @@ def BalancedTree(r, h): def BarbellGraph(n1, n2): r""" - Returns a barbell graph with ``2*n1 + n2`` nodes. The argument ``n1`` - must be greater than or equal to 2. + Returns a barbell graph with `2*n_1 + n_2` nodes. + + The argument `n_1` must be greater than or equal to 2. A barbell graph is a basic structure that consists of a path graph - of order ``n2`` connecting two complete graphs of order ``n1`` each. + of order `n_2` connecting two complete graphs of order `n_1` each. INPUT: @@ -613,8 +613,8 @@ def BarbellGraph(n1, n2): OUTPUT: - A barbell graph of order ``2*n1 + n2``. A :class:`ValueError` is - returned if ``n1 < 2`` or ``n2 < 0``. + A barbell graph of order `2*n_1 + n_2`. A :class:`ValueError` is + returned if `n_1 < 2` or `n_2 < 0`. PLOTTING: @@ -622,9 +622,9 @@ def BarbellGraph(n1, n2): override the spring-layout algorithm. By convention, each barbell graph will be displayed with the two complete graphs in the lower-left and upper-right corners, with the path graph connecting - diagonally between the two. Thus the ``n1``-th node will be drawn at a + diagonally between the two. Thus the `n_1`-th node will be drawn at a 45 degree angle from the horizontal right center of the first - complete graph, and the ``n1 + n2 + 1``-th node will be drawn 45 + complete graph, and the `n_1 + n_2 + 1`-th node will be drawn 45 degrees below the left horizontal center of the second complete graph. EXAMPLES: @@ -635,9 +635,9 @@ def BarbellGraph(n1, n2): Barbell graph: Graph on 22 vertices sage: g.show() # long time # needs sage.plot - An ``n1 >= 2``, ``n2 >= 0`` barbell graph has order ``2*n1 + n2``. It - has the complete graph on ``n1`` vertices as a subgraph. It also has - the path graph on ``n2`` vertices as a subgraph. :: + An `n_1 \geq 2`, `n_2 \geq 0` barbell graph has order `2*n_1 + n_2`. It + has the complete graph on `n_1` vertices as a subgraph. It also has + the path graph on `n_2` vertices as a subgraph. :: sage: n1 = randint(2, 2*10^2) sage: n2 = randint(0, 2*10^2) @@ -669,7 +669,7 @@ def BarbellGraph(n1, n2): sage: g.girth() == 3 True - The input ``n1`` must be `\geq 2`:: + The input `n_1` must be `\geq 2`:: sage: graphs.BarbellGraph(1, randint(0, 10^6)) Traceback (most recent call last): @@ -680,7 +680,7 @@ def BarbellGraph(n1, n2): ... ValueError: invalid graph description, n1 should be >= 2 - The input ``n2`` must be `\geq 0`:: + The input `n_2` must be `\geq 0`:: sage: graphs.BarbellGraph(randint(2, 10^6), -1) Traceback (most recent call last): @@ -714,14 +714,14 @@ def BarbellGraph(n1, n2): def LollipopGraph(n1, n2): r""" - Returns a lollipop graph with n1+n2 nodes. + Returns a lollipop graph with `n_1 + n_2` nodes. - A lollipop graph is a path graph (order n2) connected to a complete - graph (order n1). (A barbell graph minus one of the bells). + A lollipop graph is a path graph (order `n_2`) connected to a complete + graph (order `n_1`). (A barbell graph minus one of the bells). PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the complete - graph will be drawn in the lower-left corner with the (n1)th node + graph will be drawn in the lower-left corner with the `n_1`-th node at a 45 degree angle above the right horizontal center of the complete graph, leading directly into the path graph. @@ -752,14 +752,14 @@ def LollipopGraph(n1, n2): sage: graphs.LollipopGraph(0, 0).is_isomorphic(graphs.EmptyGraph()) True - The input ``n1`` must be `\geq 0`:: + The input `n_1` must be `\geq 0`:: sage: graphs.LollipopGraph(-1, randint(0, 10^6)) Traceback (most recent call last): ... ValueError: invalid graph description, n1 should be >= 0 - The input ``n2`` must be `\geq 0`:: + The input `n_2` must be `\geq 0`:: sage: graphs.LollipopGraph(randint(2, 10^6), -1) Traceback (most recent call last): @@ -787,14 +787,14 @@ def LollipopGraph(n1, n2): def TadpoleGraph(n1, n2): r""" - Return a tadpole graph with n1+n2 nodes. + Return a tadpole graph with `n_1 + n_2` nodes. - A tadpole graph is a path graph (order n2) connected to a cycle graph - (order n1). + A tadpole graph is a path graph (order `n_2`) connected to a cycle graph + (order `n_1`). PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the cycle graph will be drawn - in the lower-left corner with the (n1)th node at a 45 degree angle above + in the lower-left corner with the `n_1`-th node at a 45 degree angle above the right horizontal center of the cycle graph, leading directly into the path graph. @@ -819,14 +819,14 @@ def TadpoleGraph(n1, n2): sage: graphs.TadpoleGraph(n1, 0).is_isomorphic(graphs.CycleGraph(n1)) True - The input ``n1`` must be `\geq 3`:: + The input `n_1` must be `\geq 3`:: sage: graphs.TadpoleGraph(2, randint(0, 10^6)) Traceback (most recent call last): ... ValueError: invalid graph description, n1 should be >= 3 - The input ``n2`` must be `\geq 0`:: + The input `n_2` must be `\geq 0`:: sage: graphs.TadpoleGraph(randint(2, 10^6), -1) Traceback (most recent call last): @@ -1068,17 +1068,17 @@ def chang_graphs(): def CirculantGraph(n, adjacency): r""" - Returns a circulant graph with n nodes. + Returns a circulant graph with `n` nodes. A circulant graph has the property that the vertex `i` is connected - with the vertices `i+j` and `i-j` for each j in ``adjacency``. + with the vertices `i+j` and `i-j` for each `j` in ``adjacency``. INPUT: - ``n`` -- number of vertices in the graph - - ``adjacency`` -- the list of j values + - ``adjacency`` -- the list of `j` values PLOTTING: Upon construction, the position dictionary is filled to @@ -1086,12 +1086,12 @@ def CirculantGraph(n, adjacency): graph will be displayed with the first (0) node at the top, with the rest following in a counterclockwise manner. - Filling the position dictionary in advance adds O(n) to the + Filling the position dictionary in advance adds `O(n)` to the constructor. .. SEEALSO:: - * :meth:`sage.graphs.generic_graph.GenericGraph.is_circulant` + * :meth:`~sage.graphs.generic_graph.GenericGraph.is_circulant` -- checks whether a (di)graph is circulant, and/or returns all possible sets of parameters. @@ -1909,12 +1909,12 @@ def RoseWindowGraph(n, a, r): PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the rose window graphs are - displayed as an inner and outer cycle pair, with the first n nodes drawn on - the outer circle. The first (0) node is drawn at the top of the + displayed as an inner and outer cycle pair, with the first `n` nodes drawn + on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The inner circle is drawn - with the (n)th node at the top, then counterclockwise as well. Vertices in + with the (`n`)th node at the top, then counterclockwise as well. Vertices in the outer circle are connected in the circular manner, vertices in the inner - circle are connected when their label have difference `r` (mod n). Vertices + circle are connected when their label have difference `r \pmod{n}`. Vertices on the outer rim are connected with the vertices on the inner rim when they are at the same position and when they are `a` apart. @@ -2003,12 +2003,12 @@ def TabacjnGraph(n, a, b, r): PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the rose window graphs are - displayed as an inner and outer cycle pair, with the first n nodes drawn on - the outer circle. The first (0) node is drawn at the top of the + displayed as an inner and outer cycle pair, with the first `n` nodes drawn + on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The inner circle is drawn - with the (n)th node at the top, then counterclockwise as well. Vertices in + with the (`n`)th node at the top, then counterclockwise as well. Vertices in the outer circle are connected in the circular manner, vertices in the inner - circle are connected when their label have difference `r` (mod n). Vertices + circle are connected when their label have difference `r \pmod{n}`. Vertices on the outer rim are connected with the vertices on the inner rim when they are at the same position and when they are `a` and `b` apart. @@ -2099,8 +2099,7 @@ def HararyGraph(k, n): Harary graphs are minimal `k`-connected graphs on `n` vertices. The construction provided uses the method CirculantGraph. For more - details, see the book D. B. West, Introduction to Graph Theory, 2nd - Edition, Prentice Hall, 2001, p. 150--151; or the `MathWorld article on + details, see the book [West2001]_ or the `MathWorld article on Harary graphs `_. EXAMPLES: @@ -2223,26 +2222,26 @@ def LCFGraph(n, shift_list, repeats): r""" Return the cubic graph specified in LCF notation. - LCF (Lederberg-Coxeter-Fruchte) notation is a concise way of - describing cubic Hamiltonian graphs. The way a graph is constructed - is as follows. Since there is a Hamiltonian cycle, we first create - a cycle on n nodes. The variable shift_list = [s_0, s_1, ..., - s_k-1] describes edges to be created by the following scheme: for - each i, connect vertex i to vertex (i + s_i). Then, repeats - specifies the number of times to repeat this process, where on the - jth repeat we connect vertex (i + j\*len(shift_list)) to vertex ( - i + j\*len(shift_list) + s_i). + LCF (Lederberg-Coxeter-Fruchte) notation is a concise way of describing + cubic Hamiltonian graphs. The way a graph is constructed is as + follows. Since there is a Hamiltonian cycle, we first create a cycle on `n` + nodes. The variable ``shift_list`` = `[s_0, s_1, ..., s_{k-1}]` describes + edges to be created by the following scheme: for each `i \in \{0, 1, \dots, + k-1\}`, connect vertex `i` to vertex `(i + s_i) \pmod{n}`. Then, ``repeats`` + specifies the number of times to repeat this process, where on the `j`-th + repeat we connect vertex `(i + j k) \pmod{n}` to vertex `(i + j k + s_i) + \pmod{n}`. - INPUT: + For more details, see the :wikipedia:`LCF_notation` and [Fru1977]_, + [Gru2003]_ pp. 357-365, and [Led1965]_. + INPUT: - ``n`` -- the number of nodes. - ``shift_list`` -- a list of integer shifts mod `n`. - - ``repeats`` -- the number of times to repeat the - process. - + - ``repeats`` -- the number of times to repeat the process. EXAMPLES:: @@ -2273,23 +2272,8 @@ def LCFGraph(n, shift_list, repeats): 3 sage: G.show() # long time # needs sage.plot - PLOTTING: LCF Graphs are plotted as an n-cycle with edges in the + PLOTTING: LCF Graphs are plotted as an `n`-cycle with edges in the middle, as described above. - - REFERENCES: - - - [1] Frucht, R. "A Canonical Representation of Trivalent - Hamiltonian Graphs." J. Graph Th. 1, 45-60, 1976. - - - [2] Grunbaum, B. Convex Polytope es. New York: Wiley, - pp. 362-364, 1967. - - - [3] Lederberg, J. 'DENDRAL-64: A System for Computer - Construction, Enumeration and Notation of Organic Molecules - as Tree Structures and Cyclic Graphs. Part II. Topology of - Cyclic Graphs.' Interim Report to the National Aeronautics - and Space Administration. Grant NsG 81-60. December 15, - 1965. http://profiles.nlm.nih.gov/BB/A/B/I/U/_/bbabiu.pdf. """ import networkx G = Graph(networkx.LCF_graph(n, shift_list, repeats), name="LCF Graph") @@ -2319,6 +2303,8 @@ def MycielskiGraph(k=1, relabel=True): `w_i`-vertices. Finally, vertex `w_i` is adjacent to vertex `v_j` iff `v_i` is adjacent to `v_j`. + For more details, see the :wikipedia:`Mycielskian`. + INPUT: - ``k`` Number of steps in the construction process. @@ -2342,13 +2328,6 @@ def MycielskiGraph(k=1, relabel=True): sage: g = graphs.MycielskiGraph(4) sage: g.is_isomorphic(graphs.GrotzschGraph()) True - - REFERENCES: - - - [1] Weisstein, Eric W. "Mycielski Graph." - From MathWorld--A Wolfram Web Resource. - http://mathworld.wolfram.com/MycielskiGraph.html - """ g = Graph() g.name("Mycielski Graph " + str(k)) @@ -2418,21 +2397,21 @@ def MycielskiStep(g): def NKStarGraph(n, k): r""" - Returns the (n,k)-star graph. + Returns the `(n,k)`-star graph. - The vertices of the (n,k)-star graph are the set of all arrangements of - n symbols into labels of length k. There are two adjacency rules for - the (n,k)-star graph. First, two vertices are adjacent if one can be - obtained from the other by swapping the first symbol with another - symbol. Second, two vertices are adjacent if one can be obtained from - the other by swapping the first symbol with an external symbol (a - symbol not used in the original label). + The vertices of the `(n,k)`-star graph are the set of all arrangements of + `n` symbols into labels of length `k`. There are two adjacency rules for the + `(n,k)`-star graph. First, two vertices are adjacent if one can be obtained + from the other by swapping the first symbol with another symbol. Second, two + vertices are adjacent if one can be obtained from the other by swapping the + first symbol with an external symbol (a symbol not used in the original + label). INPUT: - - ``n`` + - ``n`` -- integer; number of symbols - - ``k`` + - ``k`` -- integer; length of the labels of the vertices EXAMPLES:: @@ -2442,9 +2421,7 @@ def NKStarGraph(n, k): REFERENCES: - - Wei-Kuo, Chiang, and Chen Rong-Jaye. "The (n, k)-star graph: A - generalized star graph." Information Processing Letters 56, - no. 5 (December 8, 1995): 259-264. + [CC1995]_ AUTHORS: @@ -2483,15 +2460,15 @@ def NKStarGraph(n, k): def NStarGraph(n): r""" - Returns the n-star graph. + Returns the `n`-star graph. - The vertices of the n-star graph are the set of permutations on n + The vertices of the `n`-star graph are the set of permutations on `n` symbols. There is an edge between two vertices if their labels differ only in the first and one other position. INPUT: - - ``n`` + - ``n`` -- integer; number of symbols EXAMPLES:: @@ -2501,9 +2478,7 @@ def NStarGraph(n): REFERENCES: - - S.B. Akers, D. Horel and B. Krishnamurthy, The star graph: An - attractive alternative to the previous n-cube. In: Proc. Internat. - Conf. on Parallel Processing (1987), pp. 393--400. + [AHK1994]_ AUTHORS: @@ -2706,7 +2681,7 @@ def SquaredSkewHadamardMatrixGraph(n): def SwitchedSquaredSkewHadamardMatrixGraph(n): r""" A strongly regular graph in Seidel switching class of - `SquaredSkewHadamardMatrixGraph` + :meth:`~sage.graphs.graph_generators.GraphGenerators.SquaredSkewHadamardMatrixGraph`. A strongly regular graph in the :meth:`Seidel switching ` class of the disjoint union of a 1-vertex graph @@ -3437,9 +3412,9 @@ def WheelGraph(n): displayed with the first (0) node in the center, the second node at the top, and the rest following in a counterclockwise manner. - With the wheel graph, we see that it doesn't take a very large n at all for - the spring-layout to give a counter-intuitive display. (See Graphics Array - examples below). + With the wheel graph, we see that it doesn't take a very large `n` at all + for the spring-layout to give a counter-intuitive display. (See Graphics + Array examples below). EXAMPLES: @@ -3779,7 +3754,7 @@ def RingedTree(k, vertex_labels=True): More precisely, in each layer of the binary tree (i.e. a layer is the set of vertices `[2^i...2^{i+1}-1]`) two vertices `u,v` are adjacent if `u=v+1` or - if `u=2^i` and `v=`2^{i+1}-1`. + if `u=2^i` and `v=2^{i+1}-1`. Ringed trees are defined in [CFHM2013]_. diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 64a5da536c1..6faf8e2c838 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -660,9 +660,9 @@ def RandomBoundedToleranceGraph(n, seed=None): def RandomGNM(n, m, dense=False, seed=None): - """ - Returns a graph randomly picked out of all graphs on n vertices - with m edges. + r""" + Return a graph randomly picked out of all graphs on `n` vertices with `m` + edges. INPUT: @@ -683,7 +683,7 @@ def RandomGNM(n, m, dense=False, seed=None): sage: graphs.RandomGNM(5, 10).edges(sort=True, labels=False) # needs networkx [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] - We plot a random graph on 12 nodes with m = 12:: + We plot a random graph on 12 nodes and 12 edges:: sage: gnm = graphs.RandomGNM(12, 12) # needs networkx sage: gnm.show() # long time # needs networkx sage.plot @@ -1216,9 +1216,9 @@ def RandomChordalGraph(n, algorithm="growing", k=None, l=None, f=None, s=None, s .. SEEALSO:: - - :meth:`~sage.graphs.graph_generators.growing_subtrees` - - :meth:`~sage.graphs.graph_generators.connecting_nodes` - - :meth:`~sage.graphs.graph_generators.pruned_tree` + - :meth:`~sage.graphs.generators.random.growing_subtrees` + - :meth:`~sage.graphs.generators.random.connecting_nodes` + - :meth:`~sage.graphs.generators.random.pruned_tree` - :wikipedia:`Chordal_graph` - :meth:`~sage.graphs.generic_graph.GenericGraph.is_chordal` - :meth:`~sage.graphs.graph_generators.GraphGenerators.IntersectionGraph` @@ -1280,12 +1280,12 @@ def RandomChordalGraph(n, algorithm="growing", k=None, l=None, f=None, s=None, s def RandomLobster(n, p, q, seed=None): - """ - Returns a random lobster. + r""" + Return a random lobster. A lobster is a tree that reduces to a caterpillar when pruning all leaf vertices. A caterpillar is a tree that reduces to a path when - pruning all leaf vertices (q=0). + pruning all leaf vertices (`q=0`). INPUT: @@ -1336,14 +1336,14 @@ def RandomTree(n, seed=None): Returns a random tree on `n` nodes numbered `0` through `n-1`. By Cayley's theorem, there are `n^{n-2}` trees with vertex - set `\{0,1,...,n-1\}`. This constructor chooses one of these uniformly + set `\{0,1,\dots,n-1\}`. This constructor chooses one of these uniformly at random. ALGORITHM: The algorithm works by generating an `(n-2)`-long random sequence of numbers chosen independently and uniformly - from `\{0,1,\ldots,n-1\}` and then applies an inverse + from `\{0,1,\dots,n-1\}` and then applies an inverse Prufer transformation. INPUT: @@ -1733,16 +1733,19 @@ def RandomToleranceGraph(n, seed=None): Return a random tolerance graph. The random tolerance graph is built from a random tolerance representation - by using the function `ToleranceGraph`. This representation is a list - `((l_0,r_0,t_0), (l_1,r_1,t_1), ..., (l_k,r_k,t_k))` where `k = n-1` and - `I_i = (l_i,r_i)` denotes a random interval and `t_i` a random positive - value. The width of the representation is limited to `n^2 * 2^n`. + by using the function + :meth:`~sage.graphs.generators.intersection.ToleranceGraph`. This + representation is a list `((l_0,r_0,t_0), (l_1,r_1,t_1), ..., + (l_k,r_k,t_k))` where `k = n-1` and `I_i = (l_i,r_i)` denotes a random + interval and `t_i` a random positive value. The width of the representation + is limited to `n^2 * 2^n`. .. NOTE:: - The vertices are named 0, 1, ..., n-1. The tolerance representation used - to create the graph is saved with the graph and can be recovered using - ``get_vertex()`` or ``get_vertices()``. + The vertices are named `0, 1, \cdots, n-1`. The tolerance representation + used to create the graph is saved with the graph and can be recovered + using :meth:`~sage.graphs.generic_graph.GenericGraph.get_vertex` or + :meth:`~sage.graphs.generic_graph.GenericGraph.get_vertices`. INPUT: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index f1eaa816d6c..50b1905b7b0 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -2925,8 +2925,8 @@ def GritsenkoGraph(): r""" Return SRG(65, 32, 15, 16) constructed by Gritsenko. - We took the adjacency matrix from O.Gritsenko's [Gri2021]_ and extracted orbits - of the automorphism group on the edges. + We took the adjacency matrix from O. Gritsenko's [Gri2021]_ and extracted + orbits of the automorphism group on the edges. EXAMPLES:: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index d3d6a4e8b0c..063931ae274 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -4572,8 +4572,9 @@ def eulerian_orientation(self): has no non-oriented edge (this vertex must have odd degree), the walk resumes at another vertex of odd degree, if any. - This algorithm has complexity `O(m)`, where `m` is the number of edges - in the graph. + This algorithm has complexity `O(n+m)` for ``SparseGraph`` and `O(n^2)` + for ``DenseGraph``, where `m` is the number of edges in the graph and + `n` is the number of vertices in the graph. EXAMPLES: @@ -14905,7 +14906,8 @@ def is_chordal(self, certificate=False, algorithm="B"): ALGORITHM: This method implements the algorithm proposed in [RT1975]_ for the - recognition of chordal graphs with time complexity in `O(m)`. The + recognition of chordal graphs. The time complexity of this algorithm is + `O(n+m)` for ``SparseGraph`` and `O(n^2)` for ``DenseGraph``. The algorithm works through computing a Lex BFS on the graph, then checking whether the order is a Perfect Elimination Order by computing for each vertex `v` the subgraph induced by its non-deleted neighbors, then @@ -19040,13 +19042,13 @@ def depth_first_search(self, start, ignore_direction=False, sage: D.add_path([22, 23, 24, 5]) sage: D.add_path([5, 33, 34, 35]) sage: list(D.depth_first_search(5, neighbors=D.neighbors_in)) - [5, 4, 3, 2, 1, 0, 24, 23, 22] + [5, 24, 23, 22, 4, 3, 2, 1, 0] sage: list(D.breadth_first_search(5, neighbors=D.neighbors_in)) - [5, 24, 4, 23, 3, 22, 2, 1, 0] + [5, 4, 24, 3, 23, 2, 22, 1, 0] sage: list(D.depth_first_search(5, neighbors=D.neighbors_out)) - [5, 6, 7, 8, 9, 33, 34, 35] + [5, 33, 34, 35, 6, 7, 8, 9] sage: list(D.breadth_first_search(5, neighbors=D.neighbors_out)) - [5, 33, 6, 34, 7, 35, 8, 9] + [5, 6, 33, 7, 34, 8, 35, 9] You can get edges of the DFS tree instead of the vertices using the ``edges`` parameter:: diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 4069c6a079d..3eda130f4d8 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -3047,7 +3047,8 @@ def strong_orientation(self): .. NOTE:: - This method assumes the graph is connected. - - This algorithm works in O(m). + - This time complexity is `O(n+m)` for ``SparseGraph`` and `O(n^2)` + for ``DenseGraph`` . .. SEEALSO:: diff --git a/src/sage/graphs/graph_decompositions/clique_separators.pyx b/src/sage/graphs/graph_decompositions/clique_separators.pyx index ed86654f595..0bd02e3b5db 100644 --- a/src/sage/graphs/graph_decompositions/clique_separators.pyx +++ b/src/sage/graphs/graph_decompositions/clique_separators.pyx @@ -172,6 +172,12 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal :meth:`~sage.graphs.traversals.maximum_cardinality_search_M` graph traversal and has time complexity in `O(|V|\cdot|E|)`. + .. NOTE:: + As the graph is converted to a short_digraph (with + ``sort_neighbors=True``), the complexity has an extra + `O(|V|+|E|\log{|E|})` for ``SparseGraph`` and `O(|V|^2\log{|E|})` for + ``DenseGraph``. + If the graph is not connected, we insert empty separators between the lists of separators of each connected components. See the examples below for more details. diff --git a/src/sage/graphs/graph_decompositions/sage_tdlib.cpp b/src/sage/graphs/graph_decompositions/sage_tdlib.cpp index 3644edf6ac7..886859e8d74 100644 --- a/src/sage/graphs/graph_decompositions/sage_tdlib.cpp +++ b/src/sage/graphs/graph_decompositions/sage_tdlib.cpp @@ -4,8 +4,8 @@ #include #include -#include "tdlib/TD_combinations.hpp" -#include "tdlib/TD_misc.hpp" +#include +#include #ifndef TD_STRUCT_VERTEX #define TD_STRUCT_VERTEX @@ -18,13 +18,6 @@ struct Vertex{ typedef boost::adjacency_list TD_graph_t; -struct bag{ - std::set bag; -}; - -typedef boost::adjacency_list TD_tree_dec_t; - - void make_tdlib_graph(TD_graph_t &G, std::vector &V, std::vector &E){ unsigned int max = 0; for(unsigned int i = 0; i < V.size(); i++) diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx index 740b07fc40b..8382cb85cdf 100644 --- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx +++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx @@ -87,7 +87,6 @@ The treewidth of a clique is `n-1` and its treelength is 1:: - Approximation of treelength based on :meth:`~sage.graphs.graph.Graph.lex_M` - Approximation of treelength based on BFS Layering - - upgrade tdlib to 0.9.0 :issue:`30813` Methods @@ -105,7 +104,6 @@ Methods from sage.sets.set import Set from sage.misc.cachefunc import cached_function -from sage.features import PythonModule from sage.sets.disjoint_set import DisjointSet from sage.rings.infinity import Infinity from sage.graphs.distances_all_pairs cimport c_distances_all_pairs @@ -619,6 +617,12 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None, nice=Fals sage: g.treewidth(algorithm='sage', certificate=True, kmin=4) Tree decomposition: Graph on 4 vertices + Check that :issue:`38159` is fixed :: + + sage: G = Graph('I~~}vPlr_') + sage: G.treewidth(algorithm='sage') == G.treewidth(algorithm='tdlib') # optional - tdlib + True + Trivially true:: sage: graphs.PetersenGraph().treewidth(k=35) diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 0461cfb4ccc..2d6841eb719 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -81,6 +81,7 @@ def wrap_name(x): "HouseXGraph", "LadderGraph", "LollipopGraph", + "MoebiusLadderGraph", "PathGraph", "StarGraph", "TadpoleGraph", @@ -455,6 +456,8 @@ def wrap_name(x): - Marco Cognetta (2016-03-03): added TuranGraph +- Janmenjaya Panda (2024-05-26): added MoebiusLadderGraph + Functions and methods --------------------- @@ -2505,6 +2508,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None HouseGraph = staticmethod(basic.HouseGraph) HouseXGraph = staticmethod(basic.HouseXGraph) LadderGraph = staticmethod(basic.LadderGraph) + MoebiusLadderGraph = staticmethod(basic.MoebiusLadderGraph) PathGraph = staticmethod(basic.PathGraph) StarGraph = staticmethod(basic.StarGraph) Toroidal6RegularGrid2dGraph = staticmethod(basic.Toroidal6RegularGrid2dGraph) diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index 9b37cb59ea8..b60ebde2e31 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -103,8 +103,8 @@ def from_sparse6(G, g6_string): k = int((ZZ(n) - 1).nbits()) ords = [ord(i) for i in s] if any(o > 126 or o < 63 for o in ords): - raise RuntimeError("the string seems corrupt: valid characters are \n" + ''.join([chr(i) for i in range(63, 127)])) - bits = ''.join([int_to_binary_string(o-63).zfill(6) for o in ords]) + raise RuntimeError("the string seems corrupt: valid characters are \n" + ''.join(chr(i) for i in range(63, 127))) + bits = ''.join(int_to_binary_string(o-63).zfill(6) for o in ords) if not k: b = [int(x) for x in bits] x = [0] * len(b) diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index 13fc1c2775a..4b9ba208b01 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -256,7 +256,8 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") - ``"fast"`` -- This algorithm uses the notion of *slices* to refine the position of the vertices in the ordering. The time complexity of this algorithm is in `O(n + m)`, and our implementation follows that - complexity. See [HMPV2000]_ and next section for more details. + complexity for ``SparseGraph``. For ``DenseGraph``, the complexity is + `O(n^2)`. See [HMPV2000]_ and next section for more details. ALGORITHM: @@ -444,7 +445,7 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") cdef int now, v, vi, int_neighbor # Perform Lex BFS - if algorithm is "fast": + if algorithm == "fast": lex_BFS_fast_short_digraph(sd, sigma_int, pred) sigma = [int_to_v[sigma_int[i]] for i in range(n)] @@ -505,8 +506,9 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): appended to the codes of all neighbors of the selected vertex that are left in the graph. - Time complexity is `O(n+m)` where `n` is the number of vertices and `m` is - the number of edges. + Time complexity is `O(n+m)` for ``SparseGraph`` and `O(n^2)` for + ``DenseGraph`` where `n` is the number of vertices and `m` is the number of + edges. See [Mil2017]_ for more details on the algorithm. @@ -677,8 +679,9 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): codes are updated. Lex DFS differs from Lex BFS only in the way codes are updated after each iteration. - Time complexity is `O(n+m)` where `n` is the number of vertices and `m` is - the number of edges. + Time complexity is `O(n+m)` for ``SparseGraph`` and `O(n^2)` for + ``DenseGraph`` where `n` is the number of vertices and `m` is the number of + edges. See [CK2008]_ for more details on the algorithm. @@ -851,8 +854,9 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): prepended to the codes of all neighbors of the selected vertex that are left in the graph. - Time complexity is `O(n+m)` where `n` is the number of vertices and `m` is - the number of edges. + Time complexity is `O(n+m)` for ``SparseGraph`` and `O(n^2)` for + ``DenseGraph`` where `n` is the number of vertices and `m` is the number of + edges. See [Mil2017]_ for more details on the algorithm. @@ -1582,6 +1586,10 @@ def maximum_cardinality_search(G, reverse=False, tree=False, initial_vertex=None chosen at each step `i` to be placed in position `n - i` in `\alpha`. This ordering can be computed in time `O(n + m)`. + Time complexity is `O(n+m)` for ``SparseGraph`` and `O(n^2)` for + ``DenseGraph`` where `n` is the number of vertices and `m` is the number of + edges. + When the graph is chordal, the ordering returned by MCS is a *perfect elimination ordering*, like :meth:`~sage.graphs.traversals.lex_BFS`. So this ordering can be used to recognize chordal graphs. See [He2006]_ for @@ -1593,7 +1601,7 @@ def maximum_cardinality_search(G, reverse=False, tree=False, initial_vertex=None INPUT: - - ``G`` -- a Sage Graph + - ``G`` -- a Sage graph - ``reverse`` -- boolean (default: ``False``); whether to return the vertices in discovery order, or the reverse @@ -1608,8 +1616,8 @@ def maximum_cardinality_search(G, reverse=False, tree=False, initial_vertex=None By default, return the ordering `\alpha` as a list. When ``tree`` is ``True``, the method returns a tuple `(\alpha, T)`, where `T` is a directed - tree with the same set of vertices as `G`and a directed edge from `u` to `v` - if `u` was the first vertex to saw `v`. + tree with the same set of vertices as `G` and a directed edge from `u` to `v` + if `u` was the first vertex to see `v`. EXAMPLES: diff --git a/src/sage/graphs/weakly_chordal.pyx b/src/sage/graphs/weakly_chordal.pyx index 2b1172e0895..aa91cfa9cdc 100644 --- a/src/sage/graphs/weakly_chordal.pyx +++ b/src/sage/graphs/weakly_chordal.pyx @@ -163,8 +163,9 @@ def is_long_hole_free(g, certificate=False): This is done through a depth-first-search. For efficiency, the auxiliary graph is constructed on-the-fly and never stored in memory. - The run time of this algorithm is `O(m^2)` [NP2007]_ ( where - `m` is the number of edges of the graph ) . + The run time of this algorithm is `O(n+m^2)` for ``SparseGraph`` and + `O(n^2 + m^2)` for ``DenseGraph`` [NP2007]_ (where `n` is the number of + vertices and `m` is the number of edges of the graph). EXAMPLES: @@ -393,8 +394,9 @@ def is_long_antihole_free(g, certificate=False): This is done through a depth-first-search. For efficiency, the auxiliary graph is constructed on-the-fly and never stored in memory. - The run time of this algorithm is `O(m^2)` [NP2007]_ (where - `m` is the number of edges of the graph). + The run time of this algorithm is `O(n+m^2)` for ``SparseGraph`` and + `O(n^2\log{m} + m^2)` for ``DenseGraph`` [NP2007]_ (where `n` is the number + of vertices and `m` is the number of edges of the graph). EXAMPLES: @@ -526,7 +528,9 @@ def is_weakly_chordal(g, certificate=False): contain an induced cycle of length at least 5. Using is_long_hole_free() and is_long_antihole_free() yields a run time - of `O(m^2)` (where `m` is the number of edges of the graph). + of `O(n+m^2)` for ``SparseGraph`` and `O(n^2\log{m} + m^2)` for + ``DenseGraph`` (where `n` is the number of vertices and `m` is the number of + edges of the graph). EXAMPLES: diff --git a/src/sage/groups/abelian_gps/abelian_group_element.py b/src/sage/groups/abelian_gps/abelian_group_element.py index ac279f71011..172a671906c 100644 --- a/src/sage/groups/abelian_gps/abelian_group_element.py +++ b/src/sage/groups/abelian_gps/abelian_group_element.py @@ -57,11 +57,19 @@ def is_AbelianGroupElement(x): sage: from sage.groups.abelian_gps.abelian_group_element import is_AbelianGroupElement sage: is_AbelianGroupElement(3) + doctest:warning... + DeprecationWarning: The function is_AbelianGroupElement is deprecated; + use 'isinstance(..., AbelianGroupElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. False sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde') sage: is_AbelianGroupElement(F.0) True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_AbelianGroupElement is deprecated; " + "use 'isinstance(..., AbelianGroupElement)' instead.") return isinstance(x, AbelianGroupElement) diff --git a/src/sage/groups/abelian_gps/dual_abelian_group.py b/src/sage/groups/abelian_gps/dual_abelian_group.py index 24c910d96d9..aaa231b0f81 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group.py @@ -345,7 +345,7 @@ def __contains__(self, X): sage: A*B^2*D^7 in Fd True """ - return X.parent() == self and is_DualAbelianGroupElement(X) + return X.parent() == self and isinstance(X, DualAbelianGroupElement) def order(self): """ diff --git a/src/sage/groups/abelian_gps/dual_abelian_group_element.py b/src/sage/groups/abelian_gps/dual_abelian_group_element.py index ecf17404bdd..048666b020f 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -71,10 +71,18 @@ def is_DualAbelianGroupElement(x) -> bool: sage: from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroupElement sage: F = AbelianGroup(5, [5,5,7,8,9], names=list("abcde")).dual_group() sage: is_DualAbelianGroupElement(F) + doctest:warning... + DeprecationWarning: The function is_DualAbelianGroupElement is deprecated; + use 'isinstance(..., DualAbelianGroupElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. False sage: is_DualAbelianGroupElement(F.an_element()) True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_DualAbelianGroupElement is deprecated; " + "use 'isinstance(..., DualAbelianGroupElement)' instead.") return isinstance(x, DualAbelianGroupElement) diff --git a/src/sage/groups/affine_gps/affine_group.py b/src/sage/groups/affine_gps/affine_group.py index 7d27488ec59..07b63d4a2bc 100644 --- a/src/sage/groups/affine_gps/affine_group.py +++ b/src/sage/groups/affine_gps/affine_group.py @@ -173,8 +173,8 @@ def __classcall__(cls, *args, **kwds): ring = V.base_ring() if len(args) == 2: degree, ring = args - from sage.rings.integer import is_Integer - if is_Integer(ring): + from sage.rings.integer import Integer + if isinstance(ring, Integer): from sage.rings.finite_rings.finite_field_constructor import FiniteField var = kwds.get('var', 'a') ring = FiniteField(ring, var) diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index a6ef6bb7395..4bb52ee4efb 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -799,7 +799,7 @@ def __init__(self, free_group, relations, category=None): ParentLibGAP.__init__(self, parent_gap) Group.__init__(self, category=category) - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation. @@ -813,7 +813,7 @@ def _repr_(self): 'Finitely presented group < a, b | a, b^3 >' """ gens = ', '.join(self.variable_names()) - rels = ', '.join([str(r) for r in self.relations()]) + rels = ', '.join(str(r) for r in self.relations()) return 'Finitely presented group ' + '< ' + gens + ' | ' + rels + ' >' def _latex_(self): diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index ef05b55c190..8cd34aa4cb1 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -59,7 +59,7 @@ from sage.categories.groups import Groups from sage.categories.rings import Rings -from sage.rings.integer import is_Integer +from sage.rings.integer import Integer from sage.matrix.matrix_space import MatrixSpace from sage.misc.latex import latex from sage.structure.richcmp import (richcmp_not_equal, rich_to_bool, @@ -345,19 +345,14 @@ def _latex_(self): gens = ', '.join(latex(x) for x in self.gens()) return '\\left\\langle %s \\right\\rangle' % gens - def sign_representation(self, base_ring=None, side="twosided"): + def sign_representation(self, base_ring=None): r""" Return the sign representation of ``self`` over ``base_ring``. - .. WARNING:: - - Assumes ``self`` is a matrix group over a field which has - embedding over real numbers. - INPUT: - - ``base_ring`` -- (optional) the base ring; the default is `\ZZ` - - ``side`` -- ignored + - ``base_ring`` -- (optional) the base ring; the default is the base + ring of ``self`` EXAMPLES:: @@ -367,8 +362,6 @@ def sign_representation(self, base_ring=None, side="twosided"): sage: e [1 0] [0 1] - sage: V._default_sign(e) - 1 sage: m2 = V.an_element() sage: m2 2*B['v'] @@ -376,13 +369,58 @@ def sign_representation(self, base_ring=None, side="twosided"): 2*B['v'] sage: m2*e*e 2*B['v'] + + sage: W = WeylGroup(["A", 1, 1]) + sage: W.sign_representation() + Sign representation of + Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space) + over Rational Field + + sage: G = GL(4, 2) + sage: G.sign_representation() == G.trivial_representation() + True """ if base_ring is None: - from sage.rings.integer_ring import ZZ - base_ring = ZZ + base_ring = self.base_ring() + if base_ring.characteristic() == 2: # characteristic 2 + return self.trivial_representation() from sage.modules.with_basis.representation import SignRepresentationMatrixGroup return SignRepresentationMatrixGroup(self, base_ring) + def natural_representation(self, base_ring=None): + r""" + Return the natural representation of ``self`` over ``base_ring``. + + INPUT: + + - ``base_ring`` -- (optional) the base ring; the default is the base + ring of ``self`` + + EXAMPLES:: + + sage: G = groups.matrix.SL(6, 3) + sage: V = G.natural_representation() + sage: V + Natural representation of Special Linear Group of degree 6 + over Finite Field of size 3 + sage: e = prod(G.gens()) + sage: e + [2 0 0 0 0 1] + [2 0 0 0 0 0] + [0 2 0 0 0 0] + [0 0 2 0 0 0] + [0 0 0 2 0 0] + [0 0 0 0 2 0] + sage: v = V.an_element() + sage: v + 2*e[0] + 2*e[1] + sage: e * v + e[0] + e[1] + e[2] + """ + from sage.modules.with_basis.representation import NaturalMatrixRepresentation + return NaturalMatrixRepresentation(self, base_ring) + + ################################################################### # # Matrix group over a generic ring @@ -417,7 +455,7 @@ def __init__(self, degree, base_ring, category=None): True """ assert base_ring in Rings - assert is_Integer(degree) + assert isinstance(degree, Integer) self._deg = degree if self._deg <= 0: diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 914eb0ad25c..2d265216519 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -4943,14 +4943,13 @@ def upper_central_series(self): from sage.groups.generic import structure_description - def sign_representation(self, base_ring=None, side="twosided"): + def sign_representation(self, base_ring=None): r""" Return the sign representation of ``self`` over ``base_ring``. INPUT: - ``base_ring`` -- (optional) the base ring; the default is `\ZZ` - - ``side`` -- ignored EXAMPLES:: diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index c6eb59df19f..4d6a67fe41b 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -211,8 +211,16 @@ def is_PermutationGroupElement(x): sage: p = PermutationGroupElement([(1,2),(3,4,5)]) sage: from sage.groups.perm_gps.permgroup_element import is_PermutationGroupElement sage: is_PermutationGroupElement(p) + doctest:warning... + DeprecationWarning: The function is_PermutationGroupElement is deprecated; + use 'isinstance(..., PermutationGroupElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38184, + "The function is_PermutationGroupElement is deprecated; " + "use 'isinstance(..., PermutationGroupElement)' instead.") return isinstance(x, PermutationGroupElement) diff --git a/src/sage/homology/chain_complex_homspace.py b/src/sage/homology/chain_complex_homspace.py index cf981d76561..1170b50b885 100644 --- a/src/sage/homology/chain_complex_homspace.py +++ b/src/sage/homology/chain_complex_homspace.py @@ -116,9 +116,17 @@ def is_ChainComplexHomspace(x): sage: C = T.chain_complex(augmented=True, cochain=True) sage: G = Hom(C, C) sage: is_ChainComplexHomspace(G) + doctest:warning... + DeprecationWarning: The function is_ChainComplexHomspace is deprecated; + use 'isinstance(..., ChainComplexHomspace)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_ChainComplexHomspace is deprecated; " + "use 'isinstance(..., ChainComplexHomspace)' instead.") return isinstance(x, ChainComplexHomspace) diff --git a/src/sage/interfaces/all.py b/src/sage/interfaces/all.py index 83100b2c3de..0ef74630304 100644 --- a/src/sage/interfaces/all.py +++ b/src/sage/interfaces/all.py @@ -1,32 +1,32 @@ # interfaces to other interpreters -from sage.interfaces.sage0 import sage0, sage0_version, Sage -from sage.interfaces.gap import gap, gap_reset_workspace, Gap -from sage.interfaces.gp import gp, gp_version, Gp # import problems -# from maxima_lib import maxima_lib -from sage.interfaces.maxima import maxima, Maxima -from sage.interfaces.singular import singular, singular_version, Singular - -from sage.interfaces.magma import magma, Magma -from sage.interfaces.polymake import polymake +try: + # from maxima_lib import maxima_lib + from sage.interfaces.maxima import maxima, Maxima +except ImportError: + pass from sage.misc.lazy_import import lazy_import +lazy_import('sage.interfaces.sage0', ['sage0', 'sage0_version', 'Sage']) lazy_import('sage.interfaces.axiom', ['Axiom', 'axiom']) lazy_import('sage.interfaces.ecm', ['ECM', 'ecm']) lazy_import('sage.interfaces.four_ti_2', 'four_ti_2') lazy_import('sage.interfaces.fricas', ['FriCAS', 'fricas']) lazy_import('sage.interfaces.frobby', 'frobby') +lazy_import('sage.interfaces.gap', ['gap', 'gap_reset_workspace', 'Gap']) lazy_import('sage.interfaces.gap3', ['gap3', 'gap3_version', 'Gap3']) lazy_import('sage.interfaces.genus2reduction', ['genus2reduction', 'Genus2reduction']) lazy_import('sage.interfaces.gfan', ['gfan', 'Gfan']) lazy_import('sage.interfaces.giac', ['giac', 'Giac']) lazy_import('sage.interfaces.gnuplot', 'gnuplot') +lazy_import('sage.interfaces.gp', ['gp', 'gp_version', 'Gp']) lazy_import('sage.interfaces.kash', ['kash', 'kash_version', 'Kash']) lazy_import('sage.interfaces.lie', ['lie', 'LiE']) lazy_import('sage.interfaces.lisp', ['lisp', 'Lisp']) lazy_import('sage.interfaces.macaulay2', ['macaulay2', 'Macaulay2']) +lazy_import('sage.interfaces.magma', ['magma', 'Magma']) lazy_import('sage.interfaces.magma_free', 'magma_free') lazy_import('sage.interfaces.maple', ['maple', 'Maple']) lazy_import('sage.interfaces.mathematica', ['mathematica', 'Mathematica']) @@ -35,12 +35,14 @@ lazy_import('sage.interfaces.mupad', ['mupad', 'Mupad']) # NOT functional yet lazy_import('sage.interfaces.mwrank', ['mwrank', 'Mwrank']) lazy_import('sage.interfaces.octave', ['octave', 'Octave']) +lazy_import('sage.interfaces.polymake', 'polymake') lazy_import('sage.interfaces.povray', 'povray') lazy_import('sage.interfaces.psage', 'PSage') lazy_import('sage.interfaces.qepcad', ['qepcad', 'qepcad_version', 'qepcad_formula']) lazy_import('sage.interfaces.r', ['r', 'R', 'r_version']) lazy_import('sage.interfaces.read_data', 'read_data') lazy_import('sage.interfaces.scilab', 'scilab') +lazy_import('sage.interfaces.singular', ['singular', 'singular_version', 'Singular']) lazy_import('sage.interfaces.tachyon', 'tachyon_rt') # The following variable is used by sage-shell-mode in emacs: diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 0d10d75f28b..2e16fd3b2e4 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -928,6 +928,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if TESTS:: + sage: from sage.interfaces.singular import singular sage: singular._eval_line('def a=3;') '' sage: singular('a') diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index fc605553dd4..f093e865d4c 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -644,6 +644,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if TESTS:: + sage: from sage.interfaces.gap import gap sage: gap._eval_line('2+2;') '4' @@ -1124,6 +1125,7 @@ def __reduce__(self): """ EXAMPLES:: + sage: from sage.interfaces.gap import gap sage: gap.__reduce__() (, ()) sage: f, args = _ diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index 4426a7af299..9459396d3e4 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -270,7 +270,7 @@ def _repr_(self): EXAMPLES:: - sage: gp # indirect doctest + sage: gp # indirect doctest PARI/GP interpreter """ return 'PARI/GP interpreter' @@ -279,6 +279,7 @@ def __reduce__(self): """ EXAMPLES:: + sage: from sage.interfaces.gp import gp sage: gp.__reduce__() (, ()) sage: f, args = _ diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 517c0c6fc7a..9b398ded62f 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -638,6 +638,7 @@ def __getattr__(self, attrname): TESTS:: sage: from sage.structure.parent_base import ParentWithBase + sage: from sage.interfaces.singular import singular sage: ParentWithBase.__getattribute__(singular, '_coerce_map_from_') """ diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index 034ea2ce550..4cf4a77f8bf 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -397,6 +397,7 @@ def __reduce__(self): EXAMPLES:: + sage: from sage.interfaces.magma import magma sage: loads(dumps(magma)) is magma True diff --git a/src/sage/interfaces/polymake.py b/src/sage/interfaces/polymake.py index 20dfafcf491..a3418e1a773 100644 --- a/src/sage/interfaces/polymake.py +++ b/src/sage/interfaces/polymake.py @@ -155,6 +155,7 @@ def __reduce__(self): """ EXAMPLES:: + sage: from sage.interfaces.polymake import polymake sage: loads(dumps(polymake)) is polymake True diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index 3a1e640d657..33addb28afa 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -1,3 +1,4 @@ +# sage.doctest: needs rpy2 r""" Interfaces to R @@ -24,21 +25,21 @@ vector named `x` using the R interface in Sage, you pass the R interpreter object a list or tuple of numbers:: - sage: x = r([10.4,5.6,3.1,6.4,21.7]); x # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]); x [1] 10.4 5.6 3.1 6.4 21.7 You can invert elements of a vector x in R by using the invert operator or by doing 1/x:: - sage: ~x # optional - rpy2 + sage: ~x [1] 0.09615385 0.17857143 0.32258065 0.15625000 0.04608295 - sage: 1/x # optional - rpy2 + sage: 1/x [1] 0.09615385 0.17857143 0.32258065 0.15625000 0.04608295 The following assignment creates a vector `y` with 11 entries which consists of two copies of `x` with a 0 in between:: - sage: y = r([x,0,x]); y # optional - rpy2 + sage: y = r([x,0,x]); y [1] 10.4 5.6 3.1 6.4 21.7 0.0 10.4 5.6 3.1 6.4 21.7 Vector Arithmetic @@ -47,25 +48,24 @@ by adding together (element by element) `2x` repeated 2.2 times, `y` repeated just once, and 1 repeated 11 times:: - sage: v = 2*x+y+1; v # optional - rpy2 + sage: v = 2*x+y+1; v [1] 32.2 17.8 10.3 20.2 66.1 21.8 22.6 12.8 16.9 50.8 43.5 One can compute the sum of the elements of an R vector in the following two ways:: - sage: sum(x) # optional - rpy2 + sage: sum(x) [1] 47.2 - sage: x.sum() # optional - rpy2 + sage: x.sum() [1] 47.2 One can calculate the sample variance of a list of numbers:: - sage: ((x-x.mean())^2/(x.length()-1)).sum() # optional - rpy2 + sage: ((x-x.mean())^2/(x.length()-1)).sum() [1] 53.853 - sage: x.var() # optional - rpy2 + sage: x.var() [1] 53.853 - sage: # optional - rpy2 sage: x.sort() [1] 3.1 5.6 6.4 10.4 21.7 sage: x.min() @@ -75,24 +75,23 @@ sage: x [1] 10.4 5.6 3.1 6.4 21.7 - sage: r(-17).sqrt() # optional - rpy2 + sage: r(-17).sqrt() [1] NaN - sage: r('-17+0i').sqrt() # optional - rpy2 + sage: r('-17+0i').sqrt() [1] 0+4.123106i Generating an arithmetic sequence:: - sage: r('1:10') # optional - rpy2 + sage: r('1:10') [1] 1 2 3 4 5 6 7 8 9 10 Because ``from`` is a keyword in Python, it can't be used as a keyword argument. Instead, ``from_`` can be passed, and R will recognize it as the correct thing:: - sage: r.seq(length=10, from_=-1, by=.2) # optional - rpy2 + sage: r.seq(length=10, from_=-1, by=.2) [1] -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 - sage: # optional - rpy2 sage: x = r([10.4,5.6,3.1,6.4,21.7]) sage: x.rep(2) [1] 10.4 5.6 3.1 6.4 21.7 10.4 5.6 3.1 6.4 21.7 @@ -103,7 +102,6 @@ Missing Values:: - sage: # optional - rpy2 sage: na = r('NA') sage: z = r([1,2,3,na]) sage: z @@ -135,19 +133,18 @@ Character Vectors:: - sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs # optional - rpy2 + sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs [1] "X1" "Y2" "X3" "Y4" "X5" "Y6" "X7" "Y8" "X9" "Y10" Index vectors; selecting and modifying subsets of a data set:: - sage: na = r('NA') # optional - rpy2 - sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x # optional - rpy2 + sage: na = r('NA') + sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x [1] 10.4 5.6 3.1 6.4 21.7 NA - sage: x['!is.na(self)'] # optional - rpy2 + sage: x['!is.na(self)'] [1] 10.4 5.6 3.1 6.4 21.7 - sage: # optional - rpy2 sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x [1] 10.4 5.6 3.1 6.4 21.7 NA sage: (x+1)['(!is.na(self)) & self>0'] @@ -159,12 +156,12 @@ Distributions:: - sage: r.options(width="60") # optional - rpy2 + sage: r.options(width="60") $width [1] 80 - sage: rr = r.dnorm(r.seq(-3,3,0.1)) # optional - rpy2 - sage: rr # optional - rpy2 + sage: rr = r.dnorm(r.seq(-3,3,0.1)) + sage: rr [1] 0.004431848 0.005952532 0.007915452 0.010420935 [5] 0.013582969 0.017528300 0.022394530 0.028327038 [9] 0.035474593 0.043983596 0.053990967 0.065615815 @@ -184,13 +181,12 @@ Convert R Data Structures to Python/Sage:: - sage: rr = r.dnorm(r.seq(-3,3,0.1)) # optional - rpy2 - sage: sum(rr._sage_()) # optional - rpy2 + sage: rr = r.dnorm(r.seq(-3,3,0.1)) + sage: sum(rr._sage_()) 9.9772125168981... Or you get a dictionary to be able to access all the information:: - sage: # optional - rpy2 sage: rs = r.summary(r.c(1,4,3,4,3,2,5,1)) sage: rs Min. 1st Qu. Median Mean 3rd Qu. Max. @@ -279,13 +275,18 @@ # see the _lazy_init for some reasoning behind the lazy imports from sage.misc.lazy_import import lazy_import -lazy_import("rpy2", "robjects") -lazy_import("rpy2.robjects", "packages", "rpy2_packages") -lazy_import("rpy2.robjects.conversion", "localconverter") +from sage.features import PythonModule + +rpy2_feature = PythonModule('rpy2', spkg='rpy2', type='standard') + +lazy_import("rpy2", "robjects", feature=rpy2_feature) +lazy_import("rpy2.robjects", "packages", "rpy2_packages", feature=rpy2_feature) +lazy_import("rpy2.robjects.conversion", ["localconverter", "Converter"], feature=rpy2_feature) # for help page fetching -lazy_import("rpy2.robjects.help", "Package") -lazy_import("rpy2", "rinterface") +lazy_import("rpy2.robjects.help", "Package", feature=rpy2_feature) +lazy_import("rpy2", "rinterface", feature=rpy2_feature) + COMMANDS_CACHE = '%s/r_commandlist.sobj' % DOT_SAGE @@ -310,49 +311,48 @@ def _setup_r_to_sage_converter(): length 1 to simple values, whether or not they "originally" were simple values or not:: - sage: r([42]).sage() # optional - rpy2 + sage: r([42]).sage() 42 - sage: r(42).sage() # optional - rpy2 + sage: r(42).sage() 42 - sage: r('c("foo")').sage() # optional - rpy2 + sage: r('c("foo")').sage() 'foo' Arrays of length greater than one are treated normally:: - sage: r([42, 43]).sage() # optional - rpy2 + sage: r([42, 43]).sage() [42, 43] We also convert all numeric values to integers if that is possible without loss of precision:: - sage: type(r([1.0]).sage()) == int # optional - rpy2 + sage: type(r([1.0]).sage()) == int True - sage: r([1.0, 42.5]).sage() # optional - rpy2 + sage: r([1.0, 42.5]).sage() [1, 42.5] Matrices are converted to sage matrices:: - sage: r('matrix(c(2,4,3,1,5,7), nrow=2, ncol=3)').sage() # optional - rpy2 + sage: r('matrix(c(2,4,3,1,5,7), nrow=2, ncol=3)').sage() [2 3 5] [4 1 7] More complex r structures are represented by dictionaries:: - sage: r.summary(1).sage() # optional - rpy2 + sage: r.summary(1).sage() {'DATA': [1, 1, 1, 1, 1, 1], '_Names': ['Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'], '_r_class': ['summaryDefault', 'table']} - sage: r.options(width="60").sage() # optional - rpy2 + sage: r.options(width="60").sage() {'DATA': {'width': 60}, '_Names': 'width'} The conversion can handle "not a number", infinity, imaginary values and missing values:: - sage: # optional - rpy2 sage: r(-17).sqrt().sage() nan sage: r('-17+0i').sqrt().sage() @@ -364,11 +364,10 @@ def _setup_r_to_sage_converter(): Character Vectors are represented by regular python arrays:: - sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs.sage() # optional - rpy2 + sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs.sage() ['X1', 'Y2', 'X3', 'Y4', 'X5', 'Y6', 'X7', 'Y8', 'X9', 'Y10'] """ from rpy2.rinterface import SexpVector, ListSexpVector, FloatSexpVector - from rpy2.robjects.conversion import Converter # convert rpy2's representation of r objects to the one sage expects (as defined by the old # expect interface) @@ -475,13 +474,13 @@ def __init__(self, EXAMPLES:: - sage: r.summary(r.c(1,2,3,111,2,3,2,3,2,5,4)) # optional - rpy2 + sage: r.summary(r.c(1,2,3,111,2,3,2,3,2,5,4)) Min. 1st Qu. Median Mean 3rd Qu. Max. 1.00 2.00 3.00 12.55 3.50 111.00 TESTS:: - sage: r == loads(dumps(r)) # optional - rpy2 + sage: r == loads(dumps(r)) True """ Interface.__init__( @@ -512,7 +511,6 @@ def _lazy_init(self): Initialization happens on eval:: - sage: # optional - rpy2 sage: my_r = R() sage: my_r._initialized False @@ -523,7 +521,6 @@ def _lazy_init(self): And on package import:: - sage: # optional - rpy2 sage: my_r = R() sage: my_r._initialized False @@ -533,7 +530,6 @@ def _lazy_init(self): And when fetching help pages:: - sage: # optional - rpy2 sage: my_r = R() sage: my_r._initialized False @@ -554,7 +550,7 @@ def _coerce_impl(self, x, use_special=True): Check conversion of Booleans (:issue:`28705`):: - sage: repr(r(True)) == r._true_symbol() # indirect doctest # optional - rpy2 + sage: repr(r(True)) == r._true_symbol() # indirect doctest True """ # We overwrite _coerce_impl here because r._true_symbol() and @@ -572,10 +568,10 @@ def set_seed(self, seed=None): EXAMPLES:: - sage: r = R() # optional - rpy2 - sage: r.set_seed(1) # optional - rpy2 + sage: r = R() + sage: r.set_seed(1) 1 - sage: r.sample("1:10", 5) # random # optional - rpy2 + sage: r.sample("1:10", 5) # random [1] 3 4 5 7 2 """ if seed is None: @@ -592,8 +588,8 @@ def _start(self): EXAMPLES:: - sage: r = R() # optional - rpy2 - sage: r._start() # optional - rpy2 + sage: r = R() + sage: r._start() """ # pager needed to replace help view from less to printout # option device= is for plotting, is set to x11, NULL would be better? @@ -622,23 +618,22 @@ def png(self, *args, **kwds): EXAMPLES:: - sage: # optional - rpy2 sage: filename = tmp_filename() + '.png' - sage: r.png(filename='"%s"'%filename) # optional - rgraphics + sage: r.png(filename='"%s"'%filename) # optional - rgraphics NULL sage: x = r([1,2,3]) sage: y = r([4,5,6]) - sage: r.plot(x,y) # optional - rgraphics + sage: r.plot(x,y) # optional - rgraphics null device 1 - sage: import os; os.unlink(filename) # optional - rgraphics + sage: import os; os.unlink(filename) # optional - rgraphics We want to make sure that we actually can view R graphics, which happens differently on different platforms:: - sage: s = r.eval('capabilities("png")') # Should be on Linux and Solaris # optional - rpy2 - sage: t = r.eval('capabilities("aqua")') # Should be on all supported Mac versions # optional - rpy2 - sage: "TRUE" in s+t # optional -- rgraphics # optional - rpy2 + sage: s = r.eval('capabilities("png")') # should be on Linux and Solaris + sage: t = r.eval('capabilities("aqua")') # should be on all supported Mac versions + sage: "TRUE" in s+t # optional - rgraphics True """ # Check to see if R has PNG support @@ -654,8 +649,8 @@ def convert_r_list(self, l): EXAMPLES:: - sage: s = 'c(".GlobalEnv", "package:stats", "package:graphics", "package:grDevices", \n"package:utils", "package:datasets", "package:methods", "Autoloads", \n"package:base")' # optional - rpy2 - sage: r.convert_r_list(s) # optional - rpy2 + sage: s = 'c(".GlobalEnv", "package:stats", "package:graphics", "package:grDevices", \n"package:utils", "package:datasets", "package:methods", "Autoloads", \n"package:base")' + sage: r.convert_r_list(s) ['.GlobalEnv', 'package:stats', 'package:graphics', @@ -677,7 +672,7 @@ def install_packages(self, package_name): EXAMPLES:: - sage: r.install_packages('aaMI') # not tested # optional - rpy2 + sage: r.install_packages('aaMI') # not tested ... R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. @@ -695,7 +690,7 @@ def _repr_(self): EXAMPLES:: - sage: r # indirect doctest # optional - rpy2 + sage: r # indirect doctest R Interpreter """ return 'R Interpreter' @@ -706,8 +701,9 @@ def __reduce__(self): EXAMPLES:: - sage: rlr, t = r.__reduce__() # optional - rpy2 - sage: rlr(*t) # optional - rpy2 + sage: from sage.interfaces.r import r + sage: rlr, t = r.__reduce__() + sage: rlr(*t) R Interpreter """ return reduce_load_R, tuple([]) @@ -720,9 +716,9 @@ def __getattr__(self, attrname): EXAMPLES:: - sage: c = r.c; c # optional - rpy2 + sage: c = r.c; c c - sage: type(c) # optional - rpy2 + sage: type(c) """ try: @@ -743,7 +739,7 @@ def _read_in_file_command(self, filename): EXAMPLES:: - sage: r._read_in_file_command('file.txt') # optional - rpy2 + sage: r._read_in_file_command('file.txt') 'file=file("file.txt",open="r")\nsource(file)' """ return 'file=file("%s",open="r")\nsource(file)' % filename @@ -755,7 +751,6 @@ def read(self, filename): EXAMPLES:: - sage: # optional - rpy2 sage: filename = tmp_filename() sage: f = open(filename, 'w') sage: _ = f.write('a <- 2+2\n') @@ -770,7 +765,7 @@ def _install_hints(self): """ EXAMPLES:: - sage: print(r._install_hints()) # optional - rpy2 + sage: print(r._install_hints()) R is currently installed with Sage. """ return "R is currently installed with Sage.\n" @@ -785,7 +780,7 @@ def _source(self, s): EXAMPLES:: - sage: print(r._source("c")) # optional - rpy2 + sage: print(r._source("c")) function (...) .Primitive("c") """ if s[-2:] == "()": @@ -804,7 +799,7 @@ def source(self, s): EXAMPLES:: - sage: print(r.source("c")) # optional - rpy2 + sage: print(r.source("c")) function (...) .Primitive("c") """ return self._source(s) @@ -817,7 +812,6 @@ def version(self): EXAMPLES:: - sage: # optional - rpy2 sage: r.version() # not tested ((3, 0, 1), 'R version 3.0.1 (2013-05-16)') sage: rint, rstr = r.version() @@ -851,10 +845,10 @@ def library(self, library_name): EXAMPLES:: - sage: r.library('grid') # optional - rpy2 - sage: 'grid' in r.eval('(.packages())') # optional - rpy2 + sage: r.library('grid') + sage: 'grid' in r.eval('(.packages())') True - sage: r.library('foobar') # optional - rpy2 + sage: r.library('foobar') Traceback (most recent call last): ... ImportError: ... @@ -889,8 +883,8 @@ def available_packages(self): EXAMPLES:: - sage: ap = r.available_packages() # optional - internet # optional - rpy2 - sage: len(ap) > 20 # optional - internet # optional - rpy2 + sage: ap = r.available_packages() # optional - internet + sage: len(ap) > 20 # optional - internet True """ p = self.new('available.packages("%s/src/contrib")' % RRepositoryURL) @@ -911,7 +905,7 @@ def _object_class(self): EXAMPLES:: - sage: r._object_class() # optional - rpy2 + sage: r._object_class() """ return RElement @@ -924,7 +918,7 @@ def _true_symbol(self): EXAMPLES:: - sage: r._true_symbol() # optional - rpy2 + sage: r._true_symbol() '[1] TRUE' """ # return the string rep of truth, i.e., what the system outputs @@ -939,7 +933,7 @@ def _false_symbol(self): EXAMPLES:: - sage: r._false_symbol() # optional - rpy2 + sage: r._false_symbol() '[1] FALSE' """ # return the string rep of false, i.e., what the system outputs @@ -950,7 +944,7 @@ def _equality_symbol(self): """ EXAMPLES:: - sage: r._equality_symbol() # optional - rpy2 + sage: r._equality_symbol() '==' """ # return the symbol for checking equality, e.g., == or eq. @@ -986,7 +980,7 @@ def help(self, command): EXAMPLES:: - sage: r.help('c') # optional - rpy2 + sage: r.help('c') title ----- @@ -1015,7 +1009,7 @@ def _assign_symbol(self): EXAMPLES:: - sage: r._assign_symbol() # optional - rpy2 + sage: r._assign_symbol() ' <- ' """ return " <- " @@ -1028,7 +1022,7 @@ def _left_list_delim(self): EXAMPLES:: - sage: r._left_list_delim() # optional - rpy2 + sage: r._left_list_delim() 'c(' """ return "c(" @@ -1041,7 +1035,7 @@ def _right_list_delim(self): EXAMPLES:: - sage: r._right_list_delim() # optional - rpy2 + sage: r._right_list_delim() ')' """ return ")" @@ -1052,7 +1046,7 @@ def console(self): EXAMPLES:: - sage: r.console() # not tested # optional - rpy2 + sage: r.console() # not tested R version 2.6.1 (2007-11-26) Copyright (C) 2007 The R Foundation for Statistical Computing ISBN 3-900051-07-0 @@ -1068,7 +1062,7 @@ def function_call(self, function, args=None, kwds=None): EXAMPLES:: - sage: r.function_call('length', args=[ [1,2,3] ]) # optional - rpy2 + sage: r.function_call('length', args=[ [1,2,3] ]) [1] 3 """ args, kwds = self._convert_args_kwds(args, kwds) @@ -1082,7 +1076,7 @@ def call(self, function_name, *args, **kwds): EXAMPLES:: - sage: r.call('length', [1,2,3]) # optional - rpy2 + sage: r.call('length', [1,2,3]) [1] 3 """ return self.function_call(function_name, args=args, kwds=kwds) @@ -1096,9 +1090,9 @@ def _an_element_(self): EXAMPLES:: - sage: r._an_element_() # optional - rpy2 + sage: r._an_element_() [1] 0 - sage: type(_) # optional - rpy2 + sage: type(_) """ return self(0) @@ -1114,8 +1108,8 @@ def set(self, var, value): EXAMPLES:: - sage: r.set('a', '2 + 3') # optional - rpy2 - sage: r.get('a') # optional - rpy2 + sage: r.set('a', '2 + 3') + sage: r.get('a') '[1] 5' """ _ = self.eval(f'{var} <- {value}') @@ -1132,8 +1126,8 @@ def get(self, var): EXAMPLES:: - sage: r.set('a', 2) # optional - rpy2 - sage: r.get('a') # optional - rpy2 + sage: r.set('a', 2) + sage: r.get('a') '[1] 2' """ return self.eval('%s' % var) @@ -1146,7 +1140,7 @@ def na(self): EXAMPLES:: - sage: r.na() # optional - rpy2 + sage: r.na() [1] NA """ return self('NA') @@ -1164,8 +1158,8 @@ def completions(self, s): EXAMPLES:: - sage: dummy = r._tab_completion(use_disk_cache=False) #clean doctest # optional - rpy2 - sage: 'testInheritedMethods' in r.completions('tes') # optional - rpy2 + sage: dummy = r._tab_completion(use_disk_cache=False) # clean doctest + sage: 'testInheritedMethods' in r.completions('tes') True """ return [name for name in self._tab_completion() if name[:len(s)] == s] @@ -1178,10 +1172,10 @@ def _commands(self): EXAMPLES:: - sage: l = r._commands() # optional - rpy2 - sage: 'AIC' in l # optional - rpy2 + sage: l = r._commands() + sage: 'AIC' in l True - sage: len(l) > 200 # optional - rpy2 + sage: len(l) > 200 True """ v = RBaseCommands @@ -1228,8 +1222,8 @@ def _tab_completion(self, verbose=True, use_disk_cache=True): EXAMPLES:: - sage: t = r._tab_completion(verbose=False) # optional - rpy2 - sage: len(t) > 200 # optional - rpy2 + sage: t = r._tab_completion(verbose=False) + sage: len(t) > 200 True """ try: @@ -1274,7 +1268,7 @@ def plot(self, *args, **kwds): persistent in your own code:: sage: from tempfile import TemporaryDirectory - sage: with TemporaryDirectory() as d: # optional - rpy2, rgraphics + sage: with TemporaryDirectory() as d: # optional - rgraphics ....: _ = r.setwd(d) ....: r.plot("1:10") null device @@ -1284,16 +1278,15 @@ def plot(self, *args, **kwds): the output device to that file. If this is done in the notebook, it must be done in the same cell as the plot itself:: - sage: # optional - rpy2 sage: filename = tmp_filename() + '.png' - sage: r.png(filename='"%s"'%filename) # optional - rgraphics + sage: r.png(filename='"%s"'%filename) # optional - rgraphics NULL sage: x = r([1,2,3]) sage: y = r([4,5,6]) - sage: r.plot(x,y) # optional - rgraphics + sage: r.plot(x,y) # optional - rgraphics null device 1 - sage: import os; os.unlink(filename) # optional - rgraphics + sage: import os; os.unlink(filename) # optional - rgraphics Please note that for more extensive use of R's plotting capabilities (such as the lattices package), it is advisable @@ -1301,7 +1294,7 @@ def plot(self, *args, **kwds): notebook. The following examples are not tested, because they differ depending on operating system:: - sage: # not tested, optional - rpy2 + sage: # not tested sage: r.X11() sage: r.quartz() sage: r.hist("rnorm(100)") @@ -1313,13 +1306,12 @@ def plot(self, *args, **kwds): would need to use the following since R lattice graphics do not automatically print away from the command line:: - sage: # optional - rpy2 - sage: filename = tmp_filename() + '.png' # Not needed in notebook, used for doctesting - sage: r.png(filename='"%s"'%filename) # optional - rgraphics + sage: filename = tmp_filename() + '.png' # not needed in notebook, used for doctesting + sage: r.png(filename='"%s"'%filename) # optional - rgraphics NULL sage: r.library("lattice") sage: r("print(histogram(~wt | cyl, data=mtcars))") # optional - rgraphics - sage: import os; os.unlink(filename) # optional - rgraphics + sage: import os; os.unlink(filename) # optional - rgraphics """ # We have to define this to override the plot function defined in the # superclass. @@ -1333,7 +1325,7 @@ def eval(self, code, *args, **kwds): EXAMPLES:: - sage: r.eval('1+1') # optional - rpy2 + sage: r.eval('1+1') '[1] 2' """ self._lazy_init() @@ -1353,7 +1345,6 @@ def _r_to_sage_name(self, s): EXAMPLES:: - sage: # optional - rpy2 sage: f = r._r_to_sage_name sage: f('t.test') 't_test' @@ -1377,7 +1368,6 @@ def _sage_to_r_name(self, s): EXAMPLES:: - sage: # optional - rpy2 sage: f = r._sage_to_r_name sage: f('t_test') 't.test' @@ -1409,9 +1399,9 @@ def __getitem__(self, s): EXAMPLES:: - sage: r['as.data.frame'] # optional - rpy2 + sage: r['as.data.frame'] as.data.frame - sage: r['print'] # optional - rpy2 + sage: r['print'] print """ return RFunction(self, s, r_name=True) @@ -1426,9 +1416,9 @@ def chdir(self, dir): EXAMPLES:: - sage: import tempfile # optional - rpy2 - sage: tmpdir = tempfile.mkdtemp() # optional - rpy2 - sage: r.chdir(tmpdir) # optional - rpy2 + sage: import tempfile + sage: tmpdir = tempfile.mkdtemp() + sage: r.chdir(tmpdir) Check that ``tmpdir`` and ``r.getwd()`` refer to the same directory. We need to use ``realpath()`` in case ``$TMPDIR`` @@ -1436,7 +1426,7 @@ def chdir(self, dir): :: - sage: os.path.realpath(tmpdir) == sageobj(r.getwd()) # known bug (trac #9970) # optional - rpy2 + sage: os.path.realpath(tmpdir) == sageobj(r.getwd()) # known bug (issue #9970) True """ self.execute('setwd(%r)' % dir) @@ -1455,9 +1445,9 @@ def _tab_completion(self): EXAMPLES:: - sage: a = r([1,2,3]) # optional - rpy2 - sage: t = a._tab_completion() # optional - rpy2 - sage: len(t) > 200 # optional - rpy2 + sage: a = r([1,2,3]) + sage: t = a._tab_completion() + sage: len(t) > 200 True """ # TODO: rewrite it, just take methods(class=class(self)) @@ -1469,7 +1459,6 @@ def tilde(self, x): EXAMPLES:: - sage: # optional - rpy2 sage: x = r([1,2,3,4,5]) sage: y = r([3,5,7,9,11]) sage: a = r.lm( y.tilde(x) ) # lm( y ~ x ) @@ -1489,9 +1478,9 @@ def is_string(self): EXAMPLES:: - sage: r('"abc"').is_string() # optional - rpy2 + sage: r('"abc"').is_string() True - sage: r([1,2,3]).is_string() # optional - rpy2 + sage: r([1,2,3]).is_string() False """ @@ -1505,8 +1494,8 @@ def __len__(self): EXAMPLES:: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: len(x) # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: len(x) 5 """ return self.parent()('length(%s)' % self.name()).sage() @@ -1524,7 +1513,6 @@ def __getattr__(self, attrname): EXAMPLES:: - sage: # optional - rpy2 sage: x = r([1,2,3]) sage: length = x.length sage: type(length) @@ -1555,7 +1543,6 @@ def __getitem__(self, n): EXAMPLES:: - sage: # optional - rpy2 sage: x = r([10.4,5.6,3.1,6.4,21.7]) sage: x[0] numeric(0) @@ -1614,7 +1601,6 @@ def __bool__(self): EXAMPLES:: - sage: # optional - rpy2 sage: x = r([10.4,5.6,3.1,6.4,21.7]) sage: bool(x) True @@ -1641,8 +1627,8 @@ def _comparison(self, other, symbol): TESTS:: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x._comparison(10.4, "==") # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x._comparison(10.4, "==") [1] TRUE FALSE FALSE FALSE FALSE """ P = self.parent() @@ -1663,8 +1649,8 @@ def __eq__(self, other): Notice that comparison is term by term and returns an R element. :: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x == 10.4 # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x == 10.4 [1] TRUE FALSE FALSE FALSE FALSE """ return self._comparison(other, "==") @@ -1683,8 +1669,8 @@ def __lt__(self, other): Notice that comparison is term by term and returns an R element. :: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x < 7 # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x < 7 [1] FALSE TRUE TRUE TRUE FALSE """ return self._comparison(other, "<") @@ -1703,8 +1689,8 @@ def __gt__(self, other): Notice that comparison is term by term and returns an R element. :: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x > 8 # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x > 8 [1] TRUE FALSE FALSE FALSE TRUE """ return self._comparison(other, ">") @@ -1721,8 +1707,8 @@ def __le__(self, other): EXAMPLES:: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x <= 10.4 # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x <= 10.4 [1] TRUE TRUE TRUE TRUE FALSE """ return self._comparison(other, "<=") @@ -1739,8 +1725,8 @@ def __ge__(self, other): EXAMPLES:: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x >= 10.4 # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x >= 10.4 [1] TRUE FALSE FALSE FALSE TRUE """ return self._comparison(other, ">=") @@ -1757,8 +1743,8 @@ def __ne__(self, other): EXAMPLES:: - sage: x = r([10.4,5.6,3.1,6.4,21.7]) # optional - rpy2 - sage: x != 10.4 # optional - rpy2 + sage: x = r([10.4,5.6,3.1,6.4,21.7]) + sage: x != 10.4 [1] FALSE TRUE TRUE TRUE TRUE """ @@ -1776,16 +1762,16 @@ def dot_product(self, other): EXAMPLES:: - sage: c = r.c(1,2,3,4) # optional - rpy2 - sage: c.dot_product(c.t()) # optional - rpy2 + sage: c = r.c(1,2,3,4) + sage: c.dot_product(c.t()) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 2 4 6 8 [3,] 3 6 9 12 [4,] 4 8 12 16 - sage: v = r([3,-1,8]) # optional - rpy2 - sage: v.dot_product(v) # optional - rpy2 + sage: v = r([3,-1,8]) + sage: v.dot_product(v) [,1] [1,] 74 """ @@ -1808,9 +1794,9 @@ def _sage_(self): EXAMPLES:: - sage: rs = r.summary(r.c(1,4,3,4,3,2,5,1)) # optional - rpy2 - sage: d = rs._sage_() # optional - rpy2 - sage: sorted(d.items()) # optional - rpy2 + sage: rs = r.summary(r.c(1,4,3,4,3,2,5,1)) + sage: d = rs._sage_() + sage: sorted(d.items()) [('DATA', [1, 1.75, 3, 2.875, 4, 5]), ('_Names', ['Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.']), ('_r_class', ['summaryDefault', 'table'])] @@ -1831,7 +1817,7 @@ def _latex_(self): EXAMPLES:: - sage: latex(r(2)) # optional - Hmisc (R package) # optional - rpy2 + sage: latex(r(2)) # optional - Hmisc (R package) 2 """ from sage.misc.latex import LatexExpr @@ -1851,10 +1837,10 @@ def __reduce__(self): """ EXAMPLES:: - sage: a = r([1,2,3]) # optional - rpy2 - sage: a.mean # optional - rpy2 + sage: a = r([1,2,3]) + sage: a.mean mean - sage: dumps(a.mean) # optional - rpy2 + sage: dumps(a.mean) Traceback (most recent call last): ... NotImplementedError: pickling of R element methods is not yet supported @@ -1867,9 +1853,9 @@ def _instancedoc_(self): EXAMPLES:: - sage: a = r([1,2,3]) # optional - rpy2 - sage: length = a.length # optional - rpy2 - sage: print(length.__doc__) # optional - rpy2 + sage: a = r([1,2,3]) + sage: length = a.length + sage: print(length.__doc__) title ----- @@ -1890,9 +1876,9 @@ def _sage_src_(self): EXAMPLES:: - sage: a = r([1,2,3]) # optional - rpy2 - sage: length = a.length # optional - rpy2 - sage: print(length._sage_src_()) # optional - rpy2 + sage: a = r([1,2,3]) + sage: length = a.length + sage: print(length._sage_src_()) function (x) .Primitive("length") """ M = self._obj.parent() @@ -1902,9 +1888,9 @@ def __call__(self, *args, **kwds): """ EXAMPLES:: - sage: a = r([1,2,3]) # optional - rpy2 - sage: length = a.length # optional - rpy2 - sage: length() # optional - rpy2 + sage: a = r([1,2,3]) + sage: length = a.length + sage: length() [1] 3 """ return self._obj.parent().function_call(self._name, args=[self._obj] + list(args), kwds=kwds) @@ -1924,10 +1910,10 @@ def __init__(self, parent, name, r_name=None): EXAMPLES:: - sage: length = r.length # optional - rpy2 - sage: type(length) # optional - rpy2 + sage: length = r.length + sage: type(length) - sage: loads(dumps(length)) # optional - rpy2 + sage: loads(dumps(length)) length """ self._parent = parent @@ -1940,9 +1926,9 @@ def __eq__(self, other): """ EXAMPLES:: - sage: r.mean == loads(dumps(r.mean)) # optional - rpy2 + sage: r.mean == loads(dumps(r.mean)) True - sage: r.mean == r.lr # optional - rpy2 + sage: r.mean == r.lr False """ return (isinstance(other, RFunction) and @@ -1952,9 +1938,9 @@ def __ne__(self, other): """ EXAMPLES:: - sage: r.mean != loads(dumps(r.mean)) # optional - rpy2 + sage: r.mean != loads(dumps(r.mean)) False - sage: r.mean != r.lr # optional - rpy2 + sage: r.mean != r.lr True """ return not (self == other) @@ -1965,8 +1951,8 @@ def _instancedoc_(self): EXAMPLES:: - sage: length = r.length # optional - rpy2 - sage: print(length.__doc__) # optional - rpy2 + sage: length = r.length + sage: print(length.__doc__) title ----- @@ -1987,8 +1973,8 @@ def _sage_src_(self): EXAMPLES:: - sage: length = r.length # optional - rpy2 - sage: print(length._sage_src_()) # optional - rpy2 + sage: length = r.length + sage: print(length._sage_src_()) function (x) .Primitive("length") """ @@ -1999,8 +1985,8 @@ def __call__(self, *args, **kwds): """ EXAMPLES:: - sage: length = r.length # optional - rpy2 - sage: length([1,2,3]) # optional - rpy2 + sage: length = r.length + sage: length([1,2,3]) [1] 3 """ return self._parent.function_call(self._name, args=list(args), kwds=kwds) @@ -2018,12 +2004,12 @@ def is_RElement(x): EXAMPLES:: - sage: from sage.interfaces.r import is_RElement # optional - rpy2 - sage: is_RElement(2) # optional - rpy2 + sage: from sage.interfaces.r import is_RElement + sage: is_RElement(2) doctest:...: DeprecationWarning: the function is_RElement is deprecated; use isinstance(x, sage.interfaces.abc.RElement) instead See https://github.com/sagemath/sage/issues/34804 for details. False - sage: is_RElement(r(2)) # optional - rpy2 + sage: is_RElement(r(2)) True """ from sage.misc.superseded import deprecation @@ -2042,8 +2028,8 @@ def reduce_load_R(): EXAMPLES:: - sage: from sage.interfaces.r import reduce_load_R # optional - rpy2 - sage: reduce_load_R() # optional - rpy2 + sage: from sage.interfaces.r import reduce_load_R + sage: reduce_load_R() R Interpreter """ return r @@ -2055,7 +2041,7 @@ def r_console(): EXAMPLES:: - sage: r.console() # not tested # optional - rpy2 + sage: r.console() # not tested R version 2.6.1 (2007-11-26) Copyright (C) 2007 The R Foundation for Statistical Computing ISBN 3-900051-07-0 @@ -2074,7 +2060,6 @@ def r_version(): EXAMPLES:: - sage: # optional - rpy2 sage: r_version() # not tested ((3, 0, 1), 'R version 3.0.1 (2013-05-16)') sage: rint, rstr = r_version() @@ -2098,10 +2083,10 @@ def __repr__(self): EXAMPLES:: - sage: a = sage.interfaces.r.HelpExpression("This\nis\nR!") # optional - rpy2 - sage: type(a) # optional - rpy2 + sage: a = sage.interfaces.r.HelpExpression("This\nis\nR!") + sage: type(a) - sage: a # optional - rpy2 + sage: a This is R! diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index f89f38dda0b..c0ab80e0a68 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -468,6 +468,7 @@ def __reduce__(self): """ EXAMPLES:: + sage: from sage.interfaces.singular import singular sage: singular.__reduce__() (, ()) """ diff --git a/src/sage/lfunctions/dokchitser.py b/src/sage/lfunctions/dokchitser.py index a5b5393fca4..f8a7465521f 100644 --- a/src/sage/lfunctions/dokchitser.py +++ b/src/sage/lfunctions/dokchitser.py @@ -467,12 +467,12 @@ def repl(m): raise TypeError("v (=%s) must be a list, tuple, or string" % v) else: CC = self.__CC - v = ','.join([CC(a)._pari_init_() for a in v]) + v = ','.join(CC(a)._pari_init_() for a in v) self._gp_eval('Avec = [%s]' % v) if w is None: self._gp_call_inst('initLdata', '"Avec[k]"', cutoff) else: - w = ','.join([CC(a)._pari_init_() for a in w]) + w = ','.join(CC(a)._pari_init_() for a in w) self._gp_eval('Bvec = [%s]' % w) self._gp_call_inst('initLdata', '"Avec[k]"', cutoff, '"Bvec[k]"') diff --git a/src/sage/libs/eclib/mwrank.pyx b/src/sage/libs/eclib/mwrank.pyx index 206097e3fc4..c4f9ed87d18 100644 --- a/src/sage/libs/eclib/mwrank.pyx +++ b/src/sage/libs/eclib/mwrank.pyx @@ -154,7 +154,7 @@ def initprimes(filename, verb=False): sage: import tempfile sage: with tempfile.NamedTemporaryFile(mode='w+t') as f: - ....: data = ' '.join([str(p) for p in prime_range(10^7,10^7+20)]) + ....: data = ' '.join(str(p) for p in prime_range(10^7, 10^7 + 20)) ....: _ = f.write(data) ....: f.flush() ....: mwrank_initprimes(f.name, verb=True) diff --git a/src/sage/libs/glpk/error.pyx b/src/sage/libs/glpk/error.pyx deleted file mode 100644 index 0ba90710023..00000000000 --- a/src/sage/libs/glpk/error.pyx +++ /dev/null @@ -1,120 +0,0 @@ -""" -Error handler for the GLPK library -""" - -# **************************************************************************** -# Copyright (C) 2015 Jeroen Demeyer -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from cysignals.signals cimport sig_error - -from sage.libs.glpk.env cimport * -from cpython.exc cimport PyErr_SetObject -from sage.cpython.string cimport char_to_str -from sage.numerical.mip import MIPSolverException - - -class GLPKError(MIPSolverException): - """ - A low-level error that is raised by ``sage_glpk_term_hook``. - - The GLPK API considers these errors non-recoverable. - User code should not try to catch this exception. - - EXAMPLES:: - - sage: from sage.libs.glpk.error import GLPKError - sage: raise GLPKError("trouble") - Traceback (most recent call last): - ... - GLPKError: trouble - """ - pass - - -# Global error message string -cdef error_message = "" - - -cdef int sage_glpk_term_hook(void *info, const char *s) noexcept with gil: - """ - A hook to intercept all output written by GLPK. - """ - global error_message - if glp_at_error(): - # Save error message and skip normal printing - error_message += char_to_str(s) - return 1 - else: - # Normal non-error output: the return value 0 means that GLPK - # will write the output as usual. - return 0 - - -cdef void sage_glpk_error_hook(void *info) noexcept with gil: - """ - A hook to intercept GLPK errors. - """ - global error_message - PyErr_SetObject(GLPKError, error_message.strip()) - error_message = "" - sig_error() - - -def setup_glpk_error_handler(): - r""" - Setup the GLPK error handler. Called automatically when this module - is imported at Sage startup. - - We install this error handler so that an error does not lead to - an immediate error exit of the process. Instead, we raise a - ``GLPKError`` for the convenience of developers. - - The GLPK API considers errors non-recoverable. - Therefore, user code should not try to catch this exception. - - TESTS:: - - sage: cython( # optional - glpk_error_recovery_patch - ....: ''' - ....: # distutils: libraries = glpk z gmp - ....: from cysignals.signals cimport sig_on, sig_off - ....: from sage.libs.glpk.env cimport glp_term_out - ....: sig_on() - ....: glp_term_out(12345) # invalid value - ....: sig_off() - ....: ''') - Traceback (most recent call last): - ... - GLPKError: glp_term_out: flag = 12345; invalid parameter - Error detected in file env/stdout.c at line ... - - Check that normal terminal output still works, see :issue:`20832`:: - - sage: def verbose_GLPK(): - ....: from sage.numerical.backends.generic_backend import get_solver - ....: s = get_solver(solver = "GLPK") - ....: s.set_verbosity(2) - ....: return s - sage: p = MixedIntegerLinearProgram(solver=verbose_GLPK) - sage: x, y = p['x'], p['y'] - sage: p.add_constraint(2*x + 3*y <= 6) - sage: p.add_constraint(3*x + 2*y <= 6) - sage: p.add_constraint(x >= 0) - sage: p.set_objective(x + y) - sage: print('output', flush=True); res = p.solve() - output ... 0: obj = ... - sage: res # rel tol 1e-15 - 2.4 - """ - glp_term_hook(sage_glpk_term_hook, NULL) - glp_error_hook(sage_glpk_error_hook, NULL) - - -setup_glpk_error_handler() diff --git a/src/sage/libs/gmp/pylong.pyx b/src/sage/libs/gmp/pylong.pyx index 660cdbbae58..30366841177 100644 --- a/src/sage/libs/gmp/pylong.pyx +++ b/src/sage/libs/gmp/pylong.pyx @@ -22,11 +22,9 @@ AUTHORS: # 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 cpython.object cimport Py_SIZE from cpython.long cimport PyLong_FromLong from cpython.longintrepr cimport _PyLong_New, py_long, digit, PyLong_SHIFT from sage.cpython.pycore_long cimport (ob_digit, _PyLong_IsNegative, diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index e9a55b48cbc..a39ee7ee2b5 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -29,7 +29,6 @@ include 'decl.pxi' from cpython.object cimport Py_EQ, Py_NE from sage.cpython.string cimport char_to_str from sage.rings.integer cimport Integer -from sage.libs.ntl.convert cimport PyLong_to_ZZ from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class diff --git a/src/sage/libs/pari/convert_sage_real_mpfr.pyx b/src/sage/libs/pari/convert_sage_real_mpfr.pyx index 4546c3def24..98db6023dc9 100644 --- a/src/sage/libs/pari/convert_sage_real_mpfr.pyx +++ b/src/sage/libs/pari/convert_sage_real_mpfr.pyx @@ -2,11 +2,11 @@ from cypari2.stack cimport new_gen from cypari2.paridecl cimport * -from cysignals.signals cimport sig_on, sig_off +from cysignals.signals cimport sig_on from sage.libs.gmp.mpz cimport * from sage.libs.mpfr cimport * -from sage.libs.mpfr.types cimport mpfr_t, mpfr_prec_t +from sage.libs.mpfr.types cimport mpfr_prec_t from sage.rings.real_mpfr cimport RealField_class, RealField diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index c5280bbe578..83edc74c16d 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -42,7 +42,7 @@ from sage.categories.commutative_rings import CommutativeRings from sage.categories.rings import Rings import sage.rings.abc -from sage.rings.integer_ring import is_IntegerRing +from sage.rings.integer_ring import IntegerRing_class import sage.modules.free_module @@ -5975,7 +5975,7 @@ cdef class Matrix(sage.structure.element.Matrix): return (~self.lift_centered()).change_ring(R) except (TypeError, ZeroDivisionError): raise ZeroDivisionError("input matrix must be nonsingular") - elif algorithm is None and is_IntegerRing(R): + elif algorithm is None and isinstance(R, IntegerRing_class): try: return (~self).change_ring(R) except (TypeError, ZeroDivisionError): diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index e03d45a212d..a810418389c 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -291,9 +291,9 @@ cdef class Matrix(Matrix0): sage: a._mathematica_init_() # needs sage.symbolic '{{Pi, Sin[x]}, {Cos[x], Exp[-1]}}' """ - return '{' + ', '.join([v._mathematica_init_() for v in self.rows()]) + '}' + return '{' + ', '.join(v._mathematica_init_() for v in self.rows()) + '}' - def _magma_init_(self, magma): + def _magma_init_(self, magma) -> str: r""" Return a string that evaluates in the given Magma session to this matrix. diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index c0f1d646340..0b51d5c1df7 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -82,7 +82,6 @@ from cysignals.signals cimport sig_check from sage.categories.fields import Fields from sage.categories.integral_domains import IntegralDomains -from sage.categories.principal_ideal_domains import PrincipalIdealDomains from sage.categories.rings import Rings from sage.misc.lazy_string import lazy_string from sage.misc.randstate cimport current_randstate @@ -93,14 +92,14 @@ from sage.structure.element import Vector from sage.structure.element cimport have_same_parent from sage.misc.verbose import verbose from sage.rings.number_field.number_field_base import NumberField -from sage.rings.integer_ring import ZZ, is_IntegerRing -from sage.rings.rational_field import QQ, is_RationalField +from sage.rings.integer_ring import ZZ, IntegerRing_class +from sage.rings.rational_field import QQ, RationalField import sage.rings.abc from sage.arith.numerical_approx cimport digits_to_bits import sage.modules.free_module from sage.matrix import berlekamp_massey -from sage.modules.free_module_element import is_FreeModuleElement +from sage.modules.free_module_element import FreeModuleElement from sage.matrix.matrix_misc import permanental_minor_polynomial from sage.misc.misc_c import prod @@ -221,8 +220,8 @@ cdef class Matrix(Matrix1): return matrix([a.subs(*args, **kwds) for a in self.list()], nrows=self._nrows, ncols=self._ncols, sparse=False) - def solve_left(self, B, check=True): - """ + def solve_left(self, B, check=True, *, extend=True): + r""" Try to find a solution `X` to the equation `X A = B`. If ``self`` is a matrix `A`, then this function returns a @@ -235,16 +234,17 @@ cdef class Matrix(Matrix1): field, this method computes a least-squares solution if the system is not square. - .. NOTE:: - - In Sage one can also write ``B / A`` for - ``A.solve_left(B)``, that is, Sage implements "the - MATLAB/Octave slash operator". - INPUT: - ``B`` -- a matrix or vector + - ``extend`` -- boolean (default: ``True``); when set to ``True``, + some solvers will return solutions over a larger ring than the + base ring of the inputs (a typical case are rational solutions + for integer linear systems). When set to ``False``, a solution + over the base ring is returned, with a :class:`ValueError` + being raised if none exists. + - ``check`` -- boolean (default: ``True``); verify the answer if the system is non-square or rank-deficient, and if its entries lie in an exact ring. Meaningless over most inexact @@ -446,16 +446,16 @@ cdef class Matrix(Matrix1): """ if isinstance(B, Vector): try: - return self.transpose().solve_right(B, check=check) + return self.transpose().solve_right(B, check=check, extend=extend) except ValueError as e: raise e.__class__(str(e).replace('row', 'column')) else: try: - return self.transpose().solve_right(B.transpose(), check=check).transpose() + return self.transpose().solve_right(B.transpose(), check=check, extend=extend).transpose() except ValueError as e: raise e.__class__(str(e).replace('row', 'column')) - def solve_right(self, B, check=True): + def solve_right(self, B, check=True, *, extend=True): r""" Try to find a solution `X` to the equation `A X = B`. @@ -469,16 +469,17 @@ cdef class Matrix(Matrix1): field, this method computes a least-squares solution if the system is not square. - .. NOTE:: - - DEPRECATED. In Sage one can also write ``A \ B`` for - ``A.solve_right(B)``, that is, Sage implements "the - MATLAB/Octave backslash operator". - INPUT: - ``B`` -- a matrix or vector + - ``extend`` -- boolean (default: ``True``); when set to ``True``, + some solvers will return solutions over a larger ring than the + base ring of the inputs (a typical case are rational solutions + for integer linear systems). When set to ``False``, a solution + over the base ring is returned, with a :class:`ValueError` + being raised if none exists. + - ``check`` -- boolean (default: ``True``); verify the answer if the system is non-square or rank-deficient, and if its entries lie in an exact ring. Meaningless over most inexact @@ -897,7 +898,7 @@ cdef class Matrix(Matrix1): L = B.base_ring() # first coerce both elements to parent over same base ring P = K if L is K else coercion_model.common_parent(K, L) - if P not in _Fields and P.is_integral_domain(): + if P not in _Fields and P.is_integral_domain() and extend: # the non-integral-domain case is handled separatedly below P = P.fraction_field() if L is not P: @@ -944,6 +945,13 @@ cdef class Matrix(Matrix1): C = B.column() if b_is_vec else B + if not extend: + try: + X = self._solve_right_hermite_form(C) + except NotImplementedError: + X = self._solve_right_smith_form(C) + return X.column(0) if b_is_vec else X + if not self.is_square(): X = self._solve_right_general(C, check=check) else: @@ -952,11 +960,7 @@ cdef class Matrix(Matrix1): except NotFullRankError: X = self._solve_right_general(C, check=check) - if b_is_vec: - # Convert back to a vector - return X.column(0) - else: - return X + return X.column(0) if b_is_vec else X def _solve_right_nonsingular_square(self, B, check_rank=True): r""" @@ -1071,6 +1075,138 @@ cdef class Matrix(Matrix1): raise ValueError("matrix equation has no solutions") return X + def _solve_right_smith_form(self, B): + r""" + Solve a matrix equation over a PID using the Smith normal form. + + EXAMPLES:: + + sage: A = matrix(ZZ, 5, 7, [(1 + x^4) % 55 for x in range(5*7)]); A + [ 1 2 17 27 37 21 32] + [37 27 17 46 12 2 17] + [27 26 32 32 37 27 6] + [ 2 12 2 17 16 37 32] + [32 37 16 17 2 12 2] + + sage: y = vector(ZZ, [1, 2, 3, 4, 5]) + sage: x, = A._solve_right_smith_form(y.column()).columns() + sage: x.parent() + Ambient free module of rank 7 over the principal ideal domain Integer Ring + sage: A * x == y + True + sage: x + (10, 1530831087980480, -2969971929450215, -178745029498097, 2320752168397186, -806846536262381, -520939892126393) + + sage: z = vector(ZZ, [-4, -1, 1, 5, 14, 31, 4]) + sage: x, = A.transpose()._solve_right_smith_form(z.column()).columns() + sage: x.parent() + Ambient free module of rank 5 over the principal ideal domain Integer Ring + sage: x * A == z + True + sage: x + (-1, 0, 1, 1, -1) + + sage: X = A._solve_right_smith_form(identity_matrix(ZZ,5)) + sage: X.parent() + Full MatrixSpace of 7 by 5 dense matrices over Integer Ring + sage: X + [ -1 0 2 0 1] + [-156182670342972 -2199494166584 310625144000132 1293916 151907461896112] + [ 303010665531453 4267248023008 -602645168043247 -2510332 -294716315371323] + [ 18236418267658 256820398262 -36269645268572 -151082 -17737230430447] + [-236774176922867 -3334450741532 470910201757143 1961587 230292926737068] + [ 82318322106118 1159275026338 -163719448527234 -681977 -80065012022313] + [ 53148766104440 748485096017 -105705345467375 -440318 -51693918051894] + """ + S,U,V = self.smith_form() + + n,m = self.dimensions() + r = B.ncols() + + X_ = [] + for d, v in zip(S.diagonal(), (U*B).rows()): + if d: + X_.append(v / d) + elif v: + raise ValueError("matrix equation has no solutions") + else: + X_.append([0] * r) + + X_ += [[0] * r] * (m - n) # arbitrary + + from sage.matrix.constructor import matrix + try: + X_ = matrix(self.base_ring(), m, r, X_) + except TypeError: + raise ValueError("matrix equation has no solutions") + + return V * X_ + + def _solve_right_hermite_form(self, B): + r""" + Solve a matrix equation over a PID using the Hermite normal form. + + EXAMPLES:: + + sage: A = matrix(ZZ, 5, 7, [(1 + x^4) % 55 for x in range(5*7)]); A + [ 1 2 17 27 37 21 32] + [37 27 17 46 12 2 17] + [27 26 32 32 37 27 6] + [ 2 12 2 17 16 37 32] + [32 37 16 17 2 12 2] + + sage: y = vector(ZZ, [1, 2, 3, 4, 5]) + sage: x, = A._solve_right_hermite_form(y.column()).columns() + sage: x.parent() + Ambient free module of rank 7 over the principal ideal domain Integer Ring + sage: A * x == y + True + sage: x + (7903368738919, 1664769092987, -13561109876830, -5130794714802, 11219929764616, -2728570619520, 0) + + sage: z = vector(ZZ, [-4, -1, 1, 5, 14, 31, 4]) + sage: x, = A.transpose()._solve_right_hermite_form(z.column()).columns() + sage: x.parent() + Ambient free module of rank 5 over the principal ideal domain Integer Ring + sage: x * A == z + True + sage: x + (-1, 0, 1, 1, -1) + + sage: X = A._solve_right_hermite_form(identity_matrix(ZZ,5)) + sage: X.parent() + Full MatrixSpace of 7 by 5 dense matrices over Integer Ring + sage: X + [ 682282983347 1029536563053 550188901703 877862915448 -1147487] + [ 143716389918 216862037808 115892034032 184913433473 -241707] + [-1170705152437 -1766545243552 -944049606627 -1506293815517 1968932] + [ -442931873812 -668365722378 -357177603912 -569900577297 744938] + [ 968595469303 1461570161933 781069571508 1246248350502 -1629017] + [ -235552378240 -355438713600 -189948023680 -303074680960 396160] + [ 0 0 0 0 0] + """ + H,U = self.transpose().hermite_form(transformation=True) + H = H.transpose() + U = U.transpose() +# assert self*U == H + + n,m = self.dimensions() + r = B.ncols() + + from sage.matrix.constructor import matrix + X_ = matrix(self.base_ring(), m, r) + for i in range(min(n,m)): + v = B[i,:] + v -= H[i,:i] * X_[:i] + d = H[i][i] + try: + X_[i] = v / d + except (ZeroDivisionError, TypeError) as e: + raise ValueError("matrix equation has no solution") +# assert H*X_ == B + + return U * X_ + def prod_of_row_sums(self, cols): r""" Calculate the product of all row sums of a submatrix of `A` @@ -4538,11 +4674,11 @@ cdef class Matrix(Matrix1): algorithm = 'default' elif algorithm not in ['default', 'generic', 'flint', 'pari', 'padic', 'pluq']: raise ValueError("matrix kernel algorithm '%s' not recognized" % algorithm) - elif algorithm == 'padic' and not (is_IntegerRing(R) or is_RationalField(R)): + elif algorithm == 'padic' and not (isinstance(R, IntegerRing_class) or isinstance(R, RationalField)): raise ValueError("'padic' matrix kernel algorithm only available over the rationals and the integers, not over %s" % R) - elif algorithm == 'flint' and not (is_IntegerRing(R) or is_RationalField(R)): + elif algorithm == 'flint' and not (isinstance(R, IntegerRing_class) or isinstance(R, RationalField)): raise ValueError("'flint' matrix kernel algorithm only available over the rationals and the integers, not over %s" % R) - elif algorithm == 'pari' and not (is_IntegerRing(R) or (isinstance(R, NumberField) and not is_RationalField(R))): + elif algorithm == 'pari' and not (isinstance(R, IntegerRing_class) or (isinstance(R, NumberField) and not isinstance(R, RationalField))): raise ValueError("'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over %s" % R) elif algorithm == 'generic' and R not in _Fields: raise ValueError("'generic' matrix kernel algorithm only available over a field, not over %s" % R) @@ -4557,7 +4693,7 @@ cdef class Matrix(Matrix1): raise ValueError("matrix kernel basis format '%s' not recognized" % basis) elif basis == 'pivot' and R not in _Fields: raise ValueError('pivot basis only available over a field, not over %s' % R) - elif basis == 'LLL' and not is_IntegerRing(R): + elif basis == 'LLL' and not isinstance(R, IntegerRing_class): raise ValueError('LLL-reduced basis only available over the integers, not over %s' % R) if basis == 'default': basis = 'echelon' if R in _Fields else 'computed' @@ -4566,7 +4702,7 @@ cdef class Matrix(Matrix1): proof = kwds.pop('proof', None) if proof not in [None, True, False]: raise ValueError("'proof' must be one of True, False or None, not %s" % proof) - if not (proof is None or is_IntegerRing(R)): + if not (proof is None or isinstance(R, IntegerRing_class)): raise ValueError("'proof' flag only valid for matrices over the integers") # We could sanitize/process remaining (un-popped) keywords here and @@ -6017,7 +6153,7 @@ cdef class Matrix(Matrix1): """ if v == 0: return [] - if not is_FreeModuleElement(v): + if not isinstance(v, FreeModuleElement): raise TypeError("v must be a FreeModuleElement") VS = v.parent() V = VS.span([v]) diff --git a/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx b/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx index 3c3d77521b1..c352b52cea2 100644 --- a/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx +++ b/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx @@ -15,7 +15,7 @@ AUTHOR: # https://www.gnu.org/licenses/ # ***************************************************************************** from sage.matrix.constructor import identity_matrix -from sage.rings.polynomial.laurent_polynomial_ring_base import LaurentPolynomialRing_generic + cdef class Matrix_laurent_mpolynomial_dense(Matrix_generic_dense): """ @@ -23,14 +23,14 @@ cdef class Matrix_laurent_mpolynomial_dense(Matrix_generic_dense): """ def laurent_matrix_reduction(self): """ - From a matrix `self` of Laurent polynomials, apply elementary operations - to obtain a matrix `P` of polynomials such that the variables do not divide - no column and no row. + From a matrix ``self`` of Laurent polynomials, apply elementary operations + to obtain a matrix ``P`` of polynomials such that the variables do not divide + any column and any row. OUTPUT: - Three matrices `L`, `P`, `R` such that ``self` equals `L P R`, where `L` and - `R` are diagonal with monomial entries. + Three matrices ``L``, ``P``, ``R`` such that ``self`` equals ``L P R``, + where ``L`` and ``R`` are diagonal with monomial entries. EXAMPLES: @@ -56,12 +56,12 @@ cdef class Matrix_laurent_mpolynomial_dense(Matrix_generic_dense): res = self.__copy__() for j, rw in enumerate(res.rows()): for t in R.gens(): - n = min(mon.degree(t) for a in rw for cf, mon in a) + n = min(mon.degree(t) for a in rw for _, mon in a) res.rescale_row(j, t ** -n) mat_l.rescale_col(j, t ** n) for j, cl in enumerate(res.columns()): for t in R.gens(): - n = min(mon.degree(t) for a in cl for cf, mon in a) + n = min(mon.degree(t) for a in cl for _, mon in a) res.rescale_col(j, t ** -n) mat_r.rescale_row(j, t ** n) res = res.change_ring(R.polynomial_ring()) @@ -69,7 +69,9 @@ cdef class Matrix_laurent_mpolynomial_dense(Matrix_generic_dense): def _fitting_ideal(self, i): r""" - Return the `i`-th Fitting ideal of the matrix. This is the ideal generated + Return the `i`-th Fitting ideal of the matrix. + + This is the ideal generated by the `n - i` minors, where `n` is the number of columns. INPUT: diff --git a/src/sage/matrix/matrix_mpolynomial_dense.pyx b/src/sage/matrix/matrix_mpolynomial_dense.pyx index 5a0719ded4d..8117911fa38 100644 --- a/src/sage/matrix/matrix_mpolynomial_dense.pyx +++ b/src/sage/matrix/matrix_mpolynomial_dense.pyx @@ -24,9 +24,7 @@ from sage.matrix.matrix2 cimport Matrix from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular -from sage.libs.singular.function import singular_function, lib - -from cysignals.signals cimport sig_on, sig_off +from sage.libs.singular.function import singular_function cdef class Matrix_mpolynomial_dense(Matrix_generic_dense): @@ -518,7 +516,7 @@ cdef class Matrix_mpolynomial_dense(Matrix_generic_dense): def determinant(self, algorithm=None): """ - Return the determinant of this matrix + Return the determinant of this matrix. INPUT: diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index 27650a74482..60ef434904a 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -110,7 +110,7 @@ from sage.matrix.args cimport SparseEntry, MatrixArgs_init from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense, _lift_crt from sage.structure.element cimport Element, Vector from sage.rings.integer cimport Integer -from sage.rings.integer_ring import ZZ, is_IntegerRing +from sage.rings.integer_ring import ZZ, IntegerRing_class import sage.rings.abc from sage.rings.rational_field import QQ @@ -1465,7 +1465,7 @@ cdef class Matrix_rational_dense(Matrix_dense): if self._is_immutable: return self return self.__copy__() - if is_IntegerRing(R): + if isinstance(R, IntegerRing_class): A, d = self._clear_denom() if not d.is_one(): raise TypeError("matrix has denominators so can't change to ZZ") diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 473d961d090..71eb305c2be 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -402,7 +402,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): if R.order() < matrix_modn_sparse.MAX_MODULUS: return matrix_modn_sparse.Matrix_modn_sparse - if sage.rings.rational_field.is_RationalField(R): + if isinstance(R, sage.rings.rational_field.RationalField): try: from . import matrix_rational_sparse except ImportError: @@ -410,7 +410,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): else: return matrix_rational_sparse.Matrix_rational_sparse - if sage.rings.integer_ring.is_IntegerRing(R): + if isinstance(R, sage.rings.integer_ring.IntegerRing_class): try: from . import matrix_integer_sparse except ImportError: diff --git a/src/sage/matroids/graphic_matroid.pyx b/src/sage/matroids/graphic_matroid.pyx index 13ceb7d77ce..2f6287fba8d 100644 --- a/src/sage/matroids/graphic_matroid.pyx +++ b/src/sage/matroids/graphic_matroid.pyx @@ -87,7 +87,7 @@ AUTHORS: # **************************************************************************** from sage.matroids.matroid cimport Matroid -from copy import copy, deepcopy +from copy import copy from sage.matroids.utilities import newlabel, split_vertex, sanitize_contractions_deletions from itertools import combinations from sage.rings.integer import Integer diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index d74751597c3..ebb1bf2a711 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -111,7 +111,7 @@ Methods # https://www.gnu.org/licenses/ # **************************************************************************** -from copy import copy, deepcopy +from copy import copy from itertools import product from cpython.object cimport Py_EQ, Py_NE diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index cc920ff09a2..5787505313c 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -582,6 +582,7 @@ cdef class CmpKeyNamed: _cmp_key_named = CmpKeyNamed() + ############################################################################## def C3_merge(list lists): @@ -660,6 +661,7 @@ def C3_merge(list lists): raise ValueError("Cannot merge the items %s."%', '.join(repr(head) for head in heads)) return out + cpdef identity(x): r""" EXAMPLES:: @@ -1355,7 +1357,6 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): super_classes = (object,) return dynamic_class("%s.cls"%self, super_classes) - @cached_method def all_bases(self): """ diff --git a/src/sage/misc/cachefunc.pyx b/src/sage/misc/cachefunc.pyx index cca3f28727f..597dfc5d049 100644 --- a/src/sage/misc/cachefunc.pyx +++ b/src/sage/misc/cachefunc.pyx @@ -457,6 +457,7 @@ cdef frozenset special_method_names = frozenset(['__abs__', '__add__', '__rtruediv__', '__rxor__', '__set__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__sub__', '__subclasscheck__', '__truediv__', '__unicode__', '__xor__', 'next']) + def _cached_function_unpickle(module, name, cache=None): """ Unpickle the cache function ``name`` defined in ``module``. @@ -505,6 +506,7 @@ def _cached_function_unpickle(module, name, cache=None): ret.cache.update(cache) return ret + cdef class NonpicklingDict(dict): r""" A special dict which does not pickle its contents. @@ -1454,6 +1456,7 @@ cdef class WeakCachedFunction(CachedFunction): weak_cached_function = decorator_keywords(WeakCachedFunction) + class CachedMethodPickle(): """ This class helps to unpickle cached methods. @@ -3017,6 +3020,7 @@ cdef class CachedSpecialMethod(CachedMethod): D[name] = Caller return Caller + @decorator_keywords def cached_method(f, name=None, key=None, do_pickle=None): """ diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 8bcbb141ce9..545e1227b0c 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -500,7 +500,7 @@ def cython_lambda(vars, expr, verbose=0, **kwds): if isinstance(vars, str): v = vars else: - v = ', '.join(['%s %s' % (typ, var) for typ, var in vars]) + v = ', '.join('%s %s' % (typ, var) for typ, var in vars) s = """ cdef class _s: diff --git a/src/sage/misc/fpickle.pyx b/src/sage/misc/fpickle.pyx index 37c26e431ba..752a2a0093a 100644 --- a/src/sage/misc/fpickle.pyx +++ b/src/sage/misc/fpickle.pyx @@ -61,6 +61,7 @@ def reduce_code(co): copyreg.pickle(types.CodeType, reduce_code) + def pickle_function(func): """ Pickle the Python function func. This is not a normal pickle; you diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index 9c2af93adeb..422aa90b89b 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -1934,7 +1934,7 @@ def png(x, filename, density=150, debug=False, ....: png(ZZ[x], f.name) """ import sage.plot.all - if sage.plot.graphics.is_Graphics(x): + if isinstance(x, sage.plot.graphics.Graphics): x.save(filename) return # if not graphics: create a string of latex code to write in a file diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 96183640a6c..6d845188adc 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -1136,6 +1136,7 @@ def lazy_import(module, names, as_=None, *, star_imports = None + def save_cache_file(): """ Used to save the cached * import names. @@ -1158,6 +1159,7 @@ def save_cache_file(): with atomic_write(cache_file, binary=True) as f: pickle.dump(star_imports, f) + def get_star_imports(module_name): """ Lookup the list of names in a module that would be imported with "import \\*" diff --git a/src/sage/misc/lazy_string.pyx b/src/sage/misc/lazy_string.pyx index 1af6efd42ee..a37b712c3cc 100644 --- a/src/sage/misc/lazy_string.pyx +++ b/src/sage/misc/lazy_string.pyx @@ -61,6 +61,7 @@ from cpython.object cimport PyObject_Call, PyObject_RichCompare import types + def is_lazy_string(obj): """ Checks if the given object is a lazy string. @@ -75,6 +76,7 @@ def is_lazy_string(obj): """ return isinstance(obj, _LazyString) + def lazy_string(f, *args, **kwargs): """ Creates a lazy string. @@ -86,7 +88,6 @@ def lazy_string(f, *args, **kwargs): applying it as a format string - named arguments, that are forwarded to ``f`` if it is not a string - EXAMPLES:: sage: from sage.misc.lazy_string import lazy_string @@ -131,6 +132,7 @@ def _make_lazy_string(ftype, fpickle, args, kwargs): f = fpickle return _LazyString(f, args, kwargs) + cdef class _LazyString(): """ Lazy class for strings created by a function call or a format string. diff --git a/src/sage/misc/misc_c.pyx b/src/sage/misc/misc_c.pyx index be5e05e441b..695806cdf69 100644 --- a/src/sage/misc/misc_c.pyx +++ b/src/sage/misc/misc_c.pyx @@ -23,6 +23,7 @@ AUTHORS: # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** +from copy import copy from cpython.sequence cimport * from cpython.list cimport * @@ -305,8 +306,6 @@ class NonAssociative: """ return NonAssociative(self, other) -from copy import copy - def balanced_sum(x, z=None, Py_ssize_t recursion_cutoff=5): """ @@ -398,6 +397,7 @@ def balanced_sum(x, z=None, Py_ssize_t recursion_cutoff=5): return sum + cdef balanced_list_sum(L, Py_ssize_t offset, Py_ssize_t count, Py_ssize_t cutoff): """ INPUT: diff --git a/src/sage/misc/nested_class.pyx b/src/sage/misc/nested_class.pyx index 637d4c9c792..7e5d00c15d8 100644 --- a/src/sage/misc/nested_class.pyx +++ b/src/sage/misc/nested_class.pyx @@ -345,6 +345,7 @@ class MainClass(object, metaclass=NestedClassMetaclass): """ pass + class SubClass(MainClass): r""" A simple class to test nested_pickle. @@ -359,11 +360,14 @@ class SubClass(MainClass): """ pass + nested_pickle(SubClass) + def _provide_SubClass(): return SubClass + class CopiedClass(): r""" A simple class to test nested_pickle. @@ -380,8 +384,10 @@ class CopiedClass(): NestedSubClass = MainClass.NestedClass.NestedSubClass SubClass = _provide_SubClass() + nested_pickle(CopiedClass) + # Further classes for recursive tests class A1: diff --git a/src/sage/misc/parser.pyx b/src/sage/misc/parser.pyx index cbc3c67b6d6..e9015d1cbcc 100644 --- a/src/sage/misc/parser.pyx +++ b/src/sage/misc/parser.pyx @@ -37,6 +37,7 @@ def foo(*args, **kwds): """ return args, kwds + function_map = { 'foo': foo, 'sqrt': math.sqrt, @@ -45,6 +46,7 @@ function_map = { 'tan': math.tan, } + cdef enum token_types: # leave room for ASCII character tokens such as '+' INT = 128 diff --git a/src/sage/misc/persist.pyx b/src/sage/misc/persist.pyx index ec803bae77a..d299ec304cb 100644 --- a/src/sage/misc/persist.pyx +++ b/src/sage/misc/persist.pyx @@ -341,6 +341,7 @@ def dumps(obj, compress=True): # This is used below, and also by explain_pickle.py unpickle_override = {} + def register_unpickle_override(module, name, callable, call_name=None): r""" Python pickles include the module and class name of classes. @@ -1000,6 +1001,7 @@ def loads(s, compress=True, **kwargs): cdef bint make_pickle_jar = 'SAGE_PICKLE_JAR' in os.environ + def picklejar(obj, dir=None): """ Create pickled sobj of ``obj`` in ``dir``, with name the absolute diff --git a/src/sage/misc/pickle_old.pyx b/src/sage/misc/pickle_old.pyx index ede0c6abe06..3b717613b73 100644 --- a/src/sage/misc/pickle_old.pyx +++ b/src/sage/misc/pickle_old.pyx @@ -2,6 +2,7 @@ from sage.misc.superseded import deprecation_cython as deprecation import sage.rings.fraction_field_element + def make_element_old(_class, _dict, parent): """ Used for unpickling old pickles of Element objects (and subclasses). diff --git a/src/sage/misc/randstate.pyx b/src/sage/misc/randstate.pyx index 6e909df0a9f..f1aefafd68a 100644 --- a/src/sage/misc/randstate.pyx +++ b/src/sage/misc/randstate.pyx @@ -753,7 +753,6 @@ cdef class randstate: except KeyError: prev = None - if prev is not self: if self._gp_saved_seeds is not None and gp in self._gp_saved_seeds: seed = self._gp_saved_seeds[gp] @@ -969,6 +968,7 @@ cpdef int random() noexcept: """ return gmp_urandomb_ui(_current_randstate.gmp_state, 31) + def initial_seed(): r""" Returns the initial seed used to create the current :class:`randstate`. @@ -990,6 +990,7 @@ def initial_seed(): """ return _current_randstate._seed + def benchmark_libc(): r""" This function was used to test whether moving from libc to GMP's @@ -1008,6 +1009,7 @@ def benchmark_libc(): for i from 0 <= i < 100000: c_libc_random() + def benchmark_mt(): r""" This function was used to test whether moving from libc to GMP's @@ -1026,6 +1028,7 @@ def benchmark_mt(): for i from 0 <= i < 100000: gmp_urandomb_ui(rstate.gmp_state, 32) + cpdef int _doctest_libc_random() noexcept: r""" Returns the result of :func:`random()` from libc. diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py index 3ce50ffe981..025b7b96f5e 100644 --- a/src/sage/misc/sage_input.py +++ b/src/sage/misc/sage_input.py @@ -2185,7 +2185,7 @@ def __repr__(self): """ kind = "list" if self._sie_is_list else "tuple" return "{%s: (%s)}" % \ - (kind, ', '.join([repr(v) for v in self._sie_values])) + (kind, ', '.join(repr(v) for v in self._sie_values)) def _sie_referenced(self): r""" @@ -2290,8 +2290,8 @@ def __repr__(self): {dict: {{atomic:'keaton'}:{atomic:'general'}, {atomic:'chan'}:{atomic:'master'}}} """ return "{dict: {%s}}" % \ - ', '.join([repr(key) + ':' + repr(val) - for key, val in self._sie_entries]) + ', '.join(repr(key) + ':' + repr(val) + for key, val in self._sie_entries) def _sie_referenced(self): r""" @@ -2454,7 +2454,7 @@ def _sie_format(self, sif): op = self._sie_op fop = op if op == '**': - lhs = sif.format(self._sie_operands[0], _prec_exponent+1) + lhs = sif.format(self._sie_operands[0], _prec_exponent + 1) rhs = sif.format(self._sie_operands[1], _prec_exponent) if self._sie_builder.preparse(): return '%s^%s' % (lhs, rhs), _prec_exponent @@ -2475,7 +2475,7 @@ def _sie_format(self, sif): raise ValueError('Unhandled op {} in SIE_binary'.format(op)) lhs = sif.format(self._sie_operands[0], prec) - rhs = sif.format(self._sie_operands[1], prec+1) + rhs = sif.format(self._sie_operands[1], prec + 1) return '%s%s%s' % (lhs, fop, rhs), prec @@ -2857,7 +2857,7 @@ def _sie_add_command(self, sif): if len(self._sie_gens) == 1: sif._commands += '%s = %s.gen()\n' % (self._sie_gens[0]._sie_get_varname(sif), self._sie_get_varname(sif)) else: - sif._commands += '%s = %s.gens()\n' % (','.join([g._sie_get_varname(sif) for g in self._sie_gens]), self._sie_get_varname(sif)) + sif._commands += '%s = %s.gens()\n' % (','.join(g._sie_get_varname(sif) for g in self._sie_gens), self._sie_get_varname(sif)) self._sie_generated = True def _sie_format(self, sif): diff --git a/src/sage/misc/stopgap.pyx b/src/sage/misc/stopgap.pyx index 70045afcf20..0b3b6cb6c1e 100644 --- a/src/sage/misc/stopgap.pyx +++ b/src/sage/misc/stopgap.pyx @@ -9,7 +9,7 @@ Stopgaps # 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 warnings @@ -18,6 +18,7 @@ import warnings from sage.doctest import DOCTEST_MODE cdef bint ENABLED = not DOCTEST_MODE + def set_state(bint mode): """ Enable or disable the stopgap warnings. @@ -41,6 +42,7 @@ def set_state(bint mode): global ENABLED ENABLED = mode + class StopgapWarning(Warning): """ This class is used to warn users of a known issue that may produce @@ -48,9 +50,12 @@ class StopgapWarning(Warning): """ pass + warnings.filterwarnings('always', category=StopgapWarning) -cdef set _stopgap_cache = set([]) + +cdef set _stopgap_cache = set() + def stopgap(message, int issue_no): r""" diff --git a/src/sage/modular/arithgroup/farey_symbol.pyx b/src/sage/modular/arithgroup/farey_symbol.pyx index da2dfd4b7cb..604270aace7 100644 --- a/src/sage/modular/arithgroup/farey_symbol.pyx +++ b/src/sage/modular/arithgroup/farey_symbol.pyx @@ -40,7 +40,7 @@ from .congroup_gamma import Gamma_class from .congroup_sl2z import SL2Z from sage.modular.cusps import Cusp -from sage.misc.decorators import options, rename_keyword +from sage.misc.decorators import options from sage.misc.cachefunc import cached_method from sage.structure.richcmp cimport richcmp_not_equal diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index 86b7a8a29f2..e579c5090e3 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -77,7 +77,7 @@ from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.power_series_ring import PowerSeriesRing -from sage.rings.rational_field import QQ, is_RationalField +from sage.rings.rational_field import QQ, RationalField from sage.structure.element import MultiplicativeGroupElement from sage.structure.factory import UniqueFactory from sage.structure.gens_py import multiplicative_iterator @@ -172,10 +172,18 @@ def is_DirichletCharacter(x) -> bool: sage: from sage.modular.dirichlet import is_DirichletCharacter sage: is_DirichletCharacter(trivial_character(3)) + doctest:warning... + DeprecationWarning: The function is_DirichletCharacter is deprecated; + use 'isinstance(..., DirichletCharacter)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_DirichletCharacter([1]) False """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_DirichletCharacter is deprecated; " + "use 'isinstance(..., DirichletCharacter)' instead.") return isinstance(x, DirichletCharacter) @@ -262,7 +270,7 @@ def __init__(self, parent, x, check=True): orders = parent.integers_mod().unit_group().gens_orders() if len(x) != len(orders): raise ValueError("wrong number of values (= {}) on generators (want {})".format(x, len(orders))) - if free_module_element.is_FreeModuleElement(x): + if isinstance(x, free_module_element.FreeModuleElement): x = parent._module(x) if any(u * v for u, v in zip(x, orders)): raise ValueError("values (= {} modulo {}) must have additive orders dividing {}, respectively" @@ -276,7 +284,7 @@ def __init__(self, parent, x, check=True): .format(x, orders)) self.values_on_gens.set_cache(x) else: - if free_module_element.is_FreeModuleElement(x): + if isinstance(x, free_module_element.FreeModuleElement): self.element.set_cache(x) else: self.values_on_gens.set_cache(x) @@ -1386,7 +1394,7 @@ def gauss_sum(self, a=1): elif isinstance(K, sage.rings.abc.AlgebraicField): L = K zeta = L.zeta(m) - elif isinstance(K, sage.rings.abc.NumberField_cyclotomic) or is_RationalField(K): + elif isinstance(K, sage.rings.abc.NumberField_cyclotomic) or isinstance(K, RationalField): chi = chi.minimize_base_ring() n = lcm(m, G.zeta_order()) L = CyclotomicField(n) @@ -1467,7 +1475,7 @@ def phi(t): from sage.rings.complex_mpfr import ComplexField CC = ComplexField(prec) phi = CC.coerce_map_from(K) - elif isinstance(K, sage.rings.abc.NumberField_cyclotomic) or is_RationalField(K): + elif isinstance(K, sage.rings.abc.NumberField_cyclotomic) or isinstance(K, RationalField): phi = K.complex_embedding(prec) CC = phi.codomain() else: @@ -1688,7 +1696,7 @@ def kloosterman_sum_numerical(self, prec=53, a=1, b=0): """ G = self.parent() K = G.base_ring() - if not (isinstance(K, sage.rings.abc.NumberField_cyclotomic) or is_RationalField(K)): + if not (isinstance(K, sage.rings.abc.NumberField_cyclotomic) or isinstance(K, RationalField)): raise NotImplementedError("Kloosterman sums only currently implemented when the base ring is a cyclotomic field or QQ.") phi = K.complex_embedding(prec) CC = phi.codomain() diff --git a/src/sage/modular/modform/ambient_eps.py b/src/sage/modular/modform/ambient_eps.py index 1d42305436c..81527a72aa8 100644 --- a/src/sage/modular/modform/ambient_eps.py +++ b/src/sage/modular/modform/ambient_eps.py @@ -124,7 +124,7 @@ def __init__(self, character, weight=2, base_ring=None, eis_only=False): sage: type(m) """ - if not dirichlet.is_DirichletCharacter(character): + if not isinstance(character, dirichlet.DirichletCharacter): raise TypeError("character (=%s) must be a Dirichlet character" % character) if base_ring is None: base_ring = character.base_ring() diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index aa859d9c38c..72880952610 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -72,10 +72,18 @@ def is_ModularFormElement(x): sage: from sage.modular.modform.element import is_ModularFormElement sage: is_ModularFormElement(5) + doctest:warning... + DeprecationWarning: The function is_ModularFormElement is deprecated; + use 'isinstance(..., ModularFormElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. False sage: is_ModularFormElement(ModularForms(11).0) True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_ModularFormElement is deprecated; " + "use 'isinstance(..., ModularFormElement)' instead.") return isinstance(x, ModularFormElement) @@ -3265,7 +3273,7 @@ def __init__(self, parent, forms_datum): k = ZZ(k) if k == 0: forms_dictionary[k] = parent.base_ring().coerce(f) - elif is_ModularFormElement(f): + elif isinstance(f, ModularFormElement): if f.weight() == k: if parent.group().is_subgroup(f.group()) and parent.base_ring().has_coerce_map_from(f.base_ring()): M = parent.modular_forms_of_weight(f.weight()).change_ring(parent.base_ring()) @@ -3280,7 +3288,7 @@ def __init__(self, parent, forms_datum): raise ValueError('at least one key (%s) of the defining dictionary is not an integer' % (k)) elif isinstance(forms_datum, list): for f in forms_datum: - if is_ModularFormElement(f): + if isinstance(f, ModularFormElement): chi = f.character(compute=False) if (chi is not None) and (not chi.is_trivial()): raise NotImplementedError("graded modular forms for non-trivial characters is not yet implemented") diff --git a/src/sage/modular/modform/hecke_operator_on_qexp.py b/src/sage/modular/modform/hecke_operator_on_qexp.py index ea472bb4185..daf4c3bfbec 100644 --- a/src/sage/modular/modform/hecke_operator_on_qexp.py +++ b/src/sage/modular/modform/hecke_operator_on_qexp.py @@ -23,8 +23,8 @@ lazy_import('sage.rings.number_field.number_field', 'CyclotomicField') -from sage.modular.dirichlet import DirichletGroup, is_DirichletCharacter -from .element import is_ModularFormElement +from sage.modular.dirichlet import DirichletGroup, DirichletCharacter +from .element import ModularFormElement def hecke_operator_on_qexp(f, n, k, eps=None, prec=None, check=True, _return_list=False): @@ -87,16 +87,16 @@ def hecke_operator_on_qexp(f, n, k, eps=None, # ZZ can coerce to GF(p), but QQ can't. eps = DirichletGroup(1, base_ring=ZZ)[0] if check: - if not (is_PowerSeries(f) or is_ModularFormElement(f)): + if not (is_PowerSeries(f) or isinstance(f, ModularFormElement)): raise TypeError("f (=%s) must be a power series or modular form" % f) - if not is_DirichletCharacter(eps): + if not isinstance(eps, DirichletCharacter): raise TypeError("eps (=%s) must be a Dirichlet character" % eps) k = Integer(k) n = Integer(n) v = [] if prec is None: - if is_ModularFormElement(f): + if isinstance(f, ModularFormElement): # always want at least three coefficients, but not too many, unless # requested pr = max(f.prec(), f.parent().prec(), (n+1)*3) @@ -123,7 +123,7 @@ def hecke_operator_on_qexp(f, n, k, eps=None, v.append(am) if _return_list: return v - if is_ModularFormElement(f): + if isinstance(f, ModularFormElement): R = f.parent()._q_expansion_ring() else: R = f.parent() diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 897c4718107..bf7b10dc025 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -40,7 +40,7 @@ from sage.structure.richcmp import richcmp_method, richcmp from .constructor import ModularForms -from .element import is_ModularFormElement, GradedModularFormElement +from .element import ModularFormElement, GradedModularFormElement from .space import ModularFormsSpace @@ -517,7 +517,7 @@ def _element_constructor_(self, forms_datum): forms_dictionary = forms_datum elif isinstance(forms_datum, self.element_class): forms_dictionary = forms_datum._forms_dictionary - elif is_ModularFormElement(forms_datum): + elif isinstance(forms_datum, ModularFormElement): if self.group().is_subgroup(forms_datum.group()) and self.base_ring().has_coerce_map_from(forms_datum.base_ring()): forms_dictionary = {forms_datum.weight(): forms_datum} else: diff --git a/src/sage/modular/modform_hecketriangle/abstract_space.py b/src/sage/modular/modform_hecketriangle/abstract_space.py index c2148a4e543..719d8847f31 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_space.py +++ b/src/sage/modular/modform_hecketriangle/abstract_space.py @@ -17,7 +17,7 @@ from sage.matrix.constructor import matrix from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import lazy_import -from sage.modules.free_module_element import is_FreeModuleElement +from sage.modules.free_module_element import FreeModuleElement from sage.modules.free_module_element import vector from sage.rings.infinity import infinity from sage.rings.integer import Integer @@ -262,9 +262,9 @@ def _element_constructor_(self, el): return self.construct_form(el) else: return self.construct_quasi_form(el) - if is_FreeModuleElement(el) and (self.module() is P or self.ambient_module() is P): + if isinstance(el, FreeModuleElement) and (self.module() is P or self.ambient_module() is P): return self.element_from_ambient_coordinates(el) - if (not self.is_ambient()) and (isinstance(el, list) or isinstance(el, tuple) or is_FreeModuleElement(el)) and len(el) == self.rank(): + if (not self.is_ambient()) and (isinstance(el, list) or isinstance(el, tuple) or isinstance(el, FreeModuleElement)) and len(el) == self.rank(): try: return self.element_from_coordinates(el) except (ArithmeticError, TypeError): diff --git a/src/sage/modular/modform_hecketriangle/functors.py b/src/sage/modular/modform_hecketriangle/functors.py index aae555d250a..b0fdfcf5ac7 100644 --- a/src/sage/modular/modform_hecketriangle/functors.py +++ b/src/sage/modular/modform_hecketriangle/functors.py @@ -78,12 +78,12 @@ def _get_base_ring(ring, var_name="d"): True """ - # from sage.rings.fraction_field import is_FractionField + # from sage.rings.fraction_field import FractionField_generic from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.categories.pushout import FractionField as FractionFieldFunctor base_ring = ring - # if (is_FractionField(base_ring)): + # if (isinstance(base_ring, FractionField_generic)): # base_ring = base_ring.base() if (base_ring.construction() and base_ring.construction()[0] == FractionFieldFunctor()): base_ring = base_ring.construction()[1] diff --git a/src/sage/modular/modsym/ambient.py b/src/sage/modular/modsym/ambient.py index 8585de56c46..02e1bc3cb9e 100644 --- a/src/sage/modular/modsym/ambient.py +++ b/src/sage/modular/modsym/ambient.py @@ -79,7 +79,7 @@ class ``ModularSymbolsAmbient``, derived from from sage.misc.latex import latex from sage.misc.verbose import verbose from sage.modular.arithgroup.arithgroup_element import M2Z -from sage.modular.dirichlet import TrivialCharacter, is_DirichletCharacter +from sage.modular.dirichlet import DirichletCharacter, TrivialCharacter from sage.modular.hecke.ambient_module import AmbientHeckeModule from sage.modular.cusps import Cusp from sage.modular.modsym.apply import apply_to_monomial @@ -2171,7 +2171,7 @@ def twisted_winding_element(self, i, eps): sage: M.twisted_winding_element(0,eps) 2*(1,23) - 2*(1,32) + 2*(1,34) """ - if not is_DirichletCharacter(eps): + if not isinstance(eps, DirichletCharacter): raise TypeError("eps must be a Dirichlet character.") if (i < 0) or (i > self.weight() - 2): raise ValueError("i must be between 0 and k-2.") diff --git a/src/sage/modular/modsym/boundary.py b/src/sage/modular/modsym/boundary.py index 2076d81eb1e..093ba6a594f 100644 --- a/src/sage/modular/modsym/boundary.py +++ b/src/sage/modular/modsym/boundary.py @@ -93,7 +93,7 @@ from sage.structure.richcmp import richcmp_method, richcmp import sage.modules.free_module as free_module -from sage.modules.free_module_element import is_FreeModuleElement +from sage.modules.free_module_element import FreeModuleElement import sage.modular.arithgroup.all as arithgroup import sage.modular.cusps as cusps @@ -554,7 +554,7 @@ def __call__(self, x): elif isinstance(x, ManinSymbol): return self._coerce_in_manin_symbol(x) - elif element.is_ModularSymbolsElement(x): + elif isinstance(x, element.ModularSymbolsElement): M = x.parent() if not isinstance(M, ModularSymbolsAmbient): raise TypeError("x (=%s) must be an element of a space of modular symbols of type ModularSymbolsAmbient" % x) @@ -566,7 +566,7 @@ def __call__(self, x): return self(0) return sum([c * self._coerce_in_manin_symbol(v) for c, v in S]) - elif is_FreeModuleElement(x): + elif isinstance(x, FreeModuleElement): y = dict(enumerate(x)) return BoundarySpaceElement(self, y) diff --git a/src/sage/modular/modsym/element.py b/src/sage/modular/modsym/element.py index 427d9218f8d..21b1ecb181b 100644 --- a/src/sage/modular/modsym/element.py +++ b/src/sage/modular/modsym/element.py @@ -36,10 +36,18 @@ def is_ModularSymbolsElement(x) -> bool: EXAMPLES:: sage: sage.modular.modsym.element.is_ModularSymbolsElement(ModularSymbols(11, 2).0) + doctest:warning... + DeprecationWarning: The function is_ModularSymbolsElement is deprecated; + use 'isinstance(..., ModularSymbolsElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: sage.modular.modsym.element.is_ModularSymbolsElement(13) False """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_ModularSymbolsElement is deprecated; " + "use 'isinstance(..., ModularSymbolsElement)' instead.") return isinstance(x, ModularSymbolsElement) diff --git a/src/sage/modular/modsym/manin_symbol.pyx b/src/sage/modular/modsym/manin_symbol.pyx index 9bf955b562b..434aa370e18 100644 --- a/src/sage/modular/modsym/manin_symbol.pyx +++ b/src/sage/modular/modsym/manin_symbol.pyx @@ -43,10 +43,18 @@ def is_ManinSymbol(x): sage: s [Y^2,(1,2)] sage: is_ManinSymbol(s) + doctest:warning... + DeprecationWarning: The function is_ManinSymbol is deprecated; + use 'isinstance(..., ManinSymbol)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_ManinSymbol(m[3]) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38184, + "The function is_ManinSymbol is deprecated; " + "use 'isinstance(..., ManinSymbol)' instead.") return isinstance(x, ManinSymbol) diff --git a/src/sage/modular/modsym/relation_matrix.py b/src/sage/modular/modsym/relation_matrix.py index ef0e17eef6a..7d58bb62a48 100644 --- a/src/sage/modular/modsym/relation_matrix.py +++ b/src/sage/modular/modsym/relation_matrix.py @@ -27,7 +27,7 @@ from sage.misc.search import search from sage.misc.verbose import verbose from sage.modular.modsym.manin_symbol_list import ManinSymbolList -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.categories.rings import Rings @@ -498,7 +498,7 @@ def relation_matrix_wtk_g0(syms, sign, field, sparse): rels = sorted(rels) # required for stability of doctests with python3 - if syms._apply_S_only_0pm1() and is_RationalField(field): + if syms._apply_S_only_0pm1() and isinstance(field, RationalField): from . import relation_matrix_pyx mod = relation_matrix_pyx.sparse_2term_quotient_only_pm1(rels, len(syms)) else: diff --git a/src/sage/modular/pollack_stevens/padic_lseries.py b/src/sage/modular/pollack_stevens/padic_lseries.py index fa97d9fb19a..1869e8ed047 100644 --- a/src/sage/modular/pollack_stevens/padic_lseries.py +++ b/src/sage/modular/pollack_stevens/padic_lseries.py @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.ring.padics +# sage.doctest: needs sage.rings.padics r""" `p`-adic `L`-series attached to overconvergent eigensymbols @@ -174,7 +174,7 @@ def __eq__(self, other): sage: E = EllipticCurve('11a') sage: L = E.padic_lseries(11,implementation="pollackstevens",precision=6) # long time - sage: L == loads(dumps(L)) # indirect doctest long time + sage: L == loads(dumps(L)) # indirect doctest, long time True """ if not isinstance(other, pAdicLseries): diff --git a/src/sage/modules/fp_graded/steenrod/module.py b/src/sage/modules/fp_graded/steenrod/module.py index 4acfa6b4002..90160d18a19 100755 --- a/src/sage/modules/fp_graded/steenrod/module.py +++ b/src/sage/modules/fp_graded/steenrod/module.py @@ -245,7 +245,7 @@ def export_module_definition(self, powers_of_two_only=True): # Print the degrees of the additive generators. ret = '%d %s' % (len(additive_generator_degrees), - ' '.join(['%d' % x for x in additive_generator_degrees])) + ' '.join('%d' % x for x in additive_generator_degrees)) # A private function which transforms a vector in a given dimension # to a vector of global indices for the basis elements corresponding diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index ad94efcc94b..6bf1b79bd7d 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -783,7 +783,7 @@ def span(gens, base_ring=None, check=True, already_echelonized=False): return FreeModule(R, 0) else: x = gens[0] - if free_module_element.is_FreeModuleElement(x): + if isinstance(x, free_module_element.FreeModuleElement): M = x.parent() else: try: @@ -3823,7 +3823,7 @@ def index_in(self, other): return sage.rings.infinity.infinity a = sage.matrix.matrix_space.MatrixSpace(self.base_field(), self.rank())(C).determinant() - if sage.rings.integer_ring.is_IntegerRing(self.base_ring()): + if isinstance(self.base_ring(), sage.rings.integer_ring.IntegerRing_class): return a.abs() elif isinstance(self.base_ring, sage.rings.abc.Order): return self.base_ring().ideal(a).norm() @@ -8266,10 +8266,10 @@ def element_class(R, is_sparse): """ import sage.rings.integer_ring - if sage.rings.integer_ring.is_IntegerRing(R) and not is_sparse: + if isinstance(R, sage.rings.integer_ring.IntegerRing_class) and not is_sparse: from sage.modules.vector_integer_dense import Vector_integer_dense return Vector_integer_dense - elif sage.rings.rational_field.is_RationalField(R) and not is_sparse: + elif isinstance(R, sage.rings.rational_field.RationalField) and not is_sparse: from sage.modules.vector_rational_dense import Vector_rational_dense return Vector_rational_dense elif isinstance(R, sage.rings.abc.IntegerModRing) and not is_sparse: diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 4500695e297..d71d22ac1f7 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -139,10 +139,18 @@ def is_FreeModuleElement(x): EXAMPLES:: sage: sage.modules.free_module_element.is_FreeModuleElement(0) + doctest:warning... + DeprecationWarning: The function is_FreeModuleElement is deprecated; + use 'isinstance(..., FreeModuleElement)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. False sage: sage.modules.free_module_element.is_FreeModuleElement(vector([1,2,3])) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38184, + "The function is_FreeModuleElement is deprecated; " + "use 'isinstance(..., FreeModuleElement)' instead.") return isinstance(x, FreeModuleElement) diff --git a/src/sage/modules/with_basis/representation.py b/src/sage/modules/with_basis/representation.py index e9199ffd01d..b7d09675a05 100644 --- a/src/sage/modules/with_basis/representation.py +++ b/src/sage/modules/with_basis/representation.py @@ -21,6 +21,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.element import Element from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModule_Tensor +from sage.modules.with_basis.subquotient import SubmoduleWithBasis from sage.categories.modules import Modules from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector @@ -518,6 +519,25 @@ def symmetric_power(self, degree=None): """ return Representation_Symmetric(self, degree) + def schur_functor(self, la): + r""" + Return the :class:`Schur functor + ` + with shape ``la`` applied to ``self``. + + EXAMPLES:: + + sage: W = CoxeterGroup(['H', 3]) + sage: R = W.reflection_representation() + sage: S111 = R.schur_functor([1,1,1]) + sage: S111.dimension() + 1 + sage: S3 = R.schur_functor([3]) + sage: S3.dimension() + 10 + """ + return SchurFunctorRepresentation(self, la) + @abstract_method(optional=True) def _semigroup_action(self, g, vec, vec_on_left): """ @@ -2492,7 +2512,7 @@ def _default_sign(self, elem): class SignRepresentationCoxeterGroup(SignRepresentation_abstract): - """ + r""" The sign representation for a Coxeter group. EXAMPLES:: @@ -2500,6 +2520,11 @@ class SignRepresentationCoxeterGroup(SignRepresentation_abstract): sage: G = WeylGroup(["A", 1, 1]) sage: V = G.sign_representation() sage: TestSuite(V).run() + + sage: # optional - gap3 + sage: W = CoxeterGroup(['B', 3], implementation="coxeter3") + sage: S = W.sign_representation() + sage: TestSuite(S).run() """ def _default_sign(self, elem): """ @@ -2516,6 +2541,13 @@ def _default_sign(self, elem): sage: V = G.sign_representation() sage: V._default_sign(elem) 1 + + sage: # optional - gap3 + sage: W = CoxeterGroup(['B', 3], implementation="coxeter3") + sage: S = W.sign_representation() + sage: elem = W.an_element() + sage: S._default_sign(elem) + 1 """ return -1 if elem.length() % 2 else 1 @@ -2612,3 +2644,303 @@ def _semigroup_action(self, g, vec, vec_on_left): if vec_on_left: g = ~g return self.from_vector(g.canonical_matrix() * vec.to_vector()) + + +class NaturalMatrixRepresentation(Representation): + r""" + The natural representation of a matrix semigroup. + + A matrix semigroup is defined by its representation on a (finite + dimensional) vector space `V`, which is called the *natural + representation*. + + INPUT: + + - ``matrix_semigroup`` -- a matrix semigroup + - ``base_ring`` -- (optional) the base ring; the default is the base ring + of the semigroup + """ + @staticmethod + def __classcall_private__(cls, semigroup, base_ring=None): + r""" + Normalize input to ensure a unique representation. + + EXAMPLES:: + + sage: G = groups.matrix.SO(5, 2) + sage: N1 = G.natural_representation() + sage: N2 = G.natural_representation(GF(2)) + sage: N1 is N2 + True + """ + if base_ring is None: + base_ring = semigroup.base_ring() + return super().__classcall__(cls, semigroup, base_ring) + + def __init__(self, semigroup, base_ring): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.SU(2, 2) + sage: N = G.natural_representation() + sage: TestSuite(N).run() + + sage: G = groups.matrix.Sp(4, 2) + sage: N = G.natural_representation() + sage: TestSuite(N).run() # long time + """ + base_ring = semigroup.base_ring() + n = semigroup.degree() + module = CombinatorialFreeModule(base_ring, list(range(n)), prefix='e') + Representation.__init__(self, semigroup, module, None, "left") + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.GL(3, 2) + sage: G.natural_representation() + Natural representation of General Linear Group of degree 3 + over Finite Field of size 2 + """ + return "Natural representation of {}".format(self._semigroup) + + def _latex_(self): + r""" + Return a latex representation of ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.GL(3, 2) + sage: latex(G.natural_representation()) + \Bold{F}_{2} ^{3} + """ + from sage.misc.latex import latex + return latex(self.base_ring()) + "^{{{}}}".format(self.dimension()) + + def _semigroup_action(self, g, vec, vec_on_left): + r""" + Return the action of the semigroup element ``g`` on the + vector ``vec`` of ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.SL(2, 3) + sage: N = G.natural_representation() + sage: N._test_representation() # indirect doctest + """ + if self._left_repr == vec_on_left: + g = ~g + # TODO: currently, the slowest part is getting the matrix from g + return self.from_vector(g.matrix() * vec.to_vector()) + + +class SchurFunctorRepresentation(Subrepresentation): + r""" + The representation constructed by the Schur functor. + + Let `G` be a semigroup and let `V` be a representation of `G`. The + *Schur functor* for a partition `\lambda` of size `k` is the functor + `\mathbb{S}_{\lambda}` that sends `V` to the `G`-subrepresentation of + `V^{\otimes k}` spanned by `(v_1 \otimes \cdots \otimes v_k) c_{\lambda}`, + where `c_{\lambda}` is the :meth:`Young symmetrizer + ` + corresponding to `\lambda`. When `G = GL_n(F)`, the Schur functor image + `\mathbb{S}_{\lambda} F^n` is the (irreducible when `F` has characteristic + `0`) highest representation of shape `\lambda`. + + EXAMPLES:: + + sage: G = groups.permutation.Dihedral(3) + sage: V = G.regular_representation() + sage: S21V = V.schur_functor([2, 1]) + sage: S21V.dimension() + 70 + sage: SemistandardTableaux([2,1], max_entry=V.dimension()).cardinality() + 70 + sage: chi = G.character([S21V.representation_matrix(g).trace() + ....: for g in G.conjugacy_classes_representatives()]) + sage: chi.values() + [70, 0, -2] + sage: G.character_table() + [ 1 -1 1] + [ 2 0 -1] + [ 1 1 1] + sage: for m, phi in chi.decompose(): + ....: print(m, phi.values()) + 11 [1, -1, 1] + 11 [1, 1, 1] + 24 [2, 0, -1] + + sage: # long time + sage: S211V = V.schur_functor([2, 1, 1]) + sage: S211V.dimension() + 105 + sage: SemistandardTableaux([2, 1, 1], max_entry=V.dimension()).cardinality() + 105 + sage: chi = G.character([S211V.representation_matrix(g).trace() + ....: for g in G.conjugacy_classes_representatives()]) + sage: chi.values() + [105, -3, 0] + sage: for m, phi in chi.decompose(): + ....: print(m, phi.values()) + 19 [1, -1, 1] + 16 [1, 1, 1] + 35 [2, 0, -1] + + An example with the cyclic group:: + + sage: C3 = groups.permutation.Cyclic(3) + sage: V3 = C3.regular_representation() + sage: S31V3 = V3.schur_functor([3, 1]) + sage: S31V3.dimension() + 15 + sage: chi = C3.character([S31V3.representation_matrix(g).trace() + ....: for g in C3.conjugacy_classes_representatives()]) + sage: chi.values() + [15, 0, 0] + sage: C3.character_table() + [ 1 1 1] + [ 1 zeta3 -zeta3 - 1] + [ 1 -zeta3 - 1 zeta3] + sage: for m, phi in chi.decompose(): + ....: print(m, phi.values()) + 5 [1, 1, 1] + 5 [1, -zeta3 - 1, zeta3] + 5 [1, zeta3, -zeta3 - 1] + + An example of `GL_3(\GF{2})`:: + + sage: G = groups.matrix.GL(3, 2) + sage: from sage.modules.with_basis.representation import Representation + sage: N = G.natural_representation() + sage: S21N = N.schur_functor([2, 1]) + sage: S21N.dimension() + 8 + + An example with the Weyl/Coxeter group of type `C_3`:: + + sage: G = WeylGroup(['C', 3], prefix='s') + sage: R = G.reflection_representation() + sage: S = R.schur_functor([3, 2, 1]) + sage: g = G.an_element(); g + s1*s2*s3 + sage: v = S.an_element(); v + 2*S[0] + 2*S[1] + 3*S[2] + sage: v * g + -(2*a+1)*S[0] - (a+2)*S[1] - (2*a-2)*S[2] + (2*a-2)*S[3] + - (-2*a+4)*S[4] + (-2*a+4)*S[5] + 2*S[6] + 2*a*S[7] + sage: g * v + 3*S[0] + (-2*a+5)*S[2] + 3*a*S[4] - (5*a-2)*S[6] - 6*S[7] + """ + @staticmethod + def __classcall_private__(cls, V, shape): + r""" + Normalize input to ensure a unique representation. + + EXAMPLES:: + + sage: from sage.modules.with_basis.representation import SchurFunctorRepresentation + sage: G = groups.permutation.Cyclic(3) + sage: V = G.regular_representation() + sage: S1 = SchurFunctorRepresentation(V, Partition([2, 1, 1])) + sage: S2 = SchurFunctorRepresentation(V, (2, 1, 1)) + sage: S1 is S2 + True + """ + from sage.combinat.partition import _Partitions + return super().__classcall__(cls, V, _Partitions(shape)) + + def __init__(self, V, shape): + r""" + Initialize ``self``. + + INPUT: + + - ``V`` -- a representation + - ``shape`` -- a partition + + EXAMPLES:: + + sage: G = groups.permutation.Dihedral(3) + sage: V = G.regular_representation() + sage: S = V.schur_functor([2, 1]) + sage: TestSuite(S).run() + + sage: G = CoxeterGroup(['B', 3]) + sage: R = G.reflection_representation() + sage: S = R.schur_functor([3, 2, 1]) + sage: TestSuite(S).run() + + sage: G = groups.matrix.GL(3, 2) + sage: N = G.natural_representation() + sage: S = N.schur_functor([2, 1]) + sage: TestSuite(S).run() + """ + from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra + from sage.groups.perm_gps.permgroup_named import SymmetricGroup + from sage.categories.tensor import tensor + from sage.matrix.matrix_space import MatrixSpace + + R = V.base_ring() + self._shape = shape + self._module = V + d = sum(shape) + + if not isinstance(V, CombinatorialFreeModule): + keys = list(range(V.dimension())) + V = CombinatorialFreeModule(R, keys) + else: + keys = list(V.basis().keys()) + + ambient = tensor([V]*d) + I = ambient.indices() + cla = SymmetricGroupAlgebra(R, SymmetricGroup(d)).young_symmetrizer(shape) + mc = cla.monomial_coefficients(copy=False) + gens = [ambient.sum_of_terms((tuple([k[i-1] for i in p.tuple()]), coeff) + for p, coeff in mc.items()) + for k in ambient.basis().keys()] + support_order = ambient._compute_support_order(gens, None) + from sage.sets.family import Family + gens = Family(ambient.echelon_form(gens, order=support_order)) + cat = Modules(ambient.category().base_ring()).WithBasis().Subobjects() + Subrepresentation.__init__(self, gens, support_order, ambient, unitriangular=False, category=cat, prefix='S') + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.GL(4, 2) + sage: N = G.natural_representation() + sage: N.schur_functor([2, 1]) + Schur functor of shape [2, 1] image of Natural representation of + General Linear Group of degree 4 over Finite Field of size 2 + """ + return "Schur functor of shape {} image of {}".format(self._shape, self._module) + + def _latex_(self): + r""" + Return a latex representation of ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.GL(4, 2) + sage: N = G.natural_representation() + sage: latex(N.schur_functor([2, 1])) + \mathbb{S}_{{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} + \raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\cline{1-2} + \lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2} + \lr{\phantom{x}}\\\cline{1-1} + \end{array}$} + }}(\Bold{F}_{2} ^{4}) + """ + from sage.misc.latex import latex + return "\\mathbb{{S}}_{{{}}}({})".format(latex(self._shape), latex(self._module)) + + Element = Subrepresentation.Element diff --git a/src/sage/monoids/free_abelian_monoid_element.pyx b/src/sage/monoids/free_abelian_monoid_element.pyx index c81c1fa5575..9f66e83942d 100644 --- a/src/sage/monoids/free_abelian_monoid_element.pyx +++ b/src/sage/monoids/free_abelian_monoid_element.pyx @@ -54,6 +54,10 @@ def is_FreeAbelianMonoidElement(x): - ``True`` if ``x`` is an object of type ``FreeAbelianMonoidElement``; ``False`` otherwise. """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38184, + "The function is_FreeAbelianMonoidElement is deprecated; " + "use 'isinstance(..., FreeAbelianMonoidElement)' instead.") return isinstance(x, FreeAbelianMonoidElement) diff --git a/src/sage/monoids/free_monoid_element.py b/src/sage/monoids/free_monoid_element.py index 42d295eab76..993fef9c72d 100644 --- a/src/sage/monoids/free_monoid_element.py +++ b/src/sage/monoids/free_monoid_element.py @@ -30,6 +30,10 @@ def is_FreeMonoidElement(x): + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_FreeMonoidElement is deprecated; " + "use 'isinstance(..., FreeMonoidElement)' instead.") return isinstance(x, FreeMonoidElement) diff --git a/src/sage/numerical/linear_functions.pyx b/src/sage/numerical/linear_functions.pyx index 3063ba7101d..d1a038fd54b 100644 --- a/src/sage/numerical/linear_functions.pyx +++ b/src/sage/numerical/linear_functions.pyx @@ -132,10 +132,18 @@ cpdef is_LinearFunction(x): sage: x = p.new_variable() sage: from sage.numerical.linear_functions import is_LinearFunction sage: is_LinearFunction(x[0] - 2*x[2]) + doctest:warning... + DeprecationWarning: The function is_LinearFunction is deprecated; + use 'isinstance(..., LinearFunction)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_LinearFunction('a string') False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38184, + "The function is_LinearFunction is deprecated; " + "use 'isinstance(..., LinearFunction)' instead.") return isinstance(x, LinearFunction) @@ -158,10 +166,18 @@ def is_LinearConstraint(x): sage: ieq = (x[0] <= x[1]) sage: from sage.numerical.linear_functions import is_LinearConstraint sage: is_LinearConstraint(ieq) + doctest:warning... + DeprecationWarning: The function is_LinearConstraint is deprecated; + use 'isinstance(..., LinearConstraint)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_LinearConstraint('a string') False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38184, + "The function is_LinearConstraint is deprecated; " + "use 'isinstance(..., LinearConstraint)' instead.") return isinstance(x, LinearConstraint) @@ -690,7 +706,7 @@ cdef class LinearFunctionsParent_class(Parent): sage: LF_QQ(f) is f False """ - if is_LinearFunction(x): + if isinstance(x, LinearFunction): return LinearFunction(self, (x)._f) return LinearFunction(self, x) @@ -891,7 +907,7 @@ cdef class LinearFunction(LinearFunctionOrConstraint): ... ValueError: x is from a different linear functions module """ - if is_LinearFunction(x): + if isinstance(x, LinearFunction): if self.parent() != x.parent(): raise ValueError('x is from a different linear functions module') if len((x)._f) != 1: @@ -1319,7 +1335,7 @@ cdef class LinearConstraintsParent_class(Parent): sage: LC_QQ(inequality) is inequality False """ - if right is None and is_LinearConstraint(left): + if right is None and isinstance(left, LinearConstraint): if (left.parent() is self) and (left.is_equation() == equality): return left else: diff --git a/src/sage/numerical/linear_tensor.py b/src/sage/numerical/linear_tensor.py index 217bd98f3bb..c4c62066db5 100644 --- a/src/sage/numerical/linear_tensor.py +++ b/src/sage/numerical/linear_tensor.py @@ -99,7 +99,7 @@ from sage.structure.parent import Parent from sage.misc.cachefunc import cached_function -from sage.numerical.linear_functions import is_LinearFunction, LinearFunctionsParent_class +from sage.numerical.linear_functions import LinearFunction, LinearFunctionsParent_class from sage.numerical.linear_tensor_element import LinearTensor @@ -128,10 +128,18 @@ def is_LinearTensor(x): sage: x = p.new_variable(nonnegative=False) sage: from sage.numerical.linear_tensor import is_LinearTensor sage: is_LinearTensor(x[0] - 2*x[2]) + doctest:warning... + DeprecationWarning: The function is_LinearTensor is deprecated; + use 'isinstance(..., LinearTensor)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. False sage: is_LinearTensor('a string') False """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_LinearTensor is deprecated; " + "use 'isinstance(..., LinearTensor)' instead.") return isinstance(x, LinearTensor) @@ -413,9 +421,9 @@ def _element_constructor_(self, x): (3.0, 3.0) + (2.0, 2.0)*x_1 + (1.0, 1.0)*x_3 """ M = self.free_module() - if is_LinearTensor(x): + if isinstance(x, LinearTensor): x = x.dict() - elif is_LinearFunction(x): + elif isinstance(x, LinearFunction): x = dict([key, self._convert_constant(value)] for key, value in x.dict().items()) elif isinstance(x, dict): x = dict([int(key), M(value)] for key, value in x.items()) diff --git a/src/sage/numerical/linear_tensor_constraints.py b/src/sage/numerical/linear_tensor_constraints.py index 24f94f3b3d6..60578c2511d 100644 --- a/src/sage/numerical/linear_tensor_constraints.py +++ b/src/sage/numerical/linear_tensor_constraints.py @@ -57,10 +57,18 @@ def is_LinearTensorConstraint(x): sage: vector_ieq = (x[0] * vector([1,2]) <= x[1] * vector([2,3])) sage: from sage.numerical.linear_tensor_constraints import is_LinearTensorConstraint sage: is_LinearTensorConstraint(vector_ieq) + doctest:warning... + DeprecationWarning: The function is_LinearTensorConstraint is deprecated; + use 'isinstance(..., LinearTensorConstraint)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_LinearTensorConstraint('a string') False """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_LinearTensorConstraint is deprecated; " + "use 'isinstance(..., LinearTensorConstraint)' instead.") return isinstance(x, LinearTensorConstraint) diff --git a/src/sage/numerical/linear_tensor_element.pyx b/src/sage/numerical/linear_tensor_element.pyx index c77aa290e21..f7dd2b61deb 100644 --- a/src/sage/numerical/linear_tensor_element.pyx +++ b/src/sage/numerical/linear_tensor_element.pyx @@ -169,7 +169,7 @@ cdef class LinearTensor(ModuleElement): ... ValueError: x is from a different linear functions module """ - if is_LinearFunction(x): + if isinstance(x, LinearFunction): if self.parent().linear_functions() != x.parent(): raise ValueError('x is from a different linear functions module') if len((x)._f) != 1: diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index 2690172b85a..7af017ebd17 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -2134,14 +2134,14 @@ cdef class MixedIntegerLinearProgram(SageObject): sage: p.solve() 6.0 """ - from sage.numerical.linear_functions import is_LinearFunction, is_LinearConstraint - from sage.numerical.linear_tensor import is_LinearTensor - from sage.numerical.linear_tensor_constraints import is_LinearTensorConstraint - if is_LinearFunction(linear_function) or is_LinearTensor(linear_function): + from sage.numerical.linear_functions import LinearFunction, LinearConstraint + from sage.numerical.linear_tensor import LinearTensor + from sage.numerical.linear_tensor_constraints import LinearTensorConstraint + if isinstance(linear_function, LinearFunction) or isinstance(linear_function, LinearTensor): # Find the parent for the coefficients - if is_LinearFunction(linear_function): + if isinstance(linear_function, LinearFunction): M = linear_function.parent().base_ring() - elif is_LinearTensor(linear_function): + elif isinstance(linear_function, LinearTensor): if not linear_function.parent().is_vector_space(): raise ValueError('the linear function must be vector-valued') M = linear_function.parent().free_module() @@ -2164,14 +2164,14 @@ cdef class MixedIntegerLinearProgram(SageObject): except KeyError: pass # Send to backend - if is_LinearFunction(linear_function): + if isinstance(linear_function, LinearFunction): if self._check_redundant and self._is_redundant_constraint(constraint, min, max): if return_indices: return [] return nrows_before = self._backend.nrows() self._backend.add_linear_constraint(constraint.items(), min, max, name) - elif is_LinearTensor(linear_function): + elif isinstance(linear_function, LinearTensor): nrows_before = self._backend.nrows() self._backend.add_linear_constraint_vector(M.degree(), constraint.items(), min, max, name) else: @@ -2179,7 +2179,7 @@ cdef class MixedIntegerLinearProgram(SageObject): if return_indices: return list(range(nrows_before, self._backend.nrows())) return - elif is_LinearConstraint(linear_function): + elif isinstance(linear_function, LinearConstraint): if not(min is None and max is None): raise ValueError('min and max must not be specified for (in)equalities') relation = linear_function @@ -2200,7 +2200,7 @@ cdef class MixedIntegerLinearProgram(SageObject): if new_indices is not None: row_indices.extend(new_indices) return row_indices - elif is_LinearTensorConstraint(linear_function): + elif isinstance(linear_function, LinearTensorConstraint): if not(min is None and max is None): raise ValueError('min and max must not be specified for (in)equalities') relation = linear_function diff --git a/src/sage/numerical/sdp.pyx b/src/sage/numerical/sdp.pyx index 4f6f4db9291..7e214ad5023 100644 --- a/src/sage/numerical/sdp.pyx +++ b/src/sage/numerical/sdp.pyx @@ -233,7 +233,7 @@ AUTHORS: from sage.structure.parent cimport Parent from sage.structure.element cimport Element -from sage.numerical.linear_functions import is_LinearFunction, is_LinearConstraint +from sage.numerical.linear_functions import LinearFunction, LinearConstraint from sage.matrix.constructor import matrix from sage.structure.element import Matrix @@ -895,10 +895,10 @@ cdef class SemidefiniteProgram(SageObject): if linear_function is 0: return - from sage.numerical.linear_tensor_constraints import is_LinearTensorConstraint - from sage.numerical.linear_tensor import is_LinearTensor + from sage.numerical.linear_tensor_constraints import LinearTensorConstraint + from sage.numerical.linear_tensor import LinearTensor - if is_LinearTensorConstraint(linear_function) or is_LinearConstraint(linear_function): + if isinstance(linear_function, LinearTensorConstraint) or isinstance(linear_function, LinearConstraint): c = linear_function if c.is_equation(): self.add_constraint(c.lhs()-c.rhs(), name=name) @@ -906,7 +906,7 @@ cdef class SemidefiniteProgram(SageObject): else: self.add_constraint(c.lhs()-c.rhs(), name=name) - elif is_LinearFunction(linear_function) or is_LinearTensor(linear_function): + elif isinstance(linear_function, LinearFunction) or isinstance(linear_function, LinearTensor): l = sorted(linear_function.dict().items()) self._backend.add_linear_constraint(l, name) diff --git a/src/sage/plot/animate.py b/src/sage/plot/animate.py index c11c80151e2..2dbc162d07c 100644 --- a/src/sage/plot/animate.py +++ b/src/sage/plot/animate.py @@ -1023,8 +1023,9 @@ def ffmpeg(self, savefile=None, show_path=False, output_format=None, # afterwards. Hence 'early_options' and 'ffmpeg_options' # The `-nostdin` is needed to avoid the command to hang, see # https://stackoverflow.com/questions/16523746/ffmpeg-hangs-when-run-in-background - cmd = 'cd {}; ffmpeg -nostdin -y -f image2 {} -i {} {} {}'.format( - shlex.quote(pngdir), early_options, shlex.quote(pngs), ffmpeg_options, shlex.quote(savefile)) + cmd = 'cd {}; {} -nostdin -y -f image2 {} -i {} {} {}'.format( + shlex.quote(pngdir), shlex.quote(FFmpeg().absolute_filename()), + early_options, shlex.quote(pngs), ffmpeg_options, shlex.quote(savefile)) from subprocess import check_call, CalledProcessError, PIPE try: if sage.misc.verbose.get_verbose() > 0: diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index a5e46d07c2d..a84d162cb56 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -61,10 +61,18 @@ def is_Graphics(x): sage: from sage.plot.graphics import is_Graphics sage: is_Graphics(1) + doctest:warning... + DeprecationWarning: The function is_Graphics is deprecated; + use 'isinstance(..., Graphics)' instead. + See https://github.com/sagemath/sage/issues/38184 for details. False sage: is_Graphics(disk((0.0, 0.0), 1, (0, pi/2))) # needs sage.symbolic True """ + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_Graphics is deprecated; " + "use 'isinstance(..., Graphics)' instead.") return isinstance(x, Graphics) @@ -2438,7 +2446,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), x_formatter, y_formatter = tick_formatter from matplotlib.ticker import FuncFormatter, FixedFormatter from sage.misc.latex import latex - from sage.symbolic.ring import SR + from sage.structure.element import Expression from .misc import _multiple_of_constant # ---------------------- Formatting x-ticks ---------------------- if x_formatter is None: @@ -2446,7 +2454,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), x_formatter = LogFormatterMathtext(base=base[0]) else: x_formatter = ScalarFormatter() - elif x_formatter in SR: + elif isinstance(x_formatter, Expression): x_const = x_formatter x_formatter = FuncFormatter(lambda n, pos: _multiple_of_constant(n, pos, x_const)) @@ -2475,7 +2483,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), y_formatter = LogFormatterMathtext(base=base[1]) else: y_formatter = ScalarFormatter() - elif y_formatter in SR: + elif isinstance(y_formatter, Expression): y_const = y_formatter y_formatter = FuncFormatter(lambda n, pos: _multiple_of_constant(n, pos, y_const)) @@ -2763,10 +2771,10 @@ def matplotlib(self, filename=None, if stylesheet in plt.style.available: plt.style.use(stylesheet) - from sage.symbolic.ring import SR + from sage.structure.element import Expression # make sure both formatters typeset or both don't if not isinstance(tick_formatter, (list, tuple)): - if tick_formatter == "latex" or tick_formatter in SR: + if tick_formatter == "latex" or isinstance(tick_formatter, Expression): tick_formatter = (tick_formatter, "latex") else: tick_formatter = (tick_formatter, None) diff --git a/src/sage/plot/hyperbolic_regular_polygon.py b/src/sage/plot/hyperbolic_regular_polygon.py index a61827142d7..96df49b2271 100644 --- a/src/sage/plot/hyperbolic_regular_polygon.py +++ b/src/sage/plot/hyperbolic_regular_polygon.py @@ -17,16 +17,18 @@ # https://www.gnu.org/licenses/ #***************************************************************************** +from sage.matrix.constructor import matrix +from sage.misc.decorators import options, rename_keyword +from sage.misc.functional import is_odd +from sage.misc.lazy_import import lazy_import from sage.plot.hyperbolic_polygon import HyperbolicPolygon -from sage.plot.all import Graphics +from sage.plot.plot import Graphics from sage.rings.cc import CC from sage.rings.integer import Integer -from sage.misc.decorators import options, rename_keyword -from sage.symbolic.constants import pi, e -from sage.functions.hyperbolic import arccosh -from sage.functions.trig import sin, cos, cot -from sage.misc.functional import is_odd -from sage.matrix.constructor import matrix + +lazy_import("sage.functions.hyperbolic", "arccosh") +lazy_import("sage.functions.trig", ["sin", "cos", "cot"]) +lazy_import("sage.symbolic.constants", ["pi", "e"]) class HyperbolicRegularPolygon(HyperbolicPolygon): diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx index daf4ba07f94..4c09ea7e7c7 100644 --- a/src/sage/plot/plot3d/base.pyx +++ b/src/sage/plot/plot3d/base.pyx @@ -52,7 +52,6 @@ AUTHORS: from cpython.list cimport * import os -import sys import zipfile from functools import reduce diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index ad885744ba7..c34830d35d6 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -147,15 +147,16 @@ def f(x,y): return math.exp(x/5)*math.cos(y) # https://www.gnu.org/licenses/ # **************************************************************************** -from .tri_plot import TrianglePlot -from .index_face_set import IndexFaceSet -from .shapes import arrow3d -from .base import Graphics3dGroup +from sage.misc.lazy_import import lazy_import +from sage.misc.sageinspect import sage_getargspec, is_function_or_cython_function from sage.plot.colors import rainbow -from .texture import Texture +from sage.plot.plot3d.base import Graphics3dGroup +from sage.plot.plot3d.index_face_set import IndexFaceSet +from sage.plot.plot3d.shapes import arrow3d +from sage.plot.plot3d.texture import Texture +from sage.plot.plot3d.tri_plot import TrianglePlot -from sage.functions.trig import cos, sin -from sage.misc.sageinspect import sage_getargspec, is_function_or_cython_function +lazy_import("sage.functions.trig", ["cos", "sin"]) class _Coordinates: @@ -318,9 +319,9 @@ def to_cartesian(self, func, params=None): """ from sage.structure.element import Expression - from sage.rings.real_mpfr import is_RealNumber - from sage.rings.integer import is_Integer - if params is not None and (isinstance(func, Expression) or is_RealNumber(func) or is_Integer(func)): + from sage.rings.real_mpfr import RealNumber + from sage.rings.integer import Integer + if params is not None and (isinstance(func, Expression) or isinstance(func, RealNumber) or isinstance(func, Integer)): return self.transform(**{ self.dep_var: func, self.indep_vars[0]: params[0], diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index 4a385e55150..1a779aba083 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -19,7 +19,7 @@ from sage.structure.parent import Parent from sage.functions.log import log from sage.misc.functional import sqrt -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.sets.set import Set from pprint import pformat @@ -27,15 +27,31 @@ ################################################################################ def is_ProbabilitySpace(S): + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_ProbabilitySpace is deprecated; " + "use 'isinstance(..., ProbabilitySpace_generic)' instead.") return isinstance(S, ProbabilitySpace_generic) def is_DiscreteProbabilitySpace(S): + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_DiscreteProbabilitySpace is deprecated; " + "use 'isinstance(..., DiscreteProbabilitySpace)' instead.") return isinstance(S, DiscreteProbabilitySpace) def is_RandomVariable(X): + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_RandomVariable is deprecated; " + "use 'isinstance(..., RandomVariable_generic)' instead.") return isinstance(X, RandomVariable_generic) def is_DiscreteRandomVariable(X): + from sage.misc.superseded import deprecation + deprecation(38184, + "The function is_DiscreteRandomVariable is deprecated; " + "use 'isinstance(..., DiscreteRandomVariable)' instead.") return isinstance(X, DiscreteRandomVariable) ################################################################################ @@ -49,7 +65,7 @@ class RandomVariable_generic(Parent): A random variable. """ def __init__(self, X, RR): - if not is_ProbabilitySpace(X): + if not isinstance(X, ProbabilitySpace_generic): raise TypeError("Argument X (= %s) must be a probability space" % X) Parent.__init__(self, X) self._codomain = RR @@ -81,7 +97,7 @@ def __init__(self, X, f, codomain=None, check=False): - f -- a dictionary such that X[x] = value for x in X is the discrete function on X """ - if not is_DiscreteProbabilitySpace(X): + if not isinstance(X, DiscreteProbabilitySpace): raise TypeError("Argument X (= %s) must be a discrete probability space" % X) if check: raise NotImplementedError("Not implemented") @@ -343,11 +359,11 @@ def __init__(self, X, P, codomain=None, check=False): if codomain is None: from sage.rings.real_mpfr import RealField codomain = RealField() - if not isinstance(codomain, sage.rings.abc.RealField) and not is_RationalField(codomain): + if not isinstance(codomain, sage.rings.abc.RealField) and not isinstance(codomain, RationalField): raise TypeError("Argument codomain (= %s) must be the reals or rationals" % codomain) if check: one = sum(P.values()) - if is_RationalField(codomain): + if isinstance(codomain, RationalField): if not one == 1: raise TypeError("Argument P (= %s) does not define a probability function") else: diff --git a/src/sage/quadratic_forms/ternary.pyx b/src/sage/quadratic_forms/ternary.pyx index 3c1ca8832a8..4ed6d76ed3d 100644 --- a/src/sage/quadratic_forms/ternary.pyx +++ b/src/sage/quadratic_forms/ternary.pyx @@ -13,7 +13,7 @@ Helper code for ternary quadratic forms # **************************************************************************** from sage.arith.misc import gcd, inverse_mod, xgcd -from sage.matrix.constructor import matrix, identity_matrix, diagonal_matrix +from sage.matrix.constructor import matrix from sage.misc.prandom import randint from sage.rings.finite_rings.integer_mod import mod from sage.rings.integer_ring import ZZ diff --git a/src/sage/repl/display/formatter.py b/src/sage/repl/display/formatter.py index 9d6eaf53894..b76457669cb 100644 --- a/src/sage/repl/display/formatter.py +++ b/src/sage/repl/display/formatter.py @@ -7,7 +7,7 @@ contains a new facility for displaying lists of matrices in an easier to read format:: - sage: [identity_matrix(i) for i in range(2,5)] + sage: [identity_matrix(i) for i in range(2, 5)] # needs sage.modules [ [1 0 0 0] [1 0 0] [0 1 0 0] @@ -236,19 +236,23 @@ def _ipython_float_precision_changed(change): sage: shell.run_cell('matrix.options.precision') # indirect doctest # needs sage.modules None """ - from sage.matrix.constructor import options - s = change.new - if not s: - # unset the precision - options.precision = None + try: + from sage.matrix.constructor import options + except ImportError: + pass else: - try: - prec = int(s) - if prec >= 0: - options.precision = prec - # otherwise ignore the change - except ValueError: - pass + s = change.new + if not s: + # unset the precision + options.precision = None + else: + try: + prec = int(s) + if prec >= 0: + options.precision = prec + # otherwise ignore the change + except ValueError: + pass class SagePlainTextFormatter(PlainTextFormatter): diff --git a/src/sage/repl/image.py b/src/sage/repl/image.py index 500e60d97b0..2170d216caa 100644 --- a/src/sage/repl/image.py +++ b/src/sage/repl/image.py @@ -1,4 +1,5 @@ # sage_setup: distribution = sagemath-repl +# sage.doctest: needs pillow """ Sage Wrapper for Bitmap Images diff --git a/src/sage/repl/ipython_kernel/interact.py b/src/sage/repl/ipython_kernel/interact.py index f62cf420fc1..a8167dcabd8 100644 --- a/src/sage/repl/ipython_kernel/interact.py +++ b/src/sage/repl/ipython_kernel/interact.py @@ -34,15 +34,18 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from ipywidgets.widgets import SelectionSlider, ValueWidget, ToggleButtons -from ipywidgets.widgets.interaction import interactive, signature from collections import OrderedDict from collections.abc import Iterable, Iterator -from .widgets import EvalText, SageColorPicker -from sage.structure.element import parent + +from ipywidgets.widgets import SelectionSlider, ValueWidget, ToggleButtons +from ipywidgets.widgets.interaction import interactive, signature + import sage.rings.abc + from sage.misc.lazy_import import lazy_import -from sage.structure.element import Matrix +from sage.repl.ipython_kernel.widgets import EvalText, SageColorPicker +from sage.structure.element import Matrix, parent + lazy_import("sage.plot.colors", "Color") @@ -173,6 +176,7 @@ def widget_from_single_value(cls, abbrev, *args, **kwds): return input_grid(abbrev.nrows(), abbrev.ncols(), default=abbrev.list(), to_value=abbrev.parent()) + if isinstance(abbrev, Color): return SageColorPicker(value=abbrev.html_color()) # Get widget from IPython if possible diff --git a/src/sage/repl/ipython_kernel/widgets.py b/src/sage/repl/ipython_kernel/widgets.py index 93498c7e09a..f3ac6a35ccb 100644 --- a/src/sage/repl/ipython_kernel/widgets.py +++ b/src/sage/repl/ipython_kernel/widgets.py @@ -101,7 +101,7 @@ class TransformWidget(): sage: from ipywidgets import ToggleButtons sage: from sage.repl.ipython_kernel.widgets import TransformWidget sage: class TransformToggleButtons(TransformWidget, ToggleButtons): pass - sage: w = TransformToggleButtons(options=["pi", "e"], transform=lambda x: x+x) + sage: w = TransformToggleButtons(options=["pi", "e"], transform=lambda x: x + x) sage: w TransformToggleButtons(options=('pi', 'e'), value='pi') sage: w.get_interact_value() @@ -240,7 +240,8 @@ class TransformIntRangeSlider(TransformWidget, IntRangeSlider): EXAMPLES:: sage: from sage.repl.ipython_kernel.widgets import TransformIntRangeSlider - sage: w = TransformIntRangeSlider(min=0, max=100, value=(7,9), transform=lambda x: x[1]-x[0]) + sage: w = TransformIntRangeSlider(min=0, max=100, value=(7, 9), + ....: transform=lambda x: x[1] - x[0]) sage: w TransformIntRangeSlider(value=(7, 9)) sage: w.get_interact_value() @@ -257,7 +258,8 @@ class TransformFloatRangeSlider(TransformWidget, FloatRangeSlider): EXAMPLES:: sage: from sage.repl.ipython_kernel.widgets import TransformFloatRangeSlider - sage: w = TransformFloatRangeSlider(min=0, max=100, value=(7,9), transform=lambda x: x[1]-x[0]) + sage: w = TransformFloatRangeSlider(min=0, max=100, value=(7, 9), + ....: transform=lambda x: x[1] - x[0]) sage: w TransformFloatRangeSlider(value=(7.0, 9.0)) sage: w.get_interact_value() @@ -274,7 +276,7 @@ class TransformText(TransformWidget, Text): EXAMPLES:: sage: from sage.repl.ipython_kernel.widgets import TransformText - sage: w = TransformText(value="hello", transform=lambda x: x+x) + sage: w = TransformText(value="hello", transform=lambda x: x + x) sage: w TransformText(value='hello') sage: w.get_interact_value() @@ -291,7 +293,7 @@ class TransformTextarea(TransformWidget, Textarea): EXAMPLES:: sage: from sage.repl.ipython_kernel.widgets import TransformTextarea - sage: w = TransformTextarea(value="hello", transform=lambda x: x+x) + sage: w = TransformTextarea(value="hello", transform=lambda x: x + x) sage: w TransformTextarea(value='hello') sage: w.get_interact_value() @@ -371,7 +373,10 @@ class Grid(TransformWidget, HBox, ValueWidget): sage: from sage.repl.ipython_kernel.widgets import Grid sage: w = Grid(2, 2, lambda i,j: Text(value="%s,%s"%(i,j))) sage: w - Grid(value=[['0,0', '0,1'], ['1,0', '1,1']], children=(Label(value=''), VBox(children=(Text(value='0,0'), Text(value='1,0'))), VBox(children=(Text(value='0,1'), Text(value='1,1'))))) + Grid(value=[['0,0', '0,1'], ['1,0', '1,1']], + children=(Label(value=''), + VBox(children=(Text(value='0,0'), Text(value='1,0'))), + VBox(children=(Text(value='0,1'), Text(value='1,1'))))) sage: w.get_interact_value() [['0,0', '0,1'], ['1,0', '1,1']] """ diff --git a/src/sage/repl/ipython_tests.py b/src/sage/repl/ipython_tests.py index 5070fc4fb35..12f03c20d7e 100644 --- a/src/sage/repl/ipython_tests.py +++ b/src/sage/repl/ipython_tests.py @@ -54,7 +54,7 @@ ... String form: lm File: .../sage/interfaces/r.py - Docstring: + Docstring:... title ***** diff --git a/src/sage/repl/preparse.py b/src/sage/repl/preparse.py index 69d129c2787..9b5dde719ce 100644 --- a/src/sage/repl/preparse.py +++ b/src/sage/repl/preparse.py @@ -64,7 +64,7 @@ 4 sage: 87.factor() 3 * 29 - sage: 15.10.sqrt() + sage: 15.10.sqrt() # needs sage.rings.real_mpfr 3.88587184554509 sage: preparse('87.sqrt()') 'Integer(87).sqrt()' @@ -83,7 +83,7 @@ Symbolic functional notation:: sage: # needs sage.symbolic - sage: a=10; f(theta, beta) = theta + beta; b = x^2 + theta + sage: a = 10; f(theta, beta) = theta + beta; b = x^2 + theta sage: f (theta, beta) |--> beta + theta sage: a @@ -1032,7 +1032,7 @@ def parse_ellipsis(code, preparse_step=True): '(ellipsis_range(1,2,Ellipsis,n))' sage: parse_ellipsis("for i in (f(x) .. L[10]):") 'for i in (ellipsis_iter(f(x) ,Ellipsis, L[10])):' - sage: [1.0..2.0] + sage: [1.0..2.0] # needs sage.rings.real_mpfr [1.00000000000000, 2.00000000000000] TESTS: diff --git a/src/sage/repl/user_globals.py b/src/sage/repl/user_globals.py index d39b1dd9aad..dfbdc7f72ef 100644 --- a/src/sage/repl/user_globals.py +++ b/src/sage/repl/user_globals.py @@ -164,8 +164,9 @@ def initialize_globals(all, g=None): def get_global(name): """ - Return the value of global variable ``name``. Raise ``NameError`` - if there is no such global variable. + Return the value of global variable ``name``. + + Raise :class:`NameError` if there is no such global variable. INPUT: diff --git a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py index 1039ce81bbc..f5163d394a5 100644 --- a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +++ b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py @@ -3289,8 +3289,8 @@ def _coerce_map_from_(self, P): if self.base().has_coerce_map_from(P.base()): return True - from sage.rings.fraction_field import is_FractionField - if is_FractionField(P): + from sage.rings.fraction_field import FractionField_generic + if isinstance(P, FractionField_generic): B = P.base() from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 2f85cbd101a..c59a2b46d6f 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -706,10 +706,18 @@ def is_ComplexDoubleElement(x): sage: from sage.rings.complex_double import is_ComplexDoubleElement sage: is_ComplexDoubleElement(0) + doctest:warning... + DeprecationWarning: The function is_ComplexDoubleElement is deprecated; + use 'isinstance(..., ComplexDoubleElement)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. False sage: is_ComplexDoubleElement(CDF(0)) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_ComplexDoubleElement is deprecated; " + "use 'isinstance(..., ComplexDoubleElement)' instead.") return isinstance(x, ComplexDoubleElement) diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index cd4ba7bb8e8..5b3064688b0 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -61,7 +61,7 @@ from sage.libs.gmp.mpz cimport mpz_sgn, mpz_cmpabs_ui from sage.libs.mpfr cimport * from sage.libs.mpfi cimport * from sage.libs.flint.fmpz cimport * -from sage.libs.mpfr cimport MPFR_RNDU, MPFR_RNDD +from sage.libs.mpfr cimport MPFR_RNDU from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON from sage.structure.element cimport FieldElement @@ -82,10 +82,18 @@ def is_ComplexIntervalFieldElement(x): sage: from sage.rings.complex_interval import is_ComplexIntervalFieldElement as is_CIFE sage: is_CIFE(CIF(2)) + doctest:warning... + DeprecationWarning: The function is_ComplexIntervalFieldElement is deprecated; + use 'isinstance(..., ComplexIntervalFieldElement)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_CIFE(CC(2)) False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_ComplexIntervalFieldElement is deprecated; " + "use 'isinstance(..., ComplexIntervalFieldElement)' instead.") return isinstance(x, ComplexIntervalFieldElement) diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index e1ce333d57d..79c06af06d5 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -127,6 +127,10 @@ def is_ComplexNumber(x): sage: a = ComplexNumber(1, 2); a 1.00000000000000 + 2.00000000000000*I sage: is_ComplexNumber(a) + doctest:warning... + DeprecationWarning: The function is_ComplexNumber is deprecated; + use 'isinstance(..., ComplexNumber)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: b = ComplexNumber(1); b 1.00000000000000 @@ -146,6 +150,10 @@ def is_ComplexNumber(x): sage: is_ComplexNumber(d) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_ComplexNumber is deprecated; " + "use 'isinstance(..., ComplexNumber)' instead.") return isinstance(x, ComplexNumber) diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index a4a0aa5cd68..401f398ddee 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -69,7 +69,7 @@ from sage.structure.element cimport Vector from sage.interfaces.abc import GapElement -cdef object is_IntegerMod +cdef object IntegerMod_abstract cdef object Integer cdef object Rational cdef object MPolynomial @@ -80,17 +80,17 @@ cdef void late_import() noexcept: """ Late import of modules """ - global is_IntegerMod, \ + global IntegerMod_abstract, \ Integer, \ Rational, \ MPolynomial, \ Polynomial - if is_IntegerMod is not None: + if IntegerMod_abstract is not None: return import sage.rings.finite_rings.integer_mod - is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod + IntegerMod_abstract = sage.rings.finite_rings.integer_mod.IntegerMod_abstract import sage.rings.integer Integer = sage.rings.integer.Integer @@ -361,7 +361,7 @@ cdef class Cache_givaro(Cache_base): else: raise TypeError("unable to coerce from a finite field other than the prime subfield") - elif isinstance(e, (int, Integer)) or is_IntegerMod(e): + elif isinstance(e, (int, Integer)) or isinstance(e, IntegerMod_abstract): try: e_int = e % self.characteristic() self.objectptr.initi(res, e_int) diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 512ac4ec1d2..32ffd192353 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -50,7 +50,7 @@ from sage.rings.finite_rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e from sage.interfaces.abc import GapElement -cdef object is_IntegerMod +cdef object IntegerMod_abstract cdef object Integer cdef object Rational cdef object MPolynomial @@ -64,7 +64,7 @@ cdef int late_import() except -1: i.e. after the module was loaded. This is needed to avoid circular imports. """ - global is_IntegerMod, \ + global IntegerMod_abstract, \ Integer, \ Rational, \ MPolynomial, \ @@ -72,11 +72,11 @@ cdef int late_import() except -1: GF, \ GF2, GF2_0, GF2_1 - if is_IntegerMod is not None: + if IntegerMod_abstract is not None: return 0 import sage.rings.finite_rings.integer_mod - is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod + IntegerMod_abstract = sage.rings.finite_rings.integer_mod.IntegerMod_abstract import sage.rings.rational Rational = sage.rings.rational.Rational @@ -275,7 +275,7 @@ cdef class Cache_ntl_gf2e(Cache_base): cdef FiniteField_ntl_gf2eElement g cdef Py_ssize_t i - if is_IntegerMod(e): + if isinstance(e, IntegerMod_abstract): e = e.lift() if isinstance(e, (int, Integer)): GF2E_conv_long(res.x,int(e&1)) diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 097f8ac87d3..b2238689afb 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -213,10 +213,18 @@ def is_IntegerMod(x): sage: from sage.rings.finite_rings.integer_mod import is_IntegerMod sage: is_IntegerMod(5) + doctest:warning... + DeprecationWarning: The function is_IntegerMod is deprecated; + use 'isinstance(..., IntegerMod_abstract)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. False sage: is_IntegerMod(Mod(5,10)) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_IntegerMod is deprecated; " + "use 'isinstance(..., IntegerMod_abstract)' instead.") return isinstance(x, IntegerMod_abstract) @@ -4213,18 +4221,18 @@ def lucas(k, P, Q=1, n=None): """ cdef IntegerMod_abstract p,q - if n is None and not is_IntegerMod(P): + if n is None and not isinstance(P, IntegerMod_abstract): raise ValueError if n is None: n = P.modulus() - if not is_IntegerMod(P): + if not isinstance(P, IntegerMod_abstract): p = Mod(P,n) else: p = P - if not is_IntegerMod(Q): + if not isinstance(Q, IntegerMod_abstract): q = Mod(Q,n) else: q = Q diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 5e9d74844e3..7a7fa6dfc23 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -186,7 +186,7 @@ from sage.rings.ideal import is_Ideal from sage.rings.number_field.number_field_element_base import NumberFieldElement_base from sage.rings.number_field.number_field_ideal import NumberFieldIdeal -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.polynomial.polynomial_ring import is_PolynomialRing @@ -1138,7 +1138,7 @@ cdef class ReductionMap(Map): return FiniteField_prime_modn._element_constructor_(self._F, x) except ZeroDivisionError: raise ZeroDivisionError("Cannot reduce rational %s modulo %s: it has negative valuation" % (x, p.gen())) - elif is_FractionField(self._K): + elif isinstance(self._K, FractionField_generic): p = p.gen() if p.degree() == 1: return self._F((x.numerator() % p)[0] / (x.denominator() % p)[0]) @@ -1656,7 +1656,7 @@ cdef class LiftingMap(Section): """ if self._K is QQ or self._K is ZZ: return self._K(x.lift()) # x.lift() is in ZZ - elif is_FractionField(self._K): + elif isinstance(self._K, FractionField_generic): if self._F.p.degree() == 1: return self._K(self._K.ring_of_integers()(x)) else: diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 742729981eb..756cbbc9efc 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -151,10 +151,18 @@ def is_FractionField(x) -> bool: sage: from sage.rings.fraction_field import is_FractionField sage: is_FractionField(Frac(ZZ['x'])) + doctest:warning... + DeprecationWarning: The function is_FractionField is deprecated; + use 'isinstance(..., FractionField_generic)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_FractionField(QQ) False """ + from sage.misc.superseded import deprecation + deprecation(38128, + "The function is_FractionField is deprecated; " + "use 'isinstance(..., FractionField_generic)' instead.") return isinstance(x, FractionField_generic) diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index a9c427c03bc..e651a0bf560 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -37,12 +37,20 @@ def is_FractionFieldElement(x): sage: from sage.rings.fraction_field_element import is_FractionFieldElement sage: R. = ZZ[] sage: is_FractionFieldElement(x/2) + doctest:warning... + DeprecationWarning: The function is_FractionFieldElement is deprecated; + use 'isinstance(..., FractionFieldElement)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. False sage: is_FractionFieldElement(2/x) True sage: is_FractionFieldElement(1/3) False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_FractionFieldElement is deprecated; " + "use 'isinstance(..., FractionFieldElement)' instead.") return isinstance(x, FractionFieldElement) diff --git a/src/sage/rings/function_field/differential.py b/src/sage/rings/function_field/differential.py index ba2144d910b..4442a63bd22 100644 --- a/src/sage/rings/function_field/differential.py +++ b/src/sage/rings/function_field/differential.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.modules """ Differentials of function fields diff --git a/src/sage/rings/function_field/divisor.py b/src/sage/rings/function_field/divisor.py index f3dddb48d7c..30d99d920d4 100644 --- a/src/sage/rings/function_field/divisor.py +++ b/src/sage/rings/function_field/divisor.py @@ -1,5 +1,5 @@ -# sage.doctest: optional - sage.rings.finite_rings (because all doctests use finite fields) -# sage.doctest: optional - sage.rings.function_field (because almost all doctests use function field extensions) +# sage.doctest: needs sage.rings.finite_rings (because all doctests use finite fields) +# sage.doctest: needs sage.rings.function_field (because almost all doctests use function field extensions) """ Divisors of function fields diff --git a/src/sage/rings/function_field/drinfeld_modules/action.py b/src/sage/rings/function_field/drinfeld_modules/action.py index cfa9774058a..6fca6225d60 100644 --- a/src/sage/rings/function_field/drinfeld_modules/action.py +++ b/src/sage/rings/function_field/drinfeld_modules/action.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings r""" The module action induced by a Drinfeld module diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 958347113c0..55b4cfab326 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings r""" Drinfeld modules diff --git a/src/sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py index 5c834733321..470dfc495d7 100644 --- a/src/sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings r""" Finite Drinfeld modules diff --git a/src/sage/rings/function_field/drinfeld_modules/homset.py b/src/sage/rings/function_field/drinfeld_modules/homset.py index 9ca53442cf5..d50e943686b 100644 --- a/src/sage/rings/function_field/drinfeld_modules/homset.py +++ b/src/sage/rings/function_field/drinfeld_modules/homset.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings r""" Set of morphisms between two Drinfeld modules diff --git a/src/sage/rings/function_field/drinfeld_modules/morphism.py b/src/sage/rings/function_field/drinfeld_modules/morphism.py index dfed15f778c..c7e1f6c3bfe 100644 --- a/src/sage/rings/function_field/drinfeld_modules/morphism.py +++ b/src/sage/rings/function_field/drinfeld_modules/morphism.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings r""" Drinfeld module morphisms diff --git a/src/sage/rings/function_field/element.pyx b/src/sage/rings/function_field/element.pyx index a5699080814..5e8254e8294 100644 --- a/src/sage/rings/function_field/element.pyx +++ b/src/sage/rings/function_field/element.pyx @@ -187,7 +187,7 @@ cdef class FunctionFieldElement(FieldElement): Now an example in a nontrivial extension of a rational function field:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: y.matrix() @@ -199,7 +199,7 @@ cdef class FunctionFieldElement(FieldElement): An example in a relative extension, where neither function field is rational:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ) sage: R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) @@ -222,7 +222,7 @@ cdef class FunctionFieldElement(FieldElement): We show that this matrix does indeed work as expected when making a vector space from a function field:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ) sage: R. = K[] sage: L. = K.extension(y^5 - (x^3 + 2*x*y + 1/x)) @@ -254,7 +254,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) # needs sage.rings.function_field - sage: y.trace() # needs sage.modules sage.rings.function_field + sage: y.trace() # needs sage.rings.function_field x """ return self.matrix().trace() @@ -267,7 +267,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) # needs sage.rings.function_field - sage: y.norm() # needs sage.modules sage.rings.function_field + sage: y.norm() # needs sage.rings.function_field 4*x^3 The norm is relative:: @@ -275,9 +275,9 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3); R. = L[] # needs sage.rings.function_field sage: M. = L.extension(z^3 - y^2*z + x) # needs sage.rings.function_field - sage: z.norm() # needs sage.modules sage.rings.function_field + sage: z.norm() # needs sage.rings.function_field -x - sage: z.norm().parent() # needs sage.modules sage.rings.function_field + sage: z.norm().parent() # needs sage.rings.function_field Function field in y defined by y^2 - x*y + 4*x^3 """ return self.matrix().determinant() @@ -326,13 +326,15 @@ cdef class FunctionFieldElement(FieldElement): EXAMPLES:: sage: K. = FunctionField(QQ); R. = K[] - sage: L. = K.extension(y^2 - x*y + 4*x^3); R. = L[] # needs sage.rings.function_field - sage: M. = L.extension(z^3 - y^2*z + x) # needs sage.rings.function_field sage: x.characteristic_polynomial('W') # needs sage.modules W - x - sage: y.characteristic_polynomial('W') # needs sage.modules sage.rings.function_field + + sage: # needs sage.rings.function_field + sage: L. = K.extension(y^2 - x*y + 4*x^3); R. = L[] + sage: M. = L.extension(z^3 - y^2*z + x) + sage: y.characteristic_polynomial('W') W^2 - x*W + 4*x^3 - sage: z.characteristic_polynomial('W') # needs sage.modules sage.rings.function_field + sage: z.characteristic_polynomial('W') W^3 + (-x*y + 4*x^3)*W + x """ return self.matrix().characteristic_polynomial(*args, **kwds) @@ -347,13 +349,15 @@ cdef class FunctionFieldElement(FieldElement): EXAMPLES:: sage: K. = FunctionField(QQ); R. = K[] - sage: L. = K.extension(y^2 - x*y + 4*x^3); R. = L[] # needs sage.rings.function_field - sage: M. = L.extension(z^3 - y^2*z + x) # needs sage.rings.function_field sage: x.minimal_polynomial('W') # needs sage.modules W - x - sage: y.minimal_polynomial('W') # needs sage.modules sage.rings.function_field + + sage: # needs sage.rings.function_field + sage: L. = K.extension(y^2 - x*y + 4*x^3); R. = L[] + sage: M. = L.extension(z^3 - y^2*z + x) + sage: y.minimal_polynomial('W') W^2 - x*W + 4*x^3 - sage: z.minimal_polynomial('W') # needs sage.modules sage.rings.function_field + sage: z.minimal_polynomial('W') W^3 + (-x*y + 4*x^3)*W + x """ return self.matrix().minimal_polynomial(*args, **kwds) @@ -366,7 +370,7 @@ cdef class FunctionFieldElement(FieldElement): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: y.is_integral() @@ -396,7 +400,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x +1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (y^3 + x).differential() # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (y^3 + x).differential() # needs sage.rings.finite_rings sage.rings.function_field (((x^2 + 1)/x^2)*y + (x^4 + x^3 + 1)/x^3) d(x) TESTS: @@ -404,16 +408,17 @@ cdef class FunctionFieldElement(FieldElement): Verify that :issue:`27712` is resolved:: sage: K. = FunctionField(GF(31)) - sage: R. = K[] - sage: L. = K.extension(y^2 - x) # needs sage.rings.function_field - sage: R. = L[] # needs sage.rings.function_field - sage: M. = L.extension(z^2 - y) # needs sage.rings.function_field - sage: x.differential() # needs sage.modules d(x) - sage: y.differential() # needs sage.modules sage.rings.function_field + + sage: # needs sage.rings.function_field + sage: R. = K[] + sage: L. = K.extension(y^2 - x) + sage: R. = L[] + sage: M. = L.extension(z^2 - y) + sage: y.differential() (16/x*y) d(x) - sage: z.differential() # needs sage.modules sage.rings.function_field + sage: z.differential() (8/x*z) d(x) """ F = self.parent() @@ -436,7 +441,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (y^3 + x).derivative() # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (y^3 + x).derivative() # needs sage.rings.finite_rings sage.rings.function_field ((x^2 + 1)/x^2)*y + (x^4 + x^3 + 1)/x^3 """ D = self.parent().derivation() @@ -458,14 +463,14 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(2)) sage: f = t^2 - sage: f.higher_derivative(2) # needs sage.modules sage.rings.function_field + sage: f.higher_derivative(2) # needs sage.rings.function_field 1 :: sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (y^3 + x).higher_derivative(2) # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (y^3 + x).higher_derivative(2) # needs sage.rings.finite_rings sage.rings.function_field 1/x^3*y + (x^6 + x^4 + x^3 + x^2 + x + 1)/x^5 """ D = self.parent().higher_derivation() @@ -489,7 +494,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(2)); _. = K[] sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.function_field - sage: y.divisor() # needs sage.modules sage.rings.function_field + sage: y.divisor() # needs sage.rings.function_field - Place (1/x, 1/x*y) - Place (x, x*y) + 2*Place (x + 1, x*y) @@ -517,7 +522,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (x/y).divisor_of_zeros() # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (x/y).divisor_of_zeros() # needs sage.rings.finite_rings sage.rings.function_field 3*Place (x, x*y) """ if self.is_zero(): @@ -544,7 +549,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (x/y).divisor_of_poles() # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (x/y).divisor_of_poles() # needs sage.rings.finite_rings sage.rings.function_field Place (1/x, 1/x*y) + 2*Place (x + 1, x*y) """ if self.is_zero(): @@ -570,7 +575,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (x/y).zeros() # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (x/y).zeros() # needs sage.rings.finite_rings sage.rings.function_field [Place (x, x*y)] """ return self.divisor_of_zeros().support() @@ -590,7 +595,7 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(4)); _. = K[] # needs sage.rings.finite_rings sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings sage.rings.function_field - sage: (x/y).poles() # needs sage.modules sage.rings.finite_rings sage.rings.function_field + sage: (x/y).poles() # needs sage.rings.finite_rings sage.rings.function_field [Place (1/x, 1/x*y), Place (x + 1, x*y)] """ return self.divisor_of_poles().support() @@ -607,8 +612,8 @@ cdef class FunctionFieldElement(FieldElement): sage: K. = FunctionField(GF(2)); _. = K[] sage: L. = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.function_field - sage: p = L.places_infinite()[0] # needs sage.modules sage.rings.function_field - sage: y.valuation(p) # needs sage.modules sage.rings.function_field + sage: p = L.places_infinite()[0] # needs sage.rings.function_field + sage: y.valuation(p) # needs sage.rings.function_field -1 :: diff --git a/src/sage/rings/function_field/element_polymod.pyx b/src/sage/rings/function_field/element_polymod.pyx index 7a75bfe978e..55e887ea491 100644 --- a/src/sage/rings/function_field/element_polymod.pyx +++ b/src/sage/rings/function_field/element_polymod.pyx @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.function_field +# sage.doctest: needs sage.rings.function_field r""" Elements of function fields: extension """ diff --git a/src/sage/rings/function_field/element_rational.pyx b/src/sage/rings/function_field/element_rational.pyx index 40d0d9734ef..5ad0d81341d 100644 --- a/src/sage/rings/function_field/element_rational.pyx +++ b/src/sage/rings/function_field/element_rational.pyx @@ -74,10 +74,11 @@ cdef class FunctionFieldElement_rational(FunctionFieldElement): sage: K. = FunctionField(GF(7)) sage: t.element() t - sage: type(t.element()) # needs sage.rings.finite_rings + sage: type(t.element()) # needs sage.libs.ntl <... 'sage.rings.fraction_field_FpT.FpTElement'> - sage: K. = FunctionField(GF(131101)) # needs sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: K. = FunctionField(GF(131101)) sage: t.element() t sage: type(t.element()) @@ -392,9 +393,9 @@ cdef class FunctionFieldElement_rational(FunctionFieldElement): True sage: f.is_nth_power(3) # needs sage.modules False - sage: (f^3).is_nth_power(3) + sage: (f^3).is_nth_power(3) # needs sage.modules True - sage: (f^9).is_nth_power(-9) + sage: (f^9).is_nth_power(-9) # needs sage.modules True """ if n == 1: @@ -437,7 +438,6 @@ cdef class FunctionFieldElement_rational(FunctionFieldElement): EXAMPLES:: - sage: # needs sage.rings.finite_rings sage: K. = FunctionField(GF(3)) sage: f = (x+1)/(x+2) sage: f.nth_root(1) @@ -446,9 +446,9 @@ cdef class FunctionFieldElement_rational(FunctionFieldElement): Traceback (most recent call last): ... ValueError: element is not an n-th power - sage: (f^3).nth_root(3) + sage: (f^3).nth_root(3) # needs sage.modules (x + 1)/(x + 2) - sage: (f^9).nth_root(-9) + sage: (f^9).nth_root(-9) # needs sage.modules (x + 2)/(x + 1) """ if n == 0: diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 5e8105db36a..315f58cdc39 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -190,7 +190,7 @@ The gap numbers for Weierstrass places are of course not ordinary:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: p1,p2,p3 = L.weierstrass_places()[:3] sage: p1.gaps() [1, 2, 4] @@ -532,9 +532,9 @@ def order(self, x, check=True): sage: O.basis() # needs sage.modules (1, y, y^2) - sage: Z = K.order(x); Z # needs sage.modules sage.rings.function_field + sage: Z = K.order(x); Z # needs sage.rings.function_field Order in Rational function field in x over Rational Field - sage: Z.basis() # needs sage.modules sage.rings.function_field + sage: Z.basis() # needs sage.rings.function_field (1,) Orders with multiple generators are not yet supported:: @@ -619,7 +619,7 @@ def order_infinite(self, x, check=True): sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^3 + x^3 + 4*x + 1) # needs sage.rings.function_field - sage: L.order_infinite(y) # not implemented # needs sage.modules sage.rings.function_field + sage: L.order_infinite(y) # not implemented # needs sage.rings.function_field sage: Z = K.order(x); Z # needs sage.modules Order in Rational function field in x over Rational Field @@ -1016,7 +1016,7 @@ def space_of_differentials(self): sage: K. = FunctionField(GF(5)); _. = K[] sage: L. = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.function_field - sage: L.space_of_differentials() # needs sage.modules sage.rings.function_field + sage: L.space_of_differentials() # needs sage.rings.function_field Space of differentials of Function field in y defined by y^3 + (4*x^3 + 1)/(x^3 + 3) """ @@ -1040,7 +1040,7 @@ def space_of_holomorphic_differentials(self): sage: K. = FunctionField(GF(5)); _. = K[] sage: L. = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.function_field - sage: L.space_of_holomorphic_differentials() # needs sage.modules sage.rings.function_field + sage: L.space_of_holomorphic_differentials() # needs sage.rings.function_field (Vector space of dimension 4 over Finite Field of size 5, Linear map: From: Vector space of dimension 4 over Finite Field of size 5 @@ -1067,7 +1067,7 @@ def basis_of_holomorphic_differentials(self): sage: K. = FunctionField(GF(5)); _. = K[] sage: L. = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.function_field - sage: L.basis_of_holomorphic_differentials() # needs sage.modules sage.rings.function_field + sage: L.basis_of_holomorphic_differentials() # needs sage.rings.function_field [((x/(x^3 + 4))*y) d(x), ((1/(x^3 + 4))*y) d(x), ((x/(x^3 + 4))*y^2) d(x), @@ -1089,12 +1089,12 @@ def divisor_group(self): sage: _. = K[] sage: L. = K.extension(Y^3 - (t^3 - 1)/(t^3 - 2)) # needs sage.rings.function_field - sage: L.divisor_group() # needs sage.modules sage.rings.function_field + sage: L.divisor_group() # needs sage.rings.function_field Divisor group of Function field in y defined by y^3 + (-t^3 + 1)/(t^3 - 2) sage: K. = FunctionField(GF(5)); _. = K[] sage: L. = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.function_field - sage: L.divisor_group() # needs sage.modules sage.rings.function_field + sage: L.divisor_group() # needs sage.rings.function_field Divisor group of Function field in y defined by y^3 + (4*x^3 + 1)/(x^3 + 3) """ from .divisor import DivisorGroup diff --git a/src/sage/rings/function_field/function_field_polymod.py b/src/sage/rings/function_field/function_field_polymod.py index ef72935eba6..fd8c975e682 100644 --- a/src/sage/rings/function_field/function_field_polymod.py +++ b/src/sage/rings/function_field/function_field_polymod.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.function_field +# sage.doctest: needs sage.rings.function_field r""" Function Fields: extension """ diff --git a/src/sage/rings/function_field/function_field_rational.py b/src/sage/rings/function_field/function_field_rational.py index 2226c086b00..bb2075b1ecf 100644 --- a/src/sage/rings/function_field/function_field_rational.py +++ b/src/sage/rings/function_field/function_field_rational.py @@ -102,7 +102,7 @@ class RationalFunctionField(FunctionField): sage: R. = FunctionField(QQ) sage: L. = R[] sage: F. = R.extension(y^2 - (x^2+1)) # needs sage.rings.function_field - sage: (y/x).divisor() # needs sage.modules sage.rings.function_field + sage: (y/x).divisor() # needs sage.rings.function_field - Place (x, y - 1) - Place (x, y + 1) + Place (x^2 + 1, y) @@ -112,15 +112,13 @@ class RationalFunctionField(FunctionField): sage: NF. = NumberField(z^2 + 1) sage: R. = FunctionField(NF) sage: L. = R[] - sage: F. = R.extension(y^2 - (x^2+1)) # needs sage.modules sage.rings.function_field - - sage: (x/y*x.differential()).divisor() # needs sage.modules sage.rings.function_field sage.rings.number_field + sage: F. = R.extension(y^2 - (x^2+1)) # needs sage.rings.function_field + sage: (x/y*x.differential()).divisor() # needs sage.rings.function_field -2*Place (1/x, 1/x*y - 1) - 2*Place (1/x, 1/x*y + 1) + Place (x, y - 1) + Place (x, y + 1) - - sage: (x/y).divisor() # needs sage.modules sage.rings.function_field sage.rings.number_field + sage: (x/y).divisor() # needs sage.rings.function_field - Place (x - i, y) + Place (x, y - 1) + Place (x, y + 1) @@ -135,7 +133,6 @@ def __init__(self, constant_field, names, category=None): EXAMPLES:: - sage: K. = FunctionField(CC); K # needs sage.rings.real_mpfr Rational function field in t over Complex Field with 53 bits of precision sage: TestSuite(K).run() # long time (5s) # needs sage.rings.real_mpfr diff --git a/src/sage/rings/function_field/ideal.py b/src/sage/rings/function_field/ideal.py index 47fba9754f7..00450c60533 100644 --- a/src/sage/rings/function_field/ideal.py +++ b/src/sage/rings/function_field/ideal.py @@ -455,14 +455,14 @@ def divisor(self): EXAMPLES:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings sage: K. = FunctionField(GF(4)) sage: O = K.maximal_order() sage: I = O.ideal(x*(x + 1)^2/(x^2 + x + 1)) sage: I.divisor() Place (x) + 2*Place (x + 1) - Place (x + z2) - Place (x + z2 + 1) - sage: # needs sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings sage: Oinf = K.maximal_order_infinite() sage: I = Oinf.ideal((x + 1)/(x^3 + 1)) sage: I.divisor() @@ -528,7 +528,7 @@ def divisor_of_zeros(self): sage: I.divisor_of_zeros() 2*Place (1/x) - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(GF(2)); _. = K[] sage: L. = K.extension(Y^2 + Y + x + 1/x) sage: O = L.maximal_order() @@ -565,7 +565,7 @@ def divisor_of_poles(self): sage: I.divisor_of_poles() 0 - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(GF(2)); _. = K[] sage: L. = K.extension(Y^2 + Y + x + 1/x) sage: O = L.maximal_order() diff --git a/src/sage/rings/function_field/ideal_polymod.py b/src/sage/rings/function_field/ideal_polymod.py index da45bc508cf..83a1370e493 100644 --- a/src/sage/rings/function_field/ideal_polymod.py +++ b/src/sage/rings/function_field/ideal_polymod.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.function_field +# sage.doctest: needs sage.rings.function_field r""" Ideals of function fields: extension """ diff --git a/src/sage/rings/function_field/maps.py b/src/sage/rings/function_field/maps.py index dedd3d2a998..2863a953f20 100644 --- a/src/sage/rings/function_field/maps.py +++ b/src/sage/rings/function_field/maps.py @@ -72,7 +72,7 @@ class FunctionFieldVectorSpaceIsomorphism(Morphism): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -85,7 +85,7 @@ def _repr_(self) -> str: EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -109,7 +109,7 @@ def is_injective(self) -> bool: EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -124,7 +124,7 @@ def is_surjective(self) -> bool: EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -191,7 +191,7 @@ class MapVectorSpaceToFunctionField(FunctionFieldVectorSpaceIsomorphism): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space(); f @@ -203,7 +203,7 @@ def __init__(self, V, K): """ EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space(); type(f) @@ -224,7 +224,7 @@ def _call_(self, v): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ) sage: R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) @@ -236,7 +236,7 @@ def _call_(self, v): Test that this map is a bijection for some random inputs:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: R. = L[] sage: M. = L.extension(z^3 - y - x) sage: for F in [K, L, M]: @@ -270,7 +270,7 @@ def domain(self): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -285,7 +285,7 @@ def codomain(self): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -301,7 +301,7 @@ class MapFunctionFieldToVectorSpace(FunctionFieldVectorSpaceIsomorphism): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space(); t @@ -321,7 +321,7 @@ def __init__(self, K, V): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -339,7 +339,7 @@ def _call_(self, x): EXAMPLES:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: K. = FunctionField(QQ); R. = K[] sage: L. = K.extension(y^2 - x*y + 4*x^3) sage: V, f, t = L.vector_space() @@ -350,7 +350,7 @@ def _call_(self, x): Test that this map is a bijection for some random inputs:: - sage: # needs sage.modules sage.rings.function_field + sage: # needs sage.rings.function_field sage: R. = L[] sage: M. = L.extension(z^3 - y - x) sage: for F in [K, L, M]: diff --git a/src/sage/rings/function_field/order.py b/src/sage/rings/function_field/order.py index 6ffe40c5faf..0afeaa5f526 100644 --- a/src/sage/rings/function_field/order.py +++ b/src/sage/rings/function_field/order.py @@ -274,7 +274,7 @@ def _repr_(self): sage: K. = FunctionField(GF(2)); R. = PolynomialRing(K) sage: F. = K.extension(t^3 - x^2*(x^2+x+1)^2) # needs sage.rings.function_field - sage: F.maximal_order_infinite() # needs sage.modules sage.rings.function_field + sage: F.maximal_order_infinite() # needs sage.rings.function_field Maximal infinite order of Function field in y defined by y^3 + x^6 + x^4 + x^2 """ return "Maximal infinite order of %s" % (self.function_field(),) diff --git a/src/sage/rings/function_field/order_polymod.py b/src/sage/rings/function_field/order_polymod.py index d6831fa7248..ad760aad0b6 100644 --- a/src/sage/rings/function_field/order_polymod.py +++ b/src/sage/rings/function_field/order_polymod.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.function_field +# sage.doctest: needs sage.rings.function_field r""" Orders of function fields: extension """ diff --git a/src/sage/rings/function_field/order_rational.py b/src/sage/rings/function_field/order_rational.py index 99da2af1ebd..b21712bcf2c 100644 --- a/src/sage/rings/function_field/order_rational.py +++ b/src/sage/rings/function_field/order_rational.py @@ -129,7 +129,7 @@ def _residue_field(self, ideal, name=None): EXAMPLES:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings sage: F. = FunctionField(GF(2)) sage: O = F.maximal_order() sage: I = O.ideal(x^2 + x + 1) @@ -150,7 +150,7 @@ def _residue_field(self, ideal, name=None): sage: to_R(e2).parent() is R True - sage: # needs sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings sage: F. = FunctionField(GF(2)) sage: O = F.maximal_order() sage: I = O.ideal(x + 1) @@ -171,20 +171,21 @@ def _residue_field(self, ideal, name=None): sage: to_R(e2).parent() is R True + sage: # needs sage.modules sage.rings.number_field sage: F. = FunctionField(QQ) sage: O = F.maximal_order() sage: I = O.ideal(x^2 + x + 1) - sage: R, fr_R, to_R = O._residue_field(I) # needs sage.rings.number_field - sage: R # needs sage.rings.number_field + sage: R, fr_R, to_R = O._residue_field(I) + sage: R Number Field in a with defining polynomial x^2 + x + 1 - sage: e1, e2 = fr_R(R.random_element()), fr_R(R.random_element()) # needs sage.rings.number_field - sage: to_R(e1 * e2) == to_R(e1) * to_R(e2) # needs sage.rings.number_field + sage: e1, e2 = fr_R(R.random_element()), fr_R(R.random_element()) + sage: to_R(e1 * e2) == to_R(e1) * to_R(e2) True - sage: to_R(e1 + e2) == to_R(e1) + to_R(e2) # needs sage.rings.number_field + sage: to_R(e1 + e2) == to_R(e1) + to_R(e2) True - sage: to_R(e1).parent() is R # needs sage.rings.number_field + sage: to_R(e1).parent() is R True - sage: to_R(e2).parent() is R # needs sage.rings.number_field + sage: to_R(e2).parent() is R True sage: F. = FunctionField(QQ) diff --git a/src/sage/rings/function_field/place.py b/src/sage/rings/function_field/place.py index efff8d4305e..a17c97b7316 100644 --- a/src/sage/rings/function_field/place.py +++ b/src/sage/rings/function_field/place.py @@ -252,7 +252,7 @@ def __radd__(self, other): sage: k. = GF(2) sage: K. = FunctionField(k) - sage: sum(K.places_finite()) # needs sage.libs.pari + sage: sum(K.places_finite()) # needs sage.libs.pari sage.modules Place (x) + Place (x + 1) Note that this does not work, as wanted:: diff --git a/src/sage/rings/function_field/place_polymod.py b/src/sage/rings/function_field/place_polymod.py index f345c31129e..ee9e8de5874 100644 --- a/src/sage/rings/function_field/place_polymod.py +++ b/src/sage/rings/function_field/place_polymod.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.function_field +# sage.doctest: needs sage.rings.function_field """ Places of function fields: extension """ diff --git a/src/sage/rings/function_field/place_rational.py b/src/sage/rings/function_field/place_rational.py index 9b98397ba90..31ffd6a40b0 100644 --- a/src/sage/rings/function_field/place_rational.py +++ b/src/sage/rings/function_field/place_rational.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings (because all doctests use finite fields) +# sage.doctest: needs sage.rings.finite_rings (because all doctests use finite fields) """ Places of function fields: rational """ @@ -102,6 +102,7 @@ def _residue_field(self, name=None): EXAMPLES:: + sage: # needs sage.modules sage: F. = FunctionField(GF(2)) sage: O = F.maximal_order() sage: i = O.ideal(x^2 + x + 1) diff --git a/src/sage/rings/function_field/valuation_ring.py b/src/sage/rings/function_field/valuation_ring.py index 81fc97d3324..e1fe9751b0b 100644 --- a/src/sage/rings/function_field/valuation_ring.py +++ b/src/sage/rings/function_field/valuation_ring.py @@ -1,5 +1,5 @@ -# sage.doctest: optional - sage.rings.finite_rings -# sage.doctest: optional - sage.rings.function_field +# sage.doctest: needs sage.rings.finite_rings +# sage.doctest: needs sage.rings.function_field r""" Valuation rings of function fields diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 6d9155b643f..b4a1fa5039b 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -326,6 +326,10 @@ def is_Integer(x): sage: from sage.rings.integer import is_Integer sage: is_Integer(2) + doctest:warning... + DeprecationWarning: The function is_Integer is deprecated; + use 'isinstance(..., Integer)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_Integer(2/1) False @@ -334,6 +338,10 @@ def is_Integer(x): sage: is_Integer('5') False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_Integer is deprecated; " + "use 'isinstance(..., Integer)' instead.") return isinstance(x, Integer) diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 12b522a8bd7..a1574d00756 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -96,6 +96,10 @@ def is_IntegerRing(x): sage: from sage.rings.integer_ring import is_IntegerRing sage: is_IntegerRing(ZZ) + doctest:warning... + DeprecationWarning: The function is_IntegerRing is deprecated; + use 'isinstance(..., IntegerRing_class)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_IntegerRing(QQ) False @@ -104,6 +108,10 @@ def is_IntegerRing(x): sage: is_IntegerRing(parent(1/3)) False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_IntegerRing is deprecated; " + "use 'isinstance(..., IntegerRing_class)' instead.") return isinstance(x, IntegerRing_class) diff --git a/src/sage/rings/laurent_series_ring.py b/src/sage/rings/laurent_series_ring.py index 8df962fe320..e2b03bcca58 100644 --- a/src/sage/rings/laurent_series_ring.py +++ b/src/sage/rings/laurent_series_ring.py @@ -503,7 +503,7 @@ def _element_constructor_(self, x, n=0, prec=infinity): sage: P({-3: 1}) x^-3 """ - from sage.rings.fraction_field_element import is_FractionFieldElement + from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.lazy_series import LazyPowerSeries, LazyLaurentSeries from sage.rings.polynomial.multi_polynomial import MPolynomial from sage.rings.polynomial.polynomial_element import Polynomial @@ -536,7 +536,7 @@ def _element_constructor_(self, x, n=0, prec=infinity): return (x << n).add_bigoh(bigoh) else: # General case, pretend to be a polynomial return (self(self.polynomial_ring()(x)) << n).add_bigoh(prec) - elif (is_FractionFieldElement(x) + elif (isinstance(x, FractionFieldElement) and (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and isinstance(x.numerator(), (Polynomial, MPolynomial))): x = self(x.numerator()) / self(x.denominator()) diff --git a/src/sage/rings/number_field/splitting_field.py b/src/sage/rings/number_field/splitting_field.py index ef26176664a..7fefcd02ce5 100644 --- a/src/sage/rings/number_field/splitting_field.py +++ b/src/sage/rings/number_field/splitting_field.py @@ -21,7 +21,7 @@ from sage.arith.misc import factorial from sage.rings.number_field.number_field import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.rational_field import RationalField, is_RationalField +from sage.rings.rational_field import RationalField from sage.libs.pari.all import pari, PariError @@ -382,7 +382,7 @@ def splitting_field(poly, name, map=False, degree_multiple=None, abort_degree=No # Kpol = PARI polynomial in y defining the extension found so far F = poly.base_ring() - if is_RationalField(F): + if isinstance(F, RationalField): Kpol = pari("'y") else: Kpol = F.pari_polynomial("y") diff --git a/src/sage/rings/number_field/totallyreal_rel.py b/src/sage/rings/number_field/totallyreal_rel.py index 46b5cd8ac3b..8ce8efb1c02 100644 --- a/src/sage/rings/number_field/totallyreal_rel.py +++ b/src/sage/rings/number_field/totallyreal_rel.py @@ -287,7 +287,7 @@ def __init__(self, F, m, B, a=None): Z_Fbasis = self.Z_F.basis() # Initialize variables. - if a == []: + if not a: # No starting input, all polynomials will be found; initialize to zero. self.a = [0]*m + [1] self.amaxvals = [[]]*m @@ -301,7 +301,7 @@ def __init__(self, F, m, B, a=None): import numpy for i in range(len(anm1s)): Q = [[v(m*x) for v in self.Foo] + [0] for x in Z_Fbasis] + [[v(anm1s[i]) for v in self.Foo] + [10**6]] - pari_string = '['+';'.join([','.join(["%s" % ii for ii in row]) for row in zip(*Q)])+']' + pari_string = '[' + ';'.join(','.join("%s" % ii for ii in row) for row in zip(*Q)) + ']' adj = pari(pari_string).qflll()[self.d] anm1s[i] += sum([m*Z_Fbasis[ii]*int(adj[ii])//int(adj[self.d]) for ii in range(self.d)]) diff --git a/src/sage/rings/padics/common_conversion.pyx b/src/sage/rings/padics/common_conversion.pyx index 0afddcc30a4..2a143e6d99e 100644 --- a/src/sage/rings/padics/common_conversion.pyx +++ b/src/sage/rings/padics/common_conversion.pyx @@ -148,7 +148,7 @@ cdef long get_ordp(x, PowComputer_class prime_pow) except? -10000: k = valp(pari_tmp) else: # t_INT and t_FRAC were converted before this function raise TypeError("unsupported coercion from pari: only p-adics, integers and rationals allowed") - elif sage.rings.finite_rings.integer_mod.is_IntegerMod(x): + elif isinstance(x, sage.rings.finite_rings.integer_mod.IntegerMod_abstract): value = x.lift() if mpz_sgn(value.value) == 0: return maxordp @@ -221,7 +221,7 @@ cdef long get_preccap(x, PowComputer_class prime_pow) except? -10000: pari_tmp = (x).g # since get_ordp has been called typ(x.g) == t_PADIC k = valp(pari_tmp) + precp(pari_tmp) - elif sage.rings.finite_rings.integer_mod.is_IntegerMod(x): + elif isinstance(x, sage.rings.finite_rings.integer_mod.IntegerMod_abstract): k = mpz_remove(temp.value, (x.modulus()).value, prime_pow.prime.value) if mpz_cmp_ui(temp.value, 1) != 0: raise TypeError("cannot coerce from the given integer mod ring (not a power of the same prime)") @@ -411,7 +411,7 @@ cdef inline int cconv_shared(mpz_t out, x, long prec, long valshift, PowComputer x = x.sage() if isinstance(x, pAdicGenericElement) and x.parent().is_relaxed(): x = x.lift(valshift + prec) - elif isinstance(x, pAdicGenericElement) or sage.rings.finite_rings.integer_mod.is_IntegerMod(x): + elif isinstance(x, pAdicGenericElement) or isinstance(x, sage.rings.finite_rings.integer_mod.IntegerMod_abstract): x = x.lift() if isinstance(x, Integer): if valshift > 0: diff --git a/src/sage/rings/padics/morphism.pyx b/src/sage/rings/padics/morphism.pyx index c8238bdc9fa..a9f041e1d70 100644 --- a/src/sage/rings/padics/morphism.pyx +++ b/src/sage/rings/padics/morphism.pyx @@ -218,7 +218,6 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): """ return self._power - def __pow__(self,n,modulus): """ Return the `n`-th iterate of this endomorphism. @@ -239,8 +238,7 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): """ return self.__class__(self.domain(), self.power()*n) - - def _composition(self,right): + def _composition(self, right): """ Return self o right. @@ -280,7 +278,6 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): """ return True - def is_surjective(self): """ Return ``True`` since any power of the Frobenius endomorphism @@ -295,7 +292,6 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): """ return True - def is_identity(self): """ Return ``True`` if this morphism is the identity morphism. diff --git a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx index f10738d25d1..09062475876 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx @@ -185,7 +185,7 @@ from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class from sage.rings.padics.padic_generic_element cimport pAdicGenericElement from sage.libs.pari.all import pari_gen from sage.interfaces.abc import GpElement -from sage.rings.finite_rings.integer_mod import is_IntegerMod +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.rings.padics.padic_ext_element cimport pAdicExtElement from sage.rings.padics.precision_error import PrecisionError @@ -339,7 +339,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): x = L else: raise TypeError("unsupported coercion from pari: only p-adics, integers, rationals, polynomials and pol_mods allowed") - elif is_IntegerMod(x): + elif isinstance(x, IntegerMod_abstract): mpz_init(tmp) ctx_prec = mpz_remove(tmp, (x.modulus()).value, self.prime_pow.prime.value) if mpz_cmp_ui(tmp, 1) == 0: diff --git a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx index 8c29fa3ee73..8463d40ce26 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx @@ -203,7 +203,7 @@ from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class from sage.rings.padics.padic_generic_element cimport pAdicGenericElement from sage.libs.pari.all import pari_gen from sage.interfaces.abc import GpElement -from sage.rings.finite_rings.integer_mod import is_IntegerMod +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract from sage.rings.padics.padic_ext_element cimport pAdicExtElement from sage.rings.padics.precision_error import PrecisionError @@ -354,7 +354,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): x = L else: raise TypeError("unsupported coercion from pari: only p-adics, integers, rationals, polynomials and pol_mods allowed") - elif is_IntegerMod(x): + elif isinstance(x, IntegerMod_abstract): mpz_init(tmp) ctx_prec = mpz_remove(tmp, (x.modulus()).value, self.prime_pow.prime.value) if mpz_cmp_ui(tmp, 1) == 0: @@ -1795,7 +1795,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): # (1 + \alpha \pi^{\lambda})^p \equiv { 1 + (\alpha^p - \epsilon \alpha) \pi_K^{p \lambda} mod \mathfrak{p}_K^{p \lambda + 1} if \lambda = \frac{e_K}{p-1} # \ 1 - \epsilon \alpha \pi_K^{\lambda + e} mod \mathfrak{p}_K^{\lambda + e + 1} if \lambda > \frac{e_K}{p-1} - def __pow__(pAdicZZpXCRElement self, _right, m): # m ignored r""" Computes ``self^right``. @@ -3248,6 +3247,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): self._normalize() return self.ext_p_list_precs(pos, self.relprec) + def make_ZZpXCRElement(parent, unit, ordp, relprec, version): """ Unpickling. diff --git a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx index 44d549847a9..f85c6b7f3b4 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -145,7 +145,7 @@ from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class from sage.rings.rational cimport Rational from sage.libs.pari.all import pari_gen from sage.interfaces.abc import GpElement -from sage.rings.finite_rings.integer_mod import is_IntegerMod +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract from sage.rings.finite_rings.integer_mod_ring import IntegerModRing @@ -233,7 +233,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): x = L else: raise TypeError("unsupported coercion from pari: only p-adics, integers, rationals, polynomials and pol_mods allowed") - elif is_IntegerMod(x): + elif isinstance(x, IntegerMod_abstract): if (x.modulus())._is_power_of(parent.prime()): x = x.lift() else: diff --git a/src/sage/rings/padics/padic_ZZ_pX_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_element.pyx index bf892956a16..9ef966c1764 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_element.pyx @@ -41,7 +41,7 @@ from sage.libs.ntl.ntl_ZZ_pContext import ntl_ZZ_pContext from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational from sage.rings.padics.padic_generic_element cimport pAdicGenericElement -from sage.rings.finite_rings.integer_mod import is_IntegerMod +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract from sage.rings.padics.padic_printing cimport pAdicPrinter_class from sage.rings.padics.pow_computer_ext cimport PowComputer_ext from sage.rings.rational_field import QQ @@ -567,6 +567,7 @@ cdef class pAdicZZpXElement(pAdicExtElement): if shift != 0: raise NotImplementedError + def _test_preprocess_list(R, L): r""" Given a list of elements convertible to ``ntl_ZZ_p``s, find the @@ -664,7 +665,7 @@ cdef preprocess_list(pAdicZZpXElement elt, L): L[i] = ntl_ZZ_p(L[i]*pshift_m, ctx) elif isinstance(L[i], pAdicGenericElement) and L[i]._is_base_elt(elt.prime_pow.prime): L[i] = ntl_ZZ_p((L[i] >> min_val).lift(), ctx) - elif is_IntegerMod(L[i]): + elif isinstance(L[i], IntegerMod_abstract): L[i] = ntl_ZZ_p(L[i].lift()*pshift_m, ctx) elif (L[i].modulus_context() is not ctx) or min_val != zero: L[i] = ntl_ZZ_p(L[i].lift()*pshift_z, ctx) @@ -682,7 +683,7 @@ cdef preprocess_list(pAdicZZpXElement elt, L): L[i] = ntl_ZZ_p(L[i]//pshift_m, ctx) elif isinstance(L[i], pAdicGenericElement) and L[i]._is_base_elt(elt.prime_pow.prime): L[i] = ntl_ZZ_p((L[i] >> min_val).lift(), ctx) - elif is_IntegerMod(L[i]): + elif isinstance(L[i], IntegerMod_abstract): L[i] = ntl_ZZ_p(L[i].lift()//pshift_m, ctx) elif (L[i].modulus_context() is not ctx) or min_val != zero: ZZ_div(tmp, (L[i].lift()).x, pshift_z.x) @@ -693,10 +694,11 @@ cdef preprocess_list(pAdicZZpXElement elt, L): for i from 0 <= i < len(L): if isinstance(L[i], (ntl_ZZ, Integer, Rational, int)): L[i] = ntl_ZZ_p(L[i], ctx) - elif (isinstance(L[i], pAdicGenericElement) and L[i]._is_base_elt(elt.prime_pow.prime)) or is_IntegerMod(L[i]) or (L[i].modulus_context() is not ctx): + elif (isinstance(L[i], pAdicGenericElement) and L[i]._is_base_elt(elt.prime_pow.prime)) or isinstance(L[i], IntegerMod_abstract) or (L[i].modulus_context() is not ctx): L[i] = ntl_ZZ_p(L[i].lift(), ctx) return L, min_val, ctx + def _find_val_aprec_test(R, L): r""" Given a list ``L``, finds the minimum valuation, minimum absolute @@ -772,6 +774,7 @@ cdef find_val_aprec(PowComputer_ext pp, L): total_type = cur_type return min_val, min_aprec, total_type + def _test_get_val_prec(R, a): """ Return valuation, absolute precision and type of an input @@ -889,7 +892,7 @@ cdef get_val_prec(PowComputer_ext pp, a): cdef mpz_t leftover cdef long long_val cdef Integer Integer_val - if is_IntegerMod(a): + if isinstance(a, IntegerMod_abstract): mpz_init(leftover) long_val = mpz_remove(leftover, (a.modulus()).value, pp.prime.value) if long_val > 0 and mpz_cmp_ui(leftover, 1) == 0: diff --git a/src/sage/rings/padics/padic_generic_element.pyx b/src/sage/rings/padics/padic_generic_element.pyx index f4e2a51385b..92fa0606de1 100644 --- a/src/sage/rings/padics/padic_generic_element.pyx +++ b/src/sage/rings/padics/padic_generic_element.pyx @@ -595,7 +595,6 @@ cdef class pAdicGenericElement(LocalGenericElement): else: return infinity - def artin_hasse_exp(self, prec=None, algorithm=None): r""" Return the Artin-Hasse exponential of this element. @@ -968,7 +967,6 @@ cdef class pAdicGenericElement(LocalGenericElement): return R(y) - def minimal_polynomial(self, name='x', base=None): """ Returns the minimal polynomial of this element over ``base`` @@ -2970,7 +2968,6 @@ cdef class pAdicGenericElement(LocalGenericElement): retval = R(retval) return retval.add_bigoh(aprec) - def _exp_generic(self, aprec): r""" Compute the exponential power series of this element, using Horner's @@ -3159,7 +3156,6 @@ cdef class pAdicGenericElement(LocalGenericElement): l += (1+b).log(aprec, algorithm=log_algorithm) return a - def exp(self, aprec=None, algorithm=None): r""" Compute the `p`-adic exponential of this element if the exponential @@ -3391,7 +3387,6 @@ cdef class pAdicGenericElement(LocalGenericElement): raise ValueError("algorithm must be 'generic', 'binary_splitting', 'newton' or None") return ans.add_bigoh(aprec) - def square_root(self, extend=True, all=False, algorithm=None): r""" Return the square root of this `p`-adic number. @@ -3594,7 +3589,6 @@ cdef class pAdicGenericElement(LocalGenericElement): else: raise ValueError("element is not a square") - def nth_root(self, n, all=False): """ Return the `n`-th root of this element. @@ -3985,7 +3979,6 @@ cdef class pAdicGenericElement(LocalGenericElement): return x, infinity - def __abs__(self): """ Return the `p`-adic absolute value of ``self``. @@ -4343,7 +4336,9 @@ cdef class pAdicGenericElement(LocalGenericElement): # Artin-Hasse exponential -_AHE_coefficients_cache = { } +_AHE_coefficients_cache = {} + + def _AHE_coefficients(p, N, prec): r""" Compute the first ``N`` coefficients of the ``p``-adic diff --git a/src/sage/rings/padics/padic_printing.pyx b/src/sage/rings/padics/padic_printing.pyx index f134c5afc45..eb5904907ba 100644 --- a/src/sage/rings/padics/padic_printing.pyx +++ b/src/sage/rings/padics/padic_printing.pyx @@ -71,6 +71,7 @@ def pAdicPrinter(ring, options={}): options[option] = None return pAdicPrinter_class(ring, **options) + class pAdicPrinterDefaults(SageObject): """ This class stores global defaults for p-adic printing. diff --git a/src/sage/rings/padics/padic_template_element.pxi b/src/sage/rings/padics/padic_template_element.pxi index 4b5b9c6dbe9..a3b203845b5 100644 --- a/src/sage/rings/padics/padic_template_element.pxi +++ b/src/sage/rings/padics/padic_template_element.pxi @@ -145,7 +145,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): x = [] else: x = [x] - elif sage.rings.finite_rings.integer_mod.is_IntegerMod(x): + elif isinstance(x, sage.rings.finite_rings.integer_mod.IntegerMod_abstract): if not Integer(self.prime_pow.prime).divides(x.parent().order()): raise TypeError("p does not divide modulus %s" % x.parent().order()) elif isinstance(x, Element) and isinstance(x.parent(), FiniteField): diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index 8ce4953fadf..6978a9435b5 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -675,7 +675,6 @@ cdef class PowComputer_ext(PowComputer_class): ZZ_mul(ans.x, self.pow_ZZ_tmp(mpz_get_ui((m).value))[0], self.pow_ZZ_tmp(mpz_get_ui((n).value))[0]) return ans - cdef mpz_srcptr pow_mpz_t_top(self) noexcept: """ Returns self.prime^self.prec_cap as an ``mpz_srcptr``. @@ -1841,7 +1840,6 @@ cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): else: raise IndexError - def __dealloc__(self): """ Deallocates low_shifter and high_shifter. @@ -2272,7 +2270,6 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): else: raise IndexError - def __dealloc__(self): """ Deallocates low_shifter and high_shifter. @@ -2325,6 +2322,7 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): """ return ZZ_pX_eis_shift_p(self, x, a, n, finalprec) + def PowComputer_ext_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, prec_type = "small", ext_type = "u", shift_seed = None): r""" Returns a PowComputer that caches the values `1, p, p^2, \ldots, p^C`, diff --git a/src/sage/rings/padics/pow_computer_flint.pyx b/src/sage/rings/padics/pow_computer_flint.pyx index 2a9c937923f..79f5a971e55 100644 --- a/src/sage/rings/padics/pow_computer_flint.pyx +++ b/src/sage/rings/padics/pow_computer_flint.pyx @@ -588,6 +588,7 @@ cdef class PowComputer_flint_eis(PowComputer_flint_1step): self.f = 1 fmpz_set(self.q, self.fprime) + def PowComputer_flint_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, prec_type): """ Return an appropriate FLINT PowComputer for the given input. diff --git a/src/sage/rings/padics/pow_computer_relative.pyx b/src/sage/rings/padics/pow_computer_relative.pyx index 507a22526fa..2de1fa5688b 100644 --- a/src/sage/rings/padics/pow_computer_relative.pyx +++ b/src/sage/rings/padics/pow_computer_relative.pyx @@ -372,11 +372,12 @@ cdef class PowComputer_relative_eis(PowComputer_relative): return self.poly_ring.one() elif r < self.e: return self.poly_ring.one() << r - elif r%2: + elif r % 2: return (self.uniformizer_pow(r-1) << 1) % self.modulus else: return (self.uniformizer_pow(r//2) * self.uniformizer_pow(r//2)) % self.modulus + def PowComputer_relative_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, shift_seed, prec_type): r""" Create a ``PowComputer``. diff --git a/src/sage/rings/polynomial/binary_form_reduce.py b/src/sage/rings/polynomial/binary_form_reduce.py index ff36ec13ab0..6afb11155cf 100644 --- a/src/sage/rings/polynomial/binary_form_reduce.py +++ b/src/sage/rings/polynomial/binary_form_reduce.py @@ -25,10 +25,8 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.calculus.functions import jacobian -from sage.functions.hyperbolic import cosh, sinh -from sage.functions.log import exp from sage.matrix.constructor import matrix +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.modules.free_module_element import vector from sage.rings.cc import CC @@ -40,6 +38,10 @@ from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RealField +lazy_import("sage.calculus.functions", "jacobian") +lazy_import("sage.functions.hyperbolic", ["cosh", "sinh"]) +lazy_import("sage.functions.log", "exp") + def covariant_z0(F, z0_cov=False, prec=53, emb=None, error_limit=0.000001): r""" diff --git a/src/sage/rings/polynomial/flatten.py b/src/sage/rings/polynomial/flatten.py index 64ab7ed99d5..ef71d2b13a6 100644 --- a/src/sage/rings/polynomial/flatten.py +++ b/src/sage/rings/polynomial/flatten.py @@ -40,7 +40,7 @@ from .polynomial_ring_constructor import PolynomialRing from .polynomial_ring import is_PolynomialRing from .multi_polynomial_ring_base import is_MPolynomialRing -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.polynomial.polydict import ETuple @@ -538,8 +538,8 @@ def __init__(self, domain, D): # Construct unflattened codomain R new_vars = [] R = domain - while is_PolynomialRing(R) or is_MPolynomialRing(R) or is_FractionField(R): - if is_FractionField(R): + while is_PolynomialRing(R) or is_MPolynomialRing(R) or isinstance(R, FractionField_generic): + if isinstance(R, FractionField_generic): # We've hit base_ring, so set _sub_specialization and exit the loop field_over = R.base() applicable_vars = {key: val for key, val in D.items() @@ -679,7 +679,7 @@ def __init__(self, domain, D): To: Fraction Field of Multivariate Polynomial Ring in x, y over Univariate Polynomial Ring in a over Rational Field """ - if not is_FractionField(domain): + if not isinstance(domain, FractionField_generic): raise TypeError("domain must be a fraction field") self._specialization = SpecializationMorphism(domain.base(), D) self._repr_type_str = 'Fraction Specialization' diff --git a/src/sage/rings/polynomial/ideal.py b/src/sage/rings/polynomial/ideal.py index 011cb860290..9eba00860b5 100644 --- a/src/sage/rings/polynomial/ideal.py +++ b/src/sage/rings/polynomial/ideal.py @@ -92,8 +92,9 @@ def change_ring(self, R): EXAMPLES:: sage: R. = QQ[] - sage: I = R.ideal([q^2+q-1]) - sage: I.change_ring(RR['q']) - Principal ideal (q^2 + q - 1.00000000000000) of Univariate Polynomial Ring in q over Real Field with 53 bits of precision + sage: I = R.ideal([q^2 + q - 1]) + sage: I.change_ring(RR['q']) # needs sage.rings.real_mpfr + Principal ideal (q^2 + q - 1.00000000000000) of + Univariate Polynomial Ring in q over Real Field with 53 bits of precision """ return R.ideal(self.gens()) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index cc31da00b9f..6b838190c52 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -226,7 +226,7 @@ import sage.structure.element from sage.rings.rational cimport Rational from sage.rings.rational_field import QQ -from sage.rings.integer_ring import is_IntegerRing, ZZ +from sage.rings.integer_ring import IntegerRing_class, ZZ from sage.rings.integer cimport Integer from sage.rings.number_field.number_field_base cimport NumberField @@ -5489,7 +5489,7 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base): if n_GetChar(_ring.cf) > 1<<29: raise NotImplementedError("Resultants of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.") - if is_IntegerRing(self._parent._base): + if isinstance(self._parent._base, IntegerRing_class): ret = self.change_ring(QQ).resultant(other.change_ring(QQ), variable.change_ring(QQ)) return ret.change_ring(ZZ) diff --git a/src/sage/rings/polynomial/padics/polynomial_padic.py b/src/sage/rings/polynomial/padics/polynomial_padic.py index f836a41957e..4103fbf9fe2 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic.py @@ -274,7 +274,7 @@ def root_field(self, names, check_irreducible=True, **kwds): * ``check_irreducible`` -- check whether the polynomial is irreducible - * ``kwds`` -- see :meth:`sage.ring.padics.padic_generic.pAdicGeneric.extension` + * ``kwds`` -- see :meth:`sage.rings.padics.padic_generic.pAdicGeneric.extension` EXAMPLES:: diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_flat.py b/src/sage/rings/polynomial/padics/polynomial_padic_flat.py index 6d25e6a0a5f..46ef0c0a9b9 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_flat.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_flat.py @@ -31,7 +31,7 @@ def __init__(self, parent, x=None, check=True, is_gen=False, construct=False, ab Polynomial_generic_dense.__init__(self, parent, x, check, is_gen, construct) return R = parent.base_ring() - if sage.rings.fraction_field_element.is_FractionFieldElement(x): + if isinstance(x, sage.rings.fraction_field_element.FractionFieldElement): if x.denominator() != 1: raise TypeError("denominator must be 1") else: diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 6a600f74f53..d78464e1deb 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -120,7 +120,7 @@ import sage.libs.singular.ring from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.integer cimport Integer -from sage.rings.integer_ring import is_IntegerRing +from sage.rings.integer_ring import IntegerRing_class from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular, MPolynomial_libsingular, new_MP from sage.rings.polynomial.multi_polynomial_ideal import NCPolynomialIdeal @@ -532,7 +532,7 @@ cdef class NCPolynomialRing_plural(Ring): _p = p_NSet(_n, _ring) # also accepting ZZ - elif is_IntegerRing(element.parent()): + elif isinstance(element.parent(), IntegerRing_class): if isinstance(base_ring, FiniteField_prime_modn): _p = p_ISet(int(element),_ring) else: diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 1270c42ce2a..dcf2af7cdf2 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -54,7 +54,6 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -cdef is_FractionField cdef ZZ, QQ, RR, CC, RDF, CDF cimport cython @@ -103,11 +102,11 @@ from sage.structure.element import coerce_binop from sage.structure.element cimport (parent, have_same_parent, Element, RingElement) -from sage.rings.rational_field import QQ, is_RationalField -from sage.rings.integer_ring import ZZ, is_IntegerRing +from sage.rings.rational_field import QQ, RationalField +from sage.rings.integer_ring import ZZ, IntegerRing_class from sage.rings.integer cimport Integer, smallInteger from sage.libs.gmp.mpz cimport * -from sage.rings.fraction_field import FractionField, is_FractionField +from sage.rings.fraction_field import FractionField from sage.rings.padics.padic_generic import pAdicGeneric from sage.structure.category_object cimport normalize_names @@ -5026,7 +5025,7 @@ cdef class Polynomial(CommutativePolynomial): n = None - if isinstance(R, sage.rings.abc.IntegerModRing) or is_IntegerRing(R): + if isinstance(R, sage.rings.abc.IntegerModRing) or isinstance(R, IntegerRing_class): try: G = list(self._pari_with_name().factor()) except PariError: @@ -5840,7 +5839,7 @@ cdef class Polynomial(CommutativePolynomial): if self.degree() <= 1: return R.fraction_field() - if is_IntegerRing(R): + if isinstance(R, IntegerRing_class): from sage.rings.number_field.number_field import NumberField return NumberField(self, names) @@ -6411,7 +6410,7 @@ cdef class Polynomial(CommutativePolynomial): from sage.categories.number_fields import NumberFields K = self.base_ring() - if K in NumberFields() or isinstance(K, sage.rings.abc.Order) or is_IntegerRing(K): + if K in NumberFields() or isinstance(K, sage.rings.abc.Order) or isinstance(K, IntegerRing_class): from sage.schemes.projective.projective_space import ProjectiveSpace P = ProjectiveSpace(K, self.number_of_terms() - 1) return P.point(self.coefficients()).global_height(prec=prec) @@ -6538,8 +6537,8 @@ cdef class Polynomial(CommutativePolynomial): TESTS:: - sage: a = RIF['x'](1/3) - sage: (a - a).exponents() + sage: a = RIF['x'](1/3) # needs sage.rings.real_interval_field + sage: (a - a).exponents() # needs sage.rings.real_interval_field [0] """ cdef Py_ssize_t i @@ -7944,11 +7943,12 @@ cdef class Polynomial(CommutativePolynomial): The following examples show that :issue:`11782` has been fixed:: - sage: var('x') # needs sage.symbolic + sage: # needs sage.libs.pari sage.symbolic + sage: var('x') x - sage: ZZ.quo(81)['x'](3*x^2 + 3*x + 3).discriminant() # needs sage.libs.pari sage.symbolic + sage: ZZ.quo(81)['x'](3*x^2 + 3*x + 3).discriminant() 54 - sage: ZZ.quo(9)['x'](2*x^3 + x^2 + x).discriminant() # needs sage.libs.pari sage.symbolic + sage: ZZ.quo(9)['x'](2*x^3 + x^2 + x).discriminant() 2 This was fixed by :issue:`15422`:: @@ -8487,7 +8487,7 @@ cdef class Polynomial(CommutativePolynomial): :: - sage: # needs sage.rings.complex_double sage.rings.real_mpfr + sage: # needs numpy sage.rings.complex_double sage.rings.real_mpfr sage: rflds = (RR, RDF, RealField(100)) sage: cflds = (CC, CDF, ComplexField(100)) sage: def cross(a, b): @@ -8931,7 +8931,7 @@ cdef class Polynomial(CommutativePolynomial): if L != K or isinstance(L, sage.rings.abc.AlgebraicField_common): # So far, the only "special" implementations are for real # and complex root isolation and for p-adic factorization - if (is_IntegerRing(K) or is_RationalField(K) + if (isinstance(K, IntegerRing_class) or isinstance(K, RationalField) or isinstance(K, sage.rings.abc.AlgebraicRealField)) and \ isinstance(L, (sage.rings.abc.AlgebraicRealField, sage.rings.abc.RealIntervalField)): @@ -8961,7 +8961,7 @@ cdef class Polynomial(CommutativePolynomial): else: return [rt for (rt, mult) in rts] - if (is_IntegerRing(K) or is_RationalField(K) + if (isinstance(K, IntegerRing_class) or isinstance(K, RationalField) or isinstance(K, sage.rings.abc.AlgebraicField_common) or input_gaussian) and \ isinstance(L, (sage.rings.abc.ComplexIntervalField, sage.rings.abc.AlgebraicField_common)): @@ -9773,6 +9773,8 @@ cdef class Polynomial(CommutativePolynomial): sage: d = z^4 + (2*t + 4)*z^3 + (-t + 5)*z^2 + (t^2 + 2)*z + t^2 + 2*t + 1 sage: prec = 9 sage: x = n.subs(z=w)/d.subs(z=w) + O(w^prec) + + sage: # needs sage.libs.flint (otherwise timeout) sage: nc, dc = Pz(x.list()).rational_reconstruction(z^prec) sage: (nc, dc) == (n, d) True @@ -9992,8 +9994,8 @@ cdef class Polynomial(CommutativePolynomial): else: raise NotImplementedError else: - from sage.rings.fraction_field import is_FractionField - if is_FractionField(p.parent()) and self._parent.has_coerce_map_from(p.parent().ring()): + from sage.rings.fraction_field import FractionField_generic + if isinstance(p.parent(), FractionField_generic) and self._parent.has_coerce_map_from(p.parent().ring()): _p = self._parent.coerce(p.parent().ring()(p)) # here we require that p be integral. else: raise TypeError("The polynomial, p, must have the same parent as self.") @@ -11983,7 +11985,7 @@ cdef class Polynomial_generic_dense(Polynomial): self._coeffs = x return - if sage.rings.fraction_field_element.is_FractionFieldElement(x): + if isinstance(x, sage.rings.fraction_field_element.FractionFieldElement): if x.denominator() != 1: raise TypeError("denominator must be 1") else: diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index bbad3b17143..a43e34a3fc9 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -12,17 +12,16 @@ AUTHOR: - Sebastian Pancratz """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2010 Sebastian Pancratz # # 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 cysignals.memory cimport check_allocarray, sig_free from cysignals.signals cimport sig_on, sig_str, sig_off from cpython.long cimport PyLong_AsLong diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index bdcfb2de0ae..d0d2d1241ab 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -3623,8 +3623,12 @@ def irreducible_element(self, n, algorithm=None): return self(conway_polynomial(p, n)) elif algorithm == "first_lexicographic": if p == 2: - from .polynomial_gf2x import GF2X_BuildIrred_list - return self(GF2X_BuildIrred_list(n)) + try: + from .polynomial_gf2x import GF2X_BuildIrred_list + except ImportError: + pass + else: + return self(GF2X_BuildIrred_list(n)) else: # Fallback to PolynomialRing_dense_finite_field.irreducible_element pass @@ -3638,8 +3642,12 @@ def irreducible_element(self, n, algorithm=None): raise NotImplementedError("'minimal_weight' option only implemented for p = 2") elif algorithm == "random": if p == 2: - from .polynomial_gf2x import GF2X_BuildRandomIrred_list - return self(GF2X_BuildRandomIrred_list(n)) + try: + from .polynomial_gf2x import GF2X_BuildRandomIrred_list + except ImportError: + pass + else: + return self(GF2X_BuildRandomIrred_list(n)) else: pass diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 3d066e68631..ee7c243087f 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -40,7 +40,7 @@ import sage.rings.abc import sage.rings.number_field as number_field -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.function_field.function_field_rational import RationalFunctionField from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.integer_ring import ZZ @@ -74,7 +74,7 @@ def _do_singular_init_(singular, base_ring, char, _vars, order): if base_ring is ZZ: return make_ring("(ZZ)"), None - if sage.rings.rational_field.is_RationalField(base_ring): + if isinstance(base_ring, sage.rings.rational_field.RationalField): return make_ring("(QQ)"), None elif isinstance(base_ring, sage.rings.abc.RealField): @@ -136,7 +136,7 @@ def _do_singular_init_(singular, base_ring, char, _vars, order): return R, minpoly - elif sage.rings.fraction_field.is_FractionField(base_ring): + elif isinstance(base_ring, sage.rings.fraction_field.FractionField_generic): if base_ring.ngens() == 1: gens = str(base_ring.gen()) else: @@ -430,7 +430,7 @@ def can_convert_to_singular(R): base_ring = R.base_ring() if (base_ring is ZZ - or is_RationalField(base_ring) + or isinstance(base_ring, RationalField) or isinstance(base_ring, (sage.rings.abc.IntegerModRing, sage.rings.abc.RealField, sage.rings.abc.ComplexField, sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField))): @@ -439,7 +439,7 @@ def can_convert_to_singular(R): return base_ring.characteristic() <= 2147483647 elif isinstance(base_ring, NumberField): return base_ring.is_absolute() - elif sage.rings.fraction_field.is_FractionField(base_ring): + elif isinstance(base_ring, sage.rings.fraction_field.FractionField_generic): B = base_ring.base_ring() return (B.is_prime_field() or B is ZZ or (isinstance(B, FiniteField) and B.characteristic() <= 2147483647)) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index f6d391679a6..73e8878150c 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -594,7 +594,7 @@ from sage.rings import infinity from sage.rings.cc import CC from sage.rings.cif import CIF -from sage.rings.complex_interval import is_ComplexIntervalFieldElement +from sage.rings.complex_interval import ComplexIntervalFieldElement from sage.rings.complex_interval_field import ComplexIntervalField from sage.rings.integer_ring import ZZ from sage.rings.number_field.number_field import ( @@ -613,7 +613,7 @@ RIF, RealIntervalField, RealIntervalField_class, - is_RealIntervalFieldElement, + RealIntervalFieldElement, ) from sage.rings.real_mpfr import RR from sage.structure.coerce import parent_is_numerical, parent_is_real_numerical @@ -1436,7 +1436,7 @@ def polynomial_root(self, poly, interval, multiplicity=1): sage: r = AA.polynomial_root(p, RIF(1, 2)); r^3 2.000000000000000? """ - if not is_RealIntervalFieldElement(interval): + if not isinstance(interval, RealIntervalFieldElement): raise ValueError("interval argument of .polynomial_root on algebraic real field must be real") return AlgebraicReal(ANRoot(poly, interval, multiplicity)) @@ -2489,7 +2489,7 @@ def conjugate_expand(v): sage: conjugate_expand(RIF(1, 2)).str(style='brackets') '[1.0000000000000000 .. 2.0000000000000000]' """ - if is_RealIntervalFieldElement(v): + if isinstance(v, RealIntervalFieldElement): return v im = v.imag() if not im.contains_zero(): @@ -2522,7 +2522,7 @@ def conjugate_shrink(v): sage: conjugate_shrink(CIF(RIF(1, 2), RIF(-1, 2))).str(style='brackets') '[1.0000000000000000 .. 2.0000000000000000]' """ - if is_RealIntervalFieldElement(v): + if isinstance(v, RealIntervalFieldElement): return v im = v.imag() if im.contains_zero(): @@ -3776,9 +3776,13 @@ def _repr_(self): if isinstance(self._descr, ANExtensionElement) and self._descr._generator is QQbar_I_generator: return repr(self._descr._value) if self.parent().options.display_format == 'radical': - radical = self.radical_expression() - if radical is not self: - return repr(radical) + try: + radical = self.radical_expression() + except ImportError: + pass + else: + if radical is not self: + return repr(radical) if self.parent() is QQbar: return repr(CIF(self._value)) else: @@ -3819,9 +3823,13 @@ def _latex_(self): if isinstance(self._descr, ANExtensionElement) and self._descr._generator is QQbar_I_generator: return latex(self._descr._value) if self.parent().options.display_format == 'radical': - radical = self.radical_expression() - if radical is not self: - return latex(radical) + try: + radical = self.radical_expression() + except ImportError: + pass + else: + if radical is not self: + return latex(radical) return repr(self).replace('*I', r' \sqrt{-1}') def _sage_input_(self, sib, coerce): @@ -4507,9 +4515,9 @@ def _set_descr(self, new_descr): """ self._descr = new_descr new_val = self._descr._interval_fast(self.parent().default_interval_prec()) - if is_RealIntervalFieldElement(new_val) and is_ComplexIntervalFieldElement(self._value): + if isinstance(new_val, RealIntervalFieldElement) and isinstance(self._value, ComplexIntervalFieldElement): self._value = self._value.real().intersection(new_val) - elif is_RealIntervalFieldElement(self._value) and is_ComplexIntervalFieldElement(new_val): + elif isinstance(self._value, RealIntervalFieldElement) and isinstance(new_val, ComplexIntervalFieldElement): self._value = self._value.intersection(new_val.real()) else: self._value = self._value.intersection(new_val) @@ -4757,7 +4765,7 @@ def interval(self, field): target = RR(1.0) >> field.prec() val = self.interval_diameter(target) if (isinstance(field, (RealIntervalField_class, RealBallField)) - and is_ComplexIntervalFieldElement(val)): + and isinstance(val, ComplexIntervalFieldElement)): if val.imag().is_zero(): return field(val.real()) elif self.imag().is_zero(): @@ -4826,7 +4834,7 @@ def radical_expression(self): # Adapted from NumberFieldElement._symbolic_() poly = self.minpoly() - if is_ComplexIntervalFieldElement(self._value): + if isinstance(self._value, ComplexIntervalFieldElement): interval_field = self._value.parent() else: interval_field = ComplexIntervalField(self._value.prec()) @@ -5484,7 +5492,7 @@ def _ensure_real(self): sage: type(b._value) """ - if is_ComplexIntervalFieldElement(self._value): + if isinstance(self._value, ComplexIntervalFieldElement): self._value = self._value.real() def _more_precision(self): @@ -6467,7 +6475,7 @@ def _act_(self, e, x): argument = argument - 2 * argument.parent().pi() else: val = x._interval_fast(prec) - if is_RealIntervalFieldElement(val) or not val.crosses_log_branch_cut(): + if isinstance(val, RealIntervalFieldElement) or not val.crosses_log_branch_cut(): argument = val.argument() if val.imag().is_zero() and val.real() < 0: argument_is_pi = True @@ -6749,12 +6757,20 @@ def is_AlgebraicReal(x): sage: from sage.rings.qqbar import is_AlgebraicReal sage: is_AlgebraicReal(AA(sqrt(2))) # needs sage.symbolic + doctest:warning... + DeprecationWarning: The function is_AlgebraicReal is deprecated; + use 'isinstance(..., AlgebraicReal)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_AlgebraicReal(QQbar(sqrt(2))) # needs sage.symbolic False sage: is_AlgebraicReal("spam") False """ + from sage.misc.superseded import deprecation + deprecation(38128, + "The function is_AlgebraicReal is deprecated; " + "use 'isinstance(..., AlgebraicReal)' instead.") return isinstance(x, AlgebraicReal) @@ -6766,12 +6782,20 @@ def is_AlgebraicNumber(x): sage: from sage.rings.qqbar import is_AlgebraicNumber sage: is_AlgebraicNumber(AA(sqrt(2))) # needs sage.symbolic + doctest:warning... + DeprecationWarning: The function is_AlgebraicNumber is deprecated; + use 'isinstance(..., AlgebraicNumber)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. False sage: is_AlgebraicNumber(QQbar(sqrt(2))) # needs sage.symbolic True sage: is_AlgebraicNumber("spam") False """ + from sage.misc.superseded import deprecation + deprecation(38128, + "The function is_AlgebraicNumber is deprecated; " + "use 'isinstance(..., AlgebraicNumber)' instead.") return isinstance(x, AlgebraicNumber) @@ -7052,7 +7076,7 @@ def __init__(self, poly, interval, multiplicity=1): poly = AlgebraicPolynomialTracker(poly) self._poly = poly self._multiplicity = multiplicity - self._complex = is_ComplexIntervalFieldElement(interval) + self._complex = isinstance(interval, ComplexIntervalFieldElement) self._complex_poly = poly.is_complex() self._interval = self.refine_interval(interval, 64) @@ -7138,7 +7162,7 @@ def handle_sage_input(self, sib, coerce, is_qqbar): intv = self._interval # Check whether a 53-bit interval actually isolates the root. # If so, use it, because 53-bit intervals print prettier. - if is_ComplexIntervalFieldElement(intv): + if isinstance(intv, ComplexIntervalFieldElement): loose_intv = CIF(intv) else: loose_intv = RIF(intv) @@ -7988,7 +8012,7 @@ def simplify(self, n): def _interval_fast(self, prec): gen_val = self._generator._interval_fast(prec) v = self._value.polynomial()(gen_val) - if self._exactly_real and is_ComplexIntervalFieldElement(v): + if self._exactly_real and isinstance(v, ComplexIntervalFieldElement): return v.real() return v @@ -8337,7 +8361,7 @@ def _interval_fast(self, prec): v = self._arg._interval_fast(prec) - if not is_ComplexIntervalFieldElement(v): + if not isinstance(v, ComplexIntervalFieldElement): self._complex = False if op == '-': @@ -8347,7 +8371,7 @@ def _interval_fast(self, prec): return ~v if op == 'conjugate': - if is_ComplexIntervalFieldElement(v): + if isinstance(v, ComplexIntervalFieldElement): return v.conjugate() else: return v @@ -8355,13 +8379,13 @@ def _interval_fast(self, prec): self._complex = False if op == 'real': - if is_ComplexIntervalFieldElement(v): + if isinstance(v, ComplexIntervalFieldElement): return v.real() else: return v if op == 'imag': - if is_ComplexIntervalFieldElement(v): + if isinstance(v, ComplexIntervalFieldElement): return v.imag() else: return RealIntervalField(prec)(0) @@ -8370,7 +8394,7 @@ def _interval_fast(self, prec): return abs(v) if op == 'norm': - if is_ComplexIntervalFieldElement(v): + if isinstance(v, ComplexIntervalFieldElement): return v.norm() else: return v.square() @@ -8611,7 +8635,7 @@ def _interval_fast(self, prec): lv = self._left._interval_fast(prec) rv = self._right._interval_fast(prec) - if not (is_ComplexIntervalFieldElement(lv) or is_ComplexIntervalFieldElement(rv)): + if not (isinstance(lv, ComplexIntervalFieldElement) or isinstance(rv, ComplexIntervalFieldElement)): self._complex = False return op(lv, rv) diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 1faece8f298..819a85dbc35 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -393,6 +393,10 @@ def is_Rational(x): sage: from sage.rings.rational import is_Rational sage: is_Rational(2) + doctest:warning... + DeprecationWarning: The function is_Rational is deprecated; + use 'isinstance(..., Rational)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. False sage: is_Rational(2/1) True @@ -401,6 +405,10 @@ def is_Rational(x): sage: is_Rational('5') False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_Rational is deprecated; " + "use 'isinstance(..., Rational)' instead.") return isinstance(x, Rational) diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 5234ea105e2..62d85cf3380 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -1701,10 +1701,18 @@ def is_RationalField(x) -> bool: sage: from sage.rings.rational_field import is_RationalField as is_RF sage: is_RF(QQ) + doctest:warning... + DeprecationWarning: The function is_RationalField is deprecated; + use 'isinstance(..., RationalField)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_RF(ZZ) False """ + from sage.misc.superseded import deprecation + deprecation(38128, + "The function is_RationalField is deprecated; " + "use 'isinstance(..., RationalField)' instead.") return isinstance(x, RationalField) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 73232348a01..4b34af0e8bf 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -675,12 +675,16 @@ class RealBallField(UniqueRepresentation, sage.rings.abc.RealBallField): [-4.733045976388941e+363922934236666733021124 +/- ...e+363922934236666733021108], [+/- inf], [+/- inf], [+/- inf], nan] """ - import sage.symbolic.constants inf = self(sage.rings.infinity.Infinity) - return [self(0), self(1), self(1)/3, - -self(2)**(Integer(2)**80), - inf, -inf, self.zero().add_error(inf), - self.element_class(self, sage.symbolic.constants.NotANumber())] + elements = [self(0), self(1), self(1)/3, -self(2)**(Integer(2)**80), + inf, -inf, self.zero().add_error(inf)] + try: + from sage.symbolic.constants import NotANumber + except ImportError: + pass + else: + elements.append(self.element_class(self, NotANumber())) + return elements def _sum_of_products(self, terms): r""" @@ -1421,8 +1425,7 @@ cdef class RealBall(RingElement): raise ValueError("unsupported string format") else: # the initializers that trigger imports - import sage.symbolic.constants - import sage.symbolic.expression + import sage.rings.infinity if isinstance(mid, sage.rings.infinity.AnInfinity): if isinstance(mid, sage.rings.infinity.PlusInfinity): arb_pos_inf(self.value) @@ -1430,33 +1433,39 @@ cdef class RealBall(RingElement): arb_neg_inf(self.value) else: arb_zero_pm_inf(self.value) - elif isinstance(mid, sage.symbolic.constants.Constant): - if _do_sig(prec(self)): sig_on() + else: try: - if isinstance(mid, sage.symbolic.constants.NotANumber): - arb_indeterminate(self.value) - elif isinstance(mid, sage.symbolic.constants.Pi): - arb_const_pi(self.value, prec(self)) - elif isinstance(mid, sage.symbolic.constants.Log2): - arb_const_log2(self.value, prec(self)) - elif isinstance(mid, sage.symbolic.constants.Catalan): - arb_const_catalan(self.value, prec(self)) - elif isinstance(mid, sage.symbolic.constants.Khinchin): - arb_const_khinchin(self.value, prec(self)) - elif isinstance(mid, sage.symbolic.constants.Glaisher): - arb_const_glaisher(self.value, prec(self)) - elif isinstance(mid, sage.symbolic.constants.EulerGamma): - arb_const_euler(self.value, prec(self)) - else: - raise TypeError("unsupported constant") - finally: + import sage.symbolic.constants + import sage.symbolic.expression + except ImportError: + raise TypeError("unsupported midpoint type") + if isinstance(mid, sage.symbolic.constants.Constant): + if _do_sig(prec(self)): sig_on() + try: + if isinstance(mid, sage.symbolic.constants.NotANumber): + arb_indeterminate(self.value) + elif isinstance(mid, sage.symbolic.constants.Pi): + arb_const_pi(self.value, prec(self)) + elif isinstance(mid, sage.symbolic.constants.Log2): + arb_const_log2(self.value, prec(self)) + elif isinstance(mid, sage.symbolic.constants.Catalan): + arb_const_catalan(self.value, prec(self)) + elif isinstance(mid, sage.symbolic.constants.Khinchin): + arb_const_khinchin(self.value, prec(self)) + elif isinstance(mid, sage.symbolic.constants.Glaisher): + arb_const_glaisher(self.value, prec(self)) + elif isinstance(mid, sage.symbolic.constants.EulerGamma): + arb_const_euler(self.value, prec(self)) + else: + raise TypeError("unsupported constant") + finally: + if _do_sig(prec(self)): sig_off() + elif isinstance(mid, sage.symbolic.expression.E): + if _do_sig(prec(self)): sig_on() + arb_const_e(self.value, prec(self)) if _do_sig(prec(self)): sig_off() - elif isinstance(mid, sage.symbolic.expression.E): - if _do_sig(prec(self)): sig_on() - arb_const_e(self.value, prec(self)) - if _do_sig(prec(self)): sig_off() - else: - raise TypeError("unsupported midpoint type") + else: + raise TypeError("unsupported midpoint type") if rad is not None: mag_init(tmpm) diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index de1f843ce87..d0ef9a4bb62 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -2055,10 +2055,18 @@ def is_RealDoubleElement(x): sage: from sage.rings.real_double import is_RealDoubleElement sage: is_RealDoubleElement(RDF(3)) + doctest:warning... + DeprecationWarning: The function is_RealDoubleElement is deprecated; + use 'isinstance(..., RealDoubleElement)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_RealDoubleElement(RIF(3)) # needs sage.rings.real_interval_field False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_RealDoubleElement is deprecated; " + "use 'isinstance(..., RealDoubleElement)' instead.") return isinstance(x, RealDoubleElement) diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 7007f1da8d7..95b472e912c 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -5332,10 +5332,18 @@ def is_RealIntervalField(x): EXAMPLES:: sage: sage.rings.real_mpfi.is_RealIntervalField(RIF) + doctest:warning... + DeprecationWarning: The function is_RealIntervalField is deprecated; + use 'isinstance(..., RealIntervalField_class)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: sage.rings.real_mpfi.is_RealIntervalField(RealIntervalField(200)) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_RealIntervalField is deprecated; " + "use 'isinstance(..., RealIntervalField_class)' instead.") return isinstance(x, RealIntervalField_class) @@ -5346,10 +5354,18 @@ def is_RealIntervalFieldElement(x): EXAMPLES:: sage: sage.rings.real_mpfi.is_RealIntervalFieldElement(RIF(2.2)) + doctest:warning... + DeprecationWarning: The function is_RealIntervalFieldElement is deprecated; + use 'isinstance(..., RealIntervalFieldElement)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: sage.rings.real_mpfi.is_RealIntervalFieldElement(RealIntervalField(200)(2.2)) True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_RealIntervalFieldElement is deprecated; " + "use 'isinstance(..., RealIntervalFieldElement)' instead.") return isinstance(x, RealIntervalFieldElement) diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 885003ed7f8..9e905c9c721 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -5886,6 +5886,10 @@ def is_RealNumber(x): sage: from sage.rings.real_mpfr import is_RealNumber sage: is_RealNumber(2.5) + doctest:warning... + DeprecationWarning: The function is_RealNumber is deprecated; + use 'isinstance(..., RealNumber)' instead. + See https://github.com/sagemath/sage/issues/38128 for details. True sage: is_RealNumber(float(2.3)) False @@ -5894,6 +5898,10 @@ def is_RealNumber(x): sage: is_RealNumber(pi) # needs sage.symbolic False """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38128, + "The function is_RealNumber is deprecated; " + "use 'isinstance(..., RealNumber)' instead.") return isinstance(x, RealNumber) diff --git a/src/sage/rings/valuation/value_group.py b/src/sage/rings/valuation/value_group.py index 2555a4319d9..b35d07e70a3 100644 --- a/src/sage/rings/valuation/value_group.py +++ b/src/sage/rings/valuation/value_group.py @@ -591,7 +591,7 @@ def _repr_(self): """ if self.is_trivial(): return "Trivial Additive Abelian Semigroup" - return "Additive Abelian Semigroup generated by %s" % (', '.join([repr(g) for g in self._generators]),) + return "Additive Abelian Semigroup generated by %s" % (', '.join(repr(g) for g in self._generators),) def __add__(self, other): r""" diff --git a/src/sage/schemes/affine/affine_homset.py b/src/sage/schemes/affine/affine_homset.py index 1a5dd8477ab..f90bcfffec1 100644 --- a/src/sage/schemes/affine/affine_homset.py +++ b/src/sage/schemes/affine/affine_homset.py @@ -38,7 +38,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.real_mpfr import RR from sage.rings.cc import CC -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.categories.fields import Fields from sage.categories.number_fields import NumberFields from sage.rings.finite_rings.finite_field_base import FiniteField @@ -349,7 +349,7 @@ def points(self, **kwds): B = kwds.pop('bound', 0) tol = kwds.pop('tolerance', 1e-2) prec = kwds.pop('precision', 53) - if is_RationalField(R) or R == ZZ: + if isinstance(R, RationalField) or R == ZZ: if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) from sage.schemes.affine.affine_rational_point import enum_affine_rational_field diff --git a/src/sage/schemes/affine/affine_space.py b/src/sage/schemes/affine/affine_space.py index 572d39bad51..889d9005ed6 100644 --- a/src/sage/schemes/affine/affine_space.py +++ b/src/sage/schemes/affine/affine_space.py @@ -14,7 +14,7 @@ from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.finite_rings.finite_field_base import FiniteField @@ -1063,7 +1063,7 @@ def points_of_bounded_height(self, **kwds): sage: len(list(A.points_of_bounded_height(bound=2, tolerance=0.1))) # needs sage.rings.number_field 529 """ - if is_RationalField(self.base_ring()): + if isinstance(self.base_ring(), RationalField): ftype = False # stores whether field is a number field or the rational field elif self.base_ring() in NumberFields(): # true for rational field as well, so check is_RationalField first ftype = True diff --git a/src/sage/schemes/berkovich/berkovich_cp_element.py b/src/sage/schemes/berkovich/berkovich_cp_element.py index bd641bd05a2..a9299e4e732 100644 --- a/src/sage/schemes/berkovich/berkovich_cp_element.py +++ b/src/sage/schemes/berkovich/berkovich_cp_element.py @@ -36,7 +36,7 @@ from sage.structure.element import Element from sage.structure.element import Expression import sage.rings.abc -from sage.rings.real_mpfr import RR, is_RealNumber +from sage.rings.real_mpfr import RR, RealNumber from sage.rings.padics.padic_generic_element import pAdicGenericElement from sage.rings.padics.padic_base_generic import pAdicBaseGeneric from sage.schemes.projective.projective_space import ProjectiveSpace @@ -215,7 +215,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= # since we are over a field, we can normalize coordinates. all code assumes normalized coordinates center.normalize_coordinates() # make sure the radius coerces into the reals - if not is_RealNumber(radius): + if not isinstance(radius, RealNumber): if isinstance(radius, Expression): radius = RR(radius) elif RR.has_coerce_map_from(radius.parent()): @@ -258,7 +258,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= except (TypeError, ValueError): raise ValueError('could not convert %s to %s' % (center, self._base_space)) # make sure the radius coerces into the reals - if not is_RealNumber(radius): + if not isinstance(radius, RealNumber): if isinstance(radius, Expression): radius = RR(radius) elif RR.has_coerce_map_from(radius.parent()): @@ -388,7 +388,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= raise ValueError('radius univariate function but center is constant. ' + 'this does not define a type IV point') raise TypeError("symbolic radius must be a real number") - if (not is_RealNumber(radius)) and power is None: + if (not isinstance(radius, RealNumber)) and power is None: if RR.has_coerce_map_from(radius.parent()): self._radius = RR(radius) else: diff --git a/src/sage/schemes/curves/affine_curve.py b/src/sage/schemes/curves/affine_curve.py index f8e5dc4bfbe..dbdb2dfa4cd 100644 --- a/src/sage/schemes/curves/affine_curve.py +++ b/src/sage/schemes/curves/affine_curve.py @@ -145,7 +145,7 @@ from sage.rings.polynomial.multi_polynomial_element import degree_lowest_rational_function from sage.rings.number_field.number_field import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.infinity import infinity from sage.schemes.affine.affine_space import AffineSpace, AffineSpace_generic @@ -1548,10 +1548,10 @@ def extension(self): pts = self.change_ring(F.embeddings(QQbar)[0]).rational_points() L = [t for pt in pts for t in pt] K = number_field_elements_from_algebraics(L)[0] - if is_RationalField(K): + if isinstance(K, RationalField): return F.embeddings(F)[0] else: - if is_RationalField(F): + if isinstance(F, RationalField): return F.embeddings(K)[0] else: # make sure the defining polynomial variable names are the same for K, N diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index cec2e08e96b..6045cc3ea70 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -154,7 +154,7 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.qqbar import (number_field_elements_from_algebraics, QQbar) -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.integer import Integer from sage.schemes.projective.projective_space import ProjectiveSpace, ProjectiveSpace_ring @@ -1458,10 +1458,10 @@ def extension(self): pts = self.change_ring(F.embeddings(QQbar)[0]).rational_points() L = [t for pt in pts for t in pt] K = number_field_elements_from_algebraics(L)[0] - if is_RationalField(K): + if isinstance(K, RationalField): return F.embeddings(F)[0] else: - if is_RationalField(F): + if isinstance(F, RationalField): return F.embeddings(K)[0] else: # make sure the defining polynomial variable names are the same for K, N @@ -1862,7 +1862,7 @@ def rational_parameterization(self): """ if self.genus(): raise TypeError("this curve must have geometric genus zero") - if not is_RationalField(self.base_ring()): + if not isinstance(self.base_ring(), RationalField): raise TypeError("this curve must be defined over the rational field") singular.lib("paraplanecurves.lib") R = singular.paraPlaneCurve(self.defining_polynomial()) diff --git a/src/sage/schemes/generic/algebraic_scheme.py b/src/sage/schemes/generic/algebraic_scheme.py index f442ff309b3..8cc0e544917 100644 --- a/src/sage/schemes/generic/algebraic_scheme.py +++ b/src/sage/schemes/generic/algebraic_scheme.py @@ -118,7 +118,7 @@ from sage.rings.ideal import is_Ideal from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.finite_rings.finite_field_base import FiniteField from sage.misc.latex import latex @@ -873,7 +873,7 @@ def rational_points(self, **kwds): F = self.base_ring() if bound == 0: - if is_RationalField(F): + if isinstance(F, RationalField): raise TypeError("A positive bound (= %s) must be specified." % bound) if not isinstance(F, FiniteField): raise TypeError("Argument F (= %s) must be a finite field." % F) diff --git a/src/sage/schemes/generic/morphism.py b/src/sage/schemes/generic/morphism.py index 9986dea97ff..8034d0b9b5a 100644 --- a/src/sage/schemes/generic/morphism.py +++ b/src/sage/schemes/generic/morphism.py @@ -82,7 +82,7 @@ from sage.structure.sequence import Sequence from sage.categories.homset import Homset, Hom, End from sage.rings.fraction_field_element import FractionFieldElement -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.categories.map import FormalCompositeMap, Map from sage.misc.constant_function import ConstantFunction from sage.misc.lazy_attribute import lazy_attribute @@ -1643,7 +1643,7 @@ def specialization(self, D=None, phi=None, homset=None): if phi is None: raise ValueError("either the dictionary or the specialization must be provided") else: - if is_FractionField(self[0].parent()): + if isinstance(self[0].parent(), FractionField_generic): from sage.rings.polynomial.flatten import FractionSpecializationMorphism phi = FractionSpecializationMorphism(self[0].parent(), D) else: diff --git a/src/sage/schemes/hyperelliptic_curves/constructor.py b/src/sage/schemes/hyperelliptic_curves/constructor.py index 16526fec853..46d01cfd2cb 100644 --- a/src/sage/schemes/hyperelliptic_curves/constructor.py +++ b/src/sage/schemes/hyperelliptic_curves/constructor.py @@ -26,7 +26,7 @@ from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.polynomial.polynomial_element import Polynomial -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.structure.dynamic_class import dynamic_class @@ -269,20 +269,14 @@ def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True): # For certain base fields, we specialise to subclasses # with special case methods - def is_FiniteField(x): - return isinstance(x, FiniteField) - - def is_pAdicField(x): - return isinstance(x, sage.rings.abc.pAdicField) - fields = [ - ("FiniteField", is_FiniteField, HyperellipticCurve_finite_field), - ("RationalField", is_RationalField, HyperellipticCurve_rational_field), - ("pAdicField", is_pAdicField, HyperellipticCurve_padic_field), + ("FiniteField", FiniteField, HyperellipticCurve_finite_field), + ("RationalField", RationalField, HyperellipticCurve_rational_field), + ("pAdicField", sage.rings.abc.pAdicField, HyperellipticCurve_padic_field), ] - for name, test, cls in fields: - if test(R): + for name, base_ring_cls, cls in fields: + if isinstance(R, base_ring_cls): bases.append(cls) cls_name.append(name) break diff --git a/src/sage/schemes/hyperelliptic_curves/jacobian_homset.py b/src/sage/schemes/hyperelliptic_curves/jacobian_homset.py index 88b28a4b753..2a192248180 100644 --- a/src/sage/schemes/hyperelliptic_curves/jacobian_homset.py +++ b/src/sage/schemes/hyperelliptic_curves/jacobian_homset.py @@ -44,7 +44,7 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer_ring import ZZ -from sage.rings.integer import is_Integer, Integer +from sage.rings.integer import Integer from sage.rings.polynomial.polynomial_element import Polynomial from sage.schemes.generic.homset import SchemeHomset_points @@ -124,16 +124,16 @@ def __call__(self, P): elif len(P) == 2: P1 = P[0] P2 = P[1] - if is_Integer(P1) and is_Integer(P2): + if isinstance(P1, Integer) and isinstance(P2, Integer): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) P2 = R(P2) return JacobianMorphism_divisor_class_field(self, (P1, P2)) - if is_Integer(P1) and isinstance(P2, Polynomial): + if isinstance(P1, Integer) and isinstance(P2, Polynomial): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) return JacobianMorphism_divisor_class_field(self, (P1, P2)) - if is_Integer(P2) and isinstance(P1, Polynomial): + if isinstance(P2, Integer) and isinstance(P1, Polynomial): R = PolynomialRing(self.value_ring(), 'x') P2 = R(P2) return JacobianMorphism_divisor_class_field(self, (P1, P2)) diff --git a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py index 204030c1142..d9a9996d44e 100644 --- a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +++ b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py @@ -56,7 +56,7 @@ from sage.misc.repr import repr_lincomb from sage.modules.free_module_element import vector from sage.modules.free_module import FreeModule -from sage.modules.free_module_element import is_FreeModuleElement +from sage.modules.free_module_element import FreeModuleElement from sage.modules.module import Module from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers from sage.rings.integer import Integer @@ -1894,7 +1894,7 @@ def __init__(self, parent, val=0, offset=0, check=True): return if isinstance(val, tuple): val, offset = val - if isinstance(val, list) and val and is_FreeModuleElement(val[0]): + if isinstance(val, list) and val and isinstance(val[0], FreeModuleElement): val = transpose_list(val) self._f = parent._poly_ring(val) if offset != 0: diff --git a/src/sage/schemes/plane_conics/con_number_field.py b/src/sage/schemes/plane_conics/con_number_field.py index f044b884932..393b77bc1ff 100644 --- a/src/sage/schemes/plane_conics/con_number_field.py +++ b/src/sage/schemes/plane_conics/con_number_field.py @@ -21,7 +21,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from .con_field import ProjectiveConic_field @@ -305,7 +305,7 @@ def has_rational_point(self, point=False, obstruction=False, if point or obstruction: return True, pt return True - if is_RationalField(B): + if isinstance(B, RationalField): K = B [KtoB, BtoK] = [K.hom(K) for i in range(2)] else: diff --git a/src/sage/schemes/plane_conics/con_rational_function_field.py b/src/sage/schemes/plane_conics/con_rational_function_field.py index fec1a50fdbb..bc842415d8e 100644 --- a/src/sage/schemes/plane_conics/con_rational_function_field.py +++ b/src/sage/schemes/plane_conics/con_rational_function_field.py @@ -44,7 +44,7 @@ from sage.arith.functions import lcm from sage.arith.misc import GCD as gcd from sage.modules.free_module_element import vector -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic class ProjectiveConic_rational_function_field(ProjectiveConic_field): @@ -392,7 +392,7 @@ def _reduce_conic(self): # remove squares for i, x in enumerate(coeff): - if is_FractionField(x.parent()): + if isinstance(x.parent(), FractionField_generic): # go to base ring of fraction field x = self.base().base()(x) diff --git a/src/sage/schemes/plane_conics/constructor.py b/src/sage/schemes/plane_conics/constructor.py index 10e158514dc..308b56f6db0 100644 --- a/src/sage/schemes/plane_conics/constructor.py +++ b/src/sage/schemes/plane_conics/constructor.py @@ -26,9 +26,9 @@ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector from sage.categories.integral_domains import IntegralDomains -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.rings.finite_rings.finite_field_base import FiniteField -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.rings.number_field.number_field_base import NumberField from sage.rings.polynomial.multi_polynomial import MPolynomial @@ -238,11 +238,11 @@ def Conic(base_field, F=None, names=None, unique=True): P2 = ProjectiveSpace(2, base_field, names) if isinstance(base_field, FiniteField): return ProjectiveConic_finite_field(P2, F) - if is_RationalField(base_field): + if isinstance(base_field, RationalField): return ProjectiveConic_rational_field(P2, F) if isinstance(base_field, NumberField): return ProjectiveConic_number_field(P2, F) - if is_FractionField(base_field) and (is_PolynomialRing(base_field.ring()) or is_MPolynomialRing(base_field.ring())): + if isinstance(base_field, FractionField_generic) and (is_PolynomialRing(base_field.ring()) or is_MPolynomialRing(base_field.ring())): return ProjectiveConic_rational_function_field(P2, F) return ProjectiveConic_field(P2, F) diff --git a/src/sage/schemes/product_projective/homset.py b/src/sage/schemes/product_projective/homset.py index 590030762e1..ef135a2cd6b 100644 --- a/src/sage/schemes/product_projective/homset.py +++ b/src/sage/schemes/product_projective/homset.py @@ -23,7 +23,7 @@ from sage.misc.mrange import xmrange from sage.misc.misc_c import prod from sage.rings.finite_rings.finite_field_base import FiniteField -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme from sage.schemes.generic.homset import SchemeHomset_points @@ -199,7 +199,7 @@ def points(self, **kwds): return list(points) R = self.value_ring() points = [] - if is_RationalField(R): + if isinstance(R, RationalField): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) alg = kwds.pop('algorithm', None) diff --git a/src/sage/schemes/projective/projective_homset.py b/src/sage/schemes/projective/projective_homset.py index a64ceabca4e..bc1a781c00b 100644 --- a/src/sage/schemes/projective/projective_homset.py +++ b/src/sage/schemes/projective/projective_homset.py @@ -44,7 +44,7 @@ from sage.misc.verbose import verbose -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.categories.fields import Fields from sage.categories.number_fields import NumberFields from sage.rings.finite_rings.finite_field_base import FiniteField @@ -274,7 +274,7 @@ def points(self, **kwds): B = kwds.pop('bound', 0) tol = kwds.pop('tolerance', 1e-2) prec = kwds.pop('precision', 53) - if is_RationalField(R): + if isinstance(R, RationalField): if not B > 0: raise TypeError("a positive bound B (= %s) must be specified" % B) if isinstance(X, AlgebraicScheme_subscheme): # sieve should only be called for subschemes diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index ded40bb85b5..c05588f4698 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -88,7 +88,7 @@ from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.rational_field import QQ, is_RationalField +from sage.rings.rational_field import QQ, RationalField from sage.rings.fraction_field import FractionField from sage.rings.number_field.order import Order @@ -264,7 +264,7 @@ def ProjectiveSpace(n, R=None, names=None): if R in _Fields: if isinstance(R, FiniteField): return ProjectiveSpace_finite_field(n, R, names) - if is_RationalField(R): + if isinstance(R, RationalField): return ProjectiveSpace_rational_field(n, R, names) else: return ProjectiveSpace_field(n, R, names) @@ -1170,10 +1170,10 @@ def points_of_bounded_height(self, **kwds): # or the ring of integers is_ring_of_ints = False - if is_RationalField(R): + if isinstance(R, RationalField): field_type = False elif R in NumberFields(): - # True for the rational field as well, so check is_RationalField first + # True for the rational field as well, so check RationalField first field_type = True elif (R is ZZ) or (isinstance(R, Order) and R.is_integrally_closed()): # Ensure ring of integers / maximal order is_ring_of_ints = True diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index f3e93cd65a5..6135a62b1cb 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -30,7 +30,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.rational_field import is_RationalField +from sage.rings.rational_field import RationalField from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme from sage.schemes.projective.projective_morphism import SchemeMorphism_polynomial_projective_subscheme_field @@ -975,7 +975,7 @@ def dual(self): from sage.libs.singular.function_factory import ff K = self.base_ring() - if not (is_RationalField(K) or K in Fields().Finite()): + if not (isinstance(K, RationalField) or K in Fields().Finite()): raise NotImplementedError("base ring must be QQ or a finite field") I = self.defining_ideal() m = I.ngens() diff --git a/src/sage/schemes/toric/fano_variety.py b/src/sage/schemes/toric/fano_variety.py index d7772aa2ca4..c17cf7c37d7 100644 --- a/src/sage/schemes/toric/fano_variety.py +++ b/src/sage/schemes/toric/fano_variety.py @@ -130,7 +130,7 @@ from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.polynomial.polynomial_ring import is_PolynomialRing -from sage.rings.fraction_field import is_FractionField +from sage.rings.fraction_field import FractionField_generic from sage.schemes.toric.toric_subscheme import AlgebraicScheme_subscheme_toric from sage.schemes.toric.variety import ( @@ -1590,7 +1590,7 @@ def add_variables(field, variables): """ if not variables: return field - if is_FractionField(field): + if isinstance(field, FractionField_generic): # Q(a) ---> Q(a, b) rather than Q(a)(b) R = field.ring() if is_PolynomialRing(R) or is_MPolynomialRing(R): diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index 94a590691be..c1ca8351263 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -226,7 +226,7 @@ sage: P4_11133 = toric_varieties.P4_11133() sage: P4_11133.is_smooth(), P4_11133.is_orbifold() (False, True) - sage: cone = P4_11133.fan(3)[8] + sage: cone = P4_11133.fan(3)[9] sage: cone.is_smooth(), cone.is_simplicial() (False, True) sage: HH = P4_11133.cohomology_ring(); HH diff --git a/src/sage/sets/family.pyx b/src/sage/sets/family.pyx index c396ced076d..0810b07f17a 100644 --- a/src/sage/sets/family.pyx +++ b/src/sage/sets/family.pyx @@ -49,7 +49,6 @@ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.misc.cachefunc import cached_method from sage.misc.call import AttrCallObject -from sage.misc.lazy_import import LazyImport from sage.rings.infinity import Infinity from sage.rings.integer import Integer from sage.sets.finite_enumerated_set import FiniteEnumeratedSet diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 00c604a07d8..2a5c8c86f23 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -491,8 +491,8 @@ def __init__(self, X, category=None): '' and 'Integer Ring' """ - from sage.rings.integer import is_Integer - if isinstance(X, int) or is_Integer(X): + from sage.rings.integer import Integer + if isinstance(X, int) or isinstance(X, Integer): # The coercion model will try to call Set_object(0) raise ValueError('underlying object cannot be an integer') diff --git a/src/sage/stats/distributions/discrete_gaussian_lattice.py b/src/sage/stats/distributions/discrete_gaussian_lattice.py index 324dcc083b4..428ca30855b 100644 --- a/src/sage/stats/distributions/discrete_gaussian_lattice.py +++ b/src/sage/stats/distributions/discrete_gaussian_lattice.py @@ -195,7 +195,6 @@ def _normalisation_factor_zz(self, tau=None, prec=None): \exp(-|x|_2^2 / (2\sigma^2))`, i.e. the normalization factor such that the sum over all probabilities is 1 for `B`, via Poisson summation. - INPUT: - ``tau`` -- (default: ``None``) all vectors `v` with `|v|_2^2 \leq @@ -235,7 +234,7 @@ def _normalisation_factor_zz(self, tau=None, prec=None): sage: while v not in counter: ....: add_samples(1000) - sage: while abs(m*f(v)*1.0/nf/counter[v] - 1.0) >= 0.2: # long time + sage: while abs(m*f(v)*1.0/nf/counter[v] - 1.0) >= 0.2: # long time ....: add_samples(1000) sage: DGL = distributions.DiscreteGaussianDistributionLatticeSampler @@ -250,9 +249,14 @@ def _normalisation_factor_zz(self, tau=None, prec=None): sage: M = Matrix(ZZ, [[1, 3, 0], [-2, 5, 1], [3, -4, 2]]) sage: D = DGL(M, 1.7) - sage: D._normalisation_factor_zz() # long time + sage: D._normalisation_factor_zz() # long time 7247.1975... + sage: Sigma = Matrix(ZZ, [[5, -2, 4], [-2, 10, -5], [4, -5, 5]]) + sage: D = DGL(ZZ^3, Sigma, [7, 2, 5]) + sage: D._normalisation_factor_zz() + 78.6804... + sage: M = Matrix(ZZ, [[1, 3, 0], [-2, 5, 1]]) sage: D = DGL(M, 3) sage: D._normalisation_factor_zz() @@ -300,7 +304,10 @@ def f_or_hat(x): from sage.functions.log import log basis = self.B.LLL() base = vector(ZZ, [v.round() for v in basis.solve_left(self._c)]) - BOUND = max(1, (self._RR(log(10**4, self.n)).ceil() - 1) // 2) + # BOUND is the largest integer such that |coords| <= 10^4 + # However, this might still drift from true value for larger lattices + # So optimally one should fix the TODO above + BOUND = max(1, (self._RR(10**(4 / self.n)).ceil() - 1) // 2) if BOUND > 10: BOUND = 10 coords = itertools.product(range(-BOUND, BOUND + 1), repeat=self.n) @@ -431,6 +438,11 @@ def __init__(self, B, sigma=1, c=0, r=None, precision=None, sigma_basis=False): - ``sigma_basis`` -- (default: ``False``) When set, ``sigma`` is treated as a (row) basis, i.e. the covariance matrix is computed by `\Sigma = SS^T` + .. TODO:: + + Rename class methods like ``.f`` and hide most of them + (at least behind something like ``.data``). + EXAMPLES:: sage: n = 2; sigma = 3.0 @@ -440,8 +452,7 @@ def __init__(self, B, sigma=1, c=0, r=None, precision=None, sigma_basis=False): 56.5486677646... sage: from collections import defaultdict - sage: counter = defaultdict(Integer) - sage: m = 0 + sage: counter = defaultdict(Integer); m = 0 sage: def add_samples(i): ....: global counter, m ....: for _ in range(i): @@ -454,7 +465,7 @@ def __init__(self, B, sigma=1, c=0, r=None, precision=None, sigma_basis=False): sage: while abs(m*f(v)*1.0/nf/counter[v] - 1.0) >= 0.1: # needs sage.symbolic ....: add_samples(1000) - sage: counter = defaultdict(Integer) + sage: counter = defaultdict(Integer); m = 0 sage: v = vector(ZZ, n, (0, 0)) sage: v.set_immutable() sage: while v not in counter: @@ -478,10 +489,24 @@ def __init__(self, B, sigma=1, c=0, r=None, precision=None, sigma_basis=False): sage: Sigma = Matrix(ZZ, [[5, -2, 4], [-2, 10, -5], [4, -5, 5]]) sage: c = vector(ZZ, [7, 2, 5]) sage: D = distributions.DiscreteGaussianDistributionLatticeSampler(ZZ^n, Sigma, c) + sage: f = D.f sage: nf = D._normalisation_factor_zz(); nf # This has not been properly implemented - 63.76927... - sage: while v not in counter: add_samples(1000) - sage: while abs(m*f(v)*1.0/nf/counter[v] - 1.0) >= 0.1: add_samples(1000) + 78.6804... + + We can compute the expected number of samples before sampling a vector:: + + sage: v = vector(ZZ, n, (11, 4, 8)) + sage: v.set_immutable() + sage: 1 / (f(v) / nf) + 2553.9461... + + sage: counter = defaultdict(Integer); m = 0 + sage: while v not in counter: + ....: add_samples(1000) + sage: sum(counter.values()) # random + 3000 + sage: while abs(m*f(v)*1.0/nf/counter[v] - 1.0) >= 0.1: # needs sage.symbolic + ....: add_samples(1000) If the covariance provided is not positive definite, an error is thrown:: diff --git a/src/sage/stats/hmm/chmm.pyx b/src/sage/stats/hmm/chmm.pyx index dc8bd1144b3..c7c2ab25b4e 100644 --- a/src/sage/stats/hmm/chmm.pyx +++ b/src/sage/stats/hmm/chmm.pyx @@ -336,7 +336,6 @@ cdef class GaussianHiddenMarkovModel(HiddenMarkovModel): s += '\nInitial probabilities: %s'%self.initial_probabilities() return s - def generate_sequence(self, Py_ssize_t length, starting_state=None): r""" Return a sample of the given length from this HMM. @@ -1165,7 +1164,6 @@ cdef class GaussianMixtureHiddenMarkovModel(GaussianHiddenMarkovModel): return unpickle_gaussian_mixture_hmm_v1, \ (self.A, self.B, self.pi, self.mixture) - def __richcmp__(self, other, op): r""" Compare self and other, which must both be GaussianMixtureHiddenMarkovModel's. @@ -1584,6 +1582,7 @@ def unpickle_gaussian_hmm_v1(A, B, pi, prob, n_out): m.n_out = n_out return m + def unpickle_gaussian_mixture_hmm_v1(A, B, pi, mixture): r""" EXAMPLES:: diff --git a/src/sage/stats/hmm/distributions.pyx b/src/sage/stats/hmm/distributions.pyx index 102630af944..1b04dff21cb 100644 --- a/src/sage/stats/hmm/distributions.pyx +++ b/src/sage/stats/hmm/distributions.pyx @@ -370,7 +370,6 @@ cdef class GaussianMixtureDistribution(Distribution): else: self.fixed[i] = 0 - def __repr__(self): r""" Return string representation of this mixed Gaussian distribution. @@ -524,6 +523,7 @@ cdef class GaussianMixtureDistribution(Distribution): mu = self.param._values[3*m+1] return self.c0._values[m]*exp((x-mu)*(x-mu)*self.c1._values[m]) + def unpickle_gaussian_mixture_distribution_v1(TimeSeries c0, TimeSeries c1, TimeSeries param, IntList fixed): r""" diff --git a/src/sage/stats/hmm/hmm.pyx b/src/sage/stats/hmm/hmm.pyx index fd3a6929cef..39fb342710d 100644 --- a/src/sage/stats/hmm/hmm.pyx +++ b/src/sage/stats/hmm/hmm.pyx @@ -219,7 +219,6 @@ cdef class HiddenMarkovModel: cdef Py_ssize_t i return [self.generate_sequence(length, starting_state=starting_state)[0] for i in range(number)] - ######################################################### # Some internal functions used for various general # HMM algorithms. @@ -435,7 +434,6 @@ cdef class DiscreteHiddenMarkovModel(HiddenMarkovModel): from sage.rings.real_double import RDF return matrix(RDF, self.N, self.n_out, self.B.list()) - def __repr__(self): r""" Return string representation of this discrete hidden Markov model. @@ -976,7 +974,6 @@ cdef class DiscreteHiddenMarkovModel(HiddenMarkovModel): return state_sequence, log(mx) - cpdef _viterbi_scale(self, IntList obs): r""" Used internally to compute the viterbi path with rescaling. @@ -1361,7 +1358,8 @@ def unpickle_discrete_hmm_v0(A, B, pi, emission_symbols, name): sage: sage.stats.hmm.hmm.unpickle_discrete_hmm_v0(m.transition_matrix(), m.emission_matrix(), m.initial_probabilities(), ['a','b'], 'test model') Discrete Hidden Markov Model with 2 States and 2 Emissions... """ - return DiscreteHiddenMarkovModel(A,B,pi,emission_symbols,normalize=False) + return DiscreteHiddenMarkovModel(A, B, pi, emission_symbols, normalize=False) + def unpickle_discrete_hmm_v1(A, B, pi, n_out, emission_symbols, emission_symbols_dict): r""" diff --git a/src/sage/stats/hmm/util.pyx b/src/sage/stats/hmm/util.pyx index 96cd881c48e..a2d34d55e1d 100644 --- a/src/sage/stats/hmm/util.pyx +++ b/src/sage/stats/hmm/util.pyx @@ -84,7 +84,6 @@ cdef class HMM_Util: for k in range(i, j): T._values[k] /= s - cpdef TimeSeries initial_probs_to_TimeSeries(self, pi, bint normalize): """ This function is used internally by the __init__ methods of @@ -123,7 +122,6 @@ cdef class HMM_Util: self.normalize_probability_TimeSeries(T, 0, T._length) return T - cpdef TimeSeries state_matrix_to_TimeSeries(self, A, int N, bint normalize): """ This function is used internally by the ``__init__`` methods of diff --git a/src/sage/stats/time_series.pyx b/src/sage/stats/time_series.pyx index d6823f85add..2e22ec45c69 100644 --- a/src/sage/stats/time_series.pyx +++ b/src/sage/stats/time_series.pyx @@ -567,7 +567,6 @@ cdef class TimeSeries: memcpy(v._values + i*T._length, T._values, sizeof(double)*T._length) return v - def autoregressive_fit(self,M): r""" This method fits the time series to an autoregressive process @@ -1269,7 +1268,6 @@ cdef class TimeSeries: s *= self._values[i] return s - def mean(self): r""" Return the mean (average) of the elements of ``self``. diff --git a/src/sage/structure/factory.pyx b/src/sage/structure/factory.pyx index ff3d6bdf596..ab8b5afa4a1 100644 --- a/src/sage/structure/factory.pyx +++ b/src/sage/structure/factory.pyx @@ -520,7 +520,7 @@ cdef class UniqueFactory(SageObject): The ``GF`` factory used to have a custom :meth:`other_keys` method, but this was removed in :issue:`16934`:: - sage: # needs sage.libs.linbox sage.ring.finite_rings + sage: # needs sage.libs.linbox sage.rings.finite_rings sage: key, _ = GF.create_key_and_extra_args(27, 'k'); key (27, ('k',), x^3 + 2*x + 1, 'givaro', 3, 3, True, None, 'poly', True, True, True) sage: K = GF.create_object(0, key); K diff --git a/src/sage/structure/formal_sum.py b/src/sage/structure/formal_sum.py index ee333decd4b..f037f71042e 100644 --- a/src/sage/structure/formal_sum.py +++ b/src/sage/structure/formal_sum.py @@ -203,7 +203,7 @@ def _latex_(self): r""" EXAMPLES:: - sage: latex(FormalSum([(1,2), (5, 8/9), (-3, 7)])) + sage: latex(FormalSum([(1,2), (5, 8/9), (-3, 7)])) # needs sage.rings.real_mpfr 2 + 5\cdot \frac{8}{9} - 3\cdot 7 """ from sage.misc.latex import repr_lincomb @@ -441,7 +441,7 @@ def _get_action_(self, other, op, self_is_left): """ EXAMPLES:: - sage: A = FormalSums(RR); A.get_action(RR) # indirect doctest + sage: A = FormalSums(RR); A.get_action(RR) # indirect doctest # needs sage.rings.real_mpfr Right scalar multiplication by Real Field with 53 bits of precision on Abelian Group of all Formal Finite Sums over Real Field with 53 bits of precision diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 0d667075ff6..dd57aa02787 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -2143,7 +2143,7 @@ cdef class Parent(sage.structure.category_object.CategoryObject): sage: # needs sage.combinat sage.modules sage: R = QQ['q,t'].fraction_field() - sage: Sym = sage.combinat.sf.sf.SymmetricFunctions(R) + sage: Sym = SymmetricFunctions(R) sage: H = Sym.macdonald().H() sage: P = Sym.macdonald().P() sage: m = Sym.monomial() @@ -2180,7 +2180,7 @@ cdef class Parent(sage.structure.category_object.CategoryObject): sage: # needs sage.combinat sage.modules sage: R = QQ['q,t'].fraction_field() - sage: Sym = sage.combinat.sf.sf.SymmetricFunctions(R) + sage: Sym = SymmetricFunctions(R) sage: P = Sym.macdonald().P() sage: Ht = Sym.macdonald().Ht() sage: Ht._internal_coerce_map_from(P) diff --git a/src/sage/structure/unique_representation.py b/src/sage/structure/unique_representation.py index 7c0652e519f..7f769522caf 100644 --- a/src/sage/structure/unique_representation.py +++ b/src/sage/structure/unique_representation.py @@ -559,7 +559,110 @@ class that inherits from :class:`UniqueRepresentation`: By adding from sage.misc.fast_methods import WithEqualityById -class CachedRepresentation(metaclass=ClasscallMetaclass): +class WithPicklingByInitArgs(metaclass=ClasscallMetaclass): + r""" + Classes derived from :class:`WithPicklingByInitArgs` store the arguments + passed to :meth:`__init__` to implement pickling. + + This class is for objects that are semantically immutable and determined + by the class and the arguments passed to :meth:`__init__`. + The class also provides implementations of :meth:`__copy__` and + :func:`__deepcopy__`, which simply return the object. + """ + + @staticmethod + def __classcall__(cls, *args, **options): + """ + Construct a new object of this class and store the arguments passed to ``__init__``. + + TESTS:: + + sage: from sage.structure.unique_representation import WithPicklingByInitArgs + sage: class MyClass(WithPicklingByInitArgs): + ....: def __init__(self, value): + ....: self.value = value + ....: def __eq__(self, other): + ....: if type(self) != type(other): + ....: return False + ....: return self.value == other.value + sage: import __main__ + sage: __main__.MyClass = MyClass # This is only needed in doctests + sage: x = MyClass(1) + sage: x == loads(dumps(x)) + True + sage: y = MyClass(1) + sage: x is y # No Cached/UniqueRepresentation behavior + False + """ + instance = typecall(cls, *args, **options) + assert isinstance(instance, cls) + if instance.__class__.__reduce__ == WithPicklingByInitArgs.__reduce__: + instance._reduction = (cls, args, options) + return instance + + def __reduce__(self): + """ + Return the arguments that have been passed to + :meth:`__new__` to construct this object, + as per the pickle protocol. + + See also :class:`CachedRepresentation` and + :class:`UniqueRepresentation` for a discussion. + + EXAMPLES:: + + sage: x = UniqueRepresentation() + sage: x.__reduce__() # indirect doctest + (, (, (), {})) + """ + return (unreduce, self._reduction) + + def __copy__(self): + """ + Return ``self``, as a semantic copy of ``self``. + + This assumes that the object is semantically immutable. + + EXAMPLES:: + + sage: x = UniqueRepresentation() + sage: x is copy(x) # indirect doctest + True + """ + return self + + def __deepcopy__(self, memo): + """ + Return ``self``, as a semantic deep copy of ``self``. + + This assumes that the object is semantically immutable. + + EXAMPLES:: + + sage: from copy import deepcopy + sage: x = UniqueRepresentation() + sage: x is deepcopy(x) # indirect doctest + True + """ + return self + + +def unreduce(cls, args, keywords): + """ + Calls a class on the given arguments:: + + sage: sage.structure.unique_representation.unreduce(Integer, (1,), {}) + 1 + + .. TODO:: + + should reuse something preexisting ... + + """ + return cls(*args, **keywords) + + +class CachedRepresentation(WithPicklingByInitArgs): """ Classes derived from CachedRepresentation inherit a weak cache for their instances. @@ -1007,11 +1110,7 @@ def __classcall__(cls, *args, **options): sage: x is y # indirect doctest True """ - instance = typecall(cls, *args, **options) - assert isinstance(instance, cls) - if instance.__class__.__reduce__ == CachedRepresentation.__reduce__: - instance._reduction = (cls, args, options) - return instance + return super().__classcall__(cls, *args, **options) @classmethod def _clear_cache_(cls): @@ -1101,67 +1200,6 @@ def _clear_cache_(cls): for k in del_list: del cache[k] - def __reduce__(self): - """ - Return the arguments that have been passed to - :meth:`__new__` to construct this object, - as per the pickle protocol. - - See also :class:`CachedRepresentation` and - :class:`UniqueRepresentation` for a discussion. - - EXAMPLES:: - - sage: x = UniqueRepresentation() - sage: x.__reduce__() # indirect doctest - (, (, (), {})) - """ - return (unreduce, self._reduction) - - def __copy__(self): - """ - Return ``self``, as a semantic copy of ``self``. - - This assumes that the object is semantically immutable. - - EXAMPLES:: - - sage: x = UniqueRepresentation() - sage: x is copy(x) # indirect doctest - True - """ - return self - - def __deepcopy__(self, memo): - """ - Return ``self``, as a semantic deep copy of ``self``. - - This assumes that the object is semantically immutable. - - EXAMPLES:: - - sage: from copy import deepcopy - sage: x = UniqueRepresentation() - sage: x is deepcopy(x) # indirect doctest - True - """ - return self - - -def unreduce(cls, args, keywords): - """ - Calls a class on the given arguments:: - - sage: sage.structure.unique_representation.unreduce(Integer, (1,), {}) - 1 - - .. TODO:: - - should reuse something preexisting ... - - """ - return cls(*args, **keywords) - class UniqueRepresentation(CachedRepresentation, WithEqualityById): r""" diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index e7a28be127a..501b0920898 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -207,7 +207,7 @@ cdef class SymbolicRing(sage.rings.abc.SymbolicRing): return False else: - from sage.rings.fraction_field import is_FractionField + from sage.rings.fraction_field import FractionField_generic from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.polynomial.laurent_polynomial_ring_base import LaurentPolynomialRing_generic @@ -220,7 +220,7 @@ cdef class SymbolicRing(sage.rings.abc.SymbolicRing): if R._is_numerical(): # Almost anything with a coercion into any precision of CC return R not in (RLF, CLF) - elif is_PolynomialRing(R) or is_MPolynomialRing(R) or is_FractionField(R) or isinstance(R, LaurentPolynomialRing_generic): + elif is_PolynomialRing(R) or is_MPolynomialRing(R) or isinstance(R, FractionField_generic) or isinstance(R, LaurentPolynomialRing_generic): base = R.base_ring() return base is not self and self.has_coerce_map_from(base) elif (R is InfinityRing or R is UnsignedInfinityRing diff --git a/src/sage/tests/books/judson-abstract-algebra/boolean-sage.py b/src/sage/tests/books/judson-abstract-algebra/boolean-sage.py index f4728a23821..65d125b5aa3 100644 --- a/src/sage/tests/books/judson-abstract-algebra/boolean-sage.py +++ b/src/sage/tests/books/judson-abstract-algebra/boolean-sage.py @@ -146,7 +146,7 @@ sage: P.level_sets() [[18, 9, 6, 0], [11, 10], [2], [1], [8], [3, 12], - [15], [7], [16, 4], [13, 17, 14, 19], [5]] + [15], [7], [4, 16], [14, 19, 13, 17], [5]] ~~~~~~~~~~~~~~~~~~~~~~ :: diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 963cf44c36c..48f5eb66f6f 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -227,6 +227,8 @@ def _n_cells_sorted(self, n, subcomplex=None): sage: K = SimplicialComplex([[1,2,3], [2,3,4]]) sage: Z._n_cells_sorted(2, subcomplex=K) [(1, 2, 4), (1, 3, 4)] + + sage: # needs sage.symbolic sage: S = SimplicialComplex([[complex(i), complex(1)]]) sage: S._n_cells_sorted(0) [((1+0j),), (1j,)] diff --git a/src/sage/topology/moment_angle_complex.py b/src/sage/topology/moment_angle_complex.py index b4c4231d835..d2b986a6a1d 100644 --- a/src/sage/topology/moment_angle_complex.py +++ b/src/sage/topology/moment_angle_complex.py @@ -18,9 +18,9 @@ from itertools import combinations from sage.categories.fields import Fields -from sage.homology.homology_group import HomologyGroup from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.structure.sage_object import SageObject @@ -29,6 +29,8 @@ from sage.topology.cubical_complex import CubicalComplex, cubical_complexes from sage.topology.simplicial_complex import SimplicialComplex, copy +lazy_import('sage.homology.homology_group', 'HomologyGroup') + def _cubical_complex_union(c1, c2): """ @@ -130,11 +132,11 @@ class MomentAngleComplex(UniqueRepresentation, SageObject): We can perform a number of operations, such as find the dimension or compute the homology:: - sage: M.homology() + sage: M.homology() # needs sage.modules {0: 0, 1: 0, 2: 0, 3: Z} sage: Z.dimension() 6 - sage: Z.homology() + sage: Z.homology() # needs sage.modules {0: 0, 1: 0, 2: 0, 3: Z x Z, 4: Z, 5: Z, 6: Z} If the associated simplicial complex is an `n`-simplex, then the @@ -403,9 +405,9 @@ def components(self): sage: S3 = simplicial_complexes.Sphere(3) sage: product_of_spheres = S3.product(S3) - sage: Z.cohomology() + sage: Z.cohomology() # needs sage.modules {0: 0, 1: 0, 2: 0, 3: Z x Z, 4: 0, 5: 0, 6: Z} - sage: Z.cohomology() == product_of_spheres.cohomology() # long time + sage: Z.cohomology() == product_of_spheres.cohomology() # long time # needs sage.modules True """ return self._components @@ -453,6 +455,7 @@ def _homology_group(self, i, base_ring, cohomology, algorithm, verbose, reduced) TESTS:: + sage: # needs sage.modules sage: Z = MomentAngleComplex([[0,1,2], [1,2,3]]); Z Moment-angle complex of Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (1, 2, 3)} @@ -550,6 +553,7 @@ def homology(self, dim=None, base_ring=ZZ, cohomology=False, EXAMPLES:: + sage: # needs sage.modules sage: Z = MomentAngleComplex([[0,1,2], [1,2,3], [3,0]]); Z Moment-angle complex of Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 3), (0, 1, 2), (1, 2, 3)} @@ -580,13 +584,14 @@ def homology(self, dim=None, base_ring=ZZ, cohomology=False, (0, 1, 2) and facets {(0, 1), (0, 2), (1, 2)} sage: Z.cubical_complex() Cubical complex with 64 vertices and 729 cubes - sage: Z.cubical_complex().homology() == Z.homology() + sage: Z.cubical_complex().homology() == Z.homology() # needs sage.modules True Meanwhile, the homology computation used here is quite efficient and works well even with significantly larger underlying simplicial complexes:: + sage: # needs sage.modules sage: Z = MomentAngleComplex([[0,1,2,3,4,5], [0,1,2,3,4,6], ....: [0,1,2,3,5,7], [0,1,2,3,6,8,9]]) sage: Z.homology() # long time @@ -656,6 +661,7 @@ def cohomology(self, dim=None, base_ring=ZZ, algorithm='pari', to a product of two 3-spheres (which can be seen by looking at the output of ``components()``):: + sage: # needs sage.modules sage: S3 = simplicial_complexes.Sphere(3) sage: product_of_spheres = S3.product(S3) sage: Z.cohomology() @@ -684,6 +690,7 @@ def betti(self, dim=None): EXAMPLES:: + sage: # needs sage.modules sage: Z = MomentAngleComplex([[0,1], [1,2], [2,0], [1,2,3]]) sage: Z.betti() {0: 1, 1: 0, 2: 0, 3: 1, 4: 0, 5: 1, 6: 1, 7: 0} @@ -714,6 +721,7 @@ def euler_characteristic(self): EXAMPLES:: + sage: # needs sage.modules sage: X = SimplicialComplex([[0,1,2,3,4,5], [0,1,2,3,4,6], ....: [0,1,2,3,5,7], [0,1,2,3,6,8,9]]) sage: M = MomentAngleComplex(X) diff --git a/src/sage/version.py b/src/sage/version.py index 7aa5469a8ce..cd0c6e32018 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.4.beta9' -date = '2024-06-09' -banner = 'SageMath version 10.4.beta9, Release Date: 2024-06-09' +version = '10.4.rc0' +date = '2024-06-22' +banner = 'SageMath version 10.4.rc0, Release Date: 2024-06-22' diff --git a/src/tox.ini b/src/tox.ini index bd6e5da0546..c270270ff52 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -156,8 +156,6 @@ deps = pycodestyle commands = pycodestyle {posargs:{toxinidir}/sage/} [testenv:pycodestyle-minimal] -## Note that the the pycodestyle linter provided by vscode checks against the -## same minimal conventions as defined below, see the file SAGE_ROOT/.vscode/settings.json. description = check against Sage's minimal style conventions # Check for the following issues: @@ -183,7 +181,7 @@ description = # 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,E303,E305,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605 {posargs:{toxinidir}/sage/} - pycodestyle --select E111,E271,E301,E306,E401,E502,E703,E712,E713,E714,E72,W29,W391,W605, --filename *.pyx {posargs:{toxinidir}/sage/} + pycodestyle --select E111,E271,E301,E305,E306,E401,E502,E703,E712,E713,E714,E72,W29,W391,W605, --filename *.pyx {posargs:{toxinidir}/sage/} [pycodestyle] max-line-length = 160 diff --git a/tox.ini b/tox.ini index ad1dc38d11b..798f2286d14 100644 --- a/tox.ini +++ b/tox.ini @@ -864,7 +864,7 @@ setenv = linuxmint-{20.1,20.2,20.3,21,21.1,21.2,21.3} \ fedora-{30,31,32,33,34,35,36,37,38,39,40} \ centos-7-devtoolset-gcc_11 \ - centos-stream-{8,9}-python3.9 \ + centos-stream-9-python3.9 \ almalinux-{8-python3.9,9-python3.11} \ gentoo-python{3.10,3.11,3.12} \ archlinux-latest \