diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f8b6b52a890..062fa973ac3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,11 @@ name: Build & Test on: pull_request: + merge_group: push: - branches: ['**'] + branches: + - master + - develop # Ignore pushes on tags to prevent two uploads of codecov reports tags-ignore: ['**'] workflow_dispatch: @@ -38,7 +41,9 @@ jobs: - name: Store CI fixes in upstream artifact run: | mkdir -p upstream - git format-patch --stdout test_base > upstream/ci_fixes.patch + if git format-patch --stdout test_base > ci_fixes.patch; then + cp ci_fixes.patch upstream/ + fi - uses: actions/upload-artifact@v3 with: path: upstream diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 9695dc7ef9a..75babf3ab8c 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -7,13 +7,6 @@ on: branches: - 'public/build/**-runci' pull_request: - types: - # Defaults - - opened - - synchronize - - reopened - # When a CI label is added - - labeled workflow_dispatch: # Allow to run manually @@ -27,20 +20,9 @@ jobs: name: Conda runs-on: ${{ matrix.os }} - # Run on push, workflow dispatch and when certain labels are added or are present - if: | - github.event_name != 'pull_request' || - ((github.event.action != 'labeled' && - (contains(github.event.pull_request.labels.*.name, 'c: packages: standard') || - contains(github.event.pull_request.labels.*.name, 'c: packages: optional') || - contains(github.event.pull_request.labels.*.name, 's: run conda ci'))) || - (github.event.action == 'labeled' && - (github.event.label.name == 'c: packages: optional' || - github.event.label.name == 'c: packages: standard' || - github.event.label.name == 's: run conda ci'))) - strategy: - fail-fast: false + fail-fast: ${{ github.event_name == 'pull_request' }} + max-parallel: ${{ github.event_name == 'pull_request' && 2 || 6 }} matrix: os: [ubuntu-latest, macos-latest] python: ['3.9', '3.10', '3.11'] diff --git a/.github/workflows/ci-cygwin-standard.yml b/.github/workflows/ci-cygwin-standard.yml deleted file mode 100644 index 326dd62490e..00000000000 --- a/.github/workflows/ci-cygwin-standard.yml +++ /dev/null @@ -1,137 +0,0 @@ -name: CI cygwin-standard - -on: - push: - tags: - - '*' - workflow_dispatch: - # Allow to run manually - -jobs: - -############################################## stage-i ########################################## - - cygwin-stage-i-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: i-a - # builds openblas - targets: iml gsl - - cygwin-stage-i-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: i-b - targets: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy - -############################################## stage-ii ########################################## - - cygwin-stage-ii-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-a - previous_stages: i-* - targets: cvxopt rpy2 - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-b - previous_stages: i-* - targets: singular maxima gap pari gfan palp arb ecm givaro - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-c: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-c - previous_stages: i-* - targets: cypari eclib fplll linbox giac - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-d: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-d - previous_stages: i-* - targets: ipython ipywidgets notebook - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-e: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-e - previous_stages: i-* - targets: threejs tachyon pillow jmol m4rie sympy lrcalc lcalc symmetrica cliquer libbraiding planarity rw elliptic_curves combinatorial_designs sympow - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - -############################################## stage-iii ########################################## - - cygwin-stage-iii-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: iii-a - previous_stages: ii-* - targets: sagelib - needs: [cygwin-stage-ii-a, cygwin-stage-ii-b, cygwin-stage-ii-c, cygwin-stage-ii-d, cygwin-stage-ii-e] - - cygwin-stage-iii-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: iii-b - previous_stages: ii-* - targets: networkx - needs: [cygwin-stage-ii-a, cygwin-stage-ii-b, cygwin-stage-ii-c, cygwin-stage-ii-d, cygwin-stage-ii-e] - -############################################## stage-iv ########################################## - - cygwin-stage-iv: - uses: ./.github/workflows/cygwin.yml - with: - stage: iv - previous_stages: iii-* - targets: build - needs: [cygwin-stage-iii-a, cygwin-stage-iii-b] - -############################################## stage-v ########################################### - - cygwin-stage-v-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-a - previous_stages: iv - targets: ptest-nodoc - needs: [cygwin-stage-iv] - - cygwin-stage-v-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-b - previous_stages: iv - targets: 4ti2 pynormaliz topcom lrslib latte_int cryptominisat - needs: [cygwin-stage-iv] - - cygwin-stage-v-c: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-c - previous_stages: iv - targets: sage_numerical_backends_coin - needs: [cygwin-stage-iv] - - cygwin-stage-v-d: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-d - previous_stages: iv - targets: qepcad barvinok isl qhull primecount plantri kenzo libsemigroups mcqd meataxe mpfrcx openssl p_group_cohomology rst2ipynb sirocco tdlib tides - needs: [cygwin-stage-iv] - - cygwin-stage-v-e: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-e - previous_stages: iv - targets: doc-html - needs: [cygwin-stage-iv] diff --git a/.github/workflows/ci-wsl.yml b/.github/workflows/ci-wsl.yml deleted file mode 100644 index ae83e1d6a0f..00000000000 --- a/.github/workflows/ci-wsl.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Build & Test WSL - -on: - push: - tags: - - '*' - branches: - - 'public/build/**wsl**' - workflow_dispatch: - # Allow to run manually - -jobs: - windows: - runs-on: windows-latest - name: Ubuntu 20.04 - # Following https://github.com/sagemath/sage/issues/25206#comment:63 - steps: - - name: Configure git - run: git config --global core.symlinks true - - uses: actions/checkout@v4 - - name: Install Ubuntu 20.04 (in WSL) - run: | - (New-Object System.Net.WebClient).DownloadFile("https://aka.ms/wslubuntu2004", "Ubuntu.appx") - Expand-Archive Ubuntu.appx - Ubuntu\ubuntu2004.exe install --root - - name: Install dependencies - run: | - wsl sudo apt-get update -y - wsl sudo apt-get install -y tox - - name: Build - run: wsl tox -e local-sudo-ubuntu-standard -- SAGE_NUM_THREADS=4 build - env: - # WSL runs everything as root, so we have to enable build as root user - EXTRA_CONFIGURE_ARGS: "--enable-build-as-root" - # If make is invoked in parellel (i.e. with -jN where N > 1), then we sometimes run into errors for some reason - # So keep N small in order to minimize the risk - MAKE: "make -j2" - WSLENV: EXTRA_CONFIGURE_ARGS:MAKE - - name: Test - run: wsl tox -e local-sudo-ubuntu-standard -- SAGE_NUM_THREADS=4 ptest - - name: Prepare logs artifact - run: mkdir -p "artifacts/logs"; cp -r .tox/*/log "artifacts/logs" - shell: bash - if: always() - - uses: actions/upload-artifact@v3 - with: - path: artifacts - name: logs - if: always() - - name: Print out logs for immediate inspection - # and markup the output with GitHub Actions logging commands - run: .github/workflows/scan-logs.sh "artifacts/logs" - shell: bash - if: always() diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 6eacba7fe52..0413954210b 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -5,6 +5,15 @@ on: push: workflow_dispatch: # Allow to run manually + inputs: + platform: + description: 'Platform' + required: true + default: 'ubuntu-focal-standard' + docker_tag: + description: 'Docker tag' + required: true + default: 'dev' concurrency: # Cancel previous runs of this workflow for the same branch @@ -12,36 +21,120 @@ concurrency: cancel-in-progress: true jobs: - build-docs: + get_ci_fixes: runs-on: ubuntu-latest - # Use "maximal" so that texlive is installed - # Use "fedora-31" for build diversity - container: ghcr.io/sagemath/sage/sage-docker-fedora-31-maximal-with-targets:dev steps: - name: Checkout + id: checkout uses: actions/checkout@v4 - - name: Merge CI fixes from sagemath/sage run: | .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + - name: Store CI fixes in upstream artifact + run: | + mkdir -p upstream + if git format-patch --stdout test_base > ci_fixes.patch; then + cp ci_fixes.patch upstream/ + fi + - uses: actions/upload-artifact@v3 + with: + path: upstream + name: upstream - - name: Prepare + build-docs-pdf: + runs-on: ubuntu-latest + container: ghcr.io/sagemath/sage/sage-${{ github.event.inputs.platform || 'ubuntu-focal-standard' }}-with-targets:${{ github.event.inputs.docker_tag || 'dev'}} + needs: [get_ci_fixes] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Update system packages + run: | + export PATH="build/bin:$PATH" + eval $(sage-print-system-package-command auto update) + eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip) + eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive) + + + - name: Add prebuilt tree as a worktree + id: worktree run: | - apt-get update && apt-get install -y zip - # Reuse built SAGE_LOCAL contained in the Docker image - ./bootstrap - ./configure --enable-build-as-root --prefix=/sage/local --with-sage-venv --enable-download-from-upstream-url + set -ex + git config --global user.email "ci-sage@example.com" + git config --global user.name "Build & Test workflow" + git config --global --add safe.directory $(pwd) + # If actions/checkout downloaded our source tree using the GitHub REST API + # instead of with git (because do not have git installed in our image), + # we first make the source tree a repo. + if [ ! -d .git ]; then git init && git add -A && git commit --quiet -m "new"; fi + # Tag this state of the source tree "new". This is what we want to build and test. + git tag -f new + # Our container image contains a source tree in /sage with a full build of Sage. + # But /sage is not a git repository. + # We make /sage a worktree whose index is at tag "new". + # We then commit the current sources and set the tag "old". (This keeps all mtimes unchanged.) + # Then we update worktree and index with "git reset --hard new". + # (This keeps mtimes of unchanged files unchanged and mtimes of changed files newer than unchanged files.) + # Finally we reset the index to "old". (This keeps all mtimes unchanged.) + # The changed files now show up as uncommitted changes. + # The final "git add -N" makes sure that files that were added in "new" do not show + # as untracked files, which would be removed by "git clean -fx". + git worktree add --detach worktree-image + rm -rf /sage/.git && mv worktree-image/.git /sage/ + rm -rf worktree-image && ln -s /sage worktree-image + if [ ! -f worktree-image/.gitignore ]; then cp .gitignore worktree-image/; fi + (cd worktree-image && git add -A && git commit --quiet --allow-empty -m "old" -a && git tag -f old && git reset --hard new && git reset --quiet old && git add -N . && git status) + # Keep track of changes to built HTML + new_version=$(cat src/VERSION.txt); (cd /sage/local/share/doc/sage/html/en && find . -name "*.html" | xargs sed -i '/class="sidebar-brand-text"/s/Sage [0-9a-z.]* /Sage '$new_version' /'; git init && (echo "*.svg binary"; echo "*.pdf binary") >> .gitattributes && (echo ".buildinfo"; echo '*.inv'; echo '.git*'; echo '*.svg'; echo '*.pdf'; echo '*.png'; echo 'searchindex.js') > .gitignore; git add -A && git commit --quiet -m "old") + + - name: Download upstream artifact + uses: actions/download-artifact@v3 + with: + path: upstream + name: upstream + + - name: Apply CI fixes from sagemath/sage + # After applying the fixes, make sure all changes are marked as uncommitted changes. + run: | + if [ -r upstream/ci_fixes.patch ]; then + (cd worktree-image && git commit -q -m "current changes" --allow-empty -a && git am; git reset --quiet old; git add -N .) < upstream/ci_fixes.patch + fi + + - name: Incremental build + id: incremental + run: | + # Now re-bootstrap and build. The build is incremental because we were careful with the timestamps. + ./bootstrap && make build + working-directory: ./worktree-image + env: + MAKE: make -j2 + SAGE_NUM_THREADS: 2 + + - name: Build (fallback to non-incremental) + id: build + if: always() && steps.worktree.outcome == 'success' && steps.incremental.outcome != 'success' + run: | + set -ex + make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage && ./config.status && make build + working-directory: ./worktree-image + env: + MAKE: make -j2 + SAGE_NUM_THREADS: 2 - - name: Build + - name: Build docs (PDF) + id: docbuild + if: always() && (steps.incremental.outcome == 'success' || steps.build.outcome == 'success') run: make build V=0 && make doc-pdf + working-directory: ./worktree-image env: MAKE: make -j2 SAGE_NUM_THREADS: 2 - TEXMFHOME: /sage/texmf - name: Copy docs + if: always() && steps.docbuild.outcome == 'success' run: | # For some reason the deploy step below cannot find /sage/... # So copy everything from there to local folder @@ -51,6 +144,7 @@ jobs: zip -r docs-pdf.zip docs - name: Upload docs + if: always() && steps.copy.outcome == 'success' uses: actions/upload-artifact@v3 with: name: docs-pdf diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 04ccb2b28fe..355e07ab78e 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -2,7 +2,11 @@ name: Build documentation on: pull_request: + merge_group: push: + branches: + - master + - develop workflow_dispatch: # Allow to run manually @@ -26,7 +30,9 @@ jobs: - name: Store CI fixes in upstream artifact run: | mkdir -p upstream - git format-patch --stdout test_base > upstream/ci_fixes.patch + if git format-patch --stdout test_base > ci_fixes.patch; then + cp ci_fixes.patch upstream/ + fi - uses: actions/upload-artifact@v3 with: path: upstream diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index db4896bbd12..d49aa516356 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -179,12 +179,6 @@ jobs: (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && sed -i.bak '/upstream/d' .dockerignore && echo "/:toolchain:/i ADD upstream upstream" | sed -i.bak -f - build/bin/write-dockerfile.sh && git diff) if: inputs.upstream_artifact - - name: Merge CI fixes from sagemath/sage - run: | - .ci/merge-fixes.sh - env: - GH_TOKEN: ${{ github.token }} - - name: Try to login to ghcr.io if: inputs.docker_push_repository != '' # https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable @@ -197,6 +191,9 @@ jobs: echo "DOCKER_PUSH_REPOSITORY=$(echo ${{ inputs.docker_push_repository }} | tr "[:upper:]" "[:lower:]")" >> $GITHUB_ENV echo "DOCKER_CONFIG_FILE=$HOME/.docker/config.json" >> $GITHUB_ENV fi + # This line needs to be run before the step "Merge CI fixes from sagemath/sage". + DOCKER_TAG="$(git describe --dirty --always)" + echo "DOCKER_TAG=$DOCKER_TAG" >> $GITHUB_ENV # From the docker documentation via .ci/update-env.sh: # "A tag name must be valid ASCII and may # contain lowercase and uppercase letters, digits, underscores, periods and @@ -211,6 +208,15 @@ jobs: EXTRA_DOCKER_TAGS="dev $EXTRA_DOCKER_TAGS";; esac echo "EXTRA_DOCKER_TAGS=$EXTRA_DOCKER_TAGS" >> $GITHUB_ENV + + - name: Merge CI fixes from sagemath/sage + # This step needs to happen after the commit sha is put in DOCKER_TAG + # so that multi-stage builds can work correctly. + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Configure and build Sage distribution within a Docker container run: | set -o pipefail; EXTRA_DOCKER_BUILD_ARGS="--build-arg NUMPROC=4 --build-arg USE_MAKEFLAGS=\"-k V=0 SAGE_NUM_THREADS=3\"" tox -e $TOX_ENV -- $TARGETS 2>&1 | sed "/^configure: notice:/s|^|::warning file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;/^configure: warning:/s|^|::warning file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;/^configure: error:/s|^|::error file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b4eebb4ac9e..79ca26827b1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,12 @@ name: Lint -on: [push, pull_request] +on: + push: + branches: + - master + - develop + pull_request: + merge_group: concurrency: # Cancel previous runs of this workflow for the same branch diff --git a/.github/workflows/scan-logs.sh b/.github/workflows/scan-logs.sh index 9cab637e850..5df32b0fc48 100755 --- a/.github/workflows/scan-logs.sh +++ b/.github/workflows/scan-logs.sh @@ -5,9 +5,13 @@ LOGS=${1-logs} for a in $(find "$LOGS" -type f -name "*.log"); do if tail -100 "$a" 2>/dev/null | grep "^[A-Za-z]*Error" >/dev/null; then echo :":"error file=$a:":" ==== ERROR IN LOG FILE $a ==== + echo "::group::$a" cat "$a" + echo "::endgroup::" elif tail -20 "$a" 2>/dev/null | grep -E "^(Warning: Error testing|^sage .*doctest.*failed)" >/dev/null; then echo :":"warning file=$a:":" ==== TESTSUITE FAILURE IN LOG FILE $a ==== + echo "::group::$a" cat "$a" + echo "::endgroup::" fi done diff --git a/.gitignore b/.gitignore index efdbfa8f616..2cec8a0cf62 100644 --- a/.gitignore +++ b/.gitignore @@ -175,6 +175,16 @@ build/bin/sage-build-env-config /pkgs/*/*.egg-info /pkgs/*/.tox +/pkgs/sage-conf_pypi/sage_root/config.log +/pkgs/sage-conf_pypi/sage_root/config.status +/pkgs/sage-conf_pypi/sage_root/local/ +/pkgs/sage-conf_pypi/sage_root/logs/ +/pkgs/sage-conf_pypi/sage_root/prefix +/pkgs/sage-conf_pypi/sage_root/src/bin/sage-env-config +/pkgs/sage-conf_pypi/sage_root/src/bin/sage-src-env-config +/pkgs/sage-conf_pypi/sage_root/upstream/ +/pkgs/sage-conf_pypi/sage_root/venv + /pkgs/sagemath-objects/setup.cfg /pkgs/sagemath-bliss/setup.cfg /pkgs/sagemath-coxeter3/setup.cfg diff --git a/CITATION.cff b/CITATION.cff index 7c31fd13f05..a4eaeb56424 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.2.beta5 +version: 10.2.beta6 doi: 10.5281/zenodo.593563 -date-released: 2023-09-27 +date-released: 2023-10-08 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/README.md b/README.md index aee0c3a0fbc..1b350a7996a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ https://www.sagemath.org +[Sage Documentation](https://doc.sagemath.org/html/en/index.html) + The Sage Library is free software released under the GNU General Public Licence GPLv2+, and included packages have [compatible software licenses](./COPYING.txt). @@ -21,6 +23,24 @@ have [compatible software licenses](./COPYING.txt). have contributed code to Sage. In many cases, documentation for modules and functions list the authors. +Table of Contents +----------------- + +* [Getting Started](#getting-started) +* [Supported Platforms](#supported-platforms) +* [\[Windows\] Preparing the Platform Libraries](#windows-preparing-the-platform) +* [\[macOS\] Preparing the Platform Libraries](#macos-preparing-the-platform) +* [Instructions to Build from Source](#instructions-to-build-from-source) +* [SageMath Docker Images](#sagemath-docker-images) +* [Troubleshooting](#troubleshooting) +* [Contributing to Sage](#contributing-to-sage) +* [Directory Layout](#directory-layout) +* [Build System](#build-system) +* [Relocation](#relocation) +* [Redistribution](#redistribution) +* [Build System](#build-system) +* [Changes to Included Software](#changes-to-included-software) + Getting Started --------------- @@ -47,7 +67,7 @@ macOS, and Windows (using Windows Subsystem for Linux or virtualization). Detailed information on supported platforms for a specific version of Sage -can be found in the section "Availability and installation help" of the +can be found in the section _Availability and installation help_ of the [release tour](https://wiki.sagemath.org/ReleaseTours) for this version. We highly appreciate contributions to Sage that fix portability bugs @@ -64,13 +84,13 @@ your Windows. Make sure you allocate WSL sufficient RAM; 5GB is known to work, w 2GB might be not enough for building Sage from source. Then all instructions for installation in Linux apply. -As an alternative, you can also run Linux on Windows using Docker (see -below) or other virtualization solutions. +As an alternative, you can also run Linux on Windows using Docker ([see +below](#sagemath-docker-images)) or other virtualization solutions. [macOS] Preparing the Platform ------------------------------ -If your Mac uses the Apple Silicon (M1, arm64) architecture: +If your Mac uses the Apple Silicon (M1, M2, arm64) architecture: - If you set up your Mac by transfering files from an older Mac, make sure that the directory ``/usr/local`` does not contain an old copy of Homebrew @@ -117,6 +137,7 @@ More details, providing a background for these instructions, can be found in the [section "Install from Source Code"](https://doc.sagemath.org/html/en/installation/source.html). in the Installation Guide. + 1. Decide on the source/build directory (`SAGE_ROOT`): - On personal computers, any subdirectory of your :envvar:`HOME` diff --git a/VERSION.txt b/VERSION.txt index 3b70b866392..9d2185159cb 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.2.beta5, Release Date: 2023-09-27 +SageMath version 10.2.beta6, Release Date: 2023-10-08 diff --git a/bootstrap b/bootstrap index aa5755cfc63..54d0a156239 100755 --- a/bootstrap +++ b/bootstrap @@ -73,9 +73,19 @@ SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(grep -v ^= build/pkgs/$pkgname/SPKG. done for pkgname in $(sage-package list --has-file spkg-configure.m4 | sort); do echo "m4_sinclude([build/pkgs/$pkgname/spkg-configure.m4])" - spkg_configures="$spkg_configures -SAGE_SPKG_CONFIGURE_$(echo ${pkgname} | tr '[a-z]' '[A-Z]')" + config="SAGE_SPKG_CONFIGURE_$(echo ${pkgname} | tr '[a-z]' '[A-Z]')" + if grep -q SAGE_PYTHON_PACKAGE_CHECK build/pkgs/$pkgname/spkg-configure.m4; then + spkg_configures_python="$spkg_configures_python +$config" + else + spkg_configures="$spkg_configures +$config" + fi done >> m4/sage_spkg_configures.m4 + cat >> m4/sage_spkg_configures.m4 <>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(ENABLE_SYSTEM_SITE_PACKAGES=yes sage-get-system-packages install-requires-toml ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions_toml.m4 fi fi - spkg_configures="$spkg_configures + spkg_finalizes="$spkg_finalizes SAGE_SPKG_FINALIZE([$pkgname], [$pkgtype], [$SPKG_SOURCE], [$SPKG_TREE_VAR])" done - echo "$spkg_configures" >> m4/sage_spkg_configures.m4 + 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 diff --git a/build/bin/sage-print-system-package-command b/build/bin/sage-print-system-package-command index b493ebd0ffb..c36f64e19bf 100755 --- a/build/bin/sage-print-system-package-command +++ b/build/bin/sage-print-system-package-command @@ -162,6 +162,12 @@ case $system:$command in nix*:install) [ -n "$system_packages" ] && print_shell_command "nix-env --install $system_packages" ;; + alpine:update) + print_shell_command "apk update" + ;; + alpine:install) + [ -n "$system_packages" ] && print_shell_command "apk add $system_packages" + ;; pip:install) [ -n "$system_packages" ] && print_shell_command "sage -pip install $system_packages" ;; diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 6980f6b6e4b..530c2c6ec63 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -158,8 +158,11 @@ EOF RUN="RUN . /opt/conda/etc/profile.d/conda.sh; conda activate base; " # to activate the conda env ;; *) - echo "Not implemented: package installation for SYSTEM=$SYSTEM" >&2 - exit 1 + cat < 0: - conf_file.write('include_dirs = '+ ':'.join(inc_dir)+'\n') - lib_dir = pc_blas['library_dirs'] - if len(lib_dir) > 0: - conf_file.write('library_dirs = '+ ':'.join(lib_dir)+'\n') -else: - conf_file.write('[blas]\n') - inc_dir = pc_blas['include_dirs'] - if len(inc_dir) > 0: - conf_file.write('include_dirs = '+ ':'.join(inc_dir)+'\n') - lib_dir = pc_blas['library_dirs'] - if len(lib_dir) > 0: - conf_file.write('library_dirs = '+ ':'.join(lib_dir)+'\n') - conf_file.write('blas_libs = '+', '.join(pc_blas['libraries'])+'\n') - conf_file.write('[lapack]\n') - lib_dir = pc_lapack['library_dirs'] - if len(lib_dir) > 0: - conf_file.write('library_dirs = '+ ':'.join(lib_dir)+'\n') - conf_file.write('lapack_libs = '+', '.join(pc_lapack['libraries'])+'\n') - -conf_file.close() diff --git a/build/pkgs/numpy/package-version.txt b/build/pkgs/numpy/package-version.txt index ca8ec414e78..5ff8c4f5d2a 100644 --- a/build/pkgs/numpy/package-version.txt +++ b/build/pkgs/numpy/package-version.txt @@ -1 +1 @@ -1.23.5 +1.26.0 diff --git a/build/pkgs/numpy/patches/21891.patch b/build/pkgs/numpy/patches/21891.patch deleted file mode 100644 index 095fa894ebb..00000000000 --- a/build/pkgs/numpy/patches/21891.patch +++ /dev/null @@ -1,31 +0,0 @@ -From c7894260aaf36c447dd091bf622c7c2bcdb15a28 Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Thu, 30 Jun 2022 13:18:46 -0700 -Subject: [PATCH] setup.py: Remove check for SETUPTOOLS_USE_DISTUTILS - ---- - setup.py | 11 ----------- - 1 file changed, 11 deletions(-) - -diff --git a/setup.py b/setup.py -index 353b6c09693..2bc70173eca 100755 ---- a/setup.py -+++ b/setup.py -@@ -85,17 +85,6 @@ - # so that it is in sys.modules - import numpy.distutils.command.sdist - import setuptools --if int(setuptools.__version__.split('.')[0]) >= 60: -- # setuptools >= 60 switches to vendored distutils by default; this -- # may break the numpy build, so make sure the stdlib version is used -- try: -- setuptools_use_distutils = os.environ['SETUPTOOLS_USE_DISTUTILS'] -- except KeyError: -- os.environ['SETUPTOOLS_USE_DISTUTILS'] = "stdlib" -- else: -- if setuptools_use_distutils != "stdlib": -- raise RuntimeError("setuptools versions >= '60.0.0' require " -- "SETUPTOOLS_USE_DISTUTILS=stdlib in the environment") - - # Initialize cmdclass from versioneer - from numpy.distutils.core import numpy_cmdclass diff --git a/build/pkgs/numpy/patches/cython3-legacy.patch b/build/pkgs/numpy/patches/cython3-legacy.patch deleted file mode 100644 index dfcb9c4a69c..00000000000 --- a/build/pkgs/numpy/patches/cython3-legacy.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/tools/cythonize.py b/tools/cythonize.py -index 002b2fa..c04422e 100755 ---- a/tools/cythonize.py -+++ b/tools/cythonize.py -@@ -47,6 +47,7 @@ def process_pyx(fromfile, tofile): - flags = ['-3', '--fast-fail'] - if tofile.endswith('.cxx'): - flags.append('--cplus') -+ flags += ['--directive', 'legacy_implicit_noexcept=true'] - - subprocess.check_call( - [sys.executable, '-m', 'cython'] + flags + ["-o", tofile, fromfile]) diff --git a/build/pkgs/numpy/spkg-install.in b/build/pkgs/numpy/spkg-install.in index e28660f393f..baebfd466a7 100644 --- a/build/pkgs/numpy/spkg-install.in +++ b/build/pkgs/numpy/spkg-install.in @@ -3,57 +3,33 @@ cd src set -e -if [ `uname` = "Darwin" ]; then - unset ATLAS - unset BLAS - unset LAPACK - # https://github.com/sagemath/sage/issues/34110#comment:35 - # The fix for "reciprocal" (affected by a clang compiler bug) in - # https://github.com/numpy/numpy/pull/19926 relies on -ftrapping-math - # being used when Apple clang v12+ is used. - # But numpy.distutils.ccompiler only sets this flag when - # $CC contains the string "clang" -- missing the case CC=/usr/bin/gcc. - # So we set it here explicitly if the compiler supports the flag. - export CFLAGS="$(testcflags.sh $CFLAGS -ftrapping-math)" -else - export {ATLAS,PTATLAS,OPENBLAS,MKL,MKLROOT}=None - export LDFLAGS="${LDFLAGS} -shared" -fi +# https://github.com/scipy/scipy/issues/16536 - meson breaks when CXX="g++ -std=gnu++11" +# -- this also affects numpy +export CXX=$(echo "$CXX" | sed 's/-std=[a-z0-9+]*//g') if [ "$UNAME" = "CYGWIN" ]; then # Trac #30643 export CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE" fi -# Trac #32746: pkg-config omits -I and -L flags that refer to directories -# that are already on CPATH, LIBRARY_PATH. -# But our script tries to obtain the list of include_dirs and library_dirs -# from pkg-config! -(unset CPATH LIBRARY_PATH; python3 ../lapack_conf.py) - -# Make sure that the fortran objects are compiled with -fPIC -export FFLAGS="$FFLAGS -fPIC" -export FCFLAGS="$FCFLAGS -fPIC" - if [ "$SAGE_FAT_BINARY" = "yes" ]; then export NUMPY_FCONFIG="--cpu-baseline=NONE" else export NUMPY_FCONFIG="" fi -# Trac #32423: Fix 32-bit builds on x86_64 -ARCH=$($CC -dumpmachine 2>/dev/null || echo unknown) -case "$ARCH" in - *x86_64*) - ;; - *) - export NPY_DISABLE_SVML=1 - ;; -esac - -################################################ - -# Trac #33138: numpy is a PEP 517 package, so the crucial "--build-option"s would be ignored. -eval sdh_pip_install --no-use-pep517 \ - $(eval sdh_prefix_args "--build-option" build ${NUMPY_CONFIG} ${NUMPY_FCONFIG}) \ - . +### Per https://github.com/numpy/numpy/releases/tag/v1.26.0b1 +### "NumPy-specific build customization": +### +### The NPY_* environment variables which control BLAS/LAPACK, SIMD, +### threading, and other such options are no longer supported, nor is +### a site.cfg file to select BLAS and LAPACK. Instead, there are +### command-line flags that can be passed to the build via pip/build's +### config-settings interface. These flags are all listed in +### https://github.com/numpy/numpy/blob/main/meson_options.txt +### +### 1.26.0b1 temporarily vendors Meson and meson-python +### http://scipy.github.io/devdocs/building/index.html + + +sdh_pip_install . diff --git a/build/pkgs/onetbb/checksums.ini b/build/pkgs/onetbb/checksums.ini index 5ff81545b4b..69e7ed4d027 100644 --- a/build/pkgs/onetbb/checksums.ini +++ b/build/pkgs/onetbb/checksums.ini @@ -1,5 +1,5 @@ tarball=onetbb-VERSION.tar.gz -sha1=e4be99dc35948052296105d2ae7da6d34e01ba2d -md5=68e617448f71df02d8688c84d53778f6 -cksum=1573392748 +sha1=b991f5d882aba2182871cfe011614cc43b92aa3c +md5=ba4ecedc4949f673a34b35de738a72fc +cksum=211900655 upstream_url=https://github.com/oneapi-src/oneTBB/archive/refs/tags/vVERSION.tar.gz diff --git a/build/pkgs/onetbb/package-version.txt b/build/pkgs/onetbb/package-version.txt index a489944aae9..a6513d2ae59 100644 --- a/build/pkgs/onetbb/package-version.txt +++ b/build/pkgs/onetbb/package-version.txt @@ -1 +1 @@ -2021.7.0 +2021.9.0 diff --git a/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch b/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch new file mode 100644 index 00000000000..a2e4d939311 --- /dev/null +++ b/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch @@ -0,0 +1,36 @@ +From 154cc73ca4d359621202399cc0c3c91058e56e79 Mon Sep 17 00:00:00 2001 +From: Sam James +Date: Wed, 22 Feb 2023 14:16:46 +0000 +Subject: [PATCH] test: common: include for abort() (fix build with + GCC 13) (#1031) + +GCC 13 (as usual for new compiler releases) shuffles around some +internal includes and so etc is no longer transitively included. + +See https://www.gnu.org/software/gcc/gcc-13/porting_to.html. + +Signed-off-by: Sam James +--- + test/common/utils_assert.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/test/common/utils_assert.h b/test/common/utils_assert.h +index 1df8ae72ac..0123ab881e 100644 +--- a/test/common/utils_assert.h ++++ b/test/common/utils_assert.h +@@ -1,5 +1,5 @@ + /* +- Copyright (c) 2005-2022 Intel Corporation ++ Copyright (c) 2005-2023 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. +@@ -20,6 +20,8 @@ + #include "config.h" + #include "utils_report.h" + ++#include ++ + #define REPORT_FATAL_ERROR REPORT + + namespace utils { diff --git a/build/pkgs/openblas/distros/alpine.txt b/build/pkgs/openblas/distros/alpine.txt new file mode 100644 index 00000000000..363072a2f2f --- /dev/null +++ b/build/pkgs/openblas/distros/alpine.txt @@ -0,0 +1 @@ +openblas-dev diff --git a/build/pkgs/packaging/dependencies b/build/pkgs/packaging/dependencies index 17220ffcc37..b63b7e33635 100644 --- a/build/pkgs/packaging/dependencies +++ b/build/pkgs/packaging/dependencies @@ -1,4 +1,4 @@ - | setuptools pip wheel pyparsing setuptools_wheel $(PYTHON) + | flit_core pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pari/distros/alpine.txt b/build/pkgs/pari/distros/alpine.txt new file mode 100644 index 00000000000..964927dedb0 --- /dev/null +++ b/build/pkgs/pari/distros/alpine.txt @@ -0,0 +1 @@ +pari-dev diff --git a/build/pkgs/patch/distros/alpine.txt b/build/pkgs/patch/distros/alpine.txt new file mode 100644 index 00000000000..9eb7b90ed50 --- /dev/null +++ b/build/pkgs/patch/distros/alpine.txt @@ -0,0 +1 @@ +patch diff --git a/build/pkgs/pcre/distros/alpine.txt b/build/pkgs/pcre/distros/alpine.txt new file mode 100644 index 00000000000..a16e4119734 --- /dev/null +++ b/build/pkgs/pcre/distros/alpine.txt @@ -0,0 +1 @@ +pcre-dev diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt new file mode 100644 index 00000000000..c100879ddcd --- /dev/null +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt @@ -0,0 +1,6 @@ +perl-term-readkey +perl-dev +perl-file-slurp +perl-json +perl-xml-writer +perl-xml-libxslt diff --git a/build/pkgs/perl_term_readline_gnu/distros/alpine.txt b/build/pkgs/perl_term_readline_gnu/distros/alpine.txt new file mode 100644 index 00000000000..2ce91c8024b --- /dev/null +++ b/build/pkgs/perl_term_readline_gnu/distros/alpine.txt @@ -0,0 +1 @@ +perl-term-readline-gnu diff --git a/build/pkgs/pip/checksums.ini b/build/pkgs/pip/checksums.ini index 1ae66fbc20a..9b6376d1abb 100644 --- a/build/pkgs/pip/checksums.ini +++ b/build/pkgs/pip/checksums.ini @@ -1,5 +1,5 @@ tarball=pip-VERSION.tar.gz -sha1=29167fffe19874a74247fe92f4fdba1bb1221c61 -md5=996f58a94fe0b8b82b6795c42bd171ba -cksum=537001443 +sha1=4bdfd8e976b5122cf55f4f4740f7305f1ffa4310 +md5=e9b1226701a56ee3fcc81aba60d25d75 +cksum=1940746834 upstream_url=https://pypi.io/packages/source/p/pip/pip-VERSION.tar.gz diff --git a/build/pkgs/pip/package-version.txt b/build/pkgs/pip/package-version.txt index 4c3dad97552..3f833b5b536 100644 --- a/build/pkgs/pip/package-version.txt +++ b/build/pkgs/pip/package-version.txt @@ -1 +1 @@ -22.3.1 +23.2.1 diff --git a/build/pkgs/pkgconf/distros/arch.txt b/build/pkgs/pkgconf/distros/arch.txt new file mode 100644 index 00000000000..05a1a221b7d --- /dev/null +++ b/build/pkgs/pkgconf/distros/arch.txt @@ -0,0 +1 @@ +pkgconf diff --git a/build/pkgs/pplpy/checksums.ini b/build/pkgs/pplpy/checksums.ini index 22961af9a1f..73f16fc3f00 100644 --- a/build/pkgs/pplpy/checksums.ini +++ b/build/pkgs/pplpy/checksums.ini @@ -1,5 +1,5 @@ tarball=pplpy-VERSION.tar.gz -sha1=9f0d531d77dab19f1f0f350022687a8bd749aee2 -md5=980223c38fc95b2f4f8265f20b45a98e -cksum=3147352163 +sha1=dc9e8a7a867ee1c066bdbecf22b6a59dc2052711 +md5=220fc7ab95d7bd62d40acb276f9b149f +cksum=2156962833 upstream_url=https://pypi.io/packages/source/p/pplpy/pplpy-VERSION.tar.gz diff --git a/build/pkgs/pplpy/package-version.txt b/build/pkgs/pplpy/package-version.txt index 1e9b46b2298..55485e17937 100644 --- a/build/pkgs/pplpy/package-version.txt +++ b/build/pkgs/pplpy/package-version.txt @@ -1 +1 @@ -0.8.7 +0.8.9 diff --git a/build/pkgs/pplpy/patches/cython3-legacy.patch b/build/pkgs/pplpy/patches/cython3-legacy.patch deleted file mode 100644 index a038da16d6b..00000000000 --- a/build/pkgs/pplpy/patches/cython3-legacy.patch +++ /dev/null @@ -1,22 +0,0 @@ -commit e6f3e66154138ce3e31e803e74b8c71787c70acc -Author: Gonzalo Tornaría -Date: Wed Jul 19 20:47:52 2023 -0300 - - cython3 support using legacy directives - -diff --git a/setup.py b/setup.py -index 13d543b..55dcd34 100755 ---- a/setup.py -+++ b/setup.py -@@ -38,7 +38,11 @@ class build_ext(_build_ext): - self.extensions[:] = cythonize( - self.extensions, - include_path=sys.path, -- compiler_directives={'embedsignature': True}) -+ compiler_directives={ -+ 'embedsignature': True, -+ 'legacy_implicit_noexcept': True, -+ 'c_api_binop_methods': True, -+ }) - - _build_ext.run(self) diff --git a/build/pkgs/pplpy/patches/relative-import.patch b/build/pkgs/pplpy/patches/relative-import.patch deleted file mode 100644 index 3c011203367..00000000000 --- a/build/pkgs/pplpy/patches/relative-import.patch +++ /dev/null @@ -1,21 +0,0 @@ -From aaa28537fa7ea061ebb8d5131b1e23673eaf741d Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Sun, 31 Jul 2022 12:39:34 -0700 -Subject: [PATCH] ppl/bit_arrays.pxd: Use relative cimport - ---- - ppl/bit_arrays.pxd | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ppl/bit_arrays.pxd b/ppl/bit_arrays.pxd -index eb57434..145a978 100644 ---- a/ppl/bit_arrays.pxd -+++ b/ppl/bit_arrays.pxd -@@ -1,4 +1,4 @@ --from ppl_decl cimport * -+from .ppl_decl cimport * - - cdef class Bit_Row(object): - cdef PPL_Bit_Row *thisptr --- -GitLab diff --git a/build/pkgs/pytz/checksums.ini b/build/pkgs/pytz/checksums.ini index 9c3074def07..0b0e03e9863 100644 --- a/build/pkgs/pytz/checksums.ini +++ b/build/pkgs/pytz/checksums.ini @@ -1,5 +1,5 @@ tarball=pytz-VERSION.tar.gz -sha1=b356ab5a8b326e9857bbce3e7a1799fc56844827 -md5=91747f483e2906cddda91b0df0b01254 -cksum=635792532 +sha1=be3f14bc0d6b89b8c579d8ae4e0fcb4478ff92e6 +md5=84e6569fcc917b096cca1063819c4ab0 +cksum=3925580206 upstream_url=https://pypi.io/packages/source/p/pytz/pytz-VERSION.tar.gz diff --git a/build/pkgs/pytz/package-version.txt b/build/pkgs/pytz/package-version.txt index ef52d12ba35..ccf8d6654d2 100644 --- a/build/pkgs/pytz/package-version.txt +++ b/build/pkgs/pytz/package-version.txt @@ -1 +1 @@ -2022.5 +2023.3.post1 diff --git a/build/pkgs/qhull/distros/alpine.txt b/build/pkgs/qhull/distros/alpine.txt new file mode 100644 index 00000000000..149747bebb0 --- /dev/null +++ b/build/pkgs/qhull/distros/alpine.txt @@ -0,0 +1,2 @@ +qhull-dev +qhull diff --git a/build/pkgs/r/distros/alpine.txt b/build/pkgs/r/distros/alpine.txt new file mode 100644 index 00000000000..8bb0d38745d --- /dev/null +++ b/build/pkgs/r/distros/alpine.txt @@ -0,0 +1,2 @@ +R-dev +R diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index f38cdee4efc..1a1aeb82ccf 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.2b5 +sage-conf ~= 10.2b6 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index 62965fd0775..835830b3029 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.2b5 +sage-docbuild ~= 10.2b6 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 42ef7aa07f9..b6780898e72 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.2b5 +sage-setup ~= 10.2b6 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 8c3cca6a40a..8529dd6a649 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.2b5 +sage-sws2rst ~= 10.2b6 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index 981188d32ca..fa3739fb0e2 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.2b5 +sagemath-standard ~= 10.2b6 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index eaf783b463d..a183832680d 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.2b5 +sagemath-bliss ~= 10.2b6 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 6f9c7bce7d6..deb3d72aaf6 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.2b5 +sagemath-categories ~= 10.2b6 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index 79e17497045..b91e7012431 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.2b5 +sagemath-coxeter3 ~= 10.2b6 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index 5e7993d773b..f874eb9227e 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.2b5 +sagemath-environment ~= 10.2b6 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index cf817314c08..8de59efbee8 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.2b5 +sagemath-mcqd ~= 10.2b6 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index 97b6bb48c9c..0e8a89d1a73 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.2b5 +sagemath-meataxe ~= 10.2b6 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index 99b0309ee9e..e35a3687836 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.2b5 +sagemath-objects ~= 10.2b6 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index 9dab260bb52..1a3de989424 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.2b5 +sagemath-repl ~= 10.2b6 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 7b67a383e35..fd64729fbea 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.2b5 +sagemath-sirocco ~= 10.2b6 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index a5f0a2240a4..62ca038c083 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.2b5 +sagemath-tdlib ~= 10.2b6 diff --git a/build/pkgs/setuptools/SPKG.rst b/build/pkgs/setuptools/SPKG.rst index a50e171a98d..bb69c65b66a 100644 --- a/build/pkgs/setuptools/SPKG.rst +++ b/build/pkgs/setuptools/SPKG.rst @@ -7,13 +7,6 @@ Description setuptools is the classical build system for Python packages, a collection of enhancements to the Python distutils. -This package represents version 63.x of ``setuptools``. -Sage installs this version to provide the build system -for non-PEP 517 packages. In particular, Sage uses it -for building ``numpy``, whose build system ``numpy.distutils`` -is not compatible with newer versions of ``setuptools``, -see https://github.com/numpy/numpy/pull/22154 - License ------- diff --git a/build/pkgs/setuptools/checksums.ini b/build/pkgs/setuptools/checksums.ini index d47099a8019..150e3c25335 100644 --- a/build/pkgs/setuptools/checksums.ini +++ b/build/pkgs/setuptools/checksums.ini @@ -1,5 +1,5 @@ tarball=setuptools-VERSION.tar.gz -sha1=b14b8e2cf965fdb6870ebfccee50c751c056f757 -md5=02a0e4dc4fa13168904e8769a077aa26 -cksum=2734084418 +sha1=b0c9b16863c57d70adc22651906eea7eaee09803 +md5=d967ca2ba7f46db887daee2d5c9bd6a2 +cksum=2346145273 upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.tar.gz diff --git a/build/pkgs/setuptools/install-requires.txt b/build/pkgs/setuptools/install-requires.txt index e0cf7c9b5dc..c12b5900873 100644 --- a/build/pkgs/setuptools/install-requires.txt +++ b/build/pkgs/setuptools/install-requires.txt @@ -1 +1,3 @@ -setuptools >=49.6.0, <64 +# 68.1.0 Promote pyproject.toml's [tool.setuptools] out of beta. +# 68.1.1 Fix editable install finder handling of nested packages +setuptools >= 68.1.1 diff --git a/build/pkgs/setuptools/package-version.txt b/build/pkgs/setuptools/package-version.txt index fe3c6688881..fc312b9c8c1 100644 --- a/build/pkgs/setuptools/package-version.txt +++ b/build/pkgs/setuptools/package-version.txt @@ -1 +1 @@ -63.4.3 +68.2.2 diff --git a/build/pkgs/setuptools_wheel/SPKG.rst b/build/pkgs/setuptools_wheel/SPKG.rst index b77a6679f8f..c78602a296a 100644 --- a/build/pkgs/setuptools_wheel/SPKG.rst +++ b/build/pkgs/setuptools_wheel/SPKG.rst @@ -3,6 +3,3 @@ setuptools_wheel: Build the setuptools package as a wheel After installing setuptools and wheel, we build a wheel of setuptools to complete the set of wheels stored in our wheelhouse. - -This version of setuptools is suitable for PEP 517/518/660 builds, -but it is not suitable for building ``numpy``. diff --git a/build/pkgs/setuptools_wheel/checksums.ini b/build/pkgs/setuptools_wheel/checksums.ini deleted file mode 100644 index 8db0d8c3016..00000000000 --- a/build/pkgs/setuptools_wheel/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=setuptools-VERSION.tar.gz -sha1=2875e8f9a12d8a971461b36e2d1bd64a3497e0f2 -md5=1fd8bd04b0bed95ad6c81f03b1c080bc -cksum=1462078737 -upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.tar.gz diff --git a/build/pkgs/setuptools_wheel/checksums.ini b/build/pkgs/setuptools_wheel/checksums.ini new file mode 120000 index 00000000000..4f64d3ce107 --- /dev/null +++ b/build/pkgs/setuptools_wheel/checksums.ini @@ -0,0 +1 @@ +../setuptools/checksums.ini \ No newline at end of file diff --git a/build/pkgs/setuptools_wheel/install-requires.txt b/build/pkgs/setuptools_wheel/install-requires.txt deleted file mode 100644 index d3767a68c8f..00000000000 --- a/build/pkgs/setuptools_wheel/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -setuptools >= 65.6 diff --git a/build/pkgs/setuptools_wheel/install-requires.txt b/build/pkgs/setuptools_wheel/install-requires.txt new file mode 120000 index 00000000000..c5cfb4ff0a9 --- /dev/null +++ b/build/pkgs/setuptools_wheel/install-requires.txt @@ -0,0 +1 @@ +../setuptools/install-requires.txt \ No newline at end of file diff --git a/build/pkgs/setuptools_wheel/package-version.txt b/build/pkgs/setuptools_wheel/package-version.txt deleted file mode 100644 index c1a8c8394ad..00000000000 --- a/build/pkgs/setuptools_wheel/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -65.6.3 diff --git a/build/pkgs/setuptools_wheel/package-version.txt b/build/pkgs/setuptools_wheel/package-version.txt new file mode 120000 index 00000000000..5268dbec8f6 --- /dev/null +++ b/build/pkgs/setuptools_wheel/package-version.txt @@ -0,0 +1 @@ +../setuptools/package-version.txt \ No newline at end of file diff --git a/build/pkgs/sqlite/distros/alpine.txt b/build/pkgs/sqlite/distros/alpine.txt new file mode 100644 index 00000000000..1598840794c --- /dev/null +++ b/build/pkgs/sqlite/distros/alpine.txt @@ -0,0 +1 @@ +sqlite-dev diff --git a/build/pkgs/suitesparse/distros/alpine.txt b/build/pkgs/suitesparse/distros/alpine.txt new file mode 100644 index 00000000000..2013d8ad35d --- /dev/null +++ b/build/pkgs/suitesparse/distros/alpine.txt @@ -0,0 +1 @@ +suitesparse-dev diff --git a/build/pkgs/tzlocal/checksums.ini b/build/pkgs/tzlocal/checksums.ini index e0a415cb4fc..eb9533b0f63 100644 --- a/build/pkgs/tzlocal/checksums.ini +++ b/build/pkgs/tzlocal/checksums.ini @@ -1,5 +1,5 @@ tarball=tzlocal-VERSION.tar.gz -sha1=76098dc67f43575cda4ab7cf20ebd1c6aef1ceaa -md5=b20f960e77612ff35c5105bb876f0853 -cksum=2281514998 +sha1=1d61e52edddf882c9af4f5f3f1be0db3788dd7b5 +md5=c209a72fd296ff6e1a98d55c2382ba79 +cksum=1644259932 upstream_url=https://pypi.io/packages/source/t/tzlocal/tzlocal-VERSION.tar.gz diff --git a/build/pkgs/tzlocal/package-version.txt b/build/pkgs/tzlocal/package-version.txt index bf77d549685..6b244dcd696 100644 --- a/build/pkgs/tzlocal/package-version.txt +++ b/build/pkgs/tzlocal/package-version.txt @@ -1 +1 @@ -4.2 +5.0.1 diff --git a/build/pkgs/valgrind/distros/alpine.txt b/build/pkgs/valgrind/distros/alpine.txt new file mode 100644 index 00000000000..e7af4129194 --- /dev/null +++ b/build/pkgs/valgrind/distros/alpine.txt @@ -0,0 +1 @@ +valgrind diff --git a/build/pkgs/xz/distros/alpine.txt b/build/pkgs/xz/distros/alpine.txt new file mode 100644 index 00000000000..d66e95ca507 --- /dev/null +++ b/build/pkgs/xz/distros/alpine.txt @@ -0,0 +1 @@ +xz diff --git a/build/pkgs/zeromq/distros/alpine.txt b/build/pkgs/zeromq/distros/alpine.txt new file mode 100644 index 00000000000..c5f85376b35 --- /dev/null +++ b/build/pkgs/zeromq/distros/alpine.txt @@ -0,0 +1 @@ +zeromq-dev diff --git a/build/pkgs/zlib/distros/alpine.txt b/build/pkgs/zlib/distros/alpine.txt new file mode 100644 index 00000000000..ec3c9ffcf26 --- /dev/null +++ b/build/pkgs/zlib/distros/alpine.txt @@ -0,0 +1 @@ +zlib-dev diff --git a/pkgs/sage-conf/README.rst b/pkgs/sage-conf/README.rst index c968612aef2..5730592e35a 100644 --- a/pkgs/sage-conf/README.rst +++ b/pkgs/sage-conf/README.rst @@ -78,10 +78,20 @@ sage_conf in the SageMath distribution The original version of the distribution package ``sage_conf`` is used internally in the SageMath distribution. It is provided in the directory `pkgs/sage-conf `_. -This version of the package is generated by the Sage distribution's ``configure`` +This version of the package is generated by the Sage distribution's ``./configure`` script. +sage_conf for conda +------------------- + +The version of the distribution package in the directory +`pkgs/sage-conf_conda `_ +is used in an experimental installation method of SageMath, where all packages +are provided by conda. This method is described in +https://doc.sagemath.org/html/en/installation/conda.html#using-conda-to-provide-all-dependencies-for-the-sage-library-experimental + + sage_conf in downstream distributions ------------------------------------- diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-conf_conda/.gitignore b/pkgs/sage-conf_conda/.gitignore new file mode 100644 index 00000000000..6fdda73c500 --- /dev/null +++ b/pkgs/sage-conf_conda/.gitignore @@ -0,0 +1,6 @@ +/_sage_conf/_conf.py +/build +/dist +/*.egg-info +/.tox +/bin/sage-env-config diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in new file mode 100644 index 00000000000..ea5f85f8c99 --- /dev/null +++ b/pkgs/sage-conf_conda/MANIFEST.in @@ -0,0 +1,53 @@ +prune .tox +include VERSION.txt +graft bin +exclude bin/sage-env-config # generated by configure + +prune sage_root +include sage_root/Makefile +include sage_root/README.md +include sage_root/VERSION.txt +include sage_root/bootstrap +include sage_root/bootstrap-conda +graft sage_root/build +prune sage_root/build/.tox +exclude sage_root/build/bin/sage-build-env-config # generated by configure +exclude sage_root/build/make/Makefile-auto # generated by configure +exclude sage_root/build/make/Makefile # generated by configure + +# These sources are not needed because individual distributions of these are made. +prune sage_root/build/pkgs/*/src* + +graft sage_root/config +include sage_root/configure +include sage_root/configure.ac +graft sage_root/m4 + +# Only these pkgs are needed (because of dependencies on source files, +# see "git grep SAGE_ROOT build/pkgs/*/dependencies") +graft sage_root/pkgs/sage-conf +prune sage_root/pkgs/sage-conf/build +prune sage_root/pkgs/sage-conf/dist +prune sage_root/pkgs/sage-conf/*.egg-info +exclude sage_root/pkgs/sage-conf/_sage_conf/_conf.py # generated by configure +graft sage_root/pkgs/sage-docbuild +prune sage_root/pkgs/sage-docbuild/build +prune sage_root/pkgs/sage-docbuild/dist +prune sage_root/pkgs/sage-docbuild/*.egg-info + +graft sage_root/src/_sage_conf +include sage_root/src/bin/sage-env +include sage_root/src/bin/sage-env-config.in +include sage_root/src/bin/sage-src-env-config.in +include sage_root/src/bin/sage-venv-config +include sage_root/src/bin/sage-version.sh +include sage_root/src/doc/bootstrap # FIXME: should move to builds/pkgs/sagemath_doc_html/ + +global-exclude .tox +global-exclude *~* +global-exclude *.bak +global-exclude *.orig +global-exclude __pycache__ +global-exclude *.py[co] +global-exclude *.so +global-exclude .DS_Store diff --git a/pkgs/sage-conf_conda/README.rst b/pkgs/sage-conf_conda/README.rst new file mode 120000 index 00000000000..feda886cd36 --- /dev/null +++ b/pkgs/sage-conf_conda/README.rst @@ -0,0 +1 @@ +../sage-conf/README.rst \ No newline at end of file diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt new file mode 100644 index 00000000000..71e18f87543 --- /dev/null +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -0,0 +1 @@ +10.2.beta6 diff --git a/pkgs/sage-conf_conda/_sage_conf b/pkgs/sage-conf_conda/_sage_conf new file mode 120000 index 00000000000..d92a91bef8c --- /dev/null +++ b/pkgs/sage-conf_conda/_sage_conf @@ -0,0 +1 @@ +../sage-conf/_sage_conf \ No newline at end of file diff --git a/pkgs/sage-conf_conda/bin b/pkgs/sage-conf_conda/bin new file mode 120000 index 00000000000..d7471f37a23 --- /dev/null +++ b/pkgs/sage-conf_conda/bin @@ -0,0 +1 @@ +../sage-conf_pypi/bin \ No newline at end of file diff --git a/pkgs/sage-conf_conda/pyproject.toml b/pkgs/sage-conf_conda/pyproject.toml new file mode 120000 index 00000000000..52c93c824e2 --- /dev/null +++ b/pkgs/sage-conf_conda/pyproject.toml @@ -0,0 +1 @@ +../sage-conf/pyproject.toml \ No newline at end of file diff --git a/pkgs/sage-conf_conda/sage_conf.py b/pkgs/sage-conf_conda/sage_conf.py new file mode 120000 index 00000000000..f4bca8cc55c --- /dev/null +++ b/pkgs/sage-conf_conda/sage_conf.py @@ -0,0 +1 @@ +../sage-conf/sage_conf.py \ No newline at end of file diff --git a/pkgs/sage-conf_conda/sage_root b/pkgs/sage-conf_conda/sage_root new file mode 120000 index 00000000000..c25bddb6dd4 --- /dev/null +++ b/pkgs/sage-conf_conda/sage_root @@ -0,0 +1 @@ +../.. \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.cfg b/pkgs/sage-conf_conda/setup.cfg new file mode 120000 index 00000000000..93df2c80a4b --- /dev/null +++ b/pkgs/sage-conf_conda/setup.cfg @@ -0,0 +1 @@ +../sage-conf/setup.cfg \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py new file mode 100644 index 00000000000..9e8ac353f4f --- /dev/null +++ b/pkgs/sage-conf_conda/setup.py @@ -0,0 +1,121 @@ +import os +import sys +import shutil +import sysconfig +import platform +import fnmatch + +from pathlib import Path + +from setuptools import setup +from distutils.command.build_scripts import build_scripts as distutils_build_scripts +from setuptools.command.build_py import build_py as setuptools_build_py +from setuptools.command.editable_wheel import editable_wheel as setuptools_editable_wheel +from setuptools.errors import SetupError + + +class build_py(setuptools_build_py): + + def run(self): + + HERE = os.path.dirname(__file__) + if self.editable_mode: + SAGE_ROOT = os.path.join(HERE, 'sage_root') + else: + SAGE_ROOT = self._create_writable_sage_root() + + if not os.environ.get('CONDA_PREFIX', ''): + raise SetupError('No conda environment is active. ' + 'See https://doc.sagemath.org/html/en/installation/conda.html on how to get started.') + + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') + else: + cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX"' + cmd += ' $(for pkg in $(PATH="build/bin:$PATH" build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' + print(f"Running {cmd}") + sys.stdout.flush() + if os.system(cmd) != 0: + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print("Warning: A configuration has been written, but the configure script has exited with an error. " + "Carefully check any messages above before continuing.") + else: + print(f"Error: The configure script has failed; this may be caused by missing build prerequisites.") + sys.stdout.flush() + PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages + os.system(f'cd {SAGE_ROOT} && export PACKAGES="$(build/bin/sage-get-system-packages conda {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command conda --verbose --sudo install $PACKAGES && echo ""') + raise SetupError("configure failed") + + # In this mode, we never run "make". + + # Copy over files generated by the configure script + # (see configure.ac AC_CONFIG_FILES) + if self.editable_mode: + pass # same file + else: + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + + setuptools_build_py.run(self) + + def _create_writable_sage_root(self): + HERE = os.path.dirname(__file__) + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + with open(os.path.join(HERE, 'VERSION.txt')) as f: + sage_version = f.read().strip() + # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version + # and architecture. + system = platform.system() + machine = platform.machine() + arch_tag = f'{system}-{machine}' + # TODO: Should be user-configurable with config settings + SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') + + def ignore(path, names): + # exclude all embedded src trees + if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + return ['src'] + ### ignore more stuff --- .tox etc. + return [name for name in names + if name in ('.tox', '.git', '__pycache__', + 'prefix', 'local', 'venv', 'upstream', + 'config.status', 'config.log', 'logs')] + + if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + # config.status and other configure output has to be writable. + # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. + try: + shutil.copytree('sage_root', SAGE_ROOT, + ignore=ignore) # will fail if already exists + except Exception as e: + raise SetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured ({e}). " + "Please either remove it and try again, or install in editable mode (pip install -e).") + + return SAGE_ROOT + + +class build_scripts(distutils_build_scripts): + + def run(self): + self.distribution.scripts.append(os.path.join('bin', 'sage-env-config')) + if not self.distribution.entry_points: + self.entry_points = self.distribution.entry_points = dict() + distutils_build_scripts.run(self) + + +class editable_wheel(setuptools_editable_wheel): + r""" + Customized so that exceptions raised by our build_py + do not lead to the "Customization incompatible with editable install" message + """ + _safely_run = setuptools_editable_wheel.run_command + + +setup( + cmdclass=dict(build_py=build_py, + build_scripts=build_scripts, + editable_wheel=editable_wheel) +) diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-conf_pypi/pyproject.toml b/pkgs/sage-conf_pypi/pyproject.toml deleted file mode 100644 index 9787c3bdf00..00000000000 --- a/pkgs/sage-conf_pypi/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" diff --git a/pkgs/sage-conf_pypi/pyproject.toml b/pkgs/sage-conf_pypi/pyproject.toml new file mode 120000 index 00000000000..52c93c824e2 --- /dev/null +++ b/pkgs/sage-conf_pypi/pyproject.toml @@ -0,0 +1 @@ +../sage-conf/pyproject.toml \ No newline at end of file diff --git a/pkgs/sage-conf_pypi/setup.py b/pkgs/sage-conf_pypi/setup.py index a689f4d617b..16686a848c9 100644 --- a/pkgs/sage-conf_pypi/setup.py +++ b/pkgs/sage-conf_pypi/setup.py @@ -3,40 +3,35 @@ import shutil import sysconfig import platform +import fnmatch from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py -from setuptools.command.egg_info import egg_info as setuptools_egg_info -from distutils.errors import (DistutilsSetupError, DistutilsModuleError, - DistutilsOptionError) +from setuptools.command.editable_wheel import editable_wheel as setuptools_editable_wheel +from setuptools.errors import SetupError + class build_py(setuptools_build_py): def run(self): - DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) HERE = os.path.dirname(__file__) - with open(os.path.join(HERE, 'VERSION.txt')) as f: - sage_version = f.read().strip() + if self.editable_mode: + SAGE_ROOT = os.path.join(HERE, 'sage_root') + else: + SAGE_ROOT = self._create_writable_sage_root() + # For convenience, set up the homebrew env automatically. This is a no-op if homebrew is not present. - SETENV = '(. ./.homebrew-build-env 2> /dev/null || :)' - # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version - # and architecture. - system = platform.system() - machine = platform.machine() - arch_tag = f'{system}-{machine}' - # TODO: These two should be user-configurable with options passed to "setup.py install" - SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}') + if os.environ.get('CONDA_PREFIX', ''): + SETENV = ':' + else: + SETENV = '(. ./.homebrew-build-env 2> /dev/null || :)' + SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): - print(f'Reusing SAGE_ROOT={SAGE_ROOT}') + print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') else: - # config.status and other configure output has to be writable. - # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. - try: - shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists - except Exception: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" print(f"Running {cmd}") sys.stdout.flush() @@ -45,7 +40,18 @@ def run(self): sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') - raise DistutilsSetupError("configure failed") + raise SetupError("configure failed") + + # Copy over files generated by the configure script + # (see configure.ac AC_CONFIG_FILES) + if self.editable_mode: + pass # same file + else: + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + # Here we run "make build" -- which builds everything except for sagelib because we # used configure --disable-sagelib # Alternative: @@ -61,13 +67,44 @@ def run(self): if os.system(cmd) != 0: raise DistutilsSetupError(f"make {TARGETS} failed") - # Install configuration - shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), - os.path.join(HERE, '_sage_conf', '_conf.py')) - shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), - os.path.join(HERE, 'bin', 'sage-env-config')) setuptools_build_py.run(self) + def _create_writable_sage_root(self): + HERE = os.path.dirname(__file__) + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + with open(os.path.join(HERE, 'VERSION.txt')) as f: + sage_version = f.read().strip() + # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version + # and architecture. + system = platform.system() + machine = platform.machine() + arch_tag = f'{system}-{machine}' + # TODO: Should be user-configurable with config settings + SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}') + + def ignore(path, names): + # exclude all embedded src trees + if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + return ['src'] + ### ignore more stuff --- .tox etc. + return [name for name in names + if name in ('.tox', '.git', '__pycache__', + 'prefix', 'local', 'venv', 'upstream', + 'config.status', 'config.log', 'logs')] + + if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + # config.status and other configure output has to be writable. + # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. + try: + shutil.copytree('sage_root', SAGE_ROOT, + ignore=ignore) # will fail if already exists + except Exception as e: + raise SetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured ({e}). " + "Please either remove it and try again, or install in editable mode (pip install -e).") + + return SAGE_ROOT + + class build_scripts(distutils_build_scripts): def run(self): @@ -76,6 +113,17 @@ def run(self): self.entry_points = self.distribution.entry_points = dict() distutils_build_scripts.run(self) + +class editable_wheel(setuptools_editable_wheel): + r""" + Customized so that exceptions raised by our build_py + do not lead to the "Customization incompatible with editable install" message + """ + _safely_run = setuptools_editable_wheel.run_command + + setup( - cmdclass=dict(build_py=build_py, build_scripts=build_scripts) + cmdclass=dict(build_py=build_py, + build_scripts=build_scripts, + editable_wheel=editable_wheel) ) diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/src/VERSION.txt b/src/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/src/bin/sage-env b/src/bin/sage-env index 2a63be5b7c0..5c1b4b87ac7 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -121,7 +121,8 @@ if [ "$SAGE_ENV_SOURCED" = "$SAGE_ENV_VERSION" ]; then # Already sourced, nothing to do. return 0 fi -export SAGE_ENV_SOURCED="$SAGE_ENV_VERSION" +# Set SAGE_ENV_SOURCED to the appropriate value at the end of this file, once +# $SAGE_LOCAL, $SAGE_VENV, $SAGE_SRC have been set. # The compilers are set in order of priority by # 1) environment variables @@ -643,3 +644,7 @@ fi # our doctests predictable (which was the status quo with earlier # versions of debugpy). export PYDEVD_DISABLE_FILE_VALIDATION=1 + +# Finally, set SAGE_ENV_SOURCED as evidence that this script has been +# run successfully. +export SAGE_ENV_SOURCED="6:$SAGE_LOCAL:$SAGE_VENV:$SAGE_SRC" diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 3bc82696a62..cb6b55a9f90 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.2.beta5' -SAGE_RELEASE_DATE='2023-09-27' -SAGE_VERSION_BANNER='SageMath version 10.2.beta5, Release Date: 2023-09-27' +SAGE_VERSION='10.2.beta6' +SAGE_RELEASE_DATE='2023-10-08' +SAGE_VERSION_BANNER='SageMath version 10.2.beta6, Release Date: 2023-10-08' diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 5228611de3b..6b4cb871dd7 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -93,7 +93,7 @@ from source as follows: .. _sec-installation-conda-develop: -Using conda to provide all dependencies for the Sage library (experimental) +Using conda to provide all dependencies for the Sage library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can build and install the Sage library from source, using conda to @@ -101,9 +101,6 @@ provide all of its dependencies. This bypasses most of the build system of the Sage distribution and is the fastest way to set up an environment for Sage development. -Note that this is still an experimental feature and may not work as -intended. - Here we assume that you are using a git checkout. - Optionally, set the build parallelism for the Sage library. Use @@ -135,24 +132,12 @@ Here we assume that you are using a git checkout. By default, the most recent version of Python supported by Sage is installed. You can use the additional option ``python=3.9`` in the above - ``env create`` command to select another Python version (here 3.9). - - - Run the ``configure`` script:: - - $ ./bootstrap - $ ./configure --with-python=$CONDA_PREFIX/bin/python \ - --prefix=$CONDA_PREFIX \ - $(for pkg in $(./sage -package list :standard: \ - --exclude rpy2 \ - --has-file spkg-configure.m4 \ - --has-file distros/conda.txt); do \ - echo --with-system-$pkg=force; \ - done) + ``env create`` command to select another Python version (here 3.9). - Install the build prerequisites and the Sage library:: - $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf ./pkgs/sage-setup - $ pip install --no-build-isolation -v -v --editable ./src + $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf_conda ./pkgs/sage-setup + $ pip install --no-build-isolation --config-settings editable_mode=compat -v -v --editable ./src - Verify that Sage has been installed:: @@ -183,3 +168,11 @@ To build the documentation, use:: $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-docbuild $ sage --docbuild all html + +.. NOTE:: + + The switch ``--config-settings editable_mode=compat`` restores the + `legacy setuptools implementation of editable installations + `_. + Adventurous developers may omit this switch to try the modern, + PEP-660 implementation of editable installations, see :issue:`34209`. diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 92ae74b30db..771d335d88d 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -93,6 +93,7 @@ Comprehensive Module List sage/combinat/designs/resolvable_bibd sage/combinat/designs/group_divisible_designs sage/combinat/designs/block_design + sage/combinat/designs/covering_array sage/combinat/designs/covering_design sage/combinat/designs/database sage/combinat/designs/design_catalog diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index fd795532c00..d91866314fc 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1002,6 +1002,11 @@ REFERENCES: group actions}, (preprint March 2003, available on Mitter's MIT website). +.. [Boa1982] J. M. Boardman, "The eightfold way to BP-operations", + in *Current trends in algebraic topology*, pp. 187–226, + Canadian Mathematical Society Proceedings, 2, Part 1. + Providence 1982. ISBN 978-0-8218-6003-8. + .. [Bond2007] P. Bonderson, Nonabelian anyons and interferometry, Dissertation (2007). https://thesis.library.caltech.edu/2447/ @@ -1046,9 +1051,10 @@ REFERENCES: equations: I. Fibonacci and Lucas perfect powers." Annals of Math, 2006. -.. [BMSS2006] Alin Bostan, Bruno Salvy, Francois Morain, Eric Schost. Fast - algorithms for computing isogenies between elliptic +.. [BMSS2006] Alin Bostan, Bruno Salvy, François Morain, Éric Schost. + Fast algorithms for computing isogenies between elliptic curves. [Research Report] 2006, pp.28. + https://arxiv.org/pdf/cs/0609020.pdf .. [BN2010] \D. Bump and M. Nakasuji. Integration on `p`-adic groups and crystal bases. @@ -1732,6 +1738,9 @@ REFERENCES: With an appendix by Ernst Kani. Canad. Math. Bull. 48 (2005), no. 1, 16--31. +.. [Colb2004] C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. + .. [Col2004] Pierre Colmez, Invariant `\mathcal{L}` et derivees de valeurs propres de Frobenius, preprint, 2004. @@ -5650,6 +5659,10 @@ REFERENCES: .. [SloaHada] \N.J.A. Sloane's Library of Hadamard Matrices, at https://neilsloane.com/hadamard/ +.. [SMC2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. + Designs, 14 (2006) pp. 202-213. + .. [SMMK2013] \T. Suzaki, K. Minematsu, S. Morioka, and E. Kobayashi, *TWINE: A lightweight block cipher for multiple platforms*; in SAC, (2012), pp. 338-354. @@ -6329,6 +6342,10 @@ REFERENCES: .. [Wat2010] Watkins, David S. Fundamentals of Matrix Computations, Third Edition. Wiley, Hoboken, New Jersey, 2010. +.. [WC2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 + .. [Web2007] James Webb. *Game theory: decisions, interaction and Evolution*. Springer Science & Business Media, 2007. diff --git a/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst b/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst index c319c38e7b9..8253bb45547 100644 --- a/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst +++ b/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst @@ -179,7 +179,7 @@ Since we defined the class interactively, instead of in a Python module, those tests will complain about "pickling". We can silence this error by making sage think that the class is defined in a module. We could also just ignore those failing tests for now or call :class:`TestSuite` with the -argument `skip='_test_pickling')`:: +argument ``skip='_test_pickling')``:: sage: import __main__ sage: __main__.MyCyclicGroupAlgebra = MyCyclicGroupAlgebra @@ -238,7 +238,7 @@ Exercises #. Make a tiny modification to ``product_on_basis`` in "MyCyclicGroupAlgebra" to implement the *dual* of the group algebra of the cyclic group instead of its group algebra (so the product is now given by - `b_fb_g=\delta_{f,g}bf`). + `b_fb_g=\delta_{f,g}b_f`). Run the :class:`TestSuite` tests (you may ignore the "pickling" errors). What do you notice? @@ -319,7 +319,7 @@ Diagonal and Triangular Morphisms We now illustrate how to specify that a given morphism is diagonal or triangular with respect to some order on the basis, which means that the morphism is -invertible and `Sage` is able to compute the inverse morphism automatically. +invertible and Sage is able to compute the inverse morphism automatically. Currently this feature requires the domain and codomain to have the same index set (in progress ...). @@ -659,7 +659,7 @@ particular, this construction says that they are: There is a bit of redundancy here: given that ``A`` knows it is a commutative algebra with realizations the infrastructure could, in principle, determine that its realizations are commutative algebras. If this - was done then it would be possible to implement `Bases.super_categories` by + was done then it would be possible to implement ``Bases.super_categories`` by returning:: [A.Realizations().WithBasis()] diff --git a/src/sage/categories/sets_with_partial_maps.py b/src/sage/categories/sets_with_partial_maps.py index 08448342ab1..5b2f9b35427 100644 --- a/src/sage/categories/sets_with_partial_maps.py +++ b/src/sage/categories/sets_with_partial_maps.py @@ -13,10 +13,11 @@ from sage.categories.category_singleton import Category_singleton from .objects import Objects + class SetsWithPartialMaps(Category_singleton): """ The category whose objects are sets and whose morphisms are - maps that are allowed to raise a ValueError on some inputs. + maps that are allowed to raise a :class:`ValueError` on some inputs. This category is equivalent to the category of pointed sets, via the equivalence sending an object X to X union {error}, diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 5b9ebedc06e..c1e0eb77022 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -361,7 +361,7 @@ def gilbert_lower_bound(n, q, d): 128/7 """ _check_n_q_d(n, q, d, field_based=False) - ans=q**n/volume_hamming(n,q,d-1) + ans = q**n/volume_hamming(n,q,d-1) return ans def plotkin_upper_bound(n,q,d, algorithm=None): @@ -389,16 +389,16 @@ def plotkin_upper_bound(n,q,d, algorithm=None): return QQ(libgap.UpperBoundPlotkin(n, d, q)) else: t = 1 - 1/q - if (q==2) and (n == 2*d) and (d%2 == 0): + if (q == 2) and (n == 2*d) and (d % 2 == 0): return 4*d - elif (q==2) and (n == 2*d + 1) and (d%2 == 1): + elif (q == 2) and (n == 2*d + 1) and (d % 2 == 1): return 4*d + 4 elif d > t*n: return int(d/( d - t*n)) elif d < t*n + 1: fact = (d-1) / t from sage.rings.real_mpfr import RR - if RR(fact)==RR(int(fact)): + if RR(fact) == RR(int(fact)): fact = int(fact) + 1 return int(d/( d - t * fact)) * q**(n - fact) @@ -487,7 +487,7 @@ def ff(n,d,w,q): def get_list(n,d,q): I = [] for i in range(1,int(r*n)+1): - if i**2-2*r*n*i+r*n*d>0: + if i**2-2*r*n*i+r*n*d > 0: I.append(i) return I I = get_list(n,d,q) diff --git a/src/sage/coding/code_constructions.py b/src/sage/coding/code_constructions.py index 2cd68c11a28..d96ad3c7627 100644 --- a/src/sage/coding/code_constructions.py +++ b/src/sage/coding/code_constructions.py @@ -321,7 +321,7 @@ def walsh_matrix(m0): if m > 1: row2 = [x.list() for x in walsh_matrix(m-1).augment(walsh_matrix(m-1)).rows()] return matrix(GF(2), m, 2**m, [[0]*2**(m-1) + [1]*2**(m-1)] + row2) - raise ValueError("%s must be an integer > 0."%m0) + raise ValueError("%s must be an integer > 0." % m0) ##################### main constructions ##################### @@ -356,7 +356,7 @@ def DuadicCodeEvenPair(F,S1,S2): from .cyclic_code import CyclicCode n = len(S1) + len(S2) + 1 if not _is_a_splitting(S1,S2,n): - raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n)) + raise TypeError("%s, %s must be a splitting of %s." % (S1,S2,n)) q = F.order() k = Mod(q,n).multiplicative_order() FF = GF(q**k,"z") @@ -406,7 +406,7 @@ def DuadicCodeOddPair(F,S1,S2): from .cyclic_code import CyclicCode n = len(S1) + len(S2) + 1 if not _is_a_splitting(S1,S2,n): - raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n)) + raise TypeError("%s, %s must be a splitting of %s." % (S1,S2,n)) q = F.order() k = Mod(q,n).multiplicative_order() FF = GF(q**k,"z") diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index 7839cd8c693..3826734c09b 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -274,9 +274,9 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, from sage.rings.finite_rings.finite_field_constructor import FiniteField from sage.matrix.constructor import Matrix - d=int(b) - if d!=b or d%2==1 or d <= 0: - raise ValueError("b (%s) must be a positive even integer."%b) + d = int(b) + if d != b or d % 2 == 1 or d <= 0: + raise ValueError("b (%s) must be a positive even integer." % b) from .linear_code import LinearCode from .binary_code import BinaryCode, BinaryCodeClassifier if k < 1 or n < 2: diff --git a/src/sage/coding/golay_code.py b/src/sage/coding/golay_code.py index b55cd8a4f4d..e698605825e 100644 --- a/src/sage/coding/golay_code.py +++ b/src/sage/coding/golay_code.py @@ -271,7 +271,7 @@ def weight_distribution(self): n = self.length() if n == 23: return ([1]+[0]*6+[253]+[506]+[0]*2+[1288]*2+[0]*2+[506] - +[253]+[0]*6+[1]) + + [253]+[0]*6+[1]) if n == 24: return ([1]+[0]*7+[759]+[0]*3+[2576]+[0]*3+[759]+[0]*7+[1]) if n == 11: diff --git a/src/sage/coding/grs_code.py b/src/sage/coding/grs_code.py index b0824a51f62..82a0a5cfe72 100644 --- a/src/sage/coding/grs_code.py +++ b/src/sage/coding/grs_code.py @@ -1235,7 +1235,7 @@ def _decode_to_code_and_message(self, r): l0 = n-1-t l1 = n-1-t-(k-1) S = matrix(C.base_field(), n, l0+l1+2, - lambda i, j: (C.evaluation_points()[i])**j if j<(l0+1) + lambda i, j: (C.evaluation_points()[i])**j if j < (l0+1) else r_list[i]*(C.evaluation_points()[i])**(j-(l0+1))) S = S.right_kernel() S = S.basis_matrix().row(0) @@ -1978,9 +1978,9 @@ def decode_to_message(self, word_and_erasure_vector): if C1_length == k: return self.connected_encoder().unencode_nocheck(word) C1_evaluation_points = [self.code().evaluation_points()[i] for i in - range(n) if erasure_vector[i]!=1] + range(n) if erasure_vector[i] != 1] C1_column_multipliers = [self.code().column_multipliers()[i] for i in - range(n) if erasure_vector[i]!=1] + range(n) if erasure_vector[i] != 1] C1 = GeneralizedReedSolomonCode(C1_evaluation_points, k, C1_column_multipliers) return C1.decode_to_message(punctured_word) diff --git a/src/sage/coding/guava.py b/src/sage/coding/guava.py index e9f0404b458..92e2dc80451 100644 --- a/src/sage/coding/guava.py +++ b/src/sage/coding/guava.py @@ -69,8 +69,8 @@ def QuasiQuadraticResidueCode(p): """ GapPackage("guava", spkg="gap_packages").require() libgap.load_package("guava") - C=libgap.QQRCode(p) - G=C.GeneratorMat() + C = libgap.QQRCode(p) + G = C.GeneratorMat() MS = MatrixSpace(GF(2), len(G), len(G[0])) return LinearCode(MS(G)) @@ -104,7 +104,7 @@ def RandomLinearCodeGuava(n, k, F): GapPackage("guava", spkg="gap_packages").require() libgap.load_package("guava") - C=libgap.RandomLinearCode(n,k,F) - G=C.GeneratorMat() + C = libgap.RandomLinearCode(n,k,F) + G = C.GeneratorMat() MS = MatrixSpace(F, len(G), len(G[0])) return LinearCode(MS(G)) diff --git a/src/sage/coding/guruswami_sudan/gs_decoder.py b/src/sage/coding/guruswami_sudan/gs_decoder.py index 3021cbbfab6..bf4c78d71e4 100644 --- a/src/sage/coding/guruswami_sudan/gs_decoder.py +++ b/src/sage/coding/guruswami_sudan/gs_decoder.py @@ -371,7 +371,7 @@ def guruswami_sudan_decoding_radius(C=None, n_k=None, l=None, s=None): def get_tau(s,l): "Return the decoding radius given this s and l" - if s<=0 or l<=0: + if s <= 0 or l <= 0: return -1 return gilt(n - n/2*(s+1)/(l+1) - (k-1)/2*l/s) if l is None and s is None: @@ -482,7 +482,7 @@ def _suitable_parameters_given_tau(tau, C=None, n_k=None): atau = n - tau smin = tau * w / (atau ** 2 - n * w) s = floor(1 + smin) - D = (s - smin) * (atau ** 2 - n * w) * s + (w**2) /4 + D = (s - smin) * (atau ** 2 - n * w) * s + (w**2) / 4 l = floor(atau / w * s + 0.5 - sqrt(D)/w) return (s, l) diff --git a/src/sage/coding/information_set_decoder.py b/src/sage/coding/information_set_decoder.py index 5d4d28a7c47..dad1f2b06f3 100644 --- a/src/sage/coding/information_set_decoder.py +++ b/src/sage/coding/information_set_decoder.py @@ -587,7 +587,7 @@ def time_search_loop(p): P = [ time_search_loop(p) for p in range(tau+1) ] def compute_estimate(p): - iters = 1.* binomial(n, k)/ \ + iters = 1. * binomial(n, k) / \ sum( binomial(n-tau, k-i)*binomial(tau,i) for i in range(p+1) ) estimate = iters*(T + sum(P[pi] * (q-1)**pi * binomial(k, pi) for pi in range(p+1) )) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index ac1581f2691..0d84996a483 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -277,7 +277,7 @@ def _dump_code_in_leon_format(C): from sage.misc.temporary_file import tmp_filename F = C.base_ring() p = F.order() # must be prime and <11 - s = "LIBRARY code;\n"+"code=seq(%s,%s,%s,seq(\n"%(p,C.dimension(),C.length()) + s = "LIBRARY code;\n"+"code=seq(%s,%s,%s,seq(\n" % (p,C.dimension(),C.length()) Gr = [str(r)[1:-1].replace(" ","") for r in C.generator_matrix().rows()] s += ",\n".join(Gr) + "\n));\nFINISH;" file_loc = tmp_filename() @@ -605,25 +605,25 @@ def assmus_mattson_designs(self, t, mode=None): n = len(G.columns()) Cp = C.dual_code() wts = C.weight_distribution() - d = min([i for i in range(1,len(wts)) if wts[i]!=0]) - if t>=d: + d = min([i for i in range(1,len(wts)) if wts[i] != 0]) + if t >= d: return 0 - nonzerowts = [i for i in range(len(wts)) if wts[i]!=0 and i<=n and i>=d] - if mode=="verbose": + nonzerowts = [i for i in range(len(wts)) if wts[i] != 0 and i <= n and i >= d] + if mode == "verbose": for w in nonzerowts: print("The weight w={} codewords of C* form a t-(v,k,lambda) design, where\n \ t={}, v={}, k={}, lambda={}. \nThere are {} block of this design.".format( w,t,n,w,wts[w]*binomial(w,t)//binomial(n,t),wts[w])) wtsp = Cp.weight_distribution() - dp = min([i for i in range(1,len(wtsp)) if wtsp[i]!=0]) - nonzerowtsp = [i for i in range(len(wtsp)) if wtsp[i]!=0 and i<=n-t and i>=dp] - s = len([i for i in range(1,n) if wtsp[i]!=0 and i<=n-t and i>0]) - if mode=="verbose": + dp = min([i for i in range(1,len(wtsp)) if wtsp[i] != 0]) + nonzerowtsp = [i for i in range(len(wtsp)) if wtsp[i] != 0 and i <= n-t and i >= dp] + s = len([i for i in range(1,n) if wtsp[i] != 0 and i <= n-t and i > 0]) + if mode == "verbose": for w in nonzerowtsp: print("The weight w={} codewords of C* form a t-(v,k,lambda) design, where\n \ t={}, v={}, k={}, lambda={}. \nThere are {} block of this design.".format( w,t,n,w,wts[w]*binomial(w,t)//binomial(n,t),wts[w])) - if s<=d-t: + if s <= d-t: des = [[t,(n,w,wts[w]*binomial(w,t)//binomial(n,t))] for w in nonzerowts] ans = ans + ["weights from C: ",nonzerowts,"designs from C: ",des] desp = [[t,(n,w,wtsp[w]*binomial(w,t)//binomial(n,t))] for w in nonzerowtsp] @@ -672,20 +672,20 @@ def binomial_moment(self, i): J = range(1,n+1) Cp = self.dual_code() dp = Cp.minimum_distance() - if in-dp and i<=n: - return binomial(n,i)*(q**(i+k-n) -1)//(q-1) + if i > n-dp and i <= n: + return binomial(n,i)*(q**(i+k-n) - 1)//(q-1) from sage.combinat.set_partition import SetPartitions P = SetPartitions(J,2).list() b = QQ(0) for p in P: p = list(p) S = p[0] - if len(S)==n-i: + if len(S) == n-i: C_S = self.shortened(S) k_S = C_S.dimension() - b = b + (q**(k_S) -1)//(q-1) + b = b + (q**(k_S) - 1)//(q-1) return b @cached_method @@ -827,7 +827,7 @@ def characteristic_polynomial(self): k = C.dimension() n = C.length() q = (C.base_ring()).order() - return q**(n-k)*prod([1-x/j for j in Sd if j>0]) + return q**(n-k)*prod([1-x/j for j in Sd if j > 0]) def chinen_polynomial(self): """ @@ -955,7 +955,7 @@ def divisor(self): V = VectorSpace(QQ,n+1) S = V(A).nonzero_positions() S0 = [S[i] for i in range(1,len(S))] - if len(S)>1: + if len(S) > 1: return GCD(S0) return 1 @@ -1220,7 +1220,7 @@ def galois_closure(self, F0): q0 = F0.order() a = q.log(q0) # test if F/F0 is a field extension if not isinstance(a, Integer): - raise ValueError("Base field must be an extension of given field %s"%F0) + raise ValueError("Base field must be an extension of given field %s" % F0) n = len(G.columns()) k = len(G.rows()) G0 = [[x**q0 for x in g.list()] for g in G.rows()] @@ -1302,7 +1302,7 @@ def is_permutation_equivalent(self,other,algorithm=None): B2 = NonlinearBinaryCodeStruct(CW2) ans = B1.is_isomorphic(B2) if ans is not False: - if algorithm=="verbose": + if algorithm == "verbose": Sn = SymmetricGroup(n) return True, Sn([i+1 for i in ans])**(-1) return True @@ -1640,28 +1640,28 @@ def permutation_automorphism_group(self, algorithm="partition"): GapPackage("guava", spkg="gap_packages").require() libgap.LoadPackage('guava') wts = self.weight_distribution() # bottleneck 1 - nonzerowts = [i for i in range(len(wts)) if wts[i]!=0] + nonzerowts = [i for i in range(len(wts)) if wts[i] != 0] Sn = libgap.SymmetricGroup(n) Sn_sage = SymmetricGroup(n) Gp = Sn # initializing G in gap C = libgap(G).GeneratorMatCode(libgap.GF(q)) eltsC = C.Elements() - if algorithm=="gap+verbose": + if algorithm == "gap+verbose": print("\n Minimum distance: %s \n Weight distribution: \n %s" % (nonzerowts[1], wts)) stop = 0 # only stop if all gens are autos for i in range(1,len(nonzerowts)): if stop == 1: break wt = nonzerowts[i] - if algorithm=="gap+verbose": + if algorithm == "gap+verbose": size = Gp.Size() print("\n Using the %s codewords of weight %s \n Supergroup size: \n %s\n " % (wts[wt], wt, size)) - Cwt=filter(lambda c: c.WeightCodeword()==wt, eltsC) # bottleneck 2 (repeated - matCwt=list(map(lambda c: c.VectorCodeword(), Cwt)) # for each i until stop = 1) + Cwt = filter(lambda c: c.WeightCodeword() == wt, eltsC) # bottleneck 2 (repeated + matCwt = list(map(lambda c: c.VectorCodeword(), Cwt)) # for each i until stop = 1) if len(matCwt) > 0: A = libgap(matCwt).MatrixAutomorphisms() Gp = A.Intersection2(Gp) # bottleneck 3 - if Gp.Size()==1: + if Gp.Size() == 1: return PermutationGroup([()]) gens = Gp.GeneratorsOfGroup() stop = 1 # get ready to stop @@ -1671,7 +1671,7 @@ def permutation_automorphism_group(self, algorithm="partition"): break G = PermutationGroup(list(map(Sn_sage, gens))) return G - if algorithm=="partition": + if algorithm == "partition": if q == 2: from sage.groups.perm_gps.partn_ref.refinement_binary import LinearBinaryCodeStruct B = LinearBinaryCodeStruct(G) @@ -1703,7 +1703,7 @@ def permutation_automorphism_group(self, algorithm="partition"): else: return PermutationGroup([]) return AutGp - if algorithm=="codecan": + if algorithm == "codecan": gens, _ = self.automorphism_group_gens("permutational") return PermutationGroup([x.get_perm() for x in gens]) raise NotImplementedError("The only algorithms implemented currently are 'gap', 'gap+verbose', and 'partition'.") @@ -1866,17 +1866,17 @@ def weight_distribution(self, algorithm=None): algorithm = "gap" F = self.base_ring() n = self.length() - if algorithm=="gap": + if algorithm == "gap": from sage.libs.gap.libgap import libgap Gmat = self.generator_matrix() q = self.base_ring().order() z = 0*libgap.Z(q)*([0]*self.length()) # GAP zero vector - w=libgap(Gmat).DistancesDistributionMatFFEVecFFE(libgap.GF(q),z) + w = libgap(Gmat).DistancesDistributionMatFFEVecFFE(libgap.GF(q),z) return w.sage() - elif algorithm=="binary": + elif algorithm == "binary": from sage.coding.binary_code import weight_dist return weight_dist(self.generator_matrix()) - elif algorithm=="leon": + elif algorithm == "leon": if not(F.order() in [2,3,5,7]): raise NotImplementedError("The algorithm 'leon' is only implemented for q = 2,3,5,7.") # The GAP command DirectoriesPackageLibrary tells the location of the latest @@ -2030,8 +2030,8 @@ def zeta_polynomial(self, name="T"): if d == 1 or dperp == 1: print("\n WARNING: There is no guarantee this function works when the minimum distance") print(" of the code or of the dual code equals 1.\n") - RT = PolynomialRing(QQ,"%s"%name) - R = PolynomialRing(QQ,3,"xy%s"%name) + RT = PolynomialRing(QQ,"%s" % name) + R = PolynomialRing(QQ,3,"xy%s" % name) x,y,T = R.gens() we = self.weight_enumerator() A = R(we) @@ -2380,9 +2380,9 @@ def _repr_(self): """ R = self.base_ring() if R in Fields(): - return "[%s, %s] linear code over GF(%s)"%(self.length(), self.dimension(), R.cardinality()) + return "[%s, %s] linear code over GF(%s)" % (self.length(), self.dimension(), R.cardinality()) else: - return "[%s, %s] linear code over %s"%(self.length(), self.dimension(), R) + return "[%s, %s] linear code over %s" % (self.length(), self.dimension(), R) def _latex_(self): r""" diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index babb22ff1ce..6a7cd14cb62 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -731,9 +731,9 @@ def _repr_(self): R = self.base_field() S = self.sub_field() if R and S in Fields(): - return "[%s, %s] linear rank metric code over GF(%s)/GF(%s)"%(self.length(), self.dimension(), R.cardinality(), S.cardinality()) + return "[%s, %s] linear rank metric code over GF(%s)/GF(%s)" % (self.length(), self.dimension(), R.cardinality(), S.cardinality()) else: - return "[%s, %s] linear rank metric code over %s/%s"%(self.length(), self.dimension(), R, S) + return "[%s, %s] linear rank metric code over %s/%s" % (self.length(), self.dimension(), R, S) def _latex_(self): r""" diff --git a/src/sage/coding/parity_check_code.py b/src/sage/coding/parity_check_code.py index d131ecaf80a..0adafbbba57 100644 --- a/src/sage/coding/parity_check_code.py +++ b/src/sage/coding/parity_check_code.py @@ -304,7 +304,7 @@ def encode(self, message): sage: C.encode(message) (1, 0, 4, 2, 0, 3, 2, 3) """ - parity=self.code().base_field().zero() + parity = self.code().base_field().zero() for i in message.list(): parity += i return vector(self.code().base_field(), message.list() + [-parity]) diff --git a/src/sage/coding/self_dual_codes.py b/src/sage/coding/self_dual_codes.py index 67f90226ccb..d60d161d28d 100644 --- a/src/sage/coding/self_dual_codes.py +++ b/src/sage/coding/self_dual_codes.py @@ -537,7 +537,7 @@ def self_dual_binary_codes(n): "Type":"I","Comment": "Huge aut gp. Unique codeword of smallest non-zero wt.\ Same spectrum as '[18,3]' sd code."} # [18,5]: - C = self_dual_binary_codes(n-2)["%s"%(n-2)]["5"]["code"] + C = self_dual_binary_codes(n-2)["%s" % (n-2)]["5"]["code"] A0 = C.redundancy_matrix() genmat = _I2(n).augment(block_diagonal_matrix([A0,_matId(n)[8]])) # G = PermutationGroup( [ "(5,10)(6,11)", "(5,11)(6,10)", "(5,11,12)(6,7,10)",\ @@ -550,7 +550,7 @@ def self_dual_binary_codes(n): self_dual_codes_18_5 = {"order autgp":451584,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment": "'Exceptional' construction."} # [18,6]: - C = self_dual_binary_codes(n-2)["%s"%(n-2)]["6"]["code"] + C = self_dual_binary_codes(n-2)["%s" % (n-2)]["6"]["code"] A0 = C.redundancy_matrix() genmat = _I2(n).augment(block_diagonal_matrix([A0,_matId(n)[8]])) G = PermutationGroup( [ "(9,18)", "(7,10)(11,17)", "(7,11)(10,17)", "(6,7)(11,12)", @@ -649,7 +649,7 @@ def self_dual_binary_codes(n): # G = PermutationGroup( [ "(5,6)(15,16)", "(5,15)(6,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)", "(8,17)(9,10)", "(8,10)(9,17)", "(8,10,20)(9,19,17)",\ # "(8,19,20,9,17,10,18)", "(7,8,19,20,9,18)(10,17)"] ) - spectrum =[1, 0, 0, 0, 29, 0, 32, 0, 226, 0, 448, 0, 226, 0, 32, 0, 29, 0, 0, 0, 1] + spectrum = [1, 0, 0, 0, 29, 0, 32, 0, 226, 0, 448, 0, 226, 0, 32, 0, 29, 0, 0, 0, 1] self_dual_codes_20_3 = {"order autgp":30965760,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment":"Min dist 4."} # [20,4]: @@ -660,7 +660,7 @@ def self_dual_binary_codes(n): # "(1,2,3,11,14,4,12)(5,17,18)(6,15,8)", "(1,5,13,17,14,8,2,7,3,16,12,6,11,18)(4,15)",\ # "(2,3,12)(4,11,14)(5,17,18)(6,15,8)(10,20)",\ # "(2,3,12)(4,11,14)(5,17,18)(6,15,8)(9,10,19,20)"] ) - spectrum =[1, 0, 2, 0, 29, 0, 56, 0, 226, 0, 396, 0, 226, 0, 56, 0, 29, 0, 2, 0, 1] + spectrum = [1, 0, 2, 0, 29, 0, 56, 0, 226, 0, 396, 0, 226, 0, 56, 0, 29, 0, 2, 0, 1] self_dual_codes_20_4 = {"order autgp":28901376,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment":""} # [20,5]: @@ -715,7 +715,7 @@ def self_dual_binary_codes(n): # G = PermutationGroup( [ "(9,10)(19,20)", "(9,19)(10,20)", "(8,9)(18,19)", "(7,8)(17,18)",\ # "(6,7)(16,17)", "(5,6)(15,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)"] ) - spectrum =[1, 0, 0, 0, 45, 0, 0, 0, 210, 0, 512, 0, 210, 0, 0, 0, 45, 0, 0, 0, 1] + spectrum = [1, 0, 0, 0, 45, 0, 0, 0, 210, 0, 512, 0, 210, 0, 0, 0, 45, 0, 0, 0, 1] self_dual_codes_20_8 = {"order autgp":1857945600,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment":"Huge aut gp. Min dist 4."} # [20,9]: (genmat, K20 are equiv) diff --git a/src/sage/coding/two_weight_db.py b/src/sage/coding/two_weight_db.py index 44695300f33..1ad3d584310 100644 --- a/src/sage/coding/two_weight_db.py +++ b/src/sage/coding/two_weight_db.py @@ -179,17 +179,17 @@ 'w1': 99, 'w2': 108, 'K' : GF(3), - 'M' : ("10000021022112121121110122002121000010001102020020110112102112202221021020201"+ + 'M' : ("10000021022112121121110122002121000010001102020020110112102112202221021020201" + "20202212102220222022222110122210022201211222111110211101121002011102101111002", - "01000020121020200200211101202000100111001222222022121120012020122110122122221"+ + "01000020121020200200211101202000100111001222222022121120012020122110122122221" + "02222102012112111221111021101101021121002001022221202211100102212212010222102", - "00100021001211011111111202122021010221101221212220022221200011221102002202120"+ + "00100021001211011111111202122021010221101221212220022221200011221102002202120" + "20121121000101000111020212200020121210011112210001001022001012222020000100212", - "00010022122200222202201212212020101202111221111211112001022110001001221210110"+ + "00010022122200222202201212212020101202111221111211112001022110001001221210110" + "12211020202200222000021101010212001022212020002112011200021100210001100121020", - "00001021201002010011020210220020010200212211101111221012101020222021111111212"+ + "00001021201002010011020210220020010200212211101111221012101020222021111111212" + "11120012122110211222201220220201222200102101111020112221020112012102211120101", - "00000120112212122122202110022120001200022010100102202210012211211120100101022"+ + "00000120112212122122202110022120001200022010100102202210012211211120100101022" + "01011212011101110111112202111200111021221112222211222020120010222012022220012"), 'source': "Shared by Eric Chen [ChenDB]_.", }, @@ -199,25 +199,25 @@ 'w1': 96, 'w2': 112, 'K' : GF(2), - 'M' : ("1000000000111111101010000100011001111101101010010010011110001101111001101100111000111101010101110011"+ + 'M' : ("1000000000111111101010000100011001111101101010010010011110001101111001101100111000111101010101110011" + "11110010100111101001001100111101011110111100101101110100111100011111011011100111110010100110110000", - "0100000000010110011100100010101010101111011010001001010110011010101011011101000110000001101101010110"+ + "0100000000010110011100100010101010101111011010001001010110011010101011011101000110000001101101010110" + "10110111110101000000011011001100010111110001001011011100111100100000110001011001110110011101011000", - "0010000000011100111110111011000011010100100011110000001100011011101111001010001100110110000001111000"+ + "0010000000011100111110111011000011010100100011110000001100011011101111001010001100110110000001111000" + "11000000101011010111110101000111110010011011101110000010110100000011100010011111100100111101010010", - "0001000000001111100010000000100101010001110111100010010010010111000100101100010001001110111101110100"+ + "0001000000001111100010000000100101010001110111100010010010010111000100101100010001001110111101110100" + "10010101101100110011010011101100110100100011011101100000110011110011111000000010110101011111101111", - "0000100000110010010000010110000111010011010101000010110100101010011011000011001100001110011011110001"+ + "0000100000110010010000010110000111010011010101000010110100101010011011000011001100001110011011110001" + "11101000010000111101101100111100001011010010111011100101101001111000100011000010110111111111011100", - "0000010000110100111001111011010000101110001011100010010010010111100101011001011011100110101110100001"+ + "0000010000110100111001111011010000101110001011100010010010010111100101011001011011100110101110100001" + "01101010110010100011000101111100100001110111001001001001001100001101110110000110101010011010101101", - "0000001000011011110010110100010010001100000011001000011101000110001101001000110110010101011011001111"+ + "0000001000011011110010110100010010001100000011001000011101000110001101001000110110010101011011001111" + "01111111010011111010100110011001110001001000001110000110111011010000011101001110111001011011001011", - "0000000100111001101011110010111100100001010100100110001100100110010101111001100101101001000101011000"+ + "0000000100111001101011110010111100100001010100100110001100100110010101111001100101101001000101011000" + "10001001111101011101001001010111010011011101010011010000101010011001010110011110010000011011111001", - "0000000010101011010101010101011100111101111110100011011001001010111101100111010110100101100110101100"+ + "0000000010101011010101010101011100111101111110100011011001001010111101100111010110100101100110101100" + "00000001100011110110010101100001000000010100001101111011111000110001100101101010000001110101011100", - "0000000001101100111101011000010000000011010100000110101010011010100111100001000011010011011101110111"+ + "0000000001101100111101011000010000000011010100000110101010011010100111100001000011010011011101110111" + "01110111011110101100100100110110011100001001000001010011010010010111110011101011101001101101011010"), 'source': "Shared by Eric Chen [ChenDB]_.", }, @@ -227,23 +227,23 @@ 'w1': 96, 'w2': 112, 'K' : GF(2), - 'M' : ("10100011001110100010100010010000100100001011110010001010011000000001101011110011001001000010011110111011111"+ + 'M' : ("10100011001110100010100010010000100100001011110010001010011000000001101011110011001001000010011110111011111" + "0001001010110110110111001100111100011011101000000110101110001010100011110011111111110111010100101011000101111111", - "01100010110101110100001000010110001010010010011000111101111001011101000011101011100111111110001100000111010"+ + "01100010110101110100001000010110001010010010011000111101111001011101000011101011100111111110001100000111010" + "1101001000110001111011001100101011110101011110010001101011110000100000101101100010110100001111001100110011001111", - "00010010001001011011001110011101111110000000101110101000110110011001110101011011101011011011000010010011111"+ + "00010010001001011011001110011101111110000000101110101000110110011001110101011011101011011011000010010011111" + "1110110100111111000000110011101101000000001010000000011000111111100101100001110011110001110011110110100111100001", - "00001000100010101110101110011100010101110011010110000001111111100111010000101110001010100100000001011010111"+ + "00001000100010101110101110011100010101110011010110000001111111100111010000101110001010100100000001011010111" + "1001001000000011000011001100100100111010000000001010111001001100100101011110001100110001000000111001100100100111", - "00000101010100010101101110011101001000101110000000000111101100011000000001110100000001011010101001111110110"+ + "00000101010100010101101110011101001000101110000000000111101100011000000001110100000001011010101001111110110" + "0010110111100111000000110011110110101101110000001111100001010001100101100001110011110001101101000000000000100001", - "00000000000000000000010000011101011100100010000110110100101011001011001100000001011000101010100111000111101"+ + "00000000000000000000010000011101011100100010000110110100101011001011001100000001011000101010100111000111101" + "0011100011011011011111100010011100010111101001011001001101100010011010001011010110001110100001001111110010100100", - "00000000000000000000000001011010110110101111010110101001001001000101010000000000001011000011000010100100110"+ + "00000000000000000000000001011010110110101111010110101001001001000101010000000000001011000011000010100100110" + "0000110000111101100010000111111111101101001010110000111111101110101011010010010001011101110011111001100100101110", - "00000000000000000000000000110111101011110010101110000110010010100010001010000000010100011000101000010011000"+ + "00000000000000000000000000110111101011110010101110000110010010100010001010000000010100011000101000010011000" + "0110000111100110100001001011111111111010110000001010111111110011110110001100100010101011101101110110011000110110", - "00000000000000000000000000000000000000000000000001111111111111111111111110000001111111111111111111111111111"+ + "00000000000000000000000000000000000000000000000001111111111111111111111110000001111111111111111111111111111" + "1111111100000000000011111111111111000000111111111111111111000000000000111111111111000000000000000000111111000110"), 'source': "Shared by Eric Chen [ChenDB]_.", }, diff --git a/src/sage/combinat/affine_permutation.py b/src/sage/combinat/affine_permutation.py index 17279fee0e8..d0ce08e3e83 100644 --- a/src/sage/combinat/affine_permutation.py +++ b/src/sage/combinat/affine_permutation.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.groups r""" Affine Permutations """ diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index 80d4ab301b7..ee34e183a70 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Alternating Sign Matrices @@ -1821,9 +1821,8 @@ def __classcall_private__(cls, n, **kwds): sage: C = ContreTableaux(4) sage: type(C) - """ - assert(isinstance(n, (int, Integer))) + assert isinstance(n, (int, Integer)) return ContreTableaux_n(n, **kwds) @@ -1983,9 +1982,8 @@ def __classcall_private__(cls, n, last_column, **kwds): sage: T = TruncatedStaircases(4, [2,3]) sage: type(T) - """ - assert(isinstance(n, (int, Integer))) + assert isinstance(n, (int, Integer)) return TruncatedStaircases_nlastcolumn(n, last_column, **kwds) diff --git a/src/sage/combinat/bijectionist.py b/src/sage/combinat/bijectionist.py index 68d1f322e9f..00053209d4e 100644 --- a/src/sage/combinat/bijectionist.py +++ b/src/sage/combinat/bijectionist.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.numerical.mip r""" A bijectionist's toolkit diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index 9527c512360..ab946066d95 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Binary Recurrence Sequences @@ -705,7 +706,7 @@ def pthpowers(self, p, Bound): #CRT by hand to gain speed for i in list(cong): - if not (i % modu in cong1): #congruence in cong is inconsistent with any in cong1 + if i % modu not in cong1: #congruence in cong is inconsistent with any in cong1 cong.remove(i) #remove that congruence killed_something = True diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py index 8e876ab137a..7d304ed1499 100644 --- a/src/sage/combinat/binary_tree.py +++ b/src/sage/combinat/binary_tree.py @@ -914,7 +914,7 @@ def make_node(self, child_list=[None, None]): """ self._require_mutable() child_lst = [self.__class__(self.parent(), x) for x in child_list] - if not(len(child_lst) == 2): + if len(child_lst) != 2: raise ValueError("the list must have length 2") self.__init__(self.parent(), child_lst, check=False) @@ -1873,7 +1873,7 @@ def left_border_symmetry(self): labelled = self in LabelledBinaryTrees() labels = [] t = self - while(t): + while t: border.append(t[1].left_border_symmetry()) if labelled: labels.append(t.label()) diff --git a/src/sage/combinat/blob_algebra.py b/src/sage/combinat/blob_algebra.py index 657c70a5c0e..595063a69fd 100644 --- a/src/sage/combinat/blob_algebra.py +++ b/src/sage/combinat/blob_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Blob Algebras diff --git a/src/sage/combinat/chas/fsym.py b/src/sage/combinat/chas/fsym.py index a2dfd12f621..f1c149c66f1 100644 --- a/src/sage/combinat/chas/fsym.py +++ b/src/sage/combinat/chas/fsym.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Poirier-Reutenauer Hopf algebra of standard tableaux diff --git a/src/sage/combinat/chas/wqsym.py b/src/sage/combinat/chas/wqsym.py index 99659ab154a..57b90761c88 100644 --- a/src/sage/combinat/chas/wqsym.py +++ b/src/sage/combinat/chas/wqsym.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Word Quasi-symmetric functions diff --git a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py index a67af5739ce..514acb43636 100644 --- a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py +++ b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py @@ -1555,7 +1555,6 @@ def g_vector(self, k): sage: [S.g_vector(k) for k in range(3)] [(1, 0, 0), (0, 0, -1), (0, -1, 0)] """ - if not (self._is_principal or self._use_g_vec or (self._use_fpolys and self._cluster)): raise ValueError("Unable to calculate g-vectors. Need to use g vectors.") if k not in range(self._n): @@ -1823,8 +1822,6 @@ def d_matrix(self, show_warnings=True): [1 1 1 1] [1 0 1 1] [0 0 0 1] - - """ if not (self._use_d_vec or self._use_fpolys or self._track_mut): # raise ValueError("No d-vectors initialized.") @@ -4345,7 +4342,7 @@ def oriented_exchange_graph(self): j = i.mutate(k, inplace=False) Varj = tuple(sorted(j.cluster())) covers.append((Vari, Varj)) - if not(Varj in known_clusters): + if Varj not in known_clusters: known_clusters += [Varj] stack.append(j) @@ -4456,7 +4453,7 @@ def find_upper_bound(self, verbose=False): new_gen_found = False i = 0 M_gens = M.gens() - while (not new_gen_found) and i < len(M_gens): + while not new_gen_found and i < len(M_gens): f = initial_product_ideal.reduce(M_gens[i]) if f != 0: rels.append('z' + str(len(gens) - 2 * rank - 1) + '*' + initial_product + '-(' + str(f) + ')') @@ -4466,7 +4463,7 @@ def find_upper_bound(self, verbose=False): print('') i += 1 - def get_upper_cluster_algebra_element(self,a): + def get_upper_cluster_algebra_element(self, a): r""" Compute an element in the upper cluster algebra of `B` corresponding to the vector `a \in \ZZ^n`. @@ -4556,7 +4553,7 @@ def LLM_gen_set(self, size_limit=-1): break a = aSet[i] genSet.append(self.get_upper_cluster_algebra_element(a)) - return (genSet) + return genSet def _compute_compatible_vectors(self, vd): r""" diff --git a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py index 3ff53f5dd31..524c95a80df 100644 --- a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py @@ -892,9 +892,9 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): # Exception 1 case (4-cycle): edges = sg.edges(sort=True, labels=False) - if not (c1[0],c1[1]) in edges and not (c1[1],c1[0]) in edges and sg.is_isomorphic( exception_graph1 ): - dg_tmp = DiGraph( dg ) - dg_tmp.delete_vertices( c1 ) + if (c1[0], c1[1]) not in edges and (c1[1], c1[0]) not in edges and sg.is_isomorphic(exception_graph1): + dg_tmp = DiGraph(dg) + dg_tmp.delete_vertices(c1) components = dg_tmp.connected_components(sort=False) # if not len(components) == 2: @@ -1081,13 +1081,13 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): if len( in_neighbors ) == 1: in_neighbors.extend(in_neighbors) - if not (in_neighbors[0],v) in oriented_trian_edges: + if (in_neighbors[0], v) not in oriented_trian_edges: return _false_return(24) - elif not (in_neighbors[1],v) in oriented_trian_edges: + elif (in_neighbors[1], v) not in oriented_trian_edges: return _false_return(25) - elif not (v,out_neighbors[0]) in oriented_trian_edges: + elif (v, out_neighbors[0]) not in oriented_trian_edges: return _false_return(26) - elif not (v,out_neighbors[1]) in oriented_trian_edges: + elif (v, out_neighbors[1]) not in oriented_trian_edges: return _false_return(27) # if a vertex has valency 3 than 2 of its neighboring edges must be contained in an oriented triangle and the remaining must not @@ -1106,14 +1106,14 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): return _false_return(30) if not long_cycle[1] == QuiverMutationType(['D',n]): return _false_return(31) - if not (v,out_neighbors[0]) in long_cycle[0] and not (v,out_neighbors[1]) in long_cycle[0]: + if (v, out_neighbors[0]) not in long_cycle[0] and (v, out_neighbors[1]) not in long_cycle[0]: return _false_return(32) if (v,out_neighbors[0]) not in oriented_trian_edges and (v,out_neighbors[1]) not in oriented_trian_edges: return _false_return(33) elif w[0] == 2: in_neighbors = dg.neighbors_in( v ) out_neighbors = dg.neighbors_out( v ) - if not (v,out_neighbors[0]) in oriented_trian_edges: + if (v, out_neighbors[0]) not in oriented_trian_edges: return _false_return(34) elif len( in_neighbors ) == 1: if (in_neighbors[0],v) not in oriented_trian_edges: @@ -1124,9 +1124,9 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): return _false_return(36) if not long_cycle[1] == QuiverMutationType(['D',n]): return _false_return(37) - if not (in_neighbors[0],v) in long_cycle[0] and not (in_neighbors[1],v) in long_cycle[0]: + if (in_neighbors[0], v) not in long_cycle[0] and (in_neighbors[1], v) not in long_cycle[0]: return _false_return(38) - if (in_neighbors[0],v) not in oriented_trian_edges and (in_neighbors[1],v) not in oriented_trian_edges: + if (in_neighbors[0], v) not in oriented_trian_edges and (in_neighbors[1], v) not in oriented_trian_edges: return _false_return(39) else: return _false_return(40) diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver.py b/src/sage/combinat/cluster_algebra_quiver/quiver.py index 23d4e5c3a62..028f8abb797 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver.py @@ -2180,7 +2180,7 @@ def d_vector_fan(self): from sage.geometry.fan import Fan from sage.geometry.cone import Cone - if not(self.is_finite()): + if not (self.is_finite()): raise ValueError('only makes sense for quivers of finite type') seed = ClusterSeed(self) return Fan([Cone(s.d_matrix().columns()) @@ -2228,7 +2228,7 @@ def g_vector_fan(self): from sage.geometry.fan import Fan from sage.geometry.cone import Cone - if not(self.is_finite()): + if not (self.is_finite()): raise ValueError('only supported for quivers of finite type') seed = ClusterSeed(self).principal_extension() return Fan([Cone(s.g_matrix().columns()) diff --git a/src/sage/combinat/cluster_complex.py b/src/sage/combinat/cluster_complex.py index e263d983887..a1f7489f1ad 100644 --- a/src/sage/combinat/cluster_complex.py +++ b/src/sage/combinat/cluster_complex.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs r""" Cluster complex (or generalized dual associahedron) diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index fc8b044d89d..dca90c2a4e3 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -242,7 +242,7 @@ def __ne__(self, other): sage: c != Combinations([1,2,3,3]) True """ - return not(self == other) + return not (self == other) def __repr__(self): """ @@ -395,7 +395,7 @@ def __ne__(self, other): sage: c != Combinations((1,2,2,3), 2) True """ - return not(self == other) + return not (self == other) def __repr__(self): """ diff --git a/src/sage/combinat/constellation.py b/src/sage/combinat/constellation.py index cbefe06054d..0ad3151925e 100644 --- a/src/sage/combinat/constellation.py +++ b/src/sage/combinat/constellation.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.groups r""" Constellations @@ -565,7 +565,7 @@ def is_isomorphic(self, other, return_map=False): True """ if return_map: - if not(self.degree() == other.degree() and + if not (self.degree() == other.degree() and self.length() == other.length()): return False, None sn, sn_map = self.relabel(return_map=True) diff --git a/src/sage/combinat/crystals/affine.py b/src/sage/combinat/crystals/affine.py index c33fe853152..186d2ea373e 100644 --- a/src/sage/combinat/crystals/affine.py +++ b/src/sage/combinat/crystals/affine.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affine Crystals """ diff --git a/src/sage/combinat/crystals/affine_factorization.py b/src/sage/combinat/crystals/affine_factorization.py index f6bbf42966f..b1d820032af 100644 --- a/src/sage/combinat/crystals/affine_factorization.py +++ b/src/sage/combinat/crystals/affine_factorization.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affine factorization crystal of type `A` """ diff --git a/src/sage/combinat/crystals/affinization.py b/src/sage/combinat/crystals/affinization.py index 2a58d8ab609..d849e407c3f 100644 --- a/src/sage/combinat/crystals/affinization.py +++ b/src/sage/combinat/crystals/affinization.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affinization Crystals """ diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index aa5dc56d9ca..2ae58703362 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Alcove paths diff --git a/src/sage/combinat/crystals/bkk_crystals.py b/src/sage/combinat/crystals/bkk_crystals.py index 15e795ca484..b3658fd28a4 100644 --- a/src/sage/combinat/crystals/bkk_crystals.py +++ b/src/sage/combinat/crystals/bkk_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Benkart-Kang-Kashiwara crystals for the general-linear Lie superalgebra """ diff --git a/src/sage/combinat/crystals/crystals.py b/src/sage/combinat/crystals/crystals.py index dbc2e9a211f..b68469ce8ba 100644 --- a/src/sage/combinat/crystals/crystals.py +++ b/src/sage/combinat/crystals/crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" An introduction to crystals =========================== diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index e66ea6e9ef5..190a3279513 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Direct Sum of Crystals """ @@ -141,11 +142,12 @@ def __init__(self, crystals, facade, keepkey, category, **options): if len(crystals) == 0: raise ValueError("the direct sum is empty") else: - assert(crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) + assert all(crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) self._cartan_type = crystals[0].cartan_type() if keepkey: - self.module_generators = tuple([ self((i,b)) for i,B in enumerate(crystals) - for b in B.module_generators ]) + self.module_generators = tuple([self((i, b)) + for i, B in enumerate(crystals) + for b in B.module_generators]) else: self.module_generators = sum((tuple(B.module_generators) for B in crystals), ()) diff --git a/src/sage/combinat/crystals/elementary_crystals.py b/src/sage/combinat/crystals/elementary_crystals.py index 2aa68d0279e..c89dd7504fd 100644 --- a/src/sage/combinat/crystals/elementary_crystals.py +++ b/src/sage/combinat/crystals/elementary_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Elementary Crystals diff --git a/src/sage/combinat/crystals/fast_crystals.py b/src/sage/combinat/crystals/fast_crystals.py index 8a33913269d..aebc499e9fb 100644 --- a/src/sage/combinat/crystals/fast_crystals.py +++ b/src/sage/combinat/crystals/fast_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fast Rank Two Crystals """ diff --git a/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py b/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py index b4fbcff59a3..51a04179364 100644 --- a/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py +++ b/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fully commutative stable Grothendieck crystal diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py index 59cd7e92050..36f6c259942 100644 --- a/src/sage/combinat/crystals/generalized_young_walls.py +++ b/src/sage/combinat/crystals/generalized_young_walls.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Crystals of Generalized Young Walls diff --git a/src/sage/combinat/crystals/highest_weight_crystals.py b/src/sage/combinat/crystals/highest_weight_crystals.py index 1b1d7f315e8..96d7377c029 100644 --- a/src/sage/combinat/crystals/highest_weight_crystals.py +++ b/src/sage/combinat/crystals/highest_weight_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Highest weight crystals """ diff --git a/src/sage/combinat/crystals/induced_structure.py b/src/sage/combinat/crystals/induced_structure.py index 2920fb67b7c..95ed85bf5f8 100644 --- a/src/sage/combinat/crystals/induced_structure.py +++ b/src/sage/combinat/crystals/induced_structure.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Induced Crystals diff --git a/src/sage/combinat/crystals/infinity_crystals.py b/src/sage/combinat/crystals/infinity_crystals.py index 32536d9de60..6219da38391 100644 --- a/src/sage/combinat/crystals/infinity_crystals.py +++ b/src/sage/combinat/crystals/infinity_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" `\mathcal{B}(\infty)` Crystals of Tableaux in Nonexceptional Types and `G_2` diff --git a/src/sage/combinat/crystals/kac_modules.py b/src/sage/combinat/crystals/kac_modules.py index d9da3fd8bff..79d753ac9ae 100644 --- a/src/sage/combinat/crystals/kac_modules.py +++ b/src/sage/combinat/crystals/kac_modules.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Crystals of Kac modules of the general-linear Lie superalgebra """ diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 10de248f868..0856d337fb6 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kirillov-Reshetikhin Crystals """ diff --git a/src/sage/combinat/crystals/kyoto_path_model.py b/src/sage/combinat/crystals/kyoto_path_model.py index ff4c69e9ff9..e7ae0b47275 100644 --- a/src/sage/combinat/crystals/kyoto_path_model.py +++ b/src/sage/combinat/crystals/kyoto_path_model.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kyoto Path Model for Affine Highest Weight Crystals """ diff --git a/src/sage/combinat/crystals/letters.pyx b/src/sage/combinat/crystals/letters.pyx index 921be80c434..d204a979563 100644 --- a/src/sage/combinat/crystals/letters.pyx +++ b/src/sage/combinat/crystals/letters.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Crystals of letters """ diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index c384a818e56..a90a61cb4c9 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Littelmann paths diff --git a/src/sage/combinat/crystals/monomial_crystals.py b/src/sage/combinat/crystals/monomial_crystals.py index 38ae061355f..7ba4b52bb51 100644 --- a/src/sage/combinat/crystals/monomial_crystals.py +++ b/src/sage/combinat/crystals/monomial_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Crystals of Modified Nakajima Monomials diff --git a/src/sage/combinat/crystals/multisegments.py b/src/sage/combinat/crystals/multisegments.py index a3d0d661015..6f63d4562a3 100644 --- a/src/sage/combinat/crystals/multisegments.py +++ b/src/sage/combinat/crystals/multisegments.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Crystal of Bernstein-Zelevinsky Multisegments """ diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index cd6a4497d8e..67967f88bd0 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Crystal Of Mirković-Vilonen (MV) Polytopes diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index df359333f6d..9859438ae58 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" `\mathcal{B}(\infty)` Crystal Of PBW Monomials diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index dd27d91294a..2adcb09d902 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" PBW Data diff --git a/src/sage/combinat/crystals/polyhedral_realization.py b/src/sage/combinat/crystals/polyhedral_realization.py index f4f20fe84f7..c4193b44655 100644 --- a/src/sage/combinat/crystals/polyhedral_realization.py +++ b/src/sage/combinat/crystals/polyhedral_realization.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Polyhedral Realization of `B(\infty)` """ diff --git a/src/sage/combinat/crystals/spins.pyx b/src/sage/combinat/crystals/spins.pyx index 0798a534077..7548b7b695e 100644 --- a/src/sage/combinat/crystals/spins.pyx +++ b/src/sage/combinat/crystals/spins.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Spin Crystals diff --git a/src/sage/combinat/crystals/star_crystal.py b/src/sage/combinat/crystals/star_crystal.py index 2b4ac9c90a8..02427149ed4 100644 --- a/src/sage/combinat/crystals/star_crystal.py +++ b/src/sage/combinat/crystals/star_crystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Star-Crystal Structure On `B(\infty)` diff --git a/src/sage/combinat/crystals/subcrystal.py b/src/sage/combinat/crystals/subcrystal.py index b1221b51e88..e712abd38c8 100644 --- a/src/sage/combinat/crystals/subcrystal.py +++ b/src/sage/combinat/crystals/subcrystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Subcrystals diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index bfe1801454d..a1b94ccf541 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Tensor Products of Crystals diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx index a95d2060b4b..bafdb5e175a 100644 --- a/src/sage/combinat/crystals/tensor_product_element.pyx +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Tensor Products of Crystal Elements diff --git a/src/sage/combinat/crystals/virtual_crystal.py b/src/sage/combinat/crystals/virtual_crystal.py index f14bf59dd42..a4cdc8b4ee8 100644 --- a/src/sage/combinat/crystals/virtual_crystal.py +++ b/src/sage/combinat/crystals/virtual_crystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Virtual Crystals diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index 0c4b8a3d9d7..d7c883c22c5 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -445,10 +445,10 @@ def _rand_der(self): mark = [x < 0 for x in A] i, u = n, n while u >= 2: - if not(mark[i - 1]): + if not mark[i - 1]: while True: j = randrange(1, i) - if not(mark[j - 1]): + if not mark[j - 1]: A[i - 1], A[j - 1] = A[j - 1], A[i - 1] break p = random() @@ -461,7 +461,7 @@ def _rand_der(self): def random_element(self): r""" - Produces all derangements of a positive integer, a list, or + Produce all derangements of a positive integer, a list, or a string. The list or string may contain repeated elements. If an integer `n` is given, then a random derangements of `[1, 2, 3, \ldots, n]` is returned diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index 8945c697c1e..3468d80b4b7 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Descent Algebras diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index 019c11dbf65..7363fa05f90 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -236,7 +236,7 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa (10,4,2)-Balanced Incomplete Block Design sage: designs.balanced_incomplete_block_design(50,25,24) # needs sage.schemes (50,25,24)-Balanced Incomplete Block Design - sage: designs.balanced_incomplete_block_design(29,15,15) # needs sage.libs.pari + sage: designs.balanced_incomplete_block_design(29,15,15) # needs sage.libs.pari sage.schemes (29,15,15)-Balanced Incomplete Block Design """ # Trivial BIBD @@ -1125,7 +1125,7 @@ def v_5_1_BIBD(v, check=True): sage: from sage.combinat.designs.bibd import v_5_1_BIBD sage: i = 0 - sage: while i<200: # needs sage.libs.pari + sage: while i<200: # needs sage.libs.pari sage.schemes ....: i += 20 ....: _ = v_5_1_BIBD(i+1) ....: _ = v_5_1_BIBD(i+5) diff --git a/src/sage/combinat/designs/block_design.py b/src/sage/combinat/designs/block_design.py index 17720d6ca92..86c3b1383ee 100644 --- a/src/sage/combinat/designs/block_design.py +++ b/src/sage/combinat/designs/block_design.py @@ -122,8 +122,8 @@ def are_hyperplanes_in_projective_geometry_parameters(v, k, lmbda, return_parame sage: are_hyperplanes_in_projective_geometry_parameters(40, 13, 4, ....: return_parameters=True) (True, (3, 3)) - sage: PG = designs.ProjectiveGeometryDesign(3, 2, GF(3)) - sage: PG.is_t_design(return_parameters=True) + sage: PG = designs.ProjectiveGeometryDesign(3, 2, GF(3)) # needs sage.combinat + sage: PG.is_t_design(return_parameters=True) # needs sage.combinat (True, (2, 40, 13, 4)) sage: are_hyperplanes_in_projective_geometry_parameters(15, 3, 1) @@ -217,13 +217,13 @@ def ProjectiveGeometryDesign(n, d, F, algorithm=None, point_coordinates=True, ch The set of `d`-dimensional subspaces in a `n`-dimensional projective space forms `2`-designs (or balanced incomplete block designs):: - sage: PG = designs.ProjectiveGeometryDesign(4, 2, GF(2)); PG + sage: PG = designs.ProjectiveGeometryDesign(4, 2, GF(2)); PG # needs sage.combinat Incidence structure with 31 points and 155 blocks - sage: PG.is_t_design(return_parameters=True) + sage: PG.is_t_design(return_parameters=True) # needs sage.combinat (True, (2, 31, 7, 7)) - sage: PG = designs.ProjectiveGeometryDesign(3, 1, GF(4)) - sage: PG.is_t_design(return_parameters=True) + sage: PG = designs.ProjectiveGeometryDesign(3, 1, GF(4)) # needs sage.combinat + sage: PG.is_t_design(return_parameters=True) # needs sage.combinat (True, (2, 85, 5, 1)) Check with ``F`` being a prime power:: @@ -707,6 +707,7 @@ def projective_plane(n, check=True, existence=False): EXAMPLES:: + sage: # needs sage.schemes sage: designs.projective_plane(2) (7,3,1)-Balanced Incomplete Block Design sage: designs.projective_plane(3) @@ -737,6 +738,7 @@ def projective_plane(n, check=True, existence=False): TESTS:: + sage: # needs sage.schemes sage: designs.projective_plane(2197, existence=True) True sage: designs.projective_plane(6, existence=True) @@ -816,6 +818,7 @@ def AffineGeometryDesign(n, d, F, point_coordinates=True, check=True): EXAMPLES:: + sage: # needs sage.combinat sage: BD = designs.AffineGeometryDesign(3, 1, GF(2)) sage: BD.is_t_design(return_parameters=True) (True, (2, 8, 2, 1)) @@ -934,12 +937,13 @@ def WittDesign(n): EXAMPLES:: - sage: BD = designs.WittDesign(9) # optional - gap_package_design - sage: BD.is_t_design(return_parameters=True) # optional - gap_package_design + sage: # optional - gap_package_design + sage: BD = designs.WittDesign(9) + sage: BD.is_t_design(return_parameters=True) (True, (2, 9, 3, 1)) - sage: BD # optional - gap_package_design + sage: BD Incidence structure with 9 points and 12 blocks - sage: print(BD) # optional - gap_package_design + sage: print(BD) Incidence structure with 9 points and 12 blocks """ libgap.load_package("design") @@ -957,16 +961,18 @@ def HadamardDesign(n): EXAMPLES:: - sage: designs.HadamardDesign(7) # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: designs.HadamardDesign(7) Incidence structure with 7 points and 7 blocks - sage: print(designs.HadamardDesign(7)) # needs sage.modules + sage: print(designs.HadamardDesign(7)) Incidence structure with 7 points and 7 blocks For example, the Hadamard 2-design with `n = 11` is a design whose parameters are `2-(11, 5, 2)`. We verify that `NJ = 5J` for this design. :: - sage: D = designs.HadamardDesign(11); N = D.incidence_matrix() # needs sage.modules - sage: J = matrix(ZZ, 11, 11, [1]*11*11); N*J # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: D = designs.HadamardDesign(11); N = D.incidence_matrix() + sage: J = matrix(ZZ, 11, 11, [1]*11*11); N*J [5 5 5 5 5 5 5 5 5 5 5] [5 5 5 5 5 5 5 5 5 5 5] [5 5 5 5 5 5 5 5 5 5 5] @@ -1010,7 +1016,8 @@ def Hadamard3Design(n): EXAMPLES:: - sage: designs.Hadamard3Design(12) # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: designs.Hadamard3Design(12) Incidence structure with 12 points and 22 blocks We verify that any two blocks of the Hadamard `3`-design `3-(8, 4, 1)` @@ -1020,9 +1027,10 @@ def Hadamard3Design(n): :: - sage: D = designs.Hadamard3Design(8) # needs sage.modules - sage: N = D.incidence_matrix() # needs sage.modules - sage: N.transpose()*N # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: D = designs.Hadamard3Design(8) + sage: N = D.incidence_matrix() + sage: N.transpose()*N [4 2 2 2 2 2 2 2 2 2 2 2 2 0] [2 4 2 2 2 2 2 2 2 2 2 2 0 2] [2 2 4 2 2 2 2 2 2 2 2 0 2 2] diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py new file mode 100644 index 00000000000..1596c708152 --- /dev/null +++ b/src/sage/combinat/designs/covering_array.py @@ -0,0 +1,52 @@ +r""" +Covering Arrays (CA) + +A Covering Array, denoted `CA(N;t,k,v)`, is an `N` by `k` array with +entries from a set of `v` elements with the property that in every +selection of `t` columns, every sequence of `t` elements appears in at +least one row. + +An Orthogonal Array, denoted `OA(N;t,k,v)` is a covering array with the +property that every sequence of `t`-elements appears in exactly one row. +(See :mod:`sage.combinat.designs.orthogonal_arrays`). + +This module collects methods relating to covering arrays, some of which +are inherited from orthogonal array methods. This module defines the +following functions: + +.. csv-table:: + :class: contentstable + :widths: 30, 70 + :delim: | + + :meth:`~sage.combinat.designs.designs_pyx.is_covering_array` | Check that an input list of lists is a `CA(N;t,k,v)`. + :meth:`~sage.combinat.designs.covering_array.CA_relabel` | Return a relabelled version of the CA. + :meth:`~sage.combinat.designs.covering_array.CA_standard_label` | Return a version of the CA relabelled to symbols `(0,\dots,n-1)`. + +REFERENCES: + +- [Colb2004]_ + +- [SMC2006]_ + +- [WC2007]_ + +AUTHORS: + +- Aaron Dwyer and brett stevens (2022): initial version + +""" + +# ********************************************************************** +# Copyright (C) 2022 Aaron Dwyer +# +# 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 .orthogonal_arrays import OA_relabel, OA_standard_label +CA_relabel = OA_relabel +CA_standard_label = OA_standard_label diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index d06578ccc22..b751df0a8eb 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -1466,8 +1466,8 @@ def OA_17_560(): sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array sage: from sage.combinat.designs.database import OA_17_560 - sage: OA = OA_17_560() # needs sage.rings.finite_rings - sage: is_orthogonal_array(OA,17,560,2) # needs sage.rings.finite_rings + sage: OA = OA_17_560() # needs sage.rings.finite_rings sage.schemes + sage: is_orthogonal_array(OA,17,560,2) # needs sage.rings.finite_rings sage.schemes True The design is available from the general constructor:: @@ -3846,13 +3846,13 @@ def DM_57_8_1(): sage: from sage.combinat.designs.designs_pyx import is_difference_matrix sage: from sage.combinat.designs.database import DM_57_8_1 - sage: G,M = DM_57_8_1() # needs sage.rings.finite_rings - sage: is_difference_matrix(M,G,8,1) # needs sage.rings.finite_rings + sage: G,M = DM_57_8_1() # needs sage.rings.finite_rings sage.schemes + sage: is_difference_matrix(M,G,8,1) # needs sage.rings.finite_rings sage.schemes True Can be obtained from the constructor:: - sage: _ = designs.difference_matrix(57,8) # needs sage.rings.finite_rings + sage: _ = designs.difference_matrix(57,8) # needs sage.rings.finite_rings sage.schemes """ M = orthogonal_array(8,8) M = [R for R in M if any(x != R[0] for x in R)] # removing the 0..0, 1..1, 7..7 rows. diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index 8bf7f14fd0b..26b899cb93d 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -118,4 +118,4 @@ 'OAMainFunctions', as_='orthogonal_arrays') lazy_import('sage.combinat.designs.gen_quadrangles_with_spread', - ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) + ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) \ No newline at end of file diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 565b7d83184..4b6638634f6 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -15,6 +15,201 @@ from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free from sage.misc.unknown import Unknown +def is_covering_array(array, strength=None, levels=None, verbose=False, parameters=False): + r""" + Check if the input is a covering array with given strength. + + See :mod:`sage.combinat.designs.covering_array` for a definition. + + INPUT: + + - ``array`` -- the Covering Array to be tested. + + - ``strength`` (integer) -- the parameter `t` of the covering array, + such that in any selection of `t` columns of the array, every `t` + -tuple appears at least once. If set to None then all t > 0 are + tested to and the maximal strength is used. + + - ``levels`` -- the number of symbols that appear in ``array``. + If set to None, then each unique entry in ``array`` is counted. + + - ``verbose`` (boolean) -- whether to display some information about + the covering array. + + - ``parameters`` (boolean) -- whether to return the parameters of + the Covering Array. If set to ``True``, the function returns a + pair ``(boolean_answer,(N,t,k,v))``. + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: C = [[1, 1, 1, 0], + ....: [1, 1, 0, 0], + ....: [0, 0, 0]] + sage: is_covering_array(C) + Traceback (most recent call last): + ... + ValueError: Not all rows are the same length, row 2 is not the same length as row 0 + + sage: C = [[0, 1, 1], + ....: [1, 1, 0], + ....: [1, 0, 1], + ....: [0, 0, 0,]] + sage: is_covering_array(C,strength=4) + Traceback (most recent call last): + ... + ValueError: Strength must be equal or less than number of columns + + sage: C = [[0, 1, 1], + ....: [1, 1, 1], + ....: [1, 0, 1]] + sage: is_covering_array(C,verbose=True) + A 3 by 3 Covering Array with strength 0 with entries from a symbol set of size 2 + True + + sage: C = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ....: [0, 0, 0, 0, 1, 1, 1, 1, 1, 1], + ....: [0, 1, 1, 1, 0, 0, 0, 1, 1, 1], + ....: [1, 0, 1, 1, 0, 1, 1, 0, 0, 1], + ....: [1, 1, 0, 1, 1, 0, 1, 0, 1, 0], + ....: [1, 1, 1, 0, 1, 1, 0, 1, 2, 0]] + sage: is_covering_array(C,levels=2) + Traceback (most recent call last): + ... + ValueError: Array should contain integer symbols from 0 to 1 + + sage: C = [[1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2], + ....: [1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2], + ....: [1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0], + ....: [0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1], + ....: [2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2], + ....: [1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2], + ....: [1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1], + ....: [2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2], + ....: [1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0], + ....: [0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2], + ....: [1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0], + ....: [0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0], + ....: [0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1], + ....: [2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1], + ....: [2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1], + ....: [2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0], + ....: [0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2], + ....: [1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1], + ....: [2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1], + ....: [2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2], + ....: [1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1], + ....: [2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0], + ....: [0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1], + ....: [2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0], + ....: [0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0], + ....: [0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2], + ....: [1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2], + ....: [1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0], + ....: [0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0], + ....: [0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1], + ....: [2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0], + ....: [0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1], + ....: [2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2], + ....: [1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1], + ....: [2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1], + ....: [2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2], + ....: [1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0], + ....: [0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1], + ....: [2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1], + ....: [2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1], + ....: [2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0], + ....: [0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0], + ....: [0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2], + ....: [1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0], + ....: [0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2], + ....: [1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1], + ....: [2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2], + ....: [1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2], + ....: [1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1], + ....: [2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0], + ....: [0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2], + ....: [1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2], + ....: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] + sage: is_covering_array(C,parameters=True) + (True, (53, 3, 13, 3)) + + sage: C = [[1, 0, 1, 1, 2, 0, 2, 2], + ....: [2, 1, 0, 1, 1, 2, 0, 2], + ....: [2, 2, 1, 0, 1, 1, 2, 0], + ....: [0, 2, 2, 1, 0, 1, 1, 2], + ....: [2, 0, 2, 2, 1, 0, 1, 1], + ....: [1, 2, 0, 2, 2, 1, 0, 1], + ....: [1, 1, 2, 0, 2, 2, 1, 0], + ....: [0, 1, 1, 2, 0, 2, 2, 1]] + sage: is_covering_array(C,strength=2,parameters=True) + (False, (8, 0, 8, 3)) + + """ + from itertools import product, combinations + + if levels is None: + symbol_list = list({x for l in array for x in l}) + levels = len(symbol_list) + else: + symbol_list = range(levels) + + number_rows = len(array) + number_columns = len(array[0]) + + for row in array: + if len(row) != number_columns: + raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(array.index(row))) + else: + for entry in row: + if int(entry) != entry or entry < -1 or entry >= levels: + raise ValueError("Array should contain integer symbols from 0 to {}".format(levels-1)) + + result = True + + # If strength t is inputted, check that for every selection of t + # columns, each v^t t-tuple is found in some row. + if strength: + if strength > number_columns: + raise ValueError("Strength must be equal or less than number of columns") + wstrength = strength + for comb in combinations(range(number_columns), wstrength): + existing_ttuples = set(tuple([row[ti] for ti in comb]) for row in array) + if len(existing_ttuples) != levels ** wstrength: + wstrength = 0 + result = False + break + + # If no strength t is inputted, starting at t=1 check all t until + # one of the v^t t-tuples does not appear. + else: + wstrength = 1 + finished = False + do_iterate = True + while finished is False: + for comb in combinations(range(number_columns), wstrength): + tuple_dictionary = {item: 0 for item in product(symbol_list, repeat=wstrength)} + for row in array: + tuple_dictionary[tuple([row[ti] for ti in comb])] += 1 + if 0 in tuple_dictionary.values(): + wstrength -= 1 + finished = True + break + elif do_iterate and any(value < levels for value in tuple_dictionary.values()): + do_iterate = False + finished = True + if finished is False and wstrength < number_columns and do_iterate: + wstrength += 1 + + if verbose: + print('A {} by {} Covering Array with strength {} with entries from a symbol set of size {}'.format(number_rows, number_columns, wstrength, levels)) + + if parameters: + return (result, (number_rows, wstrength, number_columns, levels)) + else: + return result + + def is_orthogonal_array(OA, int k, int n, int t=2, verbose=False, terminology="OA"): r""" Check that the integer matrix `OA` is an `OA(k,n,t)`. diff --git a/src/sage/combinat/designs/group_divisible_designs.py b/src/sage/combinat/designs/group_divisible_designs.py index e1d90155920..aee3bcc96cf 100644 --- a/src/sage/combinat/designs/group_divisible_designs.py +++ b/src/sage/combinat/designs/group_divisible_designs.py @@ -24,19 +24,20 @@ --------- """ -#***************************************************************************** +# **************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.arith.misc import is_prime_power -from sage.misc.unknown import Unknown +from sage.misc.unknown import Unknown from .incidence_structures import IncidenceStructure -def group_divisible_design(v,K,G,existence=False,check=False): + +def group_divisible_design(v, K, G, existence=False, check=False): r""" Return a `(v,K,G)`-Group Divisible Design. @@ -90,36 +91,31 @@ def group_divisible_design(v,K,G,existence=False,check=False): blocks = None # from a (v+1,k,1)-BIBD - if (len(G) == 1 and - len(K) == 1 and - G[0]+1 in K): + if len(G) == 1 == len(K) and G[0] + 1 in K: from .bibd import balanced_incomplete_block_design k = K[0] if existence: - return balanced_incomplete_block_design(v+1,k,existence=True) - BIBD = balanced_incomplete_block_design(v+1,k) + return balanced_incomplete_block_design(v + 1, k, existence=True) + BIBD = balanced_incomplete_block_design(v + 1, k) groups = [[x for x in S if x != v] for S in BIBD if v in S] - d = {p:i for i,p in enumerate(sum(groups,[]))} + d = {p: i for i, p in enumerate(sum(groups, []))} d[v] = v BIBD.relabel(d) - groups = [list(range((k-1)*i,(k-1)*(i+1))) for i in range(v//(k-1))] + groups = [list(range((k - 1) * i, (k - 1) * (i + 1))) + for i in range(v // (k - 1))] blocks = [S for S in BIBD if v not in S] # (v,{4},{2})-GDD - elif (v % 2 == 0 and - K == [4] and - G == [2] and - GDD_4_2(v//2,existence=True)): + elif (v % 2 == 0 and K == [4] and + G == [2] and GDD_4_2(v // 2, existence=True)): if existence: return True - return GDD_4_2(v//2,check=check) + return GDD_4_2(v // 2, check=check) # From a TD(k,g) - elif (len(G) == 1 and - len(K) == 1 and - K[0]*G[0] == v): + elif len(G) == 1 == len(K) and K[0] * G[0] == v: from .orthogonal_arrays import transversal_design - return transversal_design(k=K[0],n=G[0],existence=existence) + return transversal_design(k=K[0], n=G[0], existence=existence) if blocks: return GroupDivisibleDesign(v, @@ -134,7 +130,8 @@ def group_divisible_design(v,K,G,existence=False,check=False): return Unknown raise NotImplementedError -def GDD_4_2(q,existence=False,check=True): + +def GDD_4_2(q, existence=False, check=True): r""" Return a `(2q,\{4\},\{2\})`-GDD for `q` a prime power with `q\equiv 1\pmod{6}`. @@ -179,27 +176,28 @@ def GDD_4_2(q,existence=False,check=True): if existence: return True - from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF - G = GF(q,'x') + from sage.rings.finite_rings.finite_field_constructor import FiniteField + G = FiniteField(q, 'x') w = G.primitive_element() e = w**((q - 1) // 3) # A first parallel class is defined. G acts on it, which yields all others. - first_class = [[(0,0),(1,w**i),(1,e*w**i),(1,e*e*w**i)] + first_class = [[(0, 0), (1, w**i), (1, e * w**i), (1, e * e * w**i)] for i in range((q - 1) // 6)] - label = {p:i for i,p in enumerate(G)} - classes = [[[2*label[x[1]+g]+(x[0]+j) % 2 for x in S] + label = {p: i for i, p in enumerate(G)} + classes = [[[2 * label[x[1] + g] + (x[0] + j) % 2 for x in S] for S in first_class] for g in G for j in range(2)] - return GroupDivisibleDesign(2*q, - groups=[[i,i+1] for i in range(0,2*q,2)], - blocks=sum(classes,[]), - K=[4], - G=[2], - check=check, - copy=False) + return GroupDivisibleDesign(2 * q, + groups=[[i, i + 1] for i in range(0, 2 * q, 2)], + blocks=sum(classes, []), + K=[4], + G=[2], + check=check, + copy=False) + class GroupDivisibleDesign(IncidenceStructure): r""" @@ -257,13 +255,14 @@ class GroupDivisibleDesign(IncidenceStructure): With unspecified groups:: + sage: # needs sage.schemes sage: D = designs.transversal_design(4,3).relabel(list('abcdefghiklm'),inplace=False).blocks() sage: GDD = GroupDivisibleDesign('abcdefghiklm',None,D) sage: sorted(GDD.groups()) [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['k', 'l', 'm']] - """ - def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=True, copy=True,**kwds): + def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, + check=True, copy=True, **kwds): r""" Constructor function @@ -286,8 +285,7 @@ def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=True, check=False, **kwds) - if (groups is None or - (copy is False and self._point_to_index is None)): + if groups is None or (copy is False and self._point_to_index is None): self._groups = groups elif self._point_to_index is None: self._groups = [g[:] for g in groups] @@ -295,7 +293,9 @@ def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=True, self._groups = [[self._point_to_index[x] for x in g] for g in groups] if check or groups is None: - is_gdd = is_group_divisible_design(self._groups,self._blocks,self.num_points(),G,K,lambd,verbose=1) + is_gdd = is_group_divisible_design(self._groups, self._blocks, + self.num_points(), G, K, + lambd, verbose=1) assert is_gdd if groups is None: self._groups = is_gdd[1] @@ -321,8 +321,9 @@ def groups(self): Non-integer ground set:: - sage: TD=designs.transversal_design(5,5) - sage: TD.relabel({i:chr(97+i) for i in range(25)}) + sage: # needs sage.schemes + sage: TD = designs.transversal_design(5,5) + sage: TD.relabel({i: chr(97+i) for i in range(25)}) sage: TD.groups() [['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h', 'i', 'j'], @@ -337,7 +338,7 @@ def groups(self): def __repr__(self): r""" - Returns a string that describes self + Return a string that describes ``self``. EXAMPLES:: @@ -347,11 +348,10 @@ def __repr__(self): sage: GDD = GroupDivisibleDesign(40,groups,TD); GDD Group Divisible Design on 40 points of type 10^4 """ + group_sizes = [len(g) for g in self._groups] - group_sizes = [len(_) for _ in self._groups] - - gdd_type = ["{}^{}".format(s,group_sizes.count(s)) - for s in sorted(set(group_sizes))] + gdd_type = ("{}^{}".format(s, group_sizes.count(s)) + for s in sorted(set(group_sizes))) gdd_type = ".".join(gdd_type) if not gdd_type: @@ -359,4 +359,4 @@ def __repr__(self): v = self.num_points() - return "Group Divisible Design on {} points of type {}".format(v,gdd_type) + return "Group Divisible Design on {} points of type {}".format(v, gdd_type) diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py index e2dc0a17278..46aada66a6e 100644 --- a/src/sage/combinat/designs/incidence_structures.py +++ b/src/sage/combinat/designs/incidence_structures.py @@ -357,18 +357,18 @@ def __contains__(self, block): sage: str="I had a dream of a time when a 3-lines patch does not kill one hour" sage: sets = Subsets(str.split(), 4) - sage: IS = IncidenceStructure(sets) # a complete 4-uniform hypergraph + sage: IS = IncidenceStructure(sets) # a complete 4-uniform hypergraph sage: ["I", "dream", "of", "one"] in IS True sage: ["does", "patch", "kill", "dream"] in IS True sage: ["Am", "I", "finally", "done ?"] in IS False - sage: IS = designs.ProjectiveGeometryDesign(3, 1, GF(2), # needs sage.rings.finite_rings + sage: IS = designs.ProjectiveGeometryDesign(3, 1, GF(2), # needs sage.combinat ....: point_coordinates=False) - sage: [3,8,7] in IS # needs sage.rings.finite_rings + sage: [3,8,7] in IS # needs sage.combinat True - sage: [3,8,9] in IS + sage: [3,8,9] in IS # needs sage.combinat False """ try: @@ -1513,10 +1513,10 @@ def is_t_design(self, t=None, v=None, k=None, l=None, return_parameters=False): sage: BD.is_t_design(0,6,3,7) or BD.is_t_design(0,7,4,7) or BD.is_t_design(0,7,3,8) False - sage: BD = designs.AffineGeometryDesign(3, 1, GF(2)) # needs sage.rings.finite_rings - sage: BD.is_t_design(1) + sage: BD = designs.AffineGeometryDesign(3, 1, GF(2)) # needs sage.combinat + sage: BD.is_t_design(1) # needs sage.combinat True - sage: BD.is_t_design(2) + sage: BD.is_t_design(2) # needs sage.combinat True Steiner triple and quadruple systems are other names for `2-(v,3,1)` and @@ -1538,13 +1538,14 @@ def is_t_design(self, t=None, v=None, k=None, l=None, return_parameters=False): Some examples of Witt designs that need the gap database:: - sage: BD = designs.WittDesign(9) # optional - gap_package_design - sage: BD.is_t_design(2,9,3,1) # optional - gap_package_design + sage: # optional - gap_package_design + sage: BD = designs.WittDesign(9) + sage: BD.is_t_design(2,9,3,1) True - sage: W12 = designs.WittDesign(12) # optional - gap_package_design - sage: W12.is_t_design(5,12,6,1) # optional - gap_package_design + sage: W12 = designs.WittDesign(12) + sage: W12.is_t_design(5,12,6,1) True - sage: W12.is_t_design(4) # optional - gap_package_design + sage: W12.is_t_design(4) True Further examples:: @@ -1924,8 +1925,8 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, sage: TD.is_resolvable() True - sage: AG = designs.AffineGeometryDesign(3,1,GF(2)) # needs sage.rings.finite_rings - sage: AG.is_resolvable() # needs sage.rings.finite_rings + sage: AG = designs.AffineGeometryDesign(3,1,GF(2)) # needs sage.combinat + sage: AG.is_resolvable() # needs sage.combinat True Their classes:: @@ -1936,10 +1937,11 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, sage: cls # random [[[0, 3], [1, 2]], [[1, 3], [0, 2]]] - sage: b, cls = AG.is_resolvable(True) # needs sage.rings.finite_rings + sage: # needs sage.combinat + sage: b, cls = AG.is_resolvable(True) sage: b True - sage: cls # random + sage: cls # random [[[6, 7], [4, 5], [0, 1], [2, 3]], [[5, 7], [0, 4], [3, 6], [1, 2]], [[0, 2], [4, 7], [1, 3], [5, 6]], @@ -1958,9 +1960,10 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, TESTS:: - sage: _, cls1 = AG.is_resolvable(certificate=True) # needs sage.rings.finite_rings - sage: _, cls2 = AG.is_resolvable(certificate=True) # needs sage.rings.finite_rings - sage: cls1 is cls2 # needs sage.rings.finite_rings + sage: # needs sage.combinat + sage: _, cls1 = AG.is_resolvable(certificate=True) + sage: _, cls2 = AG.is_resolvable(certificate=True) + sage: cls1 is cls2 False """ if self._classes is None: diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index c4936f79853..b819d96c1db 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings sage.schemes r""" Orthogonal arrays (OA) @@ -35,6 +35,7 @@ :meth:`TD_product` | Return the product of two transversal designs. :meth:`OA_find_disjoint_blocks` | Return `x` disjoint blocks contained in a given `OA(k,n)`. :meth:`OA_relabel` | Return a relabelled version of the OA. + :meth:`OA_standard_label` | Return a version of the OA relabelled to symbols `(0,\dots,n-1)`. :meth:`OA_from_quasi_difference_matrix` | Return an Orthogonal Array from a Quasi-Difference matrix :meth:`OA_from_Vmt` | Return an Orthogonal Array from a `V(m,t)` :meth:`OA_from_PBD` | Return an `OA(k,n)` from a PBD @@ -476,6 +477,7 @@ def is_transversal_design(B, k, n, verbose=False): """ return is_orthogonal_array([[x % n for x in R] for R in B],k,n,verbose=verbose) + def wilson_construction(OA,k,r,m,u,check=True,explain_construction=False): r""" Returns a `OA(k,rm+\sum_i u_i)` from a truncated `OA(k+s,r)` by Wilson's @@ -681,6 +683,7 @@ def wilson_construction(OA,k,r,m,u,check=True,explain_construction=False): return OA + def TD_product(k,TD1,n1,TD2,n2, check=True): r""" Return the product of two transversal designs. @@ -729,6 +732,7 @@ def TD_product(k,TD1,n1,TD2,n2, check=True): return TD + def orthogonal_array(k,n,t=2,resolvable=False, check=True,existence=False,explain_construction=False): r""" Return an orthogonal array of parameters `k,n,t`. @@ -1010,6 +1014,7 @@ def orthogonal_array(k,n,t=2,resolvable=False, check=True,existence=False,explai return OA + def largest_available_k(n,t=2): r""" Return the largest `k` such that Sage can build an `OA(k,n)`. @@ -1059,6 +1064,7 @@ def largest_available_k(n,t=2): k += 1 return k + def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): r""" Return an `OA(k,n)-\sum_{1\leq i\leq x} OA(k,s_i)`. @@ -1401,6 +1407,7 @@ def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): return OA + def OA_find_disjoint_blocks(OA, k, n, x, *, solver=None, integrality_tolerance=1e-3): r""" @@ -1469,7 +1476,8 @@ def OA_find_disjoint_blocks(OA, k, n, x, independent_set = [OA[i] for i,v in b.items() if v] return independent_set -def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): + +def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): r""" Return a relabelled version of the OA. @@ -1498,6 +1506,11 @@ def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): If set to ``None`` (default) no such relabelling is performed. + - ``symbol_list`` -- a list of the desired symbols for the + relabelled OA. If this is not ``None``, the same relabelling is + done on all blocks such that the index of an element in + symbol_list is its preimage in the relabelling map. + .. NOTE:: A ``None`` coordinate in one block remains a ``None`` @@ -1516,6 +1529,10 @@ def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): sage: is_transversal_design(TD,3,2) True + sage: OA = designs.orthogonal_arrays.build(3,2) + sage: OA_relabel(OA, 3, 2, symbol_list=['A', 'B']) + [['A', 'A', 'A'], ['A', 'B', 'B'], ['B', 'A', 'B'], ['B', 'B', 'A']] + Making sure that ``[2,2,2,2]`` is a block of `OA(4,3)`. We do this by relabelling block ``[0,0,0,0]`` which belongs to the design:: @@ -1545,8 +1562,38 @@ def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): if matrix: OA = [[matrix[i][j] if j is not None else None for i,j in enumerate(R)] for R in OA] + if symbol_list: + mapping = {index: symbol for index, symbol in enumerate(symbol_list)} + OA = [[mapping[element] for element in row] for row in OA] return OA + +def OA_standard_label(OA): + r""" + Return the inputted OA with entries relabelled as integers [0,...,n-1]. + + INPUT: + + - ``OA`` -- a list of lists with symbols as entries that are not + necessarily integers. + + EXAMPLES:: + + sage: from sage.combinat.designs.orthogonal_arrays import OA_standard_label + sage: C = [['a', 'a', 'a', 'b'], + ....: ['a', 'a', 'b', 'a'], + ....: ['a', 'b', 'a', 'a'], + ....: ['b', 'a', 'a', 'a'], + ....: ['b', 'b', 'b', 'b']] + sage: OA_standard_label(C) + [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0], [1, 1, 1, 1]] + + """ + symbol_list = sorted({x for l in OA for x in l}) + mapping = {symbol: index for index, symbol in enumerate(symbol_list)} + return [[mapping[element] for element in row] for row in OA] + + def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): r""" Return an `OA(k, |G| \cdot 2^c)` from a constrained `(G,k-1,2)`-difference @@ -1705,6 +1752,7 @@ def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): Mb = [[e+GG((G.zero(),x*v)) for v in H for e in R] for x, R in zip(Y, A)] return OA_from_quasi_difference_matrix(list(zip(*Mb)),GG,add_col=True) + def OA_from_quasi_difference_matrix(M,G,add_col=True,fill_hole=True): r""" Return an Orthogonal Array from a Quasi-Difference matrix @@ -1824,6 +1872,7 @@ def OA_from_quasi_difference_matrix(M,G,add_col=True,fill_hole=True): return new_M + def OA_from_Vmt(m,t,V): r""" Return an Orthogonal Array from a `V(m,t)` @@ -1911,6 +1960,7 @@ def QDM_from_Vmt(m,t,V): return Fq, M + def OA_from_PBD(k,n,PBD, check=True): r""" Return an `OA(k,n)` from a PBD @@ -1993,6 +2043,7 @@ def OA_from_PBD(k,n,PBD, check=True): return OA + def OA_from_wider_OA(OA,k): r""" Return the first `k` columns of `OA`. diff --git a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py index 1f434d49494..56f7cbc3bac 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py +++ b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py @@ -64,8 +64,8 @@ def construction_3_3(k,n,m,i,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_3 sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_3 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array - sage: k=11;n=177 - sage: is_orthogonal_array(construction_3_3(*find_construction_3_3(k,n)[1]),k,n,2) + sage: k = 11; n = 177 + sage: is_orthogonal_array(construction_3_3(*find_construction_3_3(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(9,91)) @@ -134,8 +134,8 @@ def construction_3_4(k,n,m,r,s,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_4 sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_4 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array - sage: k=8;n=196 - sage: is_orthogonal_array(construction_3_4(*find_construction_3_4(k,n)[1]),k,n,2) + sage: k = 8; n = 196 + sage: is_orthogonal_array(construction_3_4(*find_construction_3_4(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(8,164)) @@ -210,7 +210,7 @@ def construction_3_5(k,n,m,r,s,t,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_5 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array sage: k=8;n=111 - sage: is_orthogonal_array(construction_3_5(*find_construction_3_5(k,n)[1]),k,n,2) + sage: is_orthogonal_array(construction_3_5(*find_construction_3_5(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(8,90)) @@ -302,7 +302,7 @@ def construction_3_6(k,n,m,i,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_6 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array sage: k=8;n=95 - sage: is_orthogonal_array(construction_3_6(*find_construction_3_6(k,n)[1]),k,n,2) + sage: is_orthogonal_array(construction_3_6(*find_construction_3_6(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(10,756)) @@ -497,7 +497,7 @@ def construction_q_x(k, q, x, check=True, explain_construction=False): EXAMPLES:: sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_q_x - sage: _ = construction_q_x(9,16,6) + sage: _ = construction_q_x(9,16,6) # needs sage.schemes sage: print(designs.orthogonal_arrays.explain_construction(9,158)) (q-x)-construction with q=16,x=6 from: @@ -650,11 +650,11 @@ def thwart_lemma_3_5(k,n,m,a,b,c,d=0,complement=False,explain_construction=False sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import thwart_lemma_3_5 sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array - sage: OA = thwart_lemma_3_5(6,23,7,5,7,8) - sage: is_orthogonal_array(OA,6,23*7+5+7+8,2) + sage: OA = thwart_lemma_3_5(6,23,7,5,7,8) # needs sage.schemes + sage: is_orthogonal_array(OA,6,23*7+5+7+8,2) # needs sage.schemes True - sage: print(designs.orthogonal_arrays.explain_construction(10,408)) + sage: print(designs.orthogonal_arrays.explain_construction(10,408)) # needs sage.schemes Lemma 4.1 with n=13,m=28 from: Charles J.Colbourn, Jeffrey H. Dinitz, Mieczyslaw Wojtas, Thwarts in transversal designs, @@ -784,7 +784,7 @@ def thwart_lemma_4_1(k,n,m,explain_construction=False): EXAMPLES:: - sage: print(designs.orthogonal_arrays.explain_construction(10,408)) + sage: print(designs.orthogonal_arrays.explain_construction(10,408)) # needs sage.schemes Lemma 4.1 with n=13,m=28 from: Charles J.Colbourn, Jeffrey H. Dinitz, Mieczyslaw Wojtas, Thwarts in transversal designs, @@ -960,25 +960,21 @@ def three_factor_product(k,n1,n2,n3,check=False,explain_construction=False): EXAMPLES:: + sage: # needs sage.schemes sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import three_factor_product - sage: OA = three_factor_product(4,4,4,4) sage: is_orthogonal_array(OA,5,64) True - sage: OA = three_factor_product(4,3,4,5) sage: is_orthogonal_array(OA,5,60) True - sage: OA = three_factor_product(5,4,5,7) sage: is_orthogonal_array(OA,6,140) True - sage: OA = three_factor_product(9,8,9,9) # long time sage: is_orthogonal_array(OA,10,8*9*9) # long time True - sage: print(designs.orthogonal_arrays.explain_construction(10,648)) Three-factor product with n=8.9.9 from: Peter J. Dukes, Alan C.H. Ling, diff --git a/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx b/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx index 1843cbe00e8..066eecb9197 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +++ b/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings sage.schemes # cython: cdivision=True r""" Orthogonal arrays (find recursive constructions) diff --git a/src/sage/combinat/designs/resolvable_bibd.py b/src/sage/combinat/designs/resolvable_bibd.py index 4af0bed4bb6..347a6a4d27b 100644 --- a/src/sage/combinat/designs/resolvable_bibd.py +++ b/src/sage/combinat/designs/resolvable_bibd.py @@ -140,6 +140,7 @@ def resolvable_balanced_incomplete_block_design(v,k,existence=False): return Unknown raise NotImplementedError("I don't know how to build a ({},{},1)-RBIBD!".format(v,3)) + def kirkman_triple_system(v,existence=False): r""" Return a Kirkman Triple System on `v` points. @@ -180,7 +181,7 @@ def kirkman_triple_system(v,existence=False): TESTS:: - sage: for i in range(3,300,6): + sage: for i in range(3,300,6): # needs sage.combinat ....: _ = designs.kirkman_triple_system(i) """ if v % 6 != 3: @@ -437,6 +438,7 @@ def v_4_1_rbibd(v,existence=False): assert BIBD.is_resolvable() return BIBD + def PBD_4_7(v,check=True, existence=False): r""" Return a `(v,\{4,7\})`-PBD @@ -458,7 +460,7 @@ def PBD_4_7(v,check=True, existence=False): All values `\leq 300`:: - sage: for i in range(1,300,3): + sage: for i in range(1,300,3): # needs sage.schemes ....: if i not in [10,19,31]: ....: assert PBD_4_7(i,existence=True) is True ....: _ = PBD_4_7(i,check=True) @@ -683,6 +685,7 @@ def PBD_4_7(v,check=True, existence=False): check=check, copy=False) + def PBD_4_7_from_Y(gdd,check=True): r""" Return a `(3v+1,\{4,7\})`-PBD from a `(v,\{4,5,7\},\NN-\{3,6,10\})`-GDD. @@ -711,16 +714,16 @@ def PBD_4_7_from_Y(gdd,check=True): EXAMPLES:: sage: from sage.combinat.designs.resolvable_bibd import PBD_4_7_from_Y - sage: PBD_4_7_from_Y(designs.transversal_design(7,8)) + sage: PBD_4_7_from_Y(designs.transversal_design(7,8)) # needs sage.schemes Pairwise Balanced Design on 169 points with sets of sizes in [4, 7] TESTS:: - sage: PBD_4_7_from_Y(designs.balanced_incomplete_block_design(10,10)) + sage: PBD_4_7_from_Y(designs.balanced_incomplete_block_design(10,10)) # needs sage.schemes Traceback (most recent call last): ... ValueError: The GDD should only contain blocks of size {4,5,7} but there are other: [10] - sage: PBD_4_7_from_Y(designs.transversal_design(4,3)) + sage: PBD_4_7_from_Y(designs.transversal_design(4,3)) # needs sage.schemes Traceback (most recent call last): ... RuntimeError: A group has size 3 but I do not know how to build a (10,[4,7])-PBD diff --git a/src/sage/combinat/designs/twographs.py b/src/sage/combinat/designs/twographs.py index 5c9a90afbcd..54d684cb9d2 100644 --- a/src/sage/combinat/designs/twographs.py +++ b/src/sage/combinat/designs/twographs.py @@ -59,6 +59,7 @@ from sage.combinat.designs.incidence_structures import IncidenceStructure from itertools import combinations + class TwoGraph(IncidenceStructure): r""" Two-graphs class. @@ -199,9 +200,10 @@ def taylor_twograph(q): from sage.graphs.generators.classical_geometries import TaylorTwographSRG return TaylorTwographSRG(q).twograph() -def is_twograph(T): + +def is_twograph(T) -> bool: r""" - Checks that the incidence system `T` is a two-graph + Check whether the incidence system `T` is a two-graph. INPUT: @@ -237,7 +239,7 @@ def is_twograph(T): return False # A structure for a fast triple existence check - v_to_blocks = {v:set() for v in range(T.num_points())} + v_to_blocks = {v: set() for v in range(T.num_points())} for B in T._blocks: B = frozenset(B) for x in B: @@ -248,8 +250,8 @@ def has_triple(x_y_z): return bool(v_to_blocks[x] & v_to_blocks[y] & v_to_blocks[z]) # Check that every quadruple contains an even number of triples - for quad in combinations(range(T.num_points()),4): - if sum(map(has_triple,combinations(quad,3))) % 2 == 1: + for quad in combinations(range(T.num_points()), 4): + if sum(map(has_triple, combinations(quad, 3))) % 2 == 1: return False return True @@ -296,10 +298,10 @@ def twograph_descendant(G, v, name=None): sage: twograph_descendant(p, 5, name=True) descendant of Petersen graph at 5: Graph on 9 vertices """ - G = G.seidel_switching(G.neighbors(v),inplace=False) + G = G.seidel_switching(G.neighbors(v), inplace=False) G.delete_vertex(v) if name: - G.name('descendant of '+G.name()+' at '+str(v)) + G.name('descendant of ' + G.name() + ' at ' + str(v)) else: G.name('') return G diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 693b8dfe269..11d96acced8 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Diagram and Partition Algebras diff --git a/src/sage/combinat/dlx.py b/src/sage/combinat/dlx.py index d243abbc9c2..25990fe55fe 100644 --- a/src/sage/combinat/dlx.py +++ b/src/sage/combinat/dlx.py @@ -237,7 +237,7 @@ def _constructmatrix(self, ones, initialsolution=None): for r in ones: curRow = r[0] # row index columns = r[1] # column indexes - if not(columns): + if not (columns): continue columns.sort() diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index cb6e5607931..72cff3d147b 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Substitutions over unit cube faces (Rauzy fractals) @@ -287,7 +288,7 @@ def __init__(self, v, t, color=None): self._vector = (ZZ**len(v))(v) self._vector.set_immutable() - if not((t in ZZ) and 1 <= t <= len(v)): + if not ((t in ZZ) and 1 <= t <= len(v)): raise ValueError('the type must be an integer between 1 and len(v)') self._type = t @@ -1418,8 +1419,8 @@ def __init__(self, sigma, method='suffix'): raise ValueError("the substitution (%s) must be unimodular" % sigma) first_letter = sigma.codomain().alphabet()[0] - if not (first_letter in ZZ) or (first_letter < 1): - raise ValueError("the substitution (%s) must be defined on positive integers" % sigma) + if first_letter not in ZZ or first_letter < 1: + raise ValueError(f"the substitution ({sigma}) must be defined on positive integers") self._sigma = WordMorphism(sigma) self._d = self._sigma.domain().alphabet().cardinality() diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 494e8154c80..9a1d4bb892c 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.graphs sage.modules r""" Finite state machines, automata, transducers @@ -1563,7 +1563,7 @@ def is_final(self): sage: A.is_final False """ - return (self.final_word_out is not None) + return self.final_word_out is not None @is_final.setter def is_final(self, is_final): @@ -9614,7 +9614,7 @@ def find_final_word_out(state): return final_word_out for state in self.iter_states(): - assert(not in_progress) + assert not in_progress # trailing_letters is an infinite iterator additionally # marking positions trailing_letters = itertools.cycle(enumerate(letters)) diff --git a/src/sage/combinat/finite_state_machine_generators.py b/src/sage/combinat/finite_state_machine_generators.py index b5b8abbbd9e..24d027c03d0 100644 --- a/src/sage/combinat/finite_state_machine_generators.py +++ b/src/sage/combinat/finite_state_machine_generators.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.graphs sage.modules r""" Common Automata and Transducers (Finite State Machines Generators) diff --git a/src/sage/combinat/fqsym.py b/src/sage/combinat/fqsym.py index 03c53e6520b..48780725faa 100644 --- a/src/sage/combinat/fqsym.py +++ b/src/sage/combinat/fqsym.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Free Quasi-symmetric functions diff --git a/src/sage/combinat/free_dendriform_algebra.py b/src/sage/combinat/free_dendriform_algebra.py index 1bdcd1dbe31..fb1cb498c79 100644 --- a/src/sage/combinat/free_dendriform_algebra.py +++ b/src/sage/combinat/free_dendriform_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Free Dendriform Algebras diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 5c196c6cbf4..2ad7845f0a5 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1349,9 +1349,9 @@ def __classcall_private__(cls, modules, **options): sage: T in Modules(ZZ).FiniteDimensional() True """ - assert(len(modules) > 0) + assert (len(modules) > 0) R = modules[0].base_ring() - assert(all(module in ModulesWithBasis(R)) for module in modules) + assert (all(module in ModulesWithBasis(R)) for module in modules) # should check the base ring # flatten the list of modules so that tensor(A, tensor(B,C)) gets rewritten into tensor(A, B, C) modules = sum([module._sets if isinstance(module, CombinatorialFreeModule_Tensor) else (module,) for module in modules], ()) @@ -1572,8 +1572,8 @@ def tensor_constructor(self, modules): + B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6] + 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6] """ - assert(module in ModulesWithBasis(self.base_ring()) for module in modules) - assert(tensor(modules) == self) + assert (module in ModulesWithBasis(self.base_ring()) for module in modules) + assert (tensor(modules) == self) # a list l such that l[i] is True if modules[i] is readily a tensor product is_tensor = [isinstance(module, CombinatorialFreeModule_Tensor) for module in modules] # the tensor_constructor, on basis elements @@ -1772,9 +1772,9 @@ def __init__(self, modules, **options): Free module generated by {2, 4, 5} over Integer Ring (+) Free module generated by {2, 4, 7} over Integer Ring sage: TestSuite(C).run() """ - assert(len(modules)) # TODO: generalize to a family or tuple + assert (len(modules)) # TODO: generalize to a family or tuple R = modules[0].base_ring() - assert(all(module in ModulesWithBasis(R)) for module in modules) + assert (all(module in ModulesWithBasis(R)) for module in modules) # should check the base ring self._sets = modules CombinatorialFreeModule.__init__(self, R, diff --git a/src/sage/combinat/free_prelie_algebra.py b/src/sage/combinat/free_prelie_algebra.py index 2354cbbe576..965c459720c 100644 --- a/src/sage/combinat/free_prelie_algebra.py +++ b/src/sage/combinat/free_prelie_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Free Pre-Lie Algebras diff --git a/src/sage/combinat/fully_commutative_elements.py b/src/sage/combinat/fully_commutative_elements.py index 79237fefe42..200b98b2f36 100644 --- a/src/sage/combinat/fully_commutative_elements.py +++ b/src/sage/combinat/fully_commutative_elements.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fully commutative elements of Coxeter groups diff --git a/src/sage/combinat/fully_packed_loop.py b/src/sage/combinat/fully_packed_loop.py index de1bf3e5269..ca4bf09b1b0 100644 --- a/src/sage/combinat/fully_packed_loop.py +++ b/src/sage/combinat/fully_packed_loop.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fully packed loops diff --git a/src/sage/combinat/grossman_larson_algebras.py b/src/sage/combinat/grossman_larson_algebras.py index 8fcf8a2e5ec..db2f1de5eca 100644 --- a/src/sage/combinat/grossman_larson_algebras.py +++ b/src/sage/combinat/grossman_larson_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Grossman-Larson Hopf Algebras diff --git a/src/sage/combinat/growth.py b/src/sage/combinat/growth.py index cf8d18c1764..86d5070a590 100644 --- a/src/sage/combinat/growth.py +++ b/src/sage/combinat/growth.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs r""" Growth diagrams and dual graded graphs diff --git a/src/sage/combinat/hall_polynomial.py b/src/sage/combinat/hall_polynomial.py index 19d65bc2263..9d2326e60f8 100644 --- a/src/sage/combinat/hall_polynomial.py +++ b/src/sage/combinat/hall_polynomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hall Polynomials """ diff --git a/src/sage/combinat/integer_lists/base.pyx b/src/sage/combinat/integer_lists/base.pyx index 91b372d2392..c39937c3ac6 100644 --- a/src/sage/combinat/integer_lists/base.pyx +++ b/src/sage/combinat/integer_lists/base.pyx @@ -163,7 +163,7 @@ cdef class IntegerListsBackend(): left.floor == right.floor and left.ceiling == right.ceiling) if equal: - return (op == Py_EQ or op == Py_LE or op == Py_GE) + return op == Py_EQ or op == Py_LE or op == Py_GE if op == Py_EQ: return False if op == Py_NE: @@ -481,7 +481,7 @@ cdef class Envelope(): left.min_slope == right.min_slope and left.max_slope == right.max_slope) if equal: - return (op == Py_EQ or op == Py_LE or op == Py_GE) + return op == Py_EQ or op == Py_LE or op == Py_GE if op == Py_EQ: return False if op == Py_NE: diff --git a/src/sage/combinat/integer_matrices.py b/src/sage/combinat/integer_matrices.py index 75e8e896db8..8d737c64349 100644 --- a/src/sage/combinat/integer_matrices.py +++ b/src/sage/combinat/integer_matrices.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Counting, generating, and manipulating non-negative integer matrices diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 8503bd978c5..996d73a5efa 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -1,4 +1,4 @@ -# optional - sage.combinat sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Integer vectors modulo the action of a permutation group """ @@ -27,7 +27,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): r""" - Returns an enumerated set containing integer vectors which are + Return an enumerated set containing integer vectors which are maximal in their orbit under the action of the permutation group ``G`` for the lexicographic order. @@ -137,7 +137,9 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): [[6, 0, 0], [5, 1, 0], [5, 0, 1], [4, 2, 0], [4, 1, 1], [4, 0, 2], [3, 3, 0], [3, 2, 1], [3, 1, 2], [2, 2, 2]] sage: I.category() - Join of Category of finite enumerated sets and Category of subquotients of finite sets and Category of quotients of sets + Join of Category of finite enumerated sets + and Category of subquotients of finite sets + and Category of quotients of sets To get the orbit of any integer vector `v` under the action of the group, use the method :meth:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup_All.orbit`; @@ -156,9 +158,9 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): Let us check that canonical integer vectors of the symmetric group are just sorted list of integers:: - sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time - sage: p = iter(I) # long time - sage: for i in range(100): # long time + sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time + sage: p = iter(I) # long time + sage: for i in range(100): # long time ....: v = list(next(p)) ....: assert sorted(v, reverse=True) == v @@ -166,8 +168,8 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): symmetric group `S_n` whose entries sum to `d` than partitions of `d` of at most `n` parts:: - sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time - sage: for i in range(10): # long time + sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time + sage: for i in range(10): # long time ....: d1 = I.subset(i).cardinality() ....: d2 = Partitions(i, max_length=5).cardinality() ....: print(d1) @@ -187,11 +189,12 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): group ``G`` acting on a list of length `n`, all integer vectors of length `n` are canonical:: - sage: G = PermutationGroup([[(6,)]]) # long time - sage: G.cardinality() # long time + sage: # long time + sage: G = PermutationGroup([[(6,)]]) + sage: G.cardinality() 1 - sage: I = IntegerVectorsModPermutationGroup(G) # long time - sage: for i in range(10): # long time + sage: I = IntegerVectorsModPermutationGroup(G) + sage: for i in range(10): ....: d1 = I.subset(i).cardinality() ....: d2 = IntegerVectors(i,6).cardinality() ....: print(d1) @@ -225,9 +228,9 @@ def __classcall__(cls, G, sum=None, max_part=None, sgs=None): return IntegerVectorsModPermutationGroup_All(G, sgs=sgs) else: if sum is not None: - assert (sum == NN(sum)) + assert sum == NN(sum) if max_part is not None: - assert (max_part == NN(max_part)) + assert max_part == NN(max_part) return IntegerVectorsModPermutationGroup_with_constraints(G, sum, max_part, sgs=sgs) @@ -245,9 +248,9 @@ class IntegerVectorsModPermutationGroup_All(UniqueRepresentation, RecursivelyEnu EXAMPLES:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])) - sage: I - Integer vectors of length 4 enumerated up to the action of Permutation Group with generators [(1,2,3,4)] + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])); I + Integer vectors of length 4 enumerated up to the action of + Permutation Group with generators [(1,2,3,4)] sage: I.cardinality() +Infinity sage: TestSuite(I).run() @@ -274,7 +277,8 @@ def __init__(self, G, sgs=None): sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])) sage: I - Integer vectors of length 4 enumerated up to the action of Permutation Group with generators [(1,2,3,4)] + Integer vectors of length 4 enumerated up to the action of + Permutation Group with generators [(1,2,3,4)] sage: I.category() Category of infinite enumerated quotients of sets sage: TestSuite(I).run() @@ -575,10 +579,13 @@ class IntegerVectorsModPermutationGroup_with_constraints(UniqueRepresentation, R EXAMPLES:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=1) + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=1) sage: I.list() - [[0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 0], [1, 1, 1, 1]] - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=6, max_part=4) + [[0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 0], + [1, 1, 1, 1]] + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=6, max_part=4) sage: I.list() [[4, 2, 0, 0], [4, 1, 1, 0], [4, 1, 0, 1], [4, 0, 2, 0], [4, 0, 1, 1], [4, 0, 0, 2], [3, 3, 0, 0], [3, 2, 1, 0], [3, 2, 0, 1], [3, 1, 2, 0], @@ -641,7 +648,9 @@ def _repr_(self): def roots(self): r""" - Returns the root of generation of ``self``.This method is + Return the root of generation of ``self``. + + This method is required to build the tree structure of ``self`` which inherits from the class :class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`. @@ -656,7 +665,9 @@ def roots(self): def children(self, x): r""" - Returns the list of children of the element ``x``. This method + Return the list of children of the element ``x``. + + This method is required to build the tree structure of ``self`` which inherits from the class :class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`. @@ -671,7 +682,7 @@ def children(self, x): def permutation_group(self): r""" - Returns the permutation group given to define ``self``. + Return the permutation group given to define ``self``. EXAMPLES:: @@ -766,7 +777,7 @@ def __iter__(self): def is_canonical(self, v, check=True): r""" - Returns ``True`` if the integer list ``v`` is maximal in its + Return ``True`` if the integer list ``v`` is maximal in its orbit under the action of the permutation group given to define ``self``. Such integer vectors are said to be canonical. A vector `v` is canonical if and only if @@ -777,7 +788,8 @@ def is_canonical(self, v, check=True): EXAMPLES:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=3) + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=3) sage: I.is_canonical([3,0,0,0]) True sage: I.is_canonical([1,0,2,0]) @@ -798,11 +810,16 @@ def ambient(self): EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6); S.ambient() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6) + sage: S.ambient() Integer vectors that sum to 6 - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=12); S.ambient() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: 6, max_part=12) + sage: S.ambient() Integer vectors that sum to 6 with constraints: max_part=12 - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=12); S.ambient() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=12) + sage: S.ambient() Integer vectors with constraints: max_part=12 """ if self._sum is not None: @@ -819,12 +836,14 @@ def lift(self, elt): EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=1) + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=1) sage: v = S.lift([1,0,1,0]); v [1, 0, 1, 0] sage: v in IntegerVectors(2,4,max_part=1) True - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=6) + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=6) sage: v = S.lift(S.list()[5]); v [4, 1, 1, 0] sage: v in IntegerVectors(n=6) @@ -847,7 +866,8 @@ def retract(self, elt): EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=2, max_part=1) + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=2, max_part=1) sage: S.retract([1,1,0,0]) [1, 1, 0, 0] sage: S.retract([1,0,1,0]) @@ -873,22 +893,35 @@ def retract(self, elt): def an_element(self): r""" - Returns an element of ``self`` or raises an EmptySetError when - ``self`` is empty. + Return an element of ``self``. + + Raises an :class:`EmptySetError` when ``self`` is empty. EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=0, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=0, max_part=1) + sage: S.an_element() [0, 0, 0, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=1, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=1, max_part=1) + sage: S.an_element() [1, 0, 0, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=2, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=2, max_part=1) + sage: S.an_element() [1, 1, 0, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=3, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=3, max_part=1) + sage: S.an_element() [1, 1, 1, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=4, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=4, max_part=1) + sage: S.an_element() [1, 1, 1, 1] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=5, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=5, max_part=1) + sage: S.an_element() Traceback (most recent call last): ... EmptySetError @@ -905,12 +938,12 @@ def an_element(self): def orbit(self, v): r""" - Returns the orbit of the vector ``v`` under the action of the + Return the orbit of the vector ``v`` under the action of the permutation group defining ``self``. The result is a set. INPUT: - - ``v`` - an element of ``self`` or any list of length the + - ``v`` -- an element of ``self`` or any list of length the degree of the permutation group. EXAMPLES: @@ -918,7 +951,7 @@ def orbit(self, v): We convert the result in a list in increasing lexicographic order, to get a reproducible doctest:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),4) + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 4) sage: I.orbit([1,1,1,1]) {[1, 1, 1, 1]} sage: sorted(I.orbit([3,0,0,1])) @@ -952,7 +985,7 @@ class Element(ClonableIntArray): def check(self): r""" - Checks that ``self`` meets the constraints of being an element of ``self.parent()``. + Check that ``self`` meets the constraints of being an element of ``self.parent()``. EXAMPLES:: diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py index 3c8e85061f3..2440843bac1 100644 --- a/src/sage/combinat/interval_posets.py +++ b/src/sage/combinat/interval_posets.py @@ -1229,7 +1229,7 @@ def insertion(self, i) -> TIP: sage: def test_equivalence(n): ....: for T in TamariIntervalPosets(n): ....: for i in range(1, n + 2): - ....: if not (insert_alternative(T, i) == T.insertion(i)): + ....: if insert_alternative(T, i) != T.insertion(i): ....: print(T, i) ....: return False ....: return True diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index 3aeeb543567..530f621ca31 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Strong and weak tableaux diff --git a/src/sage/combinat/kazhdan_lusztig.py b/src/sage/combinat/kazhdan_lusztig.py index 0c213ea9013..11e50379d1d 100644 --- a/src/sage/combinat/kazhdan_lusztig.py +++ b/src/sage/combinat/kazhdan_lusztig.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kazhdan-Lusztig Polynomials diff --git a/src/sage/combinat/key_polynomial.py b/src/sage/combinat/key_polynomial.py index d132b037de3..43db18cc72f 100644 --- a/src/sage/combinat/key_polynomial.py +++ b/src/sage/combinat/key_polynomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Key polynomials diff --git a/src/sage/combinat/matrices/dlxcpp.py b/src/sage/combinat/matrices/dlxcpp.py index e235f885188..fce16e7d2ad 100644 --- a/src/sage/combinat/matrices/dlxcpp.py +++ b/src/sage/combinat/matrices/dlxcpp.py @@ -1,7 +1,7 @@ """ Dancing links C++ wrapper """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2008 Carlo Hamalainen , # # Distributed under the terms of the GNU General Public License (GPL) @@ -13,14 +13,15 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** # OneExactCover and AllExactCovers are almost exact copies of the # functions with the same name in sage/combinat/dlx.py by Tom Boothby. from .dancing_links import dlx_solver + def DLXCPP(rows): """ Solves the Exact Cover problem by using the Dancing Links algorithm @@ -85,6 +86,7 @@ def DLXCPP(rows): while x.search(): yield x.get_solution() + def AllExactCovers(M): """ Solves the exact cover problem on the matrix M (treated as a dense @@ -112,6 +114,7 @@ def AllExactCovers(M): for s in DLXCPP(rows): yield [M.row(i) for i in s] + def OneExactCover(M): """ Solves the exact cover problem on the matrix M (treated as a dense diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 6174fe3df50..308721707fe 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs sage.modules r""" Hadamard matrices diff --git a/src/sage/combinat/matrices/latin.py b/src/sage/combinat/matrices/latin.py index b2b21ff12d2..1a369bba355 100644 --- a/src/sage/combinat/matrices/latin.py +++ b/src/sage/combinat/matrices/latin.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.groups sage.modules r""" Latin Squares diff --git a/src/sage/combinat/ncsf_qsym/generic_basis_code.py b/src/sage/combinat/ncsf_qsym/generic_basis_code.py index 505b77d42e3..bbf4d7af76c 100644 --- a/src/sage/combinat/ncsf_qsym/generic_basis_code.py +++ b/src/sage/combinat/ncsf_qsym/generic_basis_code.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Generic code for bases diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index f9aafb014aa..f8d3fb64844 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Non-Commutative Symmetric Functions """ @@ -409,8 +409,8 @@ def __init__(self, R): sage: NCSF2 = NonCommutativeSymmetricFunctions(Integers(23)) sage: TestSuite(NonCommutativeSymmetricFunctions(QQ)).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring cat = GradedHopfAlgebras(R).WithRealizations().Cocommutative() Parent.__init__(self, category=cat) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index fe4e58277b1..527724e95b6 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Quasisymmetric functions @@ -556,8 +556,8 @@ def __init__(self, R): sage: QSym2 = QuasiSymmetricFunctions(Integers(23)) sage: TestSuite(QuasiSymmetricFunctions(QQ)).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R).Commutative() self._category = category diff --git a/src/sage/combinat/ncsf_qsym/tutorial.py b/src/sage/combinat/ncsf_qsym/tutorial.py index 78978507cb3..4b7f1d199ae 100644 --- a/src/sage/combinat/ncsf_qsym/tutorial.py +++ b/src/sage/combinat/ncsf_qsym/tutorial.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Introduction to Quasisymmetric Functions diff --git a/src/sage/combinat/ncsym/bases.py b/src/sage/combinat/ncsym/bases.py index 8b703487547..9d4aac2cdf1 100644 --- a/src/sage/combinat/ncsym/bases.py +++ b/src/sage/combinat/ncsym/bases.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bases for `NCSym` diff --git a/src/sage/combinat/ncsym/dual.py b/src/sage/combinat/ncsym/dual.py index 5acd9c8f176..093f4a8e939 100644 --- a/src/sage/combinat/ncsym/dual.py +++ b/src/sage/combinat/ncsym/dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Dual Symmetric Functions in Non-Commuting Variables @@ -47,9 +48,9 @@ def __init__(self, R): sage: NCSymD2 = SymmetricFunctionsNonCommutingVariablesDual(Integers(23)) sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ).dual()).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R - self._base = R # Won't be needed once CategoryObject won't override base_ring + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R + self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R) # TODO: .Commutative() Parent.__init__(self, category=category.WithRealizations()) diff --git a/src/sage/combinat/ncsym/ncsym.py b/src/sage/combinat/ncsym/ncsym.py index 64772ade2d7..931f33c739a 100644 --- a/src/sage/combinat/ncsym/ncsym.py +++ b/src/sage/combinat/ncsym/ncsym.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symmetric Functions in Non-Commuting Variables @@ -293,9 +294,9 @@ def __init__(self, R): sage: NCSym2 = SymmetricFunctionsNonCommutingVariables(Integers(23)) sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ)).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R - self._base = R # Won't be needed once CategoryObject won't override base_ring + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R + self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R) # TODO: .Cocommutative() Parent.__init__(self, category=category.WithRealizations()) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index efb0af7f572..654b9a4c2a3 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" `\nu`-Dyck Words diff --git a/src/sage/combinat/nu_tamari_lattice.py b/src/sage/combinat/nu_tamari_lattice.py index 0d6b391aa8b..433b7058cf5 100644 --- a/src/sage/combinat/nu_tamari_lattice.py +++ b/src/sage/combinat/nu_tamari_lattice.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat r""" `\nu`-Tamari lattice diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py index 9c4ceedfd19..bdba16ab252 100644 --- a/src/sage/combinat/parallelogram_polyomino.py +++ b/src/sage/combinat/parallelogram_polyomino.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Parallelogram Polyominoes ========================= @@ -253,7 +253,7 @@ def __setitem__(self, key, value): sage: o["size"]=-6 """ - assert(key in self._available_options) + assert (key in self._available_options) if value == "?": res = "Current value : " + str(self._options[key]) option_key = self._available_options[key] @@ -263,9 +263,9 @@ def __setitem__(self, key, value): else: available_options = self._available_options if "values" in available_options: - assert(value in self._available_options[key]["values"]) + assert (value in self._available_options[key]["values"]) if "checker" in available_options: - assert(available_options["checker"](value)) + assert (available_options["checker"](value)) self._options[key] = value def __call__(self, *get_values, **options): @@ -450,7 +450,7 @@ def _dispatch(self, obj, dispatch_to, option, *get_values, **set_values): sage: e.options(delim='p'); e p """ - assert(option in self._available_options) + assert (option in self._available_options) if dispatch_to[-1] == "_": dispatch_to = dispatch_to[:-1] f = getattr(obj, dispatch_to + "_" + str(self._options[option])) diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 0b7eb06c3a5..a52fc93c338 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Partition/Diagram Algebras """ @@ -1980,7 +1981,7 @@ def set_partition_composition(sp1, sp2): total_removed = 0 for cc in connected_components: # Remove the vertices that live in the middle two rows - new_cc = [x for x in cc if not((x[0] < 0 and x[1] == 1) or + new_cc = [x for x in cc if not ((x[0] < 0 and x[1] == 1) or (x[0] > 0 and x[1] == 2))] if not new_cc: diff --git a/src/sage/combinat/partition_kleshchev.py b/src/sage/combinat/partition_kleshchev.py index 06781aa96ed..29936e4db39 100644 --- a/src/sage/combinat/partition_kleshchev.py +++ b/src/sage/combinat/partition_kleshchev.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kleshchev partitions ==================== diff --git a/src/sage/combinat/partition_shifting_algebras.py b/src/sage/combinat/partition_shifting_algebras.py index 7dfee4fa460..e8f22589eb3 100644 --- a/src/sage/combinat/partition_shifting_algebras.py +++ b/src/sage/combinat/partition_shifting_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Partition Shifting Algebras diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 5cf89374de9..8b3d1899ba0 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -1579,7 +1579,7 @@ def merge_and_countv(ivA_A, ivB_B): i, j = 0, 0 ivC = [] lA, lB = len(A), len(B) - while(i < lA and j < lB): + while i < lA and j < lB: if B[j] < A[i]: C.append(B[j]) ivC.append(ivB[j] + lA - i) @@ -2267,7 +2267,7 @@ def longest_increasing_subsequences(self): """ n = self.size() if n == 0: - return([[]]) + return [[]] from bisect import insort, bisect @@ -5396,7 +5396,7 @@ def _tableau_contribution(T): 3 """ from sage.combinat.tableau import StandardTableaux - return(StandardTableaux(T.shape()).cardinality()) + return (StandardTableaux(T.shape()).cardinality()) ################################################################ # Parent classes diff --git a/src/sage/combinat/posets/cartesian_product.py b/src/sage/combinat/posets/cartesian_product.py index e8c602895cd..abf2ec94b4d 100644 --- a/src/sage/combinat/posets/cartesian_product.py +++ b/src/sage/combinat/posets/cartesian_product.py @@ -172,7 +172,7 @@ def le_lex(self, left, right): sage: T = [Q((0, 0)), Q((1, 1)), Q((0, 1)), Q((1, 0))] sage: for a in T: ....: for b in T: - ....: assert(Q.le(a, b) == (a <= b)) + ....: assert Q.le(a, b) == (a <= b) ....: print('%s <= %s = %s' % (a, b, a <= b)) (0, 0) <= (0, 0) = True (0, 0) <= (1, 1) = True @@ -239,7 +239,7 @@ def le_product(self, left, right): sage: T = [Q((0, 0)), Q((1, 1)), Q((0, 1)), Q((1, 0))] sage: for a in T: ....: for b in T: - ....: assert(Q.le(a, b) == (a <= b)) + ....: assert Q.le(a, b) == (a <= b) ....: print('%s <= %s = %s' % (a, b, a <= b)) (0, 0) <= (0, 0) = True (0, 0) <= (1, 1) = True @@ -285,7 +285,7 @@ def le_native(self, left, right): sage: T = [Q((0, 0)), Q((1, 1)), Q((0, 1)), Q((1, 0))] sage: for a in T: ....: for b in T: - ....: assert(Q.le(a, b) == (a <= b)) + ....: assert Q.le(a, b) == (a <= b) ....: print('%s <= %s = %s' % (a, b, a <= b)) (0, 0) <= (0, 0) = True (0, 0) <= (1, 1) = True diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 6bfe6eca61e..aa3c527ef8f 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" D-Complete Posets diff --git a/src/sage/combinat/posets/hasse_cython_flint.pyx b/src/sage/combinat/posets/hasse_cython_flint.pyx index 0b33eed0b3f..fcbe29faaf6 100644 --- a/src/sage/combinat/posets/hasse_cython_flint.pyx +++ b/src/sage/combinat/posets/hasse_cython_flint.pyx @@ -1,4 +1,5 @@ # cython: binding=True +# sage.doctest: needs sage.libs.flint sage.graphs sage.modules r""" Some fast computations for finite posets using FLINT matrices """ diff --git a/src/sage/combinat/posets/incidence_algebras.py b/src/sage/combinat/posets/incidence_algebras.py index 204c4661b3b..dfd18f8c338 100644 --- a/src/sage/combinat/posets/incidence_algebras.py +++ b/src/sage/combinat/posets/incidence_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Incidence Algebras """ diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 99e403765f8..8fb9055afdb 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Finite lattices and semilattices @@ -2293,9 +2293,9 @@ def is_orthocomplemented(self, unique=False): False sage: D6 = posets.DiamondPoset(6) - sage: D6.is_orthocomplemented() + sage: D6.is_orthocomplemented() # needs sage.groups True - sage: D6.is_orthocomplemented(unique=True) + sage: D6.is_orthocomplemented(unique=True) # needs sage.groups False sage: hexagon = LatticePoset({0:[1, 2], 1:[3], 2:[4], 3:[5], 4:[5]}) @@ -2453,8 +2453,8 @@ def is_geometric(self): Canonical example is the lattice of partitions of finite set ordered by refinement:: - sage: L = posets.SetPartitions(4) - sage: L.is_geometric() + sage: L = posets.SetPartitions(4) # needs sage.combinat + sage: L.is_geometric() # needs sage.combinat True Smallest example of geometric lattice that is not modular:: @@ -2754,8 +2754,8 @@ def is_upper_semimodular(self, certificate=False): sage: L.is_upper_semimodular() False - sage: L = LatticePoset(posets.IntegerPartitions(4)) - sage: L.is_upper_semimodular() + sage: L = LatticePoset(posets.IntegerPartitions(4)) # needs sage.combinat + sage: L.is_upper_semimodular() # needs sage.combinat True sage: L = LatticePoset({1:[2, 3, 4], 2: [5], 3:[5, 6], 4:[6], 5:[7], 6:[7]}) @@ -4021,21 +4021,21 @@ def is_subdirectly_reducible(self, certificate=False): EXAMPLES:: sage: N5 = posets.PentagonPoset() - sage: N5.is_subdirectly_reducible() + sage: N5.is_subdirectly_reducible() # needs sage.combinat False sage: hex = LatticePoset({1: [2, 3], 2: [4], 3: [5], 4: [6], 5: [6]}) - sage: hex.is_subdirectly_reducible() + sage: hex.is_subdirectly_reducible() # needs sage.combinat True - sage: hex.is_subdirectly_reducible(certificate=True) + sage: hex.is_subdirectly_reducible(certificate=True) # needs sage.combinat (True, (Finite lattice containing 5 elements, Finite lattice containing 5 elements)) - sage: N5.is_subdirectly_reducible(certificate=True) + sage: N5.is_subdirectly_reducible(certificate=True) # needs sage.combinat (False, (2, 3)) - sage: res, cert = hex.is_subdirectly_reducible(certificate=True) - sage: cert[0].is_isomorphic(N5) + sage: res, cert = hex.is_subdirectly_reducible(certificate=True) # needs sage.combinat + sage: cert[0].is_isomorphic(N5) # needs sage.combinat True .. SEEALSO:: @@ -4241,7 +4241,7 @@ def is_constructible_by_doublings(self, type) -> bool: sage: posets.PentagonPoset().is_constructible_by_doublings('interval') True - sage: posets.DiamondPoset(5).is_constructible_by_doublings('any') + sage: posets.DiamondPoset(5).is_constructible_by_doublings('any') # needs sage.combinat False After doubling both upper and lower pseudo-interval a lattice is @@ -5006,7 +5006,7 @@ def feichtner_yuzvinsky_ring(self, G, use_defining=False, base_ring=None): sage: Arr = H(a-b, b-c, c-d, d-a) sage: P = LatticePoset(Arr.intersection_poset()) sage: FY = P.feichtner_yuzvinsky_ring([P.top(),5,1,2,3,4]) - sage: FY.defining_ideal().groebner_basis() + sage: FY.defining_ideal().groebner_basis() # needs sage.libs.singular [h0^2 - h0*h1, h1^2, h2, h3, h4, h5] TESTS:: diff --git a/src/sage/combinat/posets/moebius_algebra.py b/src/sage/combinat/posets/moebius_algebra.py index aada2725078..00691051587 100644 --- a/src/sage/combinat/posets/moebius_algebra.py +++ b/src/sage/combinat/posets/moebius_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Möbius Algebras """ diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index c31597c72e9..0963c2b9d31 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -681,7 +681,7 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio for the poset as it contains duplicate elements """ # Avoiding some errors from the user when data should be a pair - if not(element_labels is None or isinstance(element_labels, (dict, list))): + if not (element_labels is None or isinstance(element_labels, (dict, list))): raise TypeError("element_labels should be a dict or a list if " "different from None. (Did you intend data to be " "equal to a pair ?)") @@ -5219,7 +5219,7 @@ def rees_product(self, other): ... TypeError: the Rees product is defined only for graded posets """ - if not(self.is_graded() and other.is_graded()): + if not (self.is_graded() and other.is_graded()): raise TypeError('the Rees product is defined only for graded posets') rk0 = self.rank_function() diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index 541fc98353c..ec4fb594470 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -67,10 +67,9 @@ def q_int(n, q=None): sage: q_int(0, 3r) 0 - """ if n not in ZZ: - raise ValueError('%s must be an integer' % n) + raise ValueError(f'{n} must be an integer') if q is None: q = ZZ['q'].gen() @@ -78,7 +77,7 @@ def q_int(n, q=None): return parent(q)(0) if n > 0: return sum(q**i for i in range(n)) - return -q**n*sum(q**i for i in range(-n)) + return -q**n * sum(q**i for i in range(-n)) def q_factorial(n, q=None): @@ -211,7 +210,7 @@ def q_binomial(n, k, q=None, algorithm='auto'): 2 sage: q_binomial(4,2,3.14) 152.030056160000 - sage: R = GF(25, 't') + sage: R = GF((5, 2), 't') sage: t = R.gen(0) sage: q_binomial(6, 3, t) 2*t + 3 @@ -355,12 +354,12 @@ def q_binomial(n, k, q=None, algorithm='auto'): # the algorithms while algorithm == 'naive': - denom = prod(one - q**i for i in range(1, k+1)) + denom = prod(one - q**i for i in range(1, k + 1)) if not denom: # q is a root of unity, use the cyclotomic algorithm algorithm = 'cyclotomic' break else: - num = prod(one - q**i for i in range(n-k+1, n+1)) + num = prod(one - q**i for i in range(n - k + 1, n + 1)) try: try: return num // denom @@ -452,10 +451,16 @@ def q_multinomial(seq, q=None, binomial_algorithm='auto'): gaussian_multinomial = q_multinomial -def q_catalan_number(n, q=None): +def q_catalan_number(n, q=None, m=1): """ Return the `q`-Catalan number of index `n`. + INPUT: + + - ``q`` -- optional variable + + - ``m`` -- (optional integer) to get instead the ``m``-Fuss-Catalan numbers + If `q` is unspecified, then it defaults to using the generator `q` for a univariate polynomial ring over the integers. @@ -467,10 +472,16 @@ def q_catalan_number(n, q=None): sage: from sage.combinat.q_analogues import q_catalan_number sage: q_catalan_number(4) q^12 + q^10 + q^9 + 2*q^8 + q^7 + 2*q^6 + q^5 + 2*q^4 + q^3 + q^2 + 1 + sage: p = ZZ['p'].0 - sage: q_catalan_number(4,p) + sage: q_catalan_number(4, p) p^12 + p^10 + p^9 + 2*p^8 + p^7 + 2*p^6 + p^5 + 2*p^4 + p^3 + p^2 + 1 + sage: q_catalan_number(3, m=2) + q^12 + q^10 + q^9 + q^8 + q^7 + 2*q^6 + q^5 + q^4 + q^3 + q^2 + 1 + + TESTS: + The `q`-Catalan number of index `n` is only defined for `n` a nonnegative integer (:trac:`11411`):: @@ -479,8 +490,6 @@ def q_catalan_number(n, q=None): ... ValueError: argument (-2) must be a nonnegative integer - TESTS:: - sage: q_catalan_number(3).parent() Univariate Polynomial Ring in q over Integer Ring sage: q_catalan_number(0).parent() @@ -489,10 +498,12 @@ def q_catalan_number(n, q=None): if n in ZZ: if n in {0, 1}: return q_int(1, q) - elif n >= 2: - return (prod(q_int(j, q) for j in range(n + 2, 2 * n + 1)) // - prod(q_int(j, q) for j in range(2, n + 1))) - raise ValueError("argument (%s) must be a nonnegative integer" % n) + if n >= 2: + return (prod(q_int(j, q) + for j in range(m * n + 2, (m + 1) * n + 1)) // + prod(q_int(j, q) + for j in range(2, n + 1))) + raise ValueError(f"argument ({n}) must be a nonnegative integer") def qt_catalan_number(n): @@ -800,7 +811,7 @@ def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'): Mathematical Society 101, no. 4 (1987): 771-775. :doi:`10.1090/S0002-9939-1987-0911049-8` - .. [Delsarte48] \S. Delsarte, *Fonctions de Möbius Sur Les Groupes Abeliens + .. [Delsarte48] \S. Delsarte, *Fonctions de Möbius Sur Les Groupes Abéliens Finis*, Annals of Mathematics, second series, Vol. 45, No. 3, (Jul 1948), pp. 600-609. http://www.jstor.org/stable/1969047 @@ -822,7 +833,7 @@ def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'): if algorithm == 'delsarte': def F(args): - prd = lambda j: prod(args[j]-q**i for i in range(mu_c[j+1],mu_c[j])) + prd = lambda j: prod(args[j]-q**i for i in range(mu_c[j+1], mu_c[j])) F1 = prod(args[i]**mu_c[i+1] * prd(i) for i in range(k-1)) return F1 * prod(args[k-1]-q**i for i in range(mu_c[k-1])) @@ -866,7 +877,7 @@ def q_stirling_number1(n, k, q=None): q^3 + 3*q^2 + 4*q + 3 sage: all(stirling_number1(6,k) == q_stirling_number1(6,k)(1) - ....: for k in range(1,7)) + ....: for k in range(1,6)) True sage: x = polygen(QQ['q'],'x') diff --git a/src/sage/combinat/recognizable_series.py b/src/sage/combinat/recognizable_series.py index ca2f11bd6ff..698dd959619 100644 --- a/src/sage/combinat/recognizable_series.py +++ b/src/sage/combinat/recognizable_series.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.modules +# sage.doctest: needs sage.combinat sage.modules r""" Recognizable Series diff --git a/src/sage/combinat/regular_sequence.py b/src/sage/combinat/regular_sequence.py index afb83bed6f7..a10ceb7cf17 100644 --- a/src/sage/combinat/regular_sequence.py +++ b/src/sage/combinat/regular_sequence.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.modules sage.symbolic +# sage.doctest: needs sage.combinat sage.modules sage.symbolic r""" `k`-regular sequences diff --git a/src/sage/combinat/rigged_configurations/bij_abstract_class.py b/src/sage/combinat/rigged_configurations/bij_abstract_class.py index 66ad0ac37ce..520ce241d57 100644 --- a/src/sage/combinat/rigged_configurations/bij_abstract_class.py +++ b/src/sage/combinat/rigged_configurations/bij_abstract_class.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Abstract classes for the rigged configuration bijections diff --git a/src/sage/combinat/rigged_configurations/bij_infinity.py b/src/sage/combinat/rigged_configurations/bij_infinity.py index 8d9700e168a..0fd8ee7fdc9 100644 --- a/src/sage/combinat/rigged_configurations/bij_infinity.py +++ b/src/sage/combinat/rigged_configurations/bij_infinity.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection between rigged configurations for `B(\infty)` and marginally large tableaux diff --git a/src/sage/combinat/rigged_configurations/bij_type_A.py b/src/sage/combinat/rigged_configurations/bij_type_A.py index 198ba0fc433..2a623f322da 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py b/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py index dee72713e12..ceb6ad8f1b8 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_{2n}^{(2)\dagger}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_A2_even.py b/src/sage/combinat/rigged_configurations/bij_type_A2_even.py index 1c0d587139a..8fa552a1077 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A2_even.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A2_even.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_{2n}^{(2)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py b/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py index 42a8cf956fb..ea7862ef3ef 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_{2n-1}^{(2)}`. diff --git a/src/sage/combinat/rigged_configurations/bij_type_B.py b/src/sage/combinat/rigged_configurations/bij_type_B.py index fd924150380..299f9e2e94c 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_B.py +++ b/src/sage/combinat/rigged_configurations/bij_type_B.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `B_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_C.py b/src/sage/combinat/rigged_configurations/bij_type_C.py index d04267b5569..9e0997e1479 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_C.py +++ b/src/sage/combinat/rigged_configurations/bij_type_C.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `C_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_D.py b/src/sage/combinat/rigged_configurations/bij_type_D.py index 12fb6c6be2c..ab9b41b89bd 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_D.py +++ b/src/sage/combinat/rigged_configurations/bij_type_D.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `D_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_D_tri.py b/src/sage/combinat/rigged_configurations/bij_type_D_tri.py index f143b3ce38a..b82ff955642 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_D_tri.py +++ b/src/sage/combinat/rigged_configurations/bij_type_D_tri.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `D_4^{(3)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py b/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py index dbc049d6ae0..ce177ffb468 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py +++ b/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `D_{n+1}^{(2)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_E67.py b/src/sage/combinat/rigged_configurations/bij_type_E67.py index 3d258443276..af59d3048f5 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_E67.py +++ b/src/sage/combinat/rigged_configurations/bij_type_E67.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `E_{6,7}^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bijection.py b/src/sage/combinat/rigged_configurations/bijection.py index f312f12930c..850270930a6 100644 --- a/src/sage/combinat/rigged_configurations/bijection.py +++ b/src/sage/combinat/rigged_configurations/bijection.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection between rigged configurations and KR tableaux diff --git a/src/sage/combinat/rigged_configurations/kleber_tree.py b/src/sage/combinat/rigged_configurations/kleber_tree.py index 6d056b6c678..2403ad7ab05 100644 --- a/src/sage/combinat/rigged_configurations/kleber_tree.py +++ b/src/sage/combinat/rigged_configurations/kleber_tree.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Kleber Trees diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 84e3db6640c..3addee9e2e5 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Kirillov-Reshetikhin Tableaux diff --git a/src/sage/combinat/rigged_configurations/rc_crystal.py b/src/sage/combinat/rigged_configurations/rc_crystal.py index dbd7fd047fe..647d3c6eb0d 100644 --- a/src/sage/combinat/rigged_configurations/rc_crystal.py +++ b/src/sage/combinat/rigged_configurations/rc_crystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Crystal of Rigged Configurations diff --git a/src/sage/combinat/rigged_configurations/rc_infinity.py b/src/sage/combinat/rigged_configurations/rc_infinity.py index b988c5a6ff2..e592f9b3656 100644 --- a/src/sage/combinat/rigged_configurations/rc_infinity.py +++ b/src/sage/combinat/rigged_configurations/rc_infinity.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Configurations of `\mathcal{B}(\infty)` diff --git a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py index 542649cf9dd..088dd64f20f 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py +++ b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Configuration Elements diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index a7073a700bb..b822a668612 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Configurations diff --git a/src/sage/combinat/rigged_configurations/rigged_partition.pyx b/src/sage/combinat/rigged_configurations/rigged_partition.pyx index d5ecb7c778d..694b3dd5977 100644 --- a/src/sage/combinat/rigged_configurations/rigged_partition.pyx +++ b/src/sage/combinat/rigged_configurations/rigged_partition.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Partitions diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py index ce4c2ad2ab4..3314986004f 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Tensor Product of Kirillov-Reshetikhin Tableaux diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py index c816d2140a6..8db94443af2 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Tensor Product of Kirillov-Reshetikhin Tableaux Elements diff --git a/src/sage/combinat/root_system/branching_rules.py b/src/sage/combinat/root_system/branching_rules.py index d92d08a8eed..b2ace92a56d 100644 --- a/src/sage/combinat/root_system/branching_rules.py +++ b/src/sage/combinat/root_system/branching_rules.py @@ -1125,7 +1125,7 @@ def __ne__(self, other): sage: b1 != b2 True """ - return not(self == other) + return not (self == other) def __mul__(self, other): """ diff --git a/src/sage/combinat/root_system/cartan_type.py b/src/sage/combinat/root_system/cartan_type.py index 727319bc230..816fbadcd57 100644 --- a/src/sage/combinat/root_system/cartan_type.py +++ b/src/sage/combinat/root_system/cartan_type.py @@ -2129,7 +2129,7 @@ def row_annihilator(self, m=None): annihilator_basis = m.integer_kernel().gens() if len(annihilator_basis) != 1: raise ValueError("the kernel is not 1 dimensional") - assert(all(coef > 0 for coef in annihilator_basis[0])) + assert (all(coef > 0 for coef in annihilator_basis[0])) return Family(dict((i,annihilator_basis[0][i])for i in self.index_set())) @@ -2711,7 +2711,7 @@ def __init__(self, letter, n, affine=1): False """ - assert(letter in ['A', 'B', 'C', 'BC', 'D', 'E', 'F', 'G']) + assert (letter in ['A', 'B', 'C', 'BC', 'D', 'E', 'F', 'G']) self.letter = letter self.n = n self.affine = affine diff --git a/src/sage/combinat/root_system/pieri_factors.py b/src/sage/combinat/root_system/pieri_factors.py index d2627a36413..28b26d8bf6f 100644 --- a/src/sage/combinat/root_system/pieri_factors.py +++ b/src/sage/combinat/root_system/pieri_factors.py @@ -700,7 +700,7 @@ def __contains__(self, w): if len(support) < len(red): # There should be no repetitions return False - if not(self._min_length <= len(support) and + if not (self._min_length <= len(support) and len(support) <= self._max_length and self._min_support.issubset(support) and support.issubset(self._max_support)): diff --git a/src/sage/combinat/root_system/root_space.py b/src/sage/combinat/root_system/root_space.py index b2359c547d5..cb7fc672ac2 100644 --- a/src/sage/combinat/root_system/root_space.py +++ b/src/sage/combinat/root_system/root_space.py @@ -287,7 +287,7 @@ def is_positive_root(self): sage: w.is_positive_root() False """ - return all( c >= 0 for c in self.coefficients() ) + return all(c >= 0 for c in self.coefficients()) @cached_in_parent_method def associated_coroot(self): @@ -319,12 +319,11 @@ def associated_coroot(self): alphacheck[1] sage: alpha[1].associated_coroot().parent() # needs sage.graphs Coroot lattice of the Root system of type ['B', 3] - """ - #assert(self in self.parent().roots() is not False) + # assert self in self.parent().roots() scaled_coroot = self.parent().to_coroot_space_morphism()(self) s = self.scalar(scaled_coroot) - return scaled_coroot.map_coefficients(lambda c: (2*c) // s) + return scaled_coroot.map_coefficients(lambda c: (2 * c) // s) def quantum_root(self): r""" diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 25dd3c90acf..be54faa6bcb 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -292,7 +292,7 @@ def _test_weight_lattice_realization(self, **options): # Check that the fundamental weights form the dual basis of the simple coroots for i in self.index_set(): - assert(Lambda[i].is_dominant()) + assert (Lambda[i].is_dominant()) for j in self.index_set(): tester.assertEqual(Lambda[j].scalar(alphacheck[i]), (1 if i == j else 0)) @@ -1087,13 +1087,13 @@ def symmetric_form(self, la): iset = P.index_set() + ('delta',) return sum(cl*sym[iset.index(ml),iset.index(mr)]*cr - for ml,cl in self for mr,cr in la) + for ml, cl in self for mr, cr in la) # # This should be in a method to_weight_lattice() # alphac = self.simple_coroots() # Lambda = self.fundamental_weights() - # assert( t == self.plus(t.scalar(alphac[i]) * Lambda[i] for i in self.index_set() ) ) - # t = self.plus( t.scalar(alphac[i]) * c[i] * Lambda[i] for i in self.index_set() ) + # assert t == self.plus(t.scalar(alphac[i]) * Lambda[i] for i in self.index_set()) + # t = self.plus( t.scalar(alphac[i]) * c[i] * Lambda[i] for i in self.index_set()) def to_weight_space(self, base_ring=None): r""" diff --git a/src/sage/combinat/rsk.py b/src/sage/combinat/rsk.py index 1a4ae2e548f..2c787878768 100644 --- a/src/sage/combinat/rsk.py +++ b/src/sage/combinat/rsk.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Robinson-Schensted-Knuth correspondence diff --git a/src/sage/combinat/schubert_polynomial.py b/src/sage/combinat/schubert_polynomial.py index 441dbbe3317..e4611fcdc55 100644 --- a/src/sage/combinat/schubert_polynomial.py +++ b/src/sage/combinat/schubert_polynomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Schubert Polynomials diff --git a/src/sage/combinat/sf/character.py b/src/sage/combinat/sf/character.py index eda80d2d1c3..3bd8ab5e0a1 100644 --- a/src/sage/combinat/sf/character.py +++ b/src/sage/combinat/sf/character.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Characters of the symmetric group as bases of the symmetric functions diff --git a/src/sage/combinat/sf/classical.py b/src/sage/combinat/sf/classical.py index 73bf285c14f..3151566ed6d 100644 --- a/src/sage/combinat/sf/classical.py +++ b/src/sage/combinat/sf/classical.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Classical symmetric functions """ diff --git a/src/sage/combinat/sf/dual.py b/src/sage/combinat/sf/dual.py index 90ed7f7ac8c..6a68eb7dfe6 100644 --- a/src/sage/combinat/sf/dual.py +++ b/src/sage/combinat/sf/dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Generic dual bases symmetric functions """ diff --git a/src/sage/combinat/sf/elementary.py b/src/sage/combinat/sf/elementary.py index a7e5d9cf44c..ce9cae6cdc8 100644 --- a/src/sage/combinat/sf/elementary.py +++ b/src/sage/combinat/sf/elementary.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Elementary symmetric functions """ diff --git a/src/sage/combinat/sf/hall_littlewood.py b/src/sage/combinat/sf/hall_littlewood.py index 1397e5686f3..c3376537a35 100644 --- a/src/sage/combinat/sf/hall_littlewood.py +++ b/src/sage/combinat/sf/hall_littlewood.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hall-Littlewood Polynomials diff --git a/src/sage/combinat/sf/hecke.py b/src/sage/combinat/sf/hecke.py index 514a2cbf1d8..5cea11ccb2c 100644 --- a/src/sage/combinat/sf/hecke.py +++ b/src/sage/combinat/sf/hecke.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hecke Character Basis diff --git a/src/sage/combinat/sf/homogeneous.py b/src/sage/combinat/sf/homogeneous.py index da55fef0426..e83dd16861e 100644 --- a/src/sage/combinat/sf/homogeneous.py +++ b/src/sage/combinat/sf/homogeneous.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Homogeneous symmetric functions diff --git a/src/sage/combinat/sf/jack.py b/src/sage/combinat/sf/jack.py index 9d479f930a8..a7a0fec6186 100644 --- a/src/sage/combinat/sf/jack.py +++ b/src/sage/combinat/sf/jack.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Jack Symmetric Functions diff --git a/src/sage/combinat/sf/k_dual.py b/src/sage/combinat/sf/k_dual.py index 787ed2051ad..be19a9fd413 100644 --- a/src/sage/combinat/sf/k_dual.py +++ b/src/sage/combinat/sf/k_dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Quotient of symmetric function space by ideal generated by Hall-Littlewood symmetric functions diff --git a/src/sage/combinat/sf/kfpoly.py b/src/sage/combinat/sf/kfpoly.py index 88eb77485e8..09283745aa5 100644 --- a/src/sage/combinat/sf/kfpoly.py +++ b/src/sage/combinat/sf/kfpoly.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kostka-Foulkes Polynomials diff --git a/src/sage/combinat/sf/llt.py b/src/sage/combinat/sf/llt.py index fe7e17aa58d..6e0e20d49ba 100644 --- a/src/sage/combinat/sf/llt.py +++ b/src/sage/combinat/sf/llt.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" LLT symmetric functions diff --git a/src/sage/combinat/sf/macdonald.py b/src/sage/combinat/sf/macdonald.py index 4c85c726a8a..09a3ef98798 100644 --- a/src/sage/combinat/sf/macdonald.py +++ b/src/sage/combinat/sf/macdonald.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Macdonald Polynomials diff --git a/src/sage/combinat/sf/monomial.py b/src/sage/combinat/sf/monomial.py index 36f91772d4d..6c910527fc9 100644 --- a/src/sage/combinat/sf/monomial.py +++ b/src/sage/combinat/sf/monomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Monomial symmetric functions """ diff --git a/src/sage/combinat/sf/multiplicative.py b/src/sage/combinat/sf/multiplicative.py index 4e6c57ffffa..7ff9797f81a 100644 --- a/src/sage/combinat/sf/multiplicative.py +++ b/src/sage/combinat/sf/multiplicative.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Multiplicative symmetric functions diff --git a/src/sage/combinat/sf/new_kschur.py b/src/sage/combinat/sf/new_kschur.py index 551e776ebb6..e4c2abcc75a 100644 --- a/src/sage/combinat/sf/new_kschur.py +++ b/src/sage/combinat/sf/new_kschur.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ `k`-Schur Functions """ diff --git a/src/sage/combinat/sf/ns_macdonald.py b/src/sage/combinat/sf/ns_macdonald.py index 44075c054cf..8807bd95b87 100644 --- a/src/sage/combinat/sf/ns_macdonald.py +++ b/src/sage/combinat/sf/ns_macdonald.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Non-symmetric Macdonald Polynomials """ diff --git a/src/sage/combinat/sf/orthogonal.py b/src/sage/combinat/sf/orthogonal.py index 0e9e2053d51..3ab5f56debc 100644 --- a/src/sage/combinat/sf/orthogonal.py +++ b/src/sage/combinat/sf/orthogonal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Orthogonal Symmetric Functions diff --git a/src/sage/combinat/sf/orthotriang.py b/src/sage/combinat/sf/orthotriang.py index 96cae8e7384..2e1650e57a7 100644 --- a/src/sage/combinat/sf/orthotriang.py +++ b/src/sage/combinat/sf/orthotriang.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symmetric functions defined by orthogonality and triangularity diff --git a/src/sage/combinat/sf/powersum.py b/src/sage/combinat/sf/powersum.py index fb9ecb31e91..bb20adf9941 100644 --- a/src/sage/combinat/sf/powersum.py +++ b/src/sage/combinat/sf/powersum.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Power sum symmetric functions """ diff --git a/src/sage/combinat/sf/schur.py b/src/sage/combinat/sf/schur.py index 202c31d7cee..283a43001a7 100644 --- a/src/sage/combinat/sf/schur.py +++ b/src/sage/combinat/sf/schur.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Schur symmetric functions """ @@ -715,7 +716,7 @@ def f(partition): quotient = ZZq((prod(1-q_lim**(n+j-i) for (i, j) in partition.cells())) / prod(1-q_lim**h for h in partition.hooks())) - return (power * quotient.subs({q_lim: q})) + return power * quotient.subs({q_lim: q}) return self.parent()._apply_module_morphism(self, f, q.parent()) diff --git a/src/sage/combinat/sf/sf.py b/src/sage/combinat/sf/sf.py index 56b3b96f279..16999699f42 100644 --- a/src/sage/combinat/sf/sf.py +++ b/src/sage/combinat/sf/sf.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symmetric functions, with their multiple realizations """ @@ -865,8 +866,8 @@ def __init__(self, R): """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R - self._base = R # Won't be needed when CategoryObject won't override anymore base_ring + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R + self._base = R # Won't be needed when CategoryObject won't override anymore base_ring cat = GradedHopfAlgebras(R).Commutative().Cocommutative() if R in PrincipalIdealDomains(): cat &= UniqueFactorizationDomains() diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 432fbd06ef5..75649323746 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Symmetric Functions @@ -1439,21 +1440,21 @@ def check_word(w): return False if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s: return False - return (w[0] < w[-1]) + return w[0] < w[-1] elif comparison == 0: def check_word(w): if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d: return False if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s: return False - return (w[0] == w[-1]) + return w[0] == w[-1] elif comparison == 1: def check_word(w): if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d: return False if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s: return False - return (w[0] > w[-1]) + return w[0] > w[-1] def coeff_of_m_mu_in_result(mu): # Compute the coefficient of the monomial symmetric diff --git a/src/sage/combinat/sf/symplectic.py b/src/sage/combinat/sf/symplectic.py index 7ee859ce6db..f6db1782489 100644 --- a/src/sage/combinat/sf/symplectic.py +++ b/src/sage/combinat/sf/symplectic.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symplectic Symmetric Functions diff --git a/src/sage/combinat/sf/witt.py b/src/sage/combinat/sf/witt.py index cceebed7889..138b2647826 100644 --- a/src/sage/combinat/sf/witt.py +++ b/src/sage/combinat/sf/witt.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Witt symmetric functions """ diff --git a/src/sage/combinat/shifted_primed_tableau.py b/src/sage/combinat/shifted_primed_tableau.py index 2ca02da12da..e9a320cd0ea 100644 --- a/src/sage/combinat/shifted_primed_tableau.py +++ b/src/sage/combinat/shifted_primed_tableau.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Shifted primed tableaux diff --git a/src/sage/combinat/shuffle.py b/src/sage/combinat/shuffle.py index 4c8a9cdd217..8bae3eda267 100644 --- a/src/sage/combinat/shuffle.py +++ b/src/sage/combinat/shuffle.py @@ -137,7 +137,7 @@ def __eq__(self, other): """ if not isinstance(other, type(self)): return False - return (self._l1 == other._l1 and self._l2 == other._l2) + return self._l1 == other._l1 and self._l2 == other._l2 def __ne__(self, other): """ @@ -220,10 +220,9 @@ def __init__(self, l1, l2, element_constructor=None): [[2, 3, 4, 5], [2, 5, 3, 4], [5, 2, 3, 4], [2, 3, 5, 4], [1, 2, 3, 5], [1, 5, 2, 3], [5, 1, 2, 3], [1, 2, 5, 3]] """ - assert(isinstance(l1, Iterable) and - isinstance(l2, Iterable)) - assert(all(isinstance(elem, Iterable) for elem in l1)) - assert(all(isinstance(elem, Iterable) for elem in l2)) + assert isinstance(l1, Iterable) and isinstance(l2, Iterable) + assert all(isinstance(elem, Iterable) for elem in l1) + assert all(isinstance(elem, Iterable) for elem in l2) if element_constructor is None: try: @@ -313,7 +312,7 @@ def comp_binom(el1, el2): return (ll1 + ll2).binomial(ll2) return sum(comp_binom(el1, el2) - for (el1, el2) in itertools.product(self._l1, self._l2)) + for (el1, el2) in itertools.product(self._l1, self._l2)) class ShuffleProduct(ShuffleProduct_abstract): @@ -361,7 +360,7 @@ def __init__(self, l1, l2, element_constructor=None): [word: aabbb, word: baabb, word: ababb, word: bbaab, word: babab, word: abbab, word: bbbaa, word: bbaba, word: babba, word: abbba] """ - assert(isinstance(l1, Iterable) and isinstance(l2, Iterable)) + assert isinstance(l1, Iterable) and isinstance(l2, Iterable) if element_constructor is None: try: @@ -519,7 +518,7 @@ def __contains__(self, iterable): return iterable[i + 1:] == l2[i_l2:] if i_l2 == len_l2: return iterable[i + 1:] == l1[i_l1:] - return (i_l1 + 1 == len_l1) and (i_l2 + 1 == len_l2) + return i_l1 + 1 == len_l1 and i_l2 + 1 == len_l2 def cardinality(self): r""" diff --git a/src/sage/combinat/similarity_class_type.py b/src/sage/combinat/similarity_class_type.py index 94e87115ea3..64acd5696dc 100644 --- a/src/sage/combinat/similarity_class_type.py +++ b/src/sage/combinat/similarity_class_type.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Similarity class types of matrices with entries in a finite field @@ -1421,15 +1422,15 @@ def input_parsing(data): try: data = Partition(data) case = 'par' - except(TypeError, ValueError): + except (TypeError, ValueError): try: data = SimilarityClassType(data) case = 'sim' - except(TypeError, ValueError): + except (TypeError, ValueError): try: data = PrimarySimilarityClassType(*data) case = 'pri' - except(TypeError, ValueError): + except (TypeError, ValueError): raise ValueError("expected a Partition, a SimilarityClassType or a PrimarySimilarityClassType, got a %s" % type(data)) return case, data @@ -1686,7 +1687,7 @@ def ext_orbit_centralizers(input_data, q=None, selftranspose=False): for item in product(*[IterableFunctionCall(lambda x: ext_orbit_centralizers(x, q=q, selftranspose=selftranspose), PT) for PT in tau]): size = prod([list(entry)[0] for entry in item]) freq = prod([list(entry)[1] for entry in item]) - yield(size, freq) + yield (size, freq) def matrix_centralizer_cardinalities_length_two(n, q=None, selftranspose=False, invertible=False): diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index e5c99b71fe7..e9911d47506 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.libs.gap sage.libs.flint sage.libs.pari sage.modules r""" Functions that compute some of the sequences in Sloane's tables diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index 678933d78fb..9db20d0b184 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Specht Modules diff --git a/src/sage/combinat/species/misc.py b/src/sage/combinat/species/misc.py index 7296c77e54d..a516beb56ae 100644 --- a/src/sage/combinat/species/misc.py +++ b/src/sage/combinat/species/misc.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups """ Miscellaneous Functions """ diff --git a/src/sage/combinat/species/partition_species.py b/src/sage/combinat/species/partition_species.py index c9b08f1b4bb..3ed00b45ca4 100644 --- a/src/sage/combinat/species/partition_species.py +++ b/src/sage/combinat/species/partition_species.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.flint """ Partition Species """ diff --git a/src/sage/combinat/species/permutation_species.py b/src/sage/combinat/species/permutation_species.py index aeb7ad3ca3b..4549e0354ff 100644 --- a/src/sage/combinat/species/permutation_species.py +++ b/src/sage/combinat/species/permutation_species.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups sage.libs.flint """ Permutation species """ diff --git a/src/sage/combinat/subword.py b/src/sage/combinat/subword.py index 50869bd600a..9cced6b8645 100644 --- a/src/sage/combinat/subword.py +++ b/src/sage/combinat/subword.py @@ -292,11 +292,11 @@ def random_element(self): sage: for i in range(100): ....: w = S1.random_element() ....: if w in S2: - ....: assert(not w) + ....: assert not w sage: for i in range(100): ....: w = S2.random_element() ....: if w in S1: - ....: assert(not w) + ....: assert not w """ return self._build(elt for elt in self._w if prandom.randint(0, 1)) @@ -465,11 +465,11 @@ def random_element(self): sage: for i in range(100): ....: w = S1.random_element() ....: if w in S2: - ....: assert(not w) + ....: assert not w sage: for i in range(100): ....: w = S2.random_element() ....: if w in S1: - ....: assert(not w) + ....: assert not w """ sample = prandom.sample(self._w, self._k) if self._build is list: diff --git a/src/sage/combinat/subword_complex.py b/src/sage/combinat/subword_complex.py index de7eefe946e..1a1b05dbf17 100644 --- a/src/sage/combinat/subword_complex.py +++ b/src/sage/combinat/subword_complex.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Subword complex diff --git a/src/sage/combinat/subword_complex_c.pyx b/src/sage/combinat/subword_complex_c.pyx index 39200e0c339..66da5184356 100644 --- a/src/sage/combinat/subword_complex_c.pyx +++ b/src/sage/combinat/subword_complex_c.pyx @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.modules + cpdef int _flip_c(W, set positions, list extended_root_conf_indices, int i, side="both"): r""" diff --git a/src/sage/combinat/superpartition.py b/src/sage/combinat/superpartition.py index f278eb70e11..a2e77f8a5b1 100644 --- a/src/sage/combinat/superpartition.py +++ b/src/sage/combinat/superpartition.py @@ -92,7 +92,7 @@ @richcmp_method class SuperPartition(ClonableArray, - metaclass=InheritComparisonClasscallMetaclass): + metaclass=InheritComparisonClasscallMetaclass): r""" A super partition. @@ -688,9 +688,9 @@ def add_horizontal_border_strip_star(self, h) -> list: row_changed = [row1 - row2 for row1, row2 in zip(elt, sp1)] new_sp = [elt, [(i[0] + 1, elt[i[0] + 1]) for i in circ_list if row_changed[i[0]] != 0] - # TODO: Check that this is not supposed to be - # a tuple of size 1 - + [(i) for i in circ_list if row_changed[i[0]] == 0]] + # TODO: Check that this is not supposed to be + # a tuple of size 1 + + [(i) for i in circ_list if row_changed[i[0]] == 0]] if len(set([k for (j, k) in new_sp[1]])) == len(new_sp[1]): out += [SuperPartition.from_circled_diagram(*new_sp)] return out diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 3884747f825..3e8b27e9210 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -1,4 +1,4 @@ -# optional - sage.combinat sage.modules sage.groups +# sage.doctest: needs sage.combinat sage.modules sage.groups r""" Symmetric Group Algebra """ diff --git a/src/sage/combinat/symmetric_group_representations.py b/src/sage/combinat/symmetric_group_representations.py index ee518756525..a684702119c 100644 --- a/src/sage/combinat/symmetric_group_representations.py +++ b/src/sage/combinat/symmetric_group_representations.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules sage.groups r""" Representations of the Symmetric Group @@ -627,7 +628,7 @@ def representation_matrix_for_simple_transposition(self, i): [ 1/2 1/2] """ from copy import copy - if not(1 <= i < sum(self._partition)): + if not (1 <= i < sum(self._partition)): raise TypeError Y = self._yang_baxter_graph index_lookup = {b: a for a, b in enumerate(list(Y))} diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index cd3c902e1c9..2103cb810a7 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -4507,7 +4507,7 @@ def __classcall_private__(self, t): # check that SST is strictly increasing in columns # we know that len(rnext) <= len(rcur) as the SST cannot have # more columns in the next row than the current row. - assert (len(rnext) <= len(rcur)) + assert len(rnext) <= len(rcur) for cix in range(len(rnext)): if rnext[cix] <= rcur[cix]: @@ -6408,7 +6408,7 @@ def __iter__(self): from sage.combinat.partition import Partitions # Iterates through with maximum entry as order i = 1 - while(True): + while True: for part in Partitions(self.size): if i != 1: for k in range(1, self.size+1): @@ -6508,7 +6508,7 @@ def __iter__(self): # Iterates through with maximum entry as order i = 1 n = sum(self.shape) - while(True): + while True: if i != 1: for k in range(1, n+1): for c in integer_vectors_nk_fast_iter(n - k, i-1): diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index 6ef7dd06cdc..e7ac12e1ca3 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Generalized Tamari lattices @@ -87,7 +87,7 @@ def paths_in_triangle(i, j, a, b) -> list[tuple[int, ...]]: sage: paths_in_triangle(3,2,5,3) [(1, 0, 1, 0, 0), (1, 1, 0, 0, 0)] """ - if not(b >= j and j * a >= i * b and i >= 0): + if not (b >= j and j * a >= i * b and i >= 0): raise ValueError("the endpoint is not valid") if i == 0: @@ -215,9 +215,9 @@ def GeneralizedTamariLattice(a, b, m=1, check=True): .. [BMFPR] \M. Bousquet-Melou, E. Fusy, L.-F. Preville Ratelle. *The number of intervals in the m-Tamari lattices*. :arxiv:`1106.1498` """ - if not(gcd(a, b) == 1 and a >= b): + if not (gcd(a, b) == 1 and a >= b): raise ValueError("the numbers a and b must be coprime with a>=b") - if not(a >= b * m): + if a < b * m: raise ValueError("the condition a>=b*m does not hold") def covers(p): diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index 676a4846b23..aaa9a7227b8 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Tiling Solver diff --git a/src/sage/combinat/tuple.py b/src/sage/combinat/tuple.py index 95ae68b040c..8336fb4cbb6 100644 --- a/src/sage/combinat/tuple.py +++ b/src/sage/combinat/tuple.py @@ -15,13 +15,14 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +from itertools import product, combinations_with_replacement from sage.arith.misc import binomial +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.rings.integer_ring import ZZ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from itertools import product, combinations_with_replacement + class Tuples(Parent, UniqueRepresentation): """ diff --git a/src/sage/combinat/words/abstract_word.py b/src/sage/combinat/words/abstract_word.py index 1488d8e7271..e3c2fcc5676 100644 --- a/src/sage/combinat/words/abstract_word.py +++ b/src/sage/combinat/words/abstract_word.py @@ -641,7 +641,7 @@ def _to_integer_iterator(self, use_parent_alphabet=False): mapping = {} next_value = 0 for letter in self: - if not(letter in mapping): + if letter not in mapping: mapping[letter] = next_value next_value += 1 yield mapping[letter] diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index e476b756183..bf355d9d10a 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -5938,15 +5938,15 @@ def sturmian_desubstitute_as_possible(self): w_isolated = word_from_letter[l_isolated] # the word associated to the isolated letter w_running = word_from_letter[l_running] # the word associated to the running letter min_run = minimal_run[l_running] - if (prefix_letter == l_isolated) or (prefix_length <= min_run): + if prefix_letter == l_isolated or prefix_length <= min_run: desubstitued_word = W() else: desubstitued_word = w_running ** (prefix_length - min_run) for i in runs[l_running]: desubstitued_word = desubstitued_word + w_isolated + w_running ** (i - min_run) - if (current_run_length > 0): + if current_run_length > 0: desubstitued_word = desubstitued_word + w_isolated - if (previous_letter == l_running) and (current_run_length > min_run): + if previous_letter == l_running and current_run_length > min_run: desubstitued_word = desubstitued_word + w_running ** (current_run_length - min_run) return desubstitued_word.sturmian_desubstitute_as_possible() @@ -6064,7 +6064,7 @@ def is_tangent(self): - Thierry Monteil """ - if (self.parent().alphabet().cardinality() != 2): + if self.parent().alphabet().cardinality() != 2: raise TypeError('your word must be defined on a binary alphabet') a, b = self.parent().alphabet() mini = 0 @@ -6077,10 +6077,10 @@ def is_tangent(self): if i == b: height = height - 1 mini = min(mini, height) - return (maxi - mini <= 2) + return maxi - mini <= 2 # TODO. - # 1. Those three swap functions should use the cmp of python. + # 1. Those three swap functions should use the cmp of python # 2. The actual code should then be copied as is in the Word_over_Alphabet # and continue to use the parent cmp # 3. Once Word can define Words over alphabet, the examples @@ -7213,10 +7213,10 @@ def __call__(self, i): """ j = i for c in self: - if (j - c.length() < 0): + if j < c.length(): return c[j] j -= c.length() - raise IndexError("index (=%s) out of range" % i) + raise IndexError(f"index (={i}) out of range") class Factorization(list): diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index b06acd3839e..7e04e8646d0 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -2295,13 +2295,13 @@ def list_of_conjugates(self): c = [] m = self c.append(m) - while(m.has_left_conjugate()): + while m.has_left_conjugate(): m = m.conjugate(1) if m == self: break c.append(m) m = self - while(m.has_right_conjugate()): + while m.has_right_conjugate(): m = m.conjugate(-1) if m == self: break diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index 326f7f7090c..cc4aecd250b 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Word paths diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index c3646a36907..5e4fa13ddea 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -1366,7 +1366,7 @@ def _count_and_skip(self, node, i, j): ('explicit', 1) """ trans = self._find_transition(node, self._letters[i]) - while (trans[0][1] is not None and trans[0][1] - trans[0][0] + 1 <= j - i): + while trans[0][1] is not None and trans[0][1] - trans[0][0] + 1 <= j - i: node = trans[1] i += trans[0][1] - trans[0][0] + 1 if i == j: diff --git a/src/sage/combinat/words/word_infinite_datatypes.py b/src/sage/combinat/words/word_infinite_datatypes.py index defef1e84d1..9998d3487d5 100644 --- a/src/sage/combinat/words/word_infinite_datatypes.py +++ b/src/sage/combinat/words/word_infinite_datatypes.py @@ -237,8 +237,8 @@ def __getitem__(self, key): if isinstance(key, slice): # Infinite words if self._len is Infinity or self._len is None: - if not(key.start is None) and key.start < 0 or \ - not(key.stop is None) and key.stop < 0: + if key.start is not None and key.start < 0 or \ + key.stop is not None and key.stop < 0: raise ValueError("for infinite words, start and stop values cannot be negative") step = 1 if key.step is None else key.step if step > 0: @@ -831,8 +831,8 @@ def __getitem__(self, key): """ if isinstance(key, slice): if self._len is Infinity or self._len is None: - if not(key.start is None) and key.start < 0 or \ - not(key.stop is None) and key.stop < 0: + if key.start is not None and key.start < 0 or \ + key.stop is not None and key.stop < 0: raise ValueError("for infinite words, start and stop values cannot be negative") step = 1 if key.step is None else int(key.step) if step >= 0: @@ -840,7 +840,7 @@ def __getitem__(self, key): if key.stop is None: length = Infinity stop = None - else: # key.stop > 0 + else: # key.stop > 0 length = int(max(0, ceil((key.stop-start)/float(step)))) stop = int(key.stop) data = itertools.islice(self, start, stop, step) @@ -862,7 +862,7 @@ def __getitem__(self, key): step = 1 if key.step is None else int(key.step) # If either key.start or key.stop is negative, # then we need to expand the word. - if start < 0 or (not(stop is None) and stop < 0): + if start < 0 or (not (stop is None) and stop < 0): data = list(self)[key] length = None # If key.step is negative, then we need to expand a prefix. diff --git a/src/sage/crypto/classical.py b/src/sage/crypto/classical.py index 616dc861652..e5da119086a 100644 --- a/src/sage/crypto/classical.py +++ b/src/sage/crypto/classical.py @@ -3644,7 +3644,7 @@ def inverse_key(self, K): """ S = self.key_space() n = S.ngens() - return S([ (-i)%(n) for i in K._element_list ]) + return S([ (-i) % (n) for i in K._element_list ]) def encoding(self, M): """ diff --git a/src/sage/crypto/classical_cipher.py b/src/sage/crypto/classical_cipher.py index fd2c2464293..b775c426058 100644 --- a/src/sage/crypto/classical_cipher.py +++ b/src/sage/crypto/classical_cipher.py @@ -517,7 +517,7 @@ def __call__(self, M, mode="ECB"): g = self.key() N = len(M) m = self.parent().block_length() - if not N%m == 0: + if not N % m == 0: raise TypeError("Argument M (= %s) must be a string of length k*%s." % (M, m)) Melt = M._element_list # this uses the internal structure of string monoids # Caution: this is parsed as an outer loop in k and an inner loop in i: @@ -572,7 +572,7 @@ def __call__(self, M, mode="ECB"): # This uses the internal structure of string monoids Melt = M._element_list Kelt = K._element_list - return S([ (Melt[i]+Kelt[i%m])%n for i in range(len(M)) ]) + return S([ (Melt[i]+Kelt[i % m]) % n for i in range(len(M)) ]) def inverse(self): E = self.parent() diff --git a/src/sage/crypto/lwe.py b/src/sage/crypto/lwe.py index 0be1b92d77e..db675ebafaa 100644 --- a/src/sage/crypto/lwe.py +++ b/src/sage/crypto/lwe.py @@ -170,7 +170,7 @@ def _repr_(self): sage: UniformSampler(-2, 2) UniformSampler(-2, 2) """ - return "UniformSampler(%d, %d)"%(self.lower_bound, self.upper_bound) + return "UniformSampler(%d, %d)" % (self.lower_bound, self.upper_bound) class UniformPolynomialSampler(SageObject): @@ -236,7 +236,7 @@ def _repr_(self): sage: UniformPolynomialSampler(ZZ['x'], 8, -3, 3) UniformPolynomialSampler(8, -3, 3) """ - return "UniformPolynomialSampler(%d, %d, %d)"%(self.n, self.lower_bound, self.upper_bound) + return "UniformPolynomialSampler(%d, %d, %d)" % (self.n, self.lower_bound, self.upper_bound) class LWE(SageObject): @@ -329,7 +329,7 @@ def __init__(self, n, q, D, secret_dist='uniform', m=None): lb, ub = map(ZZ, secret_dist) self.__s = vector(self.K, self.n, [randint(lb,ub) for _ in range(n)]) except (IndexError, TypeError): - raise TypeError("Parameter secret_dist=%s not understood."%(secret_dist)) + raise TypeError("Parameter secret_dist=%s not understood." % (secret_dist)) def _repr_(self): """ @@ -345,9 +345,9 @@ def _repr_(self): LWE(20, 401, Discrete Gaussian sampler over the Integers with sigma = 3.000000 and c = 0.000000, (-3, 3), None) """ if isinstance(self.secret_dist, str): - return "LWE(%d, %d, %s, '%s', %s)"%(self.n,self.K.order(),self.D,self.secret_dist, self.m) + return "LWE(%d, %d, %s, '%s', %s)" % (self.n,self.K.order(),self.D,self.secret_dist, self.m) else: - return "LWE(%d, %d, %s, %s, %s)"%(self.n,self.K.order(),self.D,self.secret_dist, self.m) + return "LWE(%d, %d, %s, %s, %s)" % (self.n,self.K.order(),self.D,self.secret_dist, self.m) def __call__(self): """ @@ -362,7 +362,7 @@ def __call__(self): if self.m is not None: if self.__i >= self.m: raise IndexError("Number of available samples exhausted.") - self.__i+=1 + self.__i += 1 a = self.FM.random_element() return a, a.dot_product(self.__s) + self.K(self.D()) @@ -480,7 +480,7 @@ def __init__(self, n, instance='key', m=None): LWE(131, 64311834871, UniformSampler(0, 11109), 'noise', 181) """ - if n<89: + if n < 89: raise TypeError("Parameter too small") n2 = n @@ -509,7 +509,7 @@ def __init__(self, n, instance='key', m=None): m = n2+l LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m) else: - raise TypeError("Parameter instance=%s not understood."%(instance)) + raise TypeError("Parameter instance=%s not understood." % (instance)) class RingLWE(SageObject): """ @@ -551,7 +551,7 @@ def __init__(self, N, q, D, poly=None, secret_dist='uniform', m=None): self.K = IntegerModRing(q) if self.n != D.n: - raise ValueError("Noise distribution has dimensions %d != %d"%(D.n, self.n)) + raise ValueError("Noise distribution has dimensions %d != %d" % (D.n, self.n)) self.D = D self.q = q @@ -568,7 +568,7 @@ def __init__(self, N, q, D, poly=None, secret_dist='uniform', m=None): elif secret_dist == 'noise': self.__s = self.D() else: - raise TypeError("Parameter secret_dist=%s not understood."%(secret_dist)) + raise TypeError("Parameter secret_dist=%s not understood." % (secret_dist)) def _repr_(self): """ @@ -580,9 +580,9 @@ def _repr_(self): RingLWE(16, 401, Discrete Gaussian sampler for polynomials of degree < 8 with σ=3.000000 in each component, x^8 + 1, 'uniform', None) """ if isinstance(self.secret_dist, str): - return "RingLWE(%d, %d, %s, %s, '%s', %s)"%(self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) + return "RingLWE(%d, %d, %s, %s, '%s', %s)" % (self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) else: - return "RingLWE(%d, %d, %s, %s, %s, %s)"%(self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) + return "RingLWE(%d, %d, %s, %s, %s, %s)" % (self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) def __call__(self): """ @@ -602,7 +602,7 @@ def __call__(self): if self.m is not None: if self.__i >= self.m: raise IndexError("Number of available samples exhausted.") - self.__i+=1 + self.__i += 1 a = self.R_q.random_element() return vector(a), vector(a * (self.__s) + self.D()) @@ -710,7 +710,7 @@ def _repr_(self): RingLWEConverter(RingLWE(20, 257, Discrete Gaussian sampler for polynomials of degree < 8 with σ=5.000000 in each component, x^8 - x^6 + x^4 - x^2 + 1, 'uniform', None)) """ - return "RingLWEConverter(%s)"%str(self.ringlwe) + return "RingLWEConverter(%s)" % str(self.ringlwe) def samples(m, n, lwe, seed=None, balanced=False, **kwds): """ diff --git a/src/sage/crypto/mq/rijndael_gf.py b/src/sage/crypto/mq/rijndael_gf.py index ba24ed0627e..55ae295f2cd 100644 --- a/src/sage/crypto/mq/rijndael_gf.py +++ b/src/sage/crypto/mq/rijndael_gf.py @@ -1311,7 +1311,7 @@ def expand_key_poly(self, row, col, round): recur_j = (key_col - self._Nk) - (recur_r * self._Nb) result = self.expand_key_poly(row, recur_j, recur_r) # Identify key_col - 1 - recur_r = int((key_col- 1)/self._Nb) + recur_r = int((key_col - 1)/self._Nb) recur_j = (key_col - 1) - (recur_r * self._Nb) return result + \ self.expand_key_poly(row, recur_j, recur_r) diff --git a/src/sage/crypto/mq/sr.py b/src/sage/crypto/mq/sr.py index 091ff4a96fa..f4ddf5c1844 100644 --- a/src/sage/crypto/mq/sr.py +++ b/src/sage/crypto/mq/sr.py @@ -586,7 +586,7 @@ def __getattr__(self, attr): self.Mstar = self.ShiftRows * self.Lin return self.Mstar - raise AttributeError("%s has no attribute %s"%(type(self), attr)) + raise AttributeError("%s has no attribute %s" % (type(self), attr)) def _repr_(self): """ @@ -598,9 +598,9 @@ def _repr_(self): SR*(1,2,2,4) """ if self._star: - return "SR*(%d,%d,%d,%d)"%(self._n, self._r, self._c, self._e) + return "SR*(%d,%d,%d,%d)" % (self._n, self._r, self._c, self._e) else: - return "SR(%d,%d,%d,%d)"%(self._n, self._r, self._c, self._e) + return "SR(%d,%d,%d,%d)" % (self._n, self._r, self._c, self._e) def base_ring(self): r""" @@ -748,7 +748,7 @@ def sub_byte(self, b): [1, 0, 1, 1], [1, 1, 0, 1]]) - elif e==8: + elif e == 8: if not hasattr(self, "_L"): self._L = Matrix(GF(2), 8, 8, [[1, 0, 0, 0, 1, 1, 1, 1], [1, 1, 0, 0, 0, 1, 1, 1], @@ -911,7 +911,7 @@ def shift_rows(self, d): d = self.state_array(d) ret = [] for i in range(d.nrows()): - ret += list(d.row(i)[i%d.ncols():]) + list(d.row(i)[:i%d.ncols()]) + ret += list(d.row(i)[i % d.ncols():]) + list(d.row(i)[:i % d.ncols()]) return Matrix(self.base_ring(), self._r, self._c, ret) def mix_columns(self, d): @@ -958,7 +958,7 @@ def mix_columns(self, d): [1, a, a+1, 1], [1, 1, a, a+1], [a+1, 1, 1, a]]) - ret =[] + ret = [] for column in d.columns(): ret.append(M * column) # AES uses the column major ordering @@ -1315,7 +1315,7 @@ def __call__(self, P, K): elif len(P) == len(K) == r*c*e: _type = self.vector else: - raise TypeError("length %d or %d doesn't match either %d or %d"%(len(P),len(K),r*c,r*c*e)) + raise TypeError("length %d or %d doesn't match either %d or %d" % (len(P),len(K),r*c,r*c*e)) else: raise TypeError("plaintext or key parameter not understood") @@ -1332,46 +1332,46 @@ def __call__(self, P, K): for r in range(self._n-1): if get_verbose() >= 2: - print("R[%02d].start %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].start %s" % (r+1, self.hex_str_vector(P))) P = SubBytes(P) if get_verbose() >= 2: - print("R[%02d].s_box %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].s_box %s" % (r+1, self.hex_str_vector(P))) P = ShiftRows(P) if get_verbose() >= 2: - print("R[%02d].s_row %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].s_row %s" % (r+1, self.hex_str_vector(P))) P = MixColumns(P) if get_verbose() >= 2: - print("R[%02d].m_col %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].m_col %s" % (r+1, self.hex_str_vector(P))) K = KeyExpansion(K, r+1) if get_verbose() >= 2: - print("R[%02d].k_sch %s"%(r+1, self.hex_str_vector(K))) + print("R[%02d].k_sch %s" % (r+1, self.hex_str_vector(K))) P = AddRoundKey(P, K) P = SubBytes(P) if get_verbose() >= 2: - print("R[%02d].s_box %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].s_box %s" % (self.n, self.hex_str_vector(P))) P = ShiftRows(P) if get_verbose() >= 2: - print("R[%02d].s_row %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].s_row %s" % (self.n, self.hex_str_vector(P))) if not self._star: P = MixColumns(P) if get_verbose() >= 2: - print("R[%02d].m_col %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].m_col %s" % (self.n, self.hex_str_vector(P))) K = KeyExpansion(K, self._n) if get_verbose() >= 2: - print("R[%02d].k_sch %s"%(self.n, self.hex_str_vector(K))) + print("R[%02d].k_sch %s" % (self.n, self.hex_str_vector(K))) P = AddRoundKey(P, K) if get_verbose() >= 2: - print("R[%02d].output %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].output %s" % (self.n, self.hex_str_vector(P))) return _type(P) @@ -1860,7 +1860,7 @@ def round_polynomials(self, i, plaintext=None, ciphertext=None): plaintext = Matrix(R, r*c*e, 1, self.phi(plaintext)) return tuple((w1 + k0 + plaintext).list()) - elif i>0 and i<=n: + elif i > 0 and i <= n: if self._star and i == n: M = self.Mstar @@ -1957,8 +1957,8 @@ def key_schedule_polynomials(self, i): if r == 1: sbox += self.inversion_polynomials(kj[(c - 1)*e:(c - 1)*e + e], si[0:e], e) if r == 2: - sbox += self.inversion_polynomials( kj[(2*c -1)*e : (2*c -1)*e + e] , si[0:1*e], e ) - sbox += self.inversion_polynomials( kj[(2*c -2)*e : (2*c -2)*e + e] , si[e:2*e], e ) + sbox += self.inversion_polynomials( kj[(2*c - 1)*e : (2*c - 1)*e + e] , si[0:1*e], e ) + sbox += self.inversion_polynomials( kj[(2*c - 2)*e : (2*c - 2)*e + e] , si[e:2*e], e ) if r == 4: if self._aes_mode: sbox += self.inversion_polynomials( kj[(4*c-3)*e : (4*c-3)*e + e] , si[0*e : 1*e] , e ) @@ -2108,19 +2108,19 @@ def polynomial_system(self, P=None, K=None, C=None): plaintext, key, ciphertext = data if plaintext is False: - raise TypeError("type %s of P not understood"%(type(plaintext))) + raise TypeError("type %s of P not understood" % (type(plaintext))) elif plaintext is None: plaintext = self.random_element("vector") if key is None: key = self.random_element("vector") elif key is False and ciphertext is False: - raise TypeError("type %s of K not understood"%(type(key))) + raise TypeError("type %s of K not understood" % (type(key))) if ciphertext is None: ciphertext = self(plaintext, key) elif ciphertext is False: - raise TypeError("type %s of C not understood"%(type(ciphertext))) + raise TypeError("type %s of C not understood" % (type(ciphertext))) for i in range(n+1): system.append( self.round_polynomials(i, plaintext, ciphertext) ) @@ -2324,13 +2324,13 @@ def lin_matrix(self, length=None): for k in range( 0, length ): for i in range(0, 4): for j in range(0, 4): - lin[k*4+j, k*4+i] = l[(i-j)%4] ** (2**j) + lin[k*4+j, k*4+i] = l[(i-j) % 4] ** (2**j) elif e == 8: l = [k.from_integer(x) for x in (5, 9, 249, 37, 244, 1, 181, 143)] for k in range( 0, length ): for i in range(0, 8): for j in range(0, 8): - lin[k*8+j, k*8+i] = l[(i-j)%8] ** (2**j) + lin[k*8+j, k*8+i] = l[(i-j) % 8] ** (2**j) return lin @@ -2480,7 +2480,7 @@ def field_polynomials(self, name, i, l=None): l = r*c _vars = self.vars(name, i, l, e) - return [_vars[e*j+k]**2 - _vars[e*j+(k+1)%e] for j in range(l) for k in range(e)] + return [_vars[e*j+k]**2 - _vars[e*j+(k+1) % e] for j in range(l) for k in range(e)] class SR_gf2(SR_generic): def __init__(self, n=1, r=1, c=1, e=4, star=False, **kwargs): @@ -2665,7 +2665,7 @@ def antiphi(self, l): elif isinstance(l, tuple): return tuple(ret) elif is_Matrix(l): - return Matrix(self.base_ring(), self.r *self.c, 1, ret) + return Matrix(self.base_ring(), self.r * self.c, 1, ret) else: raise TypeError @@ -2911,7 +2911,7 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, if x is None and w is None: # make sure it prints like in the book. - names = ["w%d" % i for i in reversed(range(e))] + ["x%d"%i for i in reversed(range(e))] + names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))] P = PolynomialRing(GF(2), e*2, names, order='lex') x = P.gens()[e:] w = P.gens()[:e] @@ -3086,7 +3086,7 @@ def _inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, if x is None and w is None: # make sure it prints like in the book. - names = ["w%d" % i for i in reversed(range(e))] + ["x%d"%i for i in reversed(range(e))] + names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))] P = PolynomialRing(GF(2), e*2, names, order='lex') x = Matrix(P, e, 1, P.gens()[e:]) w = Matrix(P, e, 1, P.gens()[:e]) @@ -3123,8 +3123,8 @@ def _inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, l.append( (Cw * x + o).list()[:-1] ) else: l.append( (Cw * x + o).list() ) - l.append( (Cw * S *x + x).list() ) - l.append( (Cx * S *w + w).list() ) + l.append( (Cw * S * x + x).list() ) + l.append( (Cx * S * w + w).list() ) if not biaffine_only: l.append( ((Cw * S**2 + Cx*S)*x).list() ) l.append( ((Cx * S**2 + Cw*S)*w).list() ) @@ -3280,7 +3280,7 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, e = self.e if x is None and w is None: # make sure it prints like in the book. - names = ["w%d" % i for i in reversed(range(e))] + ["x%d"%i for i in reversed(range(e))] + names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))] P = PolynomialRing(GF(2), e*2, names, order='lex') x = P.gens()[e:] w = P.gens()[:e] diff --git a/src/sage/crypto/stream_cipher.py b/src/sage/crypto/stream_cipher.py index c6f46c8cef0..7eb69e3c7b7 100644 --- a/src/sage/crypto/stream_cipher.py +++ b/src/sage/crypto/stream_cipher.py @@ -95,7 +95,7 @@ def __call__(self, M, mode="ECB"): N = len(M) Melt = M._element_list Kelt = lfsr_sequence(poly.list(), IS, N) - return B([ (Melt[i]+int(Kelt[i]))%n for i in range(N) ]) + return B([ (Melt[i]+int(Kelt[i])) % n for i in range(N) ]) def _repr_(self): r""" diff --git a/src/sage/databases/sql_db.py b/src/sage/databases/sql_db.py index 299d917aed6..4c5d439eda0 100644 --- a/src/sage/databases/sql_db.py +++ b/src/sage/databases/sql_db.py @@ -1026,16 +1026,19 @@ def __init__(self, filename=None, read_only=None, skeleton=None): NOTE: The values of ``display_cols`` are always concatenated in intersections and unions. - Of course, we can save the database to file:: + Of course, we can save the database to file. Here we use a + temporary directory that we clean up afterwards:: - sage: replace_with_your_own_filepath = tmp_dir() - sage: D.save(replace_with_your_own_filepath + 'simon.db') + sage: import tempfile + sage: d = tempfile.TemporaryDirectory() + sage: dbpath = os.path.join(d.name, 'simon.db') + sage: D.save(dbpath) Now the database's hard link is to this file, and not the temporary db file. For example, let's say we open the same file with another class instance. We can load the file as an immutable database:: - sage: E = SQLDatabase(replace_with_your_own_filepath + 'simon.db') + sage: E = SQLDatabase(dbpath) sage: E.show('simon') graph6 vertices edges ------------------------------------------------------------ @@ -1062,6 +1065,11 @@ def __init__(self, filename=None, read_only=None, skeleton=None): Traceback (most recent call last): ... RuntimeError: Cannot drop tables from a read only database. + + Call ``cleanup()`` on the temporary directory to, well, clean it up:: + + sage: d.cleanup() + """ if filename is None: if read_only is None: @@ -1111,10 +1119,12 @@ def __repr__(self): EXAMPLES:: - sage: replace_with_filepath = tmp_dir() + 'test.db' - sage: SD = SQLDatabase(replace_with_filepath, False) - sage: SD.create_table('simon', {'n':{'sql':'INTEGER', 'index':True}}) - sage: print(SD) + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: dbpath = os.path.join(d, "test.db") + ....: SD = SQLDatabase(dbpath, False) + ....: SD.create_table('simon', {'n':{'sql':'INTEGER', 'index':True}}) + ....: print(SD) table simon: column n: index: True; primary_key: False; sql: INTEGER; unique: False; @@ -1182,10 +1192,12 @@ def save(self, filename): sage: MonicPolys = SQLDatabase() sage: MonicPolys.create_table('simon', {'n':{'sql':'INTEGER', 'index':True}}) sage: for n in range(20): MonicPolys.add_row('simon', (n,)) - sage: tmp = tmp_dir() # replace with your own file path - sage: MonicPolys.save(tmp+'sage.db') - sage: N = SQLDatabase(tmp+'sage.db') - sage: N.show('simon') + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: dbpath = os.path.join(d, "sage.db") + ....: MonicPolys.save(dbpath) + ....: N = SQLDatabase(dbpath) + ....: N.show('simon') n -------------------- 0 diff --git a/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py b/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py index de956719603..203eb70b563 100644 --- a/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py @@ -232,7 +232,7 @@ def __classcall_private__(cls, dynamical_system, domain=None, ideal=None): 2*3^15 + 2*3^16 + 2*3^17 + 2*3^18 + 2*3^19 + 2*3^20 + O(3^21)) """ if not (is_Berkovich_Cp(domain) or domain is None): - raise TypeError('domain must be a Berkovich space over Cp, not %s' %domain) + raise TypeError('domain must be a Berkovich space over Cp, not %s' % domain) if isinstance(domain, Berkovich_Cp_Affine): if not isinstance(dynamical_system, DynamicalSystem_affine): @@ -269,7 +269,7 @@ def __classcall_private__(cls, dynamical_system, domain=None, ideal=None): raise ValueError('conflicting inputs for ideal and domain') else: raise ValueError('base ring of domain of dynamical_system must be p-adic or a number field ' - 'not %s' %morphism_domain.base_ring()) + 'not %s' % morphism_domain.base_ring()) if is_AffineSpace(morphism_domain): return DynamicalSystem_Berkovich_affine(dynamical_system, domain) @@ -444,7 +444,7 @@ def _repr_(self): """ domain_str = self._domain._repr_() return "Dynamical system of " + domain_str + " induced by the map" + \ - "\n Defn: %s"%('\n '.join(self._system._repr_defn().split('\n'))) + "\n Defn: %s" % ('\n '.join(self._system._repr_defn().split('\n'))) class DynamicalSystem_Berkovich_projective(DynamicalSystem_Berkovich): @@ -524,19 +524,19 @@ def __classcall_private__(cls, dynamical_system, domain=None): R = dynamical_system.base_ring() morphism_domain = dynamical_system.domain() if not is_ProjectiveSpace(morphism_domain): - raise TypeError('the domain of dynamical_system must be projective space, not %s' %morphism_domain) + raise TypeError('the domain of dynamical_system must be projective space, not %s' % morphism_domain) if morphism_domain.dimension_relative() != 1: raise ValueError('domain was not relative dimension 1') if not isinstance(R, pAdicBaseGeneric): if domain is None: - raise TypeError('dynamical system defined over %s, not p-adic, ' %morphism_domain.base_ring() + + raise TypeError('dynamical system defined over %s, not p-adic, ' % morphism_domain.base_ring() + 'and domain is None') if not isinstance(domain, Berkovich_Cp_Projective): - raise TypeError('domain was %s, not a projective Berkovich space over Cp' %domain) + raise TypeError('domain was %s, not a projective Berkovich space over Cp' % domain) if domain.base() != morphism_domain: - raise ValueError('base of domain was %s, with coordinate ring %s ' %(domain.base(), - domain.base().coordinate_ring())+ 'while dynamical_system acts on %s, ' %morphism_domain + - 'with coordinate ring %s' %morphism_domain.coordinate_ring()) + raise ValueError('base of domain was %s, with coordinate ring %s ' % (domain.base(), + domain.base().coordinate_ring()) + 'while dynamical_system acts on %s, ' % morphism_domain + + 'with coordinate ring %s' % morphism_domain.coordinate_ring()) else: domain = Berkovich_Cp_Projective(morphism_domain) return typecall(cls, dynamical_system, domain) @@ -686,7 +686,7 @@ def conjugate(self, M, adjugate=False, new_ideal=None): return DynamicalSystem_Berkovich(self._system.conjugate(M, adjugate=adjugate)) from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal if not (isinstance(new_ideal, NumberFieldFractionalIdeal) or new_ideal is None or new_ideal in ZZ): - raise TypeError('new_ideal must be an ideal of a number field, not %s' %new_ideal) + raise TypeError('new_ideal must be an ideal of a number field, not %s' % new_ideal) new_system = self._system.conjugate(M, adjugate=adjugate) system_domain = new_system.domain() if new_ideal is None: @@ -1003,15 +1003,15 @@ def __classcall_private__(cls, dynamical_system, domain=None): R = dynamical_system.base_ring() morphism_domain = dynamical_system.domain() if not is_AffineSpace(morphism_domain): - raise TypeError('the domain of dynamical_system must be affine space, not %s' %morphism_domain) + raise TypeError('the domain of dynamical_system must be affine space, not %s' % morphism_domain) if morphism_domain.dimension_relative() != 1: raise ValueError('domain not relative dimension 1') if not isinstance(R, pAdicBaseGeneric): if domain is None: - raise TypeError('dynamical system defined over %s, not padic, ' %morphism_domain.base_ring() + + raise TypeError('dynamical system defined over %s, not padic, ' % morphism_domain.base_ring() + 'and domain was not specified') if not isinstance(domain, Berkovich_Cp_Affine): - raise TypeError('domain was %s, not an affine Berkovich space over Cp' %domain) + raise TypeError('domain was %s, not an affine Berkovich space over Cp' % domain) else: domain = Berkovich_Cp_Affine(morphism_domain.base_ring()) return typecall(cls, dynamical_system, domain) @@ -1080,6 +1080,6 @@ def __call__(self, x): try: x = self.domain()(x) except (TypeError, ValueError): - raise ValueError('action of dynamical system not defined on %s' %x) + raise ValueError('action of dynamical system not defined on %s' % x) proj_system = self.homogenize(1) return proj_system(x.as_projective_point()).as_affine_point() diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index e8e5ddba1c4..d42d3ca8b2d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -100,7 +100,7 @@ def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, F = R.base_ring() - if F != QQ and F!= ZZ: + if F != QQ and F != ZZ: raise TypeError("coefficient ring is not the rational numbers or the integers") z = R.gen(0) @@ -227,7 +227,7 @@ def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, elements.append(matrix(F, 2, [zeta, alpha*(1-zeta), 0, 1])) factors = (f2 - z*g2).factor() L1 = NumberField(z**2 + 1,'i') - i=L1.gen(0) + i = L1.gen(0) L2 = NumberField(z**2 + 3,'isqrt3') isqrt3 = L2.gen(0) for psi in factors: @@ -310,7 +310,7 @@ def height_bound(polynomial): 413526 """ # first check that polynomial is over QQ or ZZ - K=polynomial.parent() + K = polynomial.parent() if K.is_field(): R = K.ring() @@ -318,7 +318,7 @@ def height_bound(polynomial): R = K F = R.base_ring() - if F != QQ and F!= ZZ: + if F != QQ and F != ZZ: raise TypeError("coefficient ring is not the rational numbers or the integers") # scale polynomial so that it has integer coefficients with gcd 1 @@ -672,7 +672,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun F = R.base_ring() - if F != QQ and F!= ZZ: + if F != QQ and F != ZZ: raise TypeError("coefficient ring is not the rational numbers or the integers") z = R.gen(0) @@ -739,7 +739,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun # the only possible groups are C_n, D_2n for n|6 or n|4 # all of these groups have order dividing 24 while (congruence < (2*MaxH**2)) and len(elements) < gcd(orderaut + [24]): - if badprimes%p != 0: #prime of good reduction + if badprimes % p != 0: #prime of good reduction # compute automorphisms mod p phi_p = f.change_ring(GF(p))/g.change_ring(GF(p)) sorted_automorphisms = automorphism_group_FF(phi_p) @@ -797,7 +797,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun # if an element of Aut_{F_p} has been lifted to QQ # remove that element from Aut_{F_p} so we don't # attempt to lift that element again unnecessarily - automorphisms=remove_redundant_automorphisms(automorphisms, + automorphisms = remove_redundant_automorphisms(automorphisms, orderelts, primepowers, temp) if order == 4: #have some elements of order 4 # so possible aut group is Z/4 or D_4 @@ -808,7 +808,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun badorders.append(4) else: #no elements of order d in some F_v for m in divisors(N): - if m%order == 0: + if m % order == 0: badorders.append(m) #no elements of that order or any order that # is a multiple of it @@ -880,12 +880,12 @@ def automorphism_group_FF(rational_function, absolute=False, iso_type=False, ret if not return_functions: if absolute: - R=G[1][0].parent() + R = G[1][0].parent() if R.is_field(): R = R.ring() G[1] = [matrix(R.base_ring(),[[R(g.numerator())[1],R(g.numerator())[0]],[R(g.denominator())[1],R(g.denominator())[0]]]) for g in G[1]] else: - R=G[0].parent() + R = G[0].parent() if R.is_field(): R = R.ring() G = [matrix(R.base_ring(),[[R(g.numerator())[1],R(g.numerator())[0]],[R(g.denominator())[1],R(g.denominator())[0]]]) for g in G] @@ -941,7 +941,7 @@ def field_descent(sigma, y): if not remainder.is_constant(): return else: - x = x+ F(remainder) + x = x + F(remainder) steps = 1 while not quotient.is_constant(): @@ -949,7 +949,7 @@ def field_descent(sigma, y): if not remainder.is_constant(): return else: - x = x+ F(remainder)*a**(steps) + x = x + F(remainder)*a**(steps) steps += 1 return x + F(quotient)*a**(steps) @@ -1125,12 +1125,12 @@ def three_stable_points(rational_function, invariant_list): b = (T[0][0]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0] - T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] - - T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][0] *T[t[2]][1] + + T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][0] * T[t[2]][1] + T[0][0]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] + T[0][1]*T[1][0]*T[2][0]*T[t[0]][0]*T[t[1]][0]*T[t[2]][1] - T[0][1]*T[1][0]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0]) - c = (T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + c = (T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][0] * T[t[2]][1] - T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] - T[0][1]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] + T[0][1]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] + @@ -1138,10 +1138,10 @@ def three_stable_points(rational_function, invariant_list): T[0][1]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][1]) d = (T[0][0]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] - - T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0] * T[t[2]][1] - T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] + T[0][0]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] + - T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][0] * T[t[2]][1] - T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0]) if a*d - b*c != 0: @@ -1240,9 +1240,9 @@ def automorphism_group_FF_alg2(rational_function): y = fix.roots(multiplicities=False)[0] preimage = R(f(z) - y*g(z)) minimal_preimage = R(prod(x[0] for x in preimage.factor())) - if minimal_preimage.degree() + bool(preimage.degree()= 3: + if minimal_preimage.degree() + bool(preimage.degree() < D) >= 3: T_poly = minimal_preimage - infinity_check = bool(preimage.degree() max_reg_cyclic[0] and gcd(len(H), p) != p: max_reg_cyclic = [len(H), g, H] - discard = list(set(discard +H)) # adjoin all new elements to discard + discard = list(set(discard + H)) # adjoin all new elements to discard n_reg = max_reg_cyclic[0] # Test for dihedral subgroup. A subgroup of index 2 is always normal, so the diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py b/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py index 735e0800a6f..58df10c4a4c 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py @@ -273,7 +273,7 @@ def affine_minimal(vp, return_transformation=False, D=None, quick=False): #If the valuation of a prime in the resultant is small enough, we can say the #map is affine minimal at that prime without using the local minimality loop. See #Theorem 3.2.2 in [Molnar, M.Sc. thesis] - if d%2 == 0: + if d % 2 == 0: g = d else: g = 2*d @@ -1106,7 +1106,7 @@ def coshdelta(z): rep = 2*CC.gen(0) from math import isnan if isnan(v0.abs()): - raise ValueError("invalid covariant: %s"%v0) + raise ValueError("invalid covariant: %s" % v0) # get orbit S = matrix(ZZ,2,2,[0,-1,1,0]) diff --git a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py index 25d8645ae86..d09b15ab78c 100644 --- a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py @@ -217,10 +217,10 @@ def _repr_(self): 'Dynamical System of Projective Space of dimension 1 over Rational Field\n Defn: Defined on coordinates by sending (x : y) to\n (x^3 : x*y^2)' """ - s = "%s of %s"%(self._repr_type(), self.domain()) + s = "%s of %s" % (self._repr_type(), self.domain()) d = self._repr_defn() if d != '': - s += "\n Defn: %s"%('\n '.join(self._repr_defn().split('\n'))) + s += "\n Defn: %s" % ('\n '.join(self._repr_defn().split('\n'))) return s def as_scheme_morphism(self): diff --git a/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py index caf82a3b00d..9d6836c1e36 100644 --- a/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py @@ -104,9 +104,9 @@ def _call_with_args(self, P, check=True): try: P = self.domain()(P) except (TypeError, NotImplementedError): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self.domain())) - elif self.domain()!= P.codomain(): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self.domain())) + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self.domain())) + elif self.domain() != P.codomain(): + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self.domain())) A = self.domain() Q = list(P) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 6520177f4a7..ef1e50c78e9 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -2071,7 +2071,7 @@ def green_function(self, P, v, **kwds): K = R v = BR.places(prec=prec)[0] else: - raise ValueError("invalid valuation (=%s) entered"%v) + raise ValueError("invalid valuation (=%s) entered" % v) #Coerce all polynomials in F into polynomials with coefficients in K F = self.change_ring(K, check=False) @@ -2082,7 +2082,7 @@ def green_function(self, P, v, **kwds): if err is not None: err = R(err) if not err > 0: - raise ValueError("error bound (=%s) must be positive"%err) + raise ValueError("error bound (=%s) must be positive" % err) #if doing error estimates, compute needed number of iterates D = (dim + 1) * (d - 1) + 1 @@ -2115,7 +2115,7 @@ def green_function(self, P, v, **kwds): else: #non-archimedean h = max([c.local_height(v, prec=prec) for c in poly.coefficients()]) if h > maxh: - maxh=h + maxh = h if maxh == 0: maxh = 1 #avoid division by 0 if isinstance(v, RingHomomorphism_im_gens): #archimedean @@ -2126,7 +2126,7 @@ def green_function(self, P, v, **kwds): if C != 0: N = R(C / (err*(d-1))).log(d).abs().ceil() else: #we just need log||P||_v - N=1 + N = 1 #START GREEN FUNCTION CALCULATION if isinstance(v, RingHomomorphism_im_gens): #embedding for archimedean local height @@ -2550,7 +2550,7 @@ def multiplier(self, P, n, check=True): """ if check: if self.nth_iterate(P, n) != P: - raise ValueError("%s is not periodic of period %s"%(P, n)) + raise ValueError("%s is not periodic of period %s" % (P, n)) if n < 1: raise ValueError("period must be a positive integer") N = self.domain().ambient_space().dimension_relative() @@ -2689,7 +2689,7 @@ def _nth_preimage_tree_helper(self, Q, n, m, **kwds): if return_points: points = kwds["points"] - if n==1: + if n == 1: # Base case of recursion return D, points else: @@ -2699,7 +2699,7 @@ def _nth_preimage_tree_helper(self, Q, n, m, **kwds): D.update(self._nth_preimage_tree_helper(pt, n-1, m+1, **kwds)[0]) return D, points else: - if n==1: + if n == 1: # Base case of recursion return D else: @@ -3506,7 +3506,7 @@ def affine_preperiodic_model(self, m, n, return_conjugation=False): hyperplane_found = True break if not hyperplane_found: - raise ValueError('no possible conjugation over %s makes all preperiodic points affine' %R) + raise ValueError('no possible conjugation over %s makes all preperiodic points affine' % R) else: # if the characteristic is 0, R contains Z if R.characteristic() == 0: @@ -3541,7 +3541,7 @@ def affine_preperiodic_model(self, m, n, return_conjugation=False): if hyperplane_found: break else: - raise NotImplementedError('cannot find affine periodic model over %s' %(R)) + raise NotImplementedError('cannot find affine periodic model over %s' % (R)) source = PS.subscheme(CR.gens()[-1]) mat = PS.hyperplane_transformation_matrix(source, hyperplane) if R.is_field(): @@ -4176,7 +4176,7 @@ def critical_point_portrait(self, check=True, use_algebraic_closure=True): N = len(crit_points) for i in range(N): done = False - Q= F(crit_points[i]) + Q = F(crit_points[i]) while not done: if Q in crit_points: done = True @@ -6248,7 +6248,7 @@ def reduced_form(self, **kwds): pp_d = pts_poly.degree() pts_poly_CF = pts_poly_CF.subs({pts_poly_CF.parent().gen(1):1}).univariate_polynomial() max_mult = max([pp_d - pts_poly_CF.degree()] + [ex for p,ex in pts_poly_CF.roots()]) - assert (n<=4), "n > 4, failed to find usable poly" + assert (n <= 4), "n > 4, failed to find usable poly" G,m = pts_poly.reduced_form(prec=prec, emb=emb, smallest_coeffs=False) sm_f = self.conjugate(m) @@ -8150,7 +8150,7 @@ def is_conjugate(self, other, R=None, num_cpus=2): return m1.is_similar(m2) # sigma invariants are invariant under conjugacy but are only fast in dim 1 n = f.domain().dimension_relative() - if (n==1) and (R in NumberFields() or R in FiniteFields())\ + if (n == 1) and (R in NumberFields() or R in FiniteFields())\ and (f.sigma_invariants(1) != g.sigma_invariants(1)): return False tup = conjugating_set_initializer(f, g) diff --git a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py index cc4078c017a..f1ea230df16 100644 --- a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py +++ b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py @@ -364,8 +364,8 @@ def Gpoly(self, component, k): i = Indices[0] j = Indices[1] - return (self._Lcoeff(component, j)**2) * (self._Qcoeff(component, i, i)) - (self._Lcoeff(component, i))* \ - (self._Lcoeff(component, j)) * (self._Qcoeff(component, i, j)) + (self._Lcoeff( component, i)**2)* \ + return (self._Lcoeff(component, j)**2) * (self._Qcoeff(component, i, i)) - (self._Lcoeff(component, i)) * \ + (self._Lcoeff(component, j)) * (self._Qcoeff(component, i, j)) + (self._Lcoeff( component, i)**2) * \ (self._Qcoeff( component, j, j)) @cached_method @@ -668,11 +668,11 @@ def Ramification_poly(self, i): - 168*y0*y1^2*y2^3 - 122*y1^3*y2^3 + 14*y0^2*y2^4 + 8*y0*y1*y2^4 - 112*y1^2*y2^4 + y2^6 """ return ((self._Lcoeff(i, 0))**2)*(self._Qcoeff(i, 1, 2))**2 + \ - ((self._Lcoeff(i, 1))**2)*(self._Qcoeff(i, 0, 2)**2)+ \ - ((self._Lcoeff(i, 2))**2)*(self._Qcoeff(i, 0, 1)**2)- \ + ((self._Lcoeff(i, 1))**2)*(self._Qcoeff(i, 0, 2)**2) + \ + ((self._Lcoeff(i, 2))**2)*(self._Qcoeff(i, 0, 1)**2) - \ 2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 1))*(self._Qcoeff(i, 0, 2))*(self._Qcoeff(i, 1, 2))\ - -2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 1, 2))\ - -2*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 0, 2)) + \ + - 2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 1, 2))\ + - 2*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 0, 2)) + \ 4*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 1))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 2, 2)) + \ 4*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 2))*(self._Qcoeff(i, 1, 1)) + \ 4*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 1, 2))*(self._Qcoeff(i, 0, 0)) - \ @@ -1104,7 +1104,7 @@ def sigmaX(self, P, **kwds): try: P = self(list(P)) except (TypeError, NotImplementedError, AttributeError): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self)) + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self)) pt = list(P[0]) + [0, 0, 0] if P[1][0] != 0: [a,b,c] = [P[1][0]*self.Gpoly(1, 0)(*pt), @@ -1134,11 +1134,11 @@ def sigmaX(self, P, **kwds): #Define the blow-up map with (s0,s1) the new `\mathbb{P}^1` coordinates #so that the points on the fiber come in pairs on the lines defined by `(s0,s1)` #this allows us to extend the involution to degenerate fibers - if P[0][0]!= 0: + if P[0][0] != 0: t1 = BR(P[0][1]/P[0][0]) t = w1 - t1 phi = R.hom([s0, s0*w1, s1*t + s0*P[0][2]/P[0][0], z0, z1, z2], S) - elif P[0][1]!= 0: + elif P[0][1] != 0: t1 = BR(P[0][0]/P[0][1]) t = w1 - t1 phi = R.hom([s0*w1, s0, s1*t + s0*P[0][2]/P[0][1], z0, z1, z2], S) @@ -1215,7 +1215,7 @@ def sigmaX(self, P, **kwds): for i in range(2, len(T)): e = 0 if newT[i] != 0: - while (newT[i]/s**e).subs({s:0})==0: + while (newT[i]/s**e).subs({s:0}) == 0: e += 1 maxexp.append(e) e = min(maxexp) @@ -1346,7 +1346,7 @@ def sigmaY(self,P, **kwds): try: P = self(list(P)) except (TypeError, NotImplementedError, AttributeError): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self)) + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self)) pt = [0, 0, 0] + list(P[1]) if P[0][0] != 0: [a, b, c] = [P[0][0]*self.Gpoly(0, 0)(*pt), @@ -1380,7 +1380,7 @@ def sigmaY(self,P, **kwds): t1 = BR(P[1][1]/P[1][0]) t = w1 - t1 phi = R.hom([z0, z1, z2, s0, s0*w1, s1*t + s0*P[1][2]/P[1][0]], S) - elif P[1][1]!= 0: + elif P[1][1] != 0: t1 = BR(P[1][0]/P[1][1]) t = w1 - t1 phi = R.hom([z0, z1, z2, s0*w1, s0, s1*t + s0*P[1][2]/P[1][1]], S) @@ -1624,7 +1624,7 @@ def lambda_plus(self, P, v, N, m, n, prec=100): 0.89230705169161608922595928129 """ if not (v == 0 or v.is_prime()): - raise ValueError("invalid valuation (= %s) entered"%v) + raise ValueError("invalid valuation (= %s) entered" % v) R = RealField(prec) if v == 0: K = R @@ -1763,7 +1763,7 @@ def lambda_minus(self, P, v, N, m, n, prec=100): newQ = copy(Q) newQ.scale_by([1/Q[0][l], 1]) - if PK[1][i].abs()<= PK[1][k].abs(): + if PK[1][i].abs() <= PK[1][k].abs(): A = Rx(W.Gpoly(1, k))(tuple(newQ[0]))*PK[1][i]/PK[1][k] else: A = -Rx(W.Gpoly(1, i))(tuple(newQ[0]))*PK[1][k]/PK[1][i] @@ -2024,11 +2024,11 @@ def fiber(self, p, component): P0 = [Zero, Zero, Zero] + P Points = [] - if (self.Gpoly(component,0)(P0)!= 0): + if (self.Gpoly(component,0)(P0) != 0): #We are using the quadratic formula, we need this check to ensure that the points #will be rational - T0 = (self.Hpoly(component, 0, 1)(P0)**2 -4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 1)(P0)) - T1 = (self.Hpoly(component, 0, 2)(P0)**2 -4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 2)(P0)) + T0 = (self.Hpoly(component, 0, 1)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 1)(P0)) + T1 = (self.Hpoly(component, 0, 2)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 2)(P0)) if (T0.is_square() and T1.is_square()): T0 = T0.sqrt() T1 = T1.sqrt() diff --git a/src/sage/dynamics/cellular_automata/solitons.py b/src/sage/dynamics/cellular_automata/solitons.py index 7ae254ed69f..4afb3f104a2 100644 --- a/src/sage/dynamics/cellular_automata/solitons.py +++ b/src/sage/dynamics/cellular_automata/solitons.py @@ -951,7 +951,7 @@ def print_states(self, num=None, vacuum_letter='.'): state = [vacuum]*(num_factors - len(state)) + list(state) output = [self._column_repr(b, vacuum_letter) for b in state] max_width = max(b.width() for b in output) - start = ascii_art("t: %s \n"%i) + start = ascii_art("t: %s \n" % i) start._baseline = -1 print(start + sum((ascii_art(' '*(max_width-b.width())) + b for b in output), @@ -1024,7 +1024,7 @@ def latex_states(self, num=None, as_array=True, box_width='5pt'): def compact_repr(b): if as_array and b == vacuum: - return "\\makebox[%s]{.}"%box_width + return "\\makebox[%s]{.}" % box_width if b.parent()._tableau_height == 1: temp = latex(b[0]) @@ -1034,22 +1034,22 @@ def compact_repr(b): temp += "\\end{array}" if b == vacuum: - return "{\\color{gray} %s}"%temp + return "{\\color{gray} %s}" % temp return temp # "\\makebox[%s]{$%s$}"%(box_width, temp) num_factors = len(self._states[num-1]) if as_array: ret = "{\\arraycolsep=0.5pt \\begin{array}" - ret += "{c|c%s}\n"%('c'*num_factors) + ret += "{c|c%s}\n" % ('c'*num_factors) else: ret = "{\\begin{array}" ret += "{c|c}\n" for i,state in enumerate(self._states[:num]): state = [vacuum]*(num_factors-len(state)) + list(state) if as_array: - ret += "t = %s & \\cdots & %s \\\\\n"%(i, r" & ".join(compact_repr(b) for b in state)) + ret += "t = %s & \\cdots & %s \\\\\n" % (i, r" & ".join(compact_repr(b) for b in state)) else: - ret += "t = %s & \\cdots %s \\\\\n"%(i, r" ".join(compact_repr(b) for b in state)) + ret += "t = %s & \\cdots %s \\\\\n" % (i, r" ".join(compact_repr(b) for b in state)) ret += "\\end{array}}\n" return LatexExpr(ret) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index f0a8620011a..1b4a60b0013 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -4165,7 +4165,7 @@ def relative_quotient(self, subcone): Nsubcone = subcone.sublattice() extra_ray = None - if Ncone.dimension()-Nsubcone.dimension()==1: + if Ncone.dimension()-Nsubcone.dimension() == 1: extra_ray = set(self.rays().set() - subcone.rays().set()).pop() Q = Ncone.quotient(Nsubcone, positive_point=extra_ray) @@ -4262,7 +4262,7 @@ def relative_orthogonal_quotient(self, supercone): Msupercone = supercone.orthogonal_sublattice() extra_ray = None - if Mcone.dimension()-Msupercone.dimension()==1: + if Mcone.dimension()-Msupercone.dimension() == 1: extra_ray = set(supercone.rays().set() - self.rays().set()).pop() Q = Mcone.quotient(Msupercone, positive_dual_point=extra_ray) @@ -4391,7 +4391,7 @@ def semigroup_generators(self): origin = self.nrays() # last one in pc pc = PointConfiguration(tuple(self.rays()) + (N(0),), star=origin) triangulation = pc.triangulate() - subcones = ( Cone(( self.ray(i) for i in simplex if i!=origin ), + subcones = ( Cone(( self.ray(i) for i in simplex if i != origin ), lattice=N, check=False) for simplex in triangulation ) gens = set() diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 26c7d9a3819..7847955db7b 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -3239,7 +3239,7 @@ def index_of_max(iterable): * permutations[n_s][1] if d == 0: d = (PM[k, permutations[n_s][1](i+1) - 1] - -permutations[0][1](first_row)[i]) + - permutations[0][1](first_row)[i]) if d < 0: break if d < 0: @@ -3309,7 +3309,7 @@ def index_of_max(iterable): if d < 0: # We move to the next line continue - elif d==0: + elif d == 0: # Maximal values agree, so possible symmetry if s != l: permutations_bar[n_p][0] = S_f((l + 1, s + 1), check=False) * permutations_bar[n_p][0] diff --git a/src/sage/geometry/polyhedron/backend_polymake.py b/src/sage/geometry/polyhedron/backend_polymake.py index 624ae2f6340..089e687f3f8 100644 --- a/src/sage/geometry/polyhedron/backend_polymake.py +++ b/src/sage/geometry/polyhedron/backend_polymake.py @@ -537,7 +537,7 @@ def _init_Hrepresentation_from_polymake(self): self._Hrepresentation = [] parent = self.parent() for g in p.FACETS.sage(): - if all(x==0 for x in g[1:]): + if all(x == 0 for x in g[1:]): # Ignore vertical inequality pass else: diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 007f000eb56..d31c5bc254c 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -38,7 +38,7 @@ def _is_zero(self, x): sage: p._is_zero(1/100000) False """ - return x==0 + return x == 0 def _is_nonneg(self, x): """ @@ -60,7 +60,7 @@ def _is_nonneg(self, x): sage: p._is_nonneg(-1/100000) False """ - return x>=0 + return x >= 0 def _is_positive(self, x): """ @@ -82,7 +82,7 @@ def _is_positive(self, x): sage: p._is_positive(0) False """ - return x>0 + return x > 0 _base_ring = QQ diff --git a/src/sage/geometry/polyhedron/base_RDF.py b/src/sage/geometry/polyhedron/base_RDF.py index fe75503edf2..b3ba587746e 100644 --- a/src/sage/geometry/polyhedron/base_RDF.py +++ b/src/sage/geometry/polyhedron/base_RDF.py @@ -45,7 +45,7 @@ def _is_zero(self, x): sage: p._is_zero(1e-10) True """ - return abs(x)<=1e-6 + return abs(x) <= 1e-6 def _is_nonneg(self, x): """ @@ -72,7 +72,7 @@ def _is_nonneg(self, x): sage: p._is_nonneg(-1e-10) True """ - return x>=-1e-6 + return x >= -1e-6 def _is_positive(self, x): """ @@ -99,6 +99,6 @@ def _is_positive(self, x): sage: p._is_positive(-1e-10) True """ - return x>=-1e-6 + return x >= -1e-6 _base_ring = RDF diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 561ed76d70c..5e6633c7b3f 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -736,12 +736,12 @@ def _subpoly_parallel_facets(self): sage: list( Polyhedron()._subpoly_parallel_facets() ) [The empty polyhedron in ZZ^0] """ - if self.dim()>2 or not self.is_compact(): + if self.dim() > 2 or not self.is_compact(): raise NotImplementedError('only implemented for bounded polygons') from sage.geometry.polyhedron.plot import cyclic_sort_vertices_2d vertices = cyclic_sort_vertices_2d(self.vertices()) n = len(vertices) - if n==1: # single point + if n == 1: # single point yield self return edge_vectors = [] @@ -759,7 +759,7 @@ def _subpoly_parallel_facets(self): for e in edges: point += e v.append(point) - if point!=origin: # does not close up, not a subpolygon + if point != origin: # does not close up, not a subpolygon continue yield parent([v, [], []], None) diff --git a/src/sage/geometry/polyhedron/cdd_file_format.py b/src/sage/geometry/polyhedron/cdd_file_format.py index 4388f2ecb0b..728f20bb9b5 100644 --- a/src/sage/geometry/polyhedron/cdd_file_format.py +++ b/src/sage/geometry/polyhedron/cdd_file_format.py @@ -128,7 +128,7 @@ def cdd_Hrepresentation(cdd_type, ieqs, eqns, file_output=None): s = 'H-representation\n' if eqns is not None: - assert len(eqns)>0 + assert len(eqns) > 0 n = len(eqns) s += "linearity " + repr(n) + ' ' s += _to_space_separated_string(range(1,n+1)) + '\n' diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 91e4d4de82f..e62e108e61d 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -153,13 +153,13 @@ def LatticePolytope_PPL(*args): TypeError: polyhedron has non-integral generators """ polytope_class = LatticePolytope_PPL_class - if len(args)==1 and isinstance(args[0], C_Polyhedron): + if len(args) == 1 and isinstance(args[0], C_Polyhedron): polyhedron = args[0] polytope_class = _class_for_LatticePolytope(polyhedron.space_dimension()) if not all(p.is_point() and p.divisor() == 1 for p in polyhedron.generators()): raise TypeError('polyhedron has non-integral generators') return polytope_class(polyhedron) - if len(args)==1 \ + if len(args) == 1 \ and isinstance(args[0], (list, tuple)) \ and isinstance(args[0][0], (list,tuple)): vertices = args[0] @@ -278,7 +278,7 @@ def is_simplex(self): sage: LatticePolytope_PPL((0,0,0), (1,0,0), (0,1,0)).is_simplex() True """ - return self.affine_dimension()+1==self.n_vertices() + return self.affine_dimension()+1 == self.n_vertices() @cached_method def bounding_box(self): @@ -467,7 +467,7 @@ def integral_points_not_interior_to_facets(self): ((-1, -1), (-1, 1), (0, 0), (1, -1), (1, 1)) """ n = 1 + self.space_dimension() - self.affine_dimension() - return tuple(p[0] for p in self._integral_points_saturating() if len(p[1])!=n) + return tuple(p[0] for p in self._integral_points_saturating() if len(p[1]) != n) @cached_method def vertices(self): @@ -586,7 +586,7 @@ def fibration_generator(self, dim): # "points" are the potential vertices of the fiber. They are # in the $codim$-skeleton of the polytope, which is contained # in the points that saturate at least $dim$ equations. - points = [ p for p in self._integral_points_saturating() if len(p[1])>=dim ] + points = [ p for p in self._integral_points_saturating() if len(p[1]) >= dim ] points = sorted(points, key=lambda x:len(x[1])) # iterate over point combinations subject to all points being on one facet. @@ -597,7 +597,7 @@ def point_combinations_iterator(n, i0=0, saturated=None): saturated_ieqs = ieqs else: saturated_ieqs = saturated.intersection(ieqs) - if len(saturated_ieqs)==0: + if len(saturated_ieqs) == 0: continue if n == 1: yield [i] diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index 554e36ec239..76a7d8831fa 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -1068,7 +1068,7 @@ def _repr_(self): have_A = not self.A().is_zero() if have_A: s += repr(self.A()) + ' x ' - if self.b()>=0: + if self.b() >= 0: if have_A: s += '+' else: diff --git a/src/sage/geometry/pseudolines.py b/src/sage/geometry/pseudolines.py index 8ce4496c65a..cc52979b577 100644 --- a/src/sage/geometry/pseudolines.py +++ b/src/sage/geometry/pseudolines.py @@ -240,9 +240,9 @@ def __init__(self, seq, encoding="auto"): self._n = max(map(max, seq)) + 1 if (self._n * (self._n-1))/2 != len(seq): raise ValueError( - "A line is numbered "+str(self._n-1)+" but the number"+ - " of transpositions is different from binomial("+ - str(self._n-1)+",2). Are the lines numbered from 0 to n-1?"+ + "A line is numbered "+str(self._n-1)+" but the number" + + " of transpositions is different from binomial(" + + str(self._n-1)+",2). Are the lines numbered from 0 to n-1?" + " Are they really non-parallel? Please check the documentation.") self._permutations = [[] for i in range(self._n)] @@ -258,12 +258,12 @@ def __init__(self, seq, encoding="auto"): self._n = len(seq) self._permutations = [list(_) for _ in seq] - if max(map(max, seq)) != self._n -1 : + if max(map(max, seq)) != self._n - 1 : raise ValueError("Are the lines really numbered from 0 to n-1?") # Felsner encoding elif (encoding == "Felsner" or - (encoding == "auto" and len(seq[0]) == len(seq) -1)): + (encoding == "auto" and len(seq[0]) == len(seq) - 1)): seq = deepcopy(seq) self._n = len(seq) @@ -339,14 +339,14 @@ def transpositions(self): k = 0 while i != perm[perm[i][0]][0]: i = perm[i][0] - k+= 1 + k += 1 if k > self._n: raise ValueError( - "It looks like the data does not correspond to a"+ - "pseudoline arrangement. We have found k>2 lines"+ - "such that the ith line meets the (i+1)th before"+ - " the (i-1)th (this creates a cyclic dependency)"+ + "It looks like the data does not correspond to a" + + "pseudoline arrangement. We have found k>2 lines" + + "such that the ith line meets the (i+1)th before" + + " the (i-1)th (this creates a cyclic dependency)" + " which is totally impossible.") t.append((i, perm[i][0])) @@ -446,10 +446,10 @@ def show(self, **args): if abs(iy-jy) != 1: raise ValueError( - "There has been a problem while plotting the figure. It "+ - "seems that the lines are not correctly ordered. Please "+ + "There has been a problem while plotting the figure. It " + + "seems that the lines are not correctly ordered. Please " + "check the pseudolines modules documentation, there is a " - +"warning about that. ") + + "warning about that. ") lines[i].append((x+2,jy)) lines[j].append((x+2,iy)) diff --git a/src/sage/geometry/ribbon_graph.py b/src/sage/geometry/ribbon_graph.py index 809d6edba9a..12918ae29b5 100644 --- a/src/sage/geometry/ribbon_graph.py +++ b/src/sage/geometry/ribbon_graph.py @@ -988,7 +988,7 @@ def homology_basis(self): del vertices[i][2*m:2*m+2] k = 0 else: - k+=1 + k += 1 for i in range(len(basis)): for j in range(1, len(basis[i])): @@ -1074,9 +1074,9 @@ def normalize(self): pos_sigma = _find(aux_sigma,aux_val) #Now we set the found positions to the new normalized value - darts_rho[pos_darts]=i+1 - aux_sigma[pos_sigma[0]][pos_sigma[1]]=i+1 - aux_rho[pos_rho[0]][pos_rho[1]]=i+1 + darts_rho[pos_darts] = i+1 + aux_sigma[pos_sigma[0]][pos_sigma[1]] = i+1 + aux_rho[pos_rho[0]][pos_rho[1]] = i+1 return RibbonGraph( PermutationConstructor([tuple(x) for x in aux_sigma]), @@ -1213,7 +1213,7 @@ def bipartite_ribbon_graph(p, q): aux_tuple = [i*q + j + 1 for j in range(q)] sigma += [aux_tuple] for i in range(q): - aux_tuple = [p*q + i*p + j +1 for j in range(p)] + aux_tuple = [p*q + i*p + j + 1 for j in range(p)] sigma += [aux_tuple] for i in range(p*q): if (i+1) % q == 0: @@ -1223,7 +1223,7 @@ def bipartite_ribbon_graph(p, q): t = 0 if (i+1) % q != 0: t = 1 - aux_edge = [i+1, p*q + k*p - ((i+1 + t*q)/q).floor() +1] + aux_edge = [i+1, p*q + k*p - ((i+1 + t*q)/q).floor() + 1] rho += [aux_edge] return RibbonGraph( PermutationConstructor([tuple(x) for x in sigma]), diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index c0161ab0c4f..fd56b956c90 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -415,7 +415,7 @@ def _repr_(self): name = 'Parametrized surface' if self.name is not None: name += " ('%s')" % self.name - s ='%(designation)s with equation %(eq)s' % \ + s = '%(designation)s with equation %(eq)s' % \ {'designation': name, 'eq': str(self.equation)} return s @@ -1410,7 +1410,7 @@ def shape_operator(self): """ shop = self.shape_operator_coefficients() - shop_matrix=matrix([[shop[(1,1)],shop[(1,2)]], + shop_matrix = matrix([[shop[(1,1)],shop[(1,2)]], [shop[(2,1)],shop[(2,2)]]]) return shop_matrix @@ -1492,10 +1492,10 @@ def connection_coefficients(self): for i,j,k in product((1, 2), repeat=3): dg[(i,j,k)] = _simplify_full_rad(gg[(j,k)].differentiate(x[i])) - structfun={} + structfun = {} for i,j,k in product((1, 2), repeat=3): structfun[(i,j,k)] = sum(gi[(k,s)]*(dg[(i,j,s)] + dg[(j,i,s)] - -dg[(s,i,j)])/2 + - dg[(s,i,j)])/2 for s in (1,2)) structfun[(i,j,k)] = _simplify_full_rad(structfun[(i,j,k)]) return structfun diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index c5d35bb2002..a72f31f04d2 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -582,9 +582,9 @@ def direct_sum(self, other): def make_name(N1, N2, use_latex=False): if use_latex: - return latex(N1)+ r' \oplus ' +latex(N2) + return latex(N1) + r' \oplus ' + latex(N2) else: - return N1._name+ '+' +N2._name + return N1._name + '+' + N2._name rank = self.rank() + other.rank() name = make_name(self, other, False) @@ -1492,7 +1492,7 @@ def __init__(self, V, W, check=True, positive_point=None, positive_dual_point=No return self._flip_sign_of_generator = False - assert self.is_torsion_free() and self.ngens()==1, \ + assert self.is_torsion_free() and self.ngens() == 1, \ 'You may only specify a positive direction in the codimension one case.' quotient_generator = self.gen(0) lattice = self.V().ambient_module() @@ -1500,16 +1500,16 @@ def __init__(self, V, W, check=True, positive_point=None, positive_dual_point=No assert positive_point in lattice, 'positive_point must be a lattice point.' point_quotient = self(positive_point) scalar_product = quotient_generator.vector()[0] * point_quotient.vector()[0] - if scalar_product==0: + if scalar_product == 0: raise ValueError(str(positive_point)+' is zero in the quotient.') elif (positive_point is None) and (positive_dual_point is not None): assert positive_dual_point in lattice.dual(), 'positive_dual_point must be a dual lattice point.' scalar_product = quotient_generator.lift() * positive_dual_point - if scalar_product==0: + if scalar_product == 0: raise ValueError(str(positive_dual_point)+' is zero on the lift of the quotient generator.') else: raise ValueError('You may not specify both positive_point and positive_dual_point.') - self._flip_sign_of_generator = (scalar_product<0) + self._flip_sign_of_generator = (scalar_product < 0) def gens(self): """ @@ -1529,7 +1529,7 @@ def gens(self): """ gens = self.smith_form_gens() if self._flip_sign_of_generator: - assert len(gens)==1 + assert len(gens) == 1 return (-gens[0],) else: return gens diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index 7486488adb1..16b55ab7cac 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -80,9 +80,9 @@ def triangulation_render_2d(triangulation, **kwds): tmp_lines = [] for t in triangulation: - if len(t)>=2: + if len(t) >= 2: tmp_lines.append([t[0], t[1]]) - if len(t)>=3: + if len(t) >= 3: tmp_lines.append([t[0], t[2]]) tmp_lines.append([t[1], t[2]]) all_lines = [] @@ -103,7 +103,7 @@ def triangulation_render_2d(triangulation, **kwds): plot_triangs = sum([ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]], zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds) - for t in triangulation if len(t)>=3 ]) + for t in triangulation if len(t) >= 3 ]) return \ plot_points + \ @@ -142,12 +142,12 @@ def triangulation_render_3d(triangulation, **kwds): tmp_lines = [] for t in triangulation: - if len(t)>=2: + if len(t) >= 2: tmp_lines.append([t[0], t[1]]) - if len(t)>=3: + if len(t) >= 3: tmp_lines.append([t[0], t[2]]) tmp_lines.append([t[1], t[2]]) - if len(t)>=4: + if len(t) >= 4: tmp_lines.append([t[0], t[3]]) tmp_lines.append([t[1], t[3]]) tmp_lines.append([t[2], t[3]]) @@ -175,9 +175,9 @@ def triangulation_render_3d(triangulation, **kwds): tmp_triangs = [] for t in triangulation: - if len(t)>=3: + if len(t) >= 3: tmp_triangs.append([t[0], t[1], t[2]]) - if len(t)>=4: + if len(t) >= 4: tmp_triangs.append([t[0], t[1], t[3]]) tmp_triangs.append([t[0], t[2], t[3]]) tmp_triangs.append([t[1], t[2], t[3]]) @@ -265,7 +265,7 @@ def __init__(self, triangulation, parent, check=True): except TypeError: triangulation = tuple( self.point_configuration().int_to_simplex(i) for i in triangulation ) - assert not check or all( len(t)==self.point_configuration().dim()+1 + assert not check or all( len(t) == self.point_configuration().dim()+1 for t in triangulation) self._triangulation = triangulation @@ -924,4 +924,4 @@ def adjacency_graph(self): """ vertices = [Set(_) for _ in list(self)] return Graph([vertices, - lambda x,y: len(x-y)==1]) + lambda x,y: len(x-y) == 1]) diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index d75af2af4ce..14afe670c16 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -287,7 +287,7 @@ def _have_TOPCOM(cls): out = next(PointConfiguration._TOPCOM_exec('points2placingtriang', '[[0,1],[1,1]]', verbose=False)) PointConfiguration._have_TOPCOM_cached = True - assert out=='{{0,1}}',\ + assert out == '{{0,1}}',\ 'TOPCOM ran but did not produce the correct output!' except pexpect.ExceptionPexpect: PointConfiguration._have_TOPCOM_cached = False @@ -320,7 +320,7 @@ def __classcall__(cls, points, projective=False, connected=True, fine=False, reg defined_affine = True if star is not None and star not in ZZ: star_point = tuple(star) - if len(star_point)0 for t in triangulation): + if not all( t.count(o) > 0 for t in triangulation): continue yield self(triangulation) @@ -1228,7 +1228,7 @@ def face_interior(self, dim=None, codim=None): d = [ self.face_codimension(i) for i in range(self.n_points()) ] - return tuple( tuple(i for i in range(self.n_points()) if d[i]==codim ) + return tuple( tuple(i for i in range(self.n_points()) if d[i] == codim ) for codim in range(self.dim()+1) ) def exclude_points(self, point_idx_list): @@ -1408,12 +1408,12 @@ def circuits_support(self): independent_k = [] for idx in possible_dependency: rk = matrix([ U[i] for i in idx ]).rank() - if rk==k: + if rk == k: independent_k.append(idx) else: supports_k.append(idx) yield idx - assert independent_k==[] # there are no independent (self.dim()+3)-tuples + assert independent_k == [] # there are no independent (self.dim()+3)-tuples def circuits(self): r""" @@ -1476,9 +1476,9 @@ def circuits(self): for support in self.circuits_support(): m = matrix([ U[i] for i in support ]).transpose() ker = m.right_kernel().basis()[0] - assert len(ker)==len(support) - Cplus = [ support[i] for i in range(len(support)) if ker[i]>0 ] - Cminus = [ support[i] for i in range(len(support)) if ker[i]<0 ] + assert len(ker) == len(support) + Cplus = [ support[i] for i in range(len(support)) if ker[i] > 0 ] + Cminus = [ support[i] for i in range(len(support)) if ker[i] < 0 ] Czero = set( range(n) ).difference(support) Circuits += ( (tuple(Cplus), tuple(Czero), tuple(Cminus)), ) self._circuits = Circuits @@ -1627,7 +1627,7 @@ def lexicographic_triangulation(self): basepts = [ b[1:] for b in basepts ] # undecorate def make_cotriang(basepts): - if len(basepts)==0: + if len(basepts) == 0: return [frozenset()] triangulation = set() for tail in make_cotriang(basepts[1:]): @@ -1782,7 +1782,7 @@ def farthest_point(self, points, among=None): sage: pc.farthest_point([pc.point(0)]) P(1, 1) """ - if len(points)==0: + if len(points) == 0: return self.point(0) if among is None: among = self.points() @@ -1795,7 +1795,7 @@ def farthest_point(self, points, among=None): d_max = min(self.distance(p,q) for q in points) continue d = min(self.distance(p,q) for q in points) - if d>d_max: + if d > d_max: p_max = p return p_max diff --git a/src/sage/graphs/base/static_dense_graph.pyx b/src/sage/graphs/base/static_dense_graph.pyx index 2014289457d..78711fae2f1 100644 --- a/src/sage/graphs/base/static_dense_graph.pyx +++ b/src/sage/graphs/base/static_dense_graph.pyx @@ -344,7 +344,7 @@ def triangles_count(G): sage: from sage.graphs.base.static_dense_graph import triangles_count sage: triangles_count(graphs.PetersenGraph()) {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0} - sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3 * binomial(15, 3) + sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3 * binomial(15, 3) # needs sage.symbolic True """ from sage.rings.integer import Integer diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index b5462299058..4b98ff027a3 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -925,7 +925,7 @@ def triangles_count(G): sage: from sage.graphs.base.static_sparse_graph import triangles_count sage: triangles_count(graphs.PetersenGraph()) {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0} - sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3*binomial(15,3) + sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3*binomial(15,3) # needs sage.symbolic True """ from sage.rings.integer import Integer @@ -1023,8 +1023,8 @@ def spectral_radius(G, prec=1e-10): sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(2,4),(3,4)]) sage: e_min, e_max = spectral_radius(G, 1e-14) - sage: e = max(G.adjacency_matrix().charpoly().roots(AA, multiplicities=False)) # needs sage.modules - sage: e_min < e < e_max # needs sage.modules + sage: e = max(G.adjacency_matrix().charpoly().roots(AA, multiplicities=False)) # needs sage.modules sage.rings.number_field + sage: e_min < e < e_max # needs sage.modules sage.rings.number_field sage.symbolic True sage: G.spectral_radius() # abs tol 1e-9 @@ -1041,8 +1041,8 @@ def spectral_radius(G, prec=1e-10): sage: p = G.adjacency_matrix(sparse=True).charpoly() sage: p x^201 - x^199 - 1 - sage: r = p.roots(AA, multiplicities=False)[0] - sage: e_min < r < e_max + sage: r = p.roots(AA, multiplicities=False)[0] # needs sage.rings.number_field + sage: e_min < r < e_max # needs sage.rings.number_field True A much larger example:: @@ -1061,7 +1061,7 @@ def spectral_radius(G, prec=1e-10): sage: G.add_edges([(0,0),(0,0),(0,1),(1,0)]) sage: spectral_radius(G, 1e-14) # abs tol 1e-14 (2.414213562373094, 2.414213562373095) - sage: max(G.adjacency_matrix().eigenvalues(AA)) # needs sage.modules + sage: max(G.adjacency_matrix().eigenvalues(AA)) # needs sage.modules sage.rings.number_field 2.414213562373095? Some bipartite graphs:: @@ -1092,7 +1092,7 @@ def spectral_radius(G, prec=1e-10): ... ValueError: precision (=1.00000000000000e-20) is too small - sage: for _ in range(100): # needs sage.modules + sage: for _ in range(100): # needs sage.modules sage.rings.number_field ....: G = digraphs.RandomDirectedGNM(10,35) ....: if not G.is_strongly_connected(): ....: continue diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index f707ee2a968..8cc866616ce 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -651,8 +651,7 @@ def __repr__(self): s = Graph._repr_(self).lower() if "bipartite" in s: return s.capitalize() - else: - return "".join(["Bipartite ", s]) + return "".join(["Bipartite ", s]) def add_vertex(self, name=None, left=False, right=False): """ @@ -734,8 +733,7 @@ def add_vertex(self, name=None, left=False, right=False): if ((left and name in self.left) or (right and name in self.right)): return - else: - raise RuntimeError("cannot add duplicate vertex to other partition") + raise RuntimeError("cannot add duplicate vertex to other partition") # add the vertex retval = Graph.add_vertex(self, name) @@ -1311,8 +1309,7 @@ def is_bipartite(self, certificate=False): color = {u: 0 for u in self.left} color.update({u: 1 for u in self.right}) return True, color - else: - return True + return True def complement(self): r""" @@ -1507,7 +1504,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): EXAMPLES:: - sage: BipartiteGraph(graphs.CubeGraph(3)).matching_polynomial() + sage: BipartiteGraph(graphs.CubeGraph(3)).matching_polynomial() # needs sage.libs.flint x^8 - 12*x^6 + 42*x^4 - 44*x^2 + 9 :: @@ -1530,14 +1527,15 @@ def matching_polynomial(self, algorithm="Godsil", name=None): polynomial:: sage: g = graphs.RandomTree(20) - sage: p = g.characteristic_polynomial() - sage: p == BipartiteGraph(g).matching_polynomial(algorithm='rook') + sage: p = g.characteristic_polynomial() # needs sage.modules + sage: p == BipartiteGraph(g).matching_polynomial(algorithm='rook') # needs sage.modules True TESTS:: + sage: # needs sage.modules sage: g = BipartiteGraph(matrix.ones(4, 3)) - sage: g.matching_polynomial() + sage: g.matching_polynomial() # needs sage.libs.flint x^7 - 12*x^5 + 36*x^3 - 24*x sage: g.matching_polynomial(algorithm="rook") x^7 - 12*x^5 + 36*x^3 - 24*x @@ -1558,8 +1556,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): K = PolynomialRing(A.base_ring(), name) p = K(b) return p - else: - raise ValueError('algorithm must be one of "Godsil" or "rook"') + raise ValueError('algorithm must be one of "Godsil" or "rook"') def perfect_matchings(self, labels=False): r""" @@ -2138,7 +2135,7 @@ class :class:`MixedIntegerLinearProgram 4 sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Edmonds') # needs networkx 4 - sage: B.matching(use_edge_labels=True, value_only=True, algorithm='LP') + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='LP') # needs sage.numerical.mip 4 sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Eppstein') Traceback (most recent call last): @@ -2156,7 +2153,7 @@ class :class:`MixedIntegerLinearProgram 2 sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Edmonds') # needs networkx 2 - sage: B.matching(use_edge_labels=False, value_only=True, algorithm='LP') + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='LP') # needs sage.numerical.mip 2 With multiedges enabled:: @@ -2212,8 +2209,7 @@ class :class:`MixedIntegerLinearProgram if value_only: return Integer(len(d)) - else: - return d + return d elif algorithm == "Edmonds" or algorithm == "LP": return Graph.matching(self, value_only=value_only, @@ -2221,9 +2217,8 @@ class :class:`MixedIntegerLinearProgram use_edge_labels=use_edge_labels, solver=solver, verbose=verbose, integrality_tolerance=integrality_tolerance) - else: - raise ValueError('algorithm must be "Hopcroft-Karp", ' - '"Eppstein", "Edmonds" or "LP"') + raise ValueError('algorithm must be "Hopcroft-Karp", ' + '"Eppstein", "Edmonds" or "LP"') def vertex_cover(self, algorithm="Konig", value_only=False, reduction_rules=True, solver=None, verbose=0, @@ -2302,7 +2297,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, The two algorithms should return the same result:: - sage: # needs numpy + sage: # needs networkx numpy sage: g = BipartiteGraph(graphs.RandomBipartite(10, 10, .5)) sage: vc1 = g.vertex_cover(algorithm="Konig") sage: vc2 = g.vertex_cover(algorithm="Cliquer") @@ -2687,5 +2682,4 @@ class by some canonization function `c`. If `G` and `H` are graphs, if certificate: return C, cert - else: - return C + return C diff --git a/src/sage/graphs/chrompoly.pyx b/src/sage/graphs/chrompoly.pyx index d0611a3df84..f596272219e 100644 --- a/src/sage/graphs/chrompoly.pyx +++ b/src/sage/graphs/chrompoly.pyx @@ -1,4 +1,5 @@ # cython: binding=True +# sage.doctest: needs sage.libs.flint sage.graphs """ Chromatic polynomial diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index 9e4942e75e6..5a206221da9 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -1078,8 +1078,9 @@ def edge_connectivity(G, sage: for u,v in tree.edge_iterator(labels=None): ....: tree.set_edge_label(u, v, random()) sage: minimum = min(tree.edge_labels()) - sage: [_, [(_, _, l)]] = edge_connectivity(tree, value_only=False, use_edge_labels=True) - sage: l == minimum + sage: [_, [(_, _, l)]] = edge_connectivity(tree, value_only=False, # needs sage.numerical.mip + ....: use_edge_labels=True) + sage: l == minimum # needs sage.numerical.mip True When ``value_only=True`` and ``implementation="sage"``, this function is @@ -1102,12 +1103,14 @@ def edge_connectivity(G, We check that the result with Boost is the same as the result without Boost:: sage: g = graphs.RandomGNP(15, .3) - sage: edge_connectivity(g, implementation="boost") == edge_connectivity(g, implementation="sage") + sage: (edge_connectivity(g, implementation="boost") # needs sage.numerical.mip + ....: == edge_connectivity(g, implementation="sage")) True Boost interface also works with directed graphs:: - sage: edge_connectivity(digraphs.Circuit(10), implementation="boost", vertices=True) + sage: edge_connectivity(digraphs.Circuit(10), implementation="boost", + ....: vertices=True) [1, [(0, 1)], [{0}, {1, 2, 3, 4, 5, 6, 7, 8, 9}]] However, the Boost algorithm is not reliable if the input is directed @@ -1128,7 +1131,7 @@ def edge_connectivity(G, Checking that the two implementations agree:: - sage: for i in range(10): + sage: for i in range(10): # needs sage.numerical.mip ....: g = graphs.RandomGNP(30, 0.3) ....: e1 = edge_connectivity(g, implementation="boost") ....: e2 = edge_connectivity(g, implementation="sage") diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index b2a96335d44..c422d0c3190 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -132,7 +132,7 @@ cdef class ConvexityProperties: sage: CP = ConvexityProperties(g) sage: CP.hull([1, 3]) [1, 2, 3] - sage: CP.hull_number() + sage: CP.hull_number() # needs sage.numerical.mip 3 TESTS:: @@ -410,10 +410,10 @@ cdef class ConvexityProperties: sage: from sage.graphs.convexity_properties import ConvexityProperties sage: g = graphs.PetersenGraph() sage: CP = ConvexityProperties(g) - sage: CP.hull_number() + sage: CP.hull_number() # needs sage.numerical.mip 3 - sage: generating_set = CP.hull_number(value_only=False) - sage: CP.hull(generating_set) + sage: generating_set = CP.hull_number(value_only=False) # needs sage.numerical.mip + sage: CP.hull(generating_set) # needs sage.numerical.mip [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] """ cdef int i diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index d30d5e63efa..c57224eba22 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -905,8 +905,7 @@ def dig6_string(self): raise ValueError('dig6 format supports graphs on 0 to 262143 vertices only') elif self.has_multiple_edges(): raise ValueError('dig6 format does not support multiple edges') - else: - return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) + return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) # Attributes @@ -1641,8 +1640,7 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, integrality_tolerance=integrality_tolerance) if value_only: return FAS + len(loops) - else: - return FAS + loops + return FAS + loops if not self.is_strongly_connected(): # If the digraph is not strongly connected, we solve the problem on @@ -2366,12 +2364,11 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, if with_labels: return ecc - else: - if len(ecc) == 1: - # return single value - v, = ecc.values() - return v - return [ecc[u] for u in v] + if len(ecc) == 1: + # return single value + v, = ecc.values() + return v + return [ecc[u] for u in v] def radius(self, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -3264,8 +3261,7 @@ def topological_sort(self, implementation="default"): else: return S - else: - raise ValueError("implementation must be set to one of \"default\" or \"NetworkX\"") + raise ValueError("implementation must be set to one of \"default\" or \"NetworkX\"") def topological_sort_generator(self): """ @@ -3365,8 +3361,7 @@ def layout_acyclic(self, rankdir="up", **options): """ if have_dot2tex(): return self.layout_graphviz(rankdir=rankdir, **options) - else: - return self.layout_acyclic_dummy(rankdir=rankdir, **options) + return self.layout_acyclic_dummy(rankdir=rankdir, **options) def layout_acyclic_dummy(self, heights=None, rankdir='up', **options): """ diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index 3070cb2f37f..ec2f608e28c 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -182,7 +182,7 @@ class DiGraphGenerators(): sage: L = list(digraphs(4, lambda G: G.size() <= 3)) sage: len(L) 20 - sage: graphs_list.show_graphs(L) # long time + sage: graphs_list.show_graphs(L) # long time # needs sage.plot Generate all digraphs with degree at most 2, up to 5 vertices:: @@ -371,7 +371,7 @@ def StronglyRegular(self, n): A Strongly Regular digraph satisfies the condition `AJ = JA = kJ` where `A` is the adjacency matrix:: - sage: # needs sage.modules + sage: # needs sage.combinat sage.modules sage: g = digraphs.StronglyRegular(7); g Strongly regular digraph: Digraph on 7 vertices sage: A = g.adjacency_matrix()*ones_matrix(7) @@ -383,7 +383,7 @@ def StronglyRegular(self, n): Wrong parameter:: - sage: digraphs.StronglyRegular(73) # needs sage.modules + sage: digraphs.StronglyRegular(73) # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: strongly regular digraph with 73 vertices not yet implemented @@ -516,7 +516,7 @@ def RandomTournament(self, n): sage: T = digraphs.RandomTournament(10); T Random Tournament: Digraph on 10 vertices - sage: T.size() == binomial(10, 2) + sage: T.size() == binomial(10, 2) # needs sage.symbolic True sage: T.is_tournament() True @@ -1635,7 +1635,7 @@ def RandomSemiComplete(self, n): sage: SC = digraphs.RandomSemiComplete(10); SC Random Semi-Complete digraph: Digraph on 10 vertices - sage: SC.size() >= binomial(10, 2) + sage: SC.size() >= binomial(10, 2) # needs sage.symbolic True sage: digraphs.RandomSemiComplete(-1) Traceback (most recent call last): diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 73bbd2c62d6..9445442f603 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -2294,7 +2294,7 @@ def szeged_index(G, algorithm=None): Check that both algorithms return same value:: - sage: # long time + sage: # long time, needs networkx sage: G = graphs.RandomBarabasiAlbert(100, 2) sage: a = szeged_index(G, algorithm='low') sage: b = szeged_index(G, algorithm='high') diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index 37416d428a8..0dcab74e90c 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -344,7 +344,7 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, Minimum connected dominating sets of the Peterson graph:: sage: G = graphs.PetersenGraph() - sage: G.dominating_set(total=True, value_only=True) + sage: G.dominating_set(total=True, value_only=True) # needs sage.numerical.mip 4 sage: sorted(G.dominating_sets(k=1, connected=True)) [[0, 1, 2, 6], @@ -361,7 +361,8 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, Subgraph induced by the dominating set is connected:: sage: G = graphs.PetersenGraph() - sage: all(G.subgraph(vertices=dom).is_connected() for dom in G.dominating_set(k=1, connected=True)) + sage: all(G.subgraph(vertices=dom).is_connected() + ....: for dom in G.dominating_set(k=1, connected=True)) True Minimum distance-k connected dominating sets of the Tietze graph:: @@ -375,7 +376,7 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, TESTS:: sage: g = Graph([(0, 1)]) - sage: next(g.dominating_sets(k=-1)) # needs sage.numerical.mip + sage: next(g.dominating_sets(k=-1)) Traceback (most recent call last): ... ValueError: the domination distance must be a non-negative integer diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 314d66aef43..5dfe78f01a8 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -43,7 +43,7 @@ def BullGraph(): sage: g = graphs.BullGraph(); g Bull graph: Graph on 5 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot The bull graph has 5 vertices and 5 edges. Its radius is 2, its diameter 3, and its girth 3. The bull graph is planar with chromatic @@ -66,10 +66,13 @@ def BullGraph(): `x` is a variable, `A` the adjacency matrix of the graph, and `I` the identity matrix of the same dimensions as `A`:: + sage: # needs sage.libs.flint sage: chrompoly = g.chromatic_polynomial() sage: x = chrompoly.parent()('x') sage: x * (x - 2) * (x - 1)^3 == chrompoly True + + sage: # needs sage.libs.flint sage.modules sage: charpoly = g.characteristic_polynomial() sage: M = g.adjacency_matrix(); M [0 1 1 0 0] @@ -79,7 +82,7 @@ def BullGraph(): [0 0 1 0 0] sage: Id = identity_matrix(ZZ, M.nrows()) sage: D = x*Id - M - sage: D.determinant() == charpoly + sage: D.determinant() == charpoly # needs sage.symbolic True sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly True @@ -108,7 +111,7 @@ def ButterflyGraph(): sage: G = graphs.ButterflyGraph(); G Butterfly graph: Graph on 5 vertices - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot sage: G.is_planar() True sage: G.order() @@ -170,7 +173,7 @@ def CircularLadderGraph(n): Construct and show a circular ladder graph with 26 nodes:: sage: g = graphs.CircularLadderGraph(13) - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several circular ladder graphs in a Sage graphics array:: @@ -212,7 +215,7 @@ def ClawGraph(): Show a Claw graph:: - sage: (graphs.ClawGraph()).show() # long time + sage: (graphs.ClawGraph()).show() # long time # needs sage.plot Inspect a Claw graph:: @@ -500,7 +503,7 @@ def CompleteBipartiteGraph(p, q, set_position=True): Notice here how the spring-layout tends to center the nodes of `n1`:: sage: spring_med.show() # long time # needs networkx - sage: posdict_med.show() # long time + sage: posdict_med.show() # long time # needs sage.plot View many complete bipartite graphs with a Sage Graphics Array, with this constructor (i.e., the position dictionary filled):: @@ -659,7 +662,7 @@ def DiamondGraph(): Construct and show a diamond graph:: sage: g = graphs.DiamondGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1)} edges = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)] @@ -681,7 +684,7 @@ def GemGraph(): Construct and show a gem graph:: sage: g = graphs.GemGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0.5, 0), 1: (0, 0.75), 2: (0.25, 1), 3: (0.75, 1), 4: (1, 0.75)} edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (3, 4)] @@ -703,7 +706,7 @@ def ForkGraph(): Construct and show a fork graph:: sage: g = graphs.ForkGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0, 0), 1: (1, 0), 2: (0, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 2), (2, 3), (3, 1), (2, 4)] @@ -723,7 +726,7 @@ def DartGraph(): Construct and show a dart graph:: sage: g = graphs.DartGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 0)} edges = [(0, 1), (0, 2), (1, 4), (2, 4), (0, 4), (3, 4)] @@ -748,7 +751,7 @@ def EmptyGraph(): sage: empty1 = graphs.EmptyGraph() sage: empty1.add_vertex() 0 - sage: empty1.show() # long time + sage: empty1.show() # long time # needs sage.plot Use for loops to build a graph from an empty graph:: @@ -764,7 +767,7 @@ def EmptyGraph(): ....: empty2.add_edge(i,i+1) # add edges {[0:1],[1:2],[2:3]} sage: for i in range(1, 4): ....: empty2.add_edge(4,i) # add edges {[1:4],[2:4],[3:4]} - sage: empty2.show() # long time + sage: empty2.show() # long time # needs sage.plot """ return Graph(sparse=True) @@ -896,7 +899,7 @@ def Grid2dGraph(p, q, set_positions=True): Construct and show a grid 2d graph Rows = `5`, Columns = `7`:: sage: g = graphs.Grid2dGraph(5,7) - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS: @@ -950,14 +953,14 @@ def GridGraph(dim_list): EXAMPLES:: sage: G = graphs.GridGraph([2,3,4]) - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot :: sage: C = graphs.CubeGraph(4) sage: G = graphs.GridGraph([2,2,2,2]) - sage: C.show() # long time - sage: G.show() # long time + sage: C.show() # long time # needs sage.plot + sage: G.show() # long time # needs sage.plot TESTS: @@ -1064,7 +1067,7 @@ def HouseGraph(): Construct and show a house graph:: sage: g = graphs.HouseGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)] @@ -1092,7 +1095,7 @@ def HouseXGraph(): Construct and show a house X graph:: sage: g = graphs.HouseXGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)] @@ -1116,7 +1119,7 @@ def LadderGraph(n): Construct and show a ladder graph with 14 nodes:: sage: g = graphs.LadderGraph(7) - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several ladder graphs in a Sage graphics array:: @@ -1179,26 +1182,26 @@ def PathGraph(n, pos=None): :: sage: p = graphs.PathGraph(10) - sage: p.show() # long time + sage: p.show() # long time # needs sage.plot 'circle': `10 < n < 41` :: sage: q = graphs.PathGraph(25) - sage: q.show() # long time + sage: q.show() # long time # needs sage.plot 'line': `n \geq 41` :: sage: r = graphs.PathGraph(55) - sage: r.show() # long time + sage: r.show() # long time # needs sage.plot Override the default drawing:: sage: s = graphs.PathGraph(5,'circle') - sage: s.show() # long time + sage: s.show() # long time # needs sage.plot """ G = Graph(n, name="Path graph") diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index bf1aa04e933..1bfe55f0f54 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -1045,7 +1045,7 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, using the built-in construction:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: g = graphs.T2starGeneralizedQuadrangleGraph(4); g T2*(O,4); GQ(3, 5): Graph on 64 vertices sage: g.is_strongly_regular(parameters=True) @@ -1057,7 +1057,7 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, supplying your own hyperoval:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(4,'b') sage: O = [vector(F,(0,0,0,1)),vector(F,(0,0,1,0))] + [vector(F, (0,1,x^2,x)) ....: for x in F] @@ -1068,7 +1068,7 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, TESTS:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(4,'b') # repeating a point... sage: O = [vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) @@ -1168,21 +1168,23 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h using the built-in constructions:: - sage: g = graphs.HaemersGraph(4); g # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings + sage: g = graphs.HaemersGraph(4); g Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (96, 19, 2, 4) supplying your own hyperoval_matching:: - sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings + sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (96, 19, 2, 4) TESTS:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(4,'b') # repeating a point... sage: O = [vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] sage: graphs.HaemersGraph(4, hyperoval=O, field=F) @@ -1392,7 +1394,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov using the built-in construction:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices sage: g.is_strongly_regular(parameters=True) @@ -1403,7 +1405,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov supplying your own hyperoval:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(8) sage: O = [vector(F,(0,0,1)),vector(F,(0,1,0))] + [vector(F, (1,x^2,x)) ....: for x in F] @@ -1414,7 +1416,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov TESTS:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(8) # repeating a point... sage: O = [vector(F,(1,0,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) diff --git a/src/sage/graphs/generators/degree_sequence.py b/src/sage/graphs/generators/degree_sequence.py index ed89ce43abc..f5e68d89c79 100644 --- a/src/sage/graphs/generators/degree_sequence.py +++ b/src/sage/graphs/generators/degree_sequence.py @@ -93,15 +93,15 @@ def DegreeSequenceBipartite(s1, s2): If we are given as sequences ``[2,2,2,2,2]`` and ``[5,5]`` we are given as expected the complete bipartite graph `K_{2,5}`:: - sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) # needs sage.modules - sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # needs sage.modules + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) # needs sage.combinat sage.modules + sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # needs sage.combinat sage.modules True Some sequences being incompatible if, for example, their sums are different, the functions raises a ``ValueError`` when no graph corresponding to the degree sequences exists:: - sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # needs sage.modules + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: there exists no bipartite graph corresponding to the given degree sequences @@ -110,7 +110,7 @@ def DegreeSequenceBipartite(s1, s2): :trac:`12155`:: - sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() # needs sage.modules + sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() # needs sage.combinat sage.modules Graph on 7 vertices """ from sage.combinat.integer_vector import gale_ryser_theorem diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index b90795b86a1..f05e4d714f7 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -321,8 +321,8 @@ def LargeWittGraph(): EXAMPLES:: - sage: g = graphs.LargeWittGraph() # needs sage.modules - sage: g.is_distance_regular(True) # needs sage.modules + sage: g = graphs.LargeWittGraph() # needs sage.libs.pari sage.modules + sage: g.is_distance_regular(True) # needs sage.libs.pari sage.modules ([30, 28, 24, None], [None, 1, 3, 15]) REFERENCES: @@ -359,9 +359,10 @@ def TruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.TruncatedWittGraph() # long time # needs sage.modules - sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules - ([15, 14, 12, None], [None, 1, 1, 9]) + sage: # long time, needs sage.libs.pari sage.modules + sage: G = graphs.TruncatedWittGraph() + sage: G.is_distance_regular(True) + ([15, 14, 12, None], [None, 1, 1, 9]) REFERENCES: @@ -388,9 +389,9 @@ def DoublyTruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.modules - sage: G.is_distance_regular(True) # needs sage.modules - ([7, 6, 4, 4, None], [None, 1, 1, 1, 6]) + sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.libs.pari sage.modules + sage: G.is_distance_regular(True) # needs sage.libs.pari sage.modules + ([7, 6, 4, 4, None], [None, 1, 1, 1, 6]) REFERENCES: @@ -411,8 +412,9 @@ def distance_3_doubly_truncated_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph() # long time, needs sage.modules sage.rings.finite_rings - sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules sage.rings.finite_rings + sage: # long time, needs sage.modules sage.rings.finite_rings + sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph() + sage: G.is_distance_regular(True) # long time (due to above) ([9, 8, 6, 3, None], [None, 1, 1, 3, 8]) ALGORITHM: @@ -446,8 +448,9 @@ def shortened_00_11_binary_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.shortened_00_11_binary_Golay_code_graph() # long time (9 s), needs sage.modules sage.rings.finite_rings - sage: G.is_distance_regular(True) # long time # needs sage.modules sage.rings.finite_rings + sage: # long time, needs sage.modules sage.rings.finite_rings + sage: G = graphs.shortened_00_11_binary_Golay_code_graph() # 9 s + sage: G.is_distance_regular(True) ([21, 20, 16, 6, 2, 1, None], [None, 1, 2, 6, 16, 20, 21]) ALGORITHM: @@ -485,8 +488,9 @@ def shortened_000_111_extended_binary_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph() # long time (25 s), needs sage.modules sage.rings.finite_rings - sage: G.is_distance_regular(True) # long time # needs sage.modules sage.rings.finite_rings + sage: # long time, needs sage.modules sage.rings.finite_rings + sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph() # 25 s + sage: G.is_distance_regular(True) ([21, 20, 16, 9, 2, 1, None], [None, 1, 2, 3, 16, 20, 21]) ALGORITHM: @@ -2143,7 +2147,7 @@ def graph_with_classical_parameters(int d, int b, alpha_in, beta_in, int gamma): Half 4 Cube: Graph on 8 vertices sage: graph_with_classical_parameters(3, 2, 0, 2, 9) # needs sage.libs.gap Symplectic Dual Polar Graph DSp(6, 2): Graph on 135 vertices - sage: graph_with_classical_parameters(3, 2, 2, 14, 7) # long time + sage: graph_with_classical_parameters(3, 2, 2, 14, 7) # long time # needs sage.symbolic Grassmann graph J_2(6, 3): Graph on 1395 vertices sage: graph_with_classical_parameters(3, -2, -2, 6, 6) # optional - gap_package_atlasrep internet Generalised hexagon of order (2, 8): Graph on 819 vertices diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index a5916a13b5c..85ea52a4571 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -614,7 +614,7 @@ def BarbellGraph(n1, n2): sage: g = graphs.BarbellGraph(9, 4); g Barbell graph: Graph on 22 vertices - sage: g.show() # long time + 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 @@ -712,7 +712,7 @@ def LollipopGraph(n1, n2): sage: g = graphs.LollipopGraph(13,4); g Lollipop graph: Graph on 17 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -785,7 +785,7 @@ def TadpoleGraph(n1, n2): sage: g = graphs.TadpoleGraph(13, 4); g Tadpole graph: Graph on 17 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -877,7 +877,7 @@ def DipoleGraph(n): sage: g = graphs.DipoleGraph(13); g Dipole graph: Multi-graph on 2 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -935,7 +935,7 @@ def BubbleSortGraph(n): sage: g = graphs.BubbleSortGraph(4); g Bubble sort: Graph on 24 vertices - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 61 graphics primitives The bubble sort graph on `n = 1` symbol is the trivial graph `K_1`:: @@ -1313,9 +1313,9 @@ def GoethalsSeidelGraph(k, r): EXAMPLES:: - sage: graphs.GoethalsSeidelGraph(3,3) # needs sage.modules + sage: graphs.GoethalsSeidelGraph(3,3) # needs sage.combinat sage.modules Graph on 28 vertices - sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True) # needs sage.modules + sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True) # needs sage.combinat sage.modules (28, 15, 6, 10) """ from sage.combinat.designs.bibd import balanced_incomplete_block_design @@ -2137,7 +2137,7 @@ def HyperStarGraph(n, k): sage: g = graphs.HyperStarGraph(6,3) sage: sorted(g.neighbors('011100')) ['101100', '110100', '111000'] - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 51 graphics primitives TESTS:: @@ -2205,11 +2205,11 @@ def LCFGraph(n, shift_list, repeats): INPUT: - - ``n`` - the number of nodes. + - ``n`` -- the number of nodes. - - ``shift_list`` - a list of integer shifts mod n. + - ``shift_list`` -- a list of integer shifts mod `n`. - - ``repeats`` - the number of times to repeat the + - ``repeats`` -- the number of times to repeat the process. @@ -2406,7 +2406,7 @@ def NKStarGraph(n, k): EXAMPLES:: sage: g = graphs.NKStarGraph(4,2) - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 31 graphics primitives REFERENCES: @@ -2465,7 +2465,7 @@ def NStarGraph(n): EXAMPLES:: sage: g = graphs.NStarGraph(4) - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 61 graphics primitives REFERENCES: @@ -2639,7 +2639,7 @@ def SquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: # needs sage.modules + sage: # needs sage.combinat sage.modules sage: G = graphs.SquaredSkewHadamardMatrixGraph(4) sage: G.is_strongly_regular(parameters=True) (225, 112, 55, 56) @@ -2693,14 +2693,15 @@ def SwitchedSquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) # needs sage.modules - sage: g.is_strongly_regular(parameters=True) # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) + sage: g.is_strongly_regular(parameters=True) (226, 105, 48, 49) sage: from sage.combinat.designs.twographs import twograph_descendant - sage: twograph_descendant(g, 0).is_strongly_regular(parameters=True) # needs sage.modules + sage: twograph_descendant(g, 0).is_strongly_regular(parameters=True) (225, 112, 55, 56) - sage: gc = g.complement() # needs sage.modules - sage: twograph_descendant(gc, 0).is_strongly_regular(parameters=True) # needs sage.modules + sage: gc = g.complement() + sage: twograph_descendant(gc, 0).is_strongly_regular(parameters=True) (225, 112, 55, 56) TESTS:: @@ -3840,22 +3841,26 @@ def MathonPseudocyclicMergingGraph(M, t): sage: from sage.graphs.generators.families import MathonPseudocyclicMergingGraph as mer sage: from sage.graphs.generators.smallgraphs import _EllipticLinesProjectivePlaneScheme as ES - sage: G = mer(ES(3), 0) # long time - sage: G.is_strongly_regular(parameters=True) # long time + + sage: # long time, needs sage.libs.gap + sage: G = mer(ES(3), 0) + sage: G.is_strongly_regular(parameters=True) (784, 243, 82, 72) - sage: G = mer(ES(3), 1) # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = mer(ES(3), 1) + sage: G.is_strongly_regular(parameters=True) (784, 270, 98, 90) - sage: G = mer(ES(3), 2) # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = mer(ES(3), 2) + sage: G.is_strongly_regular(parameters=True) (784, 297, 116, 110) - sage: G = mer(ES(2), 2) # needs sage.libs.gap + sage: G = mer(ES(2), 2) Traceback (most recent call last): ... AssertionError... - sage: M = ES(3) # needs sage.libs.gap - sage: M = [M[1],M[0],M[2],M[3]] # needs sage.libs.gap - sage: G = mer(M, 2) # needs sage.libs.gap + + sage: # needs sage.libs.gap + sage: M = ES(3) + sage: M = [M[1],M[0],M[2],M[3]] + sage: G = mer(M, 2) Traceback (most recent call last): ... AssertionError... @@ -3937,7 +3942,7 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): [-4 -3 -2 2 3 4 -1 0 1] [-2 -4 -3 4 2 3 1 -1 0] - sage: # needs sage.modules sage.rings.finite_rings sage.groups sage.libs.gap + sage: # needs sage.groups sage.libs.gap sage.modules sage.rings.finite_rings sage: G.relabel(range(9)) sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) sage: G3x3.is_strongly_regular(parameters=True) @@ -4113,27 +4118,27 @@ def MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False): INPUT: - - ``n`` (integer)-- a prime power + - ``n`` (integer) -- a prime power - - ``d`` (integer)-- must be odd if `n` is odd + - ``d`` (integer) -- must be odd if `n` is odd - ``Phi`` is an optional parameter of the construction; it must be either - - 'fixed'-- this will generate fixed default `\Phi_i`, for `i \in M`, or + - ``'fixed'`` -- this will generate fixed default `\Phi_i`, for `i \in M`, or - - 'random'-- `\Phi_i` are generated at random, or + - ``'random'`` -- `\Phi_i` are generated at random, or - - A dictionary describing the functions `\Phi_i`; for `i \in M`, - Phi[(i, T)] in `M`, for each edge T of `L` on `i`. - Also, each `\Phi_i` must be injective. + - A dictionary describing the functions `\Phi_i`; for `i \in M`, + Phi[(i, T)] in `M`, for each edge T of `L` on `i`. + Also, each `\Phi_i` must be injective. - ``Sigma`` is an optional parameter of the construction; it must be either - - 'fixed'-- this will generate a fixed default `\Sigma`, or + - ``'fixed'`` -- this will generate a fixed default `\Sigma`, or - - 'random'-- `\Sigma` is generated at random. + - ``'random'`` -- `\Sigma` is generated at random. - - ``verbose`` (Boolean)-- default is False. If True, print progress information + - ``verbose`` (Boolean) -- default is ``False``. If ``True``, print progress information .. SEEALSO:: @@ -4146,12 +4151,12 @@ def MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False): EXAMPLES:: - sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings + sage: # needs sage.combinat sage.modules sage.rings.finite_rings + sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True) (378, 116, 34, 36) - sage: phi = {(2,(0,2)):0, (1,(1,3)):1, (0,(0,3)):1, (2,(1,2)):1, # needs sage.modules + sage: phi = {(2,(0,2)):0, (1,(1,3)):1, (0,(0,3)):1, (2,(1,2)):1, ....: (1,(1,2)):0, (0,(0,2)):0, (3,(0,3)):0, (3,(1,3)):1} - sage: graphs.MuzychukS6Graph(2, 2, # needs sage.modules sage.rings.finite_rings - ....: Phi=phi).is_strongly_regular(parameters=True) + sage: graphs.MuzychukS6Graph(2, 2, Phi=phi).is_strongly_regular(parameters=True) (16, 5, 0, 2) TESTS:: diff --git a/src/sage/graphs/generators/intersection.py b/src/sage/graphs/generators/intersection.py index 0de3715e0e1..0d19d30f9ea 100644 --- a/src/sage/graphs/generators/intersection.py +++ b/src/sage/graphs/generators/intersection.py @@ -464,20 +464,20 @@ def OrthogonalArrayBlockGraph(k, n, OA=None): But nevertheless isospectral:: - sage: g0.spectrum() # needs sage.modules + sage: g0.spectrum() # needs sage.modules sage.rings.number_field [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3] - sage: g1.spectrum() # needs sage.modules + sage: g1.spectrum() # needs sage.modules sage.rings.number_field [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3] Note that the graph ``g0`` is actually isomorphic to the affine polar graph `VO^+(4,2)`:: - sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) # needs sage.modules + sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) # needs sage.libs.gap sage.modules True TESTS:: - sage: G = graphs.OrthogonalArrayBlockGraph(4,6) # needs sage.modules + sage: G = graphs.OrthogonalArrayBlockGraph(4,6) # needs sage.modules sage.schemes Traceback (most recent call last): ... NotImplementedError: I don't know how to build an OA(4,6)! diff --git a/src/sage/graphs/generators/platonic_solids.py b/src/sage/graphs/generators/platonic_solids.py index 38e070a054a..d3bc60a9974 100644 --- a/src/sage/graphs/generators/platonic_solids.py +++ b/src/sage/graphs/generators/platonic_solids.py @@ -142,7 +142,7 @@ def OctahedralGraph(): Construct and show an Octahedral graph:: sage: g = graphs.OctahedralGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several octahedral graphs in a Sage graphics array They will be drawn differently due to the use of the spring-layout algorithm:: diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 5dab4071f49..d253633621c 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -69,7 +69,7 @@ def RandomGNP(n, p, seed=None, fast=True, algorithm='Sage'): We plot a random graph on 12 nodes with probability `p = .71`:: sage: gnp = graphs.RandomGNP(12,.71) - sage: gnp.show() # long time + sage: gnp.show() # long time # needs sage.plot We view many random graphs using a graphics array:: @@ -1359,7 +1359,7 @@ def RandomTree(n, seed=None): sage: G = graphs.RandomTree(10) sage: G.is_tree() True - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot TESTS: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index a090eb3f73d..a4f3e1c05ef 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -455,7 +455,7 @@ def Cell600(embedding=1): EXAMPLES:: - sage: # long time + sage: # long time, needs sage.rings.number_field sage: g = graphs.Cell600() sage: g.size() 720 @@ -531,7 +531,7 @@ def Cell120(): EXAMPLES:: - sage: # long time + sage: # long time, needs sage.rings.number_field sage: g = graphs.Cell120() sage: g.size() 1200 @@ -1066,7 +1066,7 @@ def BidiakisCube(): sage: g = graphs.BidiakisCube(); g Bidiakis cube: Graph on 12 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot sage: g.order() 12 sage: g.size() @@ -1297,7 +1297,7 @@ def BrinkmannGraph(): sage: G = graphs.BrinkmannGraph(); G Brinkmann graph: Graph on 21 vertices - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot sage: G.order() 21 sage: G.size() @@ -1424,7 +1424,7 @@ def BuckyBall(): The Bucky Ball can also be created by extracting the 1-skeleton of the Bucky Ball polyhedron, but this is much slower:: - sage: # needs sage.geometry.polyhedron sage.rings.number_field + sage: # needs sage.geometry.polyhedron sage.groups sage.rings.number_field sage: g = polytopes.buckyball().vertex_graph() sage: g.remove_loops() sage: h = graphs.BuckyBall() @@ -2184,7 +2184,7 @@ def EllinghamHorton54Graph(): TESTS:: - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ edge_dict = { 0: [1, 11, 15], 1: [2, 47], 2: [3, 13], 3: [4, 8], 4: [5, 15], @@ -2425,7 +2425,7 @@ def FlowerSnark(): Now show it:: - sage: F.show() # long time + sage: F.show() # long time # needs sage.plot """ d = {0: [1, 14, 15], 1: [2, 11], 2: [3, 7], 3: [2, 4, 16], 4: [5, 14], 5: [6, 10], 6: [5, 7, 17], 8: [7, 9, 13], 9: [10, 18], 11: [10, 12], @@ -2844,7 +2844,7 @@ def HeawoodGraph(): Heawood graph: Graph on 14 vertices sage: H.graph6_string() 'MhEGHC@AI?_PC@_G_' - sage: (graphs.HeawoodGraph()).show() # long time + sage: (graphs.HeawoodGraph()).show() # long time # needs sage.plot TESTS:: @@ -3303,7 +3303,7 @@ def KrackhardtKiteGraph(): Construct and show a Krackhardt kite graph :: sage: g = graphs.KrackhardtKiteGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -4534,7 +4534,7 @@ def TutteGraph(): 69 sage: g.is_planar() True - sage: g.vertex_connectivity() # long time + sage: g.vertex_connectivity() # long time # needs sage.numerical.mip 3 sage: g.girth() 4 @@ -4754,14 +4754,15 @@ def MathonStronglyRegularGraph(t): EXAMPLES:: + sage: # long time, needs sage.libs.gap sage: from sage.graphs.generators.smallgraphs import MathonStronglyRegularGraph - sage: G = MathonStronglyRegularGraph(0) # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = MathonStronglyRegularGraph(0) + sage: G.is_strongly_regular(parameters=True) (784, 243, 82, 72) TESTS:: - sage: # long time + sage: # long time, needs sage.libs.gap sage: G = graphs.MathonStronglyRegularGraph(1) sage: G.is_strongly_regular(parameters=True) (784, 270, 98, 90) @@ -4789,12 +4790,12 @@ def JankoKharaghaniGraph(v): EXAMPLES:: - sage: g = graphs.JankoKharaghaniGraph(936) # long time - sage: g.is_strongly_regular(parameters=True) # long time + sage: g = graphs.JankoKharaghaniGraph(936) # long time # needs sage.libs.pari + sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.pari (936, 375, 150, 150) - sage: g = graphs.JankoKharaghaniGraph(1800) # not tested (30s) - sage: g.is_strongly_regular(parameters=True) # not tested (30s) + sage: g = graphs.JankoKharaghaniGraph(1800) # not tested (30s) + sage: g.is_strongly_regular(parameters=True) # not tested (30s) (1800, 1029, 588, 588) """ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF @@ -4881,8 +4882,8 @@ def JankoKharaghaniTonchevGraph(): EXAMPLES:: - sage: Gamma=graphs.JankoKharaghaniTonchevGraph() # long time - sage: Gamma.is_strongly_regular(parameters=True) # long time + sage: Gamma = graphs.JankoKharaghaniTonchevGraph() # long time # needs sage.libs.gap + sage: Gamma.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap (324, 153, 72, 72) """ from sage.misc.misc_c import prod diff --git a/src/sage/graphs/generators/world_map.py b/src/sage/graphs/generators/world_map.py index 76c32335f60..f131aa446e2 100644 --- a/src/sage/graphs/generators/world_map.py +++ b/src/sage/graphs/generators/world_map.py @@ -48,7 +48,7 @@ def AfricaMap(continental=False, year=2018): TESTS:: - sage: Africa.plot() # long time + sage: Africa.plot() # long time # needs sage.plot Graphics object consisting of 159 graphics primitives """ if year != 2018: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 66703a0f7c1..eedbc36bef3 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -959,7 +959,7 @@ def _matrix_(self, R=None, vertices=None): [1 1 0 0 0] [1 1 0 0 0] [1 1 0 0 0] - sage: factor(m.charpoly()) # needs sage.modules + sage: factor(m.charpoly()) # needs sage.libs.pari sage.modules x^3 * (x^2 - 6) """ return self.am(vertices=vertices, base_ring=R) @@ -1995,7 +1995,7 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds A different matrix implementation:: - sage: graphs.PathGraph(5).adjacency_matrix(sparse=False, # needs sage.modules + sage: graphs.PathGraph(5).adjacency_matrix(sparse=False, # needs numpy sage.modules ....: implementation='numpy') [0 1 0 0 0] [1 0 1 0 0] @@ -4830,7 +4830,7 @@ def min_spanning_tree(self, [(0, 2, 10), (1, 2, 1)] sage: Graph(g.min_spanning_tree(algorithm='Prim_Boost', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: Graph(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)).edges(sort=True) # needs networkx + sage: Graph(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)).edges(sort=True) # needs networkx [(0, 2, 10), (1, 2, 1)] If the graph is directed, it is transformed into an undirected graph:: @@ -6811,13 +6811,13 @@ def steiner_tree(self, vertices, weighted=False, solver=None, verbose=0, sage: g = graphs.RandomGNP(30, .5) sage: first5 = g.vertices(sort=True)[:5] - sage: st = g.steiner_tree(first5) - sage: st.is_tree() + sage: st = g.steiner_tree(first5) # needs sage.numerical.mip + sage: st.is_tree() # needs sage.numerical.mip True And all the 5 vertices are contained in this tree :: - sage: all(v in st for v in first5) + sage: all(v in st for v in first5) # needs sage.numerical.mip True An exception is raised when the problem is impossible, i.e. if the @@ -7024,7 +7024,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None sage: d6 += r'@ADA@AAg?GAQW?[aIaSwHYcD@qQb@Dd?\hJTI@OHlJ_?C_OEIKoeC' sage: d6 += r'R@_BC?Q??YBFosqITEA?IvCU_' sage: G = DiGraph(d6, format='dig6') - sage: G.edge_connectivity() + sage: G.edge_connectivity() # needs sage.numerical.mip 5 sage: G.edge_disjoint_spanning_trees(5) # long time # needs sage.numerical.mip [Digraph on 28 vertices, @@ -7055,11 +7055,12 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None Choice of the algorithm:: - sage: Graph().edge_disjoint_spanning_trees(0, algorithm=None) # needs sage.numerical.mip + sage: # needs sage.numerical.mip + sage: Graph().edge_disjoint_spanning_trees(0, algorithm=None) [] sage: Graph().edge_disjoint_spanning_trees(0, algorithm="Roskind-Tarjan") [] - sage: Graph().edge_disjoint_spanning_trees(0, algorithm="MILP") # needs sage.numerical.mip + sage: Graph().edge_disjoint_spanning_trees(0, algorithm="MILP") [] sage: Graph().edge_disjoint_spanning_trees(0, algorithm="foo") Traceback (most recent call last): @@ -7067,7 +7068,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None ValueError: algorithm must be None, "Rosking-Tarjan" or "MILP" for undirected graphs sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm=None) [] - sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="MILP") # needs sage.numerical.mip + sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="MILP") [] sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="foo") Traceback (most recent call last): @@ -7284,7 +7285,8 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, The two sides of the edge cut are obviously shorter paths:: - sage: value,edges,[set1,set2] = g.edge_cut(0, 14, use_edge_labels=True, vertices=True) + sage: value, edges, [set1, set2] = g.edge_cut(0, 14, use_edge_labels=True, + ....: vertices=True) sage: g.subgraph(set1).is_isomorphic(graphs.PathGraph(len(set1))) True sage: g.subgraph(set2).is_isomorphic(graphs.PathGraph(len(set2))) @@ -7307,7 +7309,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, sage: g = graphs.RandomGNP(20,.3) sage: for u,v in g.edges(sort=True, labels=False): ....: g.set_edge_label(u,v,round(random(),5)) - sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="LP") + sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="LP") # needs sage.numerical.mip True sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="igraph") # optional - python_igraph True @@ -7315,7 +7317,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, Rounded return value when using the LP method:: sage: g = graphs.PappusGraph() - sage: g.edge_cut(1, 2, value_only=True, algorithm="LP") + sage: g.edge_cut(1, 2, value_only=True, algorithm="LP") # needs sage.numerical.mip 3 :trac:`12797`:: @@ -7326,7 +7328,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, sage: G = DiGraph([(0, 3, 1), (0, 4, 1), (2, 1, 1), (3, 2, 1), (4, 2, 1)]) sage: G.edge_cut(0, 1, value_only=False, use_edge_labels=True) [1, [(2, 1, 1)]] - sage: G.edge_cut(0, 1, value_only=False, use_edge_labels=True, algorithm='LP') + sage: G.edge_cut(0, 1, value_only=False, use_edge_labels=True, algorithm='LP') # needs sage.numerical.mip (1, [(2, 1)]) """ self._scream_if_not_simple(allow_loops=True) @@ -9519,8 +9521,8 @@ def flow(self, x, y, value_only=True, integer=False, use_edge_labels=True, sage: for u, v in g.edge_iterator(labels=False): ....: g.set_edge_label(u, v, round(random(), 5)) sage: flow_ff = g.flow(0, 1, algorithm="FF") - sage: flow_lp = g.flow(0, 1, algorithm="LP") - sage: abs(flow_ff - flow_lp) < 0.01 + sage: flow_lp = g.flow(0, 1, algorithm="LP") # needs sage.numerical.mip + sage: abs(flow_ff - flow_lp) < 0.01 # needs sage.numerical.mip True sage: flow_igraph = g.flow(0, 1, algorithm="igraph") # optional python_igraph sage: abs(flow_ff - flow_igraph) < 0.00001 # optional python_igraph @@ -12365,7 +12367,7 @@ def set_edge_label(self, u, v, l): ....: 9: [6, 11], 10: [9, 1], 11: [10, 6], 12: [13, 6], ....: 13: [16, 2], 14: [10, -6], 15: [0, -10], 16: [14, -6], ....: 17: [16, -10], 18: [6, -4]} - sage: SD.plot(pos=posn, vertex_size=400, vertex_colors={'#FFFFFF':list(range(1,19))}, edge_labels=True).show() # long time + sage: SD.plot(pos=posn, vertex_size=400, vertex_colors={'#FFFFFF':list(range(1,19))}, edge_labels=True).show() # long time, needs sage.plot :: @@ -15616,7 +15618,7 @@ def distance(self, u, v, by_weight=False, weight_function=None, check_weight=Tru sage: G.distance(0,1) +Infinity sage: G = Graph({ 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, sparse = True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.distance(0, 3) 2 sage: G.distance(0, 3, by_weight=True) @@ -16627,7 +16629,7 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, [] sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, ....: sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.shortest_path(0, 3) [0, 4, 3] sage: G.shortest_path(0, 3, by_weight=True) @@ -16675,7 +16677,7 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, sage: G = Graph() sage: G.add_vertices([1, 2]) sage: algs = ['BFS', 'BFS_Bid', 'Dijkstra_Bid', 'Bellman-Ford_Boost'] - sage: algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx + sage: import networkx; algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx sage: all(G.shortest_path(1, 2, algorithm=alg) == [] ....: for alg in algs) True @@ -16813,7 +16815,7 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, +Infinity sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, ....: sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.shortest_path_length(0, 3) 2 sage: G.shortest_path_length(0, 3, by_weight=True) @@ -16864,7 +16866,7 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, sage: G = Graph() sage: G.add_vertices([1, 2]) sage: algs = ['BFS', 'BFS_Bid', 'Dijkstra_Bid', 'Bellman-Ford_Boost'] - sage: algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx + sage: import networkx; algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx sage: all(G.shortest_path_length(1, 2, algorithm=alg) == Infinity ....: for alg in algs) True @@ -17120,7 +17122,7 @@ def shortest_paths(self, u, by_weight=False, algorithm=None, 9: [0, 10, 9], 10: [0, 10], 11: [0, 10, 11], 18: [0, 19, 18], 19: [0, 19]} sage: G = Graph( { 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2} }, sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.shortest_paths(0, by_weight=True) {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 4]} @@ -17528,8 +17530,8 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, Some standard examples (see :meth:`~GenericGraph.shortest_paths` for more examples on how to use the input variables):: - sage: G = Graph( { 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2} }, sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, sparse=True) + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: dist, pred = G.shortest_path_all_pairs(by_weight = True) sage: dist {0: {0: 0, 1: 1, 2: 2, 3: 3, 4: 2}, @@ -19059,7 +19061,7 @@ def tensor_product(self, other): Graph on 10 vertices sage: T.size() 10 - sage: T.plot() # long time + sage: T.plot() # long time # needs sage.plot Graphics object consisting of 21 graphics primitives :: @@ -19070,7 +19072,7 @@ def tensor_product(self, other): Graph on 200 vertices sage: T.size() 900 - sage: T.plot() # long time + sage: T.plot() # long time # needs sage.plot Graphics object consisting of 1101 graphics primitives TESTS: @@ -19140,7 +19142,7 @@ def lexicographic_product(self, other): sage: C = graphs.CycleGraph(5) sage: L = C.lexicographic_product(Z); L Graph on 10 vertices - sage: L.plot() # long time + sage: L.plot() # long time # needs sage.plot Graphics object consisting of 36 graphics primitives :: @@ -19149,7 +19151,7 @@ def lexicographic_product(self, other): sage: P = graphs.PetersenGraph() sage: L = D.lexicographic_product(P); L Graph on 200 vertices - sage: L.plot() # long time + sage: L.plot() # long time # needs sage.plot Graphics object consisting of 3501 graphics primitives TESTS: @@ -19220,7 +19222,7 @@ def strong_product(self, other): sage: C = graphs.CycleGraph(5) sage: S = C.strong_product(Z); S Graph on 10 vertices - sage: S.plot() # long time + sage: S.plot() # long time # needs sage.plot Graphics object consisting of 36 graphics primitives :: @@ -19229,7 +19231,7 @@ def strong_product(self, other): sage: P = graphs.PetersenGraph() sage: S = D.strong_product(P); S Graph on 200 vertices - sage: S.plot() # long time + sage: S.plot() # long time # needs sage.plot Graphics object consisting of 1701 graphics primitives TESTS: @@ -19300,7 +19302,7 @@ def disjunctive_product(self, other): sage: Z = graphs.CompleteGraph(2) sage: D = Z.disjunctive_product(Z); D Graph on 4 vertices - sage: D.plot() # long time + sage: D.plot() # long time # needs sage.plot Graphics object consisting of 11 graphics primitives :: @@ -19308,7 +19310,7 @@ def disjunctive_product(self, other): sage: C = graphs.CycleGraph(5) sage: D = C.disjunctive_product(Z); D Graph on 10 vertices - sage: D.plot() # long time + sage: D.plot() # long time # needs sage.plot Graphics object consisting of 46 graphics primitives TESTS: @@ -20915,7 +20917,7 @@ def plot(self, **options): The following illustrates the format of a position dictionary:: - sage: G.get_pos() # currently random across platforms, see #9593 # needs sage.plot + sage: G.get_pos() # currently random across platforms, see #9593 # needs sage.plot {0: [1.17..., -0.855...], 1: [1.81..., -0.0990...], 2: [1.35..., 0.184...], @@ -23178,9 +23180,9 @@ def automorphism_group(self, partition=None, verbosity=0, TESTS: - We get a KeyError when given an invalid partition (:trac:`6087`):: + We get a :class:`KeyError` when given an invalid partition (:trac:`6087`):: - sage: g=graphs.CubeGraph(3) + sage: g = graphs.CubeGraph(3) sage: g.relabel() sage: g.automorphism_group(partition=[[0,1,2],[3,4,5]],algorithm='sage') # needs sage.groups Traceback (most recent call last): @@ -23224,7 +23226,7 @@ def automorphism_group(self, partition=None, verbosity=0, sage: G1 = Graph(':H`ECw@HGXGAGUG`e') sage: G = G1.automorphism_group() # needs sage.groups - sage: G.subgroups() + sage: G.subgroups() # needs sage.groups [Subgroup generated by [()] of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)]), Subgroup generated by [(0,7)(1,4)(2,3)(6,8)] of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)])] @@ -23568,7 +23570,7 @@ def is_isomorphic(self, other, certificate=False, verbosity=0, edge_labels=False sage: position_E = {} sage: for vert in position_D: ....: position_E[b[vert]] = position_D[vert] - sage: graphics_array([D.plot(pos=position_D), E.plot(pos=position_E)]).show() # long time + sage: graphics_array([D.plot(pos=position_D), E.plot(pos=position_E)]).show() # long time, needs sage.plot :: @@ -24006,7 +24008,7 @@ class by some canonization function `c`. If `G` and `H` are graphs, ....: [(0,1), (0,2), (1,2)], ....: [(0,1), (0,2), (0,3)]] sage: algos = ['sage'] - sage: algos.append('bliss') # optional - bliss + sage: import sage.graphs.bliss; algos.append('bliss') # optional - bliss sage: S = Set([0,1,2]) sage: for (algo, edges) in product(algos, edges_list): # needs sage.combinat ....: L = cartesian_product([S] * len(edges)) @@ -24550,7 +24552,7 @@ def katz_centrality(self, alpha, u=None): all 4 vertices have the same centrality) :: sage: G = graphs.CycleGraph(4) - sage: G.katz_centrality(1/20) # needs sage.modules + sage: G.katz_centrality(1/20) # needs sage.modules sage.rings.number_field {0: 1/9, 1: 1/9, 2: 1/9, 3: 1/9} Note that in the below example the nodes having indegree `0` also have @@ -24559,7 +24561,7 @@ def katz_centrality(self, alpha, u=None): sage: G = DiGraph({1: [10], 2:[10,11], 3:[10,11], 4:[], 5:[11, 4], 6:[11], ....: 7:[10,11], 8:[10,11], 9:[10], 10:[11, 5, 8], 11:[6]}) - sage: G.katz_centrality(.85) # rel tol 1e-14 # needs sage.modules + sage: G.katz_centrality(.85) # rel tol 1e-14 # needs sage.modules sage.rings.number_field {1: 0.000000000000000, 2: 0.000000000000000, 3: 0.000000000000000, @@ -24580,7 +24582,7 @@ def katz_centrality(self, alpha, u=None): TESTS:: - sage: # needs sage.modules + sage: # needs sage.modules sage.rings.number_field sage: graphs.PathGraph(3).katz_centrality(1/20) {0: 11/199, 1: 21/199, 2: 11/199} sage: graphs.PathGraph(4).katz_centrality(1/20) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index fe02be46c77..14d8789bc63 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -783,10 +783,10 @@ class Graph(GenericGraph): #. A Seidel adjacency matrix:: - sage: from sage.combinat.matrices.hadamard_matrix import ( # needs sage.modules + sage: from sage.combinat.matrices.hadamard_matrix import ( # needs sage.combinat sage.modules ....: regular_symmetric_hadamard_matrix_with_constant_diagonal as rshcd) - sage: m = rshcd(16,1) - matrix.identity(16) # needs sage.modules - sage: Graph(m, # needs sage.modules + sage: m = rshcd(16,1) - matrix.identity(16) # needs sage.combinat sage.modules + sage: Graph(m, # needs sage.combinat sage.modules ....: format="seidel_adjacency_matrix").is_strongly_regular(parameters=True) (16, 6, 2, 2) @@ -1322,8 +1322,7 @@ def graph6_string(self): raise ValueError('graph6 format supports graphs on 0 to 262143 vertices only.') elif self.has_loops() or self.has_multiple_edges(): raise ValueError('graph6 format supports only simple graphs (no loops, no multiple edges)') - else: - return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) + return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) @doc_index("Basic methods") def sparse6_string(self): @@ -1626,8 +1625,7 @@ def vertices_to_edges(x): stack.append((v, w)) seen[v] = u - else: - return self.order() == self.size() + 1 + return self.order() == self.size() + 1 @doc_index("Graph properties") def is_forest(self, certificate=False, output='vertex'): @@ -1667,20 +1665,17 @@ def is_forest(self, certificate=False, output='vertex'): if not certificate: return isit - else: - if isit: - return (True, None) - # The graph contains a cycle, and the user wants to see it. - - # No need to copy the graph - if number_of_connected_components == 1: - return self.is_tree(certificate=True, output=output) + if isit: + return (True, None) - # We try to find a cycle in each connected component - for cc in connected_components: - isit, cycle = self.subgraph(cc).is_tree(certificate=True, output=output) - if not isit: - return (False, cycle) + # The graph contains a cycle, and the user wants to see it. + if number_of_connected_components == 1: + return self.is_tree(certificate=True, output=output) + # We try to find a cycle in each connected component + for cc in connected_components: + isit, cycle = self.subgraph(cc).is_tree(certificate=True, output=output) + if not isit: + return (False, cycle) @doc_index("Graph properties") def is_cactus(self): @@ -2070,14 +2065,14 @@ def apex_vertices(self, k=None): if not P: # The graph is planar it = self.vertex_iterator() return [next(it) for _ in range(k)] - elif len(P) > 1: + if len(P) > 1: return [] + + # We proceed with the non planar component + if P[0].is_immutable(): + H = Graph(P[0].edges(labels=0, sort=False), immutable=False, loops=False, multiedges=False) else: - # We proceed with the non planar component - if P[0].is_immutable(): - H = Graph(P[0].edges(labels=0, sort=False), immutable=False, loops=False, multiedges=False) - else: - H = P[0] + H = P[0] elif self.is_planar(): # A planar graph is apex. @@ -2319,8 +2314,7 @@ def is_even_hole_free(self, certificate=False): if subgraph is not None: if certificate: return subgraph - else: - return False + return False start += 2 @@ -2391,8 +2385,7 @@ def is_odd_hole_free(self, certificate=False): if subgraph is not None: if certificate: return subgraph - else: - return False + return False start += 2 @@ -2463,7 +2456,7 @@ def is_triangle_free(self, algorithm='dense_graph', certificate=False): Comparison of algorithms:: - sage: for i in range(10): # long time + sage: for i in range(10): # long time # needs networkx ....: G = graphs.RandomBarabasiAlbert(50,2) ....: bm = G.is_triangle_free(algorithm='matrix') ....: bb = G.is_triangle_free(algorithm='bitset') @@ -2518,8 +2511,7 @@ def is_triangle_free(self, algorithm='dense_graph', certificate=False): return True return (self.adjacency_matrix()**3).trace() == 0 - else: - raise ValueError("Algorithm '%s' not yet implemented. Please contribute." % (algorithm)) + raise ValueError("Algorithm '%s' not yet implemented. Please contribute." % (algorithm)) @doc_index("Graph properties") def is_split(self): @@ -3334,15 +3326,15 @@ def bounded_outdegree_orientation(self, bound, solver=None, verbose=False, divided by 2. Anything less, though, is impossible. sage: g = graphs.RandomGNP(40, .4) - sage: mad = g.maximum_average_degree() + sage: mad = g.maximum_average_degree() # needs sage.numerical.mip Hence this is possible :: - sage: d = g.bounded_outdegree_orientation(integer_ceil(mad/2)) + sage: d = g.bounded_outdegree_orientation(integer_ceil(mad/2)) # needs sage.numerical.mip While this is not:: - sage: try: + sage: try: # needs sage.numerical.mip ....: g.bounded_outdegree_orientation(integer_ceil(mad/2-1)) ....: print("Error") ....: except ValueError: @@ -3578,8 +3570,7 @@ def bipartite_color(self): if isit: return certificate - else: - raise RuntimeError("Graph is not bipartite.") + raise RuntimeError("Graph is not bipartite.") @doc_index("Basic methods") def bipartite_sets(self): @@ -3746,7 +3737,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, 3 sage: G.chromatic_number(algorithm="MILP") 3 - sage: G.chromatic_number(algorithm="CP") + sage: G.chromatic_number(algorithm="CP") # needs sage.libs.flint 3 sage: G.chromatic_number(algorithm="parallel") 3 @@ -3786,7 +3777,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, 0 sage: G.chromatic_number(algorithm="MILP") 0 - sage: G.chromatic_number(algorithm="CP") + sage: G.chromatic_number(algorithm="CP") # needs sage.libs.flint 0 sage: G.chromatic_number(algorithm="parallel") 0 @@ -3801,7 +3792,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, sage: G = graphs.RandomGNP(15, .2) sage: algorithms = ['DLX', 'MILP', 'CP', 'parallel'] - sage: len(set([G.chromatic_number(algorithm=algo) for algo in algorithms])) == 1 + sage: len(set([G.chromatic_number(algorithm=algo) for algo in algorithms])) == 1 # needs sage.libs.flint True """ self._scream_if_not_simple(allow_multiple_edges=True) @@ -3827,8 +3818,8 @@ def func(alg): for input, output in func(algorithms): return output return use_all(['DLX', 'MILP', 'CP']) - else: - raise ValueError("the 'algorithm' keyword must be set to either 'DLX', 'MILP', 'CP' or 'parallel'") + + raise ValueError("the 'algorithm' keyword must be set to either 'DLX', 'MILP', 'CP' or 'parallel'") @doc_index("Coloring") def coloring(self, algorithm="DLX", hex_colors=False, solver=None, verbose=0, @@ -3914,8 +3905,8 @@ def coloring(self, algorithm="DLX", hex_colors=False, solver=None, verbose=0, elif algorithm == "DLX": from sage.graphs.graph_coloring import first_coloring return first_coloring(self, hex_colors=hex_colors) - else: - raise ValueError("The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.") + + raise ValueError("The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.") @doc_index("Coloring") def chromatic_symmetric_function(self, R=None): @@ -4166,7 +4157,7 @@ def matching(self, value_only=False, algorithm="Edmonds", Same test with the Linear Program formulation:: sage: g = graphs.PappusGraph() - sage: g.matching(algorithm="LP", value_only=True) + sage: g.matching(algorithm="LP", value_only=True) # needs sage.numerical.mip 9 .. PLOT:: @@ -4182,7 +4173,7 @@ def matching(self, value_only=False, algorithm="Edmonds", sage: g = Graph([(0,1,0), (1,2,999), (2,3,-5)]) sage: sorted(g.matching()) # needs sage.networkx [(0, 1, 0), (2, 3, -5)] - sage: sorted(g.matching(algorithm="LP")) + sage: sorted(g.matching(algorithm="LP")) # needs sage.numerical.mip [(0, 1, 0), (2, 3, -5)] When ``use_edge_labels`` is set to ``True``, with Edmonds' algorithm and @@ -4191,7 +4182,7 @@ def matching(self, value_only=False, algorithm="Edmonds", sage: g = Graph([(0,1,0), (1,2,999), (2,3,-5)]) sage: g.matching(use_edge_labels=True) # needs sage.networkx [(1, 2, 999)] - sage: g.matching(algorithm="LP", use_edge_labels=True) + sage: g.matching(algorithm="LP", use_edge_labels=True) # needs sage.numerical.mip [(1, 2, 999)] With loops and multiedges:: @@ -4248,10 +4239,10 @@ def weight(x): if value_only: if use_edge_labels: return sum(W[frozenset(e)] for e in d) - else: - return Integer(len(d)) - else: - return EdgesView(Graph([(u, v, L[frozenset((u, v))]) for u, v in d], format='list_of_edges')) + return Integer(len(d)) + + return EdgesView(Graph([(u, v, L[frozenset((u, v))]) for u, v in d], + format='list_of_edges')) elif algorithm == "LP": g = self @@ -4275,13 +4266,13 @@ def weight(x): if value_only: if use_edge_labels: return sum(w for fe, w in W.items() if b[fe]) - else: - return Integer(sum(1 for fe in L if b[fe])) - else: - return EdgesView(Graph([(u, v, L[frozenset((u, v))]) for u, v in L if b[frozenset((u, v))]], format='list_of_edges')) + return Integer(sum(1 for fe in L if b[fe])) - else: - raise ValueError('algorithm must be set to either "Edmonds" or "LP"') + return EdgesView(Graph([(u, v, L[frozenset((u, v))]) + for u, v in L if b[frozenset((u, v))]], + format='list_of_edges')) + + raise ValueError('algorithm must be set to either "Edmonds" or "LP"') @doc_index("Leftovers") def is_factor_critical(self, matching=None, algorithm='Edmonds', solver=None, verbose=0, @@ -4775,8 +4766,7 @@ def maximum_average_degree(self, value_only=True, solver=None, verbose=0): if value_only: return g_mad.average_degree() - else: - return g_mad + return g_mad @doc_index("Algorithmically hard stuff") def independent_set_of_representatives(self, family, solver=None, verbose=0, @@ -5088,18 +5078,20 @@ def convexity_properties(self): .. NOTE:: - If you want to compute many convex hulls, keep this object in memory - ! When it is created, it builds a table of useful information to + If you want to compute many convex hulls, keep this object in memory! + When it is created, it builds a table of useful information to compute convex hulls. As a result :: + sage: # needs sage.numerical.mip sage: g = graphs.PetersenGraph() sage: g.convexity_properties().hull([1, 3]) [1, 2, 3] sage: g.convexity_properties().hull([3, 7]) [2, 3, 7] - Is a terrible waste of computations, while :: + is a terrible waste of computations, while :: + sage: # needs sage.numerical.mip sage: g = graphs.PetersenGraph() sage: CP = g.convexity_properties() sage: CP.hull([1, 3]) @@ -5107,7 +5099,7 @@ def convexity_properties(self): sage: CP.hull([3, 7]) [2, 3, 7] - Makes perfect sense. + makes perfect sense. """ from sage.graphs.convexity_properties import ConvexityProperties return ConvexityProperties(self) @@ -5156,8 +5148,7 @@ def centrality_degree(self, v=None): "on graphs with only one vertex") if v is None: return {v: self.degree(v)/n_minus_one for v in self} - else: - return self.degree(v)/n_minus_one + return self.degree(v)/n_minus_one # Distances @@ -5356,8 +5347,7 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, algo = 'bounds' if with_labels: return dict(zip(v, eccentricity(self, algorithm=algo, vertex_list=v))) - else: - return eccentricity(self, algorithm=algo, vertex_list=v) + return eccentricity(self, algorithm=algo, vertex_list=v) if algorithm == 'DHV': if by_weight: @@ -5366,17 +5356,15 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, return dict(zip(v, eccentricity_DHV(self, vertex_list=v, weight_function=weight_function, check_weight=check_weight))) - else: - return eccentricity_DHV(self, vertex_list=v, - weight_function=weight_function, - check_weight=check_weight) - else: - from sage.graphs.distances_all_pairs import eccentricity - if with_labels: - return dict(zip(v, eccentricity(self, algorithm=algorithm, - vertex_list=v))) - else: - return eccentricity(self, algorithm=algorithm, vertex_list=v) + return eccentricity_DHV(self, vertex_list=v, + weight_function=weight_function, + check_weight=check_weight) + + from sage.graphs.distances_all_pairs import eccentricity + if with_labels: + return dict(zip(v, eccentricity(self, algorithm=algorithm, + vertex_list=v))) + return eccentricity(self, algorithm=algorithm, vertex_list=v) if algorithm in ['Floyd-Warshall-Python', 'Floyd-Warshall-Cython', 'Johnson_Boost']: dist_dict = self.shortest_path_all_pairs(by_weight, algorithm, @@ -5410,12 +5398,11 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, if with_labels: return ecc - else: - if len(ecc) == 1: - # return single value - v, = ecc.values() - return v - return [ecc[u] for u in v] + if len(ecc) == 1: + # return single value + v, = ecc.values() + return v + return [ecc[u] for u in v] @doc_index("Distances") def radius(self, by_weight=False, algorithm='DHV', weight_function=None, @@ -5493,9 +5480,9 @@ def radius(self, by_weight=False, algorithm='DHV', weight_function=None, from sage.graphs.base.boost_graph import radius_DHV return radius_DHV(self, weight_function=weight_function, check_weight=False) - else: - from sage.graphs.distances_all_pairs import radius_DHV - return radius_DHV(self) + + from sage.graphs.distances_all_pairs import radius_DHV + return radius_DHV(self) return min(self.eccentricity(v=None, by_weight=by_weight, weight_function=weight_function, @@ -5625,9 +5612,8 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, from sage.graphs.base.boost_graph import diameter_DHV return diameter_DHV(self, weight_function=weight_function, check_weight=False) - else: - from sage.graphs.distances_all_pairs import diameter - return diameter(self, algorithm=algorithm) + from sage.graphs.distances_all_pairs import diameter + return diameter(self, algorithm=algorithm) if algorithm in ['standard', '2sweep', 'multi-sweep', 'iFUB']: if by_weight: @@ -5846,7 +5832,7 @@ def distance_graph(self, dist): The graph of eight-bit strings, adjacent if different in an odd number of bits:: - sage: # long time + sage: # long time, needs sage.symbolic sage: G = graphs.CubeGraph(8) sage: H = G.distance_graph([1,3,5,7]) sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) @@ -6606,8 +6592,7 @@ def cliques_maximal(self, algorithm="native"): elif algorithm == "NetworkX": import networkx return list(networkx.find_cliques(self.networkx_graph())) - else: - raise ValueError("Algorithm must be equal to 'native' or to 'NetworkX'.") + raise ValueError("Algorithm must be equal to 'native' or to 'NetworkX'.") @doc_index("Clique-related methods") def clique_maximum(self, algorithm="Cliquer", solver=None, verbose=0, @@ -6693,8 +6678,7 @@ def clique_maximum(self, algorithm="Cliquer", solver=None, verbose=0, integrality_tolerance=integrality_tolerance) elif algorithm == "mcqd": return mcqd(self) - else: - raise NotImplementedError("Only 'MILP', 'Cliquer' and 'mcqd' are supported.") + raise NotImplementedError("Only 'MILP', 'Cliquer' and 'mcqd' are supported.") @doc_index("Clique-related methods") def clique_number(self, algorithm="Cliquer", cliques=None, solver=None, verbose=0, @@ -6799,8 +6783,7 @@ def clique_number(self, algorithm="Cliquer", cliques=None, solver=None, verbose= integrality_tolerance=integrality_tolerance)) elif algorithm == "mcqd": return len(mcqd(self)) - else: - raise NotImplementedError("Only 'networkx' 'MILP' 'Cliquer' and 'mcqd' are supported.") + raise NotImplementedError("Only 'networkx' 'MILP' 'Cliquer' and 'mcqd' are supported.") @doc_index("Clique-related methods") def cliques_number_of(self, vertices=None, cliques=None): @@ -7007,9 +6990,8 @@ def independent_set(self, algorithm="Cliquer", value_only=False, reduction_rules integrality_tolerance=integrality_tolerance) if value_only: return self.order() - my_cover - else: - my_cover = set(my_cover) - return [u for u in self if u not in my_cover] + my_cover = set(my_cover) + return [u for u in self if u not in my_cover] @doc_index("Algorithmically hard stuff") def vertex_cover(self, algorithm="Cliquer", value_only=False, @@ -7294,19 +7276,19 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, # We finally reconstruct the solution according the reduction rules if value_only: return len(ppset) + len(folded_vertices) + size_cover_g - else: - # RULES 2 and 3: - cover_g.update(ppset) - # RULE 4: - folded_vertices.reverse() - for u, v, w in folded_vertices: - if u in cover_g: - cover_g.discard(u) - cover_g.add(v) - cover_g.add(w) - else: - cover_g.add(u) - return list(cover_g) + + # RULES 2 and 3: + cover_g.update(ppset) + # RULE 4: + folded_vertices.reverse() + for u, v, w in folded_vertices: + if u in cover_g: + cover_g.discard(u) + cover_g.add(v) + cover_g.add(w) + else: + cover_g.add(u) + return list(cover_g) @doc_index("Connectivity, orientations, trees") def ear_decomposition(self): @@ -7500,7 +7482,7 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, EXAMPLES:: sage: C = Graph('DJ{') - sage: C.cliques_vertex_clique_number() + sage: C.cliques_vertex_clique_number() # needs sage.plot {0: 2, 1: 4, 2: 4, 3: 4, 4: 4} sage: E = C.cliques_maximal(); E [[0, 4], [1, 2, 3, 4]] @@ -7510,12 +7492,12 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, sage: F = graphs.Grid2dGraph(2,3) sage: F.cliques_vertex_clique_number(algorithm="networkx") # needs networkx {(0, 0): 2, (0, 1): 2, (0, 2): 2, (1, 0): 2, (1, 1): 2, (1, 2): 2} - sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) + sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) # needs sage.plot {(0, 1): 2, (1, 2): 2} sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) sage: G.show(figsize=[2,2]) # needs sage.plot - sage: G.cliques_vertex_clique_number() + sage: G.cliques_vertex_clique_number() # needs sage.plot {0: 3, 1: 3, 2: 3, 3: 3} """ if algorithm == "cliquer": @@ -7530,8 +7512,7 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, elif algorithm == "networkx": import networkx return dict(networkx.node_clique_number(self.networkx_graph(), vertices, cliques)) - else: - raise NotImplementedError("Only 'networkx' and 'cliquer' are supported.") + raise NotImplementedError("Only 'networkx' and 'cliquer' are supported.") @doc_index("Clique-related methods") def cliques_containing_vertex(self, vertices=None, cliques=None): @@ -7881,8 +7862,7 @@ def cores(self, k=None, with_labels=False): if with_labels: return core - else: - return list(core.values()) + return list(core.values()) @doc_index("Leftovers") def modular_decomposition(self, algorithm=None, style='tuple'): @@ -8076,9 +8056,10 @@ def modular_decomposition(self, algorithm=None, style='tuple'): def relabel(x): if x.node_type == NodeType.NORMAL: return x.children[0] - else: - return x.node_type, [relabel(y) for y in x.children] + return x.node_type, [relabel(y) for y in x.children] + return relabel(D) + elif style == 'tree': from sage.combinat.rooted_tree import LabelledRootedTree if D is None: @@ -8087,11 +8068,11 @@ def relabel(x): def to_tree(x): if x.node_type == NodeType.NORMAL: return LabelledRootedTree([], label=x.children[0]) - else: - return LabelledRootedTree([to_tree(y) for y in x.children], label=x.node_type) + return LabelledRootedTree([to_tree(y) for y in x.children], label=x.node_type) + return to_tree(D) - else: - raise ValueError("style must be 'tuple' or 'tree'") + + raise ValueError("style must be 'tuple' or 'tree'") @doc_index("Graph properties") def is_polyhedral(self): @@ -8283,9 +8264,9 @@ def is_inscribable(self, solver="ppl", verbose=0): EXAMPLES:: sage: H = graphs.HerschelGraph() - sage: H.is_inscribable() # long time (> 1 sec) + sage: H.is_inscribable() # long time (> 1 sec) # needs sage.numerical.mip False - sage: H.planar_dual().is_inscribable() # long time (> 1 sec) + sage: H.planar_dual().is_inscribable() # long time (> 1 sec) # needs sage.numerical.mip True sage: C = graphs.CubeGraph(3) @@ -8929,8 +8910,8 @@ def perfect_matchings(self, labels=False): [[(-2, 1, 'x'), (-1, 2, 'y')], [(-2, 2, 'b'), (-1, 1, 'a')]] sage: G = graphs.CompleteGraph(8) - sage: mpc = G.matching_polynomial().coefficients(sparse=False)[0] - sage: len(list(G.perfect_matchings())) == mpc + sage: mpc = G.matching_polynomial().coefficients(sparse=False)[0] # needs sage.libs.flint + sage: len(list(G.perfect_matchings())) == mpc # needs sage.libs.flint True sage: G = graphs.PetersenGraph().copy(immutable=True) @@ -9049,15 +9030,15 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0, True sage: graphs.WheelGraph(5).has_perfect_matching() # needs networkx False - sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True - sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP_matching") False - sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True - sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP_matching") False @@ -9104,8 +9085,7 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0, return True except MIPSolverException: return False - else: - raise ValueError('algorithm must be set to "Edmonds", "LP_matching" or "LP"') + raise ValueError('algorithm must be set to "Edmonds", "LP_matching" or "LP"') @doc_index("Leftovers") def effective_resistance(self, i, j, *, base_ring=None): @@ -9156,7 +9136,7 @@ def effective_resistance(self, i, j, *, base_ring=None): Using a different base ring:: - sage: H.effective_resistance(1, 5, base_ring=RDF) # abs tol 1e-14 # needs sage.modules + sage: H.effective_resistance(1, 5, base_ring=RDF) # abs tol 1e-14 # needs numpy sage.modules 1.2000000000000000 sage: H.effective_resistance(1, 1, base_ring=RDF) # needs sage.modules 0.0 @@ -9189,7 +9169,7 @@ def effective_resistance(self, i, j, *, base_ring=None): 2/3 sage: G = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(1,2),(2,3),(3,4),(4,5),(5,1)]) sage: r = G.effective_resistance(0,3) - sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) + sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.libs.pari True sage: G = graphs.PathGraph(4) sage: G.delete_edge(2,3) @@ -9216,9 +9196,8 @@ def effective_resistance(self, i, j, *, base_ring=None): if j in connected_i: component = self.subgraph(connected_i) return component.effective_resistance(i, j) - else: - from sage.rings.infinity import Infinity - return Infinity + from sage.rings.infinity import Infinity + return Infinity vert = list(self) i1 = vert.index(i) @@ -9303,7 +9282,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, A different base ring:: - sage: H.effective_resistance_matrix(base_ring=RDF)[0, 0].parent() # needs sage.modules + sage: H.effective_resistance_matrix(base_ring=RDF)[0, 0].parent() # needs numpy sage.modules Real Double Field .. SEEALSO:: @@ -9754,8 +9733,7 @@ def arboricity(self, certificate=False): P = Matroid(self).partition() if certificate: return (len(P), [self.subgraph(edges=forest) for forest in P]) - else: - return len(P) + return len(P) @doc_index("Graph properties") def is_antipodal(self): diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 764ee160766..d93745b85b5 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -1598,7 +1598,7 @@ def _vizing_edge_coloring(g): True sage: all(g.has_edge(e) for C in colors for e in C) True - sage: all(len(Graph(C).matching()) == len(C) for C in colors) + sage: all(len(Graph(C).matching()) == len(C) for C in colors) # needs networkx True """ # This implementation was discussed in github issue #34809 @@ -2237,7 +2237,7 @@ cdef class Test: TESTS:: sage: from sage.graphs.graph_coloring import Test - sage: Test().random(1) + sage: Test().random(1) # needs sage.libs.flint """ self.random_all_graph_colorings(tests) @@ -2256,7 +2256,7 @@ cdef class Test: TESTS:: sage: from sage.graphs.graph_coloring import Test - sage: Test().random_all_graph_colorings(1) + sage: Test().random_all_graph_colorings(1) # needs sage.libs.flint """ from sage.graphs.generators.random import RandomGNP cdef set S diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index b8e9226bc2c..9dec951aa98 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -972,8 +972,8 @@ def query(self, query_dict=None, display_cols=None, **kwds): EXAMPLES:: sage: D = GraphDatabase() - sage: q = D.query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5]) - sage: q.show() + sage: q = D.query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5]) # needs sage.symbolic + sage: q.show() # needs sage.symbolic Graph6 Num Vertices Degree Sequence ------------------------------------------------------------ @ 1 [0] @@ -1109,7 +1109,7 @@ def interactive_query(self, display_cols, **kwds): EXAMPLES:: sage: D = GraphDatabase() - sage: D.interactive_query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=5, max_degree=3) + sage: D.interactive_query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=5, max_degree=3) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: not available in Jupyter notebook diff --git a/src/sage/graphs/graph_decompositions/cutwidth.pyx b/src/sage/graphs/graph_decompositions/cutwidth.pyx index 208bd69dea4..ddaf746adac 100644 --- a/src/sage/graphs/graph_decompositions/cutwidth.pyx +++ b/src/sage/graphs/graph_decompositions/cutwidth.pyx @@ -335,7 +335,7 @@ def cutwidth(G, algorithm="exponential", cut_off=0, solver=None, verbose=False, Comparison of algorithms:: sage: from sage.graphs.graph_decompositions.cutwidth import cutwidth - sage: for i in range(2): # long time + sage: for i in range(2): # long time # needs sage.numerical.mip ....: G = graphs.RandomGNP(7, 0.3) ....: ve, le = cutwidth(G, algorithm="exponential") ....: vm, lm = cutwidth(G, algorithm="MILP", solver='GLPK') diff --git a/src/sage/graphs/graph_decompositions/graph_products.pyx b/src/sage/graphs/graph_decompositions/graph_products.pyx index 31f49206586..cd4f0b04c7d 100644 --- a/src/sage/graphs/graph_decompositions/graph_products.pyx +++ b/src/sage/graphs/graph_decompositions/graph_products.pyx @@ -397,12 +397,12 @@ def rooted_product(G, H, root=None): sage: G = graphs.RandomGNP(20, .3) sage: P = graphs.PathGraph(2) sage: R = G.rooted_product(P) - sage: len(R.dominating_set()) == G.order() + sage: len(R.dominating_set()) == G.order() # needs sage.numerical.mip True sage: G = digraphs.RandomDirectedGNP(20, .3) sage: P = digraphs.Path(2) sage: R = G.rooted_product(P) - sage: len(R.dominating_set()) == G.order() + sage: len(R.dominating_set()) == G.order() # needs sage.numerical.mip True The rooted product of two graphs is a subgraph of the cartesian product of diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index f1d53f31e95..e45371bc6d9 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -606,7 +606,7 @@ class GraphGenerators(): sage: L = list(graphs(5, lambda G: G.size() <= 4)) sage: len(L) 14 - sage: graphs_list.show_graphs(L) # long time + sage: graphs_list.show_graphs(L) # long time # needs sage.plot Generate all graphs with up to 5 vertices and up to 4 edges. @@ -615,7 +615,7 @@ class GraphGenerators(): sage: L = list(graphs(5, lambda G: G.size() <= 4, augment='vertices')) sage: len(L) 31 - sage: graphs_list.show_graphs(L) # long time + sage: graphs_list.show_graphs(L) # long time # needs sage.plot Generate all graphs with degree at most 2, up to 6 vertices. @@ -1280,7 +1280,7 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr ....: for i in range(g.order()): ....: A.rescale_row(i, 1 / len(A.nonzero_positions_in_row(i))) ....: return A - sage: g = graphs.cospectral_graphs(5, matrix_function=DinverseA, # needs sage.modules + sage: g = graphs.cospectral_graphs(5, matrix_function=DinverseA, # needs sage.libs.pari sage.modules ....: graphs=lambda g: min(g.degree()) > 0) sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['Dlg', 'Ds_']] diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index e495ca160a4..76db076502c 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.plot r""" LaTeX options for graphs diff --git a/src/sage/graphs/graph_plot_js.py b/src/sage/graphs/graph_plot_js.py index 3bcabb58152..f1045446d65 100644 --- a/src/sage/graphs/graph_plot_js.py +++ b/src/sage/graphs/graph_plot_js.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.plot r""" Graph plotting in Javascript with d3.js diff --git a/src/sage/graphs/hyperbolicity.pyx b/src/sage/graphs/hyperbolicity.pyx index d256c01e870..880fccfc8f9 100644 --- a/src/sage/graphs/hyperbolicity.pyx +++ b/src/sage/graphs/hyperbolicity.pyx @@ -1187,7 +1187,7 @@ def hyperbolicity(G, Comparison of results:: sage: from sage.graphs.hyperbolicity import hyperbolicity - sage: for i in range(10): # long time + sage: for i in range(10): # long time # needs networkx ....: G = graphs.RandomBarabasiAlbert(100,2) ....: d1,_,_ = hyperbolicity(G, algorithm='basic') ....: d2,_,_ = hyperbolicity(G, algorithm='CCL') @@ -1201,7 +1201,7 @@ def hyperbolicity(G, sage: from sage.graphs.hyperbolicity import hyperbolicity sage: import random sage: random.seed() - sage: for i in range(10): # long time + sage: for i in range(10): # long time # needs networkx ....: n = random.randint(2, 20) ....: m = random.randint(0, n*(n-1) / 2) ....: G = graphs.RandomGNM(n, m) diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index 3d6a7d28cd6..4291e024001 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -257,7 +257,7 @@ def UniformRandomUniform(self, n, k, m): Traceback (most recent call last): ... ValueError: the uniformity should be non-negative - sage: hypergraphs.UniformRandomUniform(52, I, 17) + sage: hypergraphs.UniformRandomUniform(52, I, 17) # needs sage.symbolic Traceback (most recent call last): ... ValueError: the uniformity should be an integer diff --git a/src/sage/graphs/independent_sets.pyx b/src/sage/graphs/independent_sets.pyx index 23c8677b34a..f1dc1260c34 100644 --- a/src/sage/graphs/independent_sets.pyx +++ b/src/sage/graphs/independent_sets.pyx @@ -141,12 +141,12 @@ cdef class IndependentSets: Compute the number of matchings, and check with Sage's implementation:: sage: from sage.graphs.independent_sets import IndependentSets - sage: from sage.graphs.matchpoly import matching_polynomial + sage: from sage.graphs.matchpoly import matching_polynomial # needs sage.libs.flint sage: def check_matching(G): ....: number_of_matchings = sum(map(abs, matching_polynomial(G).coefficients(sparse=False))) ....: if number_of_matchings != IndependentSets(G.line_graph()).cardinality(): ....: raise ValueError("something goes wrong") - sage: for i in range(30): + sage: for i in range(30): # needs sage.libs.flint ....: check_matching(graphs.RandomGNP(11, .3)) Compare the result with the output of :meth:`subgraph_search`:: diff --git a/src/sage/graphs/matchpoly.pyx b/src/sage/graphs/matchpoly.pyx index 22361379291..10c8d524164 100644 --- a/src/sage/graphs/matchpoly.pyx +++ b/src/sage/graphs/matchpoly.pyx @@ -1,4 +1,5 @@ # cython: binding=True +# sage.doctest: needs sage.libs.flint sage.graphs """ Matching polynomial diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 25e803cc5d8..2c3cecfeed5 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1922,8 +1922,8 @@ def SRG_100_44_18_20(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_100_44_18_20 - sage: G = SRG_100_44_18_20() # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = SRG_100_44_18_20() # long time # needs sage.groups + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.groups (100, 44, 18, 20) """ L = ['100', '110', '130', '140', '200', '230', '240', '300', '310', '320', @@ -1944,8 +1944,8 @@ def SRG_100_45_20_20(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_100_45_20_20 - sage: G = SRG_100_45_20_20() # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = SRG_100_45_20_20() # long time # needs sage.groups + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.groups (100, 45, 20, 20) """ L = ['120', '140', '200', '210', '201', '401', '411', '321', '002', '012', @@ -2435,8 +2435,8 @@ def SRG_560_208_72_80(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_560_208_72_80 - sage: g = SRG_560_208_72_80() # not tested (~2s) - sage: g.is_strongly_regular(parameters=True) # not tested (~2s) + sage: g = SRG_560_208_72_80() # not tested (~2s) # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # not tested (~2s) # needs sage.libs.gap (560, 208, 72, 80) """ from sage.libs.gap.libgap import libgap @@ -2616,8 +2616,8 @@ def SRG_630_85_20_10(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_630_85_20_10 - sage: G = SRG_630_85_20_10() # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = SRG_630_85_20_10() # long time # needs sage.groups + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.groups (630, 85, 20, 10) """ from sage.graphs.generators.intersection import IntersectionGraph @@ -2812,7 +2812,7 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False, Petersen's graph from its set of parameters:: - sage: graphs.strongly_regular_graph(10,3,0,1,existence=True) + sage: graphs.strongly_regular_graph(10,3,0,1,existence=True) # needs sage.libs.pari True sage: graphs.strongly_regular_graph(10,3,0,1) complement(Johnson graph with parameters 5,2): Graph on 10 vertices @@ -3133,15 +3133,15 @@ def _build_small_srg_database(): complement(two-intersection set in PG(8,2)): Graph on 256 vertices sage: graphs.strongly_regular_graph(512, 73, 12, 10) # not tested (too long), needs sage.rings.finite_rings two-weight code: [219, 9] linear code over GF(2): Graph on 512 vertices - sage: graphs.strongly_regular_graph(512, 219, 106, 84) # long time + sage: graphs.strongly_regular_graph(512, 219, 106, 84) # long time, needs sage.combinat two-intersection set in PG(9,2): Graph on 512 vertices sage: graphs.strongly_regular_graph(512, 315, 202, 180) # not tested (too long), needs sage.rings.finite_rings two-weight code: [70, 9] linear code over GF(2): Graph on 512 vertices - sage: graphs.strongly_regular_graph(625, 364, 213, 210) # long time + sage: graphs.strongly_regular_graph(625, 364, 213, 210) # long time, needs sage.libs.pari complement(two-intersection set in PG(4,5)): Graph on 625 vertices - sage: graphs.strongly_regular_graph(625, 416, 279, 272) # long time + sage: graphs.strongly_regular_graph(625, 416, 279, 272) # long time, needs sage.libs.pari complement(two-intersection set in PG(4,5)): Graph on 625 vertices - sage: graphs.strongly_regular_graph(625, 468, 353, 342) # long time + sage: graphs.strongly_regular_graph(625, 468, 353, 342) # long time, needs sage.libs.pari complement(two-intersection set in PG(4,5)): Graph on 625 vertices sage: graphs.strongly_regular_graph(729, 336, 153,156) # not tested (too long) two-intersection set in PG(6,3): Graph on 729 vertices @@ -3286,7 +3286,7 @@ def _check_database(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import _check_database - sage: _check_database() # long time + sage: _check_database() # long time # needs sage.libs.pari Sage cannot build a (512 133 24 38 ) that exists. Comment ... ... In Andries Brouwer's database: diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py index 5a7b048ddfe..e82150eeb9c 100644 --- a/src/sage/graphs/tutte_polynomial.py +++ b/src/sage/graphs/tutte_polynomial.py @@ -562,7 +562,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): sage: R = PolynomialRing(ZZ, 'x') sage: R((-1)^5*x*T(1-x,0)).factor() # needs sage.symbolic (x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32) - sage: G.chromatic_polynomial().factor() + sage: G.chromatic_polynomial().factor() # needs sage.libs.flint (x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32) TESTS: @@ -580,7 +580,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): sage: g.add_edges([(0,1,1),(1,5,2),(5,3,3),(5,2,4),(2,4,5),(0,2,6),(0,3,7),(0,4,8),(0,5,9)]) sage: g.tutte_polynomial()(1,1) 52 - sage: g.spanning_trees_count() + sage: g.spanning_trees_count() # needs sage.modules 52 """ R = ZZ['x, y'] diff --git a/src/sage/groups/perm_gps/cubegroup.py b/src/sage/groups/perm_gps/cubegroup.py index 128d3beb480..134c018d3c4 100644 --- a/src/sage/groups/perm_gps/cubegroup.py +++ b/src/sage/groups/perm_gps/cubegroup.py @@ -32,19 +32,19 @@ sage: rubik = CubeGroup() sage: rubik.display2d("") - +--------------+ - | 1 2 3 | - | 4 top 5 | - | 6 7 8 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | - | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | - | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 43 | - | 44 bottom 45 | - | 46 47 48 | - +--------------+ + ┌──────────────┐ + │ 1 2 3 │ + │ 4 top 5 │ + │ 6 7 8 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 19 │ 25 26 27 │ 33 34 35 │ + │ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 │ + │ 14 15 16 │ 22 23 24 │ 30 31 32 │ 38 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 43 │ + │ 44 bottom 45 │ + │ 46 47 48 │ + └──────────────┘ AUTHORS: @@ -81,7 +81,7 @@ - Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996. -- Joyner,D., Adventures in Group Theory, Johns Hopkins Univ Press, +- Joyner, D., Adventures in Group Theory, Johns Hopkins Univ Press, 2002. """ @@ -93,13 +93,12 @@ # ***************************************************************************** from sage.groups.perm_gps.permgroup import PermutationGroup_generic -import random +from random import randint from sage.structure.sage_object import SageObject from sage.structure.richcmp import richcmp, richcmp_method - +from sage.libs.gap.libgap import libgap from sage.rings.real_double import RDF -from sage.interfaces.gap import gap from sage.groups.perm_gps.permgroup_element import PermutationGroupElement from sage.misc.lazy_import import lazy_import lazy_import("sage.plot.polygon", "polygon") @@ -113,21 +112,21 @@ ####################### predefined colors ################## named_colors = { - 'red': (1,0,0), ## F face - 'green': (0,1,0), ## R face - 'blue': (0,0,1), ## D face - 'yellow': (1,1,0), ## L face - 'white': (1,1,1), ## none - 'orange': (1,0.6,0.3), ## B face - 'purple': (1,0,1), ## none - 'lpurple': (1,0.63,1), ## U face - 'lightblue': (0,1,1), ## none - 'lgrey': (0.75,0.75,0.75), ## sagemath.org color + 'red': (1, 0, 0), ## F face + 'green': (0, 1, 0), ## R face + 'blue': (0, 0, 1), ## D face + 'yellow': (1, 1, 0), ## L face + 'white': (1, 1, 1), ## none + 'orange': (1, 0.6, 0.3), ## B face + 'purple': (1, 0, 1), ## none + 'lpurple': (1, 0.63, 1), ## U face + 'lightblue': (0, 1, 1), ## none + 'lgrey': (0.75, 0.75, 0.75), ## sagemath.org color } globals().update(named_colors) ######################################################### -#written by Tom Boothby, placed in the public domain +# written by Tom Boothby, placed in the public domain def xproj(x, y, z, r): r""" @@ -533,19 +532,19 @@ class CubeGroup(PermutationGroup_generic): sage: rubik = CubeGroup() sage: rubik.display2d("") - +--------------+ - | 1 2 3 | - | 4 top 5 | - | 6 7 8 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | - | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | - | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 43 | - | 44 bottom 45 | - | 46 47 48 | - +--------------+ + ┌──────────────┐ + │ 1 2 3 │ + │ 4 top 5 │ + │ 6 7 8 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 19 │ 25 26 27 │ 33 34 35 │ + │ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 │ + │ 14 15 16 │ 22 23 24 │ 30 31 32 │ 38 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 43 │ + │ 44 bottom 45 │ + │ 46 47 48 │ + └──────────────┘ :: @@ -574,13 +573,13 @@ def __init__(self): sage: rubik.order() 43252003274489856000 """ - U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)" ## U = top - L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)" ## L = left - F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)" ## F = front - R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)" ## R = right - B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)" ## B = back or rear - D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)" ## D = down or bottom - PermutationGroup_generic.__init__(self, gens=[B,D,F,L,R,U], canonicalize=False) + U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)" # U = top + L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)" # L = left + F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)" # F = front + R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)" # R = right + B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)" # B = back or rear + D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)" # D = down or bottom + PermutationGroup_generic.__init__(self, gens=[B, D, F, L, R, U], canonicalize=False) def gen_names(self): """ @@ -837,7 +836,7 @@ def faces(self, mv): faceD = [[fcts[40],fcts[41],fcts[42]],[fcts[43],0,fcts[44]],[fcts[45],fcts[46],fcts[47]]] faceF = [[fcts[16],fcts[17],fcts[18]],[fcts[19],0,fcts[20]],[fcts[21],fcts[22],fcts[23]]] faceB = [[fcts[32],fcts[33],fcts[34]],[fcts[35],0,fcts[36]],[fcts[37],fcts[38],fcts[39]]] - return {'right':faceR,'left':faceL,'up':faceU,'down':faceD,'front':faceF,'back':faceB} + return {'right': faceR, 'left': faceL, 'up': faceU, 'down': faceD, 'front': faceF, 'back': faceB} def move(self, mv): r""" @@ -871,19 +870,19 @@ def display2d(self, mv): sage: rubik = CubeGroup() sage: rubik.display2d("R") - +--------------+ - | 1 2 38 | - | 4 top 36 | - | 6 7 33 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 3 | 27 29 32 | 48 34 35 | - | 12 left 13 | 20 front 5 | 26 right 31 | 45 rear 37 | - | 14 15 16 | 22 23 8 | 25 28 30 | 43 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 19 | - | 44 bottom 21 | - | 46 47 24 | - +--------------+ + ┌──────────────┐ + │ 1 2 38 │ + │ 4 top 36 │ + │ 6 7 33 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 3 │ 27 29 32 │ 48 34 35 │ + │ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 8 │ 25 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 19 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ """ print(self.repr2d(mv)) @@ -896,54 +895,54 @@ def repr2d(self, mv): sage: rubik = CubeGroup() sage: print(rubik.repr2d("")) - +--------------+ - | 1 2 3 | - | 4 top 5 | - | 6 7 8 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | - | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | - | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 43 | - | 44 bottom 45 | - | 46 47 48 | - +--------------+ + ┌──────────────┐ + │ 1 2 3 │ + │ 4 top 5 │ + │ 6 7 8 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 19 │ 25 26 27 │ 33 34 35 │ + │ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 │ + │ 14 15 16 │ 22 23 24 │ 30 31 32 │ 38 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 43 │ + │ 44 bottom 45 │ + │ 46 47 48 │ + └──────────────┘ :: sage: print(rubik.repr2d("R")) - +--------------+ - | 1 2 38 | - | 4 top 36 | - | 6 7 33 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 3 | 27 29 32 | 48 34 35 | - | 12 left 13 | 20 front 5 | 26 right 31 | 45 rear 37 | - | 14 15 16 | 22 23 8 | 25 28 30 | 43 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 19 | - | 44 bottom 21 | - | 46 47 24 | - +--------------+ + ┌──────────────┐ + │ 1 2 38 │ + │ 4 top 36 │ + │ 6 7 33 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 3 │ 27 29 32 │ 48 34 35 │ + │ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 8 │ 25 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 19 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ You can see the right face has been rotated but not the left face. """ g = self.parse(mv) lst = self.facets(g) - line1 = " +--------------+\n" - line2 = " |%3d %3d %3d |\n"%(lst[0],lst[1],lst[2]) - line3 = " |%3d top %3d |\n"%(lst[3],lst[4]) - line4 = " |%3d %3d %3d |\n"%(lst[5],lst[6],lst[7]) - line5 = "+------------+--------------+-------------+------------+\n" - line6 = "|%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |\n"%(lst[8],lst[9],lst[10],lst[16],lst[17],lst[18],lst[24],lst[25],lst[26],lst[32],lst[33],lst[34]) - line7 = "|%3d left%3d |%3d front%3d |%3d right%3d |%3d rear%3d |\n"%(lst[11],lst[12],lst[19],lst[20],lst[27],lst[28],lst[35],lst[36]) - line8 = "|%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |\n"%(lst[13],lst[14],lst[15],lst[21],lst[22],lst[23],lst[29],lst[30],lst[31],lst[37],lst[38],lst[39]) - line9 = "+------------+--------------+-------------+------------+\n" - line10 = " |%3d %3d %3d |\n"%(lst[40],lst[41],lst[42]) - line11 = " |%3d bottom%3d |\n"%(lst[43],lst[44]) - line12 = " |%3d %3d %3d |\n"%(lst[45],lst[46],lst[47]) - line13 = " +--------------+\n" + line1 = " ┌──────────────┐\n" + line2 = " │%3d %3d %3d │\n" % (lst[0], lst[1], lst[2]) + line3 = " │%3d top %3d │\n" % (lst[3], lst[4]) + line4 = " │%3d %3d %3d │\n" % (lst[5], lst[6], lst[7]) + line5 = "┌────────────┼──────────────┼─────────────┬────────────┐\n" + line6 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n" % (lst[8], lst[9], lst[10], lst[16], lst[17], lst[18], lst[24], lst[25], lst[26], lst[32], lst[33], lst[34]) + line7 = "│%3d left%3d │%3d front%3d │%3d right%3d │%3d rear%3d │\n" % (lst[11], lst[12], lst[19], lst[20], lst[27], lst[28], lst[35], lst[36]) + line8 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n" % (lst[13], lst[14], lst[15], lst[21], lst[22], lst[23], lst[29], lst[30], lst[31], lst[37], lst[38], lst[39]) + line9 = "└────────────┼──────────────┼─────────────┴────────────┘\n" + line10 = " │%3d %3d %3d │\n" % (lst[40], lst[41], lst[42]) + line11 = " │%3d bottom%3d │\n" % (lst[43], lst[44]) + line12 = " │%3d %3d %3d │\n" % (lst[45], lst[46], lst[47]) + line13 = " └──────────────┘\n" return line1+line2+line3+line4+line5+line6+line7+line8+line9+line10+line11+line12+line13 def plot_cube(self, mv, title=True, colors=[lpurple, yellow, red, green, orange, blue]): @@ -970,8 +969,8 @@ def plot_cube(self, mv, title=True, colors=[lpurple, yellow, red, green, orange, clrs = sum(cubies) + sum(centers) clrs.axes(show=False) if title: - t = text('sagemath.org', (7.8,-3.5),rgbcolor=lgrey) - P = clrs+t + t = text('sagemath.org', (7.8, -3.5),rgbcolor=lgrey) + P = clrs + t P.axes(show=False) return P return clrs @@ -1011,10 +1010,10 @@ def plot3d_cube(self, mv, title=True): P = cubeR+cubeF+cubeU+centers P.axes(show=False) if title: - t1 = text('Up, Front, and Right faces. ' , (-0.2,-2.5)) - t2 = text(' sagemath.org', (0.8,-3.1),rgbcolor=lgrey) - t3 = text(" ",(3.5,0),rgbcolor=white) - P = P+t1+t2+t3 + t1 = text('Up, Front, and Right faces. ' , (-0.2, -2.5)) + t2 = text(' sagemath.org', (0.8, -3.1),rgbcolor=lgrey) + t3 = text(" ", (3.5, 0), rgbcolor=white) + P = P + t1 + t2 + t3 P.axes(show=False) return P return P @@ -1107,12 +1106,11 @@ def solve(self, state, algorithm='default'): C = RubiksCube(g) return C.solve(algorithm) - hom = self._gap_().EpimorphismFromFreeGroup() - soln = hom.PreImagesRepresentative(str(g)) - sol = str(soln) - names = self.gen_names() - for i in range(6): - sol = sol.replace("x%s" % (i + 1), names[i]) + group = libgap(self) + hom = group.EpimorphismFromFreeGroup() + sol = str(hom.PreImagesRepresentative(libgap(g))) + for i, name in enumerate(self.gen_names()): + sol = sol.replace("x%s" % (i + 1), name) return sol @@ -1202,19 +1200,19 @@ class RubiksCube(SageObject): :: sage: C = RubiksCube("R*L"); C - +--------------+ - | 17 2 38 | - | 20 top 36 | - | 22 7 33 | - +------------+--------------+-------------+------------+ - | 11 13 16 | 41 18 3 | 27 29 32 | 48 34 6 | - | 10 left 15 | 44 front 5 | 26 right 31 | 45 rear 4 | - | 9 12 14 | 46 23 8 | 25 28 30 | 43 39 1 | - +------------+--------------+-------------+------------+ - | 40 42 19 | - | 37 bottom 21 | - | 35 47 24 | - +--------------+ + ┌──────────────┐ + │ 17 2 38 │ + │ 20 top 36 │ + │ 22 7 33 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 11 13 16 │ 41 18 3 │ 27 29 32 │ 48 34 6 │ + │ 10 left 15 │ 44 front 5 │ 26 right 31 │ 45 rear 4 │ + │ 9 12 14 │ 46 23 8 │ 25 28 30 │ 43 39 1 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 40 42 19 │ + │ 37 bottom 21 │ + │ 35 47 24 │ + └──────────────┘ sage: C.show() # needs sage.plot sage: C.solve(algorithm='gap') # long time 'L*R' @@ -1280,20 +1278,19 @@ def _repr_(self): EXAMPLES:: sage: RubiksCube().move("R*U") - +--------------+ - | 3 5 38 | - | 2 top 36 | - | 1 4 25 | - +------------+--------------+-------------+------------+ - | 33 34 35 | 9 10 8 | 19 29 32 | 48 26 27 | - | 12 left 13 | 20 front 7 | 18 right 31 | 45 rear 37 | - | 14 15 16 | 22 23 6 | 17 28 30 | 43 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 11 | - | 44 bottom 21 | - | 46 47 24 | - +--------------+ - + ┌──────────────┐ + │ 3 5 38 │ + │ 2 top 36 │ + │ 1 4 25 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 33 34 35 │ 9 10 8 │ 19 29 32 │ 48 26 27 │ + │ 12 left 13 │ 20 front 7 │ 18 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 6 │ 17 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 11 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ """ return self._group.repr2d(self._state) @@ -1352,8 +1349,8 @@ def cubie(self, size, gap, x, y, z, colors, stickers=True): sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3) # needs sage.plot Graphics3d Object """ - sides = cubie_face_list[x,y,z] - t = 2*size+gap + sides = cubie_face_list[x, y, z] + t = 2 * size + gap my_colors = [colors[sides[i]+6] for i in range(6)] if stickers: B = Box(size, size, size, color=(.1, .1, .1)) @@ -1377,7 +1374,7 @@ def plot3d(self, stickers=True): side_colors = [Texture(color=c, ambient=.75) for c in self.colors] start_colors = sum([[c]*8 for c in side_colors], []) facets = self._group.facets(self._state) - facet_colors = [0]*48 + facet_colors = [0] * 48 for i in range(48): facet_colors[facets[i]-1] = start_colors[i] all_colors = side_colors + facet_colors @@ -1493,7 +1490,7 @@ def solve(self, algorithm="hybrid", timeout=15): return solver.solve(self._state, algorithm="gap") else: - raise ValueError("Unrecognized algorithm: %s" % algorithm) + raise ValueError(f"Unrecognized algorithm: {algorithm}") def scramble(self, moves=30): """ @@ -1503,26 +1500,25 @@ def scramble(self, moves=30): sage: C = RubiksCube() sage: C.scramble() # random - +--------------+ - | 38 29 35 | - | 20 top 42 | - | 11 44 30 | - +------------+--------------+-------------+------------+ - | 48 13 17 | 6 15 24 | 43 23 9 | 1 36 32 | - | 4 left 18 | 7 front 37 | 12 right 26 | 5 rear 10 | - | 33 31 40 | 14 28 8 | 25 47 16 | 22 2 3 | - +------------+--------------+-------------+------------+ - | 46 21 19 | - | 45 bottom 39 | - | 27 34 41 | - +--------------+ - + ┌──────────────┐ + │ 3 5 38 │ + │ 2 top 36 │ + │ 1 4 25 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 33 34 35 │ 9 10 8 │ 19 29 32 │ 48 26 27 │ + │ 12 left 13 │ 20 front 7 │ 18 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 6 │ 17 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 11 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ """ last_move = move = " " all = [] for i in range(moves): while move[0] == last_move[0]: - move = "RLUDBF"[random.randint(0,5)] + " '2"[random.randint(0,2)] + move = "RLUDBF"[randint(0, 5)] + " '2"[randint(0, 2)] last_move = move all.append(move) return self.move(' '.join(all)) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index bf53c7b6113..ace9775d56b 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -26,17 +26,24 @@ # https://www.gnu.org/licenses/ ######################################################################## +from sage.algebras.steenrod.steenrod_algebra import SteenrodAlgebra from sage.misc.cachefunc import cached_method from sage.categories.algebras import Algebras +from sage.categories.category import Category +from sage.categories.left_modules import LeftModules +from sage.categories.right_modules import RightModules from sage.categories.modules import Modules from sage.combinat.free_module import CombinatorialFreeModule +from sage.matrix.constructor import matrix +from sage.modules.free_module_element import vector from sage.sets.family import Family try: from sage.topology.simplicial_complex import SimplicialComplex from sage.topology.simplicial_set import SimplicialSet_arbitrary + from sage.topology.cubical_complex import CubicalComplex except ImportError: - SimplicialComplex = SimplicialSet_arbitrary = () + SimplicialComplex = SimplicialSet_arbitrary = CubicalComplex = () class HomologyVectorSpaceWithBasis(CombinatorialFreeModule): @@ -385,6 +392,65 @@ def _to_cycle_on_basis(self, i): cochains=self._cohomology) return chains.from_vector(vec) + def dual(self): + r""" + Return the dual space. + + If ``self`` is homology, return the cohomology ring. If + ``self`` is cohomology, return the homology as a vector space. + + EXAMPLES:: + + sage: T = simplicial_complexes.Torus() + sage: hom = T.homology_with_basis(GF(2)) + sage: coh = T.cohomology_ring(GF(2)) + sage: hom.dual() is coh + True + sage: coh.dual() is hom + True + """ + if is_GF2(self.base_ring()): + if self._cohomology: + return HomologyVectorSpaceWithBasis_mod2(self.base_ring(), + self.complex()) + return CohomologyRing_mod2(self.base_ring(), self.complex()) + if self._cohomology: + return HomologyVectorSpaceWithBasis(self.base_ring(), + self.complex(), + not self._cohomology) + return CohomologyRing(self.base_ring(), self.complex()) + + def _test_duality(self, **options): + r""" + Test if the ordered bases for homology and cohomology are compatible. + Return nothing if the test succeeds. + + This checks whether each evaluation map `H^n \otimes H_n \to + k` is represented by the identity matrix, in terms of the + chosen bases. + + TESTS:: + + sage: T = simplicial_complexes.Torus() + sage: K = T.suspension() + sage: K.set_immutable() + sage: H = K.cohomology_ring(QQ) + sage: H._test_duality() + + sage: simplicial_complexes.RandomComplex(8, 2, .2).homology_with_basis(GF(2))._test_duality() + sage: simplicial_complexes.RandomComplex(8, 2, .4).homology_with_basis(GF(2))._test_duality() + sage: simplicial_complexes.RandomComplex(8, 2, .6).homology_with_basis(GF(2))._test_duality() + + sage: simplicial_complexes.RandomComplex(12, 3, .5).homology_with_basis(GF(2))._test_duality() # long time + """ + tester = self._tester(**options) + dual = self.dual() + dims = [a[0] for a in self._indices] + for dim in range(max(max(dims), tester._max_runs) + 1): + n = len(self.basis(dim)) + m = matrix(n, n, [a.eval(b) for a in self.basis(dim) for b in dual.basis(dim)]) + tester.assertEqual(m, 1, f"error in dimension {dim}") + class Element(CombinatorialFreeModule.Element): def to_cycle(self): r""" @@ -413,6 +479,226 @@ def to_cycle(self): raise ValueError("only defined for homogeneous elements") return sum(c * self.parent()._to_cycle_on_basis(i) for i, c in self) + def eval(self, other): + r""" + Evaluate ``self`` at ``other``. + + INPUT: + + - ``other`` -- an element of the dual space; if ``self`` + is an element of cohomology in dimension `n`, then + ``other`` should be an element of homology in dimension + `n`, and vice versa + + This just calls the :meth:`~sage.homology.chains.Cochains.Element.eval` + method on the representing chains and cochains. + + EXAMPLES:: + + sage: T = simplicial_complexes.Torus() + sage: homology = T.homology_with_basis(QQ) + sage: cohomology = T.cohomology_ring(QQ) + sage: a1, a2 = homology.basis(1) + sage: alpha1, alpha2 = cohomology.basis(1) + sage: a1.to_cycle() + (0, 3) - (0, 6) + (3, 6) + sage: alpha1.to_cycle() + -\chi_(1, 3) - \chi_(1, 4) - \chi_(2, 3) - \chi_(2, 4) - \chi_(2, 5) + \chi_(3, 6) + sage: a1.eval(alpha1) + 1 + sage: alpha2.to_cycle() + \chi_(1, 3) + \chi_(1, 4) + \chi_(1, 6) + \chi_(2, 4) - \chi_(4, 5) + \chi_(5, 6) + sage: alpha2.eval(a1) + 0 + sage: (2 * alpha2).eval(a1 + a2) + 2 + """ + if not self or not other: + return self.base_ring().zero() + if self.parent()._cohomology: + return self.to_cycle().eval(other.to_cycle()) + else: + return other.to_cycle().eval(self.to_cycle()) + + +class HomologyVectorSpaceWithBasis_mod2(HomologyVectorSpaceWithBasis): + r""" + Homology vector space mod 2. + + Based on :class:`HomologyVectorSpaceWithBasis`, with Steenrod + operations included. + + .. NOTE:: + + This is not intended to be created directly by the user, but + instead via the method + :meth:`~sage.topology.cell_complex.GenericCellComplex.homology_with_basis` + for the class of :class:`cell + complexes`. + + .. TODO:: + + Implement Steenrod operations on (co)homology at odd primes, + and thereby implement this class over `\GF{p}` for any `p`. + + INPUT: + + - ``base_ring`` -- must be the field ``GF(2)`` + - ``cell_complex`` -- the cell complex whose homology we are + computing + - ``category`` -- (optional) a subcategory of modules with basis + + This does not include the ``cohomology`` argument present for + :class:`HomologyVectorSpaceWithBasis`: use + :class:`CohomologyRing_mod2` for cohomology. + + EXAMPLES: + + Mod 2 cohomology operations are defined on both the left and the + right:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(5) + sage: H = RP4.homology_with_basis(GF(2)) + sage: x4 = H.basis()[4,0] + sage: x4 * Sq(1) + h_{3,0} + sage: Sq(1) * x4 + h_{3,0} + sage: Sq(2) * x4 + h_{2,0} + sage: Sq(3) * x4 + h_{1,0} + sage: Sq(0,1) * x4 + h_{1,0} + sage: x4 * Sq(0,1) + h_{1,0} + sage: Sq(3) * x4 + h_{1,0} + sage: x4 * Sq(3) + 0 + """ + def __init__(self, base_ring, cell_complex, category=None): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: H = simplicial_complexes.Torus().homology_with_basis(GF(2)) + sage: TestSuite(H).run() + sage: H = simplicial_complexes.Sphere(3).homology_with_basis(GF(2)) + sage: TestSuite(H).run() + """ + if not is_GF2(base_ring): + raise ValueError + category = Modules(base_ring).WithBasis().Graded().FiniteDimensional().or_subcategory(category) + category = Category.join((category, + LeftModules(SteenrodAlgebra(2)), + RightModules(SteenrodAlgebra(2)))) + HomologyVectorSpaceWithBasis.__init__(self, base_ring, + cell_complex, + cohomology=False, + category=category) + + class Element(HomologyVectorSpaceWithBasis.Element): + + def _acted_upon_(self, a, self_on_left): + r""" + Define multiplication of ``self`` by ``a``, an + element of the Steenrod algebra. + + INPUT: + + - ``a`` - an element of the mod 2 Steenrod algebra + - ``self_on_left`` -- ``True`` if we are computing ``self * a``, + otherwise ``a * self`` + + Algorithm: use the action of the Steenrod algebra `A` on + cohomology to construct the action on homology. That is, + given a right action of `A` on `H^*`, + + .. MATH:: + + \phi_L: H^* \otimes A \to H^* + + we define (a la Boardman [Boa1982]_, p. 190) + + .. MATH:: + + S'' \phi_L: A \otimes H_* \to H_* + + using the formula + + .. MATH:: + + \langle (S'' \phi) (f \otimes a), x \rangle + = \langle f, \phi_L (a \otimes x) \rangle, + + for `f \in H_m`, `a \in A^n`, and `x \in + H^{m-n}`. Somewhat more succintly, we define the action `f + \cdot a` by + + .. MATH:: + + (f \cdot a) (x) = f (a \cdot x). + + So given `f` (a.k.a. ``self``) and `a`, we compute `f (a + \cdot x)` for all basis elements `x` in `H^{m-n}`, + yielding a vector indexed by those basis elements. Since + our basis for homology is dual to the basis for + cohomology, we can then use the homology basis to convert + the vector to an element of `H_{m-n}`. + + This gives a right module structure. To get a left module + structure, use the right module structure after applying + the antipode to `a`. + + EXAMPLES:: + + sage: # needs sage.groups + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) + sage: H = RP5.homology_with_basis(GF(2)) + sage: x5 = list(H.basis(5))[0] + sage: Sq(1) * x5 + 0 + sage: Sq(2) * x5 + h_{3,0} + sage: x5 * Sq(2) + h_{3,0} + + TESTS:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(5) + sage: H = RP4.homology_with_basis(GF(2)) + sage: x4 = H.basis()[4,0] + sage: (Sq(1) * Sq(2)) * x4 != 0 + True + sage: (Sq(1) * Sq(2)) * x4 == Sq(1) * (Sq(2) * x4) + True + sage: x4 * (Sq(2) * Sq(1)) == (x4 * Sq(2)) * Sq(1) + True + sage: 1 * x4 + h_{4,0} + sage: x4 * 0 + 0 + """ + # Handle field elements first. + ret = CombinatorialFreeModule.Element._acted_upon_(self, a, self_on_left) + if ret is not None: # did the scalar action + return ret + m = self.degree() + n = a.degree() + if m <= n: + return self.parent().zero() + + if not self_on_left: # i.e., module element on left + a = a.antipode() + P = self.parent() + B = list(P.basis(m-n)) + return P._from_dict({x.support()[0]: self.eval(a * x) + for x in sorted(self.parent().dual().basis(m-n))}) + class CohomologyRing(HomologyVectorSpaceWithBasis): """ @@ -431,6 +717,7 @@ class CohomologyRing(HomologyVectorSpaceWithBasis): - ``base_ring`` -- must be a field - ``cell_complex`` -- the cell complex whose homology we are computing + - ``category`` -- (optional) a subcategory of modules with basis EXAMPLES:: @@ -446,47 +733,23 @@ class CohomologyRing(HomologyVectorSpaceWithBasis): -h^{4,0} sage: x * x -h^{4,0} - - There are mod 2 cohomology operations defined, also, for - simplicial complexes and simplicial sets:: - - sage: Hmod2 = CP2.cohomology_ring(GF(2)) - sage: y = Hmod2.basis(2)[2,0] - sage: y.Sq(2) - h^{4,0} - - sage: # needs sage.groups - sage: Y = simplicial_sets.RealProjectiveSpace(6).suspension() - sage: H_Y = Y.cohomology_ring(GF(2)) - sage: b = H_Y.basis()[2,0] - sage: b.Sq(1) - h^{3,0} - sage: b.Sq(2) - 0 - sage: c = H_Y.basis()[4,0] - sage: c.Sq(1) - h^{5,0} - sage: c.Sq(2) - h^{6,0} - sage: c.Sq(3) - h^{7,0} - sage: c.Sq(4) - 0 """ - def __init__(self, base_ring, cell_complex): + def __init__(self, base_ring, cell_complex, category=None): """ Initialize ``self``. EXAMPLES:: sage: RP2 = simplicial_complexes.ProjectivePlane() - sage: H = RP2.cohomology_ring(GF(2)) - sage: TestSuite(H).run() sage: H = RP2.cohomology_ring(GF(5)) sage: TestSuite(H).run() + sage: T = simplicial_complexes.Torus() + sage: H = T.cohomology_ring(QQ) + sage: TestSuite(H).run() """ - cat = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() - HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, True, cat) + if category is None: + category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() + HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, True, category) def _repr_(self): """ @@ -676,6 +939,94 @@ def cup_product(self, other): """ return self * other + +class CohomologyRing_mod2(CohomologyRing): + r""" + The mod 2 cohomology ring. + + Based on :class:`CohomologyRing`, with Steenrod operations included. + + .. NOTE:: + + This is not intended to be created directly by the user, but + instead via the + :meth:`cohomology ring` + of a :class:`cell + complex`. + + .. TODO:: + + Implement Steenrod operations on (co)homology at odd primes, + and thereby implement this class over `\GF{p}` for any `p`. + + INPUT: + + - ``base_ring`` -- must be the field ``GF(2)`` + - ``cell_complex`` -- the cell complex whose homology we are + computing + + EXAMPLES: + + Mod 2 cohomology operations are defined on both the left and the + right:: + + sage: CP2 = simplicial_complexes.ComplexProjectivePlane() + sage: Hmod2 = CP2.cohomology_ring(GF(2)) + sage: y = Hmod2.basis(2)[2,0] + sage: y.Sq(2) + h^{4,0} + + sage: # needs sage.groups + sage: Y = simplicial_sets.RealProjectiveSpace(6).suspension() + sage: H_Y = Y.cohomology_ring(GF(2)) + sage: b = H_Y.basis()[2,0] + sage: b.Sq(1) + h^{3,0} + sage: b.Sq(2) + 0 + sage: c = H_Y.basis()[4,0] + sage: c.Sq(1) + h^{5,0} + sage: c.Sq(2) + h^{6,0} + sage: c.Sq(3) + h^{7,0} + sage: c.Sq(4) + 0 + + Cohomology can be viewed as a left module over the Steenrod + algebra, and also as a right module:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) + sage: H = RP4.cohomology_ring(GF(2)) + sage: x = H.basis()[1,0] + sage: Sq(0,1) * x + h^{4,0} + sage: Sq(3) * x + 0 + sage: x * Sq(3) + h^{4,0} + """ + def __init__(self, base_ring, cell_complex): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: RP2 = simplicial_complexes.ProjectivePlane() + sage: H = RP2.cohomology_ring(GF(2)) + sage: TestSuite(H).run() + """ + if not is_GF2(base_ring): + raise ValueError("the base ring must be GF(2)") + category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() + category = Category.join((category, + LeftModules(SteenrodAlgebra(2)), + RightModules(SteenrodAlgebra(2)))) + CohomologyRing.__init__(self, base_ring, cell_complex, category=category) + + class Element(CohomologyRing.Element): def Sq(self, i): r""" Return the result of applying `Sq^i` to this element. @@ -686,10 +1037,16 @@ def Sq(self, i): .. WARNING:: - This is only implemented for simplicial complexes. + The main implementation is only for simplicial + complexes and simplicial sets; cubical complexes are + converted to simplicial complexes first. Note that + this converted complex may be large and so computations + may be slow. There is no implementation for + `\Delta`-complexes. This cohomology operation is only defined in - characteristic 2. + characteristic 2. Odd primary Steenrod operations are not + implemented. Algorithm: see González-Díaz and Réal [GDR1999]_, Corollary 3.2. @@ -707,6 +1064,8 @@ def Sq(self, i): sage: y.Sq(1) h^{3,0} + sage: # long time + sage: # needs sage.groups sage: RP4 = simplicial_complexes.RealProjectiveSpace(4) sage: H = RP4.cohomology_ring(GF(2)) sage: x = H.basis()[1,0] @@ -714,7 +1073,7 @@ def Sq(self, i): sage: z = H.basis()[3,0] sage: x.Sq(1) == y True - sage: z.Sq(1) # long time + sage: z.Sq(1) h^{4,0} This calculation is much faster with simplicial sets (on @@ -728,26 +1087,35 @@ def Sq(self, i): TESTS:: - sage: T = cubical_complexes.Torus() - sage: x = T.cohomology_ring(GF(2)).basis()[1,0] + sage: RP_cubical = cubical_complexes.RealProjectivePlane() + sage: x = RP_cubical.cohomology_ring(GF(2)).basis()[1,0] sage: x.Sq(1) - Traceback (most recent call last): - ... - NotImplementedError: Steenrod squares are only implemented for simplicial complexes and simplicial sets - sage: S2 = simplicial_complexes.Sphere(2) - sage: x = S2.cohomology_ring(GF(7)).basis()[2,0] + h^{2,0} + sage: T = delta_complexes.Torus() + sage: x = T.cohomology_ring(GF(2)).basis()[1,0] sage: x.Sq(1) Traceback (most recent call last): ... - ValueError: Steenrod squares are only defined in characteristic 2 + NotImplementedError: Steenrod squares are not implemented for this type of cell complex """ P = self.parent() scomplex = P.complex() + if isinstance(scomplex, CubicalComplex): + # Convert cubical complex to simplicial complex, and + # convert self to basis element in the new complex's + # cohomology ring. + scomplex = SimplicialComplex(scomplex, is_mutable=False) + P = scomplex.cohomology_ring(self.base_ring()) + self = P.sum_of_terms(self.monomial_coefficients().items()) if not isinstance(scomplex, (SimplicialComplex, SimplicialSet_arbitrary)): - raise NotImplementedError('Steenrod squares are only implemented for ' - 'simplicial complexes and simplicial sets') + print(scomplex, isinstance(scomplex, SimplicialComplex)) + raise NotImplementedError('Steenrod squares are not implemented for ' + 'this type of cell complex') + scomplex = P.complex() base_ring = P.base_ring() - if base_ring.characteristic() != 2: + if not is_GF2(base_ring): + # This should never happen: the class should only be + # instantiated in characteristic 2. raise ValueError('Steenrod squares are only defined in characteristic 2') # We keep the same notation as in [GDR1999]. # The trivial cases: @@ -841,6 +1209,194 @@ def Sq(self, i): ret += P._from_dict(result, remove_zeros=False) return ret + def _acted_upon_(self, a, self_on_left): + r""" + Define multiplication of ``self`` by ``a``, an + element of the Steenrod algebra. + + INPUT: + + - ``a`` -- an element of the mod 2 Steenrod algebra + - ``self_on_left`` -- ``True`` if we are computing ``self * a``, + otherwise ``a * self`` + + Algorithm: for left multiplication by ``a``, since we have + :meth:`Sq` to compute multiplication by a single generator + `Sq^i`, first convert ``a`` to the Serre-Cartan basis --- + that is, sums of products of the elements `Sq^i` --- and + then apply :meth:`Sq` repeatedly. Right multiplication by + ``a`` is the same as left multiplication by the antipode + applied to ``a``. + + EXAMPLES:: + + sage: # needs sage.groups + sage: SRP4 = simplicial_sets.RealProjectiveSpace(4).suspension() + sage: H = SRP4.cohomology_ring(GF(2)) + sage: x = H.basis()[2,0] + sage: Sq(0,1) * x + h^{5,0} + sage: Sq(3) * x + 0 + sage: x * Sq(3) + h^{5,0} + + TESTS:: + + sage: # needs sage.groups + sage: (Sq(2) * Sq(1)) * x == Sq(2) * (Sq(1) * x) + True + sage: x * (Sq(1) * Sq(2)) == (x * Sq(1)) * Sq(2) + True + sage: x * 1 + h^{2,0} + sage: 0 * x + 0 + """ + # Handle field elements first. + ret = CombinatorialFreeModule.Element._acted_upon_(self, a, self_on_left) + if ret is not None: # did the scalar action + return ret + if self_on_left: # i.e., module element on left + a = a.antipode() + b = a.change_basis('adem') + ans = self.parent().zero() + mono_dict = b.monomial_coefficients() + for seq in mono_dict: + x = self + for i in reversed(seq): + x = x.Sq(i) + ans += mono_dict[seq] * x + return ans + + def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): + r""" + Return a component of the module structure map `A \otimes + H \to H`, where `H` is this cohomology ring and `A` is the + Steenrod algebra. + + INPUT: + + - ``deg_domain`` -- the degree of the domain in the cohomology + ring + + - ``deg_codomain`` -- the degree of the codomain in the + cohomology ring + + - ``side`` -- (default ``'left'``) whether we are computing + the action as a left module action or a right module + + We will write this with respect to the left action; + for the right action, just switch all of the the tensors. + Writing `m` for ``deg_domain`` and `n` for ``deg_codomain``, this + returns `A^{n-m} \otimes H^{m} \to H^{n}`, one single + component of the map making `H` into an `A`-module. + + .. WARNING:: + + This is only implemented in characteristic two. The main + implementation is only for simplicial complexes and simplicial + sets; cubical complexes are converted to simplicial complexes + first. Note that this converted complex may be large and so + computations may be slow. There is no implementation for + `\Delta`-complexes. + + ALGORITHM: + + Use the Milnor basis for the truncated Steenrod + algebra `A`, and for cohomology, use the basis with which it + is equipped. For each pair of basis elements `a` and `h`, + compute the product `a \otimes h`, and use this to assemble a + matrix defining the action map via multiplication on the + appropriate side. That is, if ``side`` is ``'left'``, return a + matrix suitable for multiplication on the left, etc. + + EXAMPLES:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) + sage: H = RP4.cohomology_ring(GF(2)) + sage: H.steenrod_module_map(1, 2) + [1] + sage: H.steenrod_module_map(1, 3) + [0] + sage: H.steenrod_module_map(1, 4, 'left') + [1 0] + sage: H.steenrod_module_map(1, 4, 'right') + [1] + [1] + + Products of projective spaces:: + + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) + sage: K = RP3.product(RP3) + sage: H = K.cohomology_ring(GF(2)) + sage: H + Cohomology ring of RP^3 x RP^3 over Finite Field of size 2 + + There is one column for each element `a \otimes b`, where `a` + is a basis element for the Steenrod algebra and `b` is a basis + element for the cohomology algebra. There is one row for each + basis element of the cohomology algebra. Unfortunately, the + chosen basis for this truncated polynomial algebra is not the + monomial basis:: + + sage: x1, x2 = H.basis(1) + sage: x1 * x1 + h^{2,0} + h^{2,1} + sage: x2 * x2 + h^{2,2} + sage: x1 * x2 + h^{2,0} + + sage: H.steenrod_module_map(1, 2) + [1 0] + [1 0] + [0 1] + sage: H.steenrod_module_map(1, 3, 'left') + [0 0] + [0 0] + [0 0] + [0 0] + sage: H.steenrod_module_map(1, 3, 'right') + [0 0 0 0] + [0 0 0 0] + sage: H.steenrod_module_map(2, 3) + [0 0 0] + [1 1 0] + [0 0 0] + [0 0 0] + """ + side = side.lower() + if side not in ['right', 'left']: + raise ValueError('side must be either "left" or "right"') + base_ring = self.base_ring() + char = base_ring.characteristic() + # Use sorted(...) so that there are reproducible orders on the bases. + A_basis = sorted(SteenrodAlgebra(char).basis(deg_codomain - deg_domain)) + H_basis_dom = sorted(self.basis(deg_domain)) + H_basis_cod = self.basis(deg_codomain).keys() + H_basis_cod = {elt: idx for idx, elt in enumerate(sorted(H_basis_cod))} + entries = [] + for a in A_basis: + for h in H_basis_dom: + vec = vector(base_ring, len(H_basis_cod)) + if side == 'left': + x = a * h + else: + x = h * a + monos = x.monomial_coefficients() + for seq in monos: + vec[H_basis_cod[seq]] = monos[seq] + entries.extend(vec) + # We built the matrix column by column, so now we take the + # transpose. + if side == 'left': + return matrix(base_ring, len(A_basis) * len(H_basis_dom), + len(H_basis_cod), entries).transpose() + return matrix(base_ring, len(A_basis) * len(H_basis_dom), + len(H_basis_cod), entries) + def sum_indices(k, i_k_plus_one, S_k_plus_one): r""" @@ -881,3 +1437,19 @@ def sum_indices(k, i_k_plus_one, S_k_plus_one): return [[S_k]] return [[i_k] + l for i_k in range(S_k, i_k_plus_one) for l in sum_indices(k-1, i_k, S_k)] + +def is_GF2(R): + r""" + Return ``True`` iff ``R`` is isomorphic to the field `\GF{2}`. + + EXAMPLES:: + + sage: from sage.homology.homology_vector_space_with_basis import is_GF2 + sage: is_GF2(GF(2)) + True + sage: is_GF2(GF(2, impl='ntl')) + True + sage: is_GF2(GF(3)) + False + """ + return 2 == R.characteristic() == R.cardinality() diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index 939a142aa70..5df8d2e184a 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -43,7 +43,7 @@ clisp. If the string "error" (case insensitive) occurs in the output of -anything from axiom, a RuntimeError exception is raised. +anything from axiom, a :class:`RuntimeError` exception is raised. EXAMPLES: We evaluate a very simple expression in axiom. diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 61f38af2d26..dd4c87ce988 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -430,7 +430,7 @@ def load_package(self, pkg, verbose=False): """ Load the Gap package with the given name. - If loading fails, raise a RuntimeError exception. + If loading fails, raise a :class:`RuntimeError` exception. TESTS:: diff --git a/src/sage/interfaces/gap_workspace.py b/src/sage/interfaces/gap_workspace.py index 03b40be6856..c104664143a 100644 --- a/src/sage/interfaces/gap_workspace.py +++ b/src/sage/interfaces/gap_workspace.py @@ -88,7 +88,9 @@ def prepare_workspace_dir(dir=None): TESTS:: - sage: prepare_workspace_dir(os.path.join(tmp_dir(), "new")) + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: prepare_workspace_dir(os.path.join(d, "new")) '.../new' """ if dir is None: diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index d7a259fd3d5..cd7e7b8def5 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -48,7 +48,7 @@ If the string "error" (case insensitive) occurs in the output of -anything from Giac, a RuntimeError exception is raised. +anything from Giac, a :class:`RuntimeError` exception is raised. Tutorial -------- diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index e9f0d5d6fb0..42f680e001b 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -36,7 +36,7 @@ (x-y)*(x^4+x^3*y+x^2*y^2+x*y^3+y^4) If the string "error" (case insensitive) occurs in the output of -anything from Maple, a RuntimeError exception is raised. +anything from Maple, a :class:`RuntimeError` exception is raised. Tutorial -------- diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index c55f9797ef2..5526e2c6458 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -35,7 +35,7 @@ If the string "error" (case insensitive) occurs in the output of -anything from Maxima, a RuntimeError exception is raised. +anything from Maxima, a :class:`RuntimeError` exception is raised. EXAMPLES: We evaluate a very simple expression in Maxima. diff --git a/src/sage/interfaces/mwrank.py b/src/sage/interfaces/mwrank.py index 35d73277109..92a9081eb4c 100644 --- a/src/sage/interfaces/mwrank.py +++ b/src/sage/interfaces/mwrank.py @@ -294,7 +294,7 @@ def eval(self, s, **kwds): .. NOTE:: - If a RuntimeError exception is raised, then the mwrank + If a :class:`RuntimeError` exception is raised, then the mwrank interface is restarted and the command is retried once. EXAMPLES:: diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx index 05ca5f7d4fb..33a17cff528 100644 --- a/src/sage/libs/gap/libgap.pyx +++ b/src/sage/libs/gap/libgap.pyx @@ -412,7 +412,7 @@ class Gap(Parent): def load_package(self, pkg): """ - If loading fails, raise a RuntimeError exception. + If loading fails, raise a :class:`RuntimeError` exception. TESTS:: diff --git a/src/sage/libs/linkages/padics/API.pxi b/src/sage/libs/linkages/padics/API.pxi index 529fc49a95b..ec69c5bbaa3 100644 --- a/src/sage/libs/linkages/padics/API.pxi +++ b/src/sage/libs/linkages/padics/API.pxi @@ -469,7 +469,7 @@ cdef inline long chash(celement a, long ordp, long prec, PowComputer_class prime # the expansion_mode enum is defined in padic_template_element_header.pxi cdef inline cexpansion_next(celement value, expansion_mode mode, long curpower, PowComputer_ prime_pow): - """ + r""" Return the next digit in a `\pi`-adic expansion of ``value``. INPUT: @@ -483,7 +483,7 @@ cdef inline cexpansion_next(celement value, expansion_mode mode, long curpower, pass cdef inline cexpansion_getitem(celement value, long m, PowComputer_ prime_pow): - """ + r""" Return the `m`th `\pi`-adic digit in the ``simple_mode`` expansion. INPUT: @@ -512,7 +512,7 @@ cdef list ccoefficients(celement x, long valshift, PowComputer_class prime_pow): pass cdef int cteichmuller(celement out, celement value, long prec, PowComputer_class prime_pow) except -1: - """ + r""" Teichmuller lifting. INPUT: diff --git a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi index 8b1b80cf0a9..843070f4a42 100644 --- a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi +++ b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi @@ -668,7 +668,7 @@ cdef list ccoefficients(celement x, long valshift, long prec, PowComputer_ prime return ans cdef int cteichmuller(celement out, celement value, long prec, PowComputer_ prime_pow) except -1: - """ + r""" Teichmuller lifting. INPUT: @@ -848,7 +848,7 @@ cdef inline int cconv_mpz_t_out(mpz_t out, celement x, long valshift, long prec, ## Extra functions ## cdef cmatrix_mod_pn(celement a, long aprec, long valshift, PowComputer_ prime_pow): - """ + r""" Returns the matrix of right multiplication by the element on the power basis `1, x, x^2, \ldots, x^{d-1}` for this extension field. Thus the *rows* of this matrix give the diff --git a/src/sage/libs/linkages/padics/mpz.pxi b/src/sage/libs/linkages/padics/mpz.pxi index 2844a3934f5..3a555e441dc 100644 --- a/src/sage/libs/linkages/padics/mpz.pxi +++ b/src/sage/libs/linkages/padics/mpz.pxi @@ -568,7 +568,7 @@ cdef list ccoefficients(mpz_t x, long valshift, long prec, PowComputer_ prime_po return [ansq] cdef int cteichmuller(mpz_t out, mpz_t value, long prec, PowComputer_ prime_pow) except -1: - """ + r""" Teichmuller lifting. INPUT: diff --git a/src/sage/libs/linkages/padics/unram_shared.pxi b/src/sage/libs/linkages/padics/unram_shared.pxi index 708cf7ac736..b23168e0eb2 100644 --- a/src/sage/libs/linkages/padics/unram_shared.pxi +++ b/src/sage/libs/linkages/padics/unram_shared.pxi @@ -3,7 +3,7 @@ cimport cython @cython.binding(True) def frobenius_unram(self, arithmetic=True): """ - Returns the image of this element under the Frobenius automorphism + Return the image of this element under the Frobenius automorphism applied to its parent. INPUT: @@ -48,9 +48,9 @@ def frobenius_unram(self, arithmetic=True): ... NotImplementedError: Frobenius automorphism only implemented for unramified extensions - TESTS:: + TESTS: - We check that :trac:`23575` is resolved: + We check that :trac:`23575` is resolved:: sage: x = R.random_element() sage: x.frobenius(arithmetic=false).frobenius() == x @@ -84,7 +84,7 @@ def frobenius_unram(self, arithmetic=True): @cython.binding(True) def norm_unram(self, base = None): - """ + r""" Return the absolute or relative norm of this element. .. WARNING:: @@ -95,9 +95,9 @@ def norm_unram(self, base = None): INPUT: - ``base`` -- a subfield of the parent `L` of this element. - The norm is the relative norm from ``L`` to ``base``. - Defaults to the absolute norm down to `\QQ_p` or `\ZZ_p`. + - ``base`` -- a subfield of the parent `L` of this element. + The norm is the relative norm from ``L`` to ``base``. + Defaults to the absolute norm down to `\QQ_p` or `\ZZ_p`. EXAMPLES:: @@ -171,7 +171,7 @@ def norm_unram(self, base = None): @cython.binding(True) def trace_unram(self, base = None): - """ + r""" Return the absolute or relative trace of this element. If ``base`` is given then ``base`` must be a subfield of the diff --git a/src/sage/libs/symmetrica/sc.pxi b/src/sage/libs/symmetrica/sc.pxi index 6082527561e..4d9fa4f009d 100644 --- a/src/sage/libs/symmetrica/sc.pxi +++ b/src/sage/libs/symmetrica/sc.pxi @@ -4,6 +4,7 @@ cdef extern from 'symmetrica/def.h': INT kranztafel(OP a, OP b, OP res, OP co, OP cl) INT c_ijk_sn(OP i, OP j, OP k, OP res) + def chartafel_symmetrica(n): """ you enter the degree of the symmetric group, as INTEGER @@ -22,8 +23,7 @@ def chartafel_symmetrica(n): [ 0 -1 2 0 2] [ 1 0 -1 -1 3] [-1 1 1 -1 1] - """ - + """ cdef OP cn, cres cn = callocobject() @@ -41,7 +41,6 @@ def chartafel_symmetrica(n): return res - def charvalue_symmetrica(irred, cls, table=None): """ you enter a PARTITION object part, labelling the irreducible @@ -67,10 +66,8 @@ def charvalue_symmetrica(irred, cls, table=None): sage: m == symmetrica.chartafel(n) True """ - cdef OP cirred, cclass, ctable, cresult - cirred = callocobject() cclass = callocobject() cresult = callocobject() @@ -81,8 +78,6 @@ def charvalue_symmetrica(irred, cls, table=None): ctable = callocobject() _op_matrix(table, ctable) - - #FIXME: assume that class is a partition _op_partition(cls, cclass) @@ -101,42 +96,38 @@ def charvalue_symmetrica(irred, cls, table=None): return res - def kranztafel_symmetrica(a, b): - """ - you enter the INTEGER objects, say a and b, and res becomes a - MATRIX object, the charactertable of S_b \wr S_a, co becomes a - VECTOR object of classorders and cl becomes a VECTOR object of + r""" + you enter the INTEGER objects, say `a` and `b`, and ``res`` becomes a + MATRIX object, the charactertable of `S_b \wr S_a`, ``co`` becomes a + VECTOR object of classorders and ``cl`` becomes a VECTOR object of the classlabels. EXAMPLES:: - sage: (a,b,c) = symmetrica.kranztafel(2,2) - sage: a - [ 1 -1 1 -1 1] - [ 1 1 1 1 1] - [-1 1 1 -1 1] - [ 0 0 2 0 -2] - [-1 -1 1 1 1] - sage: b - [2, 2, 1, 2, 1] - sage: for m in c: print(m) - [0 0] - [0 1] - [0 0] - [1 0] - [0 2] - [0 0] - [1 1] - [0 0] - [2 0] - [0 0] - + sage: (a,b,c) = symmetrica.kranztafel(2,2) + sage: a + [ 1 -1 1 -1 1] + [ 1 1 1 1 1] + [-1 1 1 -1 1] + [ 0 0 2 0 -2] + [-1 -1 1 1 1] + sage: b + [2, 2, 1, 2, 1] + sage: for m in c: print(m) + [0 0] + [0 1] + [0 0] + [1 0] + [0 2] + [0 0] + [1 1] + [0 0] + [2 0] + [0 0] """ - cdef OP ca, cb, cres, cco, ccl - ca = callocobject() cb = callocobject() cres = callocobject() @@ -194,4 +185,3 @@ def kranztafel_symmetrica(a, b): ## freeall(ck) ## return res - diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py index b2d329e064b..0705d4ecd88 100644 --- a/src/sage/manifolds/chart.py +++ b/src/sage/manifolds/chart.py @@ -3140,7 +3140,7 @@ def _plot_xx_list(xx_list, rem_coords, ranges, steps, number_values): elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) - if nca != 2 and nca !=3: + if nca != 2 and nca != 3: raise ValueError("bad number of ambient coordinates: {}".format(nca)) if ranges is None: ranges = {} diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 72955d48b3c..c0e782798aa 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -355,7 +355,7 @@ def _latex_(self): """ from sage.misc.latex import latex - return r"\mathrm{GL}\left("+ latex(self._vmodule)+ r"\right)" + return r"\mathrm{GL}\left(" + latex(self._vmodule) + r"\right)" def base_module(self): r""" diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index 7ee1517c43d..fd77c39dfc4 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -650,7 +650,7 @@ def tangent_vector_field(self, name=None, latex_name=None): if latex_name is None: if name is None: if self._latex_name is not None: - latex_name = r"{%s'}"%(self._latex_name) + latex_name = r"{%s'}" % (self._latex_name) else: latex_name = name if name is None and self._name is not None: @@ -912,7 +912,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None, if ambient_coords is None: ambient_coords = chart[:] # all chart coordinates are used n_pc = len(ambient_coords) - if n_pc != 2 and n_pc !=3: + if n_pc != 2 and n_pc != 3: raise ValueError("the number of coordinates involved in the " + "plot must be either 2 or 3, not {}".format(n_pc)) # indices of plot coordinates diff --git a/src/sage/manifolds/differentiable/degenerate.py b/src/sage/manifolds/differentiable/degenerate.py index 30846aa6891..82de8c39d74 100644 --- a/src/sage/manifolds/differentiable/degenerate.py +++ b/src/sage/manifolds/differentiable/degenerate.py @@ -479,7 +479,7 @@ def __init__(self, tensor, embedding, screen=None): self.display(frame) for i in self._domain._ambient.index_generator(tensor.tensor_rank()): for j in range(len(i)): - if i[j]==self._domain._ambient._dim-self._domain._sindex-1: + if i[j] == self._domain._ambient._dim-self._domain._sindex-1: self[frame, i] = 0 def __call__(self, *args): @@ -517,7 +517,7 @@ def __call__(self, *args): except ValueError: pass if not self._domain.is_tangent(vector): - raise ValueError("The provided vector field is not "+ + raise ValueError("The provided vector field is not " + "tangent to {}".format(self._domain._name)) try: return TensorField.__call__(self._tensor.along(self._embedding), *args) diff --git a/src/sage/manifolds/differentiable/degenerate_submanifold.py b/src/sage/manifolds/differentiable/degenerate_submanifold.py index 67d5228f2d9..581162b88f5 100644 --- a/src/sage/manifolds/differentiable/degenerate_submanifold.py +++ b/src/sage/manifolds/differentiable/degenerate_submanifold.py @@ -500,7 +500,7 @@ def set_transverse(self, rigging=None, normal=None): raise ValueError("{} is normal to {}".format(u.display(), self._name)) rig.append(u) l2 += 1 - if l1+l2!=self._codim: + if l1+l2 != self._codim: raise ValueError("length of the transverse must be {}".format(self._codim)) self._transverse['normal'] = tuple(nor) self._transverse['rigging'] = tuple(rig) @@ -558,12 +558,12 @@ def screen(self, name, screen, rad, latex_name=None): else: rad = [rad] if name in self._screens: - if list(screen)==self._screens[name]._screen and list(rad)==self._screens[name]._rad: + if list(screen) == self._screens[name]._screen and list(rad) == self._screens[name]._rad: return self._screens[name] else: raise ValueError("a different screen distribution with the " "same name had already been set") - if len(screen)+len(rad)!=self._dim: + if len(screen)+len(rad) != self._dim: raise ValueError("total length screen+rad must be {}".format(self._dim)) frame = self.default_frame() im = self.immersion() @@ -625,7 +625,7 @@ def induced_metric(self) -> DegenerateMetric: submanifold S embedded in 4-dimensional differentiable manifold M """ - if self._induced_metric is None or self._induced_metric._components=={}: + if self._induced_metric is None or self._induced_metric._components == {}: self._induced_metric = self.metric() self._induced_metric.set( self.immersion().pullback(self.ambient_metric())) @@ -741,7 +741,7 @@ def _ambient_decomposition(self, screen=None): rig = self._transverse['rigging'] else: raise ValueError("set first a screen distribution") - if self._codim==1: + if self._codim == 1: xi = rad[0] v = rig[0] g = self.ambient_metric() @@ -833,7 +833,7 @@ def _adapted_frame_(self, screen=None): self.set_change_of_frame(f.along(self.immersion()), e.along( self.immersion()), GLHPhi(A.along(self.immersion()))) b = e.dual_basis() - if self._codim==1: + if self._codim == 1: if not self._adapted_frame: e[self._dim-self._sindex].set_name('N') else: @@ -893,7 +893,7 @@ def adapted_frame(self, screen=None): """ e = self._adapted_frame_(screen).along(self.immersion()) b = e.dual_basis() - if self._codim==1: + if self._codim == 1: if not self._adapted_frame: e[self._dim-self._sindex].set_name('N') else: @@ -959,7 +959,7 @@ def second_fundamental_form(self, screen=None): """ if self._ambient._dim-self._dim != 1: - raise ValueError("'second_fundamental_form' is defined"+ + raise ValueError("'second_fundamental_form' is defined" + " only for hypersurfaces.") if screen is None: screen = self.default_screen() @@ -1018,7 +1018,7 @@ def projection(self, tensor, screen=None): sage: U1 = S.projection(U) # long time """ - if tensor.tensor_type()[0]!=1: + if tensor.tensor_type()[0] != 1: raise NotImplementedError("``projection`` is implemented only for " "tensors with 1 as contravariant order") return TangentTensor(tensor, self.immersion(), screen) @@ -1061,8 +1061,8 @@ def screen_projection(self, tensor, screen=None): sage: U1 = S.screen_projection(U); # long time """ - if tensor.tensor_type()[0]!=1: - raise NotImplementedError("``projection`` is implemented only for "+ + if tensor.tensor_type()[0] != 1: + raise NotImplementedError("``projection`` is implemented only for " + "tensors with 1 as contravariant order") frame = self.adapted_frame(screen) T = tensor.copy() @@ -1299,7 +1299,7 @@ def principal_directions(self, screen=None): """ if self._codim != 1: - raise ValueError("'principal directions' is defined"+ + raise ValueError("'principal directions' is defined" + " only for hypersurfaces.") if screen is None: screen = self.default_screen() @@ -1316,7 +1316,7 @@ def principal_directions(self, screen=None): for eigen_vector in eigen_space[1]: v = self._ambient.vector_field(name="e_{}".format(next(counter)) ).along(self.immersion()) - v[frame, :] = [elt for elt in eigen_vector]+ [0] + v[frame, :] = [elt for elt in eigen_vector] + [0] res.append((TangentTensor(v, self.immersion()), self.scalar_field( {chart: eigen_space[0] for chart in self.top_charts()}))) #res[-1][0].set_name("e_{}".format(next(counter))) @@ -1367,7 +1367,7 @@ def mean_curvature(self, screen=None): """ if self._codim != 1: - raise ValueError("'mean_curvature' is defined"+ + raise ValueError("'mean_curvature' is defined" + " only for hypersurfaces.") if screen is None: screen = self.default_screen() @@ -1650,7 +1650,7 @@ def normal_tangent_vector(self): """ rad = [elt.along(self._domain.immersion()) for elt in self._rad] - if self._domain._codim==1: + if self._domain._codim == 1: xi = rad[0] xi.set_name(name='xi', latex_name=r'\xi') return xi @@ -1695,7 +1695,7 @@ def rigging(self): """ im = self._domain.immersion() rig = [elt.along(im) for elt in self._domain._transverse['rigging']] - if self._domain._codim!=1: + if self._domain._codim != 1: return rig xi = self.normal_tangent_vector() v = rig[0] diff --git a/src/sage/manifolds/differentiable/diff_map.py b/src/sage/manifolds/differentiable/diff_map.py index ded6843afb3..a6f960c76f8 100644 --- a/src/sage/manifolds/differentiable/diff_map.py +++ b/src/sage/manifolds/differentiable/diff_map.py @@ -641,11 +641,11 @@ def differential(self, point: ManifoldPoint) -> FiniteRankFreeModuleMorphism: for i in range(n2)] bases = (chart1.frame().at(point), chart2.frame().at(image_point)) if self._name is not None and point._name is not None: - name = 'd%s_%s'%(self._name, point._name) + name = 'd%s_%s' % (self._name, point._name) else: name = None if self._latex_name is not None and point._latex_name is not None: - latex_name = r'{\mathrm{d}%s}_{%s}'%(self._latex_name, + latex_name = r'{\mathrm{d}%s}_{%s}' % (self._latex_name, point._latex_name) else: latex_name = None diff --git a/src/sage/manifolds/differentiable/integrated_curve.py b/src/sage/manifolds/differentiable/integrated_curve.py index 74f76ab3e33..0d01a9afd70 100644 --- a/src/sage/manifolds/differentiable/integrated_curve.py +++ b/src/sage/manifolds/differentiable/integrated_curve.py @@ -523,7 +523,7 @@ def __init__(self, parent, equations_rhs, velocities, # extract all the variables appearing in the initial tangent # vector components: initial_coord_basis = chart.frame().at(initial_pt) - initial_tgt_vec_comps=initial_tangent_vector[initial_coord_basis,:] + initial_tgt_vec_comps = initial_tangent_vector[initial_coord_basis,:] for comp in initial_tgt_vec_comps: if isinstance(comp, Expression): parameters = parameters.union(comp.variables()) @@ -777,7 +777,7 @@ def system(self, verbose=False): description += "Initial tangent vector: {} ".format(v0) description += "with components " - description +="{}".format(initial_tgt_vec_comps) + description += "{}".format(initial_tgt_vec_comps) description += " with respect to {}\n\n".format(chart) for coord_func,velocity in zip(chart[:],self._velocities): @@ -1397,9 +1397,9 @@ def jacobian(t,y): "to {}) is out ".format(sol[n][0]) + "of the chart domain; a curve with a " + "smaller maximal value of the curve " + - "parameter, or a smaller initial tangent "+ - "vector, might be considered. You can also try "+ - "'solve_across_charts' in order not to be "+ + "parameter, or a smaller initial tangent " + + "vector, might be considered. You can also try " + + "'solve_across_charts' in order not to be " + "confined to a single chart") else: self._solutions[solution_key] = coords_sol @@ -1994,7 +1994,7 @@ def interpolate(self, solution_key=None, method=None, "with the key '{}' ".format(interpolation_key) + "by default.") - if method=='cubic spline': + if method == 'cubic spline': self._interpolations[interpolation_key] = [] dim = self.codomain().dim() if not isinstance(self._solutions[solution_key][0], tuple): @@ -2002,7 +2002,7 @@ def interpolate(self, solution_key=None, method=None, coordinate_curve = [] for point in self._solutions[solution_key]: coordinate_curve += [[point[0], point[i+1]]] - self._interpolations[interpolation_key]+=[Spline(coordinate_curve)] + self._interpolations[interpolation_key] += [Spline(coordinate_curve)] else: # case multi charts j = 0 for chart, sol in self._solutions[solution_key]: @@ -2014,7 +2014,7 @@ def interpolate(self, solution_key=None, method=None, interp_chart += [Spline(coordinate_curve)] self._interpolations[interpolation_key] += [(chart, interp_chart)] self._interpolations[interpolation_key+"_chart_"+str(j)] = interp_chart - j+=1 + j += 1 else: raise ValueError("no available method of interpolation " + "referred to as '{}'".format(method)) @@ -2264,7 +2264,7 @@ def tangent_vector_eval_at(self, t, # contain lists of instances of the Spline class raise TypeError("unexpected type of interpolation object") - interpolated_coordinates=[coordinate_curve_spline(t) + interpolated_coordinates = [coordinate_curve_spline(t) for coordinate_curve_spline in interpolation] M = self.codomain() p = M.point(interpolated_coordinates, chart=self._chart, name=None) @@ -2456,7 +2456,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, if ambient_coords is None: ambient_coords = chart[:] # all chart coordinates are used n_pc = len(ambient_coords) - if n_pc != 2 and n_pc !=3: + if n_pc != 2 and n_pc != 3: raise ValueError("the number of coordinates involved in " + "the plot must be either 2 or 3, " + "not {}".format(n_pc)) @@ -2493,7 +2493,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, "tuple/list of 2 elements") else: p = prange #'p' declared only for the line below to be shorter - if p[0]param_max or p[1]param_max: + if p[0] < param_min or p[0] > param_max or p[1] < param_min or p[1] > param_max: raise ValueError("parameter range should be a " + "subinterval of the curve domain " + "({})".format(self.domain())) @@ -2534,8 +2534,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2552,8 +2552,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2572,7 +2572,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, from sage.plot.plot3d.shapes import arrow3d scale = kwds.pop('scale') - plot_points_tangent=kwds.pop('plot_points_tangent') + plot_points_tangent = kwds.pop('plot_points_tangent') width_tangent = kwds.pop('width_tangent') plot_vectors = Graphics() @@ -2594,8 +2594,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2613,8 +2613,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2679,7 +2679,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, # to be shorter transf[pc] = AUX.expr()[jpc] AUX2 = transf[pc].variables() # idem - required_coords=required_coords.union(AUX2) + required_coords = required_coords.union(AUX2) break else: raise ValueError("no expression has been found for " + @@ -2716,8 +2716,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2734,8 +2734,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2745,11 +2745,11 @@ def plot_integrated(self, chart=None, ambient_coords=None, xp = [fastf[j](*arg) for j in range(len(ambient_coords))] plot_curve.append(xp) - if k==0 and t > tmin: + if k == 0 and t > tmin: # in case an initial offset was earlier added to # 'tmin' in order to avoid errors, it is now needed # to cancel this offset for the next steps - t=tmin + t = tmin t += dt @@ -2787,8 +2787,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2806,8 +2806,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2826,13 +2826,13 @@ def plot_integrated(self, chart=None, ambient_coords=None, AUX = AUX.substitute(required_coords_values) # 'AUX' only used for the lines of code to # be shorter - xp+=[numerical_approx(AUX)] + xp += [numerical_approx(AUX)] pushed_comp = 0 for coord in transf[pc].variables(): D = Dpc_Dcoord[pc][coord] D = D.substitute(required_coords_values) - D=numerical_approx(D) + D = numerical_approx(D) pushed_comp += Dcoord_Dt[coord] * D pushed_vec += [pushed_comp] @@ -2857,7 +2857,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, # in case an initial offset was earlier added to # 'tmin' in order to avoid errors, it is now needed # to cancel this offset for the next steps - t=tmin + t = tmin t += dt return plot_vectors + DifferentiableCurve._graphics(self, @@ -3644,7 +3644,7 @@ def system(self, verbose=False): description += "Initial tangent vector: {} ".format(v0) description += "with components " - description +="{}".format(initial_tgt_vec_comps) + description += "{}".format(initial_tgt_vec_comps) description += " with respect to {}\n\n".format(chart) for coord_func,velocity in zip(chart[:],self._velocities): @@ -4020,7 +4020,7 @@ def system(self, verbose=False): description += "Initial tangent vector: {} ".format(v0) description += "with components " - description +="{}".format(initial_tgt_vec_comps) + description += "{}".format(initial_tgt_vec_comps) description += " with respect to {}\n\n".format(chart) for coord_func,velocity in zip(chart[:],self._velocities): diff --git a/src/sage/manifolds/differentiable/levi_civita_connection.py b/src/sage/manifolds/differentiable/levi_civita_connection.py index 7ff2643e32b..00ebf69b47f 100644 --- a/src/sage/manifolds/differentiable/levi_civita_connection.py +++ b/src/sage/manifolds/differentiable/levi_civita_connection.py @@ -520,7 +520,7 @@ def make_Connect(local_list_ijk,chart,ginv,gg,manif): for i,j,k in local_list_ijk: rsum = 0 for s in manif.irange(): - if ginv[i,s, chart]!=0: + if ginv[i,s, chart] != 0: rsum += ginv[i,s, chart] * ( gg[s,k, chart].diff(j) + gg[j,s, chart].diff(k) diff --git a/src/sage/manifolds/differentiable/manifold.py b/src/sage/manifolds/differentiable/manifold.py index 904e291ab8e..3a7820e01ec 100644 --- a/src/sage/manifolds/differentiable/manifold.py +++ b/src/sage/manifolds/differentiable/manifold.py @@ -1904,7 +1904,7 @@ def tensor_field(self, *args, **kwargs): vmodule = self.vector_field_module(dest_map) resu = vmodule.tensor((k, l), name=name, latex_name=latex_name, sym=sym, antisym=antisym) - if len(args)>2: + if len(args) > 2: # Some components are to be initialized resu._init_components(args[2], **kwargs) return resu @@ -2173,7 +2173,7 @@ def multivector_field(self, *args, **kwargs): vmodule = self.vector_field_module(dest_map) resu = vmodule.alternating_contravariant_tensor(degree, name=name, latex_name=latex_name) - if len(args)>1: + if len(args) > 1: # Some components are to be initialized resu._init_components(args[1], **kwargs) return resu @@ -2277,7 +2277,7 @@ def diff_form(self, *args, **kwargs) -> DiffForm: vmodule = self.vector_field_module(dest_map) resu = vmodule.alternating_form(degree, name=name, latex_name=latex_name) - if len(args)>1: + if len(args) > 1: # Some components are to be initialized resu._init_components(args[1], **kwargs) return resu @@ -4187,7 +4187,7 @@ class :class:`~sage.manifolds.differentiable.diff_map.DiffMap` """ vmodule = self.vector_field_module(dest_map) dim = vmodule.ambient_domain().dimension() - if signature=='positive': + if signature == 'positive': signat = dim - 2 else: signat = 2 - dim diff --git a/src/sage/manifolds/differentiable/manifold_homset.py b/src/sage/manifolds/differentiable/manifold_homset.py index 2d35505f63c..20660a01652 100644 --- a/src/sage/manifolds/differentiable/manifold_homset.py +++ b/src/sage/manifolds/differentiable/manifold_homset.py @@ -931,7 +931,7 @@ def _an_element_(self): v = codom.tangent_space(p)(v_comps) # The equations defining the curve: - eqns_rhs=[-(x0_B-x0_A)/2*sin(param-t_min)]+[0 for i in range(dim-1)] + eqns_rhs = [-(x0_B-x0_A)/2*sin(param-t_min)]+[0 for i in range(dim-1)] # combined with the initial components above, all velocities # vanish, except the first one, which is a cosine function. # This differential system results in a curve constant in all @@ -1188,8 +1188,8 @@ def __init__(self, domain, codomain, name=None, latex_name=None): else: self._name = name if latex_name is None: - self._latex_name=r"\mathrm{{Hom}_{autoparallel}}" - self._latex_name+= r"\left({},{}\right)".format( + self._latex_name = r"\mathrm{{Hom}_{autoparallel}}" + self._latex_name += r"\left({},{}\right)".format( domain._latex_name, codomain._latex_name) else: self._latex_name = latex_name @@ -1644,7 +1644,7 @@ def __init__(self, domain, codomain, name=None, latex_name=None): self._name = name if latex_name is None: self._latex_name = r"\mathrm{{Hom}_{geodesic}}" - self._latex_name+= r"\left({},{}\right)".format( + self._latex_name += r"\left({},{}\right)".format( domain._latex_name, codomain._latex_name) else: self._latex_name = latex_name diff --git a/src/sage/manifolds/differentiable/metric.py b/src/sage/manifolds/differentiable/metric.py index 8211ad1a625..74fdd076e45 100644 --- a/src/sage/manifolds/differentiable/metric.py +++ b/src/sage/manifolds/differentiable/metric.py @@ -384,15 +384,15 @@ def __init__(self, vector_field_module, name, signature=None, raise TypeError("the metric signature must be an integer") if (signature < - ndim) or (signature > ndim): raise ValueError("metric signature out of range") - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") self._signature = signature # the pair (n_+, n_-): self._signature_pm = ((ndim+signature)//2, (ndim-signature)//2) - self._indic_signat = 1 - 2*(self._signature_pm[1]%2) # (-1)^n_- + self._indic_signat = 1 - 2*(self._signature_pm[1] % 2) # (-1)^n_- # Initialization of derived quantities: PseudoRiemannianMetric._init_derived(self) @@ -1229,8 +1229,8 @@ def weyl(self, name=None, latex_name=None): rscal = self.ricci_scalar() # First index of the Ricci tensor raised with the metric ricup = ric.up(self, 0) - aux = self*ricup + ric*delta - rscal/(n-1)* self*delta - self._weyl = riem + 2/(n-2)* aux.antisymmetrize(2,3) + aux = self*ricup + ric*delta - rscal/(n-1) * self*delta + self._weyl = riem + 2/(n-2) * aux.antisymmetrize(2,3) if name is None: name = "C(" + self._name + ")" if latex_name is None: @@ -2134,15 +2134,15 @@ def __init__(self, vector_field_module, name, signature=None, raise TypeError("the metric signature must be an integer") if (signature < - ndim) or (signature > ndim): raise ValueError("metric signature out of range") - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") self._signature = signature # the pair (n_+, n_-): self._signature_pm = ((ndim+signature)//2, (ndim-signature)//2) - self._indic_signat = 1 - 2*(self._signature_pm[1]%2) # (-1)^n_- + self._indic_signat = 1 - 2*(self._signature_pm[1] % 2) # (-1)^n_- # Initialization of derived quantities: PseudoRiemannianMetricParal._init_derived(self) @@ -2654,12 +2654,12 @@ def __init__(self, vector_field_module, name, signature=None, else: try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) if elt > ndim: raise ValueError("{} must be less than {}".format(elt,ndim)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: + if sign != ndim: raise ValueError("{} is different from {}".format(sign, ndim)) except TypeError: raise TypeError("signature must be an iterable") @@ -2971,10 +2971,10 @@ def __init__(self, vector_field_module, name, signature=None, else: try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: + if sign != ndim: raise ValueError("{} is different from {}".format(sign, ndim)) except TypeError: raise TypeError("signature must be an iterable") diff --git a/src/sage/manifolds/differentiable/tangent_space.py b/src/sage/manifolds/differentiable/tangent_space.py index 4b90e711a79..98a60cede2a 100644 --- a/src/sage/manifolds/differentiable/tangent_space.py +++ b/src/sage/manifolds/differentiable/tangent_space.py @@ -246,7 +246,7 @@ def __init__(self, point: ManifoldPoint, base_ring=None): """ manif = point._manifold name = "T_{} {}".format(point._name, manif._name) - latex_name = r"T_{%s}\,%s"%(point._latex_name, manif._latex_name) + latex_name = r"T_{%s}\,%s" % (point._latex_name, manif._latex_name) self._point = point self._manif = manif if base_ring is None: diff --git a/src/sage/manifolds/differentiable/tensorfield.py b/src/sage/manifolds/differentiable/tensorfield.py index 861b05c1d1b..9e302688024 100644 --- a/src/sage/manifolds/differentiable/tensorfield.py +++ b/src/sage/manifolds/differentiable/tensorfield.py @@ -4041,7 +4041,7 @@ def down( return result if not isinstance(pos, (int, Integer)): raise TypeError("the argument 'pos' must be an integer") - if pos<0 or pos>=n_con: + if pos < 0 or pos >= n_con: print("pos = {}".format(pos)) raise ValueError("position out of range") return non_degenerate_form.contract(0, self, pos) diff --git a/src/sage/manifolds/differentiable/vectorfield.py b/src/sage/manifolds/differentiable/vectorfield.py index 01a9c52d93c..22b5df5717f 100644 --- a/src/sage/manifolds/differentiable/vectorfield.py +++ b/src/sage/manifolds/differentiable/vectorfield.py @@ -715,7 +715,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) - if nca != 2 and nca !=3: + if nca != 2 and nca != 3: raise ValueError("the number of ambient coordinates must be " + "either 2 or 3, not {}".format(nca)) if ranges is None: @@ -757,11 +757,11 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, steps = {} for coord in coords: if coord not in steps: - steps[coord] = (ranges[coord][1] - ranges[coord][0])/ \ + steps[coord] = (ranges[coord][1] - ranges[coord][0]) / \ (number_values[coord]-1) else: number_values[coord] = 1 + int( - (ranges[coord][1] - ranges[coord][0])/ steps[coord]) + (ranges[coord][1] - ranges[coord][0]) / steps[coord]) # # 2/ Plots # ----- diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index d954b5d4839..11b94366a40 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -1188,15 +1188,15 @@ def metric(self, name: str, signature: Optional[int] = None, latex_name: Optiona ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) if elt > ndim: raise ValueError("{} must be less than {}".format(elt,ndim)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: - raise ValueError("{} is different from the dimension".format(sign)+ + if sign != ndim: + raise ValueError("{} is different from the dimension".format(sign) + " of the manifold, who is {}".format(ndim)) - if signature[2]!=0: + if signature[2] != 0: from sage.manifolds.differentiable.metric import DegenerateMetric return DegenerateMetric(self, name, signature=signature, latex_name=latex_name) @@ -1205,8 +1205,8 @@ def metric(self, name: str, signature: Optional[int] = None, latex_name: Optiona if signature is None: signature = (ndim,0) if isinstance(signature, (Integer, int)): - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") @@ -2395,13 +2395,13 @@ def metric(self, name, signature=None, latex_name=None): ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: - raise ValueError("{} is different from the dimension".format(sign)+ + if sign != ndim: + raise ValueError("{} is different from the dimension".format(sign) + " of the manifold, who is {}".format(ndim)) - if signature[2]!=0: + if signature[2] != 0: from sage.manifolds.differentiable.metric import DegenerateMetricParal return DegenerateMetricParal(self, name, signature=signature, latex_name=latex_name) @@ -2410,8 +2410,8 @@ def metric(self, name, signature=None, latex_name=None): if signature is None: signature = (ndim,0) if isinstance(signature, (Integer, int)): - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") diff --git a/src/sage/manifolds/utilities.py b/src/sage/manifolds/utilities.py index c66d54e774e..4b7c21532aa 100644 --- a/src/sage/manifolds/utilities.py +++ b/src/sage/manifolds/utilities.py @@ -323,9 +323,9 @@ def composition(self, ex, operator): if x.has(abs_symbolic(sin(w0))) or x.has(abs_symbolic(cos(w0))): x = self(x) # treatment of nested abs(sin_or_cos(...)) # Simplifications for values of x in the range [-pi, 2*pi]: - if x>=0 and x<=pi: + if x >= 0 and x <= pi: ex = sin(x) - elif (x>pi and x<=2*pi) or (x>=-pi and x<0): + elif (x > pi and x <= 2*pi) or (x >= -pi and x < 0): ex = -sin(x) return ex if argum.operator() is cos: @@ -335,9 +335,9 @@ def composition(self, ex, operator): if x.has(abs_symbolic(sin(w0))) or x.has(abs_symbolic(cos(w0))): x = self(x) # treatment of nested abs(sin_or_cos(...)) # Simplifications for values of x in the range [-pi, 2*pi]: - if (x>=-pi/2 and x<=pi/2) or (x>=3*pi/2 and x<=2*pi): + if (x >= -pi/2 and x <= pi/2) or (x >= 3*pi/2 and x <= 2*pi): ex = cos(x) - elif (x>pi/2 and x<=3*pi/2) or (x>=-pi and x<-pi/2): + elif (x > pi/2 and x <= 3*pi/2) or (x >= -pi and x < -pi/2): ex = -cos(x) return ex # If no pattern is found, we default to ExpressionTreeWalker: @@ -983,7 +983,7 @@ def _repr_(self): # dictionary to group multiple occurrences of differentiation: d/dxdx -> d/dx^2 etc. occ = dict((i, strv[i] + "^" + str(diffargs.count(i)) - if (diffargs.count(i)>1) else strv[i]) + if (diffargs.count(i) > 1) else strv[i]) for i in diffargs) res = "d" + str(numargs) + "(" + str(funcname) + ")/d" + "d".join( diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index d781fc822b0..9f3ff8e6942 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -393,7 +393,7 @@ cdef class Matrix(sage.structure.element.Matrix): """ This function gets called when you're about to change this matrix. - If self is immutable, a ValueError is raised, since you should + If self is immutable, a :class:`ValueError` is raised, since you should never change a mutable matrix. If self is mutable, the cache of results about self is deleted. @@ -406,10 +406,10 @@ cdef class Matrix(sage.structure.element.Matrix): cdef check_bounds_and_mutability(self, Py_ssize_t i, Py_ssize_t j): """ This function gets called when you're about to set the i,j entry of - this matrix. If i or j is out of range, an IndexError exception is - raised. + this matrix. If i or j is out of range, an :class:`IndexError` + exception is raised. - If self is immutable, a ValueError is raised, since you should + If self is immutable, a :class:`ValueError` is raised, since you should never change a mutable matrix. If self is mutable, the cache of results about self is deleted. diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 8c276f2ca29..30d76200bb6 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -1706,14 +1706,14 @@ cdef class Matrix_integer_dense(Matrix_dense): def symplectic_form(self): r""" - Find a symplectic basis for self if self is an anti-symmetric, + Find a symplectic basis for ``self`` if ``self`` is an anti-symmetric, alternating matrix. Return a pair (F, C) such that the rows of C form a symplectic - basis for self and ``F = C * self * C.transpose()``. + basis for ``self`` and ``F = C * self * C.transpose()``. - Raise a ValueError if self is not anti-symmetric, or self is not - alternating. + Raise a :class:`ValueError` if ``self`` is not anti-symmetric, + or ``self`` is not alternating. Anti-symmetric means that `M = -M^t`. Alternating means that the diagonal of `M` is identically zero. @@ -1722,7 +1722,7 @@ cdef class Matrix_integer_dense(Matrix_dense): `e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k` such that - - `z_i M v^t` = 0 for all vectors `v` + - `z_i M v^t = 0` for all vectors `v` - `e_i M {e_j}^t = 0` for all `i, j` diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index 69569297923..753a79090e7 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -1,4 +1,4 @@ -""" +r""" Dense matrices over `\ZZ/n\ZZ` for `n` small using the LinBox library (FFLAS/FFPACK) FFLAS/FFPACK are libraries to provide BLAS/LAPACK-style routines for @@ -857,7 +857,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cpdef _add_(self, right): - """ + r""" Add two dense matrices over `\Z/n\Z` INPUT: @@ -2284,7 +2284,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): return Matrix_dense.determinant(self) cdef xgcd_eliminate(self, celement * row1, celement* row2, Py_ssize_t start_col): - """ + r""" Reduces ``row1`` and ``row2`` by a unimodular transformation using the xgcd relation between their first coefficients ``a`` and ``b``. @@ -2298,7 +2298,6 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ``row2``. It is assumed that all entries before ``start_col`` in ``row1`` and ``row2`` are zero. - OUTPUT: - g: the gcd of the first elements of row1 and diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 347b2e896d8..0967a268f6a 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -158,24 +158,31 @@ def cython(filename, verbose=0, compile_message=False, first moving to a tempdir to avoid clutter. Before :trac:`22113`, the create_local_c_file argument was not tested for C++ code:: - sage: d = sage.misc.temporary_file.tmp_dir() - sage: os.chdir(d) - sage: with open("test.pyx", 'w') as f: - ....: _ = f.write("# distutils: language = c++\n" - ....: "from libcpp.vector cimport vector\n" - ....: "cdef vector[int] * v = new vector[int](4)\n") - sage: output = sage.misc.cython.cython("test.pyx", create_local_c_file=True) + sage: orig_cwd = os.getcwd() + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: os.chdir(d) + ....: with open("test.pyx", 'w') as f: + ....: _ = f.write("# distutils: language = c++\n" + ....: "from libcpp.vector cimport vector\n" + ....: "cdef vector[int] * v = new vector[int](4)\n") + ....: output = sage.misc.cython.cython("test.pyx", + ....: create_local_c_file=True) + ....: os.chdir(orig_cwd) Accessing a ``.pxd`` file from the current directory works:: - sage: d = sage.misc.temporary_file.tmp_dir() - sage: os.chdir(d) - sage: with open("helper.pxd", 'w') as f: - ....: _ = f.write("cdef inline int the_answer(): return 42") - sage: cython(''' - ....: from helper cimport the_answer - ....: print(the_answer()) - ....: ''') + sage: orig_cwd = os.getcwd() + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: os.chdir(d) + ....: with open("helper.pxd", 'w') as f: + ....: _ = f.write("cdef inline int the_answer(): return 42") + ....: cython( + ....: "from helper cimport the_answer\n" + ....: "print(the_answer())" + ....: ) + ....: os.chdir(orig_cwd) 42 Warning and error messages generated by Cython are properly diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index 54ef9cc41c5..818e7cf1a85 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -525,15 +525,17 @@ def label(self) -> str: def newform(self, names=None): """ Return the newform `f` such that this abelian variety is isogenous to - the newform abelian variety `A_f`. If this abelian variety is not - simple, raise a ``ValueError``. + the newform abelian variety `A_f`. + + If this abelian variety is not + simple, this raises a :class:`ValueError`. INPUT: - - ``names`` -- (default: None) If the newform has coefficients in a - number field, then a generator name must be specified. + - ``names`` -- (default: ``None``) If the newform has coefficients + in a number field, then a generator name must be specified. - OUTPUT: A newform `f` so that self is isogenous to `A_f`. + OUTPUT: A newform `f` so that ``self`` is isogenous to `A_f`. EXAMPLES:: @@ -580,9 +582,11 @@ def newform_decomposition(self, names=None): def newform_label(self): """ Return the label [level][isogeny class][group] of the newform - `f` such that this abelian variety is isogenous to the - newform abelian variety `A_f`. If this abelian variety is - not simple, raise a ValueError. + `f` such that this abelian variety is isogenous to the newform + abelian variety `A_f`. + + If this abelian variety is not simple, this raises + a :class:`ValueError`. OUTPUT: string @@ -687,8 +691,10 @@ def elliptic_curve(self): def _isogeny_to_newform_abelian_variety(self): r""" Return an isogeny from self to an abelian variety `A_f` - attached to a newform. If self is not simple (so that no such - isogeny exists), raise a ValueError. + attached to a newform. + + If self is not simple (so that no such + isogeny exists), this raises a :class:`ValueError`. EXAMPLES:: @@ -733,13 +739,12 @@ def _simple_isogeny(self, other): """ Given self and other, if both are simple, and correspond to the same newform with the same congruence subgroup, return an isogeny. - Otherwise, raise a ValueError. - - INPUT: + Otherwise, this raises a :class:`ValueError`. - - ``self, other`` - modular abelian varieties + INPUT: + - ``self, other`` -- modular abelian varieties OUTPUT: an isogeny @@ -3183,7 +3188,7 @@ def degen_t(self, none_if_not_known=False): `(t,N)`, where `N` is the ambient level and `t` is an integer that divides the quotient of `N` by the newform level. This function returns the tuple - `(t,N)`, or raises a ValueError if self isn't simple. + `(t,N)`, or raises a :class:`ValueError` if self is not simple. .. note:: @@ -3234,24 +3239,25 @@ def degen_t(self, none_if_not_known=False): def isogeny_number(self, none_if_not_known=False): """ Return the number (starting at 0) of the isogeny class of new - simple abelian varieties that self is in. If self is not simple, - raises a ValueError exception. - - INPUT: + simple abelian varieties that ``self`` is in. + If ``self`` is not simple, + this raises a :class:`ValueError` exception. - - ``none_if_not_known`` - bool (default: False); if - True then this function may return None instead of True of False if - we don't already know the isogeny number of self. + INPUT: + - ``none_if_not_known`` -- bool (default: ``False``); if + ``True`` then this function may return ``None`` instead of ``True`` + or ``False`` if + we do not already know the isogeny number of ``self``. - EXAMPLES: We test the none_if_not_known flag first:: + EXAMPLES: We test the ``none_if_not_known`` flag first:: sage: J0(33).isogeny_number(none_if_not_known=True) is None True Of course, `J_0(33)` is not simple, so this function - raises a ValueError:: + raises a :class:`ValueError`:: sage: J0(33).isogeny_number() Traceback (most recent call last): diff --git a/src/sage/modular/abvar/constructor.py b/src/sage/modular/abvar/constructor.py index 7a99398a237..5dd6a77b4ca 100644 --- a/src/sage/modular/abvar/constructor.py +++ b/src/sage/modular/abvar/constructor.py @@ -95,7 +95,7 @@ def J0(N): sage: J0(33) is J0(33) True """ - key = 'J0(%s)'%N + key = 'J0(%s)' % N try: return _get(key) except ValueError: @@ -113,7 +113,7 @@ def J1(N): sage: J1(389) Abelian variety J1(389) of dimension 6112 """ - key = 'J1(%s)'%N + key = 'J1(%s)' % N try: return _get(key) except ValueError: @@ -130,7 +130,7 @@ def JH(N, H): sage: JH(389,[16]) Abelian variety JH(389,[16]) of dimension 64 """ - key = 'JH(%s,%s)'%(N,H) + key = 'JH(%s,%s)' % (N,H) try: return _get(key) except ValueError: diff --git a/src/sage/modular/abvar/cuspidal_subgroup.py b/src/sage/modular/abvar/cuspidal_subgroup.py index fe174e6631a..82e373ad716 100644 --- a/src/sage/modular/abvar/cuspidal_subgroup.py +++ b/src/sage/modular/abvar/cuspidal_subgroup.py @@ -209,7 +209,7 @@ def _repr_(self): sage: G._repr_() 'Finite subgroup with invariants [3, 3] over QQ of Abelian variety J0(27) of dimension 1' """ - return "Cuspidal subgroup %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety()) + return "Cuspidal subgroup %sover QQ of %s" % (self._invariants_repr(), self.abelian_variety()) def lattice(self): """ @@ -313,7 +313,7 @@ def _repr_(self): sage: G._repr_() 'Finite subgroup with invariants [3] over QQ of Abelian variety J0(27) of dimension 1' """ - return "Rational cuspidal subgroup %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety()) + return "Rational cuspidal subgroup %sover QQ of %s" % (self._invariants_repr(), self.abelian_variety()) def lattice(self): """ diff --git a/src/sage/modular/abvar/finite_subgroup.py b/src/sage/modular/abvar/finite_subgroup.py index ec76a0f5e26..74f7dd6389b 100644 --- a/src/sage/modular/abvar/finite_subgroup.py +++ b/src/sage/modular/abvar/finite_subgroup.py @@ -529,7 +529,7 @@ def _repr_(self): field = "QQ" else: field = str(K) - return "Finite subgroup %sover %s of %s"%(self._invariants_repr(), field, self.__abvar) + return "Finite subgroup %sover %s of %s" % (self._invariants_repr(), field, self.__abvar) def _invariants_repr(self): """ @@ -544,7 +544,7 @@ def _invariants_repr(self): sage: J0(42).cuspidal_subgroup()._invariants_repr() 'with invariants [2, 2, 12, 48] ' """ - return 'with invariants %s '%(self.invariants(), ) + return 'with invariants %s ' % (self.invariants(), ) def order(self): """ diff --git a/src/sage/modular/abvar/homspace.py b/src/sage/modular/abvar/homspace.py index 8e89399d611..06ec268e2ec 100644 --- a/src/sage/modular/abvar/homspace.py +++ b/src/sage/modular/abvar/homspace.py @@ -397,7 +397,7 @@ def _repr_(self): sage: End(J)._repr_() 'Endomorphism ring of Abelian variety J0(11) of dimension 1' """ - return "Space of homomorphisms from %s to %s"%\ + return "Space of homomorphisms from %s to %s" %\ (self.domain(), self.codomain()) def _get_matrix(self, g): @@ -501,7 +501,7 @@ def gen(self, i=0): """ self.calculate_generators() if i > self.ngens(): - raise ValueError("self only has %s generators"%self.ngens()) + raise ValueError("self only has %s generators" % self.ngens()) return self.element_class(self, self._gens[i]) def ngens(self): diff --git a/src/sage/modular/abvar/lseries.py b/src/sage/modular/abvar/lseries.py index 48c3377a4c5..84823684f03 100644 --- a/src/sage/modular/abvar/lseries.py +++ b/src/sage/modular/abvar/lseries.py @@ -322,7 +322,7 @@ def __init__(self, abvar, p): Lseries.__init__(self, abvar) p = Integer(p) if not p.is_prime(): - raise ValueError("p (=%s) must be prime"%p) + raise ValueError("p (=%s) must be prime" % p) self.__p = p def __eq__(self, other): diff --git a/src/sage/modular/abvar/torsion_subgroup.py b/src/sage/modular/abvar/torsion_subgroup.py index b2a5c35f8b9..14a52ba0284 100644 --- a/src/sage/modular/abvar/torsion_subgroup.py +++ b/src/sage/modular/abvar/torsion_subgroup.py @@ -219,7 +219,7 @@ def order(self, proof=True): n = O[0] self._order = n return n - raise RuntimeError("Unable to compute order of torsion subgroup (it is in %s)"%O) + raise RuntimeError("Unable to compute order of torsion subgroup (it is in %s)" % O) def lattice(self): """ @@ -697,7 +697,7 @@ def _repr_(self): sage: J0(23).qbar_torsion_subgroup()._repr_() 'Group of all torsion points in QQbar on Abelian variety J0(23) of dimension 2' """ - return 'Group of all torsion points in QQbar on %s'%self.__abvar + return 'Group of all torsion points in QQbar on %s' % self.__abvar def field_of_definition(self): """ diff --git a/src/sage/modular/arithgroup/arithgroup_generic.py b/src/sage/modular/arithgroup/arithgroup_generic.py index 844d8db7165..093541b9b06 100644 --- a/src/sage/modular/arithgroup/arithgroup_generic.py +++ b/src/sage/modular/arithgroup/arithgroup_generic.py @@ -1020,7 +1020,7 @@ def generators(self, algorithm="farey"): [0 1], [ 0 -1], [-2 1], [ 0 -1], [-2 3], [ 2 -1], [2 1] ] """ - if algorithm=="farey": + if algorithm == "farey": return self.farey_symbol().generators() elif algorithm == "todd-coxeter": return self.todd_coxeter()[1] @@ -1252,7 +1252,7 @@ def dimension_eis(self, k=2): if k > 1: return self.nregcusps() else: # k = 1 - return ZZ(self.nregcusps()/ ZZ(2)) + return ZZ(self.nregcusps() / ZZ(2)) def as_permutation_group(self): r""" @@ -1279,7 +1279,7 @@ def as_permutation_group(self): sage: P.an_element() in G True """ - _,_,l_edges,s2_edges=self.todd_coxeter() + _,_,l_edges,s2_edges = self.todd_coxeter() n = len(l_edges) s3_edges = [None] * n r_edges = [None] * n @@ -1289,10 +1289,10 @@ def as_permutation_group(self): r_edges[ii] = s2_edges[i] if self.is_even(): from sage.modular.arithgroup.arithgroup_perm import EvenArithmeticSubgroup_Permutation - g=EvenArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) + g = EvenArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) else: from sage.modular.arithgroup.arithgroup_perm import OddArithmeticSubgroup_Permutation - g=OddArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) + g = OddArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) g.relabel() return g diff --git a/src/sage/modular/arithgroup/arithgroup_perm.py b/src/sage/modular/arithgroup/arithgroup_perm.py index c8536611724..9f7371c1702 100644 --- a/src/sage/modular/arithgroup/arithgroup_perm.py +++ b/src/sage/modular/arithgroup/arithgroup_perm.py @@ -150,49 +150,49 @@ def sl2z_word_problem(A): output = [] # If A00 is zero - if A[0,0]==0: - c=A[1,1] + if A[0,0] == 0: + c = A[1,1] if c != 1: - A=A*Lm**(c-1)*Rm*Lmi + A = A*Lm**(c-1)*Rm*Lmi output.extend([(0,1-c),(1,-1),(0,1)]) else: - A=A*Rm*Lmi + A = A*Rm*Lmi output.extend([(1,-1),(0,1)]) - if A[0,0]<0: # Make sure A00 is positive - A=SL2Z(-1)*A + if A[0,0] < 0: # Make sure A00 is positive + A = SL2Z(-1)*A output.extend([(1,-1), (0,1), (1,-1), (0,1), (1,-1), (0,1)]) - if A[0,1]<0: # if A01 is negative make it positive - n=(-A[0,1]/A[0,0]).ceil() #n s.t. 0 <= A[0,1]+n*A[0,0] < A[0,0] - A=A*Lm**n + if A[0,1] < 0: # if A01 is negative make it positive + n = (-A[0,1]/A[0,0]).ceil() #n s.t. 0 <= A[0,1]+n*A[0,0] < A[0,0] + A = A*Lm**n output.append((0, -n)) # At this point A00>0 and A01>=0 - while not (A[0,0]==0 or A[0,1]==0): - if A[0,0]>A[0,1]: - n=(A[0,0]/A[0,1]).floor() - A=A*SL2Z([1,0,-n,1]) + while not (A[0,0] == 0 or A[0,1] == 0): + if A[0,0] > A[0,1]: + n = (A[0,0]/A[0,1]).floor() + A = A*SL2Z([1,0,-n,1]) output.append((1, n)) else: # A[0,0]<=A[0,1] - n=(A[0,1]/A[0,0]).floor() - A=A*SL2Z([1,-n,0,1]) + n = (A[0,1]/A[0,0]).floor() + A = A*SL2Z([1,-n,0,1]) output.append((0, n)) - if A==SL2Z(1): + if A == SL2Z(1): pass # done, so don't add R^0 - elif A[0,0]==0: - c=A[1,1] + elif A[0,0] == 0: + c = A[1,1] if c != 1: - A=A*Lm**(c-1)*Rm*Lmi + A = A*Lm**(c-1)*Rm*Lmi output.extend([(0,1-c),(1,-1),(0, 1)]) else: - A=A*Rm*Lmi + A = A*Rm*Lmi output.extend([(1,-1),(0,1)]) else: - c=A[1,0] + c = A[1,0] if c: - A=A*Rm**(-c) + A = A*Rm**(-c) output.append((1,c)) output.reverse() @@ -255,7 +255,7 @@ def word_of_perms(w, p1, p2): m = [p1.order(),p2.order()] for i,j in w: - M *= p[i]**(j%m[i]) + M *= p[i]**(j % m[i]) return M @@ -586,11 +586,11 @@ def _repr_(self): 'Arithmetic subgroup of index 24' """ if self.index() < 20: - return "Arithmetic subgroup with permutations of right cosets\n S2=%s\n S3=%s\n L=%s\n R=%s" %( + return "Arithmetic subgroup with permutations of right cosets\n S2=%s\n S3=%s\n L=%s\n R=%s" % ( self.S2(), self.S3(), self.L(), self.R()) else: - return "Arithmetic subgroup of index %d" %self.index() + return "Arithmetic subgroup of index %d" % self.index() # # Attribute access @@ -1002,13 +1002,13 @@ def _index_to_lr_cusp_width(self): l_cycle_length = [None]*self.index() for c in l.cycle_tuples(singletons=True): for i in c: - l_cycle_length[i-1]=len(c) + l_cycle_length[i-1] = len(c) r = G.R() r_cycle_length = [None]*self.index() for c in r.cycle_tuples(singletons=True): for i in c: - r_cycle_length[i-1]=len(c) + r_cycle_length[i-1] = len(c) return (l_cycle_length, r_cycle_length) @@ -1484,7 +1484,7 @@ def is_congruence(self): s = l**20 * r**onefifth * l**(-4) * ~r #Congruence if the seven permutations below are trivial: - rel =~a*~r*a*r + rel = ~a*~r*a*r if not rel.is_one(): verbose("Failed relation B1") return False diff --git a/src/sage/modular/arithgroup/congroup_gamma.py b/src/sage/modular/arithgroup/congroup_gamma.py index bba5868dab6..a9eeb2a5769 100644 --- a/src/sage/modular/arithgroup/congroup_gamma.py +++ b/src/sage/modular/arithgroup/congroup_gamma.py @@ -73,7 +73,7 @@ def _repr_(self): sage: Gamma(133)._repr_() 'Congruence Subgroup Gamma(133)' """ - return "Congruence Subgroup Gamma(%s)"%self.level() + return "Congruence Subgroup Gamma(%s)" % self.level() def _latex_(self): r""" @@ -86,7 +86,7 @@ def _latex_(self): sage: latex(Gamma(20)) \Gamma(20) """ - return "\\Gamma(%s)"%self.level() + return "\\Gamma(%s)" % self.level() def __reduce__(self): """ @@ -154,7 +154,7 @@ def _contains_sl2(self, a,b,c,d): """ N = self.level() # don't need to check d == 1 as this is automatic from det - return ((a%N == 1) and (b%N == 0) and (c%N == 0)) + return ((a % N == 1) and (b % N == 0) and (c % N == 0)) def ncusps(self): r""" @@ -170,9 +170,9 @@ def ncusps(self): 432345564227567616 """ n = self.level() - if n==1: + if n == 1: return ZZ(1) - if n==2: + if n == 2: return ZZ(3) return prod([p**(2*e) - p**(2*e-2) for (p,e) in n.factor()])//2 @@ -200,18 +200,18 @@ def _find_cusps(self): n = self.level() C = [QQ(x) for x in range(n)] - n0=n//2 - n1=(n+1)//2 + n0 = n//2 + n1 = (n+1)//2 for r in range(1, n1): - if r > 1 and gcd(r,n)==1: + if r > 1 and gcd(r,n) == 1: C.append(ZZ(r)/ZZ(n)) - if n0==n/2 and gcd(r,n0)==1: + if n0 == n/2 and gcd(r,n0) == 1: C.append(ZZ(r)/ZZ(n0)) for s in range(2,n1): for r in range(1, 1+n): - if GCD_list([s,r,n])==1: + if GCD_list([s,r,n]) == 1: # GCD_list is ~40x faster than gcd, since gcd wastes loads # of time initialising a Sequence type. u,v = _lift_pair(r,s,n) diff --git a/src/sage/modular/arithgroup/congroup_gamma0.py b/src/sage/modular/arithgroup/congroup_gamma0.py index e960ce477d3..70d263ebc45 100644 --- a/src/sage/modular/arithgroup/congroup_gamma0.py +++ b/src/sage/modular/arithgroup/congroup_gamma0.py @@ -147,7 +147,7 @@ def _repr_(self): sage: Gamma0(98)._repr_() 'Congruence Subgroup Gamma0(98)' """ - return "Congruence Subgroup Gamma0(%s)"%self.level() + return "Congruence Subgroup Gamma0(%s)" % self.level() def __reduce__(self): """ @@ -171,7 +171,7 @@ def _latex_(self): sage: latex(Gamma0(20)) \Gamma_0(20) """ - return "\\Gamma_0(%s)"%self.level() + return "\\Gamma_0(%s)" % self.level() @cached_method def _generators_for_H(self): @@ -364,10 +364,10 @@ def generators(self, algorithm="farey"): # reasons, which aren't the ones the Farey symbol code gives return [ self([0,-1,1,0]), self([1,1,0,1]) ] - elif algorithm=="farey": + elif algorithm == "farey": return self.farey_symbol().generators() - elif algorithm=="todd-coxeter": + elif algorithm == "todd-coxeter": from sage.modular.modsym.p1list import P1List from .congroup import generators_helper level = self.level() @@ -507,7 +507,7 @@ def nu2(self): [1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0] """ n = self.level() - if n%4 == 0: + if n % 4 == 0: return ZZ(0) return prod([ 1 + kronecker_symbol(-4, p) for p, _ in n.factor()]) diff --git a/src/sage/modular/arithgroup/congroup_gamma1.py b/src/sage/modular/arithgroup/congroup_gamma1.py index d32d3646256..00dc9e8c0a5 100644 --- a/src/sage/modular/arithgroup/congroup_gamma1.py +++ b/src/sage/modular/arithgroup/congroup_gamma1.py @@ -117,7 +117,7 @@ def _repr_(self): sage: Gamma1(133)._repr_() 'Congruence Subgroup Gamma1(133)' """ - return "Congruence Subgroup Gamma1(%s)"%self.level() + return "Congruence Subgroup Gamma1(%s)" % self.level() def __reduce__(self): """ @@ -141,7 +141,7 @@ def _latex_(self): sage: latex(Gamma1(3)) \Gamma_1(3) """ - return "\\Gamma_1(%s)"%self.level() + return "\\Gamma_1(%s)" % self.level() def is_even(self): """ @@ -221,9 +221,9 @@ def generators(self, algorithm="farey"): [ 3 -2], [ 3 -2], [ 9 -2], [-12 7] ] """ - if algorithm=="farey": + if algorithm == "farey": return self.farey_symbol().generators() - elif algorithm=="todd-coxeter": + elif algorithm == "todd-coxeter": from sage.modular.modsym.g1list import G1list from .congroup import generators_helper level = self.level() @@ -253,7 +253,7 @@ def _contains_sl2(self, a,b,c,d): """ N = self.level() # don't need to check d == 1 mod N as this is automatic from det - return ((a%N == 1) and (c%N == 0)) + return ((a % N == 1) and (c % N == 0)) def nu2(self): r""" @@ -459,7 +459,7 @@ def dimension_cusp_forms(self, k=2, eps=None, algorithm="CohenOesterle"): if eps.is_trivial(): return Gamma0(N).dimension_cusp_forms(k) - if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k%2) == 0 and eps.is_odd()): + if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k % 2) == 0 and eps.is_odd()): return ZZ(0) if k == 1: @@ -543,7 +543,7 @@ def dimension_eis(self, k=2, eps=None, algorithm="CohenOesterle"): return Gamma0(N).dimension_eis(k) # Note case of k = 0 and trivial character already dealt with separately, so k <= 0 here is valid: - if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k%2) == 0 and eps.is_odd()): + if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k % 2) == 0 and eps.is_odd()): return ZZ(0) if algorithm == "Quer": @@ -637,7 +637,7 @@ def dimension_new_cusp_forms(self, k=2, eps=None, p=0, algorithm="CohenOesterle" from .congroup_gammaH import mumu - if p == 0 or N%p != 0 or eps.conductor().valuation(p) == N.valuation(p): + if p == 0 or N % p != 0 or eps.conductor().valuation(p) == N.valuation(p): D = [eps.conductor()*d for d in divisors(N//eps.conductor())] return sum([Gamma1_constructor(M).dimension_cusp_forms(k, eps.restrict(M), algorithm)*mumu(N//M) for M in D]) eps_p = eps.restrict(N//p) diff --git a/src/sage/modular/arithgroup/congroup_generic.py b/src/sage/modular/arithgroup/congroup_generic.py index e71426f9922..edf056784e6 100644 --- a/src/sage/modular/arithgroup/congroup_generic.py +++ b/src/sage/modular/arithgroup/congroup_generic.py @@ -544,7 +544,7 @@ def _new_group_from_level(self, level): from .congroup_gammaH import is_GammaH from .all import Gamma0, Gamma1, GammaH N = self.level() - if (level%N) and (N%level): + if (level % N) and (N % level): raise ValueError("one level must divide the other") if is_Gamma0(self): return Gamma0(level) @@ -558,7 +558,7 @@ def _new_group_from_level(self, level): newH = [ h + diff for h in H for diff in diffs ] return GammaH(level, [x for x in newH if gcd(level, x) == 1]) else: - return GammaH(level, [ h%level for h in H ]) + return GammaH(level, [ h % level for h in H ]) else: raise NotImplementedError diff --git a/src/sage/modular/arithgroup/congroup_sl2z.py b/src/sage/modular/arithgroup/congroup_sl2z.py index 69a977994d0..e0bc3abe12e 100644 --- a/src/sage/modular/arithgroup/congroup_sl2z.py +++ b/src/sage/modular/arithgroup/congroup_sl2z.py @@ -146,7 +146,7 @@ def _latex_(self): sage: latex(SL2Z) \mbox{\rm SL}_2(\Bold{Z}) """ - return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_()) + return "\\mbox{\\rm SL}_2(%s)" % (ZZ._latex_()) def is_subgroup(self, right): """ diff --git a/src/sage/modular/local_comp/smoothchar.py b/src/sage/modular/local_comp/smoothchar.py index b56befe27cb..c81677589a9 100644 --- a/src/sage/modular/local_comp/smoothchar.py +++ b/src/sage/modular/local_comp/smoothchar.py @@ -1283,7 +1283,7 @@ def _reduce_Qp(self, level, x): p = self.prime() r = ZZ(x.norm().valuation(p) / 2) y = x / p**r - if p==2 and y.trace().valuation(2) < 1: + if p == 2 and y.trace().valuation(2) < 1: raise ValueError("%s not congruent mod %s to an elt of Qp" % (x, self.ideal(level))) Y = (y.trace() / 2) % self.ideal(level).smallest_integer() X = p**r * Y diff --git a/src/sage/modular/modform/ambient_R.py b/src/sage/modular/modform/ambient_R.py index 9601342faeb..95c69eea5be 100644 --- a/src/sage/modular/modform/ambient_R.py +++ b/src/sage/modular/modform/ambient_R.py @@ -123,7 +123,7 @@ def _compute_q_expansion_basis(self, prec=None): newB.append(f) V = A.span(gens) if len(newB) != self.dimension(): - raise RuntimeError("The dimension of the space is %s but the basis we computed has %s elements"%(self.dimension(), len(newB))) + raise RuntimeError("The dimension of the space is %s but the basis we computed has %s elements" % (self.dimension(), len(newB))) lst = [R(f) for f in newB] return [f/f[f.valuation()] for f in lst] else: diff --git a/src/sage/modular/modform/ambient_eps.py b/src/sage/modular/modform/ambient_eps.py index 8f14e22ce20..71502963bb8 100644 --- a/src/sage/modular/modform/ambient_eps.py +++ b/src/sage/modular/modform/ambient_eps.py @@ -118,9 +118,9 @@ def __init__(self, character, weight=2, base_ring=None, eis_only=False): """ if not dirichlet.is_DirichletCharacter(character): - raise TypeError("character (=%s) must be a Dirichlet character"%character) + raise TypeError("character (=%s) must be a Dirichlet character" % character) if base_ring is None: - base_ring=character.base_ring() + base_ring = character.base_ring() if character.base_ring() != base_ring: character = character.change_ring(base_ring) if base_ring.characteristic() != 0: @@ -152,10 +152,10 @@ def _repr_(self): Modforms of level 8 """ if self._eis_only: - return "Modular Forms space of character %s and weight %s over %s" %( + return "Modular Forms space of character %s and weight %s over %s" % ( self.character()._repr_short_(), self.weight(), self.base_ring()) else: - return "Modular Forms space of dimension %s, character %s and weight %s over %s"%( + return "Modular Forms space of dimension %s, character %s and weight %s over %s" % ( self.dimension(), self.character()._repr_short_(), self.weight(), self.base_ring()) @cached_method diff --git a/src/sage/modular/modform/constructor.py b/src/sage/modular/modform/constructor.py index 023f9a380d2..b632f6d398c 100644 --- a/src/sage/modular/modform/constructor.py +++ b/src/sage/modular/modform/constructor.py @@ -126,7 +126,7 @@ def canonical_parameters(group, level, weight, base_ring): group = arithgroup.Gamma0(m) if not isinstance(base_ring, CommutativeRing): - raise TypeError("base_ring (=%s) must be a commutative ring"%base_ring) + raise TypeError("base_ring (=%s) must be a commutative ring" % base_ring) # it is *very* important to include the level as part of the data # that defines the key, since Dirichlet characters of different diff --git a/src/sage/modular/modform/cuspidal_submodule.py b/src/sage/modular/modform/cuspidal_submodule.py index 19a0b5661c0..954542073dc 100644 --- a/src/sage/modular/modform/cuspidal_submodule.py +++ b/src/sage/modular/modform/cuspidal_submodule.py @@ -90,7 +90,7 @@ def __init__(self, ambient_space): True """ from sage.misc.verbose import verbose - verbose('creating cuspidal submodule of %s'%ambient_space) + verbose('creating cuspidal submodule of %s' % ambient_space) d = ambient_space._dim_cuspidal() V = ambient_space.module() G = [V.gen(i) for i in range(d)] @@ -121,7 +121,7 @@ def _repr_(self): sage: S = CuspForms(Gamma1(3),6); S._repr_() 'Cuspidal subspace of dimension 1 of Modular Forms space of dimension 3 for Congruence Subgroup Gamma1(3) of weight 6 over Rational Field' """ - return "Cuspidal subspace of dimension %s of %s"%(self.dimension(), self.ambient_module()) + return "Cuspidal subspace of dimension %s of %s" % (self.dimension(), self.ambient_module()) def is_cuspidal(self): """ @@ -393,7 +393,7 @@ def _compute_q_expansion_basis(self, prec=None): else: prec = Integer(prec) - chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) + chars = self.group().characters_mod_H(sign=-1, galois_orbits=True) B = [] dim = 0 @@ -484,7 +484,7 @@ def _compute_diamond_matrix(self, d): [ 0 0 0 0 0 -1 0] [ 0 0 0 0 0 0 -1] """ - chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) + chars = self.group().characters_mod_H(sign=-1, galois_orbits=True) A = Matrix(QQ, 0, 0) for c in chars: chi = c.minimize_base_ring() @@ -525,7 +525,7 @@ def _compute_hecke_matrix(self, n): True """ - chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) + chars = self.group().characters_mod_H(sign=-1, galois_orbits=True) A = Matrix(QQ, 0, 0) for c in chars: chi = c.minimize_base_ring() diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index be0f2557c73..39d78cdc0ea 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -137,13 +137,13 @@ def eisenstein_series_qexp(k, prec=10, K=QQ, var='q', normalization='linear'): try: a0fac = K(1/a0den) except ZeroDivisionError: - raise ValueError("The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0den, K)) + raise ValueError("The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s" % (a0den, K)) elif normalization == 'constant': a0num = a0.numerator() try: a0fac = K(1/a0num) except ZeroDivisionError: - raise ValueError("The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0num, K)) + raise ValueError("The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s" % (a0num, K)) elif normalization == 'integral': a0fac = None else: @@ -155,7 +155,7 @@ def eisenstein_series_qexp(k, prec=10, K=QQ, var='q', normalization='linear'): # The following is *dramatically* faster than doing the more natural # "R(ls)" would be: E = ZZ[var](ls, prec=prec, check=False).change_ring(QQ) - if len(ls)>0: + if len(ls) > 0: E._unsafe_mutate(0, a0) return R(E, prec) # The following is an older slower alternative to the above three lines: @@ -431,15 +431,15 @@ def eisenstein_series_lseries(weight, prec=53, # Using a string for residues is a hack but it works well # since this will make PARI/GP compute sqrt(pi) with the # right precision. - residues='[sqrt(Pi)*(%s)]'%((-1)**Integer(j/2)*bernoulli(j)/j), + residues='[sqrt(Pi)*(%s)]' % ((-1)**Integer(j // 2) * bernoulli(j) / j), prec=prec) - s = 'coeff = %s;'%f.list() - L.init_coeffs('coeff[k+1]',pari_precode=s, + s = 'coeff = %s;' % f.list() + L.init_coeffs('coeff[k+1]', pari_precode=s, max_imaginary_part=max_imaginary_part, max_asymp_coeffs=max_asymp_coeffs) L.check_functional_equation() - L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)'%(j,f)) + L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)' % (j, f)) return L diff --git a/src/sage/modular/modform/eisenstein_submodule.py b/src/sage/modular/modform/eisenstein_submodule.py index fd1731574fa..90370ecf78d 100644 --- a/src/sage/modular/modform/eisenstein_submodule.py +++ b/src/sage/modular/modform/eisenstein_submodule.py @@ -37,7 +37,7 @@ def __init__(self, ambient_space): True """ from sage.misc.verbose import verbose - verbose('creating eisenstein submodule of %s'%ambient_space) + verbose('creating eisenstein submodule of %s' % ambient_space) d = ambient_space._dim_eisenstein() V = ambient_space.module() n = V.dimension() diff --git a/src/sage/modular/modform/hecke_operator_on_qexp.py b/src/sage/modular/modform/hecke_operator_on_qexp.py index 36e092d8200..48590ba7d23 100644 --- a/src/sage/modular/modform/hecke_operator_on_qexp.py +++ b/src/sage/modular/modform/hecke_operator_on_qexp.py @@ -83,9 +83,9 @@ def hecke_operator_on_qexp(f, n, k, eps=None, eps = DirichletGroup(1, base_ring=ZZ)[0] if check: if not (is_PowerSeries(f) or is_ModularFormElement(f)): - raise TypeError("f (=%s) must be a power series or modular form"%f) + raise TypeError("f (=%s) must be a power series or modular form" % f) if not is_DirichletCharacter(eps): - raise TypeError("eps (=%s) must be a Dirichlet character"%eps) + raise TypeError("eps (=%s) must be a Dirichlet character" % eps) k = Integer(k) n = Integer(n) v = [] @@ -215,7 +215,7 @@ def hecke_operator_on_basis(B, n, k, eps=None, already_echelonized=False): Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 12 and degree 4 """ if not isinstance(B, (list, tuple)): - raise TypeError("B (=%s) must be a list or tuple"%B) + raise TypeError("B (=%s) must be a list or tuple" % B) if len(B) == 0: if eps is None: R = CyclotomicField(1) diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index c13ebcbb77d..f811939ca5f 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -28,7 +28,7 @@ from sage.structure.sequence import Sequence # This variable controls importing the SciPy library sparingly -scipy=None +scipy = None @richcmp_method class NumericalEigenforms(SageObject): @@ -163,7 +163,7 @@ def _repr_(self): sage: n._repr_() 'Numerical Hecke eigenvalues for Congruence Subgroup Gamma0(61) of weight 2' """ - return "Numerical Hecke eigenvalues for %s of weight %s"%( + return "Numerical Hecke eigenvalues for %s of weight %s" % ( self._group, self._weight) @cached_method diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 90e149340e4..2e98067413e 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -103,7 +103,7 @@ def _span_of_forms_in_weight(forms, weight, prec, stop_dim=None, use_random=Fals [ 0 1 0 195660 12080128] [ 0 0 1 -48 1080] """ - t = verbose('multiplying forms up to weight %s'%weight) + t = verbose('multiplying forms up to weight %s' % weight) # Algorithm: run through the monomials of the appropriate weight, and build # up the vector space they span. @@ -396,7 +396,7 @@ def _generators_variables_dictionnary(self, poly_parent, gens): nb_var = poly_parent.ngens() nb_gens = self.ngens() if nb_var != nb_gens: - raise ValueError('the number of variables (%s) must be equal to the number of generators of the modular forms ring (%s)'%(nb_var, self.ngens())) + raise ValueError('the number of variables (%s) must be equal to the number of generators of the modular forms ring (%s)' % (nb_var, self.ngens())) return {poly_parent.gen(i): self(gens[i]) for i in range(0, nb_var)} def from_polynomial(self, polynomial, gens=None): @@ -520,7 +520,7 @@ def _element_constructor_(self, forms_datum): 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: - raise ValueError('the group (%s) and/or the base ring (%s) of the given modular form is not consistant with the base space: %s'%(forms_datum.group(), forms_datum.base_ring(), self)) + raise ValueError('the group (%s) and/or the base ring (%s) of the given modular form is not consistant with the base space: %s' % (forms_datum.group(), forms_datum.base_ring(), self)) elif forms_datum in self.base_ring(): forms_dictionary = {0:forms_datum} elif isinstance(forms_datum, MPolynomial): @@ -1021,7 +1021,7 @@ def q_expansion_basis(self, weight, prec=None, use_random=True): return [] if prec is None: - prec=self.modular_forms_of_weight(weight).sturm_bound() + prec = self.modular_forms_of_weight(weight).sturm_bound() working_prec = max(prec, self.modular_forms_of_weight(weight).sturm_bound()) diff --git a/src/sage/modular/modform/space.py b/src/sage/modular/modform/space.py index 82b20da8167..36daef1d17b 100644 --- a/src/sage/modular/modform/space.py +++ b/src/sage/modular/modform/space.py @@ -138,9 +138,9 @@ def __init__(self, group, weight, character, base_ring, category=None): global WARN if WARN: print("Modular forms -- under development -- do not trust yet.") - WARN=False + WARN = False if not arithgroup.is_CongruenceSubgroup(group): - raise TypeError("group (=%s) must be a congruence subgroup"%group) + raise TypeError("group (=%s) must be a congruence subgroup" % group) weight = Integer(weight) if not ((character is None) or isinstance(character, dirichlet.DirichletCharacter)): raise TypeError("character must be a Dirichlet character") @@ -405,7 +405,7 @@ def __normalize_prec(self, prec): else: prec = Integer(prec) if prec < 0: - raise ValueError("prec (=%s) must be at least 0"%prec) + raise ValueError("prec (=%s) must be at least 0" % prec) return prec @cached_method @@ -1422,7 +1422,7 @@ def gen(self, n): try: return self.basis()[int(n)] except IndexError: - raise ValueError("Generator %s not defined"%n) + raise ValueError("Generator %s not defined" % n) def gens(self): """ @@ -1551,7 +1551,7 @@ def cuspidal_submodule(self): else: assert S.dimension() == self.dimension() self.__is_cuspidal = True - S.__is_eisenstein = (S.dimension()==0) + S.__is_eisenstein = (S.dimension() == 0) S.__is_cuspidal = True return S @@ -1737,7 +1737,7 @@ def eisenstein_submodule(self): else: assert E.dimension() == self.dimension() self.__is_eisenstein = True - E.__is_cuspidal = (E.dimension()==0) + E.__is_cuspidal = (E.dimension() == 0) E.__is_eisenstein = True return E @@ -1903,7 +1903,7 @@ def find_in_space(self, f, forms=None, prec=None, indep=True): else: B = V.span(w) if is_PowerSeries(f) and f.prec() < n: - raise ValueError("you need at least %s terms of precision"%n) + raise ValueError("you need at least %s terms of precision" % n) x = V(f.padded_list(n)) return B.coordinates(x) diff --git a/src/sage/modular/modform/submodule.py b/src/sage/modular/modform/submodule.py index 49b6c12b493..441f6d9dd05 100644 --- a/src/sage/modular/modform/submodule.py +++ b/src/sage/modular/modform/submodule.py @@ -61,7 +61,7 @@ def _repr_(self): sage: ModularForms(Gamma1(13),2).eisenstein_subspace()._repr_() 'Eisenstein subspace of dimension 11 of Modular Forms space of dimension 13 for Congruence Subgroup Gamma1(13) of weight 2 over Rational Field' """ - return "Modular Forms subspace of dimension %s of %s"%(self.dimension(), self.ambient_module()) + return "Modular Forms subspace of dimension %s of %s" % (self.dimension(), self.ambient_module()) def _compute_coefficients(self, element, X): """ diff --git a/src/sage/modular/modform/vm_basis.py b/src/sage/modular/modform/vm_basis.py index 559c36828e9..f83c6bbcc1f 100644 --- a/src/sage/modular/modform/vm_basis.py +++ b/src/sage/modular/modform/vm_basis.py @@ -128,7 +128,7 @@ def victor_miller_basis(k, prec=10, cusp_only=False, var='q'): - Martin Raum (2009-08-02): use FLINT for polynomial arithmetic (instead of NTL) """ k = Integer(k) - if k%2 == 1 or k==2: + if k % 2 == 1 or k == 2: return Sequence([]) elif k < 0: raise ValueError("k must be non-negative") diff --git a/src/sage/modular/modform/weight1.py b/src/sage/modular/modform/weight1.py index b7a2caa7a41..4cb34df7513 100644 --- a/src/sage/modular/modform/weight1.py +++ b/src/sage/modular/modform/weight1.py @@ -177,7 +177,7 @@ def hecke_stable_subspace(chi, aux_prime=ZZ(2)): # The theory does not guarantee that J is exactly S_1(chi), just that it is # intermediate between S_1(chi) and M_1(chi). In every example I know of, # it is equal to S_1(chi), but just for honesty, we check this anyway. - t=verbose("Checking cuspidality", level=1) + t = verbose("Checking cuspidality", level=1) JEis = V.span(V(x.padded_list(R)) for x in EisensteinForms(chi, 1).q_echelon_basis(prec=R)) D = JEis.intersection(J) if D.dimension() != 0: diff --git a/src/sage/modular/modform_hecketriangle/abstract_ring.py b/src/sage/modular/modform_hecketriangle/abstract_ring.py index f2b0e77d920..f28917578af 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_ring.py +++ b/src/sage/modular/modform_hecketriangle/abstract_ring.py @@ -497,7 +497,7 @@ def reduce_type(self, analytic_type=None, degree=None): return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=self.weight(), ep=self.ep()) else: (weight, ep) = degree - if (self.is_homogeneous() and (weight != self.weight() or ep!=self.ep())): + if (self.is_homogeneous() and (weight != self.weight() or ep != self.ep())): analytic_type = self._analytic_type.reduce_to([]) return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=weight, ep=ep) diff --git a/src/sage/modular/modform_hecketriangle/abstract_space.py b/src/sage/modular/modform_hecketriangle/abstract_space.py index 110b0fe3be7..d1e23066aff 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_space.py +++ b/src/sage/modular/modform_hecketriangle/abstract_space.py @@ -535,7 +535,7 @@ def contains_coeff_ring(self): False """ - return ((self.AT("holo") <= self._analytic_type) and (self.weight()==QQ(0)) and (self.ep()==ZZ(1))) + return ((self.AT("holo") <= self._analytic_type) and (self.weight() == QQ(0)) and (self.ep() == ZZ(1))) def element_from_coordinates(self, vec): r""" @@ -633,7 +633,7 @@ def homogeneous_part(self, k, ep): ValueError: QuasiMeromorphicModularForms(n=6, k=4, ep=1) over Integer Ring already is homogeneous with degree (4, 1) != (5, 1)! """ - if (k==self._weight and ep==self._ep): + if (k == self._weight and ep == self._ep): return self else: raise ValueError("{} already is homogeneous with degree ({}, {}) != ({}, {})!".format(self, self._weight, self._ep, k, ep)) @@ -829,7 +829,7 @@ def F_simple(self, order_1=ZZ(0)): if (order_inf > 0 and order_1 > 0): new_space = self.extend_type("cusp") - elif (order_inf >=0 and order_1 >= 0): + elif (order_inf >= 0 and order_1 >= 0): new_space = self.extend_type("holo") else: new_space = self.extend_type("weak") @@ -981,7 +981,7 @@ def Faber_pol(self, m, order_1=ZZ(0), fix_d=False, d_num_prec=None): # The first term is zero only up to numerical errors, # so we manually have to remove it if (not d.parent().is_exact()): - temp_reminder=temp_reminder.truncate_neg(-temp_exp+1) + temp_reminder = temp_reminder.truncate_neg(-temp_exp+1) return fab_pol.polynomial() @@ -1214,7 +1214,7 @@ def F_basis_pol(self, m, order_1=ZZ(0)): (x,y,z,d) = self.rat_field().gens() n = self._group.n() - if (n ==infinity): + if (n == infinity): order_1 = ZZ(order_1) order_inf = self._l1 - order_1 finf_pol = d*(x-y**2) @@ -2538,7 +2538,7 @@ def gen(self, k=0): """ k = ZZ(k) - if k>=0 and k < self.dimension(): + if k >= 0 and k < self.dimension(): return self.gens()[k] else: raise ValueError("Invalid index: k={} does not satisfy 0 <= k <= {}!".format(k, self.dimension())) diff --git a/src/sage/modular/modform_hecketriangle/constructor.py b/src/sage/modular/modform_hecketriangle/constructor.py index 9471394bea1..845098fe862 100644 --- a/src/sage/modular/modform_hecketriangle/constructor.py +++ b/src/sage/modular/modform_hecketriangle/constructor.py @@ -402,7 +402,7 @@ def FormsRing(analytic_type, group=3, base_ring=ZZ, red_hom=False): if analytic_type <= AT("weak"): if analytic_type <= AT("holo"): if analytic_type <= AT("cusp"): - if analytic_type <=AT([]): + if analytic_type <= AT([]): raise ValueError("Analytic type Zero is not valid for forms rings.") else: from .graded_ring import CuspFormsRing @@ -420,7 +420,7 @@ def FormsRing(analytic_type, group=3, base_ring=ZZ, red_hom=False): if analytic_type <= AT(["weak", "quasi"]): if analytic_type <= AT(["holo", "quasi"]): if analytic_type <= AT(["cusp", "quasi"]): - if analytic_type <=AT(["quasi"]): + if analytic_type <= AT(["quasi"]): raise ValueError("Analytic type Zero is not valid for forms rings.") else: from .graded_ring import QuasiCuspFormsRing diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py index 7c3867923c9..b0241196107 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py @@ -295,7 +295,7 @@ def word_S_T(self): S = self.parent().S() (L, sgn) = self._word_S_T_data() - M = [S if v[0]==0 else Tf(v[1]) for v in L] + M = [S if v[0] == 0 else Tf(v[1]) for v in L] if sgn > 0: sgn = self.parent().I() else: @@ -1025,7 +1025,7 @@ def primitive_representative(self, method="block"): G = self.parent() if self.is_identity(): - method="block" + method = "block" if self.is_elliptic(): if self.parent().n() == infinity: diff --git a/src/sage/modular/modsym/p1list.pyx b/src/sage/modular/modsym/p1list.pyx index 30a8f7471dd..1fc3e2de952 100644 --- a/src/sage/modular/modsym/p1list.pyx +++ b/src/sage/modular/modsym/p1list.pyx @@ -1371,8 +1371,8 @@ def lift_to_sl2z(c, d, N): sage: lift_to_sl2z(2,3,6000000) [1, 1, 2, 3] - You will get a ValueError exception if the input is invalid. Note - that here gcd(15,6,24)=3:: + You will get a :class:`ValueError` exception if the input is invalid. + Note that here gcd(15,6,24)=3:: sage: lift_to_sl2z(15,6,24) Traceback (most recent call last): diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 04e86a0732e..62d189e49d5 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -387,7 +387,7 @@ def _set_radius(self, radius): pi = p e = d if not e.is_integral(): - raise ValueError("no element of base ring (=%s) has normalised valuation %s" % (self.base_ring(), radius * 12 /(p-1))) + raise ValueError("no element of base ring (=%s) has normalised valuation %s" % (self.base_ring(), radius * 12 / (p-1))) self._radius = radius self._const = pi ** ZZ(e) @@ -1250,7 +1250,7 @@ def _discover_recurrence_matrix(self, use_smithline=True): xyring = PolynomialRing(self.base_ring(), ["x","y"], 2) x,y = xyring.gens() cc = self.prime() ** (-12/(self.prime() - 1)) - bigI = x*SmiH(y*cc)- y*cc*SmiH(x) + bigI = x*SmiH(y*cc) - y*cc*SmiH(x) smallI = xyring(bigI / (x - cc*y)) r = matrix(ZZ, self.prime(), self.prime()) for i in range(self.prime()): diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index fa66f2aa0a3..5183106e458 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -1004,14 +1004,14 @@ def level1_UpGj(p, klist, m, extra_data=False): e, Ep1 = katz_expansions(k0, p, ellp, mdash, n) verbose("done steps 2+3", t) - t=cputime() + t = cputime() # Step 4 G = compute_G(p, Ep1) Alist = [] verbose("done step 4a", t) - t=cputime() + t = cputime() for k in klist: k = ZZ(k) # convert to sage integer kdiv = k // (p - 1) diff --git a/src/sage/modular/pollack_stevens/distributions.py b/src/sage/modular/pollack_stevens/distributions.py index 274cdfa87a4..7aaad3c6f0e 100644 --- a/src/sage/modular/pollack_stevens/distributions.py +++ b/src/sage/modular/pollack_stevens/distributions.py @@ -319,7 +319,7 @@ def _element_constructor_(self, val, **kwargs): """ ordp = kwargs.get('ord',0) check = kwargs.get('check',True) - normalize= kwargs.get('normalize',True) + normalize = kwargs.get('normalize',True) return self.Element(val, self, ordp, check, normalize) def _coerce_map_from_(self, other): diff --git a/src/sage/repl/interpreter.py b/src/sage/repl/interpreter.py index c8fd27b35fa..b9a222c12ef 100644 --- a/src/sage/repl/interpreter.py +++ b/src/sage/repl/interpreter.py @@ -777,14 +777,14 @@ def load_config_file(self, *args, **kwds): Test that :trac:`15972` has been fixed:: - sage: from sage.misc.temporary_file import tmp_dir + sage: import tempfile sage: from sage.repl.interpreter import SageTerminalApp - sage: d = tmp_dir() sage: from IPython.paths import get_ipython_dir - sage: IPYTHONDIR = get_ipython_dir() - sage: os.environ['IPYTHONDIR'] = d - sage: SageTerminalApp().load_config_file() - sage: os.environ['IPYTHONDIR'] = IPYTHONDIR + sage: with tempfile.TemporaryDirectory() as d: + ....: IPYTHONDIR = get_ipython_dir() + ....: os.environ['IPYTHONDIR'] = d + ....: SageTerminalApp().load_config_file() + ....: os.environ['IPYTHONDIR'] = IPYTHONDIR """ super().load_config_file(*args, **kwds) newconfig = sage_ipython_config.default() diff --git a/src/sage/repl/ipython_kernel/kernel.py b/src/sage/repl/ipython_kernel/kernel.py index 73681716aa2..db7554eed59 100644 --- a/src/sage/repl/ipython_kernel/kernel.py +++ b/src/sage/repl/ipython_kernel/kernel.py @@ -16,7 +16,18 @@ # *************************************************************************** import sys -from ipykernel.ipkernel import IPythonKernel +import warnings +with warnings.catch_warnings(): + # When upstream pydevd (as opposed to the bundled version) is used + # with debugpy, a PEP 420 warning is emitted. Debugpy and/or + # pydevd will eventually work around this, but as of September + # 2023, hiding the warning gives us more flexibility in the + # versions of those packages that we can accept. + warnings.filterwarnings("ignore", + message=r".*pkg_resources\.declare_namespace", + category=DeprecationWarning) + from ipykernel.ipkernel import IPythonKernel + from ipykernel.zmqshell import ZMQInteractiveShell from traitlets import Type diff --git a/src/sage/rings/asymptotic/growth_group.py b/src/sage/rings/asymptotic/growth_group.py index 27c14592bca..906a0dbae57 100644 --- a/src/sage/rings/asymptotic/growth_group.py +++ b/src/sage/rings/asymptotic/growth_group.py @@ -3137,7 +3137,7 @@ def _log_factor_(self, base=None, locals=None): return ((e, coefficient),) if var.startswith('exp('): - assert(var[-1] == ')') + assert (var[-1] == ')') v = var[4:-1] else: v = 'log(%s)' % (var,) @@ -3207,7 +3207,7 @@ def _rpow_element_(self, base, locals=None): x^(log(2)) """ var = str(self.parent()._var_) - if not(var.startswith('log(') and self.exponent.is_one()): + if not (var.startswith('log(') and self.exponent.is_one()): raise ValueError('Variable %s is not a log of something.' % (var,)) new_var = var[4:-1] if base == 'e': diff --git a/src/sage/rings/asymptotic/growth_group_cartesian.py b/src/sage/rings/asymptotic/growth_group_cartesian.py index f93535e8d8e..447c25fa64d 100644 --- a/src/sage/rings/asymptotic/growth_group_cartesian.py +++ b/src/sage/rings/asymptotic/growth_group_cartesian.py @@ -837,7 +837,7 @@ def next_custom(self): S.next_custom() O.next_custom() - assert(len(newS) == len(newO)) + assert (len(newS) == len(newO)) if (len(Sfactors) == len(newS) and len(Ofactors) == len(newO)): diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py index 7229dab646a..26cce303581 100644 --- a/src/sage/rings/cfinite_sequence.py +++ b/src/sage/rings/cfinite_sequence.py @@ -155,7 +155,7 @@ def CFiniteSequences(base_ring, names=None, category=None): raise NotImplementedError("Multidimensional o.g.f. not implemented.") if category is None: category = Fields() - if not(base_ring in (QQ, ZZ)): + if not (base_ring in (QQ, ZZ)): raise ValueError("O.g.f. base not rational.") polynomial_ring = PolynomialRing(base_ring, names) return CFiniteSequences_generic(polynomial_ring, category) @@ -301,7 +301,7 @@ def __classcall_private__(cls, ogf): """ br = ogf.base_ring() - if not(br in (QQ, ZZ)): + if not (br in (QQ, ZZ)): br = QQ # if the base ring of the o.g.f is not QQ, we force it to QQ and see if the o.g.f converts nicely # trying to figure out the ogf variables diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py index a3f877e423d..e701c917062 100644 --- a/src/sage/rings/continued_fraction.py +++ b/src/sage/rings/continued_fraction.py @@ -700,7 +700,7 @@ def _mpfr_(self, R): q_odd = self.denominator(2 * k + 1) m_even = (p_even << N) // q_even # floor((2^N p_even) / q_even) m_odd = (p_odd << N + q_odd - 1) // q_odd # ceil((2^N p_odd) / q_odd) - while (m_odd - m_even) > 1: + while m_odd - m_even > 1: k += 1 p_even = self.numerator(2 * k) p_odd = self.numerator(2 * k + 1) @@ -725,7 +725,7 @@ def _mpfr_(self, R): # in order to find the nearest approximation we possibly need to # augment our precision on convergents. while True: - assert not(p_odd << (N+1) <= (2*m_odd-1) * q_odd) or not(p_even << (N+1) >= (2*m_even+1) * q_even) + assert not (p_odd << (N+1) <= (2*m_odd-1) * q_odd) or not (p_even << (N+1) >= (2*m_even+1) * q_even) if p_odd << (N+1) <= (2*m_odd-1) * q_odd: return R(sgn * m_even) >> N if p_even << (N+1) >= (2*m_even+1) * q_even: diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index bdb5884668e..0eca810920e 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -233,7 +233,7 @@ cdef class arith_int: return self.abs_int(a) if a<0: a=-a if b<0: b=-b - while(b): + while b: c = a % b a = b b = c @@ -261,7 +261,7 @@ cdef class arith_int: if b<0: b = -b; qsign = -1 p = 1; q = 0; r = 0; s = 1 - while (b): + while b: c = a % b; quot = a/b a = b; b = c new_r = p - quot*r @@ -360,13 +360,15 @@ cdef class arith_llong: cdef long long c_gcd_longlong(self, long long a, long long b) except -1: cdef long long c - if a==0: + if a == 0: return self.abs_longlong(b) - if b==0: + if b == 0: return self.abs_longlong(a) - if a<0: a=-a - if b<0: b=-b - while(b): + if a < 0: + a = -a + if b < 0: + b = -b + while b: c = a % b a = b b = c @@ -396,7 +398,7 @@ cdef class arith_llong: if b<0: b = -b; qsign = -1 p = 1; q = 0; r = 0; s = 1 - while (b): + while b: c = a % b; quot = a/b a = b; b = c new_r = p - quot*r diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 046b737a833..4fb4656cdd2 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -646,11 +646,14 @@ cdef class IntegerMod_abstract(FiniteRingElement): ``R`` is the parent of ``self``. - OUTPUT: Integer `x` such that `b^x = a`, if this exists; a ValueError otherwise. + OUTPUT: + + Integer `x` such that `b^x = a`, if this exists; a :class:`ValueError` + otherwise. .. NOTE:: - The algorithm first factors the modulus, then invokes Pari's ``znlog`` + The algorithm first factors the modulus, then invokes Pari's :pari:`znlog` function for each odd prime power in the factorization of the modulus. This method can be quite slow for large moduli. diff --git a/src/sage/rings/function_field/function_field_polymod.py b/src/sage/rings/function_field/function_field_polymod.py index 460096c94a1..b740b771bec 100644 --- a/src/sage/rings/function_field/function_field_polymod.py +++ b/src/sage/rings/function_field/function_field_polymod.py @@ -1127,9 +1127,9 @@ def _simple_model(self, name='v'): L = M.base_field() K = L.base_field() - assert(isinstance(K, RationalFunctionField)) - assert(K is not L) - assert(L is not M) + assert (isinstance(K, RationalFunctionField)) + assert (K is not L) + assert (L is not M) if not K.constant_field().is_perfect(): raise NotImplementedError("simple_model() only implemented over perfect constant fields") diff --git a/src/sage/rings/function_field/valuation.py b/src/sage/rings/function_field/valuation.py index e8afd1cb232..3c92f8cf212 100644 --- a/src/sage/rings/function_field/valuation.py +++ b/src/sage/rings/function_field/valuation.py @@ -1474,7 +1474,7 @@ def _repr_(self): [ Valuation at the infinite place, v(y - 1) = 2 ]-adic valuation] """ - assert(self.domain().base() is not self.domain()) + assert (self.domain().base() is not self.domain()) if repr(self._base_valuation) == repr(self.restriction(self.domain().base())): return repr(self._base_valuation) return super()._repr_() diff --git a/src/sage/rings/infinity.py b/src/sage/rings/infinity.py index c5ab0b24f32..3c4a960c037 100644 --- a/src/sage/rings/infinity.py +++ b/src/sage/rings/infinity.py @@ -1865,11 +1865,11 @@ def test_signed_infinity(pos_inf): assert InfinityRing(pos_inf) is infinity, msg assert InfinityRing(-pos_inf) is minus_infinity, msg assert infinity == pos_inf, msg - assert not(infinity > pos_inf), msg - assert not(infinity < pos_inf), msg + assert not (infinity > pos_inf), msg + assert not (infinity < pos_inf), msg assert minus_infinity == -pos_inf, msg - assert not(minus_infinity > -pos_inf), msg - assert not(minus_infinity < -pos_inf), msg + assert not (minus_infinity > -pos_inf), msg + assert not (minus_infinity < -pos_inf), msg assert pos_inf > -pos_inf, msg assert infinity > -pos_inf, msg assert pos_inf > minus_infinity, msg diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 0ca24804524..4202bcc9a10 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -2326,7 +2326,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): OUTPUT: If ``truncate_mode`` is 0 (default), then returns the exact n'th root - if ``self`` is an n'th power, or raises a ValueError if it is not. + if ``self`` is an n'th power, or raises a :class:`ValueError` + if it is not. If ``truncate_mode`` is 1, then if either ``n`` is odd or ``self`` is positive, returns a pair ``(root, exact_flag)`` where ``root`` is the diff --git a/src/sage/rings/multi_power_series_ring_element.py b/src/sage/rings/multi_power_series_ring_element.py index bd6fbde6247..8801d2d279a 100644 --- a/src/sage/rings/multi_power_series_ring_element.py +++ b/src/sage/rings/multi_power_series_ring_element.py @@ -1954,7 +1954,7 @@ def exp(self, prec=infinity): if x.is_zero(): return exp_c val = x.valuation() - assert(val >= 1) + assert (val >= 1) prec = min(prec, self.prec()) if is_Infinite(prec): @@ -2051,7 +2051,7 @@ def log(self, prec=infinity): if x.is_zero(): return log_c val = x.valuation() - assert(val >= 1) + assert (val >= 1) prec = min(prec, self.prec()) if is_Infinite(prec): diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 7fe89197011..b4ba6de1362 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -2839,7 +2839,7 @@ def is_CM(self): # Return cached answer if available try: return self.__is_CM - except(AttributeError): + except (AttributeError): pass # Then, deal with simple cases @@ -2925,7 +2925,7 @@ def complex_conjugation(self): # Return cached answer if available try: return self.__complex_conjugation - except(AttributeError): + except (AttributeError): pass # Then, deal with simple cases @@ -2956,7 +2956,7 @@ def complex_conjugation(self): # In the remaining case, self.is_CM() should have cached __max_tot_real_sub try: F, phi = self.__max_tot_real_sub - except(AttributeError): + except (AttributeError): F, phi = self.maximal_totally_real_subfield() if self.is_absolute(): K_rel = self.relativize(phi, self.variable_name() * 2) @@ -3061,7 +3061,7 @@ def maximal_totally_real_subfield(self): try: return self.__max_tot_real_sub - except(AttributeError): + except (AttributeError): pass if isinstance( diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 1e8a6a17fe1..26ab82bc54f 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -1358,7 +1358,7 @@ def is_CM_extension(self): try: return self.__is_CM_extension - except(AttributeError): + except (AttributeError): pass if self.relative_degree() == 2: diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index d821b5c1576..152db86eaf9 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -89,7 +89,7 @@ cdef class CAElement(pAdicTemplateElement): self.absprec = aprec else: self.absprec = min(aprec, val + rprec) - if isinstance(x,CAElement) and x.parent() is self.parent(): + if isinstance(x, CAElement) and x.parent() is self.parent(): cshift_notrunc(self.value, (x).value, 0, self.absprec, self.prime_pow, True) else: cconv(self.value, x, self.absprec, 0, self.prime_pow) @@ -395,9 +395,8 @@ cdef class CAElement(pAdicTemplateElement): creduce(q.value, q.value, q.absprec, q.prime_pow) return q, r - def __pow__(CAElement self, _right, dummy): - """ + r""" Exponentiation. When ``right`` is divisible by `p` then one can get more @@ -474,8 +473,8 @@ cdef class CAElement(pAdicTemplateElement): return base.__pow__(-_right, dummy) exact_exp = True elif self.parent() is _right.parent(): - ## For extension elements, we need to switch to the - ## fraction field sometimes in highly ramified extensions. + # For extension elements, we need to switch to the + # fraction field sometimes in highly ramified extensions. exact_exp = (_right)._is_exact_zero() pright = _right else: @@ -861,6 +860,7 @@ cdef class CAElement(pAdicTemplateElement): """ def tuple_recursive(l): return tuple(tuple_recursive(x) for x in l) if isinstance(l, Iterable) else l + return (self.parent(), tuple_recursive(trim_zeros(list(self.expansion()))), self.precision_absolute()) def _teichmuller_set_unsafe(self): @@ -1800,6 +1800,7 @@ cdef class pAdicConvert_CA_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_cae_v2(cls, parent, value, absprec): r""" Unpickle capped absolute elements. @@ -1834,4 +1835,3 @@ def unpickle_cae_v2(cls, parent, value, absprec): cunpickle(ans.value, value, ans.prime_pow) ans.absprec = absprec return ans - diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index 863c612587c..57ab352a66f 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -145,7 +145,7 @@ cdef class CRElement(pAdicTemplateElement): else: self.relprec = min(rprec, aprec - val) self.ordp = val - if isinstance(x,CRElement) and x.parent() is self.parent(): + if isinstance(x, CRElement) and x.parent() is self.parent(): cshift_notrunc(self.unit, (x).unit, 0, self.relprec, self.prime_pow, True) else: cconv(self.unit, x, self.relprec, val, self.prime_pow) @@ -678,8 +678,8 @@ cdef class CRElement(pAdicTemplateElement): return base.__pow__(-_right, dummy) exact_exp = True elif self.parent() is _right.parent(): - ## For extension elements, we need to switch to the - ## fraction field sometimes in highly ramified extensions. + # For extension elements, we need to switch to the + # fraction field sometimes in highly ramified extensions. exact_exp = (_right)._is_exact_zero() pright = _right else: @@ -732,7 +732,7 @@ cdef class CRElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _lshift_c(self, long shift): - """ + r""" Multiplies by `\pi^{\mbox{shift}}`. Negative shifts may truncate the result if the parent is not a @@ -763,7 +763,7 @@ cdef class CRElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _rshift_c(self, long shift): - """ + r""" Divides by ``\pi^{\mbox{shift}}``. Positive shifts may truncate the result if the parent is not a @@ -879,7 +879,6 @@ cdef class CRElement(pAdicTemplateElement): q._normalize() return q, r - def add_bigoh(self, absprec): """ Return a new element with absolute precision decreased to @@ -1253,6 +1252,7 @@ cdef class CRElement(pAdicTemplateElement): """ def tuple_recursive(l): return tuple(tuple_recursive(x) for x in l) if isinstance(l, list) else l + return (self.parent(), tuple_recursive(trim_zeros(list(self.expansion()))), self.valuation(), self.precision_relative()) def _teichmuller_set_unsafe(self): @@ -1506,7 +1506,7 @@ cdef class CRElement(pAdicTemplateElement): """ # Since we keep this element normalized there's not much to do here. if p is not None and p != self.parent().prime(): - raise ValueError('ring (%s) residue field of the wrong characteristic'%self.parent()) + raise ValueError('ring (%s) residue field of the wrong characteristic' % self.parent()) if exactzero((self).ordp): raise ValueError("unit part of 0 not defined") cdef Integer val = Integer.__new__(Integer) @@ -1968,7 +1968,7 @@ cdef class pAdicConvert_CR_QQ(RingMap): 1/5 """ cdef Rational ans = Rational.__new__(Rational) - cdef CRElement x = _x + cdef CRElement x = _x if x.relprec == 0: mpq_set_ui(ans.value, 0, 1) else: @@ -2522,6 +2522,7 @@ cdef class pAdicConvert_CR_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_cre_v2(cls, parent, unit, ordp, relprec): """ Unpickles a capped relative element. diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index 3bae827a08c..e319255a85c 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -84,7 +84,7 @@ cdef class FMElement(pAdicTemplateElement): polyt = type(self.prime_pow.modulus) self.value = polyt.__new__(polyt) cconstruct(self.value, self.prime_pow) - if isinstance(x,FMElement) and x.parent() is self.parent(): + if isinstance(x, FMElement) and x.parent() is self.parent(): cshift_notrunc(self.value, (x).value, 0, 0, self.prime_pow, False) else: cconv(self.value, x, self.prime_pow.ram_prec_cap, 0, self.prime_pow) @@ -346,7 +346,6 @@ cdef class FMElement(pAdicTemplateElement): creduce(q.value, q.value, pcap, q.prime_pow) return q, r - def __pow__(FMElement self, _right, dummy): # NOTE: dummy ignored, always use self.prime_pow.ram_prec_cap """ Exponentiation by an integer @@ -381,7 +380,7 @@ cdef class FMElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _lshift_c(self, long shift): - """ + r""" Multiplies self by `\pi^{shift}`. If shift < -self.valuation(), digits will be truncated. See @@ -428,7 +427,7 @@ cdef class FMElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _rshift_c(self, long shift): - """ + r""" Divides by `\pi^{shift}`, and truncates. Note that this operation will insert arbitrary digits (in @@ -462,7 +461,7 @@ cdef class FMElement(pAdicTemplateElement): return ans def add_bigoh(self, absprec): - """ + r""" Return a new element truncated modulo `\pi^{\mbox{absprec}}`. INPUT: @@ -1542,6 +1541,7 @@ cdef class pAdicConvert_FM_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_fme_v2(cls, parent, value): """ Unpickles a fixed-mod element. diff --git a/src/sage/rings/padics/FP_template.pxi b/src/sage/rings/padics/FP_template.pxi index d253d208410..695e66e2712 100644 --- a/src/sage/rings/padics/FP_template.pxi +++ b/src/sage/rings/padics/FP_template.pxi @@ -142,7 +142,7 @@ cdef class FPElement(pAdicTemplateElement): self._set_infinity() else: self.ordp = val - if isinstance(x,FPElement) and x.parent() is self.parent(): + if isinstance(x, FPElement) and x.parent() is self.parent(): ccopy(self.unit, (x).unit, self.prime_pow) else: cconv(self.unit, x, self.prime_pow.ram_prec_cap, val, self.prime_pow) @@ -584,7 +584,6 @@ cdef class FPElement(pAdicTemplateElement): q._normalize() return q, r - def __pow__(FPElement self, _right, dummy): # NOTE: dummy ignored, always use self.prime_pow.ram_prec_cap """ Exponentiation by an integer @@ -624,8 +623,8 @@ cdef class FPElement(pAdicTemplateElement): _right = -_right exact_exp = True elif self.parent() is _right.parent(): - ## For extension elements, we need to switch to the - ## fraction field sometimes in highly ramified extensions. + # For extension elements, we need to switch to the + # fraction field sometimes in highly ramified extensions. exact_exp = (_right)._is_exact_zero() pright = _right else: @@ -665,7 +664,7 @@ cdef class FPElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _lshift_c(self, long shift): - """ + r""" Multiplies self by `\pi^{shift}`. Negative shifts may truncate the result if the parent is not a @@ -718,7 +717,7 @@ cdef class FPElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _rshift_c(self, long shift): - """ + r""" Divides by `\pi^{shift}`. Positive shifts may truncate the result if the parent is not a @@ -772,7 +771,7 @@ cdef class FPElement(pAdicTemplateElement): def _repr_(self, mode=None, do_latex=False): """ - Returns a string representation of this element. + Return a string representation of this element. INPUT: @@ -794,7 +793,7 @@ cdef class FPElement(pAdicTemplateElement): return self.parent()._printer.repr_gen(self, do_latex, mode=mode) def add_bigoh(self, absprec): - """ + r""" Return a new element truncated modulo `\pi^{\mbox{absprec}}`. INPUT: @@ -1221,7 +1220,7 @@ cdef class FPElement(pAdicTemplateElement): ValueError: unit part of 0 and infinity not defined """ if p is not None and p != self.parent().prime(): - raise ValueError('Ring (%s) residue field of the wrong characteristic.'%self.parent()) + raise ValueError('Ring (%s) residue field of the wrong characteristic.' % self.parent()) if huge_val(self.ordp): raise ValueError("unit part of 0 and infinity not defined") cdef Integer valuation = PY_NEW(Integer) @@ -1659,7 +1658,7 @@ cdef class pAdicConvert_FP_QQ(RingMap): 1/5 """ cdef Rational ans = Rational.__new__(Rational) - cdef FPElement x = _x + cdef FPElement x = _x if very_pos_val(x.ordp): mpq_set_ui(ans.value, 0, 1) elif very_neg_val(x.ordp): @@ -2140,6 +2139,7 @@ cdef class pAdicConvert_FP_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_fpe_v2(cls, parent, unit, ordp): """ Unpickles a floating point element. diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index d8d7c7e3c3b..cea226d80c9 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -3231,10 +3231,9 @@ class pAdicExtension_class(UniqueFactory): sage: R = Zp(5,3) sage: S. = ZZ[] - sage: W. = pAdicExtension(R, x^4 - 15) - sage: W + sage: W. = pAdicExtension(R, x^4 - 15); W # needs sage.libs.ntl 5-adic Eisenstein Extension Ring in w defined by x^4 - 15 - sage: W.precision_cap() + sage: W.precision_cap() # needs sage.libs.ntl 12 """ def create_key_and_extra_args(self, base, modulus, prec=None, print_mode=None, diff --git a/src/sage/rings/padics/local_generic_element.pyx b/src/sage/rings/padics/local_generic_element.pyx index 6c78114f395..0db91750eca 100644 --- a/src/sage/rings/padics/local_generic_element.pyx +++ b/src/sage/rings/padics/local_generic_element.pyx @@ -394,8 +394,9 @@ cdef class LocalGenericElement(CommutativeRingElement): unramified_generator = self.parent()(self.parent().residue_field().gen()).lift_to_precision() for c in islice(self.expansion(lift_mode=lift_mode), int(start), int(stop), int(k)): genpow = 1 - if not isinstance(c, list): c = [c] # relevant for the case of base-rings, or one-step - # eisenstein extensions + if not isinstance(c, list): + c = [c] # relevant for the case of base-rings, or one-step + # Eisenstein extensions for d in c: ans += d * genpow * ppow genpow *= unramified_generator diff --git a/src/sage/rings/padics/morphism.pxd b/src/sage/rings/padics/morphism.pxd index acb6ebb98d5..b6afedd2377 100644 --- a/src/sage/rings/padics/morphism.pxd +++ b/src/sage/rings/padics/morphism.pxd @@ -7,4 +7,4 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): cdef long _power cdef long _order - cpdef Element _call_(self,x) + cpdef Element _call_(self, x) diff --git a/src/sage/rings/padics/morphism.pyx b/src/sage/rings/padics/morphism.pyx index 73ae1d53471..b29fc204b43 100644 --- a/src/sage/rings/padics/morphism.pyx +++ b/src/sage/rings/padics/morphism.pyx @@ -157,7 +157,6 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): sage: Frob._repr_short() 'Frob' """ - name = self.domain().variable_name() if self._power == 0: s = "Identity" elif self._power == 1: 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 979f9d54ba5..0f5270a9980 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx @@ -1237,7 +1237,6 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): cdef long self_ordp = self.valuation_c() cdef long self_relprec = self.absprec - self_ordp cdef long threshold # e / (p-1) - cdef long prime_long cdef mpz_t tmp, tmp2 if mpz_fits_slong_p(self.prime_pow.prime.value) == 0: threshold = 0 @@ -1399,7 +1398,6 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): """ cdef pAdicZZpXCAElement right = _right cdef pAdicZZpXCAElement ans - cdef long tmpL cdef ZZ_pX_c tmpP if self.absprec == 0 or right.absprec == 0: return self._new_c(0) @@ -1441,7 +1439,6 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): """ cdef pAdicZZpXCAElement right = _right cdef pAdicZZpXCAElement ans - cdef long tmpL cdef ZZ_pX_c tmpP if self.absprec == 0 or right.absprec == 0: return self._new_c(0) @@ -1824,7 +1821,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): True """ cdef pAdicZZpXCAElement ans - cdef long aprec, rprec + cdef long aprec if absprec is not None and not isinstance(absprec, Integer): absprec = Integer(absprec) if absprec is None: @@ -1977,9 +1974,9 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_modulus_capdiv(self.absprec) cdef ZZ_pX_c x ZZ_pX_SetX(x) - cdef Py_ssize_t i, j + cdef Py_ssize_t i zero = int(0) - for i from 0 <= i < n: + for i in range(n): curlist = cur.list() L.extend(curlist + [zero]*(n - len(curlist))) ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0]) @@ -2071,7 +2068,8 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): cdef long ordp = self.valuation_c() cdef long rp = self.absprec - ordp cdef long goal - if n is not None: goal = self.absprec - n + if n is not None: + goal = self.absprec - n cdef pAdicZZpXCAElement v if n is None: L = [] @@ -2084,7 +2082,8 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): else: v = self._new_c(rp) cdef pAdicZZpXCAElement u = self.unit_part() - if u is self: u = self.__copy__() + if u is self: + u = self.__copy__() while not ZZ_pX_IsZero(u.value): v = self._new_c(rp) self.prime_pow.teichmuller_set_c(&v.value, &u.value, rp) @@ -2092,7 +2091,8 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): L.append(v) elif rp == goal: return v - if rp == 1: break + if rp == 1: + break ZZ_pX_sub(u.value, u.value, v.value) rp -= 1 if self.prime_pow.e == 1: @@ -2319,6 +2319,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): """ return self.ext_p_list_precs(pos, self.absprec) + def make_ZZpXCAElement(parent, value, absprec, version): """ For pickling. Makes a ``pAdicZZpXCAElement`` with given ``parent``, ``value``, ``absprec``. 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 e3bd45e9037..8a8828a5712 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx @@ -1415,13 +1415,9 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): sage: z * 25 3 + O(w^6) """ - cdef ZZ_pX_c high_shifter, high_shifter2 + cdef ZZ_pX_c high_shifter cdef ZZ_pX_Modulus_c *modulus - cdef ZZ_pX_Modulus_c modulus_up cdef ntl_ZZ_pContext_class c - cdef PowComputer_ZZ_pX_small_Eis sm - cdef PowComputer_ZZ_pX_big_Eis big - cdef ntl_ZZ_pX printer cdef ZZ_pX_c* high_array cdef long i, high_length if self.prime_pow.e == 1: @@ -1922,7 +1918,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): cdef long exp_val cdef long relprec cdef long threshold # e / (p-1) - cdef long prime_long cdef mpz_t tmp, tmp2 if mpz_fits_slong_p(self.prime_pow.prime.value) == 0: threshold = 0 @@ -2212,7 +2207,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): """ cdef pAdicZZpXCRElement right = _right cdef ZZ_pX_c modulus_corrected - cdef ntl_ZZ_pContext_class ctx cdef pAdicZZpXCRElement ans if self._is_exact_zero(): return self @@ -2805,7 +2799,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): return zero elif n >= self.ordp + self.relprec: raise PrecisionError - cdef Integer ordp if self.relprec == 0: # cannot have n = None return [] if lift_mode == 'simple': @@ -2881,11 +2874,11 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_modulus_capdiv(self.ordp + self.relprec) cdef ZZ_pX_c x ZZ_pX_SetX(x) - cdef Py_ssize_t i, j + cdef Py_ssize_t i zero = int(0) - for i from 0 <= i < n: + for i in range(n): curlist = cur.list() - L.extend(curlist + [zero]*(n - len(curlist))) + L.extend(curlist + [zero] * (n - len(curlist))) ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0]) return matrix(R, n, n, L) 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 9dec3affd53..ec5e833662f 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -197,7 +197,6 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): pAdicZZpXElement.__init__(self, parent) if empty: return - cdef mpz_t tmp cdef ZZ_c tmp_z cdef Integer tmp_Int cdef Py_ssize_t i @@ -241,7 +240,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): poly = x.polynomial().list() x = sum([poly[i].lift() * (z ** i) for i in range(len(poly))], parent.zero()) elif isinstance(x, ntl_ZZ_p): - ctx_prec = ZZ_remove(tmp_z, (x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0]) + ZZ_remove(tmp_z, (x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0]) if ZZ_IsOne(tmp_z): x = x.lift() tmp_Int = Integer.__new__(Integer) @@ -613,12 +612,9 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): """ if n < 0: return self._lshift_c(-n) - elif n == 0: + if n == 0: return self cdef pAdicZZpXFMElement ans = self._new_c() - cdef Py_ssize_t i - cdef long topcut, rem - cdef ntl_ZZ holder if n < self.prime_pow.ram_prec_cap: if self.prime_pow.e == 1: ZZ_pX_right_pshift(ans.value, self.value, self.prime_pow.pow_ZZ_tmp(n)[0], self.prime_pow.get_top_context().x) @@ -1034,9 +1030,9 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_top_modulus() cdef ZZ_pX_c x ZZ_pX_SetX(x) - cdef Py_ssize_t i, j + cdef Py_ssize_t i zero = int(0) - for i from 0 <= i < n: + for i in range(n): curlist = cur.list() L.extend(curlist + [zero]*(n - len(curlist))) ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0]) @@ -1443,7 +1439,8 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): cdef long ordp = self.valuation_c() cdef long rp = self.prime_pow.ram_prec_cap - ordp cdef long goal - if n is not None: goal = self.ram_prec_cap - n + if n is not None: + goal = self.ram_prec_cap - n cdef pAdicZZpXFMElement v if n is None: L = [] @@ -1454,15 +1451,18 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): else: v = self._new_c() cdef pAdicZZpXFMElement u = self.unit_part() - if u is self: u = self.__copy__() + if u is self: + u = self.__copy__() while u.valuation_c() < rp: - if n is None: v = self._new_c() + if n is None: + v = self._new_c() self.prime_pow.teichmuller_set_c(&v.value, &u.value, self.prime_pow.ram_prec_cap) if n is None: L.append(v) elif rp == goal: return v - if rp == 1: break + if rp == 1: + break ZZ_pX_sub(u.value, u.value, v.value) rp -= 1 if self.prime_pow.e == 1: diff --git a/src/sage/rings/padics/padic_ZZ_pX_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_element.pyx index b0beaa85617..b23f010edde 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_element.pyx @@ -284,7 +284,6 @@ cdef class pAdicZZpXElement(pAdicExtElement): cdef Integer list_elt cdef ZZ_c halfp cdef Py_ssize_t i, j - cdef ZZ_p_c const_term_holder self.prime_pow.restore_top_context() ###ZZ_p_construct(&const_term_holder) cdef ntl_ZZ holder = ntl_ZZ() @@ -621,6 +620,7 @@ def _test_preprocess_list(R, L): """ return preprocess_list(R(0), L) + cdef preprocess_list(pAdicZZpXElement elt, L): """ See the documentation for :func:`_test_preprocess_list`. @@ -630,7 +630,6 @@ cdef preprocess_list(pAdicZZpXElement elt, L): cdef ntl_ZZ_pContext_class ctx cdef ntl_ZZ pshift_z cdef Integer pshift_m - cdef long aprec cdef ntl_ZZ py_tmp if not isinstance(L, list): raise TypeError("L must be a list") diff --git a/src/sage/rings/padics/padic_capped_relative_element.pyx b/src/sage/rings/padics/padic_capped_relative_element.pyx index f09708db2c7..10db90d1342 100644 --- a/src/sage/rings/padics/padic_capped_relative_element.pyx +++ b/src/sage/rings/padics/padic_capped_relative_element.pyx @@ -576,6 +576,7 @@ def unpickle_pcre_v1(R, unit, ordp, relprec): """ return unpickle_cre_v2(pAdicCappedRelativeElement, R, unit, ordp, relprec) + def base_p_list(Integer n, bint pos, PowComputer_class prime_pow): r""" Return a base-`p` list of digits of ``n``. diff --git a/src/sage/rings/padics/padic_extension_generic.py b/src/sage/rings/padics/padic_extension_generic.py index 88027e19439..dc80e998bcd 100644 --- a/src/sage/rings/padics/padic_extension_generic.py +++ b/src/sage/rings/padics/padic_extension_generic.py @@ -19,10 +19,11 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +import sage.rings.abc + from .padic_generic import pAdicGeneric, ResidueLiftingMap from .padic_base_generic import pAdicBaseGeneric from sage.rings.number_field.number_field_base import NumberField -from sage.rings.number_field.order import Order from sage.rings.rational_field import QQ from sage.rings.infinity import Infinity from sage.structure.richcmp import op_EQ @@ -223,7 +224,7 @@ def _convert_map_from_(self, R): cat = R.category() else: cat = EuclideanDomains() & MetricSpaces().Complete() - elif isinstance(R, Order) and R.number_field().defining_polynomial() == self.defining_polynomial(): + elif isinstance(R, sage.rings.abc.Order) and R.number_field().defining_polynomial() == self.defining_polynomial(): cat = IntegralDomains() elif isinstance(R, NumberField) and R.defining_polynomial() == self.defining_polynomial(): if self.is_field(): @@ -375,7 +376,8 @@ def exact_ring(self): """ Return the order with the same defining polynomial. - Will raise a ValueError if the coefficients of the defining polynomial are not integral. + Will raise a :class:`ValueError` if the coefficients of the defining + polynomial are not integral. EXAMPLES:: diff --git a/src/sage/rings/padics/padic_extension_leaves.py b/src/sage/rings/padics/padic_extension_leaves.py index ed171e833e4..bf5599f7c59 100644 --- a/src/sage/rings/padics/padic_extension_leaves.py +++ b/src/sage/rings/padics/padic_extension_leaves.py @@ -20,11 +20,13 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.integer_mod_ring import Zmod -from .pow_computer_ext import PowComputer_ext_maker -from .pow_computer_flint import PowComputer_flint_maker -from sage.libs.ntl.ntl_ZZ_pX import ntl_ZZ_pX + +lazy_import('sage.rings.padics.pow_computer_ext', 'PowComputer_ext_maker') +lazy_import('sage.rings.padics.pow_computer_flint', 'PowComputer_flint_maker') +lazy_import('sage.libs.ntl.ntl_ZZ_pX', 'ntl_ZZ_pX') from .unramified_extension_generic import UnramifiedExtensionGeneric from .eisenstein_extension_generic import EisensteinExtensionGeneric @@ -47,13 +49,21 @@ #from padic_general_extension_capped_relative_element import pAdicGeneralExtensionCappedRelativeElement #from padic_general_extension_lazy_element import pAdicGeneralExtensionRelaxedElement -from .padic_ZZ_pX_FM_element import pAdicZZpXFMElement -from .padic_ZZ_pX_CR_element import pAdicZZpXCRElement -from .padic_ZZ_pX_CA_element import pAdicZZpXCAElement -from .qadic_flint_CR import qAdicCappedRelativeElement -from .qadic_flint_CA import qAdicCappedAbsoluteElement -from .qadic_flint_FM import qAdicFixedModElement -from .qadic_flint_FP import qAdicFloatingPointElement +try: + from .padic_ZZ_pX_FM_element import pAdicZZpXFMElement + from .padic_ZZ_pX_CR_element import pAdicZZpXCRElement + from .padic_ZZ_pX_CA_element import pAdicZZpXCAElement +except ImportError: + pass + +try: + from .qadic_flint_CR import qAdicCappedRelativeElement + from .qadic_flint_CA import qAdicCappedAbsoluteElement + from .qadic_flint_FM import qAdicFixedModElement + from .qadic_flint_FP import qAdicFloatingPointElement +except ImportError: + pass + def _make_integral_poly(exact_modulus, p, prec): """ diff --git a/src/sage/rings/padics/padic_floating_point_element.pyx b/src/sage/rings/padics/padic_floating_point_element.pyx index d6153a1f673..32c8e25cde2 100644 --- a/src/sage/rings/padics/padic_floating_point_element.pyx +++ b/src/sage/rings/padics/padic_floating_point_element.pyx @@ -144,7 +144,8 @@ cdef class pAdicFloatingPointElement(FPElement): precision. If a rational is returned, its denominator will equal ``p^ordp(self)``. - This method will raise a ValueError when this element is infinity. + This method will raise a :class:`ValueError` when this element + is infinity. EXAMPLES:: diff --git a/src/sage/rings/padics/padic_printing.pyx b/src/sage/rings/padics/padic_printing.pyx index 344a1e544a7..aef767034a8 100644 --- a/src/sage/rings/padics/padic_printing.pyx +++ b/src/sage/rings/padics/padic_printing.pyx @@ -928,7 +928,6 @@ cdef class pAdicPrinter_class(SageObject): sage: repr(R(0,10)) '...0000000000' """ - cdef Py_ssize_t i s = "" if self.show_prec == "dots": unknown_digit = "?" @@ -1063,10 +1062,8 @@ cdef class pAdicPrinter_class(SageObject): """ cdef Integer lift_z, pprec cdef int ZZ_pEX - cdef Py_ssize_t i, j + cdef Py_ssize_t i cdef long val - #cdef bint ellipsis = 0 - cdef ellipsis_unram cdef bint integral var_name = self.latex_var_name if do_latex else self.var_name if self.base: @@ -1200,10 +1197,10 @@ cdef class pAdicPrinter_class(SageObject): s += " - " s += self._var(var_name, i, do_latex) else: - s += " - %s"%(arep) + s += " - %s" % (arep) s += self._dot_var(var_name, i, do_latex) elif a == pk: - if s != "": + if s: s += " + " s += self._var(var_name, i, do_latex) else: @@ -1211,9 +1208,9 @@ cdef class pAdicPrinter_class(SageObject): v, u = a.val_unit(self.prime_pow.prime) arep = self._terse_frac(a, v, u, ram_name, do_latex) if s == "": - s = "%s"%arep + s = "%s" % arep else: - s += " + %s"%arep + s += " + %s" % arep s += self._dot_var(var_name, i, do_latex) if ellipsis: s += self._plus_ellipsis(do_latex) diff --git a/src/sage/rings/padics/padic_relaxed_errors.pyx b/src/sage/rings/padics/padic_relaxed_errors.pyx index ddadb111ca9..2157234f62b 100644 --- a/src/sage/rings/padics/padic_relaxed_errors.pyx +++ b/src/sage/rings/padics/padic_relaxed_errors.pyx @@ -5,23 +5,23 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ # **************************************************************************** from sage.rings.padics.precision_error import PrecisionError -cdef inline int ERROR_ABANDON = 1 -cdef inline int ERROR_NOTDEFINED = 1 << 1 -cdef inline int ERROR_PRECISION = 1 << 2 -cdef inline int ERROR_OVERFLOW = 1 << 3 -cdef inline int ERROR_NOTSQUARE = 1 << 4 # maybe we should have something more generic here -cdef inline int ERROR_INTEGRAL = 1 << 5 -cdef inline int ERROR_DIVISION = 1 << 6 -cdef inline int ERROR_CIRCULAR = 1 << 7 +cdef inline int ERROR_ABANDON = 1 +cdef inline int ERROR_NOTDEFINED = 1 << 1 +cdef inline int ERROR_PRECISION = 1 << 2 +cdef inline int ERROR_OVERFLOW = 1 << 3 +cdef inline int ERROR_NOTSQUARE = 1 << 4 # maybe we should have something more generic here +cdef inline int ERROR_INTEGRAL = 1 << 5 +cdef inline int ERROR_DIVISION = 1 << 6 +cdef inline int ERROR_CIRCULAR = 1 << 7 -cdef inline int ERROR_UNEXPECTED = 1 << 30 +cdef inline int ERROR_UNEXPECTED = 1 << 30 def raise_error(error, permissive=False): diff --git a/src/sage/rings/padics/padic_template_element.pxi b/src/sage/rings/padics/padic_template_element.pxi index 06cc00e73f0..06d65d1672c 100644 --- a/src/sage/rings/padics/padic_template_element.pxi +++ b/src/sage/rings/padics/padic_template_element.pxi @@ -146,7 +146,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): x = [x] elif sage.rings.finite_rings.integer_mod.is_IntegerMod(x): if not Integer(self.prime_pow.prime).divides(x.parent().order()): - raise TypeError("p does not divide modulus %s"%x.parent().order()) + raise TypeError("p does not divide modulus %s" % x.parent().order()) elif isinstance(x, Element) and isinstance(x.parent(), FiniteField): k = self.parent().residue_field() if not k.has_coerce_map_from(x.parent()): @@ -624,7 +624,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): return trim_zeros(list(self.unit_part().expansion(lift_mode='smallest'))) cpdef pAdicTemplateElement unit_part(self): - """ + r""" Returns the unit part of this element. This is the `p`-adic element `u` in the same ring so that this @@ -739,7 +739,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): if check_prec and (R.is_fixed_mod() or R.is_floating_point()): check_prec = False if check_prec and absprec > self.precision_absolute(): - raise PrecisionError("insufficient precision to reduce modulo p^%s"%absprec) + raise PrecisionError("insufficient precision to reduce modulo p^%s" % absprec) if field and absprec != 1: raise ValueError("field keyword may only be set at precision 1") if absprec == 0: @@ -834,15 +834,15 @@ cdef long padic_pow_helper(celement result, celement base, long base_val, long b """ if base_val != 0: raise ValueError("in order to raise to a p-adic exponent, base must be a unit") - ####### NOTE: this function needs to be updated for extension elements. ####### + # TODO NOTE: this function needs to be updated for extension elements. cdef long loga_val, loga_aprec, bloga_val, bloga_aprec cdef Integer expcheck, right cteichmuller(prime_pow.powhelper_oneunit, base, base_relprec, prime_pow) cdivunit(prime_pow.powhelper_oneunit, base, prime_pow.powhelper_oneunit, base_relprec, prime_pow) csetone(prime_pow.powhelper_teichdiff, prime_pow) csub(prime_pow.powhelper_teichdiff, prime_pow.powhelper_oneunit, prime_pow.powhelper_teichdiff, base_relprec, prime_pow) - ## For extension elements in ramified extensions, the computation of the - ## valuation and precision of log(a) is more complicated) + # For extension elements in ramified extensions, the computation of the + # valuation and precision of log(a) is more complicated) loga_val = cvaluation(prime_pow.powhelper_teichdiff, base_relprec, prime_pow) loga_aprec = base_relprec # valuation of b*log(a) @@ -862,8 +862,8 @@ cdef long padic_pow_helper(celement result, celement base, long base_val, long b # Here we need to use the exp(b log(a)) definition, # since we can't convert the exponent to an integer raise NotImplementedError("exponents with negative valuation not yet supported") - ## For extension elements in ramified extensions - ## the following precision might need to be changed. + # For extension elements in ramified extensions + # the following precision might need to be changed. cpow(result, prime_pow.powhelper_oneunit, right.value, bloga_aprec, prime_pow) return bloga_aprec @@ -1185,5 +1185,4 @@ cdef class ExpansionIterable(): else: modestr = " (teichmuller)" p = self.elt.prime_pow.prime - return "%s-adic expansion of %s%s"%(p, self.elt, modestr) - + return "%s-adic expansion of %s%s" % (p, self.elt, modestr) diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py index b6ea2ea75ee..90e9d205ac5 100644 --- a/src/sage/rings/padics/padic_valuation.py +++ b/src/sage/rings/padics/padic_valuation.py @@ -256,7 +256,7 @@ def create_key_and_extra_args_for_number_field_from_valuation(self, R, v, prime, else: raise NotImplementedError("cannot rewrite %r which is defined on %r as a pseudo-valuation on %r" % (v, v.domain(), G.parent())) - assert(v.domain() is G.parent()) + assert (v.domain() is G.parent()) # To obtain uniqueness of p-adic valuations, we need a canonical # description of v. We consider all extensions of vK to L and select @@ -397,11 +397,11 @@ def create_object(self, version, key, **extra_args): R = key[0] parent = DiscretePseudoValuationSpace(R) if isinstance(R, pAdicGeneric): - assert(len(key) == 1) + assert (len(key) == 1) return parent.__make_element_class__(pAdicValuation_padic)(parent) elif R is ZZ or R is QQ: prime = key[1] - assert(len(key) == 2) + assert (len(key) == 2) return parent.__make_element_class__(pAdicValuation_int)(parent, prime) else: v = key[1] @@ -1281,7 +1281,7 @@ def simplify(self, x, error=None, force=False, size_heuristic_bound=32): if self._relative_size(rational) < self._relative_size(best): best = rational - assert(self(x-best) > error) + assert (self(x-best) > error) return best diff --git a/src/sage/rings/padics/pow_computer.pyx b/src/sage/rings/padics/pow_computer.pyx index 1c5bdf86897..4c05f1886b5 100644 --- a/src/sage/rings/padics/pow_computer.pyx +++ b/src/sage/rings/padics/pow_computer.pyx @@ -35,7 +35,7 @@ AUTHORS: # 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 weakref @@ -186,7 +186,6 @@ cdef class PowComputer_class(SageObject): 59049 """ cdef Integer _n = Integer(n) - cdef Integer ans if _n < 0: if mpz_fits_ulong_p((-_n).value) == 0: raise ValueError("result too big") @@ -210,7 +209,7 @@ cdef class PowComputer_class(SageObject): See pow_mpz_t_tmp_demo for an example of this phenomenon. """ - ## READ THE DOCSTRING + # READ THE DOCSTRING raise NotImplementedError def _pow_mpz_t_tmp_demo(self, m, n): @@ -319,7 +318,7 @@ cdef class PowComputer_class(SageObject): sage: PC = PowComputer(3, 5, 10); PC PowComputer for 3 """ - return "PowComputer for %s"%(self.prime) + return "PowComputer for %s" % (self.prime) def _prime(self): """ @@ -411,8 +410,7 @@ cdef class PowComputer_class(SageObject): sage: P(-2) 1/9 """ - cdef Integer z, _n - cdef mpz_t tmp + cdef Integer _n if n is infinity: return Integer(0) if not isinstance(n, Integer): @@ -496,12 +494,10 @@ cdef class PowComputer_base(PowComputer_class): sage: PC = PowComputer(5, 7, 10) sage: PC(3) 125 - """ PowComputer_class.__init__(self, prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, shift_seed) cdef Py_ssize_t i - cdef Integer x mpz_set_ui(self.small_powers[0], 1) if cache_limit > 0: @@ -634,6 +630,7 @@ cdef PowComputer_base PowComputer_c(Integer m, Integer cache_limit, Integer prec pow_comp_cache[key] = weakref.ref(PC) return PC + # To speed up the creation of PowComputers with the same m, we might eventually want to copy over data from an existing PowComputer. def PowComputer(m, cache_limit, prec_cap, in_field = False, prec_type=None): diff --git a/src/sage/rings/padics/pow_computer_ext.pxd b/src/sage/rings/padics/pow_computer_ext.pxd index e87f801971f..114696b34fa 100644 --- a/src/sage/rings/padics/pow_computer_ext.pxd +++ b/src/sage/rings/padics/pow_computer_ext.pxd @@ -105,4 +105,3 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): # cdef context_dict #currently using a dict, optimize for speed later # cdef modulus_dict #currently using a dict, optimize for speed later # - diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index 1626990a051..3d47d3af2f9 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -191,8 +191,7 @@ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) excep raise TypeError("unrecognized Eisenstein type") cdef long i - cdef ZZ_pX_c tmp, modup, into_multiplier, shift_seed_inv - cdef ZZ_c a + cdef ZZ_pX_c into_multiplier, shift_seed_inv # We obtain successive p/x^(2^i) by squaring and then dividing by p. So we need one extra digit of precision. prime_pow.restore_top_context() #cdef ntl_ZZ_pContext_class cup = prime_pow.get_context(prime_pow.prec_cap + low_length) @@ -320,7 +319,6 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long cdef ZZ_pX_c low_part cdef ZZ_pX_c shifted_high_part cdef ZZ_pX_c powerx - cdef ZZ_pX_c shifter cdef ZZ_pX_c lowshift cdef ZZ_pX_c highshift cdef ZZ_pX_c working, working2 @@ -354,7 +352,6 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long else: raise TypeError("inconsistent type") - cdef ntl_ZZ_pX printer if n < 0: if fm: c = self.get_top_context() @@ -478,7 +475,6 @@ cdef class PowComputer_ext(PowComputer_class): raise MemoryError("out of memory allocating power storing") cdef Py_ssize_t i - cdef Integer x ZZ_conv_from_int(self.small_powers[0], 1) @@ -1574,7 +1570,6 @@ cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX): self.cleanup_ext() raise MemoryError("out of memory allocating moduli") - cdef ntl_ZZ_pX printer cdef Py_ssize_t i cdef ZZ_pX_c tmp, pol if isinstance(poly, ntl_ZZ_pX): diff --git a/src/sage/rings/padics/pow_computer_relative.pyx b/src/sage/rings/padics/pow_computer_relative.pyx index 2253281bd35..fc51eb3410f 100644 --- a/src/sage/rings/padics/pow_computer_relative.pyx +++ b/src/sage/rings/padics/pow_computer_relative.pyx @@ -150,14 +150,16 @@ cdef class PowComputer_relative(PowComputer_class): Relative PowComputer for modulus x^3 + 5*x + a*5 """ - return "Relative PowComputer for modulus %s"%(self.modulus,) + return "Relative PowComputer for modulus %s" % (self.modulus,) cdef unsigned long capdiv(self, unsigned long n): r""" Return `\lceil n/e \rceil`. """ - if self.e == 1: return n - if n == 0: return 0 + if self.e == 1: + return n + if n == 0: + return 0 return (n - 1)/self.e + 1 def polynomial(self, n=None, var='x'): diff --git a/src/sage/rings/padics/qadic_flint_FP.pyx b/src/sage/rings/padics/qadic_flint_FP.pyx index 020b03b722a..36e898c8590 100644 --- a/src/sage/rings/padics/qadic_flint_FP.pyx +++ b/src/sage/rings/padics/qadic_flint_FP.pyx @@ -108,7 +108,6 @@ cdef class qAdicFloatingPointElement(FPElement): cshift_notrunc(self.prime_pow.poly_flint_rep, self.unit, self.ordp, self.ordp + self.prime_pow.prec_cap, self.prime_pow, False) return self.prime_pow._new_fmpz_poly(self.prime_pow.poly_flint_rep, var), Integer(0) - def _modp_rep(self, use_smallest_mode=False, return_list=True): r""" Return the element with the same reduction mod p that can be expressed diff --git a/src/sage/rings/padics/relaxed_template.pxi b/src/sage/rings/padics/relaxed_template.pxi index a18ffb1cb03..751e42700f0 100644 --- a/src/sage/rings/padics/relaxed_template.pxi +++ b/src/sage/rings/padics/relaxed_template.pxi @@ -948,11 +948,12 @@ cdef class RelaxedElement(pAdicGenericElement): return Integer(self._precrel + self._valuation) def precision_relative(self): - """ + r""" Return the relative precision of this element. This is the power of `p` modulo which the unit part of this element is known. + For unbounded nonzero elements, this methods return `+\infty`. EXAMPLES:: @@ -3056,7 +3057,6 @@ cdef class RelaxedElement_sub(RelaxedElementWithDigits): return 0 - # Multiplication cdef class RelaxedElement_mul(RelaxedElementWithDigits): @@ -3684,7 +3684,7 @@ cdef class RelaxedElement_teichmuller(RelaxedElementWithDigits): p = self.prime_pow.prime size = mpz_sizeinbase(p.value, 2) i = size - 2 - self._xns = [ ] + self._xns = [] while i >= 0: xn = element_class_mul(parent, xn, xn) self._xns.append(xn) @@ -3801,7 +3801,7 @@ cdef class RelaxedElement_unknown(RelaxedElementWithDigits): self._next = maxordp cdef cdigit digit if digits is not None: - digits = [ Integer(d) for d in digits ] + digits = [Integer(d) for d in digits] for d in digits: digit_set_sage(digit, d) element_iadd_digit(self._digits, digit, self._precrel) @@ -3828,7 +3828,7 @@ cdef class RelaxedElement_unknown(RelaxedElementWithDigits): sage: x == loads(dumps(x)) # indirect doctest True """ - digits = [ ] + digits = [] for i in range(self._initialprecrel): digits.append(digit_get_sage(element_get_digit(self._digits, i))) definition = None @@ -3933,6 +3933,7 @@ cdef class RelaxedElement_unknown(RelaxedElementWithDigits): self._next = svenext return error + def unpickle_unknown(uid, cls, parent, valuation, digits, definition): r""" Unpickle a self-referent relaxed `p`-adic number. @@ -4084,7 +4085,7 @@ cdef class ExpansionIter(): self._next_smallest() elif self.mode == teichmuller_mode: self.tail = elt - self.coefficients = { } + self.coefficients = {} while self.current < self.start: self._next_teichmuller() diff --git a/src/sage/rings/padics/unramified_extension_generic.py b/src/sage/rings/padics/unramified_extension_generic.py index b73b88ebc1c..6892c7fbddf 100644 --- a/src/sage/rings/padics/unramified_extension_generic.py +++ b/src/sage/rings/padics/unramified_extension_generic.py @@ -225,12 +225,12 @@ def _frob_gen(self, arithmetic=True): exp = p a = self.gen() if not arithmetic: - exp = p**(self.absolute_degree()-1) + exp = p**(self.absolute_degree() - 1) approx = (self(a.residue()**exp)).lift_to_precision(self.precision_cap()) #first approximation f = self.defining_polynomial() g = f.derivative() - while(f(approx) != 0): #hensel lift frobenius(a) - approx = approx - f(approx)/g(approx) + while f(approx) != 0: # hensel lift frobenius(a) + approx = approx - f(approx) / g(approx) return approx def uniformizer_pow(self, n): diff --git a/src/sage/rings/pari_ring.py b/src/sage/rings/pari_ring.py index 98b42c2634a..b44ee143680 100644 --- a/src/sage/rings/pari_ring.py +++ b/src/sage/rings/pari_ring.py @@ -123,7 +123,7 @@ def __pow__(self, other): sage: a^2 9 """ - if not(other in PariRing()): + if not (other in PariRing()): other = Pari(other) return self.__class__(self.__x ** other.__x, parent=_inst) diff --git a/src/sage/rings/polynomial/binary_form_reduce.py b/src/sage/rings/polynomial/binary_form_reduce.py index fb60089a751..1a9896f2199 100644 --- a/src/sage/rings/polynomial/binary_form_reduce.py +++ b/src/sage/rings/polynomial/binary_form_reduce.py @@ -418,7 +418,7 @@ def get_bound_poly(F, prec=53, norm_type='norm', emb=None): else: compF = F n = F.degree() - assert(n > 2), "degree 2 polynomial" + assert (n > 2), "degree 2 polynomial" z0F, thetaF = covariant_z0(compF, prec=prec, emb=emb) if norm_type == 'norm': diff --git a/src/sage/rings/polynomial/infinite_polynomial_element.py b/src/sage/rings/polynomial/infinite_polynomial_element.py index fc8449b340e..760c0dd57ab 100644 --- a/src/sage/rings/polynomial/infinite_polynomial_element.py +++ b/src/sage/rings/polynomial/infinite_polynomial_element.py @@ -952,7 +952,7 @@ def symmetric_cancellation_order(self, other): for i in Lsmall: # i is a shift of the smaller polynomial j += 1 ExpoSmall = Fsmall[i] - while (j < lenBig): + while j < lenBig: found = False if Lbig[j] >= i: ExpoBigSave = [e for e in Fbig[Lbig[j]]] diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index c9903625b38..16c8c09fbc3 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -2107,7 +2107,7 @@ cdef class NCPolynomial_plural(RingElement): raise TypeError("The input degrees must be a dictionary of variables to exponents.") # Extract the monomials that match the specifications - while(p): + while p: flag = 0 for i from 0<=iself._parent)._base) p = pNext(p) @@ -2363,7 +2363,7 @@ cdef class NCPolynomial_plural(RingElement): i += 1 p_Setm(m, r) - while(p): + while p: if p_ExpVectorEqual(p, m, r) == 1: p_Delete(&m,r) return si2sa(p_GetCoeff(p, r), r, (self._parent)._base) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 1f447fc1287..58a6a4d2308 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -1267,14 +1267,14 @@ def hensel_lift(self, a): # Newton iteration # Todo: compute everything up to the adequate precision at each step b = ~dera - while(True): + while True: na = a - selfa * b if na == a: return a a = na selfa = self(a) dera = der(a) - b *= 2 - dera*b + b *= 2 - dera * b def _factor_of_degree(self, deg): """ diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index e372be888ee..99d90a5c8f7 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -2099,10 +2099,10 @@ def _isomorphic_ring(self): basis = [self.gen()**i*self.base_ring().gen()**j for i in range(self.degree()) for j in range(self.base_ring().degree())] - assert(len(basis) == isomorphic_ring.degree()) + assert (len(basis) == isomorphic_ring.degree()) from sage.matrix.constructor import matrix A = matrix([to_isomorphic_ring(b)._vector_() for b in basis]) - assert(A.is_square()) + assert (A.is_square()) # solve x*A = (0,1,0,…,0) x = A.solve_left(A.column_space().basis()[1]) primitive_element = sum(c*b for c,b in zip(x.list(), basis)) diff --git a/src/sage/rings/polynomial/real_roots.pyx b/src/sage/rings/polynomial/real_roots.pyx index 4b5ebac6d8e..97af8b60ffd 100644 --- a/src/sage/rings/polynomial/real_roots.pyx +++ b/src/sage/rings/polynomial/real_roots.pyx @@ -490,7 +490,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): sage: bp """ - assert(len(coeffs) > 0) + assert len(coeffs) > 0 self.coeffs = coeffs self.lower = lower self.upper = upper @@ -641,7 +641,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): count_maybe_neg = 0 sign = 0 - for i from 1 <= i < n: + for i in range(1, n): lower_sgn = mpz_sgn(c._entries[i]) upper_sgn = mpz_cmp_si(c._entries[i], -self.error) new_count_maybe_pos = count_maybe_pos @@ -679,7 +679,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): cdef int degree(self): """ - Returns the (formal) degree of this polynomial. + Return the (formal) degree of this polynomial. """ return len(self.coeffs) - 1 @@ -735,7 +735,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): if msign == 0: msign = sign elif sign != 0: - assert(msign == sign) + assert msign == sign cdef Rational absolute_mid = self.lower + mid * (self.upper - self.lower) @@ -776,7 +776,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): def get_msb_bit(self): """ - Returns an approximation of the log2 of the maximum of the + Return an approximation of the log2 of the maximum of the absolute values of the coefficients, as an integer. """ return self.scale_log2 + self.bitsize @@ -916,7 +916,8 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): while True: next = degree_reduction_next_size(bp.degree()) - if next is None: return bp + if next is None: + return bp if bp.variations()[0] > next: return bp (rbp, err_info) = bp.down_degree(ctx, Integer(1) << (max_scale - bp.scale_log2), 32) @@ -971,6 +972,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): rng = rng >> (-self.scale_log2) return rng + def mk_ibpi(coeffs, lower=0, upper=1, lsign=0, usign=0, error=1, scale_log2=0, level=0, slope_err=RIF(0)): """ @@ -987,6 +989,7 @@ def mk_ibpi(coeffs, lower=0, upper=1, lsign=0, usign=0, error=1, scale_log2=0, """ return interval_bernstein_polynomial_integer(vector(ZZ, coeffs), QQ(lower), QQ(upper), lsign, usign, error, scale_log2, level, slope_err) + def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int use_ints): """ Given a polynomial in Bernstein form with integer coefficients @@ -1117,7 +1120,8 @@ def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int u den_log2 = mpz_sizeinbase(den, 2) - 1 cdef int max_den_bits = c_bitsize / 2 - if max_den_bits < 100: max_den_bits = 100 + if max_den_bits < 100: + max_den_bits = 100 # These settings are slower than the above on laguerre(1000), but that's # the only experiment I've done so far... more testing is needed. # cdef int max_den_bits = 3 * c_bitsize / 2 @@ -1131,21 +1135,21 @@ def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int u den_powers = FreeModule(ZZ, len(c)+1)(0) mpz_set_ui(den_powers._entries[0], 1) max_den_power = 1 - for i from 1 <= i <= n: + for i in range(1, n + 1): mpz_mul_ui(den_powers._entries[i], den_powers._entries[i-1], den_ui) if mpz_sizeinbase(den_powers._entries[i], 2) < max_den_bits: max_den_power = i else: break - for i from 0 <= i < n: + for i in range(n): mpz_set(c1._entries[i], c2._entries[0]) if den_ui == 2: # x == 1/2 - for j from 0 <= j < n-i-1: + for j in range(n-i-1): mpz_add(c2._entries[j], c2._entries[j], c2._entries[j+1]) else: - for j from 0 <= j < n-i-1: + for j in range(n-i-1): if diff_ui != 1: mpz_mul_ui(c2._entries[j], c2._entries[j], diff_ui) if num_ui == 1: @@ -1185,14 +1189,13 @@ def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int u # this is equal to a + num*(b-a)/den or diff*(a-b)/den + b. # If num max_exp: max_exp = cur_exp @@ -1308,9 +1309,8 @@ def intvec_to_doublevec(Vector_integer_dense b, long err): cdef int delta = -max_exp cdef double d cdef int new_exp - cdef double half = 0.5 - for i from 0 <= i < len(b): + for i in range(len(b)): d = mpz_get_d_2exp(&cur_exp, b._entries[i]) # 0.5 <= d < 1; b._entries[i] ~= d*2^cur_exp new_exp = cur_exp + delta @@ -1400,7 +1400,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): sage: bp """ - assert(len(coeffs) > 0) + assert len(coeffs) > 0 cdef numpy.ndarray[double, ndim=1] coeffs_data = coeffs._vector_numpy self.coeffs = coeffs self.lower = lower @@ -1517,7 +1517,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): count_maybe_neg = 0 sign = 0 - for i from 1 <= i < n: + for i in range(1, n): new_count_maybe_pos = count_maybe_pos new_count_maybe_neg = count_maybe_neg val = cd[i] @@ -1554,7 +1554,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): cdef int degree(self): """ - Returns the (formal) degree of this polynomial. + Return the (formal) degree of this polynomial. """ return len(self.coeffs) - 1 @@ -1608,7 +1608,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): if msign == 0: msign = sign elif sign != 0: - assert(msign == sign) + assert msign == sign # As long as new_neg and new_pos have # magnitudes less than 0.5, these computations @@ -1642,7 +1642,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): def get_msb_bit(self): """ - Returns an approximation of the log2 of the maximum of the + Return an approximation of the log2 of the maximum of the absolute values of the coefficients, as an integer. """ return self.scale_log2 - 53 + self.bitsize @@ -1658,9 +1658,6 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): sage: bp.slope_range().str(style='brackets') '[-4.8400000000000017 .. 7.2000000000000011]' """ - cdef unsigned int cwf - # fpu_fix_start(&cwf) - width = self.region_width() (min_diff, max_diff) = min_max_diff_doublevec(self.coeffs) err = self.pos_err - self.neg_err @@ -1697,17 +1694,19 @@ def mk_ibpf(coeffs, lower=0, upper=1, lsign=0, usign=0, neg_err=0, pos_err=0, """ return interval_bernstein_polynomial_float(vector(RDF, coeffs), QQ(lower), QQ(upper), lsign, usign, neg_err, pos_err, scale_log2, level, slope_err) -cdef Rational QQ_1_2 = ZZ(1)/2 -cdef Rational QQ_1_32 = QQ(1)/32 -cdef Rational QQ_31_32 = QQ(31)/32 -cdef Rational zero_QQ = QQ(0) -cdef Rational one_QQ = QQ(1) -cdef Integer zero_ZZ = ZZ(0) -cdef Integer one_ZZ = ZZ(1) + +cdef Rational QQ_1_2 = QQ((1, 2)) +cdef Rational QQ_1_32 = QQ((1, 32)) +cdef Rational QQ_31_32 = QQ((31, 32)) +cdef Rational zero_QQ = QQ.zero() +cdef Rational one_QQ = QQ.one() +cdef Integer zero_ZZ = ZZ.zero() +cdef Integer one_ZZ = ZZ.one() cdef Integer ZZ_2_31 = ZZ(2) ** 31 cdef Integer ZZ_2_32 = ZZ(2) ** 32 cdef RealIntervalFieldElement zero_RIF = RIF(0) + def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): """ Given a polynomial in Bernstein form with floating-point coefficients @@ -1747,9 +1746,6 @@ def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): c1 = Vector_real_double_dense(vs, 0) c2 = c.__copy__() - cdef unsigned int cwf - # fpu_fix_start(&cwf) - cdef numpy.ndarray[double, ndim=1] c1d = c1._vector_numpy cdef numpy.ndarray[double, ndim=1] c2d = c2._vector_numpy @@ -1758,16 +1754,14 @@ def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): cdef int n = len(c) cdef int i, j - cdef int cur_den_steps = 0 - cdef double rx, rnx cdef int extra_err if x == QQ_1_2: - for i from 0 <= i < n: + for i in range(n): c1d[i] = c2d[0] - for j from 0 <= j < n-i-1: + for j in range(n-i-1): c2d[j] = (c2d[j] + c2d[j+1]) * half # The following code lets us avoid O(n^2) floating-point multiplications @@ -1797,6 +1791,7 @@ def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): return (c1, c2, extra_err) + def max_abs_doublevec(Vector_real_double_dense c): """ Given a floating-point vector, return the maximum of the @@ -1813,23 +1808,27 @@ def max_abs_doublevec(Vector_real_double_dense c): cdef double m = 0 cdef double a - for i from 0 <= i < len(c): + for i in range(len(c)): a = fabs(cd[i]) - if a > m: m = a + if a > m: + m = a return m + def wordsize_rational(a, b, wordsize): """ - Given rationals a and b, selects a de Casteljau split point r between - a and b. An attempt is made to select an efficient split point + Given rationals a and b, select a de Casteljau split point r between + a and b. + + An attempt is made to select an efficient split point (according to the criteria mentioned in the documentation for de_casteljau_intvec), with a bias towards split points near a. In full detail: - Takes as input two rationals, a and b, such that 0<=a<=1, 0<=b<=1, - and a!=b. Returns rational r, such that a<=r<=b or b<=r<=a. + This takes as input two rationals, a and b, such that 0<=a<=1, 0<=b<=1, + and a!=b. This returns rational r, such that a<=r<=b or b<=r<=a. The denominator of r is a power of 2. Let m be min(r, 1-r), nm be numerator(m), and dml be log2(denominator(m)). The return value r is taken from the first of the following classes to have any @@ -1889,7 +1888,7 @@ def wordsize_rational(a, b, wordsize): while True: rf = fld(a) if cur_size == wordsize: - assert(mpfr_number_p(rf.value)) + assert mpfr_number_p(rf.value) exp = mpfr_get_exp(rf.value) if rf <= -(fld(-b)): if exp <= -3: @@ -1906,11 +1905,14 @@ def wordsize_rational(a, b, wordsize): fld = RealField(cur_size, rnd='RNDU') r = rf.exact_rational() - if sub_1: r = r + one_QQ - if swap_01: r = one_QQ - r + if sub_1: + r = r + one_QQ + if swap_01: + r = one_QQ - r # assert 0 <= r <= 1 return r + def relative_bounds(a, b): """ INPUT: @@ -1936,6 +1938,7 @@ def relative_bounds(a, b): width = ah - al return ((bl - al) / width, (bh - al) / width) + cdef int bitsize(Integer a): """ Compute the number of bits required to write a given integer @@ -1959,9 +1962,11 @@ cdef int bitsize(Integer a): """ return int(mpz_sizeinbase(a.value, 2)) + def bitsize_doctest(n): return bitsize(n) + def degree_reduction_next_size(n): """ Given n (a polynomial degree), returns either a smaller integer or None. @@ -1992,11 +1997,14 @@ def degree_reduction_next_size(n): # computing the exact inverse of a k by k matrix seems infeasible # for k much larger than 30.) - if n <= 2: return None + if n <= 2: + return None next = n * 3 // 4 - if next > 30: next = 30 + if next > 30: + next = 30 return next + def precompute_degree_reduction_cache(n): """ Compute and cache the matrices used for degree reduction, starting @@ -2020,7 +2028,8 @@ def precompute_degree_reduction_cache(n): ) """ while True: - if n in dr_cache: return + if n in dr_cache: + return next = degree_reduction_next_size(n) if next is None: dr_cache[n] = (None, None, 0) @@ -2052,6 +2061,7 @@ def precompute_degree_reduction_cache(n): dr_cache[n] = (next, bd, expected_err.floor(), (bdi, bdd)) n = next + def bernstein_down(d1, d2, s): """ Given polynomial degrees d1 and d2 (where d1 < d2), and a number @@ -2088,10 +2098,12 @@ def bernstein_down(d1, d2, s): return pseudoinverse(bernstein_up(d1, d2, s)) + def pseudoinverse(m): mt = m.transpose() return ~(mt * m) * mt + def bernstein_up(d1, d2, s=None): """ Given polynomial degrees d1 and d2, where d1 < d2, compute a matrix bu. @@ -2114,7 +2126,8 @@ def bernstein_up(d1, d2, s=None): [ 8/15 -4 16/3 -13/15] [ -2/5 3 -4 12/5] """ - if s is None: s = d1 + 1 + if s is None: + s = d1 + 1 MS = MatrixSpace(QQ, s, d1+1, sparse=False) m = MS() scale = factorial(d2)/factorial(d2-d1) @@ -2129,6 +2142,7 @@ def bernstein_up(d1, d2, s=None): return m + cdef int subsample_vec(int a, int slen, int llen): """ Given a vector of length llen, and slen < llen, we want to @@ -2176,10 +2190,12 @@ def maximum_root_first_lambda(p): 1.00000000000000 """ n = p.degree() - if p[n] < 0: p = -p + if p[n] < 0: + p = -p cl = [RIF(x) for x in p.list()] return cl_maximum_root_first_lambda(cl) + def cl_maximum_root_first_lambda(cl): r""" Given a polynomial represented by a list of its coefficients @@ -2204,7 +2220,7 @@ def cl_maximum_root_first_lambda(cl): Real Field with 53 bits of precision and rounding RNDU) """ n = len(cl) - 1 - assert(cl[n] > 0) + assert cl[n] > 0 pending_pos_coeff = cl[n] pending_pos_exp = n lastPos = True @@ -2242,6 +2258,7 @@ def cl_maximum_root_first_lambda(cl): return max_ub_log.upper().exp() + def maximum_root_local_max(p): r""" Given a polynomial with real coefficients, computes an upper bound @@ -2261,10 +2278,12 @@ def maximum_root_local_max(p): 1.41421356237310 """ n = p.degree() - if p[n] < 0: p = -p + if p[n] < 0: + p = -p cl = [RIF(x) for x in p.list()] return cl_maximum_root_local_max(cl) + def cl_maximum_root_local_max(cl): r""" Given a polynomial represented by a list of its coefficients @@ -2282,7 +2301,7 @@ def cl_maximum_root_local_max(cl): 1.41421356237310 """ n = len(cl) - 1 - assert(cl[n] > 0) + assert cl[n] > 0 max_pos_coeff = cl[n] max_pos_exp = n max_pos_uses = 0 @@ -2300,6 +2319,7 @@ def cl_maximum_root_local_max(cl): return max_ub_log.upper().exp() + def cl_maximum_root(cl): r""" Given a polynomial represented by a list of its coefficients @@ -2321,6 +2341,7 @@ def cl_maximum_root(cl): return min(cl_maximum_root_first_lambda(cl), cl_maximum_root_local_max(cl)) + def root_bounds(p): r""" Given a polynomial with real coefficients, computes a lower and @@ -2350,7 +2371,8 @@ def root_bounds(p): True """ n = p.degree() - if p[n] < 0: p = -p + if p[n] < 0: + p = -p cl = [RIF(x) for x in p.list()] cdef int zero_roots = 0 @@ -2390,6 +2412,7 @@ def root_bounds(p): return (lb, ub) + def rational_root_bounds(p): """ Given a polynomial p with real coefficients, computes rationals @@ -2497,9 +2520,11 @@ def rational_root_bounds(p): return (rlb, rub) + class PrecisionError(ValueError): pass + class bernstein_polynomial_factory: """ An abstract base class for bernstein_polynomial factories. That @@ -2519,24 +2544,27 @@ class bernstein_polynomial_factory: """ def _sign(self, v): - if v > 0: return 1 - if v < 0: return -1 + if v > 0: + return 1 + if v < 0: + return -1 return 0 def lsign(self): """ - Returns the sign of the first coefficient of this + Return the sign of the first coefficient of this Bernstein polynomial. """ return self._sign(self.coeffs[0]) def usign(self): """ - Returns the sign of the last coefficient of this + Return the sign of the last coefficient of this Bernstein polynomial. """ return self._sign(self.coeffs[-1]) + class bernstein_polynomial_factory_intlist(bernstein_polynomial_factory): """ This class holds an exact Bernstein polynomial (represented @@ -2615,6 +2643,7 @@ class bernstein_polynomial_factory_intlist(bernstein_polynomial_factory): return interval_bernstein_polynomial_integer((ZZ ** len(b))(intv_b), zero_QQ, one_QQ, self.lsign(), self.usign(), 1, scale_log2, 0, zero_RIF) # return bp_of_intlist(self.coeffs, scale_log2) + class bernstein_polynomial_factory_ratlist(bernstein_polynomial_factory): """ This class holds an exact Bernstein polynomial (represented @@ -2699,6 +2728,7 @@ class bernstein_polynomial_factory_ratlist(bernstein_polynomial_factory): return interval_bernstein_polynomial_integer((ZZ ** len(b))(intv_b), zero_QQ, one_QQ, self.lsign(), self.usign(), 1, scale_log2, 0, zero_RIF) # return bp_of_ratlist(self.coeffs, scale_log2) + class bernstein_polynomial_factory_ar(bernstein_polynomial_factory): """ This class holds an exact Bernstein polynomial (represented as a @@ -2860,7 +2890,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list cdef rr_gap r split_targets = [] - for (l,r,_) in target_list: + for l, r, _ in target_list: if l is None: split_targets += [(QQ(0), None, 0)] else: @@ -2869,7 +2899,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list if lbounds[0] > 0: out_of_bounds = True if r is None: - split_targets += [(QQ(1), None, 0)] + split_targets += [(QQ.one(), None, 0)] else: rbounds = relative_bounds(bounds, r.region()) split_targets += [(rbounds[0], rbounds[1], r.sign)] @@ -2895,7 +2925,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list split = wordsize_rational(split_targets[best_index][0], split_targets[best_index][1], ctx.wordsize) (p1_, p2_, ok) = bp.de_casteljau(ctx, split, msign=split_targets[best_index][2]) - assert(ok) + assert ok cdef interval_bernstein_polynomial p1 = p1_ cdef interval_bernstein_polynomial p2 = p2_ @@ -2918,17 +2948,15 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list tl1 = target_list[:target_list_splitpoint] tl2 = target_list[target_list_splitpoint:] - tiny = ~Integer(32) - if len(tl1) > 0: - if True: # p1.region_width() / bp.region_width() < tiny: + if True: # p1.region_width() / bp.region_width() < tiny: max_lsb = max([t[2] for t in tl1]) p1 = p1.down_degree_iter(ctx, max_lsb) r1 = split_for_targets(ctx, p1, tl1) else: r1 = [] if len(tl2) > 0: - if True: # p2.region_width() / bp.region_width() < tiny: + if True: # p2.region_width() / bp.region_width() < tiny: max_lsb = max([t[2] for t in tl2]) p2 = p2.down_degree_iter(ctx, max_lsb) r2 = split_for_targets(ctx, p2, tl2) @@ -2937,6 +2965,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list return r1 + r2 + cdef class ocean: """ Given the tools we've defined so far, there are many possible root @@ -3050,7 +3079,7 @@ cdef class ocean: def approx_bp(self, scale_log2): """ - Returns an approximation to our Bernstein polynomial with the + Return an approximation to our Bernstein polynomial with the given scale_log2. EXAMPLES:: @@ -3225,6 +3254,7 @@ cdef class ocean: isle = active_islands[i] isle.bp = bp + cdef class island: """ This implements the island portion of my ocean-island root isolation @@ -3530,7 +3560,7 @@ cdef class island: return else: self.refine_recurse(ctx, p1, ancestors, history, False) - assert(self.lgap.upper == p2.lower) + assert self.lgap.upper == p2.lower bp = p2 # return to top of function (tail recursion optimization) @@ -3567,7 +3597,8 @@ cdef class island: """ cur_msb = bp.scale_log2 + bp.bitsize extra_bits = bp.bitsize // 2 - if extra_bits < 30: extra_bits = 30 + if extra_bits < 30: + extra_bits = 30 target_lsb_h = cur_msb - 3*extra_bits target_lsb = cur_msb - 4*extra_bits @@ -3584,8 +3615,6 @@ cdef class island: for i in range(len(ancestors)-1, -1, -1): anc = ancestors[i] if target_lsb_h >= anc.scale_log2: - ancestor_bitsize = anc.bitsize - ancestor_msb = anc.scale_log2 + ancestor_bitsize ancestor_val = anc first_lsb = ancestor_val.scale_log2 first_msb = first_lsb + ancestor_val.bitsize @@ -3629,7 +3658,7 @@ cdef class island: ancestor_val = ancestor_val.down_degree_iter(ctx, target_lsb_h) rel_bounds = relative_bounds(ancestor_val.region(), bp.region()) - assert(rel_bounds[1] == 1) + assert rel_bounds[1] == 1 ancestor_val = split_for_targets(ctx, ancestor_val, [(self.lgap, maybe_rgap, target_lsb_h)])[0] # if rel_lbounds[1] > 0: @@ -3641,7 +3670,7 @@ cdef class island: ancestor_val.usign = bp.usign new_rel_bounds = relative_bounds(ancestor_val.region(), bp.region()) - assert(new_rel_bounds[1] - new_rel_bounds[0] >= Integer(255)/256) + assert new_rel_bounds[1] - new_rel_bounds[0] >= Integer(255)/256 while ancestor_val.scale_log2 < target_lsb_l: ancestors = ancestors + [ancestor_val] @@ -3701,7 +3730,6 @@ cdef class island: return True return False - def done(self, context ctx): """ Check to see if the island is known to contain zero roots or @@ -3725,11 +3753,11 @@ cdef class island: Assuming that the island is done (has either 0 or 1 roots), reports whether the island has a root. """ - - assert(self.known_done) + assert self.known_done return bool(self.bp.max_variations) + cdef class rr_gap: """ A simple class representing the gaps between islands, in my @@ -3748,6 +3776,7 @@ cdef class rr_gap: def region(self): return (self.lower, self.upper) + class linear_map: """ A simple class to map linearly between original coordinates @@ -3768,8 +3797,10 @@ class linear_map: (l, u) = region return ((l - self.lower) / self.width, (u - self.lower) / self.width) + lmap = linear_map(0, 1) + class warp_map: """ A class to map between original coordinates and ocean coordinates. @@ -3798,12 +3829,13 @@ class warp_map: else: return (l/(l+1), u/(u+1)) + def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=False, wordsize=32, retval='rational', strategy=None, max_diameter=None): """ - Compute the real roots of a given polynomial with exact - coefficients (integer, rational, and algebraic real coefficients - are supported). Returns a list of pairs of a root and its - multiplicity. + Compute the real roots of a given polynomial with exact coefficients + (integer, rational, and algebraic real coefficients are supported). + + This returns a list of pairs of a root and its multiplicity. The root itself can be returned in one of three different ways. If retval=='rational', then it is returned as a pair of rationals @@ -3996,12 +4028,14 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals if ar_input and bounds is not None: raise NotImplementedError("Cannot set your own bounds with algebraic real input") - if ar_input: strategy = 'warp' + if ar_input: + strategy = 'warp' - if bounds is not None and strategy=='warp': + if bounds is not None and strategy == 'warp': raise NotImplementedError("Cannot set your own bounds with strategy=warp") - if seed is None: seed = 1 + if seed is None: + seed = 1 if skip_squarefree: factors = [(p, 1)] @@ -4018,7 +4052,7 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals cdef ocean oc - for (factor, exp) in factors: + for factor, exp in factors: if strategy=='warp': if factor.constant_coefficient() == 0: x = factor.parent().gen() @@ -4073,7 +4107,7 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals while True: all_roots = copy(extra_roots) - for (oc, factor, exp) in oceans: + for oc, factor, exp in oceans: rel_roots = oc.roots() cur_roots = [oc.mapping.from_ocean(r) for r in rel_roots] @@ -4086,7 +4120,6 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals target_widths = [None] * len(all_roots) - if max_diameter is not None: # Check to make sure that no intervals are too wide. @@ -4108,7 +4141,6 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals target_widths[i] = (root[1] - root[0]) / cur_diam * half_diameter ok = False - for i in range(len(all_roots) - 1): # Check to be sure that all intervals are disjoint. if all_roots[i][0][1] >= all_roots[i+1][0][0]: @@ -4129,14 +4161,16 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals ocean_target = oc.mapping.to_ocean(target_region) oc.reset_root_width(all_roots[i][4], ocean_target[1] - ocean_target[0]) - if ok: break + if ok: + break - for (oc, factor, exp) in oceans: oc.find_roots() + for oc, factor, exp in oceans: + oc.find_roots() if do_logging: return ctx, all_roots - if retval=='rational': + if retval == 'rational': return [(r[0], r[2]) for r in all_roots] for i in range(1000): @@ -4199,6 +4233,7 @@ def scale_intvec_var(Vector_integer_dense c, k): c[i] = c[i] * factor factor = (factor * kn) // kd + def taylor_shift1_intvec(Vector_integer_dense c): """ Given a vector of integers c of length d+1, representing the @@ -4229,6 +4264,7 @@ def taylor_shift1_intvec(Vector_integer_dense c): for k from degree-i <= k < degree: mpz_add(c._entries[k], c._entries[k], c._entries[k+1]) + def reverse_intvec(Vector_integer_dense c): """ Given a vector of integers, reverse the vector (like the reverse() @@ -4250,8 +4286,10 @@ def reverse_intvec(Vector_integer_dense c): for i from 0 <= i < c_len // 2: mpz_swap(c._entries[i], c._entries[c_len - 1 - i]) + realfield_rndu_cache = {} + def get_realfield_rndu(n): """ A simple cache for RealField fields (with rounding set to @@ -4274,6 +4312,7 @@ def get_realfield_rndu(n): realfield_rndu_cache[n] = fld return fld + cdef class context: """ A simple context class, which is passed through parts of the @@ -4287,7 +4326,7 @@ cdef class context: """ Initialize a context class. """ - self.seed = seed # saved to make context printable + self.seed = seed # saved to make context printable self.random = randstate().python_random(seed=seed) self.do_logging = do_logging self.wordsize = wordsize @@ -4334,6 +4373,7 @@ cdef class context: def get_be_log(self): return self.be_log + def mk_context(do_logging=False, seed=0, wordsize=32): """ A simple wrapper for creating context objects with coercions, @@ -4349,6 +4389,7 @@ def mk_context(do_logging=False, seed=0, wordsize=32): """ return context(do_logging, seed, wordsize) + def to_bernstein(p, low=0, high=1, degree=None): """ Given a polynomial p with integer coefficients, and rational @@ -4374,7 +4415,6 @@ def to_bernstein(p, low=0, high=1, degree=None): sage: to_bernstein(x^3 + x^2 - x - 1, low=3, high=22/7) ([296352, 310464, 325206, 340605], 9261) """ - if degree is None: degree = p.degree() elif degree < p.degree(): @@ -4429,7 +4469,7 @@ def bernstein_expand(Vector_integer_dense c, int d2): multiplies, but in this version all the multiplies are by single machine words). - Returns a pair consisting of the expanded polynomial, and the maximum + This returns a pair consisting of the expanded polynomial, and the maximum error E. (So if an element of the returned polynomial is a, and the true value of that coefficient is b, then a <= b < a + E.) @@ -4462,7 +4502,8 @@ def bernstein_expand(Vector_integer_dense c, int d2): # XXX do experimentation here on how to decide when to divide cdef int max_bits = max_bitsize_intvec(c) / 2 - if max_bits < 64: max_bits = 64 + if max_bits < 64: + max_bits = 64 for i from 0 <= i <= d1: mpz_set(c2._entries[i], c._entries[i]) @@ -4486,6 +4527,7 @@ def bernstein_expand(Vector_integer_dense c, int d2): return (c2, ndivides) + cdef int max_bitsize_intvec(Vector_integer_dense b): """ Given an integer vector, find the approximate log2 of the maximum @@ -4501,15 +4543,18 @@ cdef int max_bitsize_intvec(Vector_integer_dense b): cdef int i cdef int size - for i from 0 <= i < len(b): + for i in range(len(b)): size = mpz_sizeinbase(b._entries[i], 2) - if size > max_bits: max_bits = size + if size > max_bits: + max_bits = size return max_bits + def max_bitsize_intvec_doctest(b): return max_bitsize_intvec(b) + def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): """ Computes the dot product of row k of the matrix m with the vector v @@ -4539,9 +4584,8 @@ def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): sage: dprod_imatrow_vec(m, vector(ZZ, [1, 2, 3]), 1) 26 """ - - assert(0 <= k < m.nrows()) - assert(m.ncols() <= len(v)) + assert 0 <= k < m.nrows() + assert m.ncols() <= len(v) cdef Integer sum = Integer(0) @@ -4552,13 +4596,14 @@ def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): cdef int ra cdef int a mpz_init(tmp) - for a from 0 <= a < msize: + for a in range(msize): ra = subsample_vec(a, msize, vsize) - m.get_unsafe_mpz(k,a,tmp) + m.get_unsafe_mpz(k, a, tmp) mpz_addmul(sum.value, tmp, v._entries[ra]) mpz_clear(tmp) return sum + def min_max_delta_intvec(Vector_integer_dense a, Vector_integer_dense b): """ Given two integer vectors a and b (of equal, nonzero length), return @@ -4572,9 +4617,8 @@ def min_max_delta_intvec(Vector_integer_dense a, Vector_integer_dense b): sage: min_max_delta_intvec(a, b) (30, -5) """ - - assert(len(a) == len(b)) - assert(len(a) > 0) + assert len(a) == len(b) + assert len(a) > 0 cdef Integer max = Integer() cdef Integer min = Integer() @@ -4594,6 +4638,7 @@ def min_max_delta_intvec(Vector_integer_dense a, Vector_integer_dense b): return (max, min) + def min_max_diff_intvec(Vector_integer_dense b): """ Given an integer vector b = (b0, ..., bn), compute the @@ -4606,7 +4651,7 @@ def min_max_diff_intvec(Vector_integer_dense b): (-9, 6) """ l = len(b) - assert(l > 1) + assert l > 1 cdef Integer min_diff = b[1] - b[0] cdef Integer max_diff = Integer() @@ -4624,6 +4669,7 @@ def min_max_diff_intvec(Vector_integer_dense b): return (min_diff, max_diff) + def min_max_diff_doublevec(Vector_real_double_dense c): """ Given a floating-point vector b = (b0, ..., bn), compute the @@ -4638,7 +4684,7 @@ def min_max_diff_doublevec(Vector_real_double_dense c): cdef numpy.ndarray[double, ndim=1] cd = c._vector_numpy l = len(c) - assert(l > 1) + assert l > 1 cdef double min_diff = cd[1] - cd[0] cdef double max_diff = min_diff diff --git a/src/sage/rings/polynomial/symmetric_ideal.py b/src/sage/rings/polynomial/symmetric_ideal.py index 12a629ad741..f9cae63ea4b 100644 --- a/src/sage/rings/polynomial/symmetric_ideal.py +++ b/src/sage/rings/polynomial/symmetric_ideal.py @@ -655,14 +655,14 @@ def symmetrisation(self, N=None, tailreduce=False, report=None, use_full_group=F from sage.combinat.permutation import Permutation from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy RStrat = SymmetricReductionStrategy(self.ring(),OUT.gens(),tailreduce=tailreduce) - while (OUT != newOUT): + while OUT != newOUT: OUT = newOUT PermutedGens = list(OUT.gens()) if not (report is None): print("Apply permutations") - for i in range(1,N): - for j in range(i+1,N+1): - P = Permutation(((i,j))) + for i in range(1, N): + for j in range(i + 1, N + 1): + P = Permutation(((i, j))) for X in OUT.gens(): p = RStrat.reduce(X**P,report=report) if p._p != 0: diff --git a/src/sage/rings/polynomial/symmetric_reduction.pyx b/src/sage/rings/polynomial/symmetric_reduction.pyx index 6cc00047de8..e873fcc5397 100644 --- a/src/sage/rings/polynomial/symmetric_reduction.pyx +++ b/src/sage/rings/polynomial/symmetric_reduction.pyx @@ -487,7 +487,7 @@ cdef class SymmetricReductionStrategy: p = p / p.lc() if (self._min_lm is None) or (p.lm() < self._min_lm): self._min_lm = p.lm() - while (i < l) and (self._lengths[i] < newLength): + while i < l and self._lengths[i] < newLength: i += 1 self._lm.insert(i, p) self._lengths.insert(i, newLength) @@ -514,7 +514,7 @@ cdef class SymmetricReductionStrategy: self._lm.pop(i) self._lengths.pop(i) j = 0 - while (j < i) and (self._lengths[j] < q_len): + while j < i and self._lengths[j] < q_len: j += 1 self._lm.insert(j, q) self._lengths.insert(j, q_len) diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 8bfabb73701..5e2c4511e49 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -1510,21 +1510,21 @@ cdef class PowerSeries(AlgebraElement): INPUT: - - ``prec`` - integer (default: None): if not None and the series - has infinite precision, truncates series at precision - prec. + - ``prec`` - integer (default: ``None``): if not ``None`` + and the series has infinite precision, truncates series at + precision prec. - - ``extend`` - bool (default: False); if True, return a square + - ``extend`` - bool (default: ``False``); if ``True``, return a square root in an extension ring, if necessary. Otherwise, raise - a ValueError if the square root is not in the base power series - ring. For example, if ``extend`` is True the square root of a - power series with odd degree leading coefficient is - defined as an element of a formal extension ring. + a :class:`ValueError` if the square root is not in the + base power series ring. For example, if ``extend`` is ``True`` + the square root of a power series with odd degree leading + coefficient is defined as an element of a formal extension ring. - - ``name`` - string; if ``extend`` is True, you must also specify the print + - ``name`` - string; if ``extend`` is ``True``, you must also specify the print name of the formal square root. - - ``all`` - bool (default: False); if True, return all square + - ``all`` - bool (default: ``False``); if ``True``, return all square roots of self, instead of just one. ALGORITHM: Newton's method diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 9602d569984..77d035896d0 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -3399,7 +3399,7 @@ def super_poly(self, super, checked=None): continue if self is u.child1: return u.child1_poly(poly) - assert(self is u.child2) + assert (self is u.child2) return u.child2_poly(poly) return None @@ -3447,7 +3447,7 @@ def __call__(self, elt): return elt.field_element_value() gen = elt.generator() sp = gen.super_poly(self) - assert(not(sp is None)) + assert (not (sp is None)) return self._field(elt.field_element_value().polynomial()(sp)) @@ -7543,7 +7543,7 @@ def find_fn(factor, prec): my_factor = find_zero_result(find_fn, qpf) # Factoring always returns monic polynomials over the rationals - assert(my_factor.is_monic()) + assert (my_factor.is_monic()) if my_factor.degree() == 1: return ANRational(-my_factor[0]) @@ -7586,7 +7586,7 @@ def find_fn(factor, prec): return ip(self_val) my_factor = find_zero_result(find_fn, fpf) - assert(my_factor.is_monic()) + assert (my_factor.is_monic()) if my_factor.degree() == 1: return ANExtensionElement(gen, -my_factor[0]) @@ -7751,7 +7751,7 @@ def handle_sage_input(self, sib, coerce, is_qqbar): ({call: {atomic:QQbar}({binop:+ {atomic:1} {atomic:I}})}, True) """ if self._generator is QQbar_I_generator: - assert(is_qqbar) + assert (is_qqbar) re, im = self._value.list() im_part = sib.prod([sib(im, True), sib.name('I')], simplify=True) v = sib.sum([sib(re, True), im_part], simplify=True) diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index a78680d0ee2..fb2eb1d718c 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -3905,7 +3905,7 @@ cdef class RealNumber(sage.structure.element.RingElement): cdef Integer k - while (not low_done) or (not high_done): + while not low_done or not high_done: # Move the low side k = (c*b - d*a) // (d*e - c*f) diff --git a/src/sage/rings/valuation/augmented_valuation.py b/src/sage/rings/valuation/augmented_valuation.py index 37fda19d7dc..7019fc39e91 100644 --- a/src/sage/rings/valuation/augmented_valuation.py +++ b/src/sage/rings/valuation/augmented_valuation.py @@ -631,7 +631,7 @@ def is_gauss_valuation(self): False """ - assert(self._mu > 0) + assert (self._mu > 0) return False def monic_integral_model(self, G): @@ -1120,7 +1120,7 @@ def lift(self, F): G = PolynomialRing(F.base_ring(), 'x')(list(F)) else: G = F.polynomial() - assert(G(self._residue_field_generator()) == F) + assert (G(self._residue_field_generator()) == F) F = G.change_variable_name(self._base_valuation.residue_ring().variable_name()) H = self._base_valuation.lift(F) diff --git a/src/sage/rings/valuation/inductive_valuation.py b/src/sage/rings/valuation/inductive_valuation.py index 8cc999d5bbd..5da834ad018 100644 --- a/src/sage/rings/valuation/inductive_valuation.py +++ b/src/sage/rings/valuation/inductive_valuation.py @@ -1033,7 +1033,7 @@ def is_minimal(self, f, assume_equivalence_irreducible=False): assert not F.is_constant() return F.is_irreducible() else: - assert(self(f) <= 0) # f is monic + assert (self(f) <= 0) # f is monic # f is not minimal: # Let g be f stripped of its leading term, i.e., g = f - x^n. # Then g and f are equivalent with respect to this valuation diff --git a/src/sage/rings/valuation/limit_valuation.py b/src/sage/rings/valuation/limit_valuation.py index 2820c7123a9..6aae23d9cfa 100644 --- a/src/sage/rings/valuation/limit_valuation.py +++ b/src/sage/rings/valuation/limit_valuation.py @@ -531,7 +531,7 @@ def _improve_approximation(self): check=False, principal_part_bound=1 if self._approximation.E() * self._approximation.F() == self._approximation.phi().degree() else None, report_degree_bounds_and_caches=True) - assert(len(approximations) == 1) + assert (len(approximations) == 1) self._approximation, _, _, self._next_coefficients, self._next_valuations = approximations[0] def _improve_approximation_for_call(self, f): @@ -669,7 +669,7 @@ def residue_ring(self): return R else: from sage.rings.polynomial.polynomial_ring import is_PolynomialRing - assert(is_PolynomialRing(R)) + assert (is_PolynomialRing(R)) return R.base_ring() def _ge_(self, other): @@ -787,7 +787,7 @@ def _weakly_separating_element(self, other): # phi of the initial approximant must be good enough to separate it # from any other approximant of an extension ret = self._initial_approximation.phi() - assert(self(ret) > other(ret)) # I could not come up with an example where this fails + assert (self(ret) > other(ret)) # I could not come up with an example where this fails return ret else: # if the valuations are sane, it should be possible to separate diff --git a/src/sage/rings/valuation/mapped_valuation.py b/src/sage/rings/valuation/mapped_valuation.py index e2ec88ae306..1aab2ff34b8 100644 --- a/src/sage/rings/valuation/mapped_valuation.py +++ b/src/sage/rings/valuation/mapped_valuation.py @@ -657,7 +657,7 @@ def _repr_(self): from .limit_valuation import MacLaneLimitValuation if isinstance(self._base_valuation, MacLaneLimitValuation): # print the minimal information that singles out this valuation from all approximants - assert(self._base_valuation._initial_approximation in self._approximants) + assert (self._base_valuation._initial_approximation in self._approximants) approximants = [v.augmentation_chain()[::-1] for v in self._approximants] augmentations = self._base_valuation._initial_approximation.augmentation_chain()[::-1] unique_approximant = None @@ -665,7 +665,7 @@ def _repr_(self): if len([a for a in approximants if a[:l + 1] == augmentations[:l + 1]]) == 1: unique_approximant = augmentations[:l + 1] break - assert(unique_approximant is not None) + assert (unique_approximant is not None) if unique_approximant[0].is_gauss_valuation(): unique_approximant[0] = unique_approximant[0].restriction(unique_approximant[0].domain().base_ring()) if len(unique_approximant) == 1: diff --git a/src/sage/rings/valuation/valuation_space.py b/src/sage/rings/valuation/valuation_space.py index be0e9192c7c..ce737c93969 100644 --- a/src/sage/rings/valuation/valuation_space.py +++ b/src/sage/rings/valuation/valuation_space.py @@ -592,7 +592,7 @@ def extension(self, ring): Rational Field """ extensions = self.extensions(ring) - assert(extensions) + assert extensions if len(extensions) > 1: raise ValueError("there is no unique extension of %r from %r to %r" % (self, self.domain(), ring)) return extensions[0] @@ -756,7 +756,7 @@ def separating_element(self, others): factor = ret ret = delta while any(other(ret) >= 0 for other in others[:i]): - assert(others[i](ret) < 0) + assert others[i](ret) < 0 ret *= factor else: # others[i](ret) > 0 # construct an element which approximates a unit with respect to others[i] @@ -801,16 +801,16 @@ def _strictly_separating_element(self, other): numerator = self._weakly_separating_element(other) n = self(numerator) nn = other(numerator) - assert(n > 0) - assert(nn is not infinity) - if (nn < 0): + assert n > 0 + assert nn is not infinity + if nn < 0: return numerator denominator = other._weakly_separating_element(self) d = self(denominator) dd = other(denominator) - assert(dd > 0) - assert(d is not infinity) + assert dd > 0 + assert d is not infinity if d < 0: # The following may fail if denominator is not # invertible in the domain, but we don't have a better @@ -828,11 +828,11 @@ def _strictly_separating_element(self, other): # a/b > d/n and b/a > nn/dd # which is # dd/nn > a/b > d/n - assert(dd/nn > d/n) + assert dd / nn > d / n from sage.rings.continued_fraction import continued_fraction ab_cf = [] - dn_cf = continued_fraction(d/n) - ddnn_cf = continued_fraction(dd/nn) + dn_cf = continued_fraction(d / n) + ddnn_cf = continued_fraction(dd / nn) for i, (x,y) in enumerate(zip(dn_cf, ddnn_cf)): if x == y: ab_cf.append(x) @@ -851,8 +851,8 @@ def _strictly_separating_element(self, other): a,b = ab.numerator(), ab.denominator() ret = self.domain()(numerator**a / denominator**b) - assert(self(ret) > 0) - assert(other(ret) < 0) + assert (self(ret) > 0) + assert (other(ret) < 0) return ret def _weakly_separating_element(self, other): diff --git a/src/sage/sandpiles/examples.py b/src/sage/sandpiles/examples.py index 6507992cc3c..bd6d409e770 100644 --- a/src/sage/sandpiles/examples.py +++ b/src/sage/sandpiles/examples.py @@ -156,10 +156,10 @@ def Fan(self, n, deg_three_verts=False): EXAMPLES:: sage: f = sandpiles.Fan(10) - sage: f.group_order() == fibonacci(18) + sage: f.group_order() == fibonacci(18) # needs sage.libs.pari True sage: f = sandpiles.Fan(10,True) # all nonsink vertices have deg 3 - sage: f.group_order() == fibonacci(20) + sage: f.group_order() == fibonacci(20) # needs sage.libs.pari True """ f = graphs.WheelGraph(n) diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index eca2303fc9f..b15323532b7 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -83,7 +83,7 @@ A picture of the graph:: - sage: S.show() # long time + sage: S.show() # long time # needs sage.plot The relevant Laplacian matrices:: @@ -205,17 +205,19 @@ the saturated homogeneous toppling ideal:: - sage: S.ideal() - Ideal (x1 - x0, x3*x2 - x0^2, x4^2 - x0^2, x2^3 - x4*x3*x0, x4*x2^2 - x3^2*x0, x3^3 - x4*x2*x0, x4*x3^2 - x2^2*x0) of Multivariate Polynomial Ring in x4, x3, x2, x1, x0 over Rational Field + sage: S.ideal() # needs sage.libs.singular + Ideal (x1 - x0, x3*x2 - x0^2, x4^2 - x0^2, x2^3 - x4*x3*x0, + x4*x2^2 - x3^2*x0, x3^3 - x4*x2*x0, x4*x3^2 - x2^2*x0) of + Multivariate Polynomial Ring in x4, x3, x2, x1, x0 over Rational Field its minimal free resolution:: - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^7 <-- R^15 <-- R^13 <-- R^4' and its Betti numbers:: - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 4 ------------------------------------ 0: 1 1 - - - @@ -250,10 +252,13 @@ ....: m = m.add_random() ....: m, f = m.stabilize(True) ....: a.append(sum(f.values())) - sage: p = list_plot([[log(i+1),log(a.count(i))] for i in [0..max(a)] if a.count(i)]) - sage: p.axes_labels(['log(N)','log(D(N))']) + + sage: # needs sage.plot + sage: p = list_plot([[log(i + 1), log(a.count(i))] + ....: for i in [0..max(a)] if a.count(i)]) + sage: p.axes_labels(['log(N)', 'log(D(N))']) sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) - sage: show(p+t,axes_labels=['log(N)','log(D(N))']) # long time + sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time Working with sandpile divisors:: @@ -275,6 +280,8 @@ {0: 4, 1: 0, 2: 0, 3: 1} sage: D.rank() 2 + + sage: # needs sage.geometry.polyhedron sage: sorted(D.effective_div(), key=str) [{0: 0, 1: 0, 2: 0, 3: 5}, {0: 0, 1: 0, 2: 4, 3: 1}, @@ -296,6 +303,7 @@ -1 sage: (D - E).effective_div() [] + sage: D.weierstrass_pts() (0, 1, 2, 3) sage: D.weierstrass_rank_seq(0) @@ -792,8 +800,8 @@ def show(self, **kwds): EXAMPLES:: sage: S = Sandpile({0:[], 1:[0,3,4], 2:[0,3,5], 3:[2,5], 4:[1,1], 5:[2,4]}) - sage: S.show() - sage: S.show(graph_border=True, edge_labels=True) + sage: S.show() # needs sage.plot + sage: S.show(graph_border=True, edge_labels=True) # needs sage.plot """ if self.is_undirected(): @@ -812,7 +820,7 @@ def show3d(self, **kwds): EXAMPLES:: sage: S = sandpiles.House() - sage: S.show3d() # long time + sage: S.show3d() # long time # needs sage.plot """ if self.is_undirected(): @@ -1375,7 +1383,7 @@ def recurrents(self, verbose=True): sage: r = Sandpile(graphs.HouseXGraph(),0).recurrents() sage: r[:3] [{1: 2, 2: 3, 3: 3, 4: 1}, {1: 1, 2: 3, 3: 3, 4: 0}, {1: 1, 2: 3, 3: 3, 4: 1}] - sage: sandpiles.Complete(4).recurrents(False) + sage: sandpiles.Complete(4).recurrents(False) # needs sage.combinat [[2, 2, 2], [2, 2, 1], [2, 1, 2], @@ -1434,7 +1442,7 @@ def superstables(self, verbose=True): sage: sp = Sandpile(graphs.HouseXGraph(),0).superstables() sage: sp[:3] [{1: 0, 2: 0, 3: 0, 4: 0}, {1: 1, 2: 0, 3: 0, 4: 1}, {1: 1, 2: 0, 3: 0, 4: 0}] - sage: sandpiles.Complete(4).superstables(False) + sage: sandpiles.Complete(4).superstables(False) # needs sage.combinat [[0, 0, 0], [0, 0, 1], [0, 1, 0], @@ -1555,8 +1563,8 @@ def _set_min_recurrents(self): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s._set_min_recurrents() - sage: '_min_recurrents' in s.__dict__ + sage: s._set_min_recurrents() # needs sage.combinat + sage: '_min_recurrents' in s.__dict__ # needs sage.combinat True """ if self.is_undirected(): @@ -1660,7 +1668,7 @@ def tutte_polynomial(self): x^3 + y^3 + 3*x^2 + 4*x*y + 3*y^2 + 2*x + 2*y sage: s.tutte_polynomial().subs(x=1) y^3 + 3*y^2 + 6*y + 6 - sage: s.tutte_polynomial().subs(x=1).coefficients() == s.h_vector() + sage: s.tutte_polynomial().subs(x=1).coefficients() == s.h_vector() # needs sage.combinat True """ if self.is_undirected(): @@ -1675,8 +1683,8 @@ def _set_avalanche_polynomial(self): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s._set_avalanche_polynomial() - sage: '_avalanche_polynomial' in s.__dict__ + sage: s._set_avalanche_polynomial() # needs sage.combinat + sage: '_avalanche_polynomial' in s.__dict__ # needs sage.combinat True """ n = self.num_verts() - 1 @@ -1708,9 +1716,9 @@ def avalanche_polynomial(self, multivariable=True): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s.avalanche_polynomial() + sage: s.avalanche_polynomial() # needs sage.combinat 9*x0*x1*x2 + 2*x0*x1 + 2*x0*x2 + 2*x1*x2 + 3*x0 + 3*x1 + 3*x2 + 24 - sage: s.avalanche_polynomial(False) + sage: s.avalanche_polynomial(False) # needs sage.combinat 9*x0^3 + 6*x0^2 + 9*x0 + 24 .. NOTE:: @@ -1747,12 +1755,13 @@ def nonspecial_divisors(self, verbose=True): EXAMPLES:: + sage: # needs sage.combinat sage: S = sandpiles.Complete(4) sage: ns = S.nonspecial_divisors() sage: D = ns[0] - sage: D.values() + sage: D.values() # needs sage.symbolic [-1, 0, 1, 2] - sage: D.deg() + sage: D.deg() # needs sage.symbolic 2 sage: [i.effective_div() for i in ns] [[], [], [], [], [], []] @@ -1914,7 +1923,7 @@ def postulation(self): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s.postulation() + sage: s.postulation() # needs sage.combinat 3 """ return self._postulation @@ -2000,8 +2009,8 @@ def _set_jacobian_representatives(self): EXAMPLES:: sage: s = sandpiles.Complete(3) - sage: s._set_jacobian_representatives() - sage: '_jacobian_representatives' in s.__dict__ + sage: s._set_jacobian_representatives() # needs sage.combinat + sage: '_jacobian_representatives' in s.__dict__ # needs sage.combinat True """ if self.is_undirected(): @@ -2055,9 +2064,9 @@ def jacobian_representatives(self, verbose=True): representatives for the Jacobian group.:: sage: s = sandpiles.Complete(3) - sage: s.superstables(False) + sage: s.superstables(False) # needs sage.combinat [[0, 0], [0, 1], [1, 0]] - sage: s.jacobian_representatives(False) + sage: s.jacobian_representatives(False) # needs sage.combinat [[0, 0, 0], [-1, 0, 1], [-1, 1, 0]] If the graph is directed, the representatives described above may by @@ -2066,7 +2075,7 @@ def jacobian_representatives(self, verbose=True): sage: s = Sandpile({0: {1: 1, 2: 2}, 1: {0: 2, 2: 4}, 2: {0: 4, 1: 2}},0) sage: s.group_order() 28 - sage: s.jacobian_representatives() + sage: s.jacobian_representatives() # needs sage.symbolic [{0: -5, 1: 3, 2: 2}, {0: -4, 1: 3, 2: 1}] Let `\tau` be the nonnegative generator of the kernel of the transpose of @@ -2107,11 +2116,11 @@ def picard_representatives(self, d, verbose=True): EXAMPLES:: sage: s = sandpiles.Complete(3) - sage: s.superstables(False) + sage: s.superstables(False) # needs sage.combinat [[0, 0], [0, 1], [1, 0]] - sage: s.jacobian_representatives(False) + sage: s.jacobian_representatives(False) # needs sage.combinat [[0, 0, 0], [-1, 0, 1], [-1, 1, 0]] - sage: s.picard_representatives(3,False) + sage: s.picard_representatives(3,False) # needs sage.combinat [[3, 0, 0], [2, 0, 1], [2, 1, 0]] """ D = self.zero_div() @@ -2142,12 +2151,12 @@ def stable_configs(self, smax=None): sage: s = sandpiles.Complete(3) sage: a = s.stable_configs() - sage: next(a) + sage: next(a) # needs sage.combinat {1: 0, 2: 0} - sage: [i.values() for i in a] + sage: [i.values() for i in a] # needs sage.combinat [[0, 1], [1, 0], [1, 1]] sage: b = s.stable_configs([1,0]) - sage: list(b) + sage: list(b) # needs sage.combinat [{1: 0, 2: 0}, {1: 1, 2: 0}] """ if smax is None: @@ -2317,6 +2326,8 @@ def stationary_density(self): sage: s = sandpiles.Complete(3) sage: s.stationary_density() 10/9 + + sage: # needs sage.combinat sage: s = Sandpile(digraphs.DeBruijn(2,2),'00') sage: s.stationary_density() 9/8 @@ -2378,8 +2389,8 @@ def _set_betti_complexes(self): EXAMPLES:: sage: S = Sandpile({0:{},1:{0: 1, 2: 1, 3: 4},2:{3: 5},3:{1: 1, 2: 1}},0) - sage: S._set_betti_complexes() - sage: '_betti_complexes' in S.__dict__ + sage: S._set_betti_complexes() # needs sage.geometry.polyhedron + sage: '_betti_complexes' in S.__dict__ # needs sage.geometry.polyhedron True """ results = [] @@ -2412,13 +2423,15 @@ def betti_complexes(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: S = Sandpile({0:{},1:{0: 1, 2: 1, 3: 4},2:{3: 5},3:{1: 1, 2: 1}},0) sage: p = S.betti_complexes() sage: p[0] - [{0: -8, 1: 5, 2: 4, 3: 1}, Simplicial complex with vertex set (1, 2, 3) and facets {(3,), (1, 2)}] - sage: S.resolution() + [{0: -8, 1: 5, 2: 4, 3: 1}, + Simplicial complex with vertex set (1, 2, 3) and facets {(3,), (1, 2)}] + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^5 <-- R^5 <-- R^1' - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - @@ -2489,8 +2502,8 @@ def _set_ideal(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_ideal() - sage: '_ideal' in S.__dict__ + sage: S._set_ideal() # needs sage.libs.singular + sage: '_ideal' in S.__dict__ # needs sage.libs.singular True """ from sage.libs.singular.function_factory import ff @@ -2516,8 +2529,9 @@ def unsaturated_ideal(self): sage: S = sandpiles.Diamond() sage: S.unsaturated_ideal().gens() [x1^3 - x3*x2*x0, x2^3 - x3*x1*x0, x3^2 - x2*x1] - sage: S.ideal().gens() - [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] + sage: S.ideal().gens() # needs sage.libs.singular + [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] """ return self._unsaturated_ideal @@ -2537,12 +2551,16 @@ def ideal(self, gens=False): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S.ideal() - Ideal (x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0) of Multivariate Polynomial Ring in x3, x2, x1, x0 over Rational Field - sage: S.ideal(True) - [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] - sage: S.ideal().gens() # another way to get the generators - [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] + sage: S.ideal() # needs sage.libs.singular + Ideal (x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0) + of Multivariate Polynomial Ring in x3, x2, x1, x0 over Rational Field + sage: S.ideal(True) # needs sage.libs.singular + [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] + sage: S.ideal().gens() # another way to get the generators # needs sage.libs.singular + [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] """ if gens: return self._ideal.gens() @@ -2581,8 +2599,8 @@ def _set_resolution(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_resolution() - sage: '_resolution' in S.__dict__ + sage: S._set_resolution() # needs sage.libs.singular + sage: '_resolution' in S.__dict__ # needs sage.libs.singular True """ # get the resolution in singular form @@ -2624,6 +2642,7 @@ def resolution(self, verbose=False): EXAMPLES:: + sage: # needs sage.libs.singular sage: S = Sandpile({0: {}, 1: {0: 1, 2: 1, 3: 4}, 2: {3: 5}, 3: {1: 1, 2: 1}},0) sage: S.resolution() # a Gorenstein sandpile graph 'R^1 <-- R^5 <-- R^5 <-- R^1' @@ -2661,8 +2680,8 @@ def _set_groebner(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_groebner() - sage: '_groebner' in S.__dict__ + sage: S._set_groebner() # needs sage.libs.singular + sage: '_groebner' in S.__dict__ # needs sage.libs.singular True """ self._groebner = self._ideal.groebner_basis() @@ -2679,8 +2698,9 @@ def groebner(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S.groebner() - [x3*x2^2 - x1^2*x0, x2^3 - x3*x1*x0, x3*x1^2 - x2^2*x0, x1^3 - x3*x2*x0, x3^2 - x0^2, x2*x1 - x0^2] + sage: S.groebner() # needs sage.libs.singular + [x3*x2^2 - x1^2*x0, x2^3 - x3*x1*x0, x3*x1^2 - x2^2*x0, + x1^3 - x3*x2*x0, x3^2 - x0^2, x2*x1 - x0^2] """ return self._groebner @@ -2702,7 +2722,7 @@ def betti(self, verbose=True): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - @@ -2710,7 +2730,7 @@ def betti(self, verbose=True): 2: - 4 9 4 ------------------------------ total: 1 6 9 4 - sage: S.betti(False) + sage: S.betti(False) # needs sage.libs.singular [1, 6, 9, 4] """ if verbose: @@ -2731,7 +2751,7 @@ def solve(self): EXAMPLES:: sage: S = Sandpile({0: {}, 1: {2: 2}, 2: {0: 4, 1: 1}}, 0) - sage: S.solve() + sage: Z = S.solve(); Z # needs sage.libs.singular [[-0.707107000000000 + 0.707107000000000*I, 0.707107000000000 - 0.707107000000000*I], [-0.707107000000000 - 0.707107000000000*I, @@ -2744,7 +2764,7 @@ def solve(self): -0.707107000000000 + 0.707107000000000*I], [1, 1], [-1, -1]] - sage: len(_) + sage: len(Z) # needs sage.libs.singular 8 sage: S.group_order() 8 @@ -2779,8 +2799,8 @@ def _set_points(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_points() - sage: '_points' in S.__dict__ + sage: S._set_points() # needs sage.symbolic + sage: '_points' in S.__dict__ # needs sage.symbolic True """ L = self._reduced_laplacian.transpose().dense_matrix() @@ -2811,7 +2831,7 @@ def points(self): :: sage: S = sandpiles.Complete(4) - sage: S.points() + sage: S.points() # needs sage.symbolic [[-I, I, 1], [-I, 1, I]] """ return self._points @@ -3763,10 +3783,13 @@ def add_random(self, distrib=None): ....: m = m.add_random() ....: m, f = m.stabilize(True) ....: a.append(sum(f.values())) - sage: p = list_plot([[log(i+1),log(a.count(i))] for i in [0..max(a)] if a.count(i)]) - sage: p.axes_labels(['log(N)','log(D(N))']) + + sage: # needs sage.plot + sage: p = list_plot([[log(i + 1), log(a.count(i))] + ....: for i in [0..max(a)] if a.count(i)]) + sage: p.axes_labels(['log(N)', 'log(D(N))']) sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) - sage: show(p+t,axes_labels=['log(N)','log(D(N))']) # long time + sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time .. NOTE:: @@ -4145,9 +4168,9 @@ def show(self, sink=True, colors=True, heights=False, directed=None, **kwds): sage: S = sandpiles.Diamond() sage: c = S.identity() - sage: c.show() - sage: c.show(directed=False) - sage: c.show(sink=False,colors=False,heights=True) + sage: c.show() # needs sage.plot + sage: c.show(directed=False) # needs sage.plot + sage: c.show(sink=False, colors=False, heights=True) # needs sage.plot """ if directed: T = DiGraph(self.sandpile()) @@ -4325,8 +4348,8 @@ def __setitem__(self, key, item): sage: S = sandpiles.Cycle(3) sage: D = SandpileDivisor(S,[0,1,1]) - sage: eff = D.effective_div() - sage: D.__dict__ + sage: eff = D.effective_div() # needs sage.geometry.polyhedron + sage: D.__dict__ # needs sage.geometry.polyhedron {'_effective_div': [{0: 0, 1: 1, 2: 1}, {0: 2, 1: 0, 2: 0}], '_polytope': A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices, '_polytope_integer_pts': ((0, 0), (1, 1)), @@ -5197,8 +5220,8 @@ def _set_polytope(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: D._set_polytope() - sage: '_polytope' in D.__dict__ + sage: D._set_polytope() # needs sage.geometry.polyhedron + sage: '_polytope' in D.__dict__ # needs sage.geometry.polyhedron True """ S = self.sandpile() @@ -5216,6 +5239,7 @@ def polytope(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) sage: p = D.polytope() @@ -5248,8 +5272,8 @@ def _set_polytope_integer_pts(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: D._set_polytope_integer_pts() - sage: '_polytope_integer_pts' in D.__dict__ + sage: D._set_polytope_integer_pts() # needs sage.geometry.polyhedron + sage: '_polytope_integer_pts' in D.__dict__ # needs sage.geometry.polyhedron True """ self._polytope_integer_pts = self._polytope.integral_points() @@ -5268,7 +5292,7 @@ def polytope_integer_pts(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: sorted(D.polytope_integer_pts()) + sage: sorted(D.polytope_integer_pts()) # needs sage.geometry.polyhedron [(-2, -1, -1), (-1, -2, -1), (-1, -1, -2), @@ -5276,7 +5300,7 @@ def polytope_integer_pts(self): (0, -1, -1), (0, 0, 0)] sage: D = SandpileDivisor(s,[-1,0,0,0]) - sage: D.polytope_integer_pts() + sage: D.polytope_integer_pts() # needs sage.geometry.polyhedron () """ return deepcopy(self._polytope_integer_pts) @@ -5289,8 +5313,8 @@ def _set_effective_div(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: D._set_effective_div() - sage: '_effective_div' in D.__dict__ + sage: D._set_effective_div() # needs sage.geometry.polyhedron + sage: '_effective_div' in D.__dict__ # needs sage.geometry.polyhedron True """ S = self.sandpile() @@ -5319,6 +5343,7 @@ def effective_div(self, verbose=True, with_firing_vectors=False): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) sage: sorted(D.effective_div(), key=str) @@ -5392,8 +5417,8 @@ def _set_rank(self, set_witness=False): True sage: '_rank_witness' in D.__dict__ False - sage: D._set_rank(True) - sage: '_rank_witness' in D.__dict__ + sage: D._set_rank(True) # needs sage.geometry.polyhedron + sage: '_rank_witness' in D.__dict__ # needs sage.geometry.polyhedron True sage: D = SandpileDivisor(s,[1,0,0,0]) sage: D._set_rank() @@ -5460,6 +5485,7 @@ def rank(self, with_witness=False): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: S = sandpiles.Complete(4) sage: D = SandpileDivisor(S,[4,2,0,0]) sage: D.rank() @@ -5467,19 +5493,21 @@ def rank(self, with_witness=False): sage: D.rank(True) (3, {0: 3, 1: 0, 2: 1, 3: 0}) sage: E = _[1] - sage: (D - E).rank() + sage: (D - E).rank() # needs sage.rings.number_field -1 Riemann-Roch theorem:: + sage: # needs sage.geometry.polyhedron sage: D.rank() - (S.canonical_divisor()-D).rank() == D.deg() + 1 - S.genus() True Riemann-Roch theorem:: + sage: # needs sage.geometry.polyhedron sage: D.rank() - (S.canonical_divisor()-D).rank() == D.deg() + 1 - S.genus() True - sage: S = Sandpile({0:[1,1,1,2],1:[0,0,0,1,1,1,2,2],2:[2,2,1,1,0]},0) # multigraph with loops + sage: S = Sandpile({0:[1,1,1,2],1:[0,0,0,1,1,1,2,2],2:[2,2,1,1,0]},0) # multigraph with loops sage: D = SandpileDivisor(S,[4,2,0]) sage: D.rank(True) (2, {0: 1, 1: 1, 2: 1}) @@ -5492,7 +5520,7 @@ def rank(self, with_witness=False): sage: D.rank(True) (0, {0: 0, 1: 0, 2: 1}) sage: E = D.rank(True)[1] - sage: (D - E).effective_div() + sage: (D - E).effective_div() # needs sage.rings.number_field [] .. NOTE:: @@ -5519,8 +5547,8 @@ def _set_r_of_D(self, verbose=False): EXAMPLES:: sage: S = sandpiles.Cycle(6) - sage: D = SandpileDivisor(S, [0,0,0,0,0,4]) # optional - 4ti2 - sage: D._set_r_of_D() # optional - 4ti2 + sage: D = SandpileDivisor(S, [0,0,0,0,0,4]) # optional - 4ti2 + sage: D._set_r_of_D() # optional - 4ti2 """ eff = self.effective_div() n = self._sandpile.num_verts() @@ -5573,7 +5601,7 @@ def weierstrass_rank_seq(self, v='sink'): sage: s = sandpiles.House() sage: K = s.canonical_divisor() - sage: [K.weierstrass_rank_seq(v) for v in s.vertices(sort=True)] + sage: [K.weierstrass_rank_seq(v) for v in s.vertices(sort=True)] # needs sage.geometry.polyhedron [(1, 0, -1), (1, 0, -1), (1, 0, -1), (1, 0, -1), (1, 0, 0, -1)] """ s = self.sandpile() @@ -5613,13 +5641,14 @@ def weierstrass_gap_seq(self, v='sink', weight=True): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.Cycle(4) sage: D = SandpileDivisor(s,[2,0,0,0]) sage: [D.weierstrass_gap_seq(v,False) for v in s.vertices(sort=True)] [(1, 3), (1, 2), (1, 3), (1, 2)] sage: [D.weierstrass_gap_seq(v) for v in s.vertices(sort=True)] [((1, 3), 1), ((1, 2), 0), ((1, 3), 1), ((1, 2), 0)] - sage: D.weierstrass_gap_seq() # gap sequence at sink vertex, 0 + sage: D.weierstrass_gap_seq() # gap sequence at sink vertex, 0 ((1, 3), 1) sage: D.weierstrass_rank_seq() # rank sequence at the sink vertex (1, 0, 0, -1) @@ -5655,6 +5684,7 @@ def is_weierstrass_pt(self, v='sink'): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.House() sage: K = s.canonical_divisor() sage: K.weierstrass_rank_seq() # sequence at the sink vertex, 0 @@ -5682,8 +5712,8 @@ def _set_weierstrass_pts(self): sage: s = sandpiles.Diamond() sage: D = SandpileDivisor(s, [2,1,0,0]) - sage: D._set_weierstrass_pts() - sage: '_weierstrass_pts' in D.__dict__ + sage: D._set_weierstrass_pts() # needs sage.geometry.polyhedron + sage: '_weierstrass_pts' in D.__dict__ # needs sage.geometry.polyhedron True """ self._weierstrass_pts = tuple([v for v in self.sandpile().vertices(sort=True) @@ -5705,9 +5735,9 @@ def weierstrass_pts(self, with_rank_seq=False): sage: s = sandpiles.House() sage: K = s.canonical_divisor() - sage: K.weierstrass_pts() + sage: K.weierstrass_pts() # needs sage.geometry.polyhedron (4,) - sage: K.weierstrass_pts(True) + sage: K.weierstrass_pts(True) # needs sage.geometry.polyhedron [(4, (1, 0, 0, -1))] .. NOTE:: @@ -5739,12 +5769,12 @@ def weierstrass_div(self, verbose=True): sage: s = sandpiles.Diamond() sage: D = SandpileDivisor(s,[4,2,1,0]) - sage: [D.weierstrass_rank_seq(v) for v in s] + sage: [D.weierstrass_rank_seq(v) for v in s] # needs sage.geometry.polyhedron [(5, 4, 3, 2, 1, 0, 0, -1), (5, 4, 3, 2, 1, 0, -1), (5, 4, 3, 2, 1, 0, 0, 0, -1), (5, 4, 3, 2, 1, 0, 0, -1)] - sage: D.weierstrass_div() + sage: D.weierstrass_div() # needs sage.geometry.polyhedron {0: 1, 1: 0, 2: 2, 3: 1} sage: k5 = sandpiles.Complete(5) sage: K = k5.canonical_divisor() @@ -5787,8 +5817,8 @@ def _set_Dcomplex(self): sage: S = sandpiles.Complete(4) sage: D = SandpileDivisor(S, [0,0,1,1]) - sage: D._set_Dcomplex() - sage: '_Dcomplex' in D.__dict__ + sage: D._set_Dcomplex() # needs sage.geometry.polyhedron + sage: '_Dcomplex' in D.__dict__ # needs sage.geometry.polyhedron True """ simp = [] @@ -5824,6 +5854,7 @@ def Dcomplex(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: S = sandpiles.House() sage: p = SandpileDivisor(S, [1,2,1,0,0]).Dcomplex() sage: p.homology() @@ -5852,7 +5883,7 @@ def betti(self): sage: S = sandpiles.Cycle(3) sage: D = SandpileDivisor(S, [2,0,1]) - sage: D.betti() + sage: D.betti() # needs sage.geometry.polyhedron {0: 1, 1: 1} .. NOTE:: @@ -6045,8 +6076,8 @@ def show(self, heights=True, directed=None, **kwds): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: D = SandpileDivisor(S,[1,-2,0,2]) - sage: D.show(graph_border=True,vertex_size=700,directed=False) + sage: D = SandpileDivisor(S, [1,-2,0,2]) + sage: D.show(graph_border=True, vertex_size=700, directed=False) # needs sage.plot """ if directed: T = DiGraph(self.sandpile()) @@ -6097,7 +6128,7 @@ def sandlib(selector=None): riemann-roch1 : directed graph with postulation 9 and 3 maximal weight superstables riemann-roch2 : directed graph with a superstable not majorized by a maximal superstable sage: S = sandlib('gor') - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^5 <-- R^5 <-- R^1' """ # The convention is for the sink to be zero. @@ -6289,7 +6320,7 @@ def glue_graphs(g, h, glue_g, glue_h): sage: S = Sandpile(z,'sink') sage: S.h_vector() [1, 6, 17, 31, 41, 41, 31, 17, 6, 1] - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^7 <-- R^21 <-- R^35 <-- R^35 <-- R^21 <-- R^7 <-- R^1' .. NOTE:: @@ -6361,8 +6392,9 @@ def firing_graph(S, eff): sage: S = sandpiles.Cycle(6) sage: D = SandpileDivisor(S, [1,1,1,1,2,0]) - sage: eff = D.effective_div() - sage: firing_graph(S,eff).show3d(edge_size=.005,vertex_size=0.01) # long time + sage: eff = D.effective_div() # needs sage.geometry.polyhedron + sage: firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.geometry.polyhedron sage.plot + ....: vertex_size=0.01) """ g = DiGraph() g.add_vertices(range(len(eff))) @@ -6397,8 +6429,9 @@ def parallel_firing_graph(S, eff): sage: S = sandpiles.Cycle(6) sage: D = SandpileDivisor(S, [1,1,1,1,2,0]) - sage: eff = D.effective_div() - sage: parallel_firing_graph(S,eff).show3d(edge_size=.005,vertex_size=0.01) # long time + sage: eff = D.effective_div() # needs sage.geometry.polyhedron + sage: parallel_firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.geometry.polyhedron sage.plot + ....: vertex_size=0.01) """ g = DiGraph() g.add_vertices(range(len(eff))) @@ -6436,8 +6469,8 @@ def admissible_partitions(S, k): sage: from sage.sandpiles.sandpile import admissible_partitions sage: from sage.sandpiles.sandpile import partition_sandpile sage: S = sandpiles.Cycle(4) - sage: P = [admissible_partitions(S, i) for i in [2,3,4]] - sage: P + sage: P = [admissible_partitions(S, i) for i in [2,3,4]] # needs sage.combinat + sage: P # needs sage.combinat [[{{0, 2, 3}, {1}}, {{0, 3}, {1, 2}}, {{0, 1, 3}, {2}}, @@ -6449,12 +6482,12 @@ def admissible_partitions(S, k): {{0}, {1, 2}, {3}}, {{0, 1}, {2}, {3}}], [{{0}, {1}, {2}, {3}}]] - sage: for p in P: + sage: for p in P: # needs sage.combinat ....: sum([partition_sandpile(S, i).betti(verbose=False)[-1] for i in p]) 6 8 3 - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - @@ -6494,13 +6527,13 @@ def partition_sandpile(S, p): sage: from sage.sandpiles.sandpile import admissible_partitions, partition_sandpile sage: S = sandpiles.Cycle(4) - sage: P = [admissible_partitions(S, i) for i in [2,3,4]] - sage: for p in P: + sage: P = [admissible_partitions(S, i) for i in [2,3,4]] # needs sage.combinat + sage: for p in P: # needs sage.combinat ....: sum([partition_sandpile(S, i).betti(verbose=False)[-1] for i in p]) 6 8 3 - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 958a402da19..5a4f9f5f4ce 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2009,7 +2009,7 @@ def _points_via_singular(self, sort=True): .. note:: The Brill-Noether package does not always work (i.e., the - 'bn' algorithm. When it fails a RuntimeError exception is + 'bn' algorithm. When it fails a :class:`RuntimeError` exception is raised. """ f = self.defining_polynomial()._singular_() @@ -2150,7 +2150,7 @@ def rational_points(self, algorithm="enum", sort=True): .. NOTE:: The Brill-Noether package does not always work (i.e., the 'bn' - algorithm. When it fails a RuntimeError exception is raised. + algorithm. When it fails a :class:`RuntimeError` exception is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 6195ec76a5e..cccfce646b3 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -69,7 +69,10 @@ use of univariate vs. bivariate polynomials and rational functions. - Lorenz Panny (2022-04): major cleanup of code and documentation + - Lorenz Panny (2022): inseparable duals + +- Rémy Oudompheng (2023): implementation of the BMSS algorithm """ # **************************************************************************** @@ -79,7 +82,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from copy import copy +from copy import copy, deepcopy from sage.structure.sequence import Sequence @@ -1432,7 +1435,7 @@ def __neg__(self): sage: negphi.rational_maps() ((x^2 + (-a)*x - 2)/(x + (-a)), (-x^2*y + (2*a)*x*y - y)/(x^2 + (-2*a)*x - 1)) """ - output = copy(self) + output = deepcopy(self) output._set_post_isomorphism(negation_morphism(output._codomain)) return output @@ -3313,19 +3316,93 @@ def _composition_impl(left, right): NotImplemented """ if isinstance(left, WeierstrassIsomorphism) and isinstance(right, EllipticCurveIsogeny): - result = copy(right) + result = deepcopy(right) result._set_post_isomorphism(left) return result if isinstance(left, EllipticCurveIsogeny) and isinstance(right, WeierstrassIsomorphism): assert isinstance(left, EllipticCurveIsogeny) - result = copy(left) + result = deepcopy(left) result._set_pre_isomorphism(right) return result return NotImplemented +def compute_isogeny_bmss(E1, E2, l): + r""" + Compute the kernel polynomial of the unique normalized isogeny + of degree ``l`` between ``E1`` and ``E2``. + + Both curves must be given in short Weierstrass form, and the + characteristic must be either `0` or no smaller than `4l+4`. + + ALGORITHM: [BMSS2006]_, algorithm *fastElkies'*. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_bmss + sage: E1 = EllipticCurve(GF(167), [153, 112]) + sage: E2 = EllipticCurve(GF(167), [56, 40]) + sage: compute_isogeny_bmss(E1, E2, 13) + x^6 + 139*x^5 + 73*x^4 + 139*x^3 + 120*x^2 + 88*x + """ + # Original author of this function: Rémy Oudompheng. + # https://github.com/remyoudompheng/isogeny_weber/blob/64289127a337ac1bf258b711e02fea02b7df5275/isogeny_weber/isogenies.py#L272-L332 + # Released under the MIT license: https://github.com/remyoudompheng/isogeny_weber/blob/64289127a337ac1bf258b711e02fea02b7df5275/LICENSE + # Slightly adjusted for inclusion in the Sage library. + if E1.a1() or E1.a2() or E1.a3(): + raise ValueError('E1 must be a short Weierstrass curve') + if E2.a1() or E2.a2() or E2.a3(): + raise ValueError('E2 must be a short Weierstrass curve') + char = E1.base_ring().characteristic() + if char != 0 and char < 4*l + 4: + raise ValueError('characteristic must be at least 4*degree+4') + Rx, x = E1.base_ring()["x"].objgen() + # Compute C = 1/(1 + Ax^4 + Bx^6) mod x^4l + A, B = E1.a4(), E1.a6() + C = (1 + A * x**4 + B * x**6).inverse_series_trunc(4 * l) + # Solve differential equation + # The number of terms doubles at each iteration. + # S'^2 = G(x,S) = (1 + A2 S^4 + B2 S^6) / (1 + Ax^4 + Bx^6) + # S = x + O(x^2) + A2, B2 = E2.a4(), E2.a6() + S = x + (A2 - A) / 10 * x**5 + (B2 - B) / 14 * x**7 + sprec = 8 + while sprec < 4 * l: + assert sprec % 2 == 0 + if sprec > 2 * l: + sprec = 2 * l + # s1 => s1 + x^k s2 + # 2 s1' s2' - dG/dS(x, s1) s2 = G(x, s1) - s1'2 + s1 = S + ds1 = s1.derivative() + s1pows = [1, s1] + while len(s1pows) < 7: + s1pows.append(s1._mul_trunc_(s1pows[-1], 2 * sprec)) + GS = C * (1 + A2 * s1pows[4] + B2 * s1pows[6]) + dGS = C * (4 * A2 * s1pows[3] + 6 * B2 * s1pows[5]) + # s2' = (dGS / 2s1') s2 + (G(x, s1) - s1'2) / (2s1') + denom = (2 * ds1).inverse_series_trunc(2 * sprec) + a = dGS._mul_trunc_(denom, 2 * sprec) + b = (GS - ds1**2)._mul_trunc_(denom, 2 * sprec) + s2 = a.add_bigoh(2 * sprec).solve_linear_de(prec=2 * sprec, b=b, f0=0) + S = s1 + Rx(s2) + sprec = 2 * sprec + # Reconstruct: + # S = x * T(x^2) + # Compute U = 1/T^2 + # Reconstruct N(1/x) / D(1/x) = U + T = Rx([S[2 * i + 1] for i in range(2 * l)]) + U = T._mul_trunc_(T, 2 * l).inverse_series_trunc(2 * l) + _, Q = Rx(U).rational_reconstruction(x ** (2 * l), l, l) + Q = Q.add_bigoh((l + 1) // 2) + if not Q.is_square(): + raise ValueError(f"the two curves are not linked by a cyclic normalized isogeny of degree {l}") + Q = Q.sqrt() + ker = Rx(Q).reverse(degree=l//2) + return ker.monic() + def compute_isogeny_stark(E1, E2, ell): r""" Return the kernel polynomial of an isogeny of degree ``ell`` @@ -3437,10 +3514,11 @@ def compute_isogeny_stark(E1, E2, ell): from sage.misc.superseded import deprecated_function_alias compute_isogeny_starks = deprecated_function_alias(34871, compute_isogeny_stark) -def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): + +def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm=None): r""" - Return the kernel polynomial of an isogeny of degree ``ell`` - from ``E1`` to ``E2``. + Return the kernel polynomial of a cyclic, separable, normalized + isogeny of degree ``ell`` from ``E1`` to ``E2``. INPUT: @@ -3450,7 +3528,9 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): - ``ell`` -- the degree of an isogeny from ``E1`` to ``E2`` - - ``algorithm`` -- currently only ``"stark"`` (default) is implemented + - ``algorithm`` -- ``None`` (default, choose automatically) or + ``"bmss"`` (:func:`compute_isogeny_bmss`) or + ``"stark"`` (:func:`compute_isogeny_stark`) OUTPUT: @@ -3507,9 +3587,19 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): from sage.misc.superseded import deprecation deprecation(34871, 'The "starks" algorithm is being renamed to "stark".') algorithm = 'stark' - if algorithm != "stark": - raise NotImplementedError(f'unknown algorithm {algorithm}') - return compute_isogeny_stark(E1, E2, ell).radical() + + if algorithm is None: + char = E1.base_ring().characteristic() + if char != 0 and char < 4*ell + 4: + raise NotImplementedError(f'no algorithm for computing kernel polynomial from domain and codomain is implemented for degree {ell} and characteristic {char}') + algorithm = 'stark' if ell < 10 else 'bmss' + + if algorithm == 'bmss': + return compute_isogeny_bmss(E1, E2, ell) + if algorithm == 'stark': + return compute_isogeny_stark(E1, E2, ell).radical() + + raise NotImplementedError(f'unknown algorithm {algorithm}') def compute_intermediate_curves(E1, E2): r""" diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 70848089476..7dd65c95749 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -2048,3 +2048,72 @@ def compute_model(E, name): return E.montgomery_model() raise NotImplementedError(f'cannot compute {name} model') + +def point_of_order(E, l): + r""" + Given an elliptic curve `E` over a finite field or a number field + and an integer `\ell \geq 1`, construct a point of order `\ell` on `E`, + possibly defined over an extension of the base field of `E`. + + Currently only prime values of `\ell` are supported. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.ell_field import point_of_order + sage: E = EllipticCurve(GF(101), [1,2,3,4,5]) + sage: P = point_of_order(E, 5); P + (50*Y^5 + 48*Y^4 + 26*Y^3 + 37*Y^2 + 48*Y + 15 : 25*Y^5 + 31*Y^4 + 79*Y^3 + 39*Y^2 + 3*Y + 20 : 1) + sage: P.base_ring() + Finite Field in Y of size 101^6 + sage: P.order() + 5 + sage: P.curve().a_invariants() + (1, 2, 3, 4, 5) + + :: + + sage: from sage.schemes.elliptic_curves.ell_field import point_of_order + sage: E = EllipticCurve(QQ, [7,7]) + sage: P = point_of_order(E, 3); P # random + (x : -Y : 1) + sage: P.base_ring() + Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field + sage: P.order() + 3 + sage: P.curve().a_invariants() + (0, 0, 0, 7, 7) + """ + # Construct the field extension defined by the given polynomial, + # in such a way that the result is recognized by Sage as a field. + def ffext(poly): + rng = poly.parent() + fld = rng.base_ring() + if fld in FiniteFields(): + # Workaround: .extension() would return a PolynomialQuotientRing + # rather than another FiniteField. + return poly.splitting_field(rng.variable_name()) + return fld.extension(poly, rng.variable_name()) + + l = ZZ(l) + if l == 1: + return E(0) + + if not l.is_prime(): + raise NotImplementedError('composite orders are currently unsupported') + + xpoly = E.division_polynomial(l) + if xpoly.degree() < 1: # supersingular and l == p + raise ValueError('curve does not have any points of the specified order') + + mu = xpoly.factor()[0][0] + FF = ffext(mu) + xx = mu.any_root(ring=FF, assume_squarefree=True) + + Y = polygen(FF, 'Y') + ypoly = E.defining_polynomial()(xx, Y, 1) + if ypoly.is_irreducible(): + FF = ffext(ypoly) + xx = FF(xx) + + EE = E.change_ring(FF) + return EE.lift_x(xx) diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 8e7fb204892..5b569ae54e3 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -729,7 +729,7 @@ def lift_x(self, x, all=False, extend=False): - ``all`` (bool, default False) -- if True, return a (possibly empty) list of all points; if False, return just one point, - or raise a ValueError if there are none. + or raise a :class:`ValueError` if there are none. - ``extend`` (bool, default False) -- diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 54777488572..7f5752b9e92 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -2256,7 +2256,7 @@ def rank(self, **kwds): If the upper and lower bounds given by Simon two-descent are the same, then the rank has been uniquely identified and we - return this. Otherwise, we raise a ValueError with an error + return this. Otherwise, we raise a :class:`ValueError` with an error message specifying the upper and lower bounds. .. NOTE:: diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index e257b511371..8861f643198 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -432,7 +432,7 @@ def _non_surjective(E, patience=100): - ``list`` -- A list of primes where mod-`p` representation is very likely not surjective. At any prime not in this list, the representation is - definitely surjective. If E has CM, a ValueError is raised. + definitely surjective. If E has CM, a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 58375d02a64..995420ae438 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -23,6 +23,8 @@ the common :class:`EllipticCurveHom` interface. - Lorenz Panny (2022): :meth:`~EllipticCurveHom.matrix_on_subgroup` + +- Lorenz Panny (2023): :meth:`~EllipticCurveHom.trace`, :meth:`~EllipticCurveHom.characteristic_polynomial` """ from sage.misc.cachefunc import cached_method from sage.structure.richcmp import richcmp_not_equal, richcmp, op_EQ, op_NE @@ -31,6 +33,7 @@ from sage.arith.misc import integer_floor +from sage.rings.integer_ring import ZZ from sage.rings.finite_rings import finite_field_base from sage.rings.number_field import number_field_base @@ -283,6 +286,95 @@ def degree(self): except AttributeError: raise NotImplementedError('children must implement') + @cached_method + def trace(self): + r""" + Return the trace of this elliptic-curve morphism, which must + be an endomorphism. + + ALGORITHM: :func:`compute_trace_generic` + + EXAMPLES:: + + sage: E = EllipticCurve(QQ, [42, 42]) + sage: m5 = E.scalar_multiplication(5) + sage: m5.trace() + 10 + + :: + + sage: E = EllipticCurve(GF(71^2), [45, 45]) + sage: P = E.lift_x(27) + sage: P.order() + 71 + sage: tau = E.isogeny(P, codomain=E) + sage: tau.trace() + -1 + + TESTS: + + Make sure the cached value of the trace is not accidentally + copied on composition with automorphisms:: + + sage: aut = E.automorphisms()[1] # [-1] + sage: (aut * tau).trace() + 1 + + It also works for more complicated :class:`EllipticCurveHom` + children:: + + sage: tau = E.isogeny(P, codomain=E, algorithm='velusqrt') + sage: tau.trace() + -1 + + Check that negation commutes with taking the trace:: + + sage: (-tau).trace() + 1 + """ + F = self.domain().base_field() + if F.characteristic().is_zero(): + d = self.degree() + s = self.scaling_factor() + return ZZ(s + d/s) + return compute_trace_generic(self) + + def characteristic_polynomial(self): + r""" + Return the characteristic polynomial of this elliptic-curve + morphism, which must be an endomorphism. + + .. SEEALSO:: + + - :meth:`degree` + - :meth:`trace` + + EXAMPLES:: + + sage: E = EllipticCurve(QQ, [42, 42]) + sage: m5 = E.scalar_multiplication(5) + sage: m5.characteristic_polynomial() + x^2 - 10*x + 25 + + :: + + sage: E = EllipticCurve(GF(71), [42, 42]) + sage: pi = E.frobenius_endomorphism() + sage: pi.characteristic_polynomial() + x^2 - 8*x + 71 + sage: E.frobenius().charpoly() + x^2 - 8*x + 71 + + TESTS:: + + sage: m5.characteristic_polynomial().parent() + Univariate Polynomial Ring in x over Integer Ring + sage: pi.characteristic_polynomial().parent() + Univariate Polynomial Ring in x over Integer Ring + """ + R = ZZ['x'] + return R([self.degree(), -self.trace(), 1]) + def kernel_polynomial(self): r""" Return the kernel polynomial of this elliptic-curve morphism. @@ -692,7 +784,7 @@ def __hash__(self): sage: EllipticCurveIsogeny(E,X^3-13*X^2-58*X+503,check=False) Isogeny of degree 7 from Elliptic Curve defined by y^2 + x*y = x^3 - x^2 - 107*x + 552 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 - x^2 - 5252*x - 178837 over Rational Field """ - return hash((self.domain(), self.codomain(), self.kernel_polynomial())) + return hash((self.domain(), self.codomain(), self.kernel_polynomial(), self.scaling_factor())) def as_morphism(self): r""" @@ -970,8 +1062,6 @@ def find_post_isomorphism(phi, psi): raise ValueError('codomains not isomorphic') F = E.base_ring() - from sage.rings.finite_rings import finite_field_base - from sage.rings.number_field import number_field_base if isinstance(F, finite_field_base.FiniteField): while len(isos) > 1: @@ -1006,3 +1096,109 @@ def find_post_isomorphism(phi, psi): # found no suitable isomorphism -- either doesn't exist or a bug raise ValueError('isogenies not equal up to post-isomorphism') + + +def compute_trace_generic(phi): + r""" + Compute the trace of the given elliptic-curve endomorphism. + + ALGORITHM: Simple variant of Schoof's algorithm. + For enough small primes `\ell`, we find an order-`\ell` point `P` + on `E` and use a discrete-logarithm calculation to find the unique + scalar `t_\ell \in \{0,...,\ell-1\}` such that + `\varphi^2(P)+[\deg(\varphi)]P = [t_\ell]\varphi(P)`. + Then `t_\ell` equals the trace of `\varphi` modulo `\ell`, which + can therefore be recovered using the Chinese remainder theorem. + + EXAMPLES: + + It works over finite fields:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: E = EllipticCurve(GF(31337), [1,1]) + sage: compute_trace_generic(E.frobenius_endomorphism()) + 314 + + It works over `\QQ`:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: E = EllipticCurve(QQ, [1,2,3,4,5]) + sage: dbl = E.scalar_multiplication(2) + sage: compute_trace_generic(dbl) + 4 + + It works over number fields (for a CM curve):: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: x = polygen(QQ) + sage: K. = NumberField(5*x^2 - 2*x + 1) + sage: E = EllipticCurve(K, [1,0]) + sage: phi = E.isogeny([t,0,1], codomain=E) # phi = 2 + i + sage: compute_trace_generic(phi) + 4 + + TESTS: + + Check on random elliptic curves over finite fields that + the result for Frobenius matches + :meth:`~sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field.trace_of_frobenius`:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: p = random_prime(10^3) + sage: e = randrange(1, ceil(log(10^5,p))) + sage: F. = GF((p, e)) + sage: E = choice(EllipticCurve(j=F.random_element()).twists()) + sage: pi = E.frobenius_endomorphism() + sage: compute_trace_generic(pi) == E.trace_of_frobenius() + True + + Check that the nonexistence of `p`-torsion for supersingular curves + does not cause trouble:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: E = EllipticCurve(GF(5), [0,1]) + sage: E.division_polynomial(5) + 4 + sage: m7 = E.scalar_multiplication(7) + sage: compute_trace_generic(-m7) + -14 + """ + from sage.rings.finite_rings.integer_mod import Mod + from sage.groups.generic import discrete_log + from sage.sets.primes import Primes + from sage.schemes.elliptic_curves.ell_field import point_of_order + + E = phi.domain() + if phi.codomain() != E: + raise ValueError('trace only makes sense for endomorphisms') + + d = phi.degree() + + M = 4 * d.isqrt() + 1 # |trace| <= 2 sqrt(deg) + tr = Mod(0,1) + + F = E.base_field() + p = F.characteristic() + if p: + s = phi.scaling_factor() + if s: + tr = Mod(ZZ(s + d/s), p) + + for l in Primes(): + if tr.modulus() >= M: + break + try: + P = point_of_order(E, l) + except ValueError: + continue # supersingular and l == p + + Q = phi._eval(P) + if not Q: # we learn nothing when P lies in the kernel + continue + R = phi._eval(Q) + t = discrete_log(R + d*P, Q, ord=l, operation='+') +# assert not R - t*Q + d*P + + tr = tr.crt(Mod(t, l)) + + return tr.lift_centered() diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index fe07917abaa..3597123f188 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -813,14 +813,14 @@ def is_real(self): """ return self.real_flag != 0 - def is_rectangular(self): + def is_rectangular(self) -> bool: r""" - Return True if this period lattice is rectangular. + Return ``True`` if this period lattice is rectangular. .. NOTE:: - Only defined for real lattices; a RuntimeError is raised for - non-real lattices. + Only defined for real lattices; a :class:`RuntimeError` + is raised for non-real lattices. EXAMPLES:: @@ -864,8 +864,8 @@ def real_period(self, prec=None, algorithm='sage'): .. NOTE:: - Only defined for real lattices; a RuntimeError is raised for - non-real lattices. + Only defined for real lattices; a :class:`RuntimeError` + is raised for non-real lattices. EXAMPLES:: diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index f110f55cfc9..9d0bb024a12 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -354,9 +354,9 @@ def __len__(self): EXAMPLES:: - sage: C = cartesian_product([ZZ, QQ, CC]) - sage: e = C.random_element() - sage: len(e) + sage: C = cartesian_product([ZZ, QQ, CC]) # needs sage.rings.real_mpfr + sage: e = C.random_element() # needs sage.rings.real_mpfr + sage: len(e) # needs sage.rings.real_mpfr 3 """ return len(self.value) @@ -368,7 +368,7 @@ def cartesian_factors(self): EXAMPLES:: sage: A = cartesian_product([ZZ, RR]) - sage: A((1, 1.23)).cartesian_factors() + sage: A((1, 1.23)).cartesian_factors() # needs sage.rings.real_mpfr (1, 1.23000000000000) sage: type(_) <... 'tuple'> diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 92f17647315..e29f0124224 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -62,11 +62,12 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope sage: 7/2 in EvensAndOdds False - sage: var('y') + sage: var('y') # needs sage.symbolic y - sage: SmallOdds = ConditionSet(ZZ, is_odd, abs(y) <= 11, vars=[y]); SmallOdds + sage: SmallOdds = ConditionSet(ZZ, is_odd, abs(y) <= 11, vars=[y]); SmallOdds # needs sage.symbolic { y ∈ Integer Ring : abs(y) <= 11, (y) } + sage: # needs sage.geometry.polyhedron sage: P = polytopes.cube(); P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices sage: P.rename("P") @@ -74,16 +75,17 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope { x ∈ P : at 0x...>(x) } sage: vector([1, 0, 0]) in P_inter_B True - sage: vector([1, 1, 1]) in P_inter_B + sage: vector([1, 1, 1]) in P_inter_B # needs sage.symbolic False + sage: # needs sage.symbolic sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 1.2; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 1.20000000000000 - sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again + sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again # needs sage.geometry.polyhedron { (x, y, z) ∈ P : sqrt(x^2 + y^2 + z^2) < 1.20000000000000 } - sage: vector([1, 0, 0]) in P_inter_B_again + sage: vector([1, 0, 0]) in P_inter_B_again # needs sage.geometry.polyhedron True - sage: vector([1, 1, 1]) in P_inter_B_again + sage: vector([1, 1, 1]) in P_inter_B_again # needs sage.geometry.polyhedron False Iterating over subsets determined by predicates:: @@ -104,24 +106,25 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope Using ``ConditionSet`` without predicates provides a way of attaching variable names to a set:: - sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 - { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring } - sage: Z3.variable_names() + sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 # needs sage.modules + { (x, y, z) ∈ Ambient free module of rank 3 + over the principal ideal domain Integer Ring } + sage: Z3.variable_names() # needs sage.modules ('x', 'y', 'z') - sage: Z3.arguments() + sage: Z3.arguments() # needs sage.modules sage.symbolic (x, y, z) - sage: Q4. = ConditionSet(QQ^4); Q4 + sage: Q4. = ConditionSet(QQ^4); Q4 # needs sage.modules sage.symbolic { (a, b, c, d) ∈ Vector space of dimension 4 over Rational Field } - sage: Q4.variable_names() + sage: Q4.variable_names() # needs sage.modules sage.symbolic ('a', 'b', 'c', 'd') - sage: Q4.arguments() + sage: Q4.arguments() # needs sage.modules sage.symbolic (a, b, c, d) TESTS:: - sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas - sage: TestSuite(P_inter_B_again).run() + sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas # needs sage.geometry.polyhedron + sage: TestSuite(P_inter_B_again).run() # needs sage.geometry.polyhedron sage.symbolic """ @staticmethod def __classcall_private__(cls, universe, *predicates, vars=None, names=None, category=None): @@ -130,9 +133,9 @@ def __classcall_private__(cls, universe, *predicates, vars=None, names=None, cat TESTS:: - sage: ConditionSet(ZZ, names=["x"]) is ConditionSet(ZZ, names=x) + sage: ConditionSet(ZZ, names=["x"]) is ConditionSet(ZZ, names=x) # needs sage.symbolic True - sage: ConditionSet(RR, x > 0, names=x) is ConditionSet(RR, (x > 0).function(x)) + sage: ConditionSet(RR, x > 0, names=x) is ConditionSet(RR, (x > 0).function(x)) # needs sage.symbolic True """ if category is None: @@ -224,10 +227,10 @@ def _repr_(self): EXAMPLES:: - sage: var('t') # parameter + sage: var('t') # parameter # needs sage.symbolic t - sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) - sage: ZeroDimButNotNullary._repr_() + sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) # needs sage.symbolic + sage: ZeroDimButNotNullary._repr_() # needs sage.symbolic '{ q ∈ Ambient free module of rank 0 over the principal ideal domain Integer Ring : t > 0 }' """ @@ -257,10 +260,12 @@ def _repr_condition(self, predicate): sage: Evens = ConditionSet(ZZ, is_even) sage: Evens._repr_condition(is_even) '(x)' + + sage: # needs sage.symbolic sage: BigSin = ConditionSet(RR, sin(x) > 0.9, vars=[x]) sage: BigSin._repr_condition(BigSin._predicates[0]) 'sin(x) > 0.900000000000000' - sage: var('t') # parameter + sage: var('t') # parameter t sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) sage: ZeroDimButNotNullary._repr_condition(ZeroDimButNotNullary._predicates[0]) @@ -285,9 +290,9 @@ def arguments(self): sage: Odds = ConditionSet(ZZ, is_odd); Odds { x ∈ Integer Ring : (x) } - sage: args = Odds.arguments(); args + sage: args = Odds.arguments(); args # needs sage.symbolic (x,) - sage: args[0].parent() + sage: args[0].parent() # needs sage.symbolic Symbolic Ring """ from sage.symbolic.ring import SR @@ -339,6 +344,7 @@ def _call_predicate(self, predicate, element): TESTS:: + sage: # needs sage.modules sage.symbolic sage: TripleDigits = ZZ^3 sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 @@ -350,6 +356,7 @@ def _call_predicate(self, predicate, element): sage: SmallTriples._call_predicate(predicate, element) sqrt(14) < 12 + sage: # needs sage.modules sage.symbolic sage: var('t') t sage: TinyUniverse = ZZ^0 @@ -372,6 +379,7 @@ def _an_element_(self): TESTS:: + sage: # needs sage.modules sage.symbolic sage: TripleDigits = ZZ^3 sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 @@ -406,6 +414,7 @@ def _sympy_(self): EXAMPLES:: + sage: # needs sympy sage.modules sage.symbolic sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples @@ -418,17 +427,17 @@ def _sympy_(self): True sage: (5, 7, 9) in ST False - sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval { x ∈ Real Field with 53 bits of precision : x >= -7, x <= 4 } sage: Interval._sympy_() - ConditionSet(x, (x >= -7) & (x <= 4), SageSet(Real Field with 53 bits of precision)) + ConditionSet(x, (x >= -7) & (x <= 4), + SageSet(Real Field with 53 bits of precision)) If a predicate is not symbolic, we fall back to creating a wrapper:: sage: Evens = ConditionSet(ZZ, is_even); Evens { x ∈ Integer Ring : (x) } - sage: Evens._sympy_() + sage: Evens._sympy_() # needs sympy sage.symbolic SageSet({ x ∈ Integer Ring : (x) }) """ from sage.interfaces.sympy import sympy_init @@ -463,10 +472,12 @@ def intersection(self, X): EXAMPLES:: + sage: # needs sage.modules sage.symbolic sage: in_small_oblong(x, y) = x^2 + 3 * y^2 <= 42 sage: SmallOblongUniverse = ConditionSet(QQ^2, in_small_oblong) sage: SmallOblongUniverse - { (x, y) ∈ Vector space of dimension 2 over Rational Field : x^2 + 3*y^2 <= 42 } + { (x, y) ∈ Vector space of dimension 2 + over Rational Field : x^2 + 3*y^2 <= 42 } sage: parity_check(x, y) = abs(sin(pi/2*(x + y))) < 1/1000 sage: EvenUniverse = ConditionSet(ZZ^2, parity_check); EvenUniverse { (x, y) ∈ Ambient free module of rank 2 over the principal ideal @@ -480,13 +491,18 @@ def intersection(self, X): Combining two ``ConditionSet``s with different formal variables works correctly. The formal variables of the intersection are taken from ``self``:: - sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong, vars=(y, x)) + sage: # needs sage.modules sage.symbolic + sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong, + ....: vars=(y, x)) sage: SmallMirrorUniverse - { (y, x) ∈ Vector space of dimension 2 over Rational Field : 3*x^2 + y^2 <= 42 } + { (y, x) ∈ Vector space of dimension 2 + over Rational Field : 3*x^2 + y^2 <= 42 } sage: SmallOblongUniverse & SmallMirrorUniverse - { (x, y) ∈ Vector space of dimension 2 over Rational Field : x^2 + 3*y^2 <= 42 } + { (x, y) ∈ Vector space of dimension 2 + over Rational Field : x^2 + 3*y^2 <= 42 } sage: SmallMirrorUniverse & SmallOblongUniverse - { (y, x) ∈ Vector space of dimension 2 over Rational Field : 3*x^2 + y^2 <= 42 } + { (y, x) ∈ Vector space of dimension 2 + over Rational Field : 3*x^2 + y^2 <= 42 } """ if isinstance(X, ConditionSet): return ConditionSet(self.ambient().intersection(X.ambient()), diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index 0dc2f93c20b..4db91f4f058 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -122,7 +122,7 @@ def DisjointSet(arg): or an iterable:: - sage: DisjointSet(4.3) + sage: DisjointSet(4.3) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: 'sage.rings.real_mpfr.RealLiteral' object is not iterable @@ -561,7 +561,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(4,1) sage: e = d.element_to_root_dict(); e {0: 0, 1: 4, 2: 2, 3: 2, 4: 4} - sage: WordMorphism(e) + sage: WordMorphism(e) # needs sage.combinat WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4 """ d = {} @@ -583,9 +583,9 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(3,4) sage: d {{0}, {1, 2, 3, 4}} - sage: g = d.to_digraph(); g + sage: g = d.to_digraph(); g # needs sage.graphs Looped digraph on 5 vertices - sage: g.edges(sort=True) + sage: g.edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] The result depends on the ordering of the union:: @@ -596,7 +596,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(1,4) sage: d {{0}, {1, 2, 3, 4}} - sage: d.to_digraph().edges(sort=True) + sage: d.to_digraph().edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {i: [self._nodes.parent[i]] for i in range(self.cardinality())} @@ -849,7 +849,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: e = d.element_to_root_dict() sage: sorted(e.items()) [(0, 0), (1, 4), (2, 2), (3, 2), (4, 4)] - sage: WordMorphism(e) + sage: WordMorphism(e) # needs sage.combinat WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4 """ d = {} @@ -870,9 +870,9 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: d.union(3,4) sage: d {{0}, {1, 2, 3, 4}} - sage: g = d.to_digraph(); g + sage: g = d.to_digraph(); g # needs sage.graphs Looped digraph on 5 vertices - sage: g.edges(sort=True) + sage: g.edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] The result depends on the ordering of the union:: @@ -883,7 +883,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: d.union(1,4) sage: d {{0}, {1, 2, 3, 4}} - sage: d.to_digraph().edges(sort=True) + sage: d.to_digraph().edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {} diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 3dea567a779..2375f4d191a 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -90,10 +90,12 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): In general the input can be any family:: + sage: # needs sage.combinat sage: U3 = DisjointUnionEnumeratedSets( ....: Family([2,3,4], Permutations, lazy=True)) sage: U3 - Disjoint union of Lazy family ((i))_{i in [2, 3, 4]} + Disjoint union of Lazy family + ((i))_{i in [2, 3, 4]} sage: U3.cardinality() 32 sage: it = iter(U3) @@ -104,10 +106,12 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): This allows for infinite unions:: + sage: # needs sage.combinat sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Permutations)) sage: U4 - Disjoint union of Lazy family ((i))_{i in Non negative integers} + Disjoint union of Lazy family + ((i))_{i in Non negative integers} sage: U4.cardinality() +Infinity sage: it = iter(U4) @@ -126,6 +130,7 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): We demonstrate the ``keepkey`` option:: + sage: # needs sage.combinat sage: Ukeep = DisjointUnionEnumeratedSets( ....: Family(list(range(4)), Permutations), keepkey=True) sage: it = iter(Ukeep) @@ -136,6 +141,7 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): We now demonstrate the ``facade`` option:: + sage: # needs sage.combinat sage: UNoFacade = DisjointUnionEnumeratedSets( ....: Family(list(range(4)), Permutations), facade=False) sage: it = iter(UNoFacade) @@ -155,12 +161,12 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): The elements ``el`` of the disjoint union are simple wrapped elements. So to access the methods, you need to do ``el.value``:: - sage: el[0] + sage: el[0] # needs sage.combinat Traceback (most recent call last): ... TypeError: 'sage.structure.element_wrapper.ElementWrapper' object is not subscriptable - sage: el.value[0] + sage: el.value[0] # needs sage.combinat 2 Possible extensions: the current enumeration order is not suitable @@ -210,16 +216,18 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: TestSuite(U1).run() sage: TestSuite(U2).run() - sage: TestSuite(U3).run() - sage: TestSuite(U4).run() - doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union + sage: TestSuite(U3).run() # needs sage.combinat + sage: TestSuite(U4).run() # needs sage.combinat + doctest:...: UserWarning: Disjoint union of Lazy family + ((i))_{i in Non negative integers} + is an infinite union The default implementation of __contains__ can loop forever. Please overload it. - sage: TestSuite(UNoFacade).run() + sage: TestSuite(UNoFacade).run() # needs sage.combinat We skip ``_test_an_element`` because the coercion framework does not currently allow a tuple to be returned for facade parents:: - sage: TestSuite(Ukeep).run(skip="_test_an_element") + sage: TestSuite(Ukeep).run(skip="_test_an_element") # needs sage.combinat The following three lines are required for the pickling tests, because the classes ``MyUnion`` and ``UnionOfSpecialSets`` have @@ -273,8 +281,8 @@ def __init__(self, family, facade=True, keepkey=False, category=None): ....: 2: FiniteEnumeratedSet([4,5,6])}) sage: TestSuite(U).run() - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) - sage: TestSuite(X).run() + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # needs sage.combinat sage.libs.flint + sage: TestSuite(X).run() # needs sage.combinat sage.libs.flint """ self._family = family self._facade = facade @@ -326,7 +334,9 @@ def _is_a(self, x): sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Compositions)) sage: U4._is_a(Composition([3,2,1,1])) - doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union + doctest:...: UserWarning: Disjoint union of Lazy family + ((i))_{i in Non negative integers} + is an infinite union The default implementation of __contains__ can loop forever. Please overload it. True """ @@ -352,17 +362,19 @@ def __contains__(self, x): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # needs sage.combinat ....: Family(NonNegativeIntegers(), Partitions)) - sage: Partition([]) in U4 - doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union + sage: Partition([]) in U4 # needs sage.combinat + doctest:...: UserWarning: Disjoint union of Lazy family + ((i))_{i in Non negative integers} + is an infinite union The default implementation of __contains__ can loop forever. Please overload it. True Note: one has to use a different family from the previous one in this file otherwise the warning is not re-issued:: - sage: Partition([3,2,1,1]) in U4 + sage: Partition([3,2,1,1]) in U4 # needs sage.combinat True The following call will loop forever:: @@ -387,6 +399,7 @@ def __iter__(self): sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] + sage: # needs sage.combinat sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Permutations), ....: keepkey=True, facade=False) @@ -463,6 +476,7 @@ def _element_constructor_(self): """ TESTS:: + sage: # needs sage.combinat sage.libs.flint sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) sage: U._element_constructor_ @@ -483,6 +497,7 @@ def _element_constructor_default(self, el): r""" TESTS:: + sage: # needs sage.combinat sage.libs.flint sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) sage: U([1]) # indirect doctest @@ -497,6 +512,7 @@ def _element_constructor_default(self, el): 2: Partitions of the integer 2, 3: Partitions of the integer 3} + sage: # needs sage.combinat sage.libs.flint sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), keepkey=True, facade=False) sage: U((1, [1])) # indirect doctest @@ -522,7 +538,9 @@ def _element_constructor_facade(self, el): """ TESTS:: - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) + sage: # needs sage.combinat sage.libs.flint + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) + ....: for i in range(5)}) sage: X([1]).parent() Partitions of the integer 1 sage: X([2,1,1]).parent() # indirect doctest @@ -536,15 +554,17 @@ def _element_constructor_facade(self, el): because this returns a `tuple`, where the coercion framework requires an :class:`Element` be returned. - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}, + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) # needs sage.combinat sage.libs.flint + ....: for i in range(5)}, ....: keepkey=True) - sage: p = X._element_constructor_((0, [])) # indirect doctest - sage: p[1].parent() + sage: p = X._element_constructor_((0, [])) # indirect doctest # needs sage.combinat sage.libs.flint + sage: p[1].parent() # needs sage.combinat sage.libs.flint Partitions of the integer 0 Test that facade parents can create and properly access elements that are tuples (fixed by :trac:`22382`):: + sage: # needs sage.combinat sage.libs.flint sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), ....: mu.standard_tableaux()]) sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) @@ -588,6 +608,7 @@ def Element(self): """ TESTS:: + sage: # needs sage.combinat sage.libs.flint sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) sage: U.Element @@ -597,7 +618,8 @@ def Element(self): sage: U.Element Traceback (most recent call last): ... - AttributeError: 'DisjointUnionEnumeratedSets_with_category' object has no attribute 'Element' + AttributeError: 'DisjointUnionEnumeratedSets_with_category' object + has no attribute 'Element' """ if not self._facade: return ElementWrapper diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index a630ef51e24..6c007a96835 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -17,8 +17,8 @@ Check :trac:`12482` (shall be run in a fresh session):: - sage: P = Partitions(3) - sage: Family(P, lambda x: x).category() + sage: P = Partitions(3) # needs sage.combinat + sage: Family(P, lambda x: x).category() # needs sage.combinat Category of finite enumerated sets """ @@ -1069,7 +1069,7 @@ def _repr_(self): Check that using a class as the function is correctly handled:: - sage: Family(NonNegativeIntegers(), PerfectMatchings) + sage: Family(NonNegativeIntegers(), PerfectMatchings) # needs sage.combinat Lazy family ((i))_{i in Non negative integers} """ if self.function_name is not None: diff --git a/src/sage/sets/image_set.py b/src/sage/sets/image_set.py index 54b78eede7a..0472d793c19 100644 --- a/src/sage/sets/image_set.py +++ b/src/sage/sets/image_set.py @@ -73,6 +73,7 @@ def __init__(self, map, domain_subset, *, category=None, is_injective=None, inve EXAMPLES:: + sage: # needs sage.modules sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) sage: R. = QQ[] sage: H = Hom(M, R, category=Sets()) @@ -173,6 +174,7 @@ def ambient(self): EXAMPLES:: + sage: # needs sage.modules sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) sage: R. = ZZ[] sage: H = Hom(M, R, category=Sets()) @@ -181,8 +183,8 @@ def ambient(self): sage: Im.ambient() is R True - sage: P = Partitions(3).map(attrcall('conjugate')) - sage: P.ambient() is None + sage: P = Partitions(3).map(attrcall('conjugate')) # needs sage.combinat + sage: P.ambient() is None # needs sage.combinat True sage: R = Permutations(10).map(attrcall('reduced_word')) @@ -197,6 +199,7 @@ def lift(self, x): EXAMPLES:: + sage: # needs sage.modules sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) sage: R. = ZZ[] sage: H = Hom(M, R, category=Sets()) @@ -219,6 +222,7 @@ def retract(self, x): EXAMPLES:: + sage: # needs sage.modules sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) sage: R. = ZZ[] sage: H = Hom(M, R, category=Sets()) @@ -234,7 +238,7 @@ def _repr_(self) -> str: r""" TESTS:: - sage: Partitions(3).map(attrcall('conjugate')) + sage: Partitions(3).map(attrcall('conjugate')) # needs sage.combinat Image of Partitions of the integer 3 by The map *.conjugate() from Partitions of the integer 3 """ @@ -276,7 +280,8 @@ def cardinality(self) -> Integer: sage: Mod2.cardinality() Traceback (most recent call last): ... - NotImplementedError: cannot determine cardinality of a non-injective image of an infinite set + NotImplementedError: cannot determine cardinality of a + non-injective image of an infinite set """ domain_cardinality = self._domain_subset.cardinality() if self._is_injective and self._is_injective != 'check': @@ -294,6 +299,7 @@ def __iter__(self) -> Iterator: EXAMPLES:: + sage: # needs sage.combinat sage: P = Partitions() sage: H = Hom(P, ZZ) sage: f = H(ZZ.sum) @@ -322,8 +328,8 @@ def _an_element_(self): EXAMPLES:: - sage: R = SymmetricGroup(10).map(attrcall('reduced_word')) - sage: R.an_element() + sage: R = SymmetricGroup(10).map(attrcall('reduced_word')) # needs sage.groups + sage: R.an_element() # needs sage.groups [9, 8, 7, 6, 5, 4, 3, 2] """ domain_element = self._domain_subset.an_element() @@ -336,9 +342,9 @@ def _sympy_(self): EXAMPLES:: sage: from sage.sets.image_set import ImageSet - sage: S = ImageSet(sin, RealSet.open(0, pi/4)); S + sage: S = ImageSet(sin, RealSet.open(0, pi/4)); S # needs sage.symbolic Image of (0, 1/4*pi) by The map sin from (0, 1/4*pi) - sage: S._sympy_() + sage: S._sympy_() # needs sage.symbolic ImageSet(Lambda(x, sin(x)), Interval.open(0, pi/4)) """ from sympy import imageset @@ -360,11 +366,12 @@ class ImageSet(ImageSubobject, Set_base, Set_add_sub_operators, Set_boolean_oper Symbolics:: - sage: ImageSet(sin, RealSet.open(0, pi/4)) + sage: ImageSet(sin, RealSet.open(0, pi/4)) # needs sage.symbolic Image of (0, 1/4*pi) by The map sin from (0, 1/4*pi) - sage: _.an_element() + sage: _.an_element() # needs sage.symbolic 1/2*sqrt(-sqrt(2) + 2) + sage: # needs sage.symbolic sage: sos(x,y) = x^2 + y^2; sos (x, y) |--> x^2 + y^2 sage: ImageSet(sos, ZZ^2) diff --git a/src/sage/sets/integer_range.py b/src/sage/sets/integer_range.py index 1eeb9681527..d42f77a5307 100644 --- a/src/sage/sets/integer_range.py +++ b/src/sage/sets/integer_range.py @@ -217,7 +217,7 @@ def __classcall_private__(cls, begin, end=None, step=Integer(1), middle_point=No ValueError: IntegerRange() step argument must not be zero sage: IntegerRange(2) is IntegerRange(0, 2) True - sage: IntegerRange(1.0) + sage: IntegerRange(1.0) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: end must be Integer or Infinity, not <... 'sage.rings.real_mpfr.RealLiteral'> diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index c7b3fd27a2d..a7995ff3e1e 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -102,17 +102,17 @@ def __contains__(self, elt): True sage: -1 in NN False - sage: x in NN + sage: x in NN # needs sage.symbolic False sage: None in NN False - sage: QQbar(sqrt(2)) in NN + sage: QQbar(sqrt(2)) in NN # needs sage.rings.number_field sage.symbolic False - sage: RIF(1,2) in NN + sage: RIF(1,2) in NN # needs sage.rings.real_interval_field False - sage: QQbar(2) in NN + sage: QQbar(2) in NN # needs sage.rings.number_field True - sage: RIF(2) in NN + sage: RIF(2) in NN # needs sage.rings.real_interval_field True """ try: @@ -135,7 +135,7 @@ def _element_constructor_(self, i): Traceback (most recent call last): ... ValueError: Value -5 in not in Non negative integers. - sage: NN._element_constructor_(x) + sage: NN._element_constructor_(x) # needs sage.symbolic Traceback (most recent call last): ... ValueError: Value x in not in Non negative integers. @@ -231,7 +231,7 @@ def _sympy_(self): EXAMPLES:: sage: NN = NonNegativeIntegers() - sage: NN._sympy_() + sage: NN._sympy_() # needs sympy Naturals0 """ from sympy import Naturals0 diff --git a/src/sage/sets/positive_integers.py b/src/sage/sets/positive_integers.py index aae3c5a031f..70625fb53b7 100644 --- a/src/sage/sets/positive_integers.py +++ b/src/sage/sets/positive_integers.py @@ -83,7 +83,7 @@ def _sympy_(self): EXAMPLES:: - sage: PositiveIntegers()._sympy_() + sage: PositiveIntegers()._sympy_() # needs sympy Naturals """ from sympy import Naturals diff --git a/src/sage/sets/primes.py b/src/sage/sets/primes.py index df64c2efbbf..ac33901a73b 100644 --- a/src/sage/sets/primes.py +++ b/src/sage/sets/primes.py @@ -66,18 +66,18 @@ def __init__(self, proof): sage: P = Primes(); P Set of all prime numbers: 2, 3, 5, 7, ... - sage: Q = Primes(proof = False); Q + sage: Q = Primes(proof=False); Q Set of all prime numbers: 2, 3, 5, 7, ... TESTS:: sage: P.category() Category of facade infinite enumerated sets - sage: TestSuite(P).run() + sage: TestSuite(P).run() # needs sage.libs.pari sage: Q.category() Category of facade infinite enumerated sets - sage: TestSuite(Q).run() + sage: TestSuite(Q).run() # needs sage.libs.pari The set of primes can be compared to various things, but is only equal to itself:: @@ -123,7 +123,7 @@ def __contains__(self, x): False sage: 1.5 in P False - sage: e in P + sage: e in P # needs sage.symbolic False """ try: @@ -164,7 +164,7 @@ def next(self, pr): EXAMPLES:: sage: P = Primes() - sage: P.next(5) + sage: P.next(5) # needs sage.libs.pari 7 """ pr = pr.next_prime(self.__proof) @@ -177,11 +177,11 @@ def unrank(self, n): EXAMPLES:: sage: P = Primes() - sage: P.unrank(0) + sage: P.unrank(0) # needs sage.libs.pari 2 - sage: P.unrank(5) + sage: P.unrank(5) # needs sage.libs.pari 13 - sage: P.unrank(42) + sage: P.unrank(42) # needs sage.libs.pari 191 """ return nth_prime(n + 1) diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index 47a0505de6b..45394cba23c 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.rings.real_interval_field sage.rings.real_mpfr """ Subsets of the Real Line @@ -48,6 +48,7 @@ Relations containing symbols and numeric values or constants:: + sage: # needs sage.symbolic sage: RealSet(x != 0) (-oo, 0) ∪ (0, +oo) sage: RealSet(x == pi) @@ -61,11 +62,11 @@ Note that multiple arguments are combined as union:: - sage: RealSet(x >= 0, x < 1) + sage: RealSet(x >= 0, x < 1) # needs sage.symbolic (-oo, +oo) - sage: RealSet(x >= 0, x > 1) + sage: RealSet(x >= 0, x > 1) # needs sage.symbolic [0, +oo) - sage: RealSet(x >= 0, x > -1) + sage: RealSet(x >= 0, x > -1) # needs sage.symbolic (-1, +oo) AUTHORS: @@ -406,9 +407,9 @@ def _latex_(self): EXAMPLES:: - sage: RealSet.open_closed(1/2, pi)._latex_() + sage: RealSet.open_closed(1/2, pi)._latex_() # needs sage.symbolic '(\\frac{1}{2}, \\pi]' - sage: (RealSet.point(sqrt(2)))._latex_() + sage: (RealSet.point(sqrt(2)))._latex_() # needs sage.symbolic '\\{\\sqrt{2}\\}' """ from sage.misc.latex import latex @@ -435,7 +436,7 @@ def _sympy_condition_(self, variable): EXAMPLES:: - sage: RealSet(0, 4)._sympy_condition_(x) + sage: RealSet(0, 4)._sympy_condition_(x) # needs sage.symbolic (0 < x) & (x < 4) """ x = variable @@ -464,6 +465,7 @@ def _sympy_(self): EXAMPLES:: + sage: # needs sympy sage: RealSet.open_closed(0, 1)[0]._sympy_() Interval.Lopen(0, 1) sage: RealSet.point(0)[0]._sympy_() # random - this output format is sympy >= 1.9 @@ -494,7 +496,7 @@ def _giac_condition_(self, variable): EXAMPLES:: - sage: RealSet(0, 4)._giac_condition_(x) + sage: RealSet(0, 4)._giac_condition_(x) # needs sage.symbolic '((0 < sageVARx) and (sageVARx < 4))' """ x = variable @@ -985,11 +987,13 @@ class RealSet(UniqueRepresentation, Parent, Set_base, sage: i1, i2 = s1[0], s2[0] sage: RealSet(i2, i1) # union of intervals (1, 2) ∪ [3, 4] - sage: RealSet((-oo, 0), x > 6, i1, RealSet.point(5), RealSet.closed_open(4, 3)) + sage: RealSet((-oo, 0), x > 6, i1, RealSet.point(5), # needs sage.symbolic + ....: RealSet.closed_open(4, 3)) (-oo, 0) ∪ (1, 2) ∪ [3, 4) ∪ {5} ∪ (6, +oo) Initialization from manifold objects:: + sage: # needs sage.symbolic sage: R = manifolds.RealLine(); R Real number line ℝ sage: RealSet(R) @@ -1004,7 +1008,8 @@ class RealSet(UniqueRepresentation, Parent, Set_base, (0, 1) sage: RealSet(I01_of_R.closure()) [0, 1] - sage: I01_of_I02 = manifolds.OpenInterval(0, 1, ambient_interval=I02); I01_of_I02 + sage: I01_of_I02 = manifolds.OpenInterval(0, 1, + ....: ambient_interval=I02); I01_of_I02 Real interval (0, 1) sage: RealSet(I01_of_I02) (0, 1) @@ -1038,23 +1043,22 @@ class RealSet(UniqueRepresentation, Parent, Set_base, Constructing real sets as manifolds or manifold subsets by passing ``structure='differentiable'``:: + sage: # needs sage.symbolic sage: RealSet(-oo, oo, structure='differentiable') Real number line ℝ - sage: RealSet([0, 1], structure='differentiable') Subset [0, 1] of the Real number line ℝ sage: _.category() Category of subobjects of sets - sage: RealSet.open_closed(0, 5, structure='differentiable') Subset (0, 5] of the Real number line ℝ This is implied when a coordinate name is given using the keywords ``coordinate`` or ``names``:: - sage: RealSet(0, 1, coordinate='λ') + sage: RealSet(0, 1, coordinate='λ') # needs sage.symbolic Open subset (0, 1) of the Real number line ℝ - sage: _.category() + sage: _.category() # needs sage.symbolic Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and @@ -1062,14 +1066,15 @@ class RealSet(UniqueRepresentation, Parent, Set_base, It is also implied by assigning a coordinate name using generator notation:: - sage: R_xi.<ξ> = RealSet.real_line(); R_xi + sage: R_xi.<ξ> = RealSet.real_line(); R_xi # needs sage.symbolic Real number line ℝ - sage: R_xi.canonical_chart() + sage: R_xi.canonical_chart() # needs sage.symbolic Chart (ℝ, (ξ,)) With the keyword ``ambient``, we can construct a subset of a previously constructed manifold:: + sage: # needs sage.symbolic sage: P_xi = RealSet(0, oo, ambient=R_xi); P_xi Open subset (0, +oo) of the Real number line ℝ sage: P_xi.default_chart() @@ -1080,7 +1085,6 @@ class RealSet(UniqueRepresentation, Parent, Set_base, Chart ((0, 1), (ξ,)) sage: R_xi.subset_family() Set {(0, +oo), (0, 1), ℝ} of open subsets of the Real number line ℝ - sage: F = RealSet.point(0).union(RealSet.point(1)).union(RealSet.point(2)); F {0} ∪ {1} ∪ {2} sage: F_tau = RealSet(F, names="τ"); F_tau @@ -1090,6 +1094,7 @@ class RealSet(UniqueRepresentation, Parent, Set_base, TESTS:: + sage: # needs sage.symbolic sage: TestSuite(R_xi).run() sage: TestSuite(P_xi).run() sage: R_xi.point((1,)) in P_xi @@ -1123,6 +1128,7 @@ def __classcall__(cls, *args, **kwds): TESTS:: + sage: # needs sage.symbolic sage: RealSet(x != 0) (-oo, 0) ∪ (0, +oo) sage: RealSet(x == pi) @@ -1628,6 +1634,7 @@ def _sympy_condition_(self, variable): EXAMPLES:: + sage: # needs sage.symbolic sage: RealSet(0, 1)._sympy_condition_(x) (0 < x) & (x < 1) sage: RealSet((0,1), [2,3])._sympy_condition_(x) @@ -1639,9 +1646,9 @@ def _sympy_condition_(self, variable): TESTS:: - sage: RealSet(6,6)._sympy_condition_(x) + sage: RealSet(6,6)._sympy_condition_(x) # needs sympy sage.symbolic False - sage: RealSet([6,6])._sympy_condition_(x) + sage: RealSet([6,6])._sympy_condition_(x) # needs sympy sage.symbolic Eq(x, 6) """ x = variable @@ -1664,6 +1671,7 @@ def _giac_condition_(self, variable): EXAMPLES:: + sage: # needs sage.symbolic sage: RealSet(0, 1)._giac_condition_(x) '((0 < sageVARx) and (sageVARx < 1))' sage: RealSet((0,1), [2,3])._giac_condition_(x) @@ -1675,9 +1683,9 @@ def _giac_condition_(self, variable): TESTS:: - sage: RealSet(6,6)._giac_condition_(x) + sage: RealSet(6,6)._giac_condition_(x) # needs sage.symbolic 'false' - sage: RealSet([6,6])._giac_condition_(x) + sage: RealSet([6,6])._giac_condition_(x) # needs sage.symbolic 'sageVARx == 6' """ x = variable @@ -2107,7 +2115,8 @@ def union(self, *real_set_collection): (-oo, +oo) sage: s = RealSet().union([1, 2], (2, 3)); s [1, 3) - sage: RealSet().union((-oo, 0), x > 6, s[0], RealSet.point(5.0), RealSet.closed_open(2, 4)) + sage: RealSet().union((-oo, 0), x > 6, s[0], # needs sage.symbolic + ....: RealSet.point(5.0), RealSet.closed_open(2, 4)) (-oo, 0) ∪ [1, 4) ∪ {5} ∪ (6, +oo) """ sets = [self] @@ -2170,7 +2179,7 @@ def intersection(self, *real_set_collection): [1, 10) sage: s5.intersection(-oo, +oo) [1, 10) - sage: s5.intersection(x != 2, (-oo, 3), RealSet.real_line()[0]) + sage: s5.intersection(x != 2, (-oo, 3), RealSet.real_line()[0]) # needs sage.symbolic [1, 2) ∪ (2, 3) TESTS:: @@ -2284,7 +2293,7 @@ def complement(self): TESTS:: - sage: RealSet(x != 0).complement() + sage: RealSet(x != 0).complement() # needs sage.symbolic {0} sage: RealSet.real_line().complement() {} @@ -2638,7 +2647,7 @@ def is_connected(self): (-oo, -10] ∪ (1, 3) sage: s3.is_connected() False - sage: RealSet(x != 0).is_connected() + sage: RealSet(x != 0).is_connected() # needs sage.symbolic False sage: RealSet(-oo, oo).is_connected() True @@ -2795,7 +2804,7 @@ def __rmul__(self, other): sage: A = RealSet([0, 1/2], RealSet.unbounded_above_closed(2)); A [0, 1/2] ∪ [2, +oo) - sage: pi * A + sage: pi * A # needs sage.symbolic [0, 1/2*pi] ∪ [2*pi, +oo) """ return self * other @@ -2806,9 +2815,10 @@ def _sympy_(self): EXAMPLES:: + sage: # needs sympy sage: RealSet()._sympy_() EmptySet - sage: RealSet.point(5)._sympy_() # random - this output format is sympy >= 1.9 + sage: RealSet.point(5)._sympy_() # random - this format is sympy >= 1.9 {5} sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() # random {1, 2} @@ -2819,8 +2829,8 @@ def _sympy_(self): Infinities are not elements:: - sage: import sympy - sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) + sage: import sympy # needs sympy + sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) # needs sympy False """ from sympy import Reals, Union diff --git a/src/sage/sets/recursively_enumerated_set.pyx b/src/sage/sets/recursively_enumerated_set.pyx index a8b21530946..26bcd769b44 100644 --- a/src/sage/sets/recursively_enumerated_set.pyx +++ b/src/sage/sets/recursively_enumerated_set.pyx @@ -127,6 +127,7 @@ Elements of given depth iterator:: Graded components (set of elements of the same depth):: + sage: # needs sage.combinat sage: sorted(R.graded_component(0)) [[1, 2, 3, 4, 5]] sage: sorted(R.graded_component(1)) @@ -394,9 +395,10 @@ def RecursivelyEnumeratedSet(seeds, successors, structure=None, A recursive set given by a graded relation:: - sage: f = lambda a: [a+1, a+I] - sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') - sage: C + sage: # needs sage.symbolic + sage: def f(a): + ....: return [a + 1, a + I] + sage: C = RecursivelyEnumeratedSet([0], f, structure='graded'); C A recursively enumerated set with a graded structure (breadth first search) sage: it = iter(C) sage: [next(it) for _ in range(7)] @@ -880,6 +882,7 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): We compute all the permutations of 3:: + sage: # needs sage.combinat sage: seeds = [Permutation([1,2,3])] sage: succ = attrcall("permutohedron_succ") sage: R = RecursivelyEnumeratedSet(seeds, succ) @@ -954,7 +957,7 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): sage: child = lambda i: [(i+3) % 10, (i+8) % 10] sage: R = RecursivelyEnumeratedSet([0], child) - sage: R.to_digraph() + sage: R.to_digraph() # needs sage.graphs Looped multi-digraph on 10 vertices Digraph of an recursively enumerated set with a symmetric structure of @@ -963,20 +966,21 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): sage: succ = lambda a: [(a[0]-1,a[1]), (a[0],a[1]-1), (a[0]+1,a[1]), (a[0],a[1]+1)] sage: seeds = [(0,0)] sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric') - sage: C.to_digraph(max_depth=3) + sage: C.to_digraph(max_depth=3) # needs sage.graphs Looped multi-digraph on 41 vertices The ``max_depth`` argument can be given at the creation of the set:: - sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric', max_depth=2) - sage: C.to_digraph() + sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric', + ....: max_depth=2) + sage: C.to_digraph() # needs sage.graphs Looped multi-digraph on 25 vertices Digraph of an recursively enumerated set with a graded structure:: sage: f = lambda a: [a+1, a+I] sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') - sage: C.to_digraph(max_depth=4) + sage: C.to_digraph(max_depth=4) # needs sage.graphs Looped multi-digraph on 21 vertices """ successors = self.successors @@ -1125,7 +1129,9 @@ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic): Gaussian integers:: - sage: f = lambda a: [a+1, a+I] + sage: # needs sage.symbolic + sage: def f(a): + ....: return [a + 1, a + I] sage: S = RecursivelyEnumeratedSet([0], f, structure='symmetric') sage: it = S.graded_component_iterator() sage: [sorted(next(it)) for _ in range(7)] @@ -1142,6 +1148,7 @@ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic): Note that interrupting the computation (``KeyboardInterrupt`` for instance) breaks the iterator:: + sage: # needs sage.symbolic sage: def f(a): ....: sleep(0.05r) ....: return [a-1,a+1] @@ -1411,7 +1418,9 @@ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic): EXAMPLES:: - sage: f = lambda a: [a+1, a+I] + sage: # needs sage.symbolic + sage: def f(a): + ....: return [a + 1, a + I] sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') sage: for i in range(5): sorted(C.graded_component(i)) [0] @@ -1424,6 +1433,7 @@ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic): We make sure that :trac:`21312` is fixed:: + sage: # needs sage.symbolic sage: def f(a): ....: sleep(0.1r) ....: return [a+1, a+I] diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index a1789c61300..4e8789a2d57 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -71,7 +71,7 @@ def has_finite_length(obj): True sage: has_finite_length(iter(range(10))) False - sage: has_finite_length(GF(17^127)) + sage: has_finite_length(GF(17^127)) # needs sage.rings.finite_rings True sage: has_finite_length(ZZ) False @@ -100,14 +100,17 @@ def Set(X=None, category=None): EXAMPLES:: - sage: X = Set(GF(9,'a')) + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(9, 'a')) sage: X {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} sage: type(X) sage: Y = X.union(Set(QQ)) sage: Y - Set-theoretic union of {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} and Set of elements of Rational Field + Set-theoretic union of + {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} and + Set of elements of Rational Field sage: type(Y) @@ -115,7 +118,8 @@ def Set(X=None, category=None): :: - sage: d={Set([2*I,1+I]):10} + sage: # needs sage.symbolic + sage: d = {Set([2*I, 1 + I]): 10} sage: d # key is randomly ordered {{I + 1, 2*I}: 10} sage: d[Set([1+I,2*I])] @@ -149,7 +153,7 @@ def Set(X=None, category=None): We can also create sets from different types:: - sage: sorted(Set([Sequence([3,1], immutable=True), 5, QQ, Partition([3,1,1])]), key=str) + sage: sorted(Set([Sequence([3,1], immutable=True), 5, QQ, Partition([3,1,1])]), key=str) # needs sage.combinat [5, Rational Field, [3, 1, 1], [3, 1]] Sets with unhashable objects work, but with less functionality:: @@ -218,14 +222,20 @@ def union(self, X): EXAMPLES:: sage: Set(QQ).union(Set(ZZ)) - Set-theoretic union of Set of elements of Rational Field and Set of elements of Integer Ring + Set-theoretic union of + Set of elements of Rational Field and + Set of elements of Integer Ring sage: Set(QQ) + Set(ZZ) - Set-theoretic union of Set of elements of Rational Field and Set of elements of Integer Ring + Set-theoretic union of + Set of elements of Rational Field and + Set of elements of Integer Ring sage: X = Set(QQ).union(Set(GF(3))); X - Set-theoretic union of Set of elements of Rational Field and {0, 1, 2} + Set-theoretic union of + Set of elements of Rational Field and + {0, 1, 2} sage: 2/3 in X True - sage: GF(3)(2) in X + sage: GF(3)(2) in X # needs sage.libs.pari True sage: GF(5)(2) in X False @@ -253,12 +263,10 @@ def intersection(self, X): sage: 2/1 in X True - sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'c'))) - sage: X + sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'c'))); X # needs sage.rings.finite_rings {} - sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'b'))) - sage: X + sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'b'))); X # needs sage.rings.finite_rings {} """ if isinstance(X, (Set_generic, Set_base)): @@ -282,12 +290,10 @@ def difference(self, X): sage: 4/1 in X True - sage: X = Set(GF(9,'b')).difference(Set(GF(27,'c'))) - sage: X + sage: X = Set(GF(9,'b')).difference(Set(GF(27,'c'))); X # needs sage.rings.finite_rings {0, 1, 2, b, b + 1, b + 2, 2*b, 2*b + 1, 2*b + 2} - sage: X = Set(GF(9,'b')).difference(Set(GF(27,'b'))) - sage: X + sage: X = Set(GF(9,'b')).difference(Set(GF(27,'b'))); X # needs sage.rings.finite_rings {0, 1, 2, b, b + 1, b + 2, 2*b, 2*b + 1, 2*b + 2} """ if isinstance(X, (Set_generic, Set_base)): @@ -325,7 +331,7 @@ def _test_as_set_object(self, tester=None, **options): Instances of other subclasses of :class:`Set_base` run this method:: - sage: Polyhedron()._test_as_set_object(verbose=True) + sage: Polyhedron()._test_as_set_object(verbose=True) # needs sage.geometry.polyhedron Running the test suite of Set(self) running ._test_an_element() . . . pass ... @@ -407,15 +413,15 @@ def __add__(self, X): EXAMPLES:: - sage: Set(RealField()) + Set(QQ^5) + sage: Set(RealField()) + Set(QQ^5) # needs sage.modules Set-theoretic union of Set of elements of Real Field with 53 bits of precision and Set of elements of Vector space of dimension 5 over Rational Field sage: Set(GF(3)) + Set(GF(2)) {0, 1, 2, 0, 1} - sage: Set(GF(2)) + Set(GF(4,'a')) + sage: Set(GF(2)) + Set(GF(4,'a')) # needs sage.rings.finite_rings {0, 1, a, a + 1} - sage: sorted(Set(GF(8,'b')) + Set(GF(4,'a')), key=str) + sage: sorted(Set(GF(8,'b')) + Set(GF(4,'a')), key=str) # needs sage.rings.finite_rings [0, 0, 1, 1, a, a + 1, b, b + 1, b^2, b^2 + 1, b^2 + b, b^2 + b + 1] """ return self.union(X) @@ -583,7 +589,7 @@ def _an_element_(self): EXAMPLES:: sage: R = Set(RR) - sage: R.an_element() # indirect doctest + sage: R.an_element() # indirect doctest # needs sage.rings.real_mpfr 1.00000000000000 sage: F = Set([1, 2, 3]) @@ -606,7 +612,7 @@ def __contains__(self, x): sage: X = Set(ZZ) sage: 5 in X True - sage: GF(7)(3) in X + sage: GF(7)(3) in X # needs sage.libs.pari True sage: 2/1 in X True @@ -673,7 +679,7 @@ def cardinality(self): +Infinity sage: Set(GF(5)).cardinality() 5 - sage: Set(GF(5^2,'a')).cardinality() + sage: Set(GF(5^2,'a')).cardinality() # needs sage.rings.finite_rings 25 """ if self in Sets().Infinite(): @@ -711,7 +717,7 @@ def is_empty(self): False sage: Set([1..100]).is_empty() False - sage: Set(SymmetricGroup(2).list()).is_empty() + sage: Set(SymmetricGroup(2).list()).is_empty() # needs sage.groups False sage: Set(ZZ).is_empty() False @@ -724,7 +730,7 @@ def is_empty(self): False sage: Set([1..100]).is_empty() False - sage: Set(DihedralGroup(4).list()).is_empty() + sage: Set(DihedralGroup(4).list()).is_empty() # needs sage.groups False sage: Set(QQ).is_empty() False @@ -739,7 +745,7 @@ def is_finite(self): sage: Set(QQ).is_finite() False - sage: Set(GF(250037)).is_finite() + sage: Set(GF(250037)).is_finite() # needs sage.rings.finite_rings True sage: Set(Integers(2^1000000)).is_finite() True @@ -796,10 +802,10 @@ def subsets_lattice(self): EXAMPLES:: sage: X = Set([1,2,3]) - sage: X.subsets_lattice() + sage: X.subsets_lattice() # needs sage.graphs Finite lattice containing 8 elements sage: Y = Set() - sage: Y.subsets_lattice() + sage: Y.subsets_lattice() # needs sage.graphs Finite lattice containing 1 elements """ @@ -835,7 +841,7 @@ def _sympy_(self): sage: X = Set(ZZ); X Set of elements of Integer Ring - sage: X._sympy_() + sage: X._sympy_() # needs sympy Integers """ from sage.interfaces.sympy import sympy_init @@ -967,6 +973,7 @@ def list(self): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: X = Set(GF(8,'c')) sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} @@ -995,6 +1002,7 @@ def set(self): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: X = Set(GF(8,'c')) sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} @@ -1014,6 +1022,7 @@ def frozenset(self): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: X = Set(GF(8,'c')) sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} @@ -1026,10 +1035,10 @@ def frozenset(self): sage: s = X.frozenset(); s frozenset({0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1}) - sage: hash(s) != hash(tuple(X.set())) + sage: hash(s) != hash(tuple(X.set())) # needs sage.rings.finite_rings True - sage: type(s) + sage: type(s) # needs sage.rings.finite_rings <... 'frozenset'> """ return frozenset(self.object()) @@ -1040,8 +1049,8 @@ def __hash__(self): EXAMPLES:: - sage: s = Set(GF(8,'c')) - sage: hash(s) == hash(s) + sage: s = Set(GF(8,'c')) # needs sage.rings.finite_rings + sage: hash(s) == hash(s) # needs sage.rings.finite_rings True """ return hash(self.frozenset()) @@ -1052,10 +1061,10 @@ def __richcmp__(self, other, op): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: X == Set(GF(8,'c')) + sage: X = Set(GF(8,'c')) # needs sage.rings.finite_rings + sage: X == Set(GF(8,'c')) # needs sage.rings.finite_rings True - sage: X == Set(GF(4,'a')) + sage: X == Set(GF(4,'a')) # needs sage.rings.finite_rings False sage: Set(QQ) == Set(ZZ) False @@ -1142,6 +1151,7 @@ def union(self, other): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: X = Set(GF(8,'c')) sage: Y = Set([GF(8,'c').0, 1, 2, 3]) sage: X @@ -1161,10 +1171,10 @@ def intersection(self, other): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: Y = Set([GF(8,'c').0, 1, 2, 3]) - sage: X.intersection(Y) - {1, c} + sage: X = Set(GF(8,'c')) # needs sage.rings.finite_rings + sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # needs sage.rings.finite_rings + sage: sorted(X.intersection(Y), key=str) # needs sage.rings.finite_rings + [1, c] """ if not isinstance(other, Set_object_enumerated): return Set_object.intersection(self, other) @@ -1182,7 +1192,7 @@ def difference(self, other): {3, 4} sage: Z = Set(ZZ) sage: W = Set([2.5, 4, 5, 6]) - sage: W.difference(Z) + sage: W.difference(Z) # needs sage.rings.real_mpfr {2.50000000000000} """ if not isinstance(other, Set_object_enumerated): @@ -1227,16 +1237,16 @@ def _sympy_(self): sage: X = Set({1, 2, 3}); X {1, 2, 3} - sage: sX = X._sympy_(); sX + sage: sX = X._sympy_(); sX # needs sympy Set(1, 2, 3) - sage: sX.is_empty is None + sage: sX.is_empty is None # needs sympy True sage: Empty = Set([]); Empty {} - sage: sEmpty = Empty._sympy_(); sEmpty + sage: sEmpty = Empty._sympy_(); sEmpty # needs sympy EmptySet - sage: sEmpty.is_empty + sage: sEmpty.is_empty # needs sympy True """ from sympy import Set, EmptySet @@ -1264,10 +1274,10 @@ class Set_object_binary(Set_object, metaclass=ClasscallMetaclass): EXAMPLES:: - sage: X = Set(QQ^2) + sage: X = Set(QQ^2) # needs sage.modules sage: Y = Set(ZZ) sage: from sage.sets.set import Set_object_binary - sage: S = Set_object_binary(X, Y, "union", "\\cup"); S + sage: S = Set_object_binary(X, Y, "union", "\\cup"); S # needs sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring @@ -1281,9 +1291,9 @@ def __classcall__(cls, X, Y, *args, **kwds): TESTS:: sage: from sage.sets.set import Set_object_binary - sage: X = QQ^2 + sage: X = QQ^2 # needs sage.modules sage: Y = ZZ - sage: Set_object_binary(X, Y, "union", "\\cup") + sage: Set_object_binary(X, Y, "union", "\\cup") # needs sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring @@ -1301,10 +1311,10 @@ def __init__(self, X, Y, op, latex_op, category=None): TESTS:: sage: from sage.sets.set import Set_object_binary - sage: X = Set(QQ^2) + sage: X = Set(QQ^2) # needs sage.modules sage: Y = Set(ZZ) - sage: S = Set_object_binary(X, Y, "union", "\\cup") - sage: type(S) + sage: S = Set_object_binary(X, Y, "union", "\\cup") # needs sage.modules + sage: type(S) # needs sage.modules """ self._X = X @@ -1371,16 +1381,17 @@ def __init__(self, X, Y, category=None): EXAMPLES:: + sage: # needs sage.modules sage: S = Set(QQ^2) sage: T = Set(ZZ) sage: X = S.union(T); X - Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring + Set-theoretic union of + Set of elements of Vector space of dimension 2 over Rational Field and + Set of elements of Integer Ring sage: X.category() Category of infinite sets - sage: latex(X) \Bold{Q}^{2} \cup \Bold{Z} - sage: TestSuite(X).run() """ if category is None: @@ -1422,6 +1433,7 @@ def __richcmp__(self, right, op): EXAMPLES:: + sage: # needs sage.modules sage: Y = Set(ZZ^2).union(Set(ZZ^3)) sage: X = Set(ZZ^3).union(Set(ZZ^2)) sage: X == Y @@ -1466,6 +1478,7 @@ def __contains__(self, x): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: X = Set(GF(3)).union(Set(GF(2))) sage: GF(5)(1) in X False @@ -1505,7 +1518,7 @@ def _sympy_(self): sage: X = Set(ZZ).union(Set([1/2])); X Set-theoretic union of Set of elements of Integer Ring and {1/2} - sage: X._sympy_() + sage: X._sympy_() # needs sympy Union(Integers, Set(1/2)) """ from sympy import Union @@ -1524,10 +1537,13 @@ def __init__(self, X, Y, category=None): EXAMPLES:: + sage: # needs sage.modules sage: S = Set(QQ^2) sage: T = Set(ZZ) sage: X = S.intersection(T); X - Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring + Set-theoretic intersection of + Set of elements of Vector space of dimension 2 over Rational Field and + Set of elements of Integer Ring sage: X.category() Category of enumerated sets sage: latex(X) @@ -1657,18 +1673,18 @@ def __contains__(self, x): sage: X = Set(QQ).intersection(Set(RR)) sage: 5 in X True - sage: ComplexField().0 in X + sage: ComplexField().0 in X # needs sage.rings.real_mpfr False Any specific floating-point number in Sage is to finite precision, hence it is rational:: - sage: RR(sqrt(2)) in X + sage: RR(sqrt(2)) in X # needs sage.rings.real_mpfr sage.symbolic True Real constants are not rational:: - sage: pi in X + sage: pi in X # needs sage.symbolic False """ return x in self._X and x in self._Y @@ -1684,7 +1700,7 @@ def _sympy_(self): Set-theoretic intersection of Set of elements of Integer Ring and Set of elements of [3/2, 11/2] - sage: X._sympy_() + sage: X._sympy_() # needs sympy Range(2, 6, 1) """ from sympy import Intersection @@ -1829,11 +1845,11 @@ def __contains__(self, x): sage: X = Set(QQ).difference(Set(ZZ)) sage: 5 in X False - sage: ComplexField().0 in X + sage: ComplexField().0 in X # needs sage.rings.real_mpfr False - sage: sqrt(2) in X # since sqrt(2) is not a numerical approx + sage: sqrt(2) in X # since sqrt(2) is not a numerical approx # needs sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx # needs sage.rings.real_interval_field True sage: 5/2 in X True @@ -1853,7 +1869,7 @@ def _sympy_(self): Set of elements of Integer Ring sage: X.category() Category of sets - sage: X._sympy_() + sage: X._sympy_() # needs sympy Complement(Rationals, Integers) sage: X = Set(ZZ).difference(Set(QQ)); X @@ -1862,7 +1878,7 @@ def _sympy_(self): Set of elements of Rational Field sage: X.category() Category of enumerated sets - sage: X._sympy_() + sage: X._sympy_() # needs sympy EmptySet """ from sympy import Complement @@ -2002,13 +2018,13 @@ def __contains__(self, x): sage: X = Set(QQ).symmetric_difference(Primes()) sage: 4 in X True - sage: ComplexField().0 in X + sage: ComplexField().0 in X # needs sage.rings.real_mpfr False - sage: sqrt(2) in X # since sqrt(2) is currently symbolic + sage: sqrt(2) in X # since sqrt(2) is currently symbolic # needs sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated # needs sage.rings.real_interval_field True - sage: pi in X + sage: pi in X # needs sage.symbolic False sage: 5/2 in X True @@ -2029,7 +2045,7 @@ def _sympy_(self): Set-theoretic symmetric difference of Set of elements of Integer Ring and {0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3} - sage: X._sympy_() + sage: X._sympy_() # needs sympy Union(Complement(Integers, Set(0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3)), Complement(Set(0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3), Integers)) """ diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index 4c92deb5d52..5123879673a 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -3,15 +3,16 @@ EXAMPLES: -We build a set from the iterator ``graphs`` that returns a canonical +We build a set from the iterator :obj:`graphs` that returns a canonical representative for each isomorphism class of graphs:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator( ....: graphs, - ....: name = "Graphs", - ....: category = InfiniteEnumeratedSets(), - ....: cache = True) + ....: name="Graphs", + ....: category=InfiniteEnumeratedSets(), + ....: cache=True) sage: E Graphs sage: E.unrank(0) @@ -37,9 +38,9 @@ sage: from sage.sets.set_from_iterator import set_from_method sage: class A: - ....: @set_from_method - ....: def f(self,n): - ....: return xsrange(n) + ....: @set_from_method + ....: def f(self,n): + ....: return xsrange(n) sage: a = A() sage: a.f(3) {0, 1, 2} @@ -97,25 +98,21 @@ class EnumeratedSetFromIterator(Parent): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args = (7,)) - sage: E - {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, ...} - sage: E.category() + sage: E = EnumeratedSetFromIterator(graphs, args=(7,)); E # needs sage.graphs + {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, + Graph on 7 vertices, Graph on 7 vertices, ...} + sage: E.category() # needs sage.graphs Category of facade enumerated sets The same example with a cache and a custom name:: - sage: E = EnumeratedSetFromIterator( - ....: graphs, - ....: args = (8,), - ....: category = FiniteEnumeratedSets(), - ....: name = "Graphs with 8 vertices", - ....: cache = True) - sage: E + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True, # needs sage.graphs + ....: name="Graphs with 8 vertices", + ....: category=FiniteEnumeratedSets()); E Graphs with 8 vertices - sage: E.unrank(3) + sage: E.unrank(3) # needs sage.graphs Graph on 8 vertices - sage: E.category() + sage: E.category() # needs sage.graphs Category of facade finite enumerated sets TESTS: @@ -154,7 +151,7 @@ def __init__(self, f, args=None, kwds=None, name=None, category=None, cache=Fals TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: S = EnumeratedSetFromIterator(xsrange, (1,200,-1), category=FiniteEnumeratedSets()) + sage: S = EnumeratedSetFromIterator(xsrange, (1, 200, -1), category=FiniteEnumeratedSets()) sage: TestSuite(S).run() """ if category is not None: @@ -184,7 +181,7 @@ def __hash__(self): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(xsrange, (1,200)) + sage: E = EnumeratedSetFromIterator(xsrange, (1, 200)) sage: hash(E) == hash(tuple(range(1, 14))) True """ @@ -200,6 +197,7 @@ def __reduce__(self): TESTS:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: from sage.graphs.graph_generators import graphs sage: E = EnumeratedSetFromIterator(graphs, @@ -228,14 +226,16 @@ def _repr_(self): TESTS:: + sage: # needs sage.combinat sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(Partitions(7,min_part=2).__iter__) + sage: E = EnumeratedSetFromIterator(Partitions(7, min_part=2).__iter__) sage: repr(E) # indirect doctest '{[7], [5, 2], [4, 3], [3, 2, 2]}' - sage: E = EnumeratedSetFromIterator(Partitions(9,min_part=2).__iter__) + sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__) sage: repr(E) # indirect doctest '{[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], ...}' - sage: E = EnumeratedSetFromIterator(Partitions(9,min_part=2).__iter__, name="Some partitions") + sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__, + ....: name="Some partitions") sage: repr(E) # indirect doctest 'Some partitions' """ @@ -261,9 +261,9 @@ def __contains__(self, x): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: P = Partitions(12,min_part=2,max_part=5) - sage: E = EnumeratedSetFromIterator(P.__iter__) - sage: P([5,5,2]) in E + sage: P = Partitions(12, min_part=2, max_part=5) # needs sage.combinat + sage: E = EnumeratedSetFromIterator(P.__iter__) # needs sage.combinat + sage: P([5,5,2]) in E # needs sage.combinat True """ return any(x == y for y in self) @@ -280,10 +280,14 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), + ....: category=FiniteEnumeratedSets()) + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), + ....: category=FiniteEnumeratedSets()) + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), + ....: category=FiniteEnumeratedSets()) sage: E4 == E4 True sage: E4 == F4 @@ -335,10 +339,14 @@ def __ne__(self, other): TESTS:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), + ....: category=FiniteEnumeratedSets()) + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), + ....: category=FiniteEnumeratedSets()) + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), + ....: category=FiniteEnumeratedSets()) sage: E4 != E4 False sage: E4 != F4 @@ -358,6 +366,7 @@ def __iter__(self): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) sage: g1 = next(iter(E)); g1 @@ -378,6 +387,7 @@ def unrank(self, i): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) @@ -400,7 +410,8 @@ def _element_constructor_(self, el): sage: S = EnumeratedSetFromIterator(range, args=(1,4)) sage: S(1) - doctest:...: UserWarning: Testing equality of infinite sets which will not end in case of equality + doctest:...: UserWarning: Testing equality of infinite sets + which will not end in case of equality 1 sage: S(0) # indirect doctest Traceback (most recent call last): @@ -420,8 +431,7 @@ def clear_cache(self): sage: from itertools import count sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(count, args=(1,), cache=True) - sage: e1 = E._cache - sage: e1 + sage: e1 = E._cache; e1 lazy list [1, 2, 3, ...] sage: E.clear_cache() sage: E._cache @@ -501,6 +511,7 @@ def _sage_src_lines_(self): TESTS:: + sage: # needs sage.groups sage: from sage.misc.sageinspect import sage_getsourcelines sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() @@ -520,11 +531,12 @@ def _sage_argspec_(self): TESTS:: + sage: # needs sage.modules sage: from sage.misc.sageinspect import sage_getargspec sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() sage: d.f = find_local_minimum - sage: sage_getargspec(d) # indirect doctest + sage: sage_getargspec(d) # indirect doctest FullArgSpec(args=['f', 'a', 'b', 'tol', 'maxfun'], varargs=None, varkw=None, defaults=(1.48e-08, 500), kwonlyargs=[], kwonlydefaults=None, annotations={}) @@ -555,12 +567,12 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): r""" Decorator for :class:`EnumeratedSetFromIterator`. - Name could be string or a function ``(args,kwds) -> string``. + Name could be string or a function ``(args, kwds) -> string``. .. WARNING:: - If you are going to use this with the decorator ``cached_function``, - you must place the ``cached_function`` first. See the example below. + If you are going to use this with the decorator :func:`cached_function`, + you must place the ``@cached_function`` first. See the example below. EXAMPLES:: @@ -584,18 +596,16 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): ....: while True: ....: yield a ....: a, b = b, a + b - sage: F = Fibonacci() - sage: F + sage: F = Fibonacci(); F {1, 2, 3, 5, 8, ...} sage: F.cardinality() +Infinity A simple example with many options:: - sage: @set_from_function( - ....: name = "From %(m)d to %(n)d", - ....: category = FiniteEnumeratedSets()) - ....: def f(m, n): return xsrange(m,n+1) + sage: @set_from_function(name="From %(m)d to %(n)d", + ....: category=FiniteEnumeratedSets()) + ....: def f(m, n): return xsrange(m, n + 1) sage: E = f(3,10); E From 3 to 10 sage: E.list() @@ -604,38 +614,34 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): From 1 to 100 sage: E.cardinality() 100 - sage: f(n=100,m=1) == E + sage: f(n=100, m=1) == E True - An example which mixes together ``set_from_function`` and - ``cached_method``:: + An example which mixes together :func:`set_from_function` and + :func:`cached_method`:: sage: @cached_function - ....: @set_from_function( - ....: name = "Graphs on %(n)d vertices", - ....: category = FiniteEnumeratedSets(), - ....: cache = True) + ....: @set_from_function(name="Graphs on %(n)d vertices", + ....: category=FiniteEnumeratedSets(), cache=True) ....: def Graphs(n): return graphs(n) - sage: Graphs(10) + sage: Graphs(10) # needs sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) + sage: Graphs(10).unrank(0) # needs sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) + sage: Graphs(10) is Graphs(10) # needs sage.graphs True - The ``cached_function`` must go first:: + The ``@cached_function`` must go first:: - sage: @set_from_function( - ....: name = "Graphs on %(n)d vertices", - ....: category = FiniteEnumeratedSets(), - ....: cache = True) + sage: @set_from_function(name="Graphs on %(n)d vertices", + ....: category=FiniteEnumeratedSets(), cache=True) ....: @cached_function ....: def Graphs(n): return graphs(n) - sage: Graphs(10) + sage: Graphs(10) # needs sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) + sage: Graphs(10).unrank(0) # needs sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) + sage: Graphs(10) is Graphs(10) # needs sage.graphs False """ def __init__(self, f=None, name=None, **options): @@ -719,7 +725,7 @@ class EnumeratedSetFromIterator_method_caller(Decorator): - ``f`` -- a method of a class of ``inst`` (and not of the instance itself) - ``name`` -- optional -- either a string (which may contains substitution - rules from argument or a function args,kwds -> string. + rules from argument or a function ``args, kwds -> string``. - ``options`` -- any option accepted by :class:`EnumeratedSetFromIterator` """ @@ -746,7 +752,8 @@ def __init__(self, inst, f, name=None, **options): sage: loads(dumps(d.f())) Traceback (most recent call last): ... - _pickle.PicklingError: Can't pickle : it's not the same object as sage.sets.set_from_iterator.DummyExampleForPicklingTest.f + _pickle.PicklingError: Can't pickle : + it's not the same object as sage.sets.set_from_iterator.DummyExampleForPicklingTest.f """ self.inst = inst self.f = f @@ -811,8 +818,8 @@ def __get__(self, inst, cls): sage: class A: ....: stop = 10000 ....: @set_from_method - ....: def f(self,start): - ....: return xsrange(start,self.stop) + ....: def f(self, start): + ....: return xsrange(start, self.stop) sage: a = A() sage: A.f(a,4) {4, 5, 6, 7, 8, ...} @@ -820,8 +827,8 @@ def __get__(self, inst, cls): sage: class B: ....: stop = 10000 ....: @set_from_method(category=FiniteEnumeratedSets()) - ....: def f(self,start): - ....: return xsrange(start,self.stop) + ....: def f(self, start): + ....: return xsrange(start, self.stop) sage: b = B() sage: B.f(b,2) {2, 3, 4, 5, 6, ...} @@ -850,9 +857,9 @@ class EnumeratedSetFromIterator_method_decorator(): sage: from sage.sets.set_from_iterator import set_from_method sage: class A(): - ....: def n(self): return 12 - ....: @set_from_method - ....: def f(self): return xsrange(self.n()) + ....: def n(self): return 12 + ....: @set_from_method + ....: def f(self): return xsrange(self.n()) sage: a = A() sage: print(a.f.__class__) @@ -864,31 +871,28 @@ class EnumeratedSetFromIterator_method_decorator(): A more complicated example with a parametrized name:: sage: class B(): - ....: @set_from_method( - ....: name = "Graphs(%(n)d)", - ....: category = FiniteEnumeratedSets()) - ....: def graphs(self, n): return graphs(n) + ....: @set_from_method(name="Graphs(%(n)d)", + ....: category=FiniteEnumeratedSets()) + ....: def graphs(self, n): return graphs(n) sage: b = B() - sage: G3 = b.graphs(3) - sage: G3 + sage: G3 = b.graphs(3); G3 Graphs(3) - sage: G3.cardinality() + sage: G3.cardinality() # needs sage.graphs 4 sage: G3.category() Category of facade finite enumerated sets - sage: B.graphs(b,3) + sage: B.graphs(b, 3) Graphs(3) And a last example with a name parametrized by a function:: sage: class D(): - ....: def __init__(self, name): self.name = str(name) - ....: def __str__(self): return self.name - ....: @set_from_method( - ....: name = lambda self,n: str(self)*n, - ....: category = FiniteEnumeratedSets()) - ....: def subset(self, n): - ....: return xsrange(n) + ....: def __init__(self, name): self.name = str(name) + ....: def __str__(self): return self.name + ....: @set_from_method(name=lambda self, n: str(self) * n, + ....: category=FiniteEnumeratedSets()) + ....: def subset(self, n): + ....: return xsrange(n) sage: d = D('a') sage: E = d.subset(3); E aaa @@ -948,9 +952,9 @@ def __call__(self, f): sage: from sage.sets.set_from_iterator import set_from_method sage: class A: # indirect doctest - ....: @set_from_method() - ....: def f(self): - ....: return xsrange(3) + ....: @set_from_method() + ....: def f(self): + ....: return xsrange(3) sage: a = A() sage: a.f() {0, 1, 2} @@ -963,9 +967,9 @@ def __get__(self, inst, cls): sage: from sage.sets.set_from_iterator import set_from_method sage: class A(): - ....: def n(self): return 12 - ....: @set_from_method - ....: def f(self): return xsrange(self.n()) + ....: def n(self): return 12 + ....: @set_from_method + ....: def f(self): return xsrange(self.n()) sage: a = A() sage: print(A.f.__class__) diff --git a/src/sage/sets/totally_ordered_finite_set.py b/src/sage/sets/totally_ordered_finite_set.py index fde8984b501..f28840c81f7 100644 --- a/src/sage/sets/totally_ordered_finite_set.py +++ b/src/sage/sets/totally_ordered_finite_set.py @@ -173,8 +173,8 @@ class TotallyOrderedFiniteSet(FiniteEnumeratedSet): sage: T1 = TotallyOrderedFiniteSet([3,2,5,1]) sage: T1(3) < T1(1) False - sage: T2 = TotallyOrderedFiniteSet([3,var('x')]) - sage: T2(3) < T2(var('x')) + sage: T2 = TotallyOrderedFiniteSet([3, x]) # needs sage.symbolic + sage: T2(3) < T2(x) # needs sage.symbolic 3 < x To make the above example work, you should set the argument facade to diff --git a/src/sage/symbolic/series_impl.pxi b/src/sage/symbolic/series_impl.pxi index abac6155572..1d979dbc505 100644 --- a/src/sage/symbolic/series_impl.pxi +++ b/src/sage/symbolic/series_impl.pxi @@ -1,4 +1,4 @@ -""" +r""" Symbolic Series Symbolic series are special kinds of symbolic expressions that are diff --git a/src/sage/tensor/modules/tensor_with_indices.py b/src/sage/tensor/modules/tensor_with_indices.py index 2e4c611b11a..8a637315af8 100644 --- a/src/sage/tensor/modules/tensor_with_indices.py +++ b/src/sage/tensor/modules/tensor_with_indices.py @@ -258,8 +258,8 @@ def _parse_indices(indices, tensor_type=None, allow_contraction=True, indices. Parse ``indices`` checking usual conventions on repeating indices, - wildcard, balanced parentheses/brackets and raises a ValueError if not. - Return a couple contravariant/covariant indices. + wildcard, balanced parentheses/brackets and raises a :class:`ValueError` + if not. Return a couple contravariant/covariant indices. INPUT: diff --git a/src/sage/tests/benchmark.py b/src/sage/tests/benchmark.py index 6ac0136c653..626388bd3ab 100644 --- a/src/sage/tests/benchmark.py +++ b/src/sage/tests/benchmark.py @@ -14,11 +14,9 @@ sage: import sage.tests.benchmark """ - from cysignals.alarm import alarm, cancel_alarm, AlarmInterrupt from sage.combinat.combinat import fibonacci from sage.functions.other import factorial -from sage.interfaces.gap import gap from sage.interfaces.gp import gp from sage.interfaces.macaulay2 import macaulay2 from sage.interfaces.magma import magma, Magma @@ -27,6 +25,7 @@ from sage.interfaces.maxima import maxima from sage.interfaces.singular import singular from sage.libs.pari import pari +from sage.libs.gap.libgap import libgap from sage.matrix.matrix_space import MatrixSpace from sage.misc.functional import log from sage.misc.timing import cputime, walltime @@ -40,6 +39,7 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.schemes.elliptic_curves.constructor import EllipticCurve + def avg(X): """ Return the average of the list X. @@ -50,13 +50,14 @@ def avg(X): sage: avg([1,2,3]) 2.0 """ - s = sum(X,0) - return s/float(len(X)) + s = sum(X, 0) + return s / float(len(X)) -STD_SYSTEMS = ['sage', 'maxima', 'gap', 'gp', 'pari', 'python'] +STD_SYSTEMS = ['sage', 'maxima', 'libgap', 'gp', 'pari', 'python'] OPT_SYSTEMS = ['magma', 'macaulay2', 'maple', 'mathematica'] + class Benchmark: """ A class for running specific benchmarks against different systems. @@ -133,12 +134,12 @@ def run(self, systems=None, timeout=60, trials=1, sort=False, optional=False): mn = min(X) mx = max(X) av = avg(X) - s = '* %-12s%-12f%-12f%-12f%-12s'%(S, mn, av, - mx, trials) + s = '* %-12s%-12f%-12f%-12f%-12s' % (S, mn, av, + mx, trials) if wall: - s += '%15fw'%t + s += '%15fw' % t else: - s += '%15fc'%t + s += '%15fc' % t print(s) except AlarmInterrupt: print('%-12sinterrupted (timeout: %s seconds wall time)' % @@ -188,7 +189,7 @@ def __init__(self, n): 99-Division polynomial """ self.__n = n - self.repr_str = "%s-Division polynomial"%self.__n + self.repr_str = "%s-Division polynomial" % self.__n def sage(self): """ @@ -200,11 +201,10 @@ def sage(self): sage: B = Divpoly(3) sage: isinstance(B.sage(), float) True - """ n = self.__n t = cputime() - E = EllipticCurve([1,2,3,4,5]) + E = EllipticCurve([1, 2, 3, 4, 5]) E.division_polynomial(n) return cputime(t) @@ -222,14 +222,15 @@ def magma(self): """ n = self.__n t = magma.cputime() - magma('DivisionPolynomial(EllipticCurve([1,2,3,4,5]), %s)'%n) + magma('DivisionPolynomial(EllipticCurve([1,2,3,4,5]), %s)' % n) return magma.cputime(t) + class PolySquare(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = 'Square a polynomial of degree %s over %s'%(self.__n, self.__R) + self.repr_str = 'Square a polynomial of degree %s over %s' % (self.__n, self.__R) def sage(self): """ @@ -241,11 +242,10 @@ def sage(self): sage: B = PolySquare(3, QQ) sage: isinstance(B.sage(), float) True - """ R = self.__R n = self.__n - f = R['x'](range(1,n+1)) + f = R['x'](range(1, n + 1)) t = cputime() f**2 return cputime(t) @@ -260,12 +260,11 @@ def magma(self): sage: B = PolySquare(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('PolynomialRing(%s)![1..%s]'%(R.name(),self.__n)) + f = magma('PolynomialRing(%s)![1..%s]' % (R.name(), self.__n)) t = magma.cputime() - f*f + f * f return magma.cputime(t) def maple(self): @@ -284,18 +283,19 @@ def maple(self): if not (R == ZZ or R == QQ): raise NotImplementedError n = self.__n - f = maple(str(R['x'](range(1,n+1)))) + f = maple(str(R['x'](range(1, n + 1)))) t = walltime() - f*f + f * f return False, walltime(t) + class MPolynomialPower(Benchmark): def __init__(self, nvars=2, exp=10, base=QQ, allow_singular=True): self.nvars = nvars self.exp = exp self.base = base self.allow_singular = allow_singular - s = 'Compute (x_0 + ... + x_%s)^%s over %s'%( + s = 'Compute (x_0 + ... + x_%s)^%s over %s' % ( self.nvars - 1, self.exp, self.base) if self.allow_singular: s += ' (use singular for Sage mult.)' @@ -396,14 +396,14 @@ def mathematica(self): (z**self.exp).Expand() return False, walltime(w) -## this doesn't really expand out -- pari has no function to do so, -## as far as I know. -## def gp(self): -## R = PolynomialRing(self.base, self.nvars) -## z = gp(str(sum(R.gens()))) -## gp.eval('gettime') -## z**self.exp -## return float(gp.eval('gettime/1000.0')) +# this doesn't really expand out -- pari has no function to do so, +# as far as I know. +# def gp(self): +# R = PolynomialRing(self.base, self.nvars) +# z = gp(str(sum(R.gens()))) +# gp.eval('gettime') +# z**self.exp +# return float(gp.eval('gettime/1000.0')) def magma(self): """ @@ -419,7 +419,7 @@ def magma(self): """ R = magma.PolynomialRing(self.base, self.nvars) z = R.gen(1) - for i in range(2,self.nvars+1): + for i in range(2, self.nvars + 1): z += R.gen(i) t = magma.cputime() z**magma(self.exp) @@ -428,13 +428,13 @@ def magma(self): class MPolynomialMult(Benchmark): def __init__(self, nvars=2, base=QQ, allow_singular=True): - if nvars%2: + if nvars % 2: nvars += 1 self.nvars = nvars self.base = base self.allow_singular = allow_singular - s = 'Compute (x_0 + ... + x_%s) * (x_%s + ... + x_%s) over %s'%( - self.nvars/2 - 1, self.nvars/2, self.nvars, self.base) + s = 'Compute (x_0 + ... + x_%s) * (x_%s + ... + x_%s) over %s' % ( + self.nvars // 2 - 1, self.nvars // 2, self.nvars, self.base) if self.allow_singular: s += ' (use singular for Sage mult.)' self.repr_str = s @@ -449,14 +449,13 @@ def maxima(self): sage: B = MPolynomialMult() sage: isinstance(B.maxima()[1], float) True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = maxima(str(sum(R.gens()[:k]))) z1 = maxima(str(sum(R.gens()[k:]))) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def maple(self): @@ -469,14 +468,13 @@ def maple(self): sage: B = MPolynomialMult() sage: isinstance(B.maple()[1], float) # optional - maple True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = maple(str(sum(R.gens()[:k]))) z1 = maple(str(sum(R.gens()[k:]))) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def mathematica(self): @@ -496,17 +494,17 @@ def mathematica(self): z0 = mathematica(str(sum(R.gens()[:k]))) z1 = mathematica(str(sum(R.gens()[k:]))) w = walltime() - (z0*z1).Expand() + (z0 * z1).Expand() return False, walltime(w) -## def gp(self): -## R = PolynomialRing(self.base, self.nvars) -## k = self.nvars // 2 -## z0 = gp(str(sum(R.gens()[:k]))) -## z1 = gp(str(sum(R.gens()[k:]))) -## gp.eval('gettime') -## z0*z1 -## return float(gp.eval('gettime/1000.0')) +# def gp(self): +# R = PolynomialRing(self.base, self.nvars) +# k = self.nvars // 2 +# z0 = gp(str(sum(R.gens()[:k]))) +# z1 = gp(str(sum(R.gens()[k:]))) +# gp.eval('gettime') +# z0*z1 +# return float(gp.eval('gettime/1000.0')) def sage(self): """ @@ -528,7 +526,7 @@ def sage(self): z0 = singular(z0) z1 = singular(z1) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) else: t = cputime() @@ -545,14 +543,13 @@ def macaulay2(self): sage: B = MPolynomialMult() sage: isinstance(B.macaulay2()[1], float) # optional - macaulay2 True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = macaulay2(sum(R.gens()[:k])) z1 = macaulay2(sum(R.gens()[k:])) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) def magma(self): @@ -570,43 +567,44 @@ def magma(self): R = magma.PolynomialRing(self.base, self.nvars) z0 = R.gen(1) k = self.nvars // 2 - for i in range(2,k+1): + for i in range(2, k + 1): z0 += R.gen(i) z1 = R.gen(k + 1) - for i in range(k+1, self.nvars + 1): + for i in range(k + 1, self.nvars + 1): z1 += R.gen(i) t = magma.cputime() z0 * z1 return magma.cputime(t) + class MPolynomialMult2(Benchmark): def __init__(self, nvars=2, base=QQ, allow_singular=True): - if nvars%2: + if nvars % 2: nvars += 1 self.nvars = nvars self.base = base self.allow_singular = allow_singular - s = 'Compute (x_1 + 2*x_2 + 3*x_3 + ... + %s*x_%s) * (%s * x_%s + ... + %s*x_%s) over %s'%( - self.nvars/2, self.nvars/2, self.nvars/2+1, self.nvars/2+1, - self.nvars+1, self.nvars+1, self.base) + s = 'Compute (x_1 + 2*x_2 + 3*x_3 + ... + %s*x_%s) * (%s * x_%s + ... + %s*x_%s) over %s' % ( + self.nvars // 2, self.nvars // 2, self.nvars // 2 + 1, self.nvars // 2 + 1, + self.nvars + 1, self.nvars + 1, self.base) if self.allow_singular: s += ' (use singular for Sage mult.)' self.repr_str = s -## def gp(self): -## R = PolynomialRing(self.base, self.nvars) -## k = self.nvars // 2 -## z0 = R(0) -## z1 = R(0) -## for i in range(k): -## z0 += (i+1)*R.gen(i) -## for i in range(k,self.nvars): -## z1 += (i+1)*R.gen(i) -## z0 = gp(str(z0)) -## z1 = gp(str(z1)) -## gp.eval('gettime') -## z0*z1 -## return float(gp.eval('gettime/1000.0')) +# def gp(self): +# R = PolynomialRing(self.base, self.nvars) +# k = self.nvars // 2 +# z0 = R(0) +# z1 = R(0) +# for i in range(k): +# z0 += (i+1)*R.gen(i) +# for i in range(k,self.nvars): +# z1 += (i+1)*R.gen(i) +# z0 = gp(str(z0)) +# z1 = gp(str(z1)) +# gp.eval('gettime') +# z0*z1 +# return float(gp.eval('gettime/1000.0')) def maxima(self): """ @@ -618,20 +616,19 @@ def maxima(self): sage: B = MPolynomialMult2() sage: isinstance(B.maxima()[1], float) True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = maxima(str(z0)) z1 = maxima(str(z1)) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def macaulay2(self): @@ -644,20 +641,19 @@ def macaulay2(self): sage: B = MPolynomialMult2() sage: isinstance(B.macaulay2()[1], float) # optional - macaulay2 True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = macaulay2(z0) z1 = macaulay2(z1) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) def maple(self): @@ -670,20 +666,19 @@ def maple(self): sage: B = MPolynomialMult2() sage: isinstance(B.maple()[1], float) # optional - maple True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = maple(str(z0)) z1 = maple(str(z1)) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def mathematica(self): @@ -696,20 +691,19 @@ def mathematica(self): sage: B = MPolynomialMult2() sage: isinstance(B.mathematica()[1], float) # optional - mathematica True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = mathematica(str(z0)) z1 = mathematica(str(z1)) w = walltime() - (z0*z1).Expand() + (z0 * z1).Expand() return False, walltime(w) def sage(self): @@ -729,14 +723,14 @@ def sage(self): z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) if self.allow_singular: z0 = singular(z0) z1 = singular(z1) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) else: t = cputime() @@ -753,28 +747,27 @@ def magma(self): sage: B = MPolynomialMult2() sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma.PolynomialRing(self.base, self.nvars) z0 = R.gen(1) k = self.nvars // 2 - for i in range(2,k+1): - z0 += magma(i)*R.gen(i) + for i in range(2, k + 1): + z0 += magma(i) * R.gen(i) z1 = R.gen(k + 1) - for i in range(k+1, self.nvars + 1): - z1 += magma(i)*R.gen(i) + for i in range(k + 1, self.nvars + 1): + z1 += magma(i) * R.gen(i) t = magma.cputime() z0 * z1 return magma.cputime(t) class CharPolyTp(Benchmark): - def __init__(self, N=37,k=2,p=2,sign=1): + def __init__(self, N=37, k=2, p=2, sign=1): self.N = N self.k = k self.p = p self.sign = sign - self.repr_str = "Compute the charpoly (given the matrix) of T_%s on S_%s(Gamma_0(%s)) with sign %s."%(self.p, self.k, self.N, self.sign) + self.repr_str = "Compute the charpoly (given the matrix) of T_%s on S_%s(Gamma_0(%s)) with sign %s." % (self.p, self.k, self.N, self.sign) def matrix(self): try: @@ -856,7 +849,7 @@ class PolyFactor(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = "Factor a product of 2 polynomials of degree %s over %s."%(self.__n, self.__R) + self.repr_str = "Factor a product of 2 polynomials of degree %s over %s." % (self.__n, self.__R) def sage(self): """ @@ -868,12 +861,11 @@ def sage(self): sage: B = PolyFactor(3, QQ) sage: isinstance(B.sage(), float) True - """ R = PolynomialRing(self.__R, 'x') - f = R(range(1,self.__n+1)) - g = R(range(self.__n+1,2*(self.__n+1))) - h = f*g + f = R(range(1, self.__n + 1)) + g = R(range(self.__n + 1, 2 * (self.__n + 1))) + h = f * g t = cputime() h.factor() return cputime(t) @@ -888,13 +880,12 @@ def magma(self): sage: B = PolyFactor(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('PolynomialRing(%s)![1..%s]'%(R.name(),self.__n)) - g = magma('PolynomialRing(%s)![%s+1..2*(%s+1)]'%( - R.name(),self.__n,self.__n)) - h = f*g + f = magma('PolynomialRing(%s)![1..%s]' % (R.name(), self.__n)) + g = magma('PolynomialRing(%s)![%s+1..2*(%s+1)]' % ( + R.name(), self.__n, self.__n)) + h = f * g t = magma.cputime() h.Factorization() return magma.cputime(t) @@ -909,12 +900,11 @@ def gp(self): sage: B = PolyFactor(3, QQ) sage: isinstance(B.gp(), float) True - """ R = PolynomialRing(self.__R, 'x') - f = R(range(1,self.__n+1)) - g = R(range(self.__n+1,2*(self.__n+1))) - h = f*g + f = R(range(1, self.__n + 1)) + g = R(range(self.__n + 1, 2 * (self.__n + 1))) + h = f * g f = gp(h) gp.eval('gettime') f.factor() @@ -924,8 +914,8 @@ def gp(self): class SquareInts(Benchmark): def __init__(self, base=10, ndigits=10**5): self.__ndigits = ndigits - self.base =base - self.repr_str = "Square the integer %s^%s"%(self.base, self.__ndigits) + self.base = base + self.repr_str = "Square the integer %s^%s" % (self.base, self.__ndigits) def sage(self): """ @@ -954,9 +944,8 @@ def gp(self): sage: B = SquareInts() sage: isinstance(B.gp(), float) True - """ - n = gp('%s^%s'%(self.base,self.__ndigits)) + n = gp('%s^%s' % (self.base, self.__ndigits)) gp.eval('gettime') n**2 return float(gp.eval('gettime/1000.0')) @@ -971,9 +960,8 @@ def maxima(self): sage: B = SquareInts() sage: isinstance(B.maxima()[1], float) True - """ - n = maxima('%s^%s'%(self.base,self.__ndigits)) + n = maxima('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) @@ -988,9 +976,8 @@ def magma(self): sage: B = SquareInts() sage: isinstance(B.magma(), float) # optional - magma True - """ - n = magma('%s^%s'%(self.base,self.__ndigits)) + n = magma('%s^%s' % (self.base, self.__ndigits)) t = magma.cputime() n**2 return magma.cputime(t) @@ -1022,26 +1009,24 @@ def maple(self): sage: B = SquareInts() sage: isinstance(B.maple()[1], float) # optional - maple True - """ - n = maple('%s^%s'%(self.base,self.__ndigits)) + n = maple('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) - def gap(self): + def libgap(self): """ - Time the computation in GAP. + Time the computation in libGAP. EXAMPLES:: sage: from sage.tests.benchmark import SquareInts sage: B = SquareInts() - sage: isinstance(B.gap()[1], float) + sage: isinstance(B.libgap()[1], float) True - """ - n = gap('%s^%s'%(self.base,self.__ndigits)) + n = libgap(self.base)**libgap(self.__ndigits) t = walltime() n**2 return False, walltime(t) @@ -1056,9 +1041,8 @@ def mathematica(self): sage: B = SquareInts() sage: isinstance(B.mathematica()[1], float) # optional - mathematica True - """ - n = mathematica('%s^%s'%(self.base,self.__ndigits)) + n = mathematica('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) @@ -1068,7 +1052,7 @@ class MatrixSquare(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = 'Square a matrix of degree %s over %s'%(self.__n, self.__R) + self.repr_str = 'Square a matrix of degree %s over %s' % (self.__n, self.__R) def sage(self): """ @@ -1080,11 +1064,10 @@ def sage(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.sage(), float) True - """ R = self.__R n = self.__n - f = MatrixSpace(R,n)(list(range(n*n))) + f = MatrixSpace(R, n)(list(range(n * n))) t = cputime() f**2 return cputime(t) @@ -1099,13 +1082,12 @@ def magma(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('MatrixAlgebra(%s, %s)![0..%s^2-1]'%( - R.name(),self.__n, self.__n)) + f = magma('MatrixAlgebra(%s, %s)![0..%s^2-1]' % ( + R.name(), self.__n, self.__n)) t = magma.cputime() - f*f + f * f return magma.cputime(t) def gp(self): @@ -1118,37 +1100,37 @@ def gp(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.gp(), float) True - """ n = self.__n - m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))'%(n,n,n)) + m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))' % (n, n, n)) gp('gettime') - m*m + m * m return float(gp.eval('gettime/1000.0')) - def gap(self): + def libgap(self): """ - Time the computation in GAP. + Time the computation in libGAP. EXAMPLES:: sage: from sage.tests.benchmark import MatrixSquare sage: B = MatrixSquare(3, QQ) - sage: isinstance(B.gap()[1], float) + sage: isinstance(B.libgap()[1], float) True - """ + R = self.__R n = self.__n - m = gap(str([list(range(n*k,n*(k+1))) for k in range(n)])) + f = MatrixSpace(R, n)(list(range(n * n))) + m = libgap(f) t = walltime() - m*m + m * m return False, walltime(t) class Factorial(Benchmark): def __init__(self, n): self.__n = n - self.repr_str = "Compute the factorial of %s"%self.__n + self.repr_str = "Compute the factorial of %s" % self.__n def sage(self): """ @@ -1176,10 +1158,9 @@ def magma(self): sage: B = Factorial(10) sage: isinstance(B.magma(), float) # optional - magma True - """ t = magma.cputime() - magma('&*[1..%s]'%self.__n) # &* is way better than Factorial!! + magma('&*[1..%s]' % self.__n) # &* is way better than Factorial!! return magma.cputime(t) def maple(self): @@ -1209,16 +1190,16 @@ def gp(self): sage: B = Factorial(10) sage: isinstance(B.gp(), float) True - """ gp.eval('gettime') - gp('%s!'%self.__n) + gp('%s!' % self.__n) return float(gp.eval('gettime/1000.0')) + class Fibonacci(Benchmark): def __init__(self, n): self.__n = n - self.repr_str = "Compute the %s-th Fibonacci number"%self.__n + self.repr_str = "Compute the %s-th Fibonacci number" % self.__n def sage(self): """ @@ -1246,25 +1227,23 @@ def magma(self): sage: B = Fibonacci(10) sage: isinstance(B.magma(), float) # optional - magma True - """ t = magma.cputime() - magma('Fibonacci(%s)'%self.__n) + magma('Fibonacci(%s)' % self.__n) return magma.cputime(t) - def gap(self): + def libgap(self): """ - Time the computation in GAP. + Time the computation in libGAP. EXAMPLES:: sage: from sage.tests.benchmark import Fibonacci sage: B = Fibonacci(10) - sage: isinstance(B.gap()[1], float) + sage: isinstance(B.libgap()[1], float) True - """ - n = gap(self.__n) + n = libgap(self.__n) t = walltime() n.Fibonacci() return False, walltime(t) @@ -1279,7 +1258,6 @@ def mathematica(self): sage: B = Fibonacci(10) sage: isinstance(B.mathematica()[1], float) # optional - mathematica True - """ n = mathematica(self.__n) t = walltime() @@ -1296,17 +1274,16 @@ def gp(self): sage: B = Fibonacci(10) sage: isinstance(B.gp(), float) True - """ gp.eval('gettime') - gp('fibonacci(%s)'%self.__n) + gp('fibonacci(%s)' % self.__n) return float(gp.eval('gettime/1000.0')) class SEA(Benchmark): def __init__(self, p): self.__p = p - self.repr_str = "Do SEA on an elliptic curve over GF(%s)"%self.__p + self.repr_str = "Do SEA on an elliptic curve over GF(%s)" % self.__p def sage(self): """ @@ -1318,9 +1295,8 @@ def sage(self): sage: B = SEA(5) sage: isinstance(B.sage()[1], float) True - """ - E = EllipticCurve([1,2,3,4,5]) + E = EllipticCurve([1, 2, 3, 4, 5]) t = walltime() # Note that from pari 2.4.3, the SEA algorithm is used by the # pari library, but only for large primes, so for a better @@ -1339,18 +1315,18 @@ def magma(self): sage: B = SEA(5) sage: isinstance(B.magma(), float) # optional - magma True - """ magma(0) t = magma.cputime() - magma('#EllipticCurve([GF(%s)|1,2,3,4,5])'%(self.__p)) + magma('#EllipticCurve([GF(%s)|1,2,3,4,5])' % (self.__p)) return magma.cputime(t) + class MatrixKernel(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = 'Kernel of a matrix of degree %s over %s'%(self.__n, self.__R) + self.repr_str = 'Kernel of a matrix of degree %s over %s' % (self.__n, self.__R) def sage(self): """ @@ -1362,11 +1338,10 @@ def sage(self): sage: B = MatrixKernel(3, QQ) sage: isinstance(B.sage(), float) True - """ R = self.__R n = self.__n - f = MatrixSpace(R,n,2*n)(list(range(n*(2*n)))) + f = MatrixSpace(R, n, 2 * n)(list(range(n * (2 * n)))) t = cputime() f.kernel() return cputime(t) @@ -1381,11 +1356,10 @@ def magma(self): sage: B = MatrixKernel(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('RMatrixSpace(%s, %s, %s)![0..(%s*2*%s)-1]'%( - R.name(),self.__n, 2*self.__n, self.__n, self.__n)) + f = magma('RMatrixSpace(%s, %s, %s)![0..(%s*2*%s)-1]' % ( + R.name(), self.__n, 2 * self.__n, self.__n, self.__n)) t = magma.cputime() f.Kernel() return magma.cputime(t) @@ -1400,19 +1374,19 @@ def gp(self): sage: B = MatrixKernel(3, QQ) sage: isinstance(B.gp(), float) True - """ n = self.__n - m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))'%(n,2*n,n)) + m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))' % (n, 2 * n, n)) gp('gettime') m.matker() return float(gp.eval('gettime/1000.0')) + class ComplexMultiply(Benchmark): def __init__(self, bits_prec, times): self.__bits_prec = bits_prec self.__times = times - self.repr_str = "List of multiplies of two complex numbers with %s bits of precision %s times"%(self.__bits_prec, self.__times) + self.repr_str = "List of multiplies of two complex numbers with %s bits of precision %s times" % (self.__bits_prec, self.__times) def sage(self): """ @@ -1424,12 +1398,11 @@ def sage(self): sage: B = ComplexMultiply(28, 2) sage: isinstance(B.sage(), float) True - """ CC = ComplexField(self.__bits_prec) - s = CC(2).sqrt() + (CC.gen()*2).sqrt() + s = CC(2).sqrt() + (CC.gen() * 2).sqrt() t = cputime() - [s*s for _ in range(self.__times)] + [s * s for _ in range(self.__times)] return cputime(t) def magma(self): @@ -1446,14 +1419,13 @@ def magma(self): .. NOTE:: decimal digits (despite magma docs that say bits!!) - """ - n = int(self.__bits_prec/log(10,2)) + 1 + n = int(self.__bits_prec / log(10, 2)) + 1 CC = magma.ComplexField(n) s = CC(2).Sqrt() + CC.gen(1).Sqrt() t = magma.cputime() - magma.eval('s := %s;'%s.name()) - magma('[s*s : i in [1..%s]]'%self.__times) + magma.eval('s := %s;' % s.name()) + magma('[s*s : i in [1..%s]]' % self.__times) return magma.cputime(t) def gp(self): @@ -1466,20 +1438,20 @@ def gp(self): sage: B = ComplexMultiply(28, 2) sage: isinstance(B.gp(), float) True - """ - n = int(self.__bits_prec/log(10,2)) + 1 + n = int(self.__bits_prec / log(10, 2)) + 1 gp.set_real_precision(n) gp.eval('s = sqrt(2) + sqrt(2*I);') gp.eval('gettime;') - gp('vector(%s,i,s*s)'%self.__times) + gp('vector(%s,i,s*s)' % self.__times) return float(gp.eval('gettime/1000.0')) + class ModularSymbols1(Benchmark): def __init__(self, N, k=2): self.__N = N self.__k = k - self.repr_str = 'Presentation for modular symbols on Gamma_0(%s) of weight %s'%(self.__N, self.__k) + self.repr_str = 'Presentation for modular symbols on Gamma_0(%s) of weight %s' % (self.__N, self.__k) def sage(self): """ @@ -1507,20 +1479,20 @@ def magma(self): sage: B = ModularSymbols1(11) sage: isinstance(B.magma(), float) # optional - magma True - """ - magma = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared + magma = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared t = magma.cputime() - magma('ModularSymbols(%s, %s)'%(self.__N, self.__k)) + magma('ModularSymbols(%s, %s)' % (self.__N, self.__k)) return magma.cputime(t) + class ModularSymbolsDecomp1(Benchmark): def __init__(self, N, k=2, sign=1, bnd=10): self.N = N self.k = k self.sign = sign self.bnd = bnd - self.repr_str = 'Decomposition of modular symbols on Gamma_0(%s) of weight %s and sign %s'%(self.N, self.k, self.sign) + self.repr_str = 'Decomposition of modular symbols on Gamma_0(%s) of weight %s and sign %s' % (self.N, self.k, self.sign) def sage(self): """ @@ -1532,7 +1504,6 @@ def sage(self): sage: B = ModularSymbolsDecomp1(11) sage: isinstance(B.sage(), float) True - """ t = cputime() M = ModularSymbols(self.N, self.k, sign=self.sign, use_cache=False) @@ -1549,18 +1520,18 @@ def magma(self): sage: B = ModularSymbolsDecomp1(11) sage: isinstance(B.magma(), float) # optional - magma True - """ - m = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared + m = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared t = m.cputime() - m.eval('Decomposition(ModularSymbols(%s, %s, %s),%s);'%( + m.eval('Decomposition(ModularSymbols(%s, %s, %s),%s);' % ( self.N, self.k, self.sign, self.bnd)) return m.cputime(t) + class EllipticCurveTraces(Benchmark): def __init__(self, B): self.B = B - self.repr_str = "Compute all a_p for the elliptic curve [1,2,3,4,5], for p < %s"%self.B + self.repr_str = "Compute all a_p for the elliptic curve [1,2,3,4,5], for p < %s" % self.B def sage(self): """ @@ -1574,9 +1545,8 @@ def sage(self): Traceback (most recent call last): ... TypeError: ...anlist() got an unexpected keyword argument 'pari_ints' - """ - E = EllipticCurve([1,2,3,4,5]) + E = EllipticCurve([1, 2, 3, 4, 5]) t = cputime() E.anlist(self.B, pari_ints=True) return cputime(t) @@ -1591,17 +1561,17 @@ def magma(self): sage: B = EllipticCurveTraces(11) sage: isinstance(B.magma(), float) # optional - magma True - """ - E = magma.EllipticCurve([1,2,3,4,5]) + E = magma.EllipticCurve([1, 2, 3, 4, 5]) t = magma.cputime() E.TracesOfFrobenius(self.B) return magma.cputime(t) + class EllipticCurvePointMul(Benchmark): def __init__(self, n): self.n = n - self.repr_str = "Compute %s*(0,0) on the elliptic curve [0, 0, 1, -1, 0] over QQ"%self.n + self.repr_str = "Compute %s*(0,0) on the elliptic curve [0, 0, 1, -1, 0] over QQ" % self.n def sage(self): """ @@ -1613,10 +1583,9 @@ def sage(self): sage: B = EllipticCurvePointMul(11) sage: isinstance(B.sage(), float) True - """ E = EllipticCurve([0, 0, 1, -1, 0]) - P = E([0,0]) + P = E([0, 0]) t = cputime() self.n * P return cputime(t) @@ -1649,11 +1618,10 @@ def gp(self): sage: B = EllipticCurvePointMul(11) sage: isinstance(B.gp(), float) True - """ E = gp.ellinit('[0, 0, 1, -1, 0]') gp.eval('gettime') - P = gp([0,0]) + P = gp([0, 0]) E.ellmul(P, self.n) return float(gp.eval('gettime/1000.0')) @@ -1667,18 +1635,18 @@ def pari(self): sage: B = EllipticCurvePointMul(11) sage: isinstance(B.pari(), float) True - """ E = pari('ellinit([0, 0, 1, -1, 0])') pari('gettime') - P = pari([0,0]) + P = pari([0, 0]) E.ellmul(P, self.n) return float(pari('gettime/1000.0')) + class EllipticCurveMW(Benchmark): def __init__(self, ainvs): self.ainvs = ainvs - self.repr_str = "Compute generators for the Mordell-Weil group of the elliptic curve %s over QQ"%self.ainvs + self.repr_str = "Compute generators for the Mordell-Weil group of the elliptic curve %s over QQ" % self.ainvs def sage(self): """ @@ -1714,12 +1682,13 @@ def magma(self): E.Generators() return magma.cputime(t) + class FiniteExtFieldMult(Benchmark): - def __init__(self,field,times): + def __init__(self, field, times): self.__times = times self.field = field - self.e = field.gen()**(field.cardinality()/3) - self.f = field.gen()**(2*field.cardinality()/3) + self.e = field.gen()**(field.cardinality() / 3) + self.f = field.gen()**(2 * field.cardinality() / 3) self.repr_str = "Multiply a^(#K/3) with a^(2*#K/3) where a == K.gen()" def sage(self): @@ -1732,12 +1701,11 @@ def sage(self): sage: B = FiniteExtFieldMult(GF(9, 'x'), 2) sage: isinstance(B.sage(), float) True - """ e = self.e f = self.f t = cputime() - [e*f for _ in range(self.__times)] + [e * f for _ in range(self.__times)] return cputime(t) def pari(self): @@ -1750,12 +1718,11 @@ def pari(self): sage: B = FiniteExtFieldMult(GF(9, 'x'), 2) sage: isinstance(B.pari(), float) True - """ e = self.e.__pari__() f = self.f.__pari__() t = cputime() - [e*f for _ in range(self.__times)] + [e * f for _ in range(self.__times)] return cputime(t) def magma(self): @@ -1768,13 +1735,12 @@ def magma(self): sage: B = FiniteExtFieldMult(GF(9, 'x'), 2) sage: isinstance(B.magma(), float) # optional - magma True - """ - magma.eval('F := GF(%s)'%(self.field.cardinality())) - magma.eval('e := a^Floor(%s/3);'%(self.field.cardinality())) - magma.eval('f := a^Floor(2*%s/3);'%(self.field.cardinality())) + magma.eval('F := GF(%s)' % (self.field.cardinality())) + magma.eval('e := a^Floor(%s/3);' % (self.field.cardinality())) + magma.eval('f := a^Floor(2*%s/3);' % (self.field.cardinality())) t = magma.cputime() - magma('[e*f : i in [1..%s]]'%self.__times) + magma('[e*f : i in [1..%s]]' % self.__times) return magma.cputime(t) @@ -1782,8 +1748,8 @@ class FiniteExtFieldAdd(Benchmark): def __init__(self, field, times): self.__times = times self.field = field - self.e = field.gen()**(field.cardinality()/3) - self.f = field.gen()**(2*field.cardinality()/3) + self.e = field.gen()**(field.cardinality() / 3) + self.f = field.gen()**(2 * field.cardinality() / 3) self.repr_str = "Add a^(#K/3) to a^(2*#K/3) where a == K.gen()" def sage(self): @@ -1796,12 +1762,11 @@ def sage(self): sage: B = FiniteExtFieldAdd(GF(9,'x'), 2) sage: isinstance(B.sage(), float) True - """ e = self.e f = self.f t = cputime() - [e+f for _ in range(self.__times)] + [e + f for _ in range(self.__times)] return cputime(t) def pari(self): @@ -1814,12 +1779,11 @@ def pari(self): sage: B = FiniteExtFieldAdd(GF(9,'x'), 2) sage: isinstance(B.pari(), float) True - """ e = self.e.__pari__() f = self.f.__pari__() t = cputime() - [e+f for _ in range(self.__times)] + [e + f for _ in range(self.__times)] return cputime(t) def magma(self): @@ -1832,13 +1796,12 @@ def magma(self): sage: B = FiniteExtFieldAdd(GF(9,'x'), 2) sage: isinstance(B.magma(), float) # optional - magma True - """ - magma.eval('F := GF(%s)'%(self.field.cardinality())) - magma.eval('e := a^Floor(%s/3);'%(self.field.cardinality())) - magma.eval('f := a^Floor(2*%s/3);'%(self.field.cardinality())) + magma.eval('F := GF(%s)' % (self.field.cardinality())) + magma.eval('e := a^Floor(%s/3);' % (self.field.cardinality())) + magma.eval('f := a^Floor(2*%s/3);' % (self.field.cardinality())) t = magma.cputime() - magma('[e+f : i in [1..%s]]'%self.__times) + magma('[e+f : i in [1..%s]]' % self.__times) return magma.cputime(t) @@ -1857,60 +1820,61 @@ def magma(self): def suite1(): - PolySquare(10000,QQ).run() - PolySquare(20000,ZZ).run() - PolySquare(50000,GF(5)).run() - PolySquare(20000,Integers(8)).run() + PolySquare(10000, QQ).run() + PolySquare(20000, ZZ).run() + PolySquare(50000, GF(5)).run() + PolySquare(20000, Integers(8)).run() - SquareInts(10,2000000).run() + SquareInts(10, 2000000).run() - MatrixSquare(200,QQ).run() - MatrixSquare(50,ZZ).run() + MatrixSquare(200, QQ).run() + MatrixSquare(50, ZZ).run() - SquareInts(10,150000).run() + SquareInts(10, 150000).run() - Factorial(2*10**6).run(systems=['sage', 'magma']) + Factorial(2 * 10**6).run(systems=['sage', 'magma']) Fibonacci(10**6).run() - Fibonacci(2*10**7).run(systems=["sage", "magma", "mathematica"]) + Fibonacci(2 * 10**7).run(systems=["sage", "magma", "mathematica"]) - MatrixKernel(150,QQ).run() + MatrixKernel(150, QQ).run() - ComplexMultiply(100000,1000) - ComplexMultiply(100,100000) - ComplexMultiply(53,100000) + ComplexMultiply(100000, 1000) + ComplexMultiply(100, 100000) + ComplexMultiply(53, 100000) - PolyFactor(300,ZZ) - PolyFactor(300,GF(19)) - PolyFactor(700,GF(19)) + PolyFactor(300, ZZ) + PolyFactor(300, GF(19)) + PolyFactor(700, GF(19)) - PolyFactor(500,GF(49,'a')) - PolyFactor(100,GF((10007,3),'a')) + PolyFactor(500, GF((9, 2), 'a')) + PolyFactor(100, GF((10007, 3), 'a')) + + CharPolyTp(54, 4).run() + CharPolyTp(389, 2).run() + CharPolyTp(389, 2, sign=0, p=3).run() + CharPolyTp(1000, 2, sign=1, p=2).run(systems=['sage', 'magma']) + CharPolyTp(1, 100, sign=1, p=5).run(systems=['sage', 'magma']) # Sage's multimodular really sucks here! (GP is way better, even) + CharPolyTp(512, sign=1, p=3).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(512, sign=0, p=3).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(1024, sign=1, p=3).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(2006, sign=1, p=2).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(2006, sign=1, p=2).run(systems=['sage', 'magma']) # gp takes > 1 minute. - CharPolyTp(54,4).run() - CharPolyTp(389,2).run() - CharPolyTp(389,2,sign=0,p=3).run() - CharPolyTp(1000,2,sign=1,p=2).run(systems=['sage','magma']) - CharPolyTp(1,100,sign=1,p=5).run(systems=['sage','magma']) # Sage's multimodular really sucks here! (GP is way better, even) - CharPolyTp(512,sign=1,p=3).run(systems=['sage','magma','gp']) - CharPolyTp(512,sign=0,p=3).run(systems=['sage','magma','gp']) - CharPolyTp(1024,sign=1,p=3).run(systems=['sage','magma','gp']) - CharPolyTp(2006,sign=1,p=2).run(systems=['sage','magma','gp']) - CharPolyTp(2006,sign=1,p=2).run(systems=['sage','magma']) # gp takes > 1 minute. def mpoly(): # This includes a maxima benchmark. Note that # maxima is *shockingly* slow in comparison to Singular or MAGMA. # It is so slow as to be useless, basically, i.e., factor # of 5000 slower than Singular on this example! - MPolynomialPower(nvars=6,exp=10).run() + MPolynomialPower(nvars=6, exp=10).run() main = ['sage', 'magma'] # just the main competitors - MPolynomialPower(nvars=2,exp=200, allow_singular=False).run(main) - MPolynomialPower(nvars=5,exp=10, allow_singular=False).run(main) - MPolynomialPower(nvars=5,exp=30, allow_singular=True).run(main) - MPolynomialPower(nvars=2,exp=1000, allow_singular=True).run(main) - MPolynomialPower(nvars=10,exp=10, allow_singular=True).run(main) - MPolynomialPower(nvars=4,exp=350, base=GF(7), allow_singular=True).run(main) + MPolynomialPower(nvars=2, exp=200, allow_singular=False).run(main) + MPolynomialPower(nvars=5, exp=10, allow_singular=False).run(main) + MPolynomialPower(nvars=5, exp=30, allow_singular=True).run(main) + MPolynomialPower(nvars=2, exp=1000, allow_singular=True).run(main) + MPolynomialPower(nvars=10, exp=10, allow_singular=True).run(main) + MPolynomialPower(nvars=4, exp=350, base=GF(7), allow_singular=True).run(main) MPolynomialMult(200, allow_singular=False).run(main) MPolynomialMult(400, allow_singular=True).run(main) MPolynomialMult(800, allow_singular=True).run(main) @@ -1948,25 +1912,28 @@ def mpoly_all(include_maple=False): MPolynomialMult(400).run(systems=systems) MPolynomialMult2(256).run(systems=systems) MPolynomialMult2(512).run(systems=systems) - MPolynomialPower(nvars=4,exp=50).run(systems=systems) # mathematica wins - MPolynomialPower(nvars=10,exp=10).run(systems=systems) + MPolynomialPower(nvars=4, exp=50).run(systems=systems) # mathematica wins + MPolynomialPower(nvars=10, exp=10).run(systems=systems) + def modsym_present(): - ModularSymbols1(2006,2) - ModularSymbols1(1,50) - ModularSymbols1(1,100) - ModularSymbols1(1,150) - ModularSymbols1(30,8) - ModularSymbols1(225,4) - ModularSymbols1(2,50) - ModularSymbols1(2,100) + ModularSymbols1(2006, 2) + ModularSymbols1(1, 50) + ModularSymbols1(1, 100) + ModularSymbols1(1, 150) + ModularSymbols1(30, 8) + ModularSymbols1(225, 4) + ModularSymbols1(2, 50) + ModularSymbols1(2, 100) + def modsym_decomp(): - ModularSymbolsDecomp1(1,24).run() - ModularSymbolsDecomp1(125,2).run() - ModularSymbolsDecomp1(389,2).run() - ModularSymbolsDecomp1(1,100).run() - ModularSymbolsDecomp1(54,4).run() + ModularSymbolsDecomp1(1, 24).run() + ModularSymbolsDecomp1(125, 2).run() + ModularSymbolsDecomp1(389, 2).run() + ModularSymbolsDecomp1(1, 100).run() + ModularSymbolsDecomp1(54, 4).run() + def elliptic_curve(): EllipticCurveTraces(100000).run() @@ -1978,7 +1945,7 @@ def elliptic_curve(): # NOTE -- Sage can also do these using Simon's program, which is # *way* *way* faster than MAGMA... - EllipticCurveMW([5,6,7,8,9]).run() - EllipticCurveMW([50,6,7,8,9]).run() + EllipticCurveMW([5, 6, 7, 8, 9]).run() + EllipticCurveMW([50, 6, 7, 8, 9]).run() EllipticCurveMW([1, -1, 0, -79, 289]).run(trials=1) # rank 4 EllipticCurveMW([0, 0, 1, -79, 342]).run(trials=1) # rank 5 (Sage wins) diff --git a/src/sage/tests/cmdline.py b/src/sage/tests/cmdline.py index f14cd2db768..5a06a349f63 100644 --- a/src/sage/tests/cmdline.py +++ b/src/sage/tests/cmdline.py @@ -231,75 +231,49 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False Test ``sage-run`` on a Python file, both with an absolute and with a relative path:: - sage: dir = tmp_dir(); name = 'python_test_file.py' - sage: fullname = os.path.join(dir, name) - sage: F = open(fullname, 'w') - sage: _ = F.write("print(3^33)\n") - sage: F.close() - sage: (out, err, ret) = test_executable(["sage", fullname]) - sage: print(out) - 34 - sage: err - '' - sage: ret - 0 - sage: (out, err, ret) = test_executable(["sage", name], cwd=dir) - sage: print(out) - 34 - sage: err - '' - sage: ret - 0 + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as dir: + ....: name = 'python_test_file.py' + ....: fullname = os.path.join(dir, name) + ....: with open(fullname, 'w') as F: + ....: _ = F.write("print(3^33)\n") + ....: test_executable(["sage", fullname]) + ....: test_executable(["sage", name], cwd=dir) + ('34\n', '', 0) + ('34\n', '', 0) The same as above, but now with a ``.sage`` file. This indirectly also tests the preparser:: - sage: dir = tmp_dir(); name = 'sage_test_file.sage' - sage: fullname = os.path.join(dir, name) - sage: F = open(fullname, 'w') - sage: _ = F.write("k. = GF(5^3); print(a^124)\n") - sage: F.close() - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", fullname]) - sage: print(out) # long time - 1 - sage: err # long time - '' - sage: ret # long time - 0 - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", name], cwd=dir) - sage: print(out) # long time - 1 - sage: err # long time - '' - sage: ret # long time - 0 + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as dir: # long time + ....: name = 'sage_test_file.sage' + ....: fullname = os.path.join(dir, name) + ....: with open(fullname, 'w') as F: + ....: _ = F.write("k. = GF(5^3); print(a^124)\n") + ....: test_executable(["sage", fullname]) + ....: test_executable(["sage", name], cwd=dir) + ('1\n', '', 0) + ('1\n', '', 0) Test running a ``.spyx`` file:: - sage: dir = tmp_dir(); name = 'sage_test_file.spyx' - sage: fullname = os.path.join(dir, name) - sage: F = open(fullname, 'w') - sage: _ = F.write("from cysignals.signals cimport *\nfrom sage.rings.integer cimport Integer\ncdef long i, s = 0\nsig_on()\nfor i in range(1000): s += i\nsig_off()\nprint(Integer(s))") - sage: F.close() - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", fullname], pydebug_ignore_warnings=True) - sage: print(out) # long time - 499500 - sage: import re # long time - sage: bool(re.match('Compiling.*spyx.*', err)) # long time - True - sage: ret # long time - 0 - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", name], cwd=dir, pydebug_ignore_warnings=True) - sage: print(out) # long time - 499500 - sage: bool(re.match('Compiling.*spyx.*', err)) # long time - True - sage: ret # long time - 0 + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as dir: # long time + ....: name = 'sage_test_file.spyx' + ....: fullname = os.path.join(dir, name) + ....: with open(fullname, 'w') as F: + ....: _ = F.write("from cysignals.signals cimport *\n") + ....: _ = F.write("from sage.rings.integer cimport Integer\n") + ....: _ = F.write("cdef long i, s = 0\n") + ....: _ = F.write("sig_on()\n") + ....: _ = F.write("for i in range(5): s += i\n") + ....: _ = F.write("sig_off()\n") + ....: _ = F.write("print(Integer(s))") + ....: test_executable(["sage", fullname], pydebug_ignore_warnings=True) + ....: test_executable(["sage", name], cwd=dir, pydebug_ignore_warnings=True) + ('10\n', 'Compiling .../sage_test_file.spyx...\n', 0) + ('10\n', 'Compiling sage_test_file.spyx...\n', 0) Testing ``sage --preparse FILE`` and ``sage -t FILE``. First create a file and preparse it:: diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 906936a44c1..2f5abd5fc2b 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -836,8 +836,7 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): .. SEEALSO:: If ``cohomology`` is ``True``, this returns the cohomology - as a graded module. For the ring structure, use - :meth:`cohomology_ring`. + as a ring: it calls :meth:`cohomology_ring`. EXAMPLES:: @@ -865,7 +864,14 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): sage: list(H.basis(3)) # needs sage.modules [h^{3,0}] """ - from sage.homology.homology_vector_space_with_basis import HomologyVectorSpaceWithBasis + from sage.homology.homology_vector_space_with_basis import \ + HomologyVectorSpaceWithBasis, HomologyVectorSpaceWithBasis_mod2, \ + is_GF2 + + if cohomology: + return self.cohomology_ring(base_ring) + if is_GF2(base_ring): + return HomologyVectorSpaceWithBasis_mod2(base_ring, self) return HomologyVectorSpaceWithBasis(base_ring, self, cohomology) def cohomology_ring(self, base_ring=QQ): @@ -972,7 +978,11 @@ def cohomology_ring(self, base_ring=QQ): Cohomology ring of Simplicial complex with 9 vertices and 18 facets over Rational Field """ - from sage.homology.homology_vector_space_with_basis import CohomologyRing + from sage.homology.homology_vector_space_with_basis import CohomologyRing, \ + CohomologyRing_mod2, is_GF2 + + if is_GF2(base_ring): + return CohomologyRing_mod2(base_ring, self) return CohomologyRing(base_ring, self) @abstract_method diff --git a/src/sage/version.py b/src/sage/version.py index 659a7932e4e..338430c34c8 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.2.beta5' -date = '2023-09-27' -banner = 'SageMath version 10.2.beta5, Release Date: 2023-09-27' +version = '10.2.beta6' +date = '2023-10-08' +banner = 'SageMath version 10.2.beta6, Release Date: 2023-10-08' diff --git a/tox.ini b/tox.ini index 39a087c1062..c084e4c821e 100644 --- a/tox.ini +++ b/tox.ini @@ -142,6 +142,7 @@ passenv = TARGETS_OPTIONAL docker: EXTRA_DOCKER_BUILD_ARGS docker: EXTRA_DOCKER_TAGS + docker: DOCKER_TAG # Use DOCKER_BUILDKIT=1 for new version - for which unfortunately we cannot save failed builds as an image docker: DOCKER_BUILDKIT docker: BUILDKIT_INLINE_CACHE @@ -221,11 +222,10 @@ setenv = ubuntu-focal: BASE_TAG=focal ubuntu-jammy: BASE_TAG=jammy ubuntu-lunar: BASE_TAG=lunar - ubuntu-lunar: IGNORE_MISSING_SYSTEM_PACKAGES=yes ubuntu-mantic: BASE_TAG=mantic - ubuntu-mantic: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/_/debian + # debian-buster does not have libfreetype-dev (it only has libfreetype6-dev) # debian-bullseye does not have libgiac-dev # debian-trixie does not have libbrial-dev # @@ -236,6 +236,7 @@ setenv = debian-stretch: BASE_TAG=stretch debian-stretch: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-buster: BASE_TAG=buster + debian-buster: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-bullseye: BASE_TAG=bullseye debian-bullseye: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-bookworm: BASE_TAG=bookworm @@ -327,10 +328,11 @@ setenv = gentoo: IGNORE_MISSING_SYSTEM_PACKAGES=no # # https://hub.docker.com/_/archlinux/ + # 2023-09: libgiac went missing, hence IGNORE_MISSING_SYSTEM_PACKAGES=yes # archlinux: SYSTEM=arch archlinux: BASE_IMAGE=archlinux - archlinux: IGNORE_MISSING_SYSTEM_PACKAGES=no + archlinux: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/r/vbatts/slackware # @@ -348,6 +350,13 @@ setenv = voidlinux: BASE_TAG=20200104 voidlinux: IGNORE_MISSING_SYSTEM_PACKAGES=no # + # https://hub.docker.com/_/alpine/ + # + alpine: SYSTEM=alpine + alpine: BASE_IMAGE=alpine + alpine-edge: BASE_TAG=edge + alpine: IGNORE_MISSING_SYSTEM_PACKAGES=yes + # # https://hub.docker.com/r/continuumio # conda: SYSTEM=conda @@ -528,7 +537,11 @@ setenv = # - python # # Setting "--with-system-python3=yes" explicitly in case we change the configure default - # to "--with-system-python3=force" as originally proposed in #32060 + # to "--with-system-python3=force" as originally proposed in #32060. + # + # For all factors that set "--with-system-python3=force", + # we add "_bootstrap liblzma bzip2 libffi libpng zlib" to EXTRA_SAGE_PACKAGES_5 + # so that the configured python3 can be accepted by configure. PYTHON_MAJOR=3 PYTHON_MINOR=10 python3.9: PYTHON_MINOR=9 @@ -539,16 +552,22 @@ setenv = python3_spkg: CONFIG_CONFIGURE_ARGS_1=--without-system-python3 python3.9,python3.10,python3.11,python3.12: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=python{env:PYTHON_MAJOR}.{env:PYTHON_MINOR} python3.9,python3.10,python3.11,python3.12: EXTRA_SAGE_PACKAGES_5=_python{env:PYTHON_MAJOR}.{env:PYTHON_MINOR} _bootstrap liblzma bzip2 libffi libpng zlib + # As of 2023-9, Xcode 15.0.0, this is Python 3.9.6. macos-python3_xcode: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/usr/bin/python3 - macos-{python3_xcode,nohomebrew}-{python3.8}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 + macos-python3_xcode: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib + macos-{python3_xcode,nohomebrew}-{python3.9}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 # Homebrew keg installs - homebrew-{python3.9,python3.10,python3.11,python3.12}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python={env:HOMEBREW}/opt/python@{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 + homebrew-{python3.9,python3.10,python3.11,python3.12}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python={env:HOMEBREW}/opt/python@{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 # Installers from https://www.python.org/downloads/macos/ (must manually download and install) macos-python3_pythonorg: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/Library/Frameworks/Python.framework/Versions/{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 + macos-python3_pythonorg: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib # https://github.com/pypa/manylinux manylinux-standard: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/opt/python/cp{env:PYTHON_MAJOR}{env:PYTHON_MINOR}-cp{env:PYTHON_MAJOR}{env:PYTHON_MINOR}/bin/python3 manylinux-{python3.9,python3.10,python3.11,python3.12}: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng conda: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=python3 + conda: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib + + {centos-stream,almalinux}-8-python3.9: EXTRA_SYSTEM_PACKAGES=python39 python39-devel # # - toolchain # @@ -699,7 +718,7 @@ commands = docker: bash -c 'for docker_target in {env:DOCKER_TARGETS:with-targets}; do \ docker: BUILD_IMAGE_STEM=sage-$(echo {envname} | sed "s/docker-//;s/-incremental//"); \ docker: BUILD_IMAGE=$DOCKER_PUSH_REPOSITORY$BUILD_IMAGE_STEM-$docker_target; \ - docker: BUILD_TAG=$(git describe --dirty --always); \ + docker: BUILD_TAG={env:DOCKER_TAG:$(git describe --dirty --always)}; \ docker: TAG_ARGS=$(for tag in $BUILD_TAG {env:EXTRA_DOCKER_TAGS:}; do echo --tag $BUILD_IMAGE:$tag; done); \ docker: DOCKER_BUILDKIT={env:DOCKER_BUILDKIT:0} \ docker: docker build . -f {envdir}/Dockerfile \