From 3dabee0cdcca553e4df078a7c16a32b9b4a45fdb Mon Sep 17 00:00:00 2001 From: adrinospy Date: Fri, 9 Feb 2024 22:24:04 +0530 Subject: [PATCH 001/191] added auto labeler based on size of changes --- .github/workflows/pr-labeler.yml | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/pr-labeler.yml diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 00000000000..c146a5c6aa2 --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,38 @@ +# set labels on Pull-Requests based on size of changes +# size is compared form first to last commit in the pull request +name: Size Labeler/Checker +on: + pull_request_target: + types: + - opened + - synchronize +jobs: + label-changes: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Check changes and label + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + CHANGES=$((${{github.event.pull_request.additions}} + ${{github.event.pull_request.deletions}})) + echo "Changed files: $CHANGES" + + THRESHOLD=200 + + PR_NUMBER="${{ github.event.number }}" + API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" + AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" + + if [ "$CHANGES" -le "$THRESHOLD" ]; then + LABEL="tiny" + DELETE_LABEL="huge" + else + LABEL="huge" + DELETE_LABEL="tiny" + fi + + echo "Adding label: $LABEL" + curl -X POST -H "$AUTH_HEADER" -d "{\"labels\":[\"$LABEL\"]}" "$API_URL" + curl -X DELETE -H "$AUTH_HEADER" "$API_URL/$DELETE_LABEL" \ No newline at end of file From 6c4ac86aa73b2f9a06c985957727e437b039d622 Mon Sep 17 00:00:00 2001 From: adrinospy Date: Sun, 11 Feb 2024 16:48:18 +0530 Subject: [PATCH 002/191] added new labels for different thresholds --- .github/workflows/pr-labeler.yml | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index c146a5c6aa2..b4f3c76e3f3 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -17,22 +17,32 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | CHANGES=$((${{github.event.pull_request.additions}} + ${{github.event.pull_request.deletions}})) - echo "Changed files: $CHANGES" + echo "Changes Made: $CHANGES" - THRESHOLD=200 + MINIMAL_THRESHOLD=50 + SMALL_THRESHOLD=100 + MODERATE_THRESHOLD=300 PR_NUMBER="${{ github.event.number }}" API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" - if [ "$CHANGES" -le "$THRESHOLD" ]; then - LABEL="tiny" - DELETE_LABEL="huge" + DELETE_LABELS=("minimal" "small" "moderate" "large") + + if [ "$CHANGES" -le "$MINIMAL_THRESHOLD" ]; then + LABEL="minimal" + elif [ "$CHANGES" -le "$SMALL_THRESHOLD" ]; then + LABEL="small" + elif [ "$CHANGES" -le "$MODERATE_THRESHOLD" ]; then + LABEL="moderate" else - LABEL="huge" - DELETE_LABEL="tiny" + LABEL="large" fi + DELETE_LABELS=("${DELETE_LABELS[@]/$LABEL}") + echo "Adding label: $LABEL" curl -X POST -H "$AUTH_HEADER" -d "{\"labels\":[\"$LABEL\"]}" "$API_URL" - curl -X DELETE -H "$AUTH_HEADER" "$API_URL/$DELETE_LABEL" \ No newline at end of file + for DELETE_LABEL in "${DELETE_LABELS[@]}"; do + curl -X DELETE -H "$AUTH_HEADER" "$API_URL/$DELETE_LABEL" + done From 9a19e596f58f298187fdbcd056f473f95561cc63 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 15:55:36 -0800 Subject: [PATCH 003/191] .github/workflows/macos.yml: Install tox from PyPI, not homebrew --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index bfa4bc58f96..0e8a76ad13d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -77,7 +77,7 @@ jobs: - name: Install test prerequisites run: | - brew install tox + pip install tox - name: Download upstream artifact uses: actions/download-artifact@v3 with: From 296fc20b7c0ebdbf280093dde4838799d53358cc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 16:37:45 -0800 Subject: [PATCH 004/191] .github/workflows/macos.yml: Add tests on M1 runners --- .github/workflows/macos.yml | 17 +++++++++++------ tox.ini | 3 +++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0e8a76ad13d..2cbeb765b20 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -19,17 +19,22 @@ on: type: string # System configuration osversion_xcodeversion_toxenv_tuples: + # As of 2024-02, "runs-on: macos-latest" is macos-12. + # and "runs-on: macos-14" selects the new M1 runners. + # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories description: 'Stringified JSON object' default: >- - [["latest", "", "homebrew-macos-usrlocal-minimal"], - ["latest", "", "homebrew-macos-usrlocal-standard"], - ["11", "xcode_13.2.1", "homebrew-macos-usrlocal-minimal"], + [["11", "xcode_13.2.1", "homebrew-macos-usrlocal-minimal"], + ["12", "", "homebrew-macos-usrlocal-minimal"], ["12", "", "homebrew-macos-usrlocal-standard"], + ["12", "", "homebrew-macos-usrlocal-python3_xcode-standard"], + ["12", "", "homebrew-macos-usrlocal-maximal"], ["13", "xcode_15.0", "homebrew-macos-usrlocal-standard"], - ["latest", "", "homebrew-macos-usrlocal-maximal"], - ["latest", "", "homebrew-macos-usrlocal-python3_xcode-standard"], + ["14", "", "homebrew-macos-opthomebrew-standard"], ["latest", "", "conda-forge-macos-minimal"], - ["latest", "", "conda-forge-macos-standard"]] + ["latest", "", "conda-forge-macos-standard"], + ["14", "", "conda-forge-macos-minimal"], + ["14", "", "conda-forge-macos-standard"]] type: string extra_sage_packages: description: 'Extra Sage packages to install as system packages' diff --git a/tox.ini b/tox.ini index 3673833724c..8f5a381201d 100644 --- a/tox.ini +++ b/tox.ini @@ -512,6 +512,9 @@ setenv = # brew caches downloaded files in ${HOME}/Library/Caches. We share it between different toxenvs. homebrew: SYSTEM=homebrew local-homebrew: HOMEBREW={envdir}/homebrew + # /opt/homebrew is the default install location on arm64 macOS + local-homebrew-opthomebrew: HOMEBREW=/opt/homebrew + # /usr/local is the default install location on x86_64 macOS local-{homebrew-usrlocal,nohomebrew}: HOMEBREW=/usr/local # local-macos-nohomebrew: "best effort" isolation to avoid using a homebrew installation in /usr/local # We use liblzma from the macOS system - which is available but its headers are not (neither is the xz executable). From 76720ad52d0485dae2ef5122fc5776a2e25f2f5c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 16:39:12 -0800 Subject: [PATCH 005/191] .github/workflows/macos.yml: Increase SAGE_NUM_THREADS to 6 --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 2cbeb765b20..4a5dd8d5888 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -134,7 +134,7 @@ jobs: *) export TARGETS_PRE="${{ inputs.targets_pre }}" TARGETS="${{ inputs.targets }} TARGETS_OPTIONAL="${{ inputs.targets_optional }} ;; esac - MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=4 $TARGETS + MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS - name: Prepare logs artifact run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" From deb02bc5e3e787685436e27ba4deebabfc617f2b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 16:46:47 -0800 Subject: [PATCH 006/191] .github/workflows/ci-macos.yml (local-nohomebrew): Increase SAGE_NUM_THREADS to 6 --- .github/workflows/ci-macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 9d2c70cbb78..19ea15aaed6 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -140,7 +140,7 @@ jobs: # We use a high parallelization on purpose in order to catch possible parallelization bugs in the build scripts. # For doctesting, we use a lower parallelization to avoid timeouts. run: | - MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=4 $TARGETS + MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS - name: Prepare logs artifact run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" From 4c3e28181d7f050dfa8b171f32a41961c843f194 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 16:48:33 -0800 Subject: [PATCH 007/191] .github/workflows/ci-macos.yml (local-nohomebrew): Also test on M1 --- .github/workflows/ci-macos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 19ea15aaed6..13c0a83e1a9 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -108,7 +108,7 @@ jobs: fail-fast: false max-parallel: 4 matrix: - os: [ macos-11, macos-12 ] + os: [ macos-11, macos-12, macos-14 ] tox_system_factor: [macos-nobootstrap] tox_packages_factor: [minimal] xcode_version_factor: [default] @@ -129,7 +129,7 @@ jobs: if: contains(matrix.tox_system_factor, 'nobootstrap') - name: Move homebrew away run: | - (cd /usr/local && for a in bin etc include lib opt sbin share; do sudo mv $a $a-moved; done) + (cd $(brew --prefix) && for a in bin etc include lib opt sbin share; do sudo mv $a $a-moved; done) - name: Select Xcode version run: | if [ ${{ matrix.xcode_version_factor }} != default ]; then sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version_factor }}.app; fi From 214c0ebf50a24949196b21ff903f76332b4315fb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 17:02:18 -0800 Subject: [PATCH 008/191] .github/workflows/ci-macos.yml (local-nohomebrew): Add self-destruct sequence --- .github/workflows/ci-macos.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 13c0a83e1a9..bac51f2d592 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -140,6 +140,7 @@ jobs: # We use a high parallelization on purpose in order to catch possible parallelization bugs in the build scripts. # For doctesting, we use a lower parallelization to avoid timeouts. run: | + (sleep 20000; pkill make) & MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS - name: Prepare logs artifact run: | From fd342f6fd442b7a90510a8c2a02a93e4d6a47e45 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 17:24:06 -0800 Subject: [PATCH 009/191] .github/workflows/macos.yml: Add input 'timeout' --- .github/workflows/macos.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 4a5dd8d5888..20f6b29cf41 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -46,6 +46,10 @@ on: free_disk_space: default: false type: boolean + timeout: + description: 'Elapsed time (seconds) at which to kill the build' + default: 20000 + type: number # # For use in upstream CIs. # @@ -134,6 +138,7 @@ jobs: *) export TARGETS_PRE="${{ inputs.targets_pre }}" TARGETS="${{ inputs.targets }} TARGETS_OPTIONAL="${{ inputs.targets_optional }} ;; esac + (sleep ${{ inputs.timeout }}; pkill make) & MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS - name: Prepare logs artifact run: | From 7a921b364f38620483dda1736ccfdf709194ec5b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 21:28:58 -0800 Subject: [PATCH 010/191] .github/workflows/macos.yml: Use pipx to install tox --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 20f6b29cf41..12d50394a39 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -86,7 +86,7 @@ jobs: - name: Install test prerequisites run: | - pip install tox + pipx install tox - name: Download upstream artifact uses: actions/download-artifact@v3 with: From 9694cd9364674fcd2fa7602b44001655d735989e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 22:05:20 -0800 Subject: [PATCH 011/191] .github/workflows/macos.yml: Use tox via 'pipx run' --- .github/workflows/macos.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 12d50394a39..93a8f856994 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -83,10 +83,16 @@ jobs: repository: ${{ inputs.sage_repo }} ref: ${{ inputs.sage_ref }} fetch-depth: 10000 - + - uses: actions/setup-python@v5 + # As of 2024-02-03, the macOS M1 runners do not have preinstalled python or pipx. + # Installing pipx follows the approach of https://github.com/pypa/cibuildwheel/pull/1743 + id: python + with: + python-version: "3.8 - 3.12" + update-environment: false - name: Install test prerequisites run: | - pipx install tox + "${{ steps.python.outputs.python-path }}" -m pip install pipx - name: Download upstream artifact uses: actions/download-artifact@v3 with: @@ -139,7 +145,7 @@ jobs: ;; esac (sleep ${{ inputs.timeout }}; pkill make) & - MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS + MAKE="make -j12" "${{ steps.python.outputs.python-path }}" -m pipx run tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS - name: Prepare logs artifact run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" From dc13076c1b694b9fc9817e6c8dbe87fbfb052f2e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 3 Feb 2024 22:14:15 -0800 Subject: [PATCH 012/191] .github/workflows/ci-macos.yml: Set timeout for stage 1 to 4 hours --- .github/workflows/ci-macos.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index bac51f2d592..1b448c62722 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -34,6 +34,7 @@ jobs: uses: ./.github/workflows/macos.yml with: stage: "1" + timeout: 14400 stage-2: uses: ./.github/workflows/macos.yml From 468ead3b4bfe307c57e33cf8c067d82903d9d8d0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 4 Feb 2024 17:23:21 -0800 Subject: [PATCH 013/191] tox.ini (local-conda): Use 'uname -m' to determine arch for installer --- tox.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 8f5a381201d..a9ff0423488 100644 --- a/tox.ini +++ b/tox.ini @@ -541,10 +541,11 @@ setenv = local-conda: PATH={env:CONDA_PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin local-conda: CONDA_PKGS_DIRS={env:SHARED_CACHE_DIR}/conda_pkgs local-conda: CONDA_OS=$(uname | sed 's/^Darwin/MacOSX/;') + local-conda: CONDA_ARCH=$(uname -m) local-conda-forge: CONDA_INSTALLER_URL_BASE=https://github.com/conda-forge/miniforge/releases/latest/download/ - local-conda-forge: CONDA_INSTALLER_FILE=Miniforge3-{env:CONDA_OS}-x86_64.sh + local-conda-forge: CONDA_INSTALLER_FILE=Miniforge3-{env:CONDA_OS}-{env:CONDA_ARCH}.sh local-conda-miniconda: CONDA_INSTALLER_URL_BASE=https://repo.anaconda.com/miniconda/ - local-conda-miniconda: CONDA_INSTALLER_FILE=Miniconda3-latest-{env:CONDA_OS}-x86_64.sh + local-conda-miniconda: CONDA_INSTALLER_FILE=Miniconda3-latest-{env:CONDA_OS}-{env:CONDA_ARCH}.sh local-conda: SETENV=. {env:CONDA_PREFIX}/bin/activate base local-conda-environment: CONDA_SAGE_ENVIRONMENT=sage-build local-conda-environment: CONDA_SAGE_ENVIRONMENT_DIR= From d6ac96b59d348ce4d868abc73eef64c4f9da80e8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 5 Feb 2024 12:37:30 -0800 Subject: [PATCH 014/191] .github/workflows/macos.yml: Remove failing test of macos-14-minimal --- .github/workflows/macos.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 93a8f856994..7344d839620 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -33,7 +33,6 @@ on: ["14", "", "homebrew-macos-opthomebrew-standard"], ["latest", "", "conda-forge-macos-minimal"], ["latest", "", "conda-forge-macos-standard"], - ["14", "", "conda-forge-macos-minimal"], ["14", "", "conda-forge-macos-standard"]] type: string extra_sage_packages: From db2814d69ffb3cb6e069eb9cba39c319604714f1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 5 Feb 2024 17:28:16 -0800 Subject: [PATCH 015/191] build/pkgs/dsdp/spkg-install.in: Increase verbosity --- build/pkgs/dsdp/spkg-install.in | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pkgs/dsdp/spkg-install.in b/build/pkgs/dsdp/spkg-install.in index 8c29005b9b1..5d0ecadf030 100644 --- a/build/pkgs/dsdp/spkg-install.in +++ b/build/pkgs/dsdp/spkg-install.in @@ -1,6 +1,7 @@ cd src cp ../patches/CMakeLists.txt . sdh_cmake -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_VERBOSE_MAKEFILE=ON \ -DBUILD_SHARED_LIBS=ON \ -DBLA_VENDOR=OpenBLAS \ -DBLAS_LIBRARIES="$(pkg-config --libs blas)" \ From 69738f774afc4662bc271669909af581f6c452e1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 5 Feb 2024 21:07:50 -0800 Subject: [PATCH 016/191] src/bin/sage-env [macOS]: Detect ld-classic when full XCode is in use --- src/bin/sage-env | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bin/sage-env b/src/bin/sage-env index 8fcfda48fb6..074392150b9 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -373,7 +373,12 @@ if [ -n "$SAGE_LOCAL" ]; then # On OS X, test whether "ld-classic" is present in the installed # version of the command-line tools. If so, we add "-ld_classic" # to LD_FLAGS. See #36599. - if [ "$UNAME" = "Darwin" ] && [ -x "$(xcode-select -p)/usr/bin/ld-classic" ] ; then + # When the full XCode is installed and in use, for example after + # "sudo xcode-select -s /Applications/Xcode.app", then "xcode-select -p" + # gives "/Applications/Xcode.app/Contents/Developer", but "ld-classic" + # is not in the subdirectory "usr/bin/" but rather in the subdirectory + # "Toolchains/XcodeDefault.xctoolchain/usr/bin/". See #37237. + if [ "$UNAME" = "Darwin" ] && [ -x "$(xcode-select -p)/usr/bin/ld-classic" -o -x "$(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-classic" ] ; then LDFLAGS="-L$SAGE_LOCAL/lib -Wl,-ld_classic,-rpath,$SAGE_LOCAL/lib $LDFLAGS" else LDFLAGS="-L$SAGE_LOCAL/lib -Wl,-rpath,$SAGE_LOCAL/lib $LDFLAGS" From 4bdc404323cc0b93f11292c69b51c5c252cff22f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 6 Feb 2024 19:12:32 -0800 Subject: [PATCH 017/191] .github/workflows/ci-macos.yml (dist): Do not use tag to bump the version --- .github/workflows/ci-macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 1b448c62722..d1a5d62f425 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -91,7 +91,7 @@ jobs: run: | git config --global user.email "nobody@example.com" git config --global user.name "Sage GitHub CI" - SAGE_ROOT=. SAGE_SRC=./src src/bin/sage-update-version $(git describe --tags) || echo "(ignoring error)" + SAGE_ROOT=. SAGE_SRC=./src src/bin/sage-update-version $(cat src/VERSION.txt).dev0 || echo "(ignoring error)" - name: make dist run: | ./configure --enable-download-from-upstream-url && make dist From d70aae0fd6f0ddf49d751b9ba14142fbba7a3b38 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 6 Feb 2024 20:55:23 -0800 Subject: [PATCH 018/191] src/bin/sage-env: Do not set the ld-classic flag when LD is set --- src/bin/sage-env | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bin/sage-env b/src/bin/sage-env index 074392150b9..61901897bcd 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -127,7 +127,7 @@ fi # The compilers are set in order of priority by # 1) environment variables # 2) compiler installed by sage -# 3) compiler set at configuration time +# 3) compiler set at configuration time if [ -z "$CC" ]; then if [ -n "$SAGE_LOCAL" -a -x "$SAGE_LOCAL/bin/gcc" ]; then CC=gcc @@ -378,7 +378,9 @@ if [ -n "$SAGE_LOCAL" ]; then # gives "/Applications/Xcode.app/Contents/Developer", but "ld-classic" # is not in the subdirectory "usr/bin/" but rather in the subdirectory # "Toolchains/XcodeDefault.xctoolchain/usr/bin/". See #37237. - if [ "$UNAME" = "Darwin" ] && [ -x "$(xcode-select -p)/usr/bin/ld-classic" -o -x "$(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-classic" ] ; then + # However, if LD is set explicitly, as it is within conda on macOS, + # do not not do this. + if [ "$UNAME" = "Darwin" ] && [ -z "$LD" ] && [ -x "$(xcode-select -p)/usr/bin/ld-classic" -o -x "$(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-classic" ] ; then LDFLAGS="-L$SAGE_LOCAL/lib -Wl,-ld_classic,-rpath,$SAGE_LOCAL/lib $LDFLAGS" else LDFLAGS="-L$SAGE_LOCAL/lib -Wl,-rpath,$SAGE_LOCAL/lib $LDFLAGS" From 83348a2235cd7047926a45c33d8d0828195f358a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 18 Feb 2024 19:53:25 -0800 Subject: [PATCH 019/191] build/pkgs/pyscipopt: Update to 4.4.0 --- build/pkgs/pyscipopt/checksums.ini | 6 +++--- build/pkgs/pyscipopt/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pyscipopt/checksums.ini b/build/pkgs/pyscipopt/checksums.ini index a7c0dad6706..022bf3873fd 100644 --- a/build/pkgs/pyscipopt/checksums.ini +++ b/build/pkgs/pyscipopt/checksums.ini @@ -1,5 +1,5 @@ tarball=PySCIPOpt_no_C-VERSION.tar.gz -sha1=cd8a7a5ee2f3d72eb0505b050ab8ffcf3acba409 -md5=b8a846432a7a1e6d5c6dcc547e7a6380 -cksum=710591360 +sha1=5ae7f3d7e9d8b344ee9a4413154ae80a5ee137de +md5=32a4dced7e74a1c290b32ef0da751129 +cksum=2258510906 upstream_url=https://github.com/scipopt/PySCIPOpt/archive/refs/tags/vVERSION.tar.gz diff --git a/build/pkgs/pyscipopt/package-version.txt b/build/pkgs/pyscipopt/package-version.txt index 80895903a15..fdc6698807a 100644 --- a/build/pkgs/pyscipopt/package-version.txt +++ b/build/pkgs/pyscipopt/package-version.txt @@ -1 +1 @@ -4.3.0 +4.4.0 From de6e1649f5255d74709d9a55548eb702ef6030a1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 18 Feb 2024 19:58:18 -0800 Subject: [PATCH 020/191] build/pkgs/pyscipopt: Add https://github.com/scipopt/PySCIPOpt/pull/792 as a patch --- build/pkgs/pyscipopt/patches/792.patch | 1217 ++++++++++++++++++++++++ 1 file changed, 1217 insertions(+) create mode 100644 build/pkgs/pyscipopt/patches/792.patch diff --git a/build/pkgs/pyscipopt/patches/792.patch b/build/pkgs/pyscipopt/patches/792.patch new file mode 100644 index 00000000000..faff6076eb4 --- /dev/null +++ b/build/pkgs/pyscipopt/patches/792.patch @@ -0,0 +1,1217 @@ +From 96acc6be39b6d153cfcfe7b14741956eaf7f5851 Mon Sep 17 00:00:00 2001 +From: Matthias Koeppe +Date: Sun, 18 Feb 2024 19:47:52 -0800 +Subject: [PATCH] src/pyscipopt: Add 'noexcept' to functions that use 'with + gil' + +--- + src/pyscipopt/benders.pxi | 30 ++++++++--------- + src/pyscipopt/benderscut.pxi | 14 ++++---- + src/pyscipopt/branchrule.pxi | 18 +++++----- + src/pyscipopt/conshdlr.pxi | 64 ++++++++++++++++++------------------ + src/pyscipopt/cutsel.pxi | 14 ++++---- + src/pyscipopt/event.pxi | 18 +++++----- + src/pyscipopt/heuristic.pxi | 14 ++++---- + src/pyscipopt/nodesel.pxi | 16 ++++----- + src/pyscipopt/presol.pxi | 14 ++++---- + src/pyscipopt/pricer.pxi | 16 ++++----- + src/pyscipopt/propagator.pxi | 22 ++++++------- + src/pyscipopt/reader.pxi | 8 ++--- + src/pyscipopt/relax.pxi | 14 ++++---- + src/pyscipopt/scip.pxd | 2 +- + src/pyscipopt/scip.pxi | 4 +-- + src/pyscipopt/sepa.pxi | 16 ++++----- + 16 files changed, 142 insertions(+), 142 deletions(-) + +diff --git a/src/pyscipopt/benders.pxi b/src/pyscipopt/benders.pxi +index 3e11db189..66a394d8d 100644 +--- a/src/pyscipopt/benders.pxi ++++ b/src/pyscipopt/benders.pxi +@@ -70,10 +70,10 @@ cdef Variable getPyVar(SCIP_VAR* var): + return vardata + + +-cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_Bool threadsafe) with gil: ++cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_Bool threadsafe) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +@@ -81,56 +81,56 @@ cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) with gil: + Py_DECREF(PyBenders) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersInit (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersInit (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.bendersinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersExit (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersExit (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.bendersexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersInitpre (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersInitpre (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.bendersinitpre() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersExitpre (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersExitpre (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.bendersexitpre() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersInitsol (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersInitsol (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.bendersinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersExitsol (SCIP* scip, SCIP_BENDERS* benders) with gil: ++cdef SCIP_RETCODE PyBendersExitsol (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.bendersexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersCreatesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) with gil: ++cdef SCIP_RETCODE PyBendersCreatesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata + PyBenders.benderscreatesub(probnumber) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint, SCIP_Bool* infeasible, SCIP_Bool* auxviol, SCIP_Bool* skipsolve, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint, SCIP_Bool* infeasible, SCIP_Bool* auxviol, SCIP_Bool* skipsolve, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +@@ -146,7 +146,7 @@ cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_ + result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Bool onlyconvex, SCIP_Real* objective, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Bool onlyconvex, SCIP_Real* objective, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +@@ -159,7 +159,7 @@ cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SC + result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Real* objective, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Real* objective, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +@@ -174,7 +174,7 @@ cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL + + cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, + SCIP_BENDERSENFOTYPE type, int* mergecands, int npriomergecands, int nmergecands, SCIP_Bool checkint, +- SCIP_Bool infeasible, SCIP_Bool* merged) with gil: ++ SCIP_Bool infeasible, SCIP_Bool* merged) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +@@ -190,7 +190,7 @@ cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SO + merged[0] = result_dict.get("merged", False) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) with gil: ++cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +@@ -198,7 +198,7 @@ cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probn + return SCIP_OKAY + + #TODO: Really need to ask about the passing and returning of variables +-cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber) with gil: ++cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber) noexcept with gil: + cdef SCIP_BENDERSDATA* bendersdata + bendersdata = SCIPbendersGetData(benders) + PyBenders = bendersdata +diff --git a/src/pyscipopt/benderscut.pxi b/src/pyscipopt/benderscut.pxi +index 506a6f065..1ce561a06 100644 +--- a/src/pyscipopt/benderscut.pxi ++++ b/src/pyscipopt/benderscut.pxi +@@ -24,10 +24,10 @@ cdef class Benderscut: + print("python error in benderscutexec: this method needs to be implemented") + return {} + +-cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut) with gil: ++cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: ++cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: + cdef SCIP_BENDERSCUTDATA* benderscutdata + benderscutdata = SCIPbenderscutGetData(benderscut) + PyBenderscut = benderscutdata +@@ -35,35 +35,35 @@ cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) wit + Py_DECREF(PyBenderscut) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: ++cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: + cdef SCIP_BENDERSCUTDATA* benderscutdata + benderscutdata = SCIPbenderscutGetData(benderscut) + PyBenderscut = benderscutdata + PyBenderscut.benderscutinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: ++cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: + cdef SCIP_BENDERSCUTDATA* benderscutdata + benderscutdata = SCIPbenderscutGetData(benderscut) + PyBenderscut = benderscutdata + PyBenderscut.benderscutexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: ++cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: + cdef SCIP_BENDERSCUTDATA* benderscutdata + benderscutdata = SCIPbenderscutGetData(benderscut) + PyBenderscut = benderscutdata + PyBenderscut.benderscutinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: ++cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: + cdef SCIP_BENDERSCUTDATA* benderscutdata + benderscutdata = SCIPbenderscutGetData(benderscut) + PyBenderscut = benderscutdata + PyBenderscut.benderscutexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BENDERSCUTDATA* benderscutdata + benderscutdata = SCIPbenderscutGetData(benderscut) + PyBenderscut = benderscutdata +diff --git a/src/pyscipopt/branchrule.pxi b/src/pyscipopt/branchrule.pxi +index 251aa33b1..2d3411d2c 100644 +--- a/src/pyscipopt/branchrule.pxi ++++ b/src/pyscipopt/branchrule.pxi +@@ -39,10 +39,10 @@ cdef class Branchrule: + + + +-cdef SCIP_RETCODE PyBranchruleCopy (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: ++cdef SCIP_RETCODE PyBranchruleCopy (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: ++cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata +@@ -50,35 +50,35 @@ cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) wit + Py_DECREF(PyBranchrule) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleInit (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: ++cdef SCIP_RETCODE PyBranchruleInit (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata + PyBranchrule.branchinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleExit (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: ++cdef SCIP_RETCODE PyBranchruleExit (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata + PyBranchrule.branchexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleInitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: ++cdef SCIP_RETCODE PyBranchruleInitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata + PyBranchrule.branchinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleExitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: ++cdef SCIP_RETCODE PyBranchruleExitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata + PyBranchrule.branchexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata +@@ -86,7 +86,7 @@ cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, S + result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata +@@ -94,7 +94,7 @@ cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, S + result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyBranchruleExecps(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyBranchruleExecps(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_BRANCHRULEDATA* branchruledata + branchruledata = SCIPbranchruleGetData(branchrule) + PyBranchrule = branchruledata +diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi +index 80c60c17c..1299ad35c 100644 +--- a/src/pyscipopt/conshdlr.pxi ++++ b/src/pyscipopt/conshdlr.pxi +@@ -150,16 +150,16 @@ cdef Constraint getPyCons(SCIP_CONS* cons): + + + +-cdef SCIP_RETCODE PyConshdlrCopy (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_Bool* valid) with gil: ++cdef SCIP_RETCODE PyConshdlrCopy (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_Bool* valid) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) with gil: ++cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyConshdlr.consfree() + Py_DECREF(PyConshdlr) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: ++cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -167,7 +167,7 @@ cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c + PyConshdlr.consinit(constraints) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: ++cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -175,7 +175,7 @@ cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c + PyConshdlr.consexit(constraints) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: ++cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -183,7 +183,7 @@ cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + PyConshdlr.consinitpre(constraints) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: ++cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -191,7 +191,7 @@ cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + PyConshdlr.consexitpre(constraints) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: ++cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -199,7 +199,7 @@ cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + PyConshdlr.consinitsol(constraints) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) with gil: ++cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -207,7 +207,7 @@ cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + PyConshdlr.consexitsol(constraints, restart) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_CONSDATA** consdata) with gil: ++cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_CONSDATA** consdata) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + assert consdata[0] == PyCons +@@ -216,7 +216,7 @@ cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + Py_DECREF(PyCons) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* sourcecons, SCIP_CONS** targetcons) with gil: ++cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* sourcecons, SCIP_CONS** targetcons) noexcept with gil: + cdef Constraint PyTargetCons + PyConshdlr = getPyConshdlr(conshdlr) + PySourceCons = getPyCons(sourcecons) +@@ -235,7 +235,7 @@ cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* s + PySourceCons.isRemovable(), PySourceCons.isStickingAtNode())) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) with gil: ++cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -244,7 +244,7 @@ cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + infeasible[0] = result_dict.get("infeasible", infeasible[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -254,7 +254,7 @@ cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, +- SCIP_SOL* sol, SCIP_RESULT* result) with gil: ++ SCIP_SOL* sol, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -265,7 +265,7 @@ cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, +- SCIP_Bool solinfeasible, SCIP_RESULT* result) with gil: ++ SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -274,7 +274,7 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -285,7 +285,7 @@ cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* con + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, +- SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) with gil: ++ SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -295,7 +295,7 @@ cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_SOL* sol, SCIP_Bool checkintegrality, +- SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) with gil: ++ SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -306,7 +306,7 @@ cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsProp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, int nmarkedconss, +- SCIP_PROPTIMING proptiming, SCIP_RESULT* result) with gil: ++ SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -319,7 +319,7 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, + int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, + int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, +- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: ++ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -354,12 +354,12 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsResprop (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR* infervar, int inferinfo, +- SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) with gil: ++ SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyConshdlr.consresprop() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) with gil: ++cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + if cons == NULL: + PyConshdlr.conslock(None, locktype, nlockspos, nlocksneg) +@@ -368,31 +368,31 @@ cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* co + PyConshdlr.conslock(PyCons, locktype, nlockspos, nlocksneg) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsActive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: ++cdef SCIP_RETCODE PyConsActive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + PyConshdlr.consactive(PyCons) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsDeactive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: ++cdef SCIP_RETCODE PyConsDeactive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + PyConshdlr.consdeactive(PyCons) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsEnable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: ++cdef SCIP_RETCODE PyConsEnable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + PyConshdlr.consenable(PyCons) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: ++cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + PyConshdlr.consdisable(PyCons) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: ++cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + cdef constraints = [] + for i in range(nconss): +@@ -400,7 +400,7 @@ cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + PyConshdlr.consdelvars(constraints) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsPrint (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, FILE* file) with gil: ++cdef SCIP_RETCODE PyConsPrint (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, FILE* file) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + # TODO: pass file +@@ -411,7 +411,7 @@ cdef SCIP_RETCODE PyConsCopy (SCIP* scip, SCIP_CONS** cons, const char* name, SC + SCIP_CONS* sourcecons, SCIP_HASHMAP* varmap, SCIP_HASHMAP* consmap, SCIP_Bool initial, + SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, + SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, +- SCIP_Bool isglobal, SCIP_Bool* valid) with gil: ++ SCIP_Bool isglobal, SCIP_Bool* valid) noexcept with gil: + # TODO everything! + PyConshdlr = getPyConshdlr(sourceconshdlr) + PyConshdlr.conscopy() +@@ -421,14 +421,14 @@ cdef SCIP_RETCODE PyConsCopy (SCIP* scip, SCIP_CONS** cons, const char* name, SC + cdef SCIP_RETCODE PyConsParse (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cons, const char* name, const char* str, + SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, + SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, +- SCIP_Bool stickingatnode, SCIP_Bool* success) with gil: ++ SCIP_Bool stickingatnode, SCIP_Bool* success) noexcept with gil: + # TODO everything! + PyConshdlr = getPyConshdlr(conshdlr) + PyConshdlr.consparse() + success[0] = False + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success) with gil: ++cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success) noexcept with gil: + # TODO + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) +@@ -436,7 +436,7 @@ cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* + success[0] = False + return SCIP_OKAY + +-cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success) with gil: ++cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) + PyCons = getPyCons(cons) + result_dict = PyConshdlr.consgetnvars(PyCons) +@@ -445,7 +445,7 @@ cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS + return SCIP_OKAY + + cdef SCIP_RETCODE PyConsGetdivebdchgs (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_DIVESET* diveset, SCIP_SOL* sol, +- SCIP_Bool* success, SCIP_Bool* infeasible) with gil: ++ SCIP_Bool* success, SCIP_Bool* infeasible) noexcept with gil: + # TODO + PyConshdlr = getPyConshdlr(conshdlr) + PyConshdlr.consgetdivebdchgs() +diff --git a/src/pyscipopt/cutsel.pxi b/src/pyscipopt/cutsel.pxi +index e953cb1e9..d259fb28e 100644 +--- a/src/pyscipopt/cutsel.pxi ++++ b/src/pyscipopt/cutsel.pxi +@@ -29,10 +29,10 @@ cdef class Cutsel: + return {} + + +-cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: ++cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: ++cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: + cdef SCIP_CUTSELDATA* cutseldata + cutseldata = SCIPcutselGetData(cutsel) + PyCutsel = cutseldata +@@ -40,7 +40,7 @@ cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: + Py_DECREF(PyCutsel) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: ++cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: + cdef SCIP_CUTSELDATA* cutseldata + cutseldata = SCIPcutselGetData(cutsel) + PyCutsel = cutseldata +@@ -48,21 +48,21 @@ cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: + return SCIP_OKAY + + +-cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: ++cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: + cdef SCIP_CUTSELDATA* cutseldata + cutseldata = SCIPcutselGetData(cutsel) + PyCutsel = cutseldata + PyCutsel.cutselexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: ++cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: + cdef SCIP_CUTSELDATA* cutseldata + cutseldata = SCIPcutselGetData(cutsel) + PyCutsel = cutseldata + PyCutsel.cutselinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: ++cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: + cdef SCIP_CUTSELDATA* cutseldata + cutseldata = SCIPcutselGetData(cutsel) + PyCutsel = cutseldata +@@ -71,7 +71,7 @@ cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: + + cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts, + SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts, +- int* nselectedcuts, SCIP_RESULT* result) with gil: ++ int* nselectedcuts, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_CUTSELDATA* cutseldata + cdef SCIP_ROW* scip_row + cutseldata = SCIPcutselGetData(cutsel) +diff --git a/src/pyscipopt/event.pxi b/src/pyscipopt/event.pxi +index 95c8bc1f4..914e882ed 100644 +--- a/src/pyscipopt/event.pxi ++++ b/src/pyscipopt/event.pxi +@@ -39,48 +39,48 @@ cdef class Eventhdlr: + + + # local helper functions for the interface +-cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + cdef SCIP_EVENTHDLRDATA* eventhdlrdata + eventhdlrdata = SCIPeventhdlrGetData(eventhdlr) + return eventhdlrdata + +-cdef SCIP_RETCODE PyEventCopy (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef SCIP_RETCODE PyEventCopy (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventcopy() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventFree (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef SCIP_RETCODE PyEventFree (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventfree() + Py_DECREF(PyEventhdlr) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventInit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef SCIP_RETCODE PyEventInit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventExit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef SCIP_RETCODE PyEventExit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventInitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef SCIP_RETCODE PyEventInitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventExitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: ++cdef SCIP_RETCODE PyEventExitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventDelete (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA** eventdata) with gil: ++cdef SCIP_RETCODE PyEventDelete (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA** eventdata) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEventhdlr.eventdelete() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyEventExec (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENT* event, SCIP_EVENTDATA* eventdata) with gil: ++cdef SCIP_RETCODE PyEventExec (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENT* event, SCIP_EVENTDATA* eventdata) noexcept with gil: + PyEventhdlr = getPyEventhdlr(eventhdlr) + PyEvent = Event() + PyEvent.event = event +diff --git a/src/pyscipopt/heuristic.pxi b/src/pyscipopt/heuristic.pxi +index 2980a1aee..930315630 100644 +--- a/src/pyscipopt/heuristic.pxi ++++ b/src/pyscipopt/heuristic.pxi +@@ -31,10 +31,10 @@ cdef class Heur: + + + +-cdef SCIP_RETCODE PyHeurCopy (SCIP* scip, SCIP_HEUR* heur) with gil: ++cdef SCIP_RETCODE PyHeurCopy (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) with gil: ++cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: + cdef SCIP_HEURDATA* heurdata + heurdata = SCIPheurGetData(heur) + PyHeur = heurdata +@@ -42,35 +42,35 @@ cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) with gil: + Py_DECREF(PyHeur) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyHeurInit (SCIP* scip, SCIP_HEUR* heur) with gil: ++cdef SCIP_RETCODE PyHeurInit (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: + cdef SCIP_HEURDATA* heurdata + heurdata = SCIPheurGetData(heur) + PyHeur = heurdata + PyHeur.heurinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyHeurExit (SCIP* scip, SCIP_HEUR* heur) with gil: ++cdef SCIP_RETCODE PyHeurExit (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: + cdef SCIP_HEURDATA* heurdata + heurdata = SCIPheurGetData(heur) + PyHeur = heurdata + PyHeur.heurexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyHeurInitsol (SCIP* scip, SCIP_HEUR* heur) with gil: ++cdef SCIP_RETCODE PyHeurInitsol (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: + cdef SCIP_HEURDATA* heurdata + heurdata = SCIPheurGetData(heur) + PyHeur = heurdata + PyHeur.heurinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyHeurExitsol (SCIP* scip, SCIP_HEUR* heur) with gil: ++cdef SCIP_RETCODE PyHeurExitsol (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: + cdef SCIP_HEURDATA* heurdata + heurdata = SCIPheurGetData(heur) + PyHeur = heurdata + PyHeur.heurexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyHeurExec (SCIP* scip, SCIP_HEUR* heur, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyHeurExec (SCIP* scip, SCIP_HEUR* heur, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_HEURDATA* heurdata + heurdata = SCIPheurGetData(heur) + PyHeur = heurdata +diff --git a/src/pyscipopt/nodesel.pxi b/src/pyscipopt/nodesel.pxi +index 4d795bc9d..a3e832f15 100644 +--- a/src/pyscipopt/nodesel.pxi ++++ b/src/pyscipopt/nodesel.pxi +@@ -42,10 +42,10 @@ cdef class Nodesel: + return 0 + + +-cdef SCIP_RETCODE PyNodeselCopy (SCIP* scip, SCIP_NODESEL* nodesel) with gil: ++cdef SCIP_RETCODE PyNodeselCopy (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) with gil: ++cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata +@@ -53,7 +53,7 @@ cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) with gil: + Py_DECREF(PyNodesel) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: ++cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata +@@ -61,28 +61,28 @@ cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: + return SCIP_OKAY + + +-cdef SCIP_RETCODE PyNodeselExit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: ++cdef SCIP_RETCODE PyNodeselExit (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata + PyNodesel.nodeexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyNodeselInitsol (SCIP* scip, SCIP_NODESEL* nodesel) with gil: ++cdef SCIP_RETCODE PyNodeselInitsol (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata + PyNodesel.nodeinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyNodeselExitsol (SCIP* scip, SCIP_NODESEL* nodesel) with gil: ++cdef SCIP_RETCODE PyNodeselExitsol (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata + PyNodesel.nodeexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE** selnode) with gil: ++cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE** selnode) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata +@@ -91,7 +91,7 @@ cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* + selnode[0] = selected_node.scip_node + return SCIP_OKAY + +-cdef int PyNodeselComp (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* node1, SCIP_NODE* node2) with gil: ++cdef int PyNodeselComp (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* node1, SCIP_NODE* node2) noexcept with gil: + cdef SCIP_NODESELDATA* nodeseldata + nodeseldata = SCIPnodeselGetData(nodesel) + PyNodesel = nodeseldata +diff --git a/src/pyscipopt/presol.pxi b/src/pyscipopt/presol.pxi +index d2b9115a5..13bd9a623 100644 +--- a/src/pyscipopt/presol.pxi ++++ b/src/pyscipopt/presol.pxi +@@ -30,10 +30,10 @@ cdef class Presol: + + + +-cdef SCIP_RETCODE PyPresolCopy (SCIP* scip, SCIP_PRESOL* presol) with gil: ++cdef SCIP_RETCODE PyPresolCopy (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) with gil: ++cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: + cdef SCIP_PRESOLDATA* presoldata + presoldata = SCIPpresolGetData(presol) + PyPresol = presoldata +@@ -41,14 +41,14 @@ cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) with gil: + Py_DECREF(PyPresol) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPresolInit (SCIP* scip, SCIP_PRESOL* presol) with gil: ++cdef SCIP_RETCODE PyPresolInit (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: + cdef SCIP_PRESOLDATA* presoldata + presoldata = SCIPpresolGetData(presol) + PyPresol = presoldata + PyPresol.presolinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) with gil: ++cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: + cdef SCIP_PRESOLDATA* presoldata + presoldata = SCIPpresolGetData(presol) + PyPresol = presoldata +@@ -56,14 +56,14 @@ cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) with gil: + return SCIP_OKAY + + +-cdef SCIP_RETCODE PyPresolInitpre (SCIP* scip, SCIP_PRESOL* presol) with gil: ++cdef SCIP_RETCODE PyPresolInitpre (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: + cdef SCIP_PRESOLDATA* presoldata + presoldata = SCIPpresolGetData(presol) + PyPresol = presoldata + PyPresol.presolinitpre() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPresolExitpre (SCIP* scip, SCIP_PRESOL* presol) with gil: ++cdef SCIP_RETCODE PyPresolExitpre (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: + cdef SCIP_PRESOLDATA* presoldata + presoldata = SCIPpresolGetData(presol) + PyPresol = presoldata +@@ -74,7 +74,7 @@ cdef SCIP_RETCODE PyPresolExec (SCIP* scip, SCIP_PRESOL* presol, int nrounds, SC + int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, + int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, + int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, +- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: ++ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_PRESOLDATA* presoldata + presoldata = SCIPpresolGetData(presol) + PyPresol = presoldata +diff --git a/src/pyscipopt/pricer.pxi b/src/pyscipopt/pricer.pxi +index 1368572de..a218b254c 100644 +--- a/src/pyscipopt/pricer.pxi ++++ b/src/pyscipopt/pricer.pxi +@@ -33,10 +33,10 @@ cdef class Pricer: + + + +-cdef SCIP_RETCODE PyPricerCopy (SCIP* scip, SCIP_PRICER* pricer, SCIP_Bool* valid) with gil: ++cdef SCIP_RETCODE PyPricerCopy (SCIP* scip, SCIP_PRICER* pricer, SCIP_Bool* valid) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) with gil: ++cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata +@@ -44,35 +44,35 @@ cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) with gil: + Py_DECREF(PyPricer) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerInit (SCIP* scip, SCIP_PRICER* pricer) with gil: ++cdef SCIP_RETCODE PyPricerInit (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata + PyPricer.pricerinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerExit (SCIP* scip, SCIP_PRICER* pricer) with gil: ++cdef SCIP_RETCODE PyPricerExit (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata + PyPricer.pricerexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerInitsol (SCIP* scip, SCIP_PRICER* pricer) with gil: ++cdef SCIP_RETCODE PyPricerInitsol (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata + PyPricer.pricerinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerExitsol (SCIP* scip, SCIP_PRICER* pricer) with gil: ++cdef SCIP_RETCODE PyPricerExitsol (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata + PyPricer.pricerexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* lowerbound, SCIP_Bool* stopearly, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* lowerbound, SCIP_Bool* stopearly, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata +@@ -82,7 +82,7 @@ cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* l + stopearly[0] = result_dict.get("stopearly", stopearly[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPricerFarkas (SCIP* scip, SCIP_PRICER* pricer, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyPricerFarkas (SCIP* scip, SCIP_PRICER* pricer, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_PRICERDATA* pricerdata + pricerdata = SCIPpricerGetData(pricer) + PyPricer = pricerdata +diff --git a/src/pyscipopt/propagator.pxi b/src/pyscipopt/propagator.pxi +index d792577d9..4508efe78 100644 +--- a/src/pyscipopt/propagator.pxi ++++ b/src/pyscipopt/propagator.pxi +@@ -47,10 +47,10 @@ cdef class Prop: + + + +-cdef SCIP_RETCODE PyPropCopy (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropCopy (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata +@@ -58,42 +58,42 @@ cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) with gil: + Py_DECREF(PyProp) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropInit (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropInit (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata + PyProp.propinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropExit (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropExit (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata + PyProp.propexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropInitpre (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropInitpre (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata + PyProp.propinitpre() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropExitpre (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropExitpre (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata + PyProp.propexitpre() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropInitsol (SCIP* scip, SCIP_PROP* prop) with gil: ++cdef SCIP_RETCODE PyPropInitsol (SCIP* scip, SCIP_PROP* prop) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata + PyProp.propinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropExitsol (SCIP* scip, SCIP_PROP* prop, SCIP_Bool restart) with gil: ++cdef SCIP_RETCODE PyPropExitsol (SCIP* scip, SCIP_PROP* prop, SCIP_Bool restart) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata +@@ -104,7 +104,7 @@ cdef SCIP_RETCODE PyPropPresol (SCIP* scip, SCIP_PROP* prop, int nrounds, SCIP_P + int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, + int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, + int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, +- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: ++ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata +@@ -137,7 +137,7 @@ cdef SCIP_RETCODE PyPropPresol (SCIP* scip, SCIP_PROP* prop, int nrounds, SCIP_P + nchgsides[0] = result_dict["nchgsides"] + return SCIP_OKAY + +-cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_PROPDATA* propdata + propdata = SCIPpropGetData(prop) + PyProp = propdata +@@ -147,7 +147,7 @@ cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING propt + return SCIP_OKAY + + cdef SCIP_RETCODE PyPropResProp (SCIP* scip, SCIP_PROP* prop, SCIP_VAR* infervar, int inferinfo, +- SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) with gil: ++ SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_PROPDATA* propdata + cdef SCIP_VAR* tmp + tmp = infervar +diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi +index df0b3a288..2c45585d6 100644 +--- a/src/pyscipopt/reader.pxi ++++ b/src/pyscipopt/reader.pxi +@@ -18,10 +18,10 @@ cdef class Reader: + return {} + + +-cdef SCIP_RETCODE PyReaderCopy (SCIP* scip, SCIP_READER* reader) with gil: ++cdef SCIP_RETCODE PyReaderCopy (SCIP* scip, SCIP_READER* reader) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) with gil: ++cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) noexcept with gil: + cdef SCIP_READERDATA* readerdata + readerdata = SCIPreaderGetData(reader) + PyReader = readerdata +@@ -29,7 +29,7 @@ cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) with gil: + Py_DECREF(PyReader) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyReaderRead (SCIP* scip, SCIP_READER* reader, const char* filename, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyReaderRead (SCIP* scip, SCIP_READER* reader, const char* filename, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_READERDATA* readerdata + readerdata = SCIPreaderGetData(reader) + PyReader = readerdata +@@ -44,7 +44,7 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, + SCIP_VAR** vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, + SCIP_VAR** fixedvars, int nfixedvars, int startnvars, + SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, +- SCIP_Bool genericnames, SCIP_RESULT* result) with gil: ++ SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_READERDATA* readerdata + readerdata = SCIPreaderGetData(reader) + cdef int fd = fileno(file) +diff --git a/src/pyscipopt/relax.pxi b/src/pyscipopt/relax.pxi +index 2b52c2643..81695e8bb 100644 +--- a/src/pyscipopt/relax.pxi ++++ b/src/pyscipopt/relax.pxi +@@ -30,10 +30,10 @@ cdef class Relax: + return{} + + +-cdef SCIP_RETCODE PyRelaxCopy (SCIP* scip, SCIP_RELAX* relax) with gil: ++cdef SCIP_RETCODE PyRelaxCopy (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) with gil: ++cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: + cdef SCIP_RELAXDATA* relaxdata + relaxdata = SCIPrelaxGetData(relax) + PyRelax = relaxdata +@@ -41,35 +41,35 @@ cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) with gil: + Py_DECREF(PyRelax) + return SCIP_OKAY + +-cdef SCIP_RETCODE PyRelaxInit (SCIP* scip, SCIP_RELAX* relax) with gil: ++cdef SCIP_RETCODE PyRelaxInit (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: + cdef SCIP_RELAXDATA* relaxdata + relaxdata = SCIPrelaxGetData(relax) + PyRelax = relaxdata + PyRelax.relaxinit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyRelaxExit (SCIP* scip, SCIP_RELAX* relax) with gil: ++cdef SCIP_RETCODE PyRelaxExit (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: + cdef SCIP_RELAXDATA* relaxdata + relaxdata = SCIPrelaxGetData(relax) + PyRelax = relaxdata + PyRelax.relaxexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyRelaxInitsol (SCIP* scip, SCIP_RELAX* relax) with gil: ++cdef SCIP_RETCODE PyRelaxInitsol (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: + cdef SCIP_RELAXDATA* relaxdata + relaxdata = SCIPrelaxGetData(relax) + PyRelax = relaxdata + PyRelax.relaxinitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyRelaxExitsol (SCIP* scip, SCIP_RELAX* relax) with gil: ++cdef SCIP_RETCODE PyRelaxExitsol (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: + cdef SCIP_RELAXDATA* relaxdata + relaxdata = SCIPrelaxGetData(relax) + PyRelax = relaxdata + PyRelax.relaxexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_RELAX* relax, SCIP_Real* lowerbound, SCIP_RESULT* result) with gil: ++cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_RELAX* relax, SCIP_Real* lowerbound, SCIP_RESULT* result) noexcept with gil: + cdef SCIP_RELAXDATA* relaxdata + relaxdata = SCIPrelaxGetData(relax) + PyRelax = relaxdata +diff --git a/src/pyscipopt/scip.pxd b/src/pyscipopt/scip.pxd +index 12815dbc4..f35a42486 100644 +--- a/src/pyscipopt/scip.pxd ++++ b/src/pyscipopt/scip.pxd +@@ -501,7 +501,7 @@ cdef extern from "scip/scip.h": + ctypedef union SCIP_DOMCHG: + pass + +- ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) ++ ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept + ctypedef void (*errormessagecallback) (void *data, FILE *file, const char *msg) + ctypedef SCIP_RETCODE (*messagehdlrfree) (SCIP_MESSAGEHDLR *messagehdlr) + +diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi +index 0b2332d88..552197785 100644 +--- a/src/pyscipopt/scip.pxi ++++ b/src/pyscipopt/scip.pxi +@@ -975,10 +975,10 @@ cdef class Constraint: + and self.scip_cons == (other).scip_cons) + + +-cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg): ++cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept: + sys.stdout.write(msg.decode('UTF-8')) + +-cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg): ++cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg) noexcept: + sys.stderr.write(msg.decode('UTF-8')) + + # - remove create(), includeDefaultPlugins(), createProbBasic() methods +diff --git a/src/pyscipopt/sepa.pxi b/src/pyscipopt/sepa.pxi +index 271945db1..94355a7d2 100644 +--- a/src/pyscipopt/sepa.pxi ++++ b/src/pyscipopt/sepa.pxi +@@ -34,10 +34,10 @@ cdef class Sepa: + + + +-cdef SCIP_RETCODE PySepaCopy (SCIP* scip, SCIP_SEPA* sepa) with gil: ++cdef SCIP_RETCODE PySepaCopy (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) with gil: ++cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + PySepa = sepadata +@@ -45,35 +45,35 @@ cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) with gil: + Py_DECREF(PySepa) + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaInit (SCIP* scip, SCIP_SEPA* sepa) with gil: ++cdef SCIP_RETCODE PySepaInit (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + PySepa = sepadata + PySepa.sepainit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaExit (SCIP* scip, SCIP_SEPA* sepa) with gil: ++cdef SCIP_RETCODE PySepaExit (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + PySepa = sepadata + PySepa.sepaexit() + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaInitsol (SCIP* scip, SCIP_SEPA* sepa) with gil: ++cdef SCIP_RETCODE PySepaInitsol (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + PySepa = sepadata + PySepa.sepainitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaExitsol (SCIP* scip, SCIP_SEPA* sepa) with gil: ++cdef SCIP_RETCODE PySepaExitsol (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + PySepa = sepadata + PySepa.sepaexitsol() + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result, unsigned int allowlocal, int depth) with gil: ++cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result, unsigned int allowlocal, int depth) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + PySepa = sepadata +@@ -81,7 +81,7 @@ cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result + result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY + +-cdef SCIP_RETCODE PySepaExecsol (SCIP* scip, SCIP_SEPA* sepa, SCIP_SOL* sol, SCIP_RESULT* result, unsigned int allowlocal, int depth) with gil: ++cdef SCIP_RETCODE PySepaExecsol (SCIP* scip, SCIP_SEPA* sepa, SCIP_SOL* sol, SCIP_RESULT* result, unsigned int allowlocal, int depth) noexcept with gil: + cdef SCIP_SEPADATA* sepadata + sepadata = SCIPsepaGetData(sepa) + solution = Solution.create(scip, sol) From 22fdd8cfe8a7d7b84e686a522acb7eba6bdc324a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 18 Feb 2024 23:11:11 -0800 Subject: [PATCH 021/191] build/pkgs/pyscipopt: Fix upstream_url --- build/pkgs/pyscipopt/SPKG.rst | 4 ---- build/pkgs/pyscipopt/checksums.ini | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/build/pkgs/pyscipopt/SPKG.rst b/build/pkgs/pyscipopt/SPKG.rst index 28d6ee75aaa..555866ee6bd 100644 --- a/build/pkgs/pyscipopt/SPKG.rst +++ b/build/pkgs/pyscipopt/SPKG.rst @@ -16,7 +16,3 @@ Upstream Contact https://pypi.org/project/PySCIPOpt/ -Dependencies ------------- - -scipoptsuite diff --git a/build/pkgs/pyscipopt/checksums.ini b/build/pkgs/pyscipopt/checksums.ini index 022bf3873fd..5b537d4c57d 100644 --- a/build/pkgs/pyscipopt/checksums.ini +++ b/build/pkgs/pyscipopt/checksums.ini @@ -1,5 +1,5 @@ -tarball=PySCIPOpt_no_C-VERSION.tar.gz +tarball=PySCIPOpt-VERSION.tar.gz sha1=5ae7f3d7e9d8b344ee9a4413154ae80a5ee137de md5=32a4dced7e74a1c290b32ef0da751129 cksum=2258510906 -upstream_url=https://github.com/scipopt/PySCIPOpt/archive/refs/tags/vVERSION.tar.gz +upstream_url=https://pypi.io/packages/source/p/pyscipopt/PySCIPOpt-VERSION.tar.gz From c6a82b717ab34245a0011367c8e2ce5acd25deb8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 19 Feb 2024 22:09:03 -0800 Subject: [PATCH 022/191] .github/workflows/macos.yml: Pass inputs.extra_sage_packages to tox --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 7344d839620..ccba31a3dcc 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -144,7 +144,7 @@ jobs: ;; esac (sleep ${{ inputs.timeout }}; pkill make) & - MAKE="make -j12" "${{ steps.python.outputs.python-path }}" -m pipx run tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS + MAKE="make -j12" EXTRA_SAGE_PACKAGES="${{ inputs.extra_sage_packages }}" "${{ steps.python.outputs.python-path }}" -m pipx run tox -e $TOX_ENV -- SAGE_NUM_THREADS=6 $TARGETS - name: Prepare logs artifact run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" From 40f4d9b27a1abe6fff3fd316f7c65d90491a670f Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 23 Feb 2024 15:06:26 +0000 Subject: [PATCH 023/191] Add fast pow for NTL polynomials over extensions --- .../rings/polynomial/polynomial_zz_pex.pxd | 3 +- .../rings/polynomial/polynomial_zz_pex.pyx | 92 ++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pxd b/src/sage/rings/polynomial/polynomial_zz_pex.pxd index ca60398ef68..809bb45300f 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pxd +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pxd @@ -1,5 +1,6 @@ from sage.libs.ntl.ZZ_pEX cimport ZZ_pEX_c from sage.libs.ntl.ntl_ZZ_pEContext cimport ZZ_pEContext_ptrs +from sage.rings.integer cimport Integer ctypedef ZZ_pEX_c celement ctypedef ZZ_pEContext_ptrs *cparent @@ -7,5 +8,5 @@ ctypedef ZZ_pEContext_ptrs *cparent include "polynomial_template_header.pxi" cdef class Polynomial_ZZ_pEX(Polynomial_template): - pass + cdef _powmod_bigexp(Polynomial_ZZ_pEX self, Integer exp, Polynomial_ZZ_pEX modulus) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 295bc4fccbe..b2a62635f77 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -20,7 +20,10 @@ from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class from sage.libs.ntl.ZZ_pE cimport ZZ_pE_to_ZZ_pX from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff from sage.libs.ntl.ZZ_p cimport ZZ_p_rep -from sage.libs.ntl.convert cimport ZZ_to_mpz +from sage.libs.ntl.convert cimport ZZ_to_mpz, mpz_to_ZZ + +from sage.structure.element import have_same_parent +from sage.structure.element import canonical_coercion # We need to define this stuff before including the templating stuff # to make sure the function get_cparent is found since it is used in @@ -616,3 +619,90 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): ZZ_pEX_InvTrunc(r.x, self.x, prec) sig_off() return r + + def __pow__(self, exp, modulus): + r""" + Exponentiation of polynomials over extension fields. + + EXAMPLES:: + + sage: K. = GF(101^2, 'a', modulus=[1,1,1]) + sage: R. = PolynomialRing(K, implementation="NTL") + sage: pow(x, 100) + x^100 + sage: pow(x + 3, 5) + x^5 + 15*x^4 + 90*x^3 + 68*x^2 + x + 41 + + If modulus is not None, performs modular exponentiation:: + + sage: K. = GF(101^2, 'a', modulus=[1,1,1]) + sage: R. = PolynomialRing(K, implementation="NTL") + sage: pow(x, 100, x^2 + x + a) + (19*a + 64)*x + 30*a + 2 + sage: pow(x, 100 * 101**200, x^2 + x + a) + (19*a + 64)*x + 30*a + 2 + + The modulus can have smaller degree than ``self``:: + + sage: K. = GF(101^2, 'a', modulus=[1,1,1]) + sage: R. = PolynomialRing(K, implementation="NTL") + sage: pow(x^4, 25, x^2 + x + a) + (19*a + 64)*x + 30*a + 2 + + TESTS:: + + Canonical coercion should apply:: + + sage: xx = GF(101)["x"].gen() + sage: pow(x+1, 25, 2) + 0 + sage: pow(x + a, 101**2, xx^3 + xx + 1) + 4*x^2 + 44*x + a + 70 + sage: pow(x + a, int(101**2), xx^3 + xx + 1) + 4*x^2 + 44*x + a + 70 + sage: xx = polygen(GF(97)) + sage: _ = pow(x + a, 101**2, xx^3 + xx + 1) + Traceback (most recent call last): + ... + TypeError: no common canonical parent for objects with parents: ... + """ + exp = Integer(exp) + if modulus is not None: + # Similar to coerce_binop + if not have_same_parent(self, modulus): + a, m = canonical_coercion(self, modulus) + if a is not self: + return pow(a, exp, m) + modulus = m + self = self % modulus + if exp > 0 and exp.bit_length() >= 32: + return (self)._powmod_bigexp(Integer(exp), modulus) + return Polynomial_template.__pow__(self, exp, modulus) + + cdef _powmod_bigexp(Polynomial_ZZ_pEX self, Integer exp, Polynomial_ZZ_pEX modulus): + """ + Modular exponentiation for large exponents. + """ + self._parent._modulus.restore() + cdef Polynomial_ZZ_pEX r + cdef ZZ_c e_ZZ + cdef ZZ_pEX_c y + cdef ZZ_pEX_Modulus_c mod + + mpz_to_ZZ(&e_ZZ, exp.value) + r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent + ZZ_pEX_Modulus_build(mod, modulus.x) + + sig_on() + if ZZ_pEX_IsX(self.x): + ZZ_pEX_PowerXMod_ZZ_pre(r.x, e_ZZ, mod) + elif ZZ_pEX_deg(self.x) < ZZ_pEX_deg(modulus.x): + ZZ_pEX_PowerMod_ZZ_pre(r.x, self.x, e_ZZ, mod) + else: + ZZ_pEX_rem_pre(y, self.x, mod) + ZZ_pEX_PowerMod_ZZ_pre(r.x, y, e_ZZ, mod) + sig_off() + return r From 9331b5fcb0ec68c7b4ab5bf86e077b9771daaf07 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 23 Feb 2024 15:07:49 +0000 Subject: [PATCH 024/191] Fix linting --- src/sage/rings/polynomial/polynomial_zz_pex.pxd | 1 - src/sage/rings/polynomial/polynomial_zz_pex.pyx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pxd b/src/sage/rings/polynomial/polynomial_zz_pex.pxd index 809bb45300f..b3cd775542e 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pxd +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pxd @@ -9,4 +9,3 @@ include "polynomial_template_header.pxi" cdef class Polynomial_ZZ_pEX(Polynomial_template): cdef _powmod_bigexp(Polynomial_ZZ_pEX self, Integer exp, Polynomial_ZZ_pEX modulus) - diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index b2a62635f77..2b1b4bc9395 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -678,7 +678,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if exp > 0 and exp.bit_length() >= 32: return (self)._powmod_bigexp(Integer(exp), modulus) return Polynomial_template.__pow__(self, exp, modulus) - + cdef _powmod_bigexp(Polynomial_ZZ_pEX self, Integer exp, Polynomial_ZZ_pEX modulus): """ Modular exponentiation for large exponents. From 7eca602c942b18b79e082fe15d83175346551716 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 23 Feb 2024 15:26:45 +0000 Subject: [PATCH 025/191] update docstring --- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 2b1b4bc9395..97b99883ec5 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -22,8 +22,7 @@ from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff from sage.libs.ntl.ZZ_p cimport ZZ_p_rep from sage.libs.ntl.convert cimport ZZ_to_mpz, mpz_to_ZZ -from sage.structure.element import have_same_parent -from sage.structure.element import canonical_coercion +from sage.structure.element import have_same_parent, canonical_coercion # We need to define this stuff before including the templating stuff # to make sure the function get_cparent is found since it is used in @@ -624,6 +623,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): r""" Exponentiation of polynomials over extension fields. + If ``modulus`` is not ``None``, the exponentiation is performed + modulo the polynomial ``modulus``. + EXAMPLES:: sage: K. = GF(101^2, 'a', modulus=[1,1,1]) From 2750aeebaebcc8be9cb4d4e18928a84354844bee Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 23 Feb 2024 15:29:47 +0000 Subject: [PATCH 026/191] add fast modular exponentiation for polynomial rings over Z/NZ --- src/sage/libs/ntl/ntl_ZZ_pX.pxd | 3 + src/sage/libs/ntl/ntl_ZZ_pX.pyx | 60 +++++++++++- .../polynomial/polynomial_modn_dense_ntl.pyx | 93 ++++++++++++++++--- 3 files changed, 142 insertions(+), 14 deletions(-) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pxd b/src/sage/libs/ntl/ntl_ZZ_pX.pxd index 38792bca2d1..c7132de6eff 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pxd +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pxd @@ -1,5 +1,6 @@ from sage.libs.ntl.ZZ_pX cimport * from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class +from sage.rings.integer cimport Integer cdef class ntl_ZZ_pX(): cdef ZZ_pX_c x @@ -7,6 +8,8 @@ cdef class ntl_ZZ_pX(): cdef void setitem_from_int(ntl_ZZ_pX self, long i, int value) noexcept cdef int getitem_as_int(ntl_ZZ_pX self, long i) noexcept cdef ntl_ZZ_pX _new(self) noexcept + cpdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, exp) + cpdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer exp, ntl_ZZ_pX modulus) cdef class ntl_ZZ_pX_Modulus(): cdef ZZ_pX_Modulus_c x diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index 3422239aaac..4a5ef4eee79 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -29,6 +29,7 @@ include 'decl.pxi' from cpython.object cimport Py_EQ, Py_NE from sage.cpython.string cimport char_to_str from sage.rings.integer cimport Integer +from sage.libs.ntl.convert cimport PyLong_to_ZZ from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class @@ -489,23 +490,78 @@ cdef class ntl_ZZ_pX(): sig_off() return r - def __pow__(ntl_ZZ_pX self, long n, ignored): + def __pow__(self, n, modulus): """ Return the n-th nonnegative power of self. + If ``modulus`` is not ``None``, the exponentiation is performed + modulo the polynomial ``modulus``. + EXAMPLES:: sage: c = ntl.ZZ_pContext(20) sage: g = ntl.ZZ_pX([-1,0,1],c) sage: g**10 [1 0 10 0 5 0 0 0 10 0 8 0 10 0 0 0 5 0 10 0 1] + + sage: x = ntl.ZZ_pX([0,1],c) + sage: x**10 + [0 0 0 0 0 0 0 0 0 0 1] + + Modular exponentiation:: + + sage: c = ntl.ZZ_pContext(20) + sage: f = ntl.ZZ_pX([1,0,1],c) + sage: m = ntl.ZZ_pX([1,0,0,0,0,1],c) + sage: pow(f, 123**45, m) + [1 19 3 0 3] + + Modular exponentiation of ``x``:: + + sage: f = ntl.ZZ_pX([0,1],c) + sage: f.is_x() + True + sage: m = ntl.ZZ_pX([1,1,0,0,0,1],c) + sage: pow(f, 123**45, m) + [15 5 5 11] + """ + if modulus is None: + return self._pow(n) + else: + return self._powmod(Integer(n), modulus) + + cpdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, n): + """ + Compute the n-th power of self. """ if n < 0: raise NotImplementedError + cdef long ln = n #self.c.restore_c() # restored in _new() cdef ntl_ZZ_pX r = self._new() + if self.is_x() and n >= 1: + ZZ_pX_LeftShift(r.x, self.x, n-1) + else: + sig_on() + ZZ_pX_power(r.x, self.x, ln) + sig_off() + return r + + cpdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer n, ntl_ZZ_pX modulus): + r""" + Compute the n-th power of self modulo a polynomial. + """ + cdef ntl_ZZ_pX r = self._new() + cdef ZZ_c n_ZZ + cdef ZZ_pX_Modulus_c mod + is_x = self.is_x() sig_on() - ZZ_pX_power(r.x, self.x, n) + mpz_to_ZZ(&n_ZZ, (n).value) + ZZ_pX_Modulus_build(mod, modulus.x) + if is_x: + ZZ_pX_PowerXMod_pre(r.x, n_ZZ, mod) + else: + ZZ_pX_PowerMod_pre(r.x, self.x, n_ZZ, mod) sig_off() return r diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 65bd584d9ea..a646e3324e4 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -49,7 +49,7 @@ from sage.rings.infinity import infinity from sage.interfaces.singular import singular as singular_default -from sage.structure.element import coerce_binop +from sage.structure.element import canonical_coercion, coerce_binop, have_same_parent from sage.libs.ntl.types cimport NTL_SP_BOUND from sage.libs.ntl.ZZ_p cimport * @@ -211,15 +211,6 @@ cdef class Polynomial_dense_mod_n(Polynomial): raise IndexError("n must be >= 0") self._poly[n] = int(value) - def _pow(self, n): - n = int(n) - - if self.degree() <= 0: - return self.parent()(self[0]**n) - if n < 0: - return (~self)**(-n) - return self.parent()(self._poly**n, construct=True) - cpdef _add_(self, right) noexcept: return self.parent()(self._poly + (right)._poly, construct=True) @@ -845,7 +836,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): return r def __pow__(Polynomial_dense_modn_ntl_zz self, ee, modulus): - """ + r""" TESTS:: sage: R. = PolynomialRing(Integers(100), implementation='NTL') @@ -871,7 +862,6 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): sage: R. = PolynomialRing(Integers(100), implementation='NTL') sage: type(R(0)^0) == type(R(0)) True - """ cdef bint recip = 0, do_sig cdef long e = ee @@ -1793,6 +1783,85 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): A dense polynomial over the integers modulo `p`, where `p` is prime. """ + def __pow__(self, n, modulus): + """ + Exponentiation of polynomials over extension fields. + + If ``modulus`` is not ``None``, the exponentiation is performed + modulo the polynomial ``modulus``. + + EXAMPLES:: + + sage: R. = PolynomialRing(Integers(101), implementation='NTL') + sage: (x-1)^5 + x^5 + 96*x^4 + 10*x^3 + 91*x^2 + 5*x + 100 + sage: pow(x-1, 15, x^3+x+1) + 55*x^2 + 6*x + 46 + + TESTS:: + + Negative powers will not work:: + + sage: R. = PolynomialRing(Integers(101), implementation='NTL') + sage: (x-1)^(-5) + Traceback (most recent call last): + ... + NotImplementedError: Fraction fields not implemented for this type. + + We define ``0^0`` to be unity, :trac:`13895`:: + + sage: R. = PolynomialRing(Integers(101), implementation='NTL') + sage: R(0)^0 + 1 + + The value returned from ``0^0`` should belong to our ring:: + + sage: R. = PolynomialRing(Integers(101), implementation='NTL') + sage: type(R(0)^0) == type(R(0)) + True + + The modulus can have smaller degree than ``self``:: + + sage: R. = PolynomialRing(GF(101), implementation="NTL") + sage: pow(x^4 + 1, 100, x^2 + x + 1) + 100*x + 100 + + Canonical coercion should apply:: + + sage: R. = PolynomialRing(GF(101), implementation="FLINT") + sage: x_ZZ = ZZ["x"].gen() + sage: pow(x+1, 100, 2) + 0 + sage: pow(x+1, 100, x_ZZ^2 + x_ZZ + 1) + 100*x + 100 + sage: pow(x+1, int(100), x_ZZ^2 + x_ZZ + 1) + 100*x + 100 + sage: xx = polygen(GF(97)) + sage: _ = pow(x + 1, 3, xx^3 + xx + 1) + Traceback (most recent call last): + ... + TypeError: no canonical coercion from Univariate Polynomial Ring in x over Finite Field of size 97 to Univariate Polynomial Ring in x over Finite Field of size 101 + """ + n = Integer(n) + parent = (self)._parent + + if modulus is not None: + # Similar to coerce_binop + if not have_same_parent(self, modulus): + a, m = canonical_coercion(self, modulus) + if a is not self: + return pow(a, n, m) + modulus = m + self = self % modulus + return parent(pow(self.ntl_ZZ_pX(), n, modulus.ntl_ZZ_pX()), construct=True) + else: + if n < 0: + return ~(self**(-n)) + elif self.degree() <= 0: + return parent(self[0]**n) + else: + return parent(self.ntl_ZZ_pX()**n, construct=True) + @coerce_binop def gcd(self, right): """ From 68c1f10a6b58ac787b1bb2b61e08c189c9cc4410 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 23 Feb 2024 15:45:25 +0000 Subject: [PATCH 027/191] fast pow mod for flint Z/NZ --- .../polynomial/polynomial_modn_dense_ntl.pyx | 4 +- .../polynomial/polynomial_zmod_flint.pxd | 2 + .../polynomial/polynomial_zmod_flint.pyx | 92 ++++++++++++++++++- .../rings/polynomial/polynomial_zz_pex.pyx | 2 +- 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index a646e3324e4..6ace99bbea7 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -1785,7 +1785,7 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): def __pow__(self, n, modulus): """ - Exponentiation of polynomials over extension fields. + Exponentiation of polynomials. If ``modulus`` is not ``None``, the exponentiation is performed modulo the polynomial ``modulus``. @@ -1840,7 +1840,7 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): sage: _ = pow(x + 1, 3, xx^3 + xx + 1) Traceback (most recent call last): ... - TypeError: no canonical coercion from Univariate Polynomial Ring in x over Finite Field of size 97 to Univariate Polynomial Ring in x over Finite Field of size 101 + TypeError: no common canonical parent for objects with parents: ... """ n = Integer(n) parent = (self)._parent diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pxd b/src/sage/rings/polynomial/polynomial_zmod_flint.pxd index 887f46ea6eb..6ef9cf7f4d7 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pxd +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pxd @@ -1,5 +1,6 @@ from sage.libs.flint.types cimport nmod_poly_t, nmod_poly_struct, fmpz_poly_t from sage.structure.parent cimport Parent +from sage.rings.integer cimport Integer from sage.rings.polynomial.polynomial_integer_dense_flint cimport Polynomial_integer_dense_flint ctypedef nmod_poly_struct celement @@ -14,4 +15,5 @@ cdef class Polynomial_zmod_flint(Polynomial_template): cdef int _set_list(self, x) except -1 cdef int _set_fmpz_poly(self, fmpz_poly_t) except -1 cpdef Polynomial _mul_trunc_opposite(self, Polynomial_zmod_flint other, length) noexcept + cpdef Polynomial _powmod_bigexp(self, Integer exp, Polynomial_zmod_flint modulus) cpdef rational_reconstruction(self, m, n_deg=?, d_deg=?) noexcept diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 1df2497b4ad..4bce8a5de75 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -41,7 +41,7 @@ AUTHORS: from sage.libs.ntl.ntl_lzz_pX import ntl_zz_pX from sage.structure.element cimport parent -from sage.structure.element import coerce_binop +from sage.structure.element import coerce_binop, canonical_coercion, have_same_parent from sage.rings.polynomial.polynomial_integer_dense_flint cimport Polynomial_integer_dense_flint from sage.misc.superseded import deprecated_function_alias @@ -62,6 +62,7 @@ include "sage/libs/flint/nmod_poly_linkage.pxi" # and then the interface include "polynomial_template.pxi" +from sage.libs.flint.fmpz cimport * from sage.libs.flint.fmpz_poly cimport * from sage.libs.flint.nmod_poly cimport * @@ -482,6 +483,95 @@ cdef class Polynomial_zmod_flint(Polynomial_template): _mul_short_opposite = _mul_trunc_opposite + def __pow__(self, exp, modulus): + r""" + Exponentiation of polynomials. + + If ``modulus`` is not ``None``, the exponentiation is performed + modulo the polynomial ``modulus``. + + EXAMPLES:: + + sage: R. = GF(5)[] + sage: pow(x+1, 5**50, x^5 + 4*x + 3) + x + 1 + sage: pow(x+1, 5**64, x^5 + 4*x + 3) + x + 4 + sage: pow(x, 5**64, x^5 + 4*x + 3) + x + 3 + + The modulus can have smaller degree than ``self``:: + + sage: R. = PolynomialRing(GF(5), implementation="FLINT") + sage: pow(x^4, 6, x^2 + x + 1) + 1 + + TESTS:: + + Canonical coercion applies:: + + sage: R. = PolynomialRing(GF(5), implementation="FLINT") + sage: x_ZZ = ZZ["x"].gen() + sage: pow(x+1, 25, 2) + 0 + sage: pow(x+1, 4, x_ZZ^2 + x_ZZ + 1) + 4*x + 4 + sage: pow(x+1, int(4), x_ZZ^2 + x_ZZ + 1) + 4*x + 4 + sage: xx = polygen(GF(97)) + sage: pow(x + 1, 3, xx^3 + xx + 1) + Traceback (most recent call last): + ... + TypeError: no common canonical parent for objects with parents: ... + """ + exp = Integer(exp) + if modulus is not None: + # Similar to coerce_binop + if not have_same_parent(self, modulus): + a, m = canonical_coercion(self, modulus) + if a is not self: + return pow(a, exp, m) + modulus = m + self = self % modulus + if exp > 0 and exp.bit_length() >= 32: + return self._powmod_bigexp(exp, modulus) + + return Polynomial_template.__pow__(self, exp, modulus) + + cpdef Polynomial _powmod_bigexp(Polynomial_zmod_flint self, Integer exp, Polynomial_zmod_flint m): + r""" + Modular exponentiation with a large integer exponent. + + It is assumed that checks and coercions have been already performed on arguments. + + TESTS:: + + sage: R. = PolynomialRing(GF(5), implementation="FLINT") + sage: f = x+1 + sage: f._powmod_bigexp(5**50, x^5 + 4*x + 3) + x + 1 + sage: x._powmod_bigexp(5**64, x^5 + 4*x + 3) + x + 3 + """ + cdef Polynomial_zmod_flint ans = self._new() + # Preconditioning is useful for large exponents: the inverse + # power series helps computing fast quotients. + cdef Polynomial_zmod_flint minv = self._new() + cdef fmpz_t exp_fmpz + + fmpz_init(exp_fmpz) + fmpz_set_mpz(exp_fmpz, (exp).value) + nmod_poly_reverse(&minv.x, &m.x, nmod_poly_length(&m.x)) + nmod_poly_inv_series(&minv.x, &minv.x, nmod_poly_length(&m.x)) + + if self == self._parent.gen(): + nmod_poly_powmod_x_fmpz_preinv(&ans.x, exp_fmpz, &m.x, &minv.x) + else: + nmod_poly_powmod_fmpz_binexp_preinv(&ans.x, &self.x, exp_fmpz, &m.x, &minv.x) + + fmpz_clear(exp_fmpz) + return ans + cpdef Polynomial _power_trunc(self, unsigned long n, long prec) noexcept: r""" TESTS:: diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 97b99883ec5..ad2f3376f84 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -621,7 +621,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): def __pow__(self, exp, modulus): r""" - Exponentiation of polynomials over extension fields. + Exponentiation of polynomials. If ``modulus`` is not ``None``, the exponentiation is performed modulo the polynomial ``modulus``. From 84e5dc6e7960f53079f4b623293876e771072fe9 Mon Sep 17 00:00:00 2001 From: Giacomo Pope <44242839+GiacomoPope@users.noreply.github.com> Date: Sat, 24 Feb 2024 14:28:04 +0000 Subject: [PATCH 028/191] Apply suggestions from code review Co-authored-by: Travis Scrimshaw --- src/sage/libs/ntl/ntl_ZZ_pX.pyx | 8 ++++---- src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx | 6 +++--- src/sage/rings/polynomial/polynomial_zmod_flint.pyx | 4 ++-- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index 4a5ef4eee79..244478307f6 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -530,9 +530,9 @@ cdef class ntl_ZZ_pX(): else: return self._powmod(Integer(n), modulus) - cpdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, n): + cdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, long n): """ - Compute the n-th power of self. + Compute the ``n``-th power of `self``. """ if n < 0: raise NotImplementedError @@ -547,9 +547,9 @@ cdef class ntl_ZZ_pX(): sig_off() return r - cpdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer n, ntl_ZZ_pX modulus): + cdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer n, ntl_ZZ_pX modulus): r""" - Compute the n-th power of self modulo a polynomial. + Compute the ``n``-th power of ``self`` modulo a polynomial. """ cdef ntl_ZZ_pX r = self._new() cdef ZZ_c n_ZZ diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 6ace99bbea7..0b6bf4a443b 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -1785,7 +1785,7 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): def __pow__(self, n, modulus): """ - Exponentiation of polynomials. + Exponentiation of ``self``. If ``modulus`` is not ``None``, the exponentiation is performed modulo the polynomial ``modulus``. @@ -1798,7 +1798,7 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): sage: pow(x-1, 15, x^3+x+1) 55*x^2 + 6*x + 46 - TESTS:: + TESTS: Negative powers will not work:: @@ -1808,7 +1808,7 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): ... NotImplementedError: Fraction fields not implemented for this type. - We define ``0^0`` to be unity, :trac:`13895`:: + We define ``0^0`` to be unity, :issue:`13895`:: sage: R. = PolynomialRing(Integers(101), implementation='NTL') sage: R(0)^0 diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 4bce8a5de75..775258190cb 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -485,7 +485,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): def __pow__(self, exp, modulus): r""" - Exponentiation of polynomials. + Exponentiation of ``self``. If ``modulus`` is not ``None``, the exponentiation is performed modulo the polynomial ``modulus``. @@ -506,7 +506,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): sage: pow(x^4, 6, x^2 + x + 1) 1 - TESTS:: + TESTS: Canonical coercion applies:: diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index ad2f3376f84..e033d834200 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -635,7 +635,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: pow(x + 3, 5) x^5 + 15*x^4 + 90*x^3 + 68*x^2 + x + 41 - If modulus is not None, performs modular exponentiation:: + If modulus is not ``None``, performs modular exponentiation:: sage: K. = GF(101^2, 'a', modulus=[1,1,1]) sage: R. = PolynomialRing(K, implementation="NTL") @@ -651,7 +651,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: pow(x^4, 25, x^2 + x + a) (19*a + 64)*x + 30*a + 2 - TESTS:: + TESTS: Canonical coercion should apply:: From 10d57ed3daf2411a770559179f77e08b96ad0d3d Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Sat, 24 Feb 2024 14:39:24 +0000 Subject: [PATCH 029/191] Ensure cython compiles after reviewer suggestion --- src/sage/libs/ntl/ntl_ZZ_pX.pxd | 4 ++-- src/sage/rings/polynomial/polynomial_zmod_flint.pxd | 2 +- src/sage/rings/polynomial/polynomial_zmod_flint.pyx | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pxd b/src/sage/libs/ntl/ntl_ZZ_pX.pxd index c7132de6eff..829eab2a769 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pxd +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pxd @@ -8,8 +8,8 @@ cdef class ntl_ZZ_pX(): cdef void setitem_from_int(ntl_ZZ_pX self, long i, int value) noexcept cdef int getitem_as_int(ntl_ZZ_pX self, long i) noexcept cdef ntl_ZZ_pX _new(self) noexcept - cpdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, exp) - cpdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer exp, ntl_ZZ_pX modulus) + cdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, long exp) + cdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer exp, ntl_ZZ_pX modulus) cdef class ntl_ZZ_pX_Modulus(): cdef ZZ_pX_Modulus_c x diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pxd b/src/sage/rings/polynomial/polynomial_zmod_flint.pxd index 6ef9cf7f4d7..189bddad656 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pxd +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pxd @@ -15,5 +15,5 @@ cdef class Polynomial_zmod_flint(Polynomial_template): cdef int _set_list(self, x) except -1 cdef int _set_fmpz_poly(self, fmpz_poly_t) except -1 cpdef Polynomial _mul_trunc_opposite(self, Polynomial_zmod_flint other, length) noexcept - cpdef Polynomial _powmod_bigexp(self, Integer exp, Polynomial_zmod_flint modulus) + cdef Polynomial _powmod_bigexp(self, Integer exp, Polynomial_zmod_flint modulus) cpdef rational_reconstruction(self, m, n_deg=?, d_deg=?) noexcept diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 775258190cb..0e2a75291a0 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -534,11 +534,11 @@ cdef class Polynomial_zmod_flint(Polynomial_template): modulus = m self = self % modulus if exp > 0 and exp.bit_length() >= 32: - return self._powmod_bigexp(exp, modulus) + return (self)._powmod_bigexp(exp, modulus) return Polynomial_template.__pow__(self, exp, modulus) - cpdef Polynomial _powmod_bigexp(Polynomial_zmod_flint self, Integer exp, Polynomial_zmod_flint m): + cdef Polynomial _powmod_bigexp(Polynomial_zmod_flint self, Integer exp, Polynomial_zmod_flint m): r""" Modular exponentiation with a large integer exponent. @@ -548,9 +548,9 @@ cdef class Polynomial_zmod_flint(Polynomial_template): sage: R. = PolynomialRing(GF(5), implementation="FLINT") sage: f = x+1 - sage: f._powmod_bigexp(5**50, x^5 + 4*x + 3) + sage: pow(f, 5**50, x^5 + 4*x + 3) # indirect doctest x + 1 - sage: x._powmod_bigexp(5**64, x^5 + 4*x + 3) + sage: pow(x, 5**64, x^5 + 4*x + 3) # indirect doctest x + 3 """ cdef Polynomial_zmod_flint ans = self._new() From 713af40980e834c6fe2e743be0bec2d5b290dd93 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Sat, 24 Feb 2024 16:01:40 +0000 Subject: [PATCH 030/191] fix change from cpdef to cdef --- src/sage/libs/ntl/ntl_ZZ_pX.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index 244478307f6..5066de60e3f 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -526,9 +526,9 @@ cdef class ntl_ZZ_pX(): [15 5 5 11] """ if modulus is None: - return self._pow(n) + return (self)._pow(n) else: - return self._powmod(Integer(n), modulus) + return (self)._powmod(Integer(n), modulus) cdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, long n): """ From 2e98cf8e68c89f2157f457d6965c2baa0aa51f24 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Sat, 24 Feb 2024 23:05:19 +0000 Subject: [PATCH 031/191] replace trac with issue --- .../rings/polynomial/polynomial_modn_dense_ntl.pyx | 6 +++--- src/sage/rings/polynomial/polynomial_zmod_flint.pyx | 6 +++--- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 0b6bf4a443b..39741c20860 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -299,7 +299,7 @@ cdef class Polynomial_dense_mod_n(Polynomial): TESTS: - Check output type (see :trac:`25182`):: + Check output type (see :issue:`25182`):: sage: R. = PolynomialRing(Integers(3), implementation='NTL') sage: isinstance(x.degree(), Integer) @@ -851,7 +851,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): ... NotImplementedError: Fraction fields not implemented for this type. - We define ``0^0`` to be unity, :trac:`13895`:: + We define ``0^0`` to be unity, :issue:`13895`:: sage: R. = PolynomialRing(Integers(100), implementation='NTL') sage: R(0)^0 @@ -1409,7 +1409,7 @@ cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n): sage: (x+1)^5 x^5 + 5*x^4 + 10*x^3 + 10*x^2 + 5*x + 1 - We define ``0^0`` to be unity, :trac:`13895`:: + We define ``0^0`` to be unity, :issue:`13895`:: sage: R. = PolynomialRing(Integers(10^30), implementation='NTL') sage: R(0)^0 diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 0e2a75291a0..3a9f49d9a49 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -228,7 +228,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): TESTS: - The following test from :trac:`12173` used to be horribly slow:: + The following test from :issue:`12173` used to be horribly slow:: sage: a = ZZ['x'](range(100000)) sage: R = Integers(3)['x'] @@ -347,7 +347,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): sage: r.parent() is GF(19) True - The following example shows that :trac:`11782` has been fixed:: + The following example shows that :issue:`11782` has been fixed:: sage: R. = ZZ.quo(9)['x'] sage: f = 2*x^3 + x^2 + x; g = 6*x^2 + 2*x + 1 @@ -748,7 +748,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): ... NotImplementedError: square free factorization of polynomials over rings with composite characteristic is not implemented - :trac:`20003`:: + :issue:`20003`:: sage: P. = GF(7)[] sage: (6*x+3).squarefree_decomposition() diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index e033d834200..6ce1c1422a7 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -89,7 +89,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): TESTS: - The following tests against a bug that was fixed in :trac:`9944`. + The following tests against a bug that was fixed in :issue:`9944`. With the ring definition above, we now have:: sage: R([3,'1234']) @@ -104,7 +104,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): TypeError: not a constant polynomial Check that NTL contexts are correctly restored and that - :trac:`9524` has been fixed:: + :issue:`9524` has been fixed:: sage: x = polygen(GF(9, 'a')) sage: x = polygen(GF(49, 'a')) @@ -113,7 +113,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: 5*x 5*x - Check that :trac:`11239` is fixed:: + Check that :issue:`11239` is fixed:: sage: Fq. = GF(2^4); Fqq. = GF(3^7) sage: PFq. = Fq[]; PFqq. = Fqq[] @@ -237,7 +237,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): TESTS: - The work around provided in :trac:`10475` is superseded by :trac:`24072`:: + The work around provided in :issue:`10475` is superseded by :issue:`24072`:: sage: F. = GF(4) sage: P. = F[] @@ -248,7 +248,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): TypeError: positive characteristic not allowed in symbolic computations Check that polynomial evaluation works when using logarithmic - representation of finite field elements (:trac:`16383`):: + representation of finite field elements (:issue:`16383`):: sage: for i in range(10): ....: F = FiniteField(random_prime(15) ** ZZ.random_element(2, 5), 'a', repr='log') From 7f8254b4da72277c0c1ecd9885b937857b43fc40 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 21:02:28 -0800 Subject: [PATCH 032/191] .github/workflows/ci-linux.yml: Build 'default' with free_disk_space: true --- .github/workflows/ci-linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index 7c0d22118c0..7e86f010b42 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -39,6 +39,7 @@ jobs: uses: ./.github/workflows/docker.yml with: # Build from scratch + free_disk_space: true docker_targets: "with-system-packages configured with-targets-pre with-targets" # FIXME: duplicated from env.TARGETS targets_pre: all-sage-local From 40ae78b10ead6441b7d2d8b989e97c757bc4a0e1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 21:04:55 -0800 Subject: [PATCH 033/191] .github/workflows/docker.yml: Build with 'make -j9', test with SAGE_NUM_THREADS=5 --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1ee938339b3..970e7db502e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -244,7 +244,7 @@ jobs: # configuration on many platforms. run: | (sleep ${{ inputs.timeout }}; for id in $(docker ps -q); do docker exec $id find /proc -maxdepth 2 -name cmdline -exec bash -c "grep -l [m][a][k][e] {} | cut -d/ -f3 | xargs --no-run-if-empty kill" \;; done) & - 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::|;" + set -o pipefail; EXTRA_DOCKER_BUILD_ARGS="--build-arg NUMPROC=9 --build-arg USE_MAKEFLAGS=\"-k V=0 SAGE_NUM_THREADS=5\"" 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::|;" - name: Copy logs from the Docker image or build container run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME" From 081c9ee01b5a826dff7782f4bb194d67878b77f5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 21:11:30 -0800 Subject: [PATCH 034/191] tox.ini: Add ubuntu-noble, fedora-40, linuxmint-21.3, gentoo-python3.12 --- tox.ini | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tox.ini b/tox.ini index 3673833724c..db66de3ea4f 100644 --- a/tox.ini +++ b/tox.ini @@ -205,7 +205,7 @@ setenv = docker: BASE_TAG=latest # # https://hub.docker.com/_/ubuntu?tab=description - # as of 2023-05, latest=jammy=22.04, rolling=lunar=23.04, devel=mantic=23.10 + # as of 2024-02, latest=jammy=22.04, rolling=mantic=23.10, devel=noble=24.04 # ubuntu-focal does not have libgap-dev # ubuntu: SYSTEM=debian @@ -226,6 +226,7 @@ setenv = ubuntu-jammy: BASE_TAG=jammy ubuntu-lunar: BASE_TAG=lunar ubuntu-mantic: BASE_TAG=mantic + ubuntu-noble: BASE_TAG=noble # # https://hub.docker.com/_/debian # debian-buster does not have libfreetype-dev (it only has libfreetype6-dev) @@ -264,6 +265,7 @@ setenv = linuxmint-21: BASE_IMAGE=linuxmintd/mint21 linuxmint-21.1: BASE_IMAGE=linuxmintd/mint21.1 linuxmint-21.2: BASE_IMAGE=linuxmintd/mint21.2 + linuxmint-21.3: BASE_IMAGE=linuxmintd/mint21.3 # # https://hub.docker.com/_/fedora # as of 2024-01, latest=39, rawhide=40 @@ -822,14 +824,14 @@ setenv = # Master list of platforms tested in CI Linux # DEFAULT_SYSTEM_FACTORS=\ - ubuntu-{trusty-toolchain-gcc_9,xenial-toolchain-gcc_9,bionic-gcc_8,focal,jammy,lunar,mantic} \ + ubuntu-{trusty-toolchain-gcc_9,xenial-toolchain-gcc_9,bionic-gcc_8,focal,jammy,lunar,mantic,noble} \ debian-{buster-gcc_spkg,bullseye,bookworm,trixie,sid} \ - linuxmint-{20.1,20.2,20.3,21,21.1,21.2} \ - fedora-{30,31,32,33,34,35,36,37,38,39} \ + linuxmint-{20.1,20.2,20.3,21,21.1,21.2,21.3} \ + fedora-{30,31,32,33,34,35,36,37,38,39,40} \ centos-7-devtoolset-gcc_11 \ centos-stream-{8,9}-python3.9 \ almalinux-{8-python3.9,9-python3.11} \ - gentoo-python{3.10,3.11} \ + gentoo-python{3.10,3.11,3.12} \ archlinux-latest \ opensuse-{15.3-gcc_11-python3.9,15.4-gcc_11-python3.10,15.5-gcc_11-python3.11} \ opensuse-tumbleweed{-python3.10,} \ From 504c4cd878f9d38cea97a9a742d1222fd904da5e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 21:12:24 -0800 Subject: [PATCH 035/191] tox -e update_docker_platforms --- .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .../devcontainer.json | 25 ++ .../portability-Dockerfile | 1 + .github/workflows/docker.yml | 4 + .../developer/portability_platform_table.rst | 260 ++++++++++++++++++ 18 files changed, 472 insertions(+) create mode 100644 .devcontainer/portability-fedora-40-minimal/devcontainer.json create mode 120000 .devcontainer/portability-fedora-40-minimal/portability-Dockerfile create mode 100644 .devcontainer/portability-fedora-40-standard/devcontainer.json create mode 120000 .devcontainer/portability-fedora-40-standard/portability-Dockerfile create mode 100644 .devcontainer/portability-gentoo-python3.12-minimal/devcontainer.json create mode 120000 .devcontainer/portability-gentoo-python3.12-minimal/portability-Dockerfile create mode 100644 .devcontainer/portability-gentoo-python3.12-standard/devcontainer.json create mode 120000 .devcontainer/portability-gentoo-python3.12-standard/portability-Dockerfile create mode 100644 .devcontainer/portability-linuxmint-21.3-minimal/devcontainer.json create mode 120000 .devcontainer/portability-linuxmint-21.3-minimal/portability-Dockerfile create mode 100644 .devcontainer/portability-linuxmint-21.3-standard/devcontainer.json create mode 120000 .devcontainer/portability-linuxmint-21.3-standard/portability-Dockerfile create mode 100644 .devcontainer/portability-ubuntu-noble-minimal/devcontainer.json create mode 120000 .devcontainer/portability-ubuntu-noble-minimal/portability-Dockerfile create mode 100644 .devcontainer/portability-ubuntu-noble-standard/devcontainer.json create mode 120000 .devcontainer/portability-ubuntu-noble-standard/portability-Dockerfile diff --git a/.devcontainer/portability-fedora-40-minimal/devcontainer.json b/.devcontainer/portability-fedora-40-minimal/devcontainer.json new file mode 100644 index 00000000000..dd037154fe3 --- /dev/null +++ b/.devcontainer/portability-fedora-40-minimal/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "fedora-40-minimal (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "fedora-40", + "PACKAGE_FACTOR": "minimal", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-fedora-40-minimal/portability-Dockerfile b/.devcontainer/portability-fedora-40-minimal/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-fedora-40-minimal/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-fedora-40-standard/devcontainer.json b/.devcontainer/portability-fedora-40-standard/devcontainer.json new file mode 100644 index 00000000000..1f9d4a5e378 --- /dev/null +++ b/.devcontainer/portability-fedora-40-standard/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "fedora-40-standard (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "fedora-40", + "PACKAGE_FACTOR": "standard", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-fedora-40-standard/portability-Dockerfile b/.devcontainer/portability-fedora-40-standard/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-fedora-40-standard/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-gentoo-python3.12-minimal/devcontainer.json b/.devcontainer/portability-gentoo-python3.12-minimal/devcontainer.json new file mode 100644 index 00000000000..41250ac5e74 --- /dev/null +++ b/.devcontainer/portability-gentoo-python3.12-minimal/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "gentoo-python3.12-minimal (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "gentoo-python3.12", + "PACKAGE_FACTOR": "minimal", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-gentoo-python3.12-minimal/portability-Dockerfile b/.devcontainer/portability-gentoo-python3.12-minimal/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-gentoo-python3.12-minimal/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-gentoo-python3.12-standard/devcontainer.json b/.devcontainer/portability-gentoo-python3.12-standard/devcontainer.json new file mode 100644 index 00000000000..3193910dd6a --- /dev/null +++ b/.devcontainer/portability-gentoo-python3.12-standard/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "gentoo-python3.12-standard (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "gentoo-python3.12", + "PACKAGE_FACTOR": "standard", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-gentoo-python3.12-standard/portability-Dockerfile b/.devcontainer/portability-gentoo-python3.12-standard/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-gentoo-python3.12-standard/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-linuxmint-21.3-minimal/devcontainer.json b/.devcontainer/portability-linuxmint-21.3-minimal/devcontainer.json new file mode 100644 index 00000000000..6350569173d --- /dev/null +++ b/.devcontainer/portability-linuxmint-21.3-minimal/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "linuxmint-21.3-minimal (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "linuxmint-21.3", + "PACKAGE_FACTOR": "minimal", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-linuxmint-21.3-minimal/portability-Dockerfile b/.devcontainer/portability-linuxmint-21.3-minimal/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-linuxmint-21.3-minimal/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-linuxmint-21.3-standard/devcontainer.json b/.devcontainer/portability-linuxmint-21.3-standard/devcontainer.json new file mode 100644 index 00000000000..245fee17201 --- /dev/null +++ b/.devcontainer/portability-linuxmint-21.3-standard/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "linuxmint-21.3-standard (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "linuxmint-21.3", + "PACKAGE_FACTOR": "standard", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-linuxmint-21.3-standard/portability-Dockerfile b/.devcontainer/portability-linuxmint-21.3-standard/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-linuxmint-21.3-standard/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-ubuntu-noble-minimal/devcontainer.json b/.devcontainer/portability-ubuntu-noble-minimal/devcontainer.json new file mode 100644 index 00000000000..f22b6775f74 --- /dev/null +++ b/.devcontainer/portability-ubuntu-noble-minimal/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "ubuntu-noble-minimal (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "ubuntu-noble", + "PACKAGE_FACTOR": "minimal", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-ubuntu-noble-minimal/portability-Dockerfile b/.devcontainer/portability-ubuntu-noble-minimal/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-ubuntu-noble-minimal/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-ubuntu-noble-standard/devcontainer.json b/.devcontainer/portability-ubuntu-noble-standard/devcontainer.json new file mode 100644 index 00000000000..7acec1e29ac --- /dev/null +++ b/.devcontainer/portability-ubuntu-noble-standard/devcontainer.json @@ -0,0 +1,25 @@ +// The command "tox -e update_docker_platforms" +// creates .devcontainer/portability-*-*/devcontainer.json +// from .devcontainer/portability-devcontainer.json.in +// See https://aka.ms/devcontainer.json for format details. +{ + "name": "ubuntu-noble-standard (≥ 8-core)", + "build": { + "dockerfile": "portability-Dockerfile", + // See tox.ini for definitions + "args": { + "SYSTEM_FACTOR": "ubuntu-noble", + "PACKAGE_FACTOR": "standard", + "DOCKER_TARGET": "with-targets", + "DOCKER_TAG": "dev" + } + }, + "containerEnv": { + "MAKE": "make -j4" + }, + "onCreateCommand": ".devcontainer/onCreate.sh", + "updateContentCommand": ".devcontainer/portability-updateContent.sh", + "extensions": [ + "ms-python.python" + ] +} diff --git a/.devcontainer/portability-ubuntu-noble-standard/portability-Dockerfile b/.devcontainer/portability-ubuntu-noble-standard/portability-Dockerfile new file mode 120000 index 00000000000..692e2a79d64 --- /dev/null +++ b/.devcontainer/portability-ubuntu-noble-standard/portability-Dockerfile @@ -0,0 +1 @@ +../portability-Dockerfile \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 970e7db502e..ed049f3e85e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -25,6 +25,7 @@ on: "ubuntu-jammy", "ubuntu-lunar", "ubuntu-mantic", + "ubuntu-noble", "debian-buster-gcc_spkg", "debian-bullseye", "debian-bookworm", @@ -36,6 +37,7 @@ on: "linuxmint-21", "linuxmint-21.1", "linuxmint-21.2", + "linuxmint-21.3", "fedora-30", "fedora-31", "fedora-32", @@ -46,6 +48,7 @@ on: "fedora-37", "fedora-38", "fedora-39", + "fedora-40", "centos-7-devtoolset-gcc_11", "centos-stream-8-python3.9", "centos-stream-9-python3.9", @@ -53,6 +56,7 @@ on: "almalinux-9-python3.11", "gentoo-python3.10", "gentoo-python3.11", + "gentoo-python3.12", "archlinux-latest", "opensuse-15.3-gcc_11-python3.9", "opensuse-15.4-gcc_11-python3.10", diff --git a/src/doc/en/developer/portability_platform_table.rst b/src/doc/en/developer/portability_platform_table.rst index d024671c9d8..7b173a1959c 100644 --- a/src/doc/en/developer/portability_platform_table.rst +++ b/src/doc/en/developer/portability_platform_table.rst @@ -376,6 +376,60 @@ .. |codespace-ubuntu-mantic-maximal| image:: https://github.com/codespaces/badge.svg :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-ubuntu-mantic-maximal%2Fdevcontainer.json +.. |image-ubuntu-noble-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-minimal-with-system-packages + +.. |image-ubuntu-noble-minimal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-minimal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-minimal-configured + +.. |image-ubuntu-noble-minimal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-minimal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%23677895 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-minimal-with-targets-pre + +.. |image-ubuntu-noble-minimal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-minimal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%236686c1 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-minimal-with-targets + +.. |image-ubuntu-noble-minimal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-minimal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%236495ed + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-minimal-with-targets-optional + +.. |codespace-ubuntu-noble-minimal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-ubuntu-noble-minimal%2Fdevcontainer.json + +.. |image-ubuntu-noble-standard-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-standard-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-standard-with-system-packages + +.. |image-ubuntu-noble-standard-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-standard-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-standard-configured + +.. |image-ubuntu-noble-standard-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-standard-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%235d8a4c + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-standard-with-targets-pre + +.. |image-ubuntu-noble-standard-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-standard-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%2350ab2e + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-standard-with-targets + +.. |image-ubuntu-noble-standard-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-standard-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%2344cc11 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-standard-with-targets-optional + +.. |codespace-ubuntu-noble-standard| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-ubuntu-noble-standard%2Fdevcontainer.json + +.. |image-ubuntu-noble-maximal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-maximal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-maximal-with-system-packages + +.. |image-ubuntu-noble-maximal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-maximal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-maximal-configured + +.. |image-ubuntu-noble-maximal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-maximal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%238f6b8d + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-maximal-with-targets-pre + +.. |image-ubuntu-noble-maximal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-maximal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%23b46eb2 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-maximal-with-targets + +.. |image-ubuntu-noble-maximal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-ubuntu-noble-maximal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%23da70d6 + :target: https://ghcr.io/sagemath/sage/sage-ubuntu-noble-maximal-with-targets-optional + +.. |codespace-ubuntu-noble-maximal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-ubuntu-noble-maximal%2Fdevcontainer.json + .. |image-debian-buster-gcc_spkg-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-debian-buster-gcc_spkg-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 :target: https://ghcr.io/sagemath/sage/sage-debian-buster-gcc_spkg-minimal-with-system-packages @@ -970,6 +1024,60 @@ .. |codespace-linuxmint-21.2-maximal| image:: https://github.com/codespaces/badge.svg :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-linuxmint-21.2-maximal%2Fdevcontainer.json +.. |image-linuxmint-21.3-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-minimal-with-system-packages + +.. |image-linuxmint-21.3-minimal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-minimal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-minimal-configured + +.. |image-linuxmint-21.3-minimal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-minimal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%23677895 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-minimal-with-targets-pre + +.. |image-linuxmint-21.3-minimal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-minimal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%236686c1 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-minimal-with-targets + +.. |image-linuxmint-21.3-minimal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-minimal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%236495ed + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-minimal-with-targets-optional + +.. |codespace-linuxmint-21.3-minimal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-linuxmint-21.3-minimal%2Fdevcontainer.json + +.. |image-linuxmint-21.3-standard-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-standard-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-standard-with-system-packages + +.. |image-linuxmint-21.3-standard-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-standard-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-standard-configured + +.. |image-linuxmint-21.3-standard-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-standard-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%235d8a4c + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-standard-with-targets-pre + +.. |image-linuxmint-21.3-standard-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-standard-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%2350ab2e + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-standard-with-targets + +.. |image-linuxmint-21.3-standard-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-standard-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%2344cc11 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-standard-with-targets-optional + +.. |codespace-linuxmint-21.3-standard| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-linuxmint-21.3-standard%2Fdevcontainer.json + +.. |image-linuxmint-21.3-maximal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-maximal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-maximal-with-system-packages + +.. |image-linuxmint-21.3-maximal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-maximal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-maximal-configured + +.. |image-linuxmint-21.3-maximal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-maximal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%238f6b8d + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-maximal-with-targets-pre + +.. |image-linuxmint-21.3-maximal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-maximal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%23b46eb2 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-maximal-with-targets + +.. |image-linuxmint-21.3-maximal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-linuxmint-21.3-maximal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%23da70d6 + :target: https://ghcr.io/sagemath/sage/sage-linuxmint-21.3-maximal-with-targets-optional + +.. |codespace-linuxmint-21.3-maximal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-linuxmint-21.3-maximal%2Fdevcontainer.json + .. |image-fedora-30-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-30-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 :target: https://ghcr.io/sagemath/sage/sage-fedora-30-minimal-with-system-packages @@ -1510,6 +1618,60 @@ .. |codespace-fedora-39-maximal| image:: https://github.com/codespaces/badge.svg :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-fedora-39-maximal%2Fdevcontainer.json +.. |image-fedora-40-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-minimal-with-system-packages + +.. |image-fedora-40-minimal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-minimal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-minimal-configured + +.. |image-fedora-40-minimal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-minimal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%23677895 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-minimal-with-targets-pre + +.. |image-fedora-40-minimal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-minimal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%236686c1 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-minimal-with-targets + +.. |image-fedora-40-minimal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-minimal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%236495ed + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-minimal-with-targets-optional + +.. |codespace-fedora-40-minimal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-fedora-40-minimal%2Fdevcontainer.json + +.. |image-fedora-40-standard-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-standard-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-standard-with-system-packages + +.. |image-fedora-40-standard-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-standard-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-standard-configured + +.. |image-fedora-40-standard-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-standard-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%235d8a4c + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-standard-with-targets-pre + +.. |image-fedora-40-standard-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-standard-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%2350ab2e + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-standard-with-targets + +.. |image-fedora-40-standard-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-standard-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%2344cc11 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-standard-with-targets-optional + +.. |codespace-fedora-40-standard| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-fedora-40-standard%2Fdevcontainer.json + +.. |image-fedora-40-maximal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-maximal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-maximal-with-system-packages + +.. |image-fedora-40-maximal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-maximal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-maximal-configured + +.. |image-fedora-40-maximal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-maximal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%238f6b8d + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-maximal-with-targets-pre + +.. |image-fedora-40-maximal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-maximal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%23b46eb2 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-maximal-with-targets + +.. |image-fedora-40-maximal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-fedora-40-maximal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%23da70d6 + :target: https://ghcr.io/sagemath/sage/sage-fedora-40-maximal-with-targets-optional + +.. |codespace-fedora-40-maximal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-fedora-40-maximal%2Fdevcontainer.json + .. |image-centos-7-devtoolset-gcc_11-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-system-packages @@ -1888,6 +2050,60 @@ .. |codespace-gentoo-python3.11-maximal| image:: https://github.com/codespaces/badge.svg :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-gentoo-python3.11-maximal%2Fdevcontainer.json +.. |image-gentoo-python3.12-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-minimal-with-system-packages + +.. |image-gentoo-python3.12-minimal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-minimal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-minimal-configured + +.. |image-gentoo-python3.12-minimal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-minimal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%23677895 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-minimal-with-targets-pre + +.. |image-gentoo-python3.12-minimal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-minimal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%236686c1 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-minimal-with-targets + +.. |image-gentoo-python3.12-minimal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-minimal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%236495ed + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-minimal-with-targets-optional + +.. |codespace-gentoo-python3.12-minimal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-gentoo-python3.12-minimal%2Fdevcontainer.json + +.. |image-gentoo-python3.12-standard-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-standard-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-standard-with-system-packages + +.. |image-gentoo-python3.12-standard-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-standard-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-standard-configured + +.. |image-gentoo-python3.12-standard-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-standard-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%235d8a4c + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-standard-with-targets-pre + +.. |image-gentoo-python3.12-standard-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-standard-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%2350ab2e + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-standard-with-targets + +.. |image-gentoo-python3.12-standard-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-standard-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%2344cc11 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-standard-with-targets-optional + +.. |codespace-gentoo-python3.12-standard| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-gentoo-python3.12-standard%2Fdevcontainer.json + +.. |image-gentoo-python3.12-maximal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-maximal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-maximal-with-system-packages + +.. |image-gentoo-python3.12-maximal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-maximal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-maximal-configured + +.. |image-gentoo-python3.12-maximal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-maximal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%238f6b8d + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-maximal-with-targets-pre + +.. |image-gentoo-python3.12-maximal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-maximal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%23b46eb2 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-maximal-with-targets + +.. |image-gentoo-python3.12-maximal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-gentoo-python3.12-maximal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%23da70d6 + :target: https://ghcr.io/sagemath/sage/sage-gentoo-python3.12-maximal-with-targets-optional + +.. |codespace-gentoo-python3.12-maximal| image:: https://github.com/codespaces/badge.svg + :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-gentoo-python3.12-maximal%2Fdevcontainer.json + .. |image-archlinux-latest-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-archlinux-latest-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 :target: https://ghcr.io/sagemath/sage/sage-archlinux-latest-minimal-with-system-packages @@ -2459,6 +2675,17 @@ * -    ‑*maximal* - |image-ubuntu-mantic-maximal-with-system-packages| |image-ubuntu-mantic-maximal-with-targets-pre| - + * - **ubuntu**-noble + +    ‑*minimal* + - |image-ubuntu-noble-minimal-with-system-packages| |image-ubuntu-noble-minimal-with-targets-pre| |image-ubuntu-noble-minimal-with-targets| |image-ubuntu-noble-minimal-with-targets-optional| + - |codespace-ubuntu-noble-minimal| + * -    ‑*standard* + - |image-ubuntu-noble-standard-with-system-packages| |image-ubuntu-noble-standard-with-targets-pre| |image-ubuntu-noble-standard-with-targets| |image-ubuntu-noble-standard-with-targets-optional| + - |codespace-ubuntu-noble-standard| + * -    ‑*maximal* + - |image-ubuntu-noble-maximal-with-system-packages| |image-ubuntu-noble-maximal-with-targets-pre| + - * - **debian**-buster-gcc_spkg    ‑*minimal* @@ -2580,6 +2807,17 @@ * -    ‑*maximal* - |image-linuxmint-21.2-maximal-with-system-packages| |image-linuxmint-21.2-maximal-with-targets-pre| - + * - **linuxmint**-21.3 + +    ‑*minimal* + - |image-linuxmint-21.3-minimal-with-system-packages| |image-linuxmint-21.3-minimal-with-targets-pre| |image-linuxmint-21.3-minimal-with-targets| |image-linuxmint-21.3-minimal-with-targets-optional| + - |codespace-linuxmint-21.3-minimal| + * -    ‑*standard* + - |image-linuxmint-21.3-standard-with-system-packages| |image-linuxmint-21.3-standard-with-targets-pre| |image-linuxmint-21.3-standard-with-targets| |image-linuxmint-21.3-standard-with-targets-optional| + - |codespace-linuxmint-21.3-standard| + * -    ‑*maximal* + - |image-linuxmint-21.3-maximal-with-system-packages| |image-linuxmint-21.3-maximal-with-targets-pre| + - * - **fedora**-30    ‑*minimal* @@ -2690,6 +2928,17 @@ * -    ‑*maximal* - |image-fedora-39-maximal-with-system-packages| |image-fedora-39-maximal-with-targets-pre| - + * - **fedora**-40 + +    ‑*minimal* + - |image-fedora-40-minimal-with-system-packages| |image-fedora-40-minimal-with-targets-pre| |image-fedora-40-minimal-with-targets| |image-fedora-40-minimal-with-targets-optional| + - |codespace-fedora-40-minimal| + * -    ‑*standard* + - |image-fedora-40-standard-with-system-packages| |image-fedora-40-standard-with-targets-pre| |image-fedora-40-standard-with-targets| |image-fedora-40-standard-with-targets-optional| + - |codespace-fedora-40-standard| + * -    ‑*maximal* + - |image-fedora-40-maximal-with-system-packages| |image-fedora-40-maximal-with-targets-pre| + - * - **centos**-7-devtoolset-gcc_11    ‑*minimal* @@ -2767,6 +3016,17 @@ * -    ‑*maximal* - |image-gentoo-python3.11-maximal-with-system-packages| |image-gentoo-python3.11-maximal-with-targets-pre| - + * - **gentoo**-python3.12 + +    ‑*minimal* + - |image-gentoo-python3.12-minimal-with-system-packages| |image-gentoo-python3.12-minimal-with-targets-pre| |image-gentoo-python3.12-minimal-with-targets| |image-gentoo-python3.12-minimal-with-targets-optional| + - |codespace-gentoo-python3.12-minimal| + * -    ‑*standard* + - |image-gentoo-python3.12-standard-with-system-packages| |image-gentoo-python3.12-standard-with-targets-pre| |image-gentoo-python3.12-standard-with-targets| |image-gentoo-python3.12-standard-with-targets-optional| + - |codespace-gentoo-python3.12-standard| + * -    ‑*maximal* + - |image-gentoo-python3.12-maximal-with-system-packages| |image-gentoo-python3.12-maximal-with-targets-pre| + - * - **archlinux**-latest    ‑*minimal* From b08c7273fde5379611f50b32a412c129ac75c832 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 21:14:23 -0800 Subject: [PATCH 036/191] .github/workflows/build.yml: Use 4 instead of 2 processors --- .github/workflows/build.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ce3c7889f4b..79c3a74c5d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -93,16 +93,16 @@ jobs: ./bootstrap && make build working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Build modularized distributions if: (success() || failure()) && steps.worktree.outcome == 'success' run: make V=0 tox && make SAGE_CHECK=no pypi-wheels working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Static code check with pyright if: (success() || failure()) && steps.worktree.outcome == 'success' @@ -137,8 +137,8 @@ jobs: ./bootstrap && make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage && ./config.status working-directory: ./worktree-image env: - MAKE: make -j2 - SAGE_NUM_THREADS: 2 + MAKE: make -j4 + SAGE_NUM_THREADS: 4 - name: Build # This step is needed because building the modularized distributions installs some optional packages, @@ -149,8 +149,8 @@ jobs: make build working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 # Testing @@ -161,16 +161,16 @@ jobs: ./sage -t --new -p2 working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Test modularized distributions if: (success() || failure()) && steps.build.outcome == 'success' run: make V=0 tox && make pypi-wheels-check working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Check that all modules can be imported run: | From 06116c4d1a360172e071a22d95e804bdad8540d0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 21:16:25 -0800 Subject: [PATCH 037/191] .github/workflows/doc-build*.yml: Use 4 instead of 2 processors --- .github/workflows/doc-build-pdf.yml | 12 ++++++------ .github/workflows/doc-build.yml | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 7ae675d9e64..713aa02543d 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -87,8 +87,8 @@ jobs: ./bootstrap && make build working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Build (fallback to non-incremental) id: build @@ -98,8 +98,8 @@ jobs: make sagelib-clean && git clean -fx src/sage && ./config.status && make build working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Build docs (PDF) id: docbuild @@ -108,8 +108,8 @@ jobs: make doc-clean doc-uninstall; make sagemath_doc_html-build-deps sagemath_doc_pdf-no-deps working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Copy docs id: copy diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 9d82909ef5f..1b1198f5ff8 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -95,8 +95,8 @@ jobs: ./bootstrap && make sagemath_doc_html-build-deps working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Build (fallback to non-incremental) id: build @@ -106,8 +106,8 @@ jobs: make sagelib-clean && git clean -fx src/sage && ./config.status && make sagemath_doc_html-build-deps working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Build docs id: docbuild @@ -124,8 +124,8 @@ jobs: ./config.status && make sagemath_doc_html-no-deps working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Copy docs id: copy @@ -169,8 +169,8 @@ jobs: ./config.status && make sagemath_doc_html-no-deps sagemath_doc_pdf-no-deps working-directory: ./worktree-image env: - MAKE: make -j2 --output-sync=recurse - SAGE_NUM_THREADS: 2 + MAKE: make -j4 --output-sync=recurse + SAGE_NUM_THREADS: 4 - name: Copy live doc id: copylivedoc From b2d7229f9775d1375424cbb4228f684cf1ed05d2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Feb 2024 23:15:51 -0800 Subject: [PATCH 038/191] tox.ini (ubuntu-noble): Set IGNORE_MISSING_SYSTEM_PACKAGES=yes --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index db66de3ea4f..cf8507128fd 100644 --- a/tox.ini +++ b/tox.ini @@ -207,6 +207,7 @@ setenv = # https://hub.docker.com/_/ubuntu?tab=description # as of 2024-02, latest=jammy=22.04, rolling=mantic=23.10, devel=noble=24.04 # ubuntu-focal does not have libgap-dev + # ubuntu-noble does not have libbrial-dev # ubuntu: SYSTEM=debian ubuntu: BASE_IMAGE=ubuntu @@ -227,6 +228,7 @@ setenv = ubuntu-lunar: BASE_TAG=lunar ubuntu-mantic: BASE_TAG=mantic ubuntu-noble: BASE_TAG=noble + ubuntu-noble: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/_/debian # debian-buster does not have libfreetype-dev (it only has libfreetype6-dev) From 995a94b40fca1de83d728b05bed1f111c10b3203 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Mon, 26 Feb 2024 12:32:06 +0000 Subject: [PATCH 039/191] Fix docstring formatting --- src/sage/libs/ntl/ntl_ZZ_pX.pyx | 4 ++-- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index 5066de60e3f..8d2e5b1d43b 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -492,7 +492,7 @@ cdef class ntl_ZZ_pX(): def __pow__(self, n, modulus): """ - Return the n-th nonnegative power of self. + Return the ``n``-th nonnegative power of ``self``. If ``modulus`` is not ``None``, the exponentiation is performed modulo the polynomial ``modulus``. @@ -532,7 +532,7 @@ cdef class ntl_ZZ_pX(): cdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, long n): """ - Compute the ``n``-th power of `self``. + Compute the ``n``-th power of ``self``. """ if n < 0: raise NotImplementedError diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 6ce1c1422a7..9ed9acbaa84 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -621,7 +621,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): def __pow__(self, exp, modulus): r""" - Exponentiation of polynomials. + Exponentiation of ``self``. If ``modulus`` is not ``None``, the exponentiation is performed modulo the polynomial ``modulus``. From 992dc4defaa08ed73832b344073bd63c414c913c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 19:22:13 -0800 Subject: [PATCH 040/191] build/pkgs/onetbb: Update to 2021.11.0 --- build/pkgs/onetbb/checksums.ini | 6 +++--- build/pkgs/onetbb/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/onetbb/checksums.ini b/build/pkgs/onetbb/checksums.ini index 69e7ed4d027..42e837760b6 100644 --- a/build/pkgs/onetbb/checksums.ini +++ b/build/pkgs/onetbb/checksums.ini @@ -1,5 +1,5 @@ tarball=onetbb-VERSION.tar.gz -sha1=b991f5d882aba2182871cfe011614cc43b92aa3c -md5=ba4ecedc4949f673a34b35de738a72fc -cksum=211900655 +sha1=740e86b703f42446ddde392b73a9db3dc0f5f4cd +md5=b301151120b08a17e98dcdda6e4f6011 +cksum=3287903962 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 a6513d2ae59..90431db79ad 100644 --- a/build/pkgs/onetbb/package-version.txt +++ b/build/pkgs/onetbb/package-version.txt @@ -1 +1 @@ -2021.9.0 +2021.11.0 From a80bbf9978fbd76f8103d8eec8a75cd52fd425dc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 19:22:41 -0800 Subject: [PATCH 041/191] build/pkgs/papilo: Update to 2.2.0 --- build/pkgs/papilo/checksums.ini | 6 +++--- build/pkgs/papilo/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/papilo/checksums.ini b/build/pkgs/papilo/checksums.ini index b2385565547..8bebc605f2c 100644 --- a/build/pkgs/papilo/checksums.ini +++ b/build/pkgs/papilo/checksums.ini @@ -1,5 +1,5 @@ tarball=papilo-VERSION.tar.gz -sha1=85d599ac9936aa1ddf687e04273b995522909de5 -md5=c41f5aa615ffc9914f8ca924947aa8cb -cksum=1535425476 +sha1=069f64ff25cfb08c9b2a416d1d215bd5b907c877 +md5=d58b7c991ac1c4a863de92a404409ca8 +cksum=1552180280 upstream_url=https://github.com/scipopt/papilo/archive/refs/tags/vVERSION.tar.gz diff --git a/build/pkgs/papilo/package-version.txt b/build/pkgs/papilo/package-version.txt index 3e3c2f1e5ed..ccbccc3dc62 100644 --- a/build/pkgs/papilo/package-version.txt +++ b/build/pkgs/papilo/package-version.txt @@ -1 +1 @@ -2.1.1 +2.2.0 From 0d444bc37dbe88af8e9bb72fd2ea68a8cf5fd127 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 19:25:39 -0800 Subject: [PATCH 042/191] build/pkgs/scip: Update to 9.0.0 --- build/pkgs/scip/checksums.ini | 10 +++++----- build/pkgs/scip/package-version.txt | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/pkgs/scip/checksums.ini b/build/pkgs/scip/checksums.ini index 97b8c8a7084..9dce3926f9b 100644 --- a/build/pkgs/scip/checksums.ini +++ b/build/pkgs/scip/checksums.ini @@ -1,5 +1,5 @@ -tarball=scip-VERSION.tar.gz -sha1=2637767428e285b6ddda8c462f1cc31d66833d80 -md5=b657369986ecd9b2944206d11ecce2e4 -cksum=967379932 -upstream_url=https://github.com/scipopt/scip/archive/refs/tags/vVERSION.tar.gz +tarball=scip-${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}.tar.gz +sha1=bb28aef4bad00a1ff2c7f4ee982961709d15b9f8 +md5=2fdbc40c98d380b12586bcef6819b9d7 +cksum=1262698285 +upstream_url=https://github.com/scipopt/scip/archive/refs/tags/v${VERSION_MAJOR}${VERSION_MINOR}${VERSION_MICRO}.tar.gz diff --git a/build/pkgs/scip/package-version.txt b/build/pkgs/scip/package-version.txt index 227b54a0631..f7ee06693c1 100644 --- a/build/pkgs/scip/package-version.txt +++ b/build/pkgs/scip/package-version.txt @@ -1 +1 @@ -802 +9.0.0 From 407cc17384e2ac7f9603f5c870f4436b6cb90a78 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 19:33:18 -0800 Subject: [PATCH 043/191] build/pkgs/papilo: Remove patches --- ...o-not-require-boost-program_options-.patch | 26 ------------------- .../import_memory_multiprecision.patch | 20 -------------- 2 files changed, 46 deletions(-) delete mode 100644 build/pkgs/papilo/patches/0001-CMakeLists.txt-Do-not-require-boost-program_options-.patch delete mode 100644 build/pkgs/papilo/patches/import_memory_multiprecision.patch diff --git a/build/pkgs/papilo/patches/0001-CMakeLists.txt-Do-not-require-boost-program_options-.patch b/build/pkgs/papilo/patches/0001-CMakeLists.txt-Do-not-require-boost-program_options-.patch deleted file mode 100644 index 5001ca4d67a..00000000000 --- a/build/pkgs/papilo/patches/0001-CMakeLists.txt-Do-not-require-boost-program_options-.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 1fc5aecb4eca500917407b008c8c8eb8637a9c27 Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Sat, 19 Nov 2022 19:03:37 -0800 -Subject: [PATCH] CMakeLists.txt: Do not require boost program_options for the - library - ---- - CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 7256877..db905aa 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -47,7 +47,7 @@ if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) - endif() - --find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS program_options REQUIRED) -+find_package(Boost ${BOOST_MIN_VERSION} REQUIRED) - - if(GMP) - find_package(GMP) --- -2.37.3 - diff --git a/build/pkgs/papilo/patches/import_memory_multiprecision.patch b/build/pkgs/papilo/patches/import_memory_multiprecision.patch deleted file mode 100644 index 1f16ced0bed..00000000000 --- a/build/pkgs/papilo/patches/import_memory_multiprecision.patch +++ /dev/null @@ -1,20 +0,0 @@ -commit 855bd67a64c5c044080d790e5c9fb7e298a61ab7 -Author: Matthias Koeppe -Date: Thu Dec 8 18:10:29 2022 -0800 - - src/papilo/misc/MultiPrecision.hpp: Add #include - -diff --git a/src/papilo/misc/MultiPrecision.hpp b/src/papilo/misc/MultiPrecision.hpp -index 669014c..44d3e63 100644 ---- a/src/papilo/misc/MultiPrecision.hpp -+++ b/src/papilo/misc/MultiPrecision.hpp -@@ -26,6 +26,9 @@ - - #include "papilo/Config.hpp" - -+// work around build failure with boost on Fedora 37 -+#include -+ - #include - - #ifdef PAPILO_HAVE_FLOAT128 From bb3805307241b349c202ccc3ef3de2514ea19939 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 20:57:19 -0800 Subject: [PATCH 044/191] build/pkgs/scip: Remove patches/no_rpath.patch --- build/pkgs/scip/patches/no_rpath.patch | 40 -------------------------- 1 file changed, 40 deletions(-) delete mode 100644 build/pkgs/scip/patches/no_rpath.patch diff --git a/build/pkgs/scip/patches/no_rpath.patch b/build/pkgs/scip/patches/no_rpath.patch deleted file mode 100644 index 28b4220b6b3..00000000000 --- a/build/pkgs/scip/patches/no_rpath.patch +++ /dev/null @@ -1,40 +0,0 @@ -commit eaff18abb55c86e90d44583731550c874dc3c3e0 -Author: Matthias Koeppe -Date: Sun Nov 27 14:12:32 2022 -0800 - - CMakeLists.txt: Remove hardcoded RPATH settings - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 8629ace18b..db2505d74b 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -3,8 +3,7 @@ - # - function(setLibProperties targetname outputname) - set_target_properties(${targetname} PROPERTIES -- OUTPUT_NAME ${outputname} -- MACOSX_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -+ OUTPUT_NAME ${outputname}) - endfunction(setLibProperties) - - set(CMAKE_C_STANDARD 99) -@@ -1092,7 +1091,6 @@ add_dependencies(scip scip_update_githash) - set_target_properties(libscip PROPERTIES - VERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR}.${SCIP_VERSION_PATCH}.${SCIP_VERSION_SUB} - SOVERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR} -- INSTALL_RPATH_USE_LINK_PATH TRUE - CXX_VISIBILITY_PRESET hidden - C_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN 1) -@@ -1102,11 +1100,6 @@ target_include_directories(scip PUBLIC - $ - $) - --# set the install rpath to the installed destination --set_target_properties(scip PROPERTIES -- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" -- INSTALL_RPATH_USE_LINK_PATH TRUE) -- - # install the header files of scip - install(FILES ${lpiheaders} DESTINATION include/lpi) - install(FILES ${dijkstraheaders} DESTINATION include/dijkstra) From 6c9a3526ca9f8c7e3428bc3a4f9cec800647eca5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 21:11:51 -0800 Subject: [PATCH 045/191] build/pkgs/scip/dependencies: Add bliss --- build/pkgs/scip/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/scip/dependencies b/build/pkgs/scip/dependencies index 62836bef5a5..fb21a14a5dd 100644 --- a/build/pkgs/scip/dependencies +++ b/build/pkgs/scip/dependencies @@ -1,4 +1,4 @@ -$(MP_LIBRARY) readline soplex papilo zlib | cmake +$(MP_LIBRARY) readline soplex papilo zlib bliss | cmake ---------- All lines of this file are ignored except the first. From 76ef32c70fb39b8795f71d00f018333f7666328d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 21:14:25 -0800 Subject: [PATCH 046/191] build/pkgs/scip_sdp: Update to 4.3.0 --- build/pkgs/scip_sdp/checksums.ini | 6 +++--- build/pkgs/scip_sdp/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/scip_sdp/checksums.ini b/build/pkgs/scip_sdp/checksums.ini index b0e38cf751d..94370bcab39 100644 --- a/build/pkgs/scip_sdp/checksums.ini +++ b/build/pkgs/scip_sdp/checksums.ini @@ -1,5 +1,5 @@ tarball=scipsdp-VERSION.tgz -sha1=dcfb090a95f79df8524bcc63d34d7ddc6692924e -md5=4f900c60456b3f08160ca494bec8e9f4 -cksum=2622380399 +sha1=d5482fd414fdcaa38d6d80111bbe8931aeef63ea +md5=0de7752ba6602e3432940eaaf79dfa9d +cksum=162799809 upstream_url=http://www.opt.tu-darmstadt.de/scipsdp/downloads/scipsdp-VERSION.tgz diff --git a/build/pkgs/scip_sdp/package-version.txt b/build/pkgs/scip_sdp/package-version.txt index ee74734aa22..80895903a15 100644 --- a/build/pkgs/scip_sdp/package-version.txt +++ b/build/pkgs/scip_sdp/package-version.txt @@ -1 +1 @@ -4.1.0 +4.3.0 From ed0aae9b8514966b51063a210591fbfb0c185cf0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Feb 2024 21:19:18 -0800 Subject: [PATCH 047/191] build/pkgs/scip_sdp/patches: Remove --- ...9cf75146ca34c637f919d1f4527a63743300.patch | 55 ------------- build/pkgs/scip_sdp/patches/macos_link.patch | 19 ----- build/pkgs/scip_sdp/patches/no_rpath.patch | 35 -------- .../patches/zz_another_blas_change.patch | 80 ------------------- 4 files changed, 189 deletions(-) delete mode 100644 build/pkgs/scip_sdp/patches/findlapack-09e79cf75146ca34c637f919d1f4527a63743300.patch delete mode 100644 build/pkgs/scip_sdp/patches/macos_link.patch delete mode 100644 build/pkgs/scip_sdp/patches/no_rpath.patch delete mode 100644 build/pkgs/scip_sdp/patches/zz_another_blas_change.patch diff --git a/build/pkgs/scip_sdp/patches/findlapack-09e79cf75146ca34c637f919d1f4527a63743300.patch b/build/pkgs/scip_sdp/patches/findlapack-09e79cf75146ca34c637f919d1f4527a63743300.patch deleted file mode 100644 index a2ec71a5e71..00000000000 --- a/build/pkgs/scip_sdp/patches/findlapack-09e79cf75146ca34c637f919d1f4527a63743300.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 09e79cf75146ca34c637f919d1f4527a63743300 Mon Sep 17 00:00:00 2001 -From: Marc Pfetsch -Date: Fri, 9 Dec 2022 18:52:09 +0100 -Subject: [PATCH] use cmake FindLAPACK - ---- - CMakeLists.txt | 14 +++++--------- - src/CMakeLists.txt | 6 +++--- - 2 files changed, 8 insertions(+), 12 deletions(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 15e4edc..d4f14f5 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -79,16 +79,12 @@ add_custom_target(scip_update_githash - COMMAND ${CMAKE_COMMAND} -DDST=${PROJECT_SOURCE_DIR}/scipsdpgithash.c - -P ${CMAKE_BINARY_DIR}/scip_update_githash.cmake) - -- - # find lapack and blas --find_library(LAPACK_LIBRARY lapack) --if(LAPACK_LIBRARY) -- message(STATUS "Found lapack library: " ${LAPACK_LIBRARY}) --endif() -- --find_library(BLAS_LIBRARY blas) --if(BLAS_LIBRARY) -- message(STATUS "Found blas library: " ${BLAS_LIBRARY}) -+find_package(LAPACK REQUIRED) -+if(LAPACK_FOUND) -+ message(STATUS "Found lapack library: " ${LAPACK_LIBRARIES}) -+else() -+ message(FATAL_ERROR "Lapack not found") - endif() - - # search the selected symmetry computation program -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 30c66b7..5e5d7d3 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -125,11 +125,11 @@ setLibProperties(libscipsdp "scipsdp") - #put binary in bin directory - set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - if(SHARED) -- target_link_libraries(libscipsdp PRIVATE ${ZIMPL_PIC_LIBRARIES} ${SDPS_PIC_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARY} ${BLAS_LIBRARY} m) -+ target_link_libraries(libscipsdp PRIVATE ${ZIMPL_PIC_LIBRARIES} ${SDPS_PIC_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) - add_executable(scipsdp scipsdp/main.c ${scipsdpsources} ${objscipsdpsources} ${sdpisources} ${sym}) -- target_link_libraries(scipsdp ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${GMP_LIBRARIES} ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARY} ${BLAS_LIBRARY} m) -+ target_link_libraries(scipsdp ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${GMP_LIBRARIES} ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) - else() -- target_link_libraries(libscipsdp PRIVATE ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARY} ${BLAS_LIBRARY} m) -+ target_link_libraries(libscipsdp PRIVATE ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) - add_executable(scipsdp scipsdp/main.c ${scipsdpsources} ${objscipsdpsources} ${sdpisources} ${sym}) - target_link_libraries(scipsdp libscipsdp ${SCIP_LIBRARIES}) - endif() diff --git a/build/pkgs/scip_sdp/patches/macos_link.patch b/build/pkgs/scip_sdp/patches/macos_link.patch deleted file mode 100644 index 16f2da86d22..00000000000 --- a/build/pkgs/scip_sdp/patches/macos_link.patch +++ /dev/null @@ -1,19 +0,0 @@ -commit 09f4b596870a2774f7104e318d9812cd5c7ace4a -Author: Matthias Koeppe -Date: Wed Dec 7 14:59:49 2022 -0800 - - src/CMakeLists.txt: Link libscipsdp through with libscip - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 5e5d7d3..ac3841e 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -125,7 +125,7 @@ setLibProperties(libscipsdp "scipsdp") - #put binary in bin directory - set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - if(SHARED) -- target_link_libraries(libscipsdp PRIVATE ${ZIMPL_PIC_LIBRARIES} ${SDPS_PIC_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) -+ target_link_libraries(libscipsdp PRIVATE ${ZIMPL_PIC_LIBRARIES} ${SDPS_PIC_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) - add_executable(scipsdp scipsdp/main.c ${scipsdpsources} ${objscipsdpsources} ${sdpisources} ${sym}) - target_link_libraries(scipsdp ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${GMP_LIBRARIES} ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) - else() diff --git a/build/pkgs/scip_sdp/patches/no_rpath.patch b/build/pkgs/scip_sdp/patches/no_rpath.patch deleted file mode 100644 index a4509df7fc7..00000000000 --- a/build/pkgs/scip_sdp/patches/no_rpath.patch +++ /dev/null @@ -1,35 +0,0 @@ -commit b12db4b95295fec9b32131039a6ee4a746c6f832 -Author: Matthias Koeppe -Date: Wed Dec 7 15:03:48 2022 -0800 - - src/CMakeLists.txt: Remote hardcoded RPATH settings - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index f293115..64ac3d1 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -5,8 +5,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - # - function(setLibProperties targetname outputname) - set_target_properties(${targetname} PROPERTIES -- OUTPUT_NAME ${outputname} -- MACOSX_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -+ OUTPUT_NAME ${outputname}) - endfunction(setLibProperties) - - set(CMAKE_C_STANDARD 99) -@@ -141,13 +140,7 @@ target_compile_definitions(scipsdp PRIVATE EXTERN=extern) - - set_target_properties(libscipsdp PROPERTIES - VERSION ${SCIPSDP_VERSION_MAJOR}.${SCIPSDP_VERSION_MINOR}.${SCIPSDP_VERSION_PATCH} -- SOVERSION ${SCIPSDP_VERSION_MAJOR}.${SCIPSDP_VERSION_MINOR} -- INSTALL_RPATH_USE_LINK_PATH TRUE) -- --# set the install rpath to the installed destination --set_target_properties(scipsdp PROPERTIES -- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" -- INSTALL_RPATH_USE_LINK_PATH TRUE) -+ SOVERSION ${SCIPSDP_VERSION_MAJOR}.${SCIPSDP_VERSION_MINOR}) - - # install the header files of scip - install(FILES ${sdpiheaders} DESTINATION include/sdpi) diff --git a/build/pkgs/scip_sdp/patches/zz_another_blas_change.patch b/build/pkgs/scip_sdp/patches/zz_another_blas_change.patch deleted file mode 100644 index 132f13eab82..00000000000 --- a/build/pkgs/scip_sdp/patches/zz_another_blas_change.patch +++ /dev/null @@ -1,80 +0,0 @@ -commit acb468a1805055e9f34dc1057eea186335bc2e13 -Author: Matthias Koeppe -Date: Fri Dec 9 15:53:05 2022 -0800 - - cmake/Modules/Find{DSDP,MOSEK}.cmake: Do not hardcode blas/lapack lib names here - -commit 8c8f7f82a16af70e044526f2911a94429d65b588 -Author: Matthias Koeppe -Date: Fri Dec 9 19:09:51 2022 -0800 - - CMakeLists.txt, src/CMakeLists.txt: Explicitly link through with blas - - -diff --git a/cmake/Modules/FindDSDP.cmake b/cmake/Modules/FindDSDP.cmake -index 8f43ae8..376fbdb 100644 ---- a/cmake/Modules/FindDSDP.cmake -+++ b/cmake/Modules/FindDSDP.cmake -@@ -8,7 +8,7 @@ find_library(DSDP_LIBRARY - HINTS ${DSDP_DIR} $ENV{DSDP_DIR} - PATH_SUFFIXES lib) - --set(DSDP_LIBRARIES ${DSDP_LIBRARY} -llapack -lblas) -+set(DSDP_LIBRARIES ${DSDP_LIBRARY}) - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(DSDP DEFAULT_MSG DSDP_INCLUDE_DIRS DSDP_LIBRARIES) -diff --git a/cmake/Modules/FindMOSEK.cmake b/cmake/Modules/FindMOSEK.cmake -index a8ee1d6..e3b7ab7 100644 ---- a/cmake/Modules/FindMOSEK.cmake -+++ b/cmake/Modules/FindMOSEK.cmake -@@ -15,10 +15,10 @@ find_library(IOMP5_LIBRARY - PATH_SUFFIXES bin) - - if(IOMPS_LIBRARY) -- set(MOSEK_LIBRARIES ${MOSEK_LIBRARY} ${IOMP5_LIBRARY} -llapack -lblas -pthread) -+ set(MOSEK_LIBRARIES ${MOSEK_LIBRARY} ${IOMP5_LIBRARY} -pthread) - else() - # if libiomps is not available, we skip it -- set(MOSEK_LIBRARIES ${MOSEK_LIBRARY} -llapack -lblas -pthread) -+ set(MOSEK_LIBRARIES ${MOSEK_LIBRARY} -pthread) - endif() - - include(FindPackageHandleStandardArgs) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index d4f14f5..fd2bdf9 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -86,6 +86,12 @@ if(LAPACK_FOUND) - else() - message(FATAL_ERROR "Lapack not found") - endif() -+find_package(BLAS REQUIRED) -+if(BLAS_FOUND) -+ message(STATUS "Found blas library: " ${BLAS_LIBRARIES}) -+else() -+ message(FATAL_ERROR "Blas not found") -+endif() - - # search the selected symmetry computation program - message(STATUS "Finding symmetry computation program \"${SYM}\"") -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 5e5d7d3..b3e2be9 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -125,11 +125,11 @@ setLibProperties(libscipsdp "scipsdp") - #put binary in bin directory - set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - if(SHARED) -- target_link_libraries(libscipsdp PRIVATE ${ZIMPL_PIC_LIBRARIES} ${SDPS_PIC_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) -+ target_link_libraries(libscipsdp PRIVATE ${ZIMPL_PIC_LIBRARIES} ${SDPS_PIC_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} m) - add_executable(scipsdp scipsdp/main.c ${scipsdpsources} ${objscipsdpsources} ${sdpisources} ${sym}) -- target_link_libraries(scipsdp ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${GMP_LIBRARIES} ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) -+ target_link_libraries(scipsdp ${ZLIB_LIBRARIES} ${Readline_LIBRARY} ${GMP_LIBRARIES} ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SCIP_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} m) - else() -- target_link_libraries(libscipsdp PRIVATE ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} m) -+ target_link_libraries(libscipsdp PRIVATE ${ZIMPL_LIBRARIES} ${SDPS_LIBRARIES} ${SYM_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} m) - add_executable(scipsdp scipsdp/main.c ${scipsdpsources} ${objscipsdpsources} ${sdpisources} ${sym}) - target_link_libraries(scipsdp libscipsdp ${SCIP_LIBRARIES}) - endif() From 70df6458e873177d475798efb8c49857a2d5c6cf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 12:21:20 -0800 Subject: [PATCH 048/191] build/pkgs/scip: Add patch from https://github.com/scipopt/SCIP-SDP/issues/12\#issuecomment-1969453709 --- build/pkgs/scip/package-version.txt | 2 +- .../pkgs/scip/patches/struct_symmetry_header.patch | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/scip/patches/struct_symmetry_header.patch diff --git a/build/pkgs/scip/package-version.txt b/build/pkgs/scip/package-version.txt index f7ee06693c1..486ff8cd7ba 100644 --- a/build/pkgs/scip/package-version.txt +++ b/build/pkgs/scip/package-version.txt @@ -1 +1 @@ -9.0.0 +9.0.0.p0 diff --git a/build/pkgs/scip/patches/struct_symmetry_header.patch b/build/pkgs/scip/patches/struct_symmetry_header.patch new file mode 100644 index 00000000000..39d9114a58e --- /dev/null +++ b/build/pkgs/scip/patches/struct_symmetry_header.patch @@ -0,0 +1,14 @@ +From https://github.com/scipopt/SCIP-SDP/issues/12#issuecomment-1969453709 + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 5392127c5d..b66e86dec5 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -991,6 +991,7 @@ set(scipheaders + set(symheaders + symmetry/build_sassy_graph.h + symmetry/compute_symmetry.h ++ symmetry/struct_symmetry.h + symmetry/type_symmetry.h + ) + From 9a29147d41d8b48e34eda94ffb4ac8fa0a0f5b7f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 12:35:34 -0800 Subject: [PATCH 049/191] build/pkgs/soplex: Update to 7.0.0 --- build/pkgs/soplex/checksums.ini | 8 ++++---- build/pkgs/soplex/package-version.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/pkgs/soplex/checksums.ini b/build/pkgs/soplex/checksums.ini index 5689a553333..866f76b3ba9 100644 --- a/build/pkgs/soplex/checksums.ini +++ b/build/pkgs/soplex/checksums.ini @@ -1,5 +1,5 @@ tarball=soplex-VERSION.tar.gz -sha1=6777fa6e7fd02ea6805901dbf60d873b4c312b62 -md5=2865c3a95ee903307d4bd32b0c9594e7 -cksum=278250056 -upstream_url=https://github.com/scipopt/soplex/archive/refs/tags/release-VERSION.tar.gz +sha1=5d0e7fa41b45aa0877134a5b8e261d9608505636 +md5=28be7e9aa5579ccd62cbe492d874ca2a +cksum=232471152 +upstream_url=https://github.com/scipopt/soplex/archive/refs/tags/release-${VERSION_MAJOR}${VERSION_MINOR}${VERSION_MICRO}.tar.gz diff --git a/build/pkgs/soplex/package-version.txt b/build/pkgs/soplex/package-version.txt index 85c3d27e59d..66ce77b7ead 100644 --- a/build/pkgs/soplex/package-version.txt +++ b/build/pkgs/soplex/package-version.txt @@ -1 +1 @@ -602 +7.0.0 From 297cb51b18374fa63caec8f44f12a4dc5f654010 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 12:42:30 -0800 Subject: [PATCH 050/191] build/pkgs/soplex/patches/no_rpath.patch: Remove --- build/pkgs/soplex/patches/no_rpath.patch | 44 ------------------------ 1 file changed, 44 deletions(-) delete mode 100644 build/pkgs/soplex/patches/no_rpath.patch diff --git a/build/pkgs/soplex/patches/no_rpath.patch b/build/pkgs/soplex/patches/no_rpath.patch deleted file mode 100644 index 7cad9b059f7..00000000000 --- a/build/pkgs/soplex/patches/no_rpath.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit 0c2527842fe4eaed8d9e5107d6a6621b3d6a716f -Author: Matthias Koeppe -Date: Sat Nov 26 17:08:40 2022 -0800 - - CMakeLists.txt, src/CMakeLists.txt: Remove hardcoded RPATH settings - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 4f8635fc..6f7a6e1b 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -64,9 +64,6 @@ if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) - endif() - --# set the correct rpath for OS X --set(CMAKE_MACOSX_RPATH ON) -- - # use C++14 standard - set(CMAKE_CXX_STANDARD 14) - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 27d52f14..fd3705ed 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -3,8 +3,7 @@ - # - function(setLibProperties targetname outputname) - set_target_properties(${targetname} PROPERTIES -- OUTPUT_NAME ${outputname} -- MACOSX_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -+ OUTPUT_NAME ${outputname}) - endfunction(setLibProperties) - - include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) -@@ -200,9 +199,6 @@ endif() - add_executable(example EXCLUDE_FROM_ALL example.cpp) - target_link_libraries(example libsoplex) - --# set the install rpath to the installed destination --set_target_properties(soplex PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -- - # install the header files of soplex - install(FILES ${headers} ${PROJECT_BINARY_DIR}/soplex/config.h DESTINATION include/soplex) - install(FILES soplex.h soplex.hpp soplex_interface.h DESTINATION include) From fc3c9a18479a2aa28de6e72ddda438ac82ee23d6 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 1 Mar 2024 17:43:52 +0000 Subject: [PATCH 051/191] Add -Infinity as degree for LaurentPolynomialRing --- src/sage/rings/polynomial/laurent_polynomial.pyx | 12 +++++++++++- .../rings/polynomial/laurent_polynomial_mpair.pyx | 13 ++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 03de4a1179f..b5d5323643e 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -15,6 +15,7 @@ from sage.misc.derivative import multi_derivative from sage.rings.polynomial.polynomial_element import Polynomial from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.structure.richcmp cimport richcmp, rich_to_bool +from sage.rings.infinity import minus_infinity cdef class LaurentPolynomial(CommutativeAlgebraElement): @@ -1018,7 +1019,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): return ret def degree(self): - """ + r""" Return the degree of ``self``. EXAMPLES:: @@ -1030,7 +1031,16 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): sage: g = -10/x^5 + x^2 - x^7 sage: g.degree() 7 + + The zero polynomial is defined to have degree `-\infty`:: + + sage: R. = LaurentPolynomialRing(ZZ) + sage: R.zero().degree() + -Infinity """ + # The zero polynomial is defined to have degree -Infinity + if self.is_zero(): + return minus_infinity return self.__u.degree() + self.__n def __neg__(self): diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index 893b81c87af..c84a34a4a90 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -16,6 +16,7 @@ from sage.structure.factorization import Factorization from sage.misc.derivative import multi_derivative from sage.rings.polynomial.polydict cimport monomial_exponent from sage.matrix.matrix0 cimport Matrix +from sage.rings.infinity import minus_infinity cdef class LaurentPolynomial_mpair(LaurentPolynomial): @@ -1155,7 +1156,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): return [a.eadd(self._mon) for a in self._poly.exponents()] def degree(self, x=None): - """ + r""" Return the degree of ``x`` in ``self``. EXAMPLES:: @@ -1168,7 +1169,17 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): 1 sage: f.degree(z) 0 + + The zero polynomial is defined to have degree `-\infty`:: + + sage: R. = LaurentPolynomialRing(ZZ) + sage: R.zero().degree() + -Infinity """ + # The zero polynomial is defined to have degree -Infinity + if self.is_zero(): + return minus_infinity + if not x: return self._poly.total_degree() + sum(self._mon) From 976ad8c81c5a878d06491afbcaaa54b210df13fe Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Fri, 1 Mar 2024 18:14:32 +0000 Subject: [PATCH 052/191] Improve docstring for degree --- .../polynomial/laurent_polynomial_mpair.pyx | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index c84a34a4a90..3a75f349677 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -1157,12 +1157,15 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): def degree(self, x=None): r""" - Return the degree of ``x`` in ``self``. + Return the degree of ``x`` in ``self``. If ``x`` is ``None`` + then insteads returns the degree of the highest degree term. EXAMPLES:: sage: R. = LaurentPolynomialRing(QQ) sage: f = 4*x^7*z^-1 + 3*x^3*y + 2*x^4*z^-2 + x^6*y^-7 + sage: f.degree() + 6 sage: f.degree(x) 7 sage: f.degree(y) @@ -1172,15 +1175,28 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): The zero polynomial is defined to have degree `-\infty`:: - sage: R. = LaurentPolynomialRing(ZZ) + sage: R. = LaurentPolynomialRing(ZZ) sage: R.zero().degree() -Infinity + sage: R.zero().degree(x) + -Infinity + sage: R.zero().degree(x) == R.zero().degree(y) == R.zero().degree(z) + True + + TESTS:: + + sage: R. = LaurentPolynomialRing(ZZ) + sage: f = x + y + z + sage: f.degree(1) + Traceback (most recent call last): + ... + TypeError: x must be a generator of parent """ # The zero polynomial is defined to have degree -Infinity if self.is_zero(): return minus_infinity - if not x: + if x is None: return self._poly.total_degree() + sum(self._mon) cdef tuple g = self._parent.gens() From b76407e4fbccd28f30a6686223bdee51dff47c4f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Mar 2024 09:49:49 -0800 Subject: [PATCH 053/191] build/pkgs/scip_sdp/spkg-install.in: Use 'ctest --rerun-failed --output-on-failure' --- build/pkgs/scip_sdp/spkg-check.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/pkgs/scip_sdp/spkg-check.in b/build/pkgs/scip_sdp/spkg-check.in index 8df53fc6a36..8ef3bb74f54 100644 --- a/build/pkgs/scip_sdp/spkg-check.in +++ b/build/pkgs/scip_sdp/spkg-check.in @@ -1,3 +1,6 @@ cd src cd build $MAKE test +if [ $? != 0 ]; then + ctest --rerun-failed --output-on-failure +fi From 0563c507a45bcd9dcc6689564f16b9fd0170058f Mon Sep 17 00:00:00 2001 From: adrinospy Date: Mon, 4 Mar 2024 04:31:30 +0530 Subject: [PATCH 054/191] added functionality to ignore blank lines --- .github/workflows/sync_labels.yml | 63 +++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/.github/workflows/sync_labels.yml b/.github/workflows/sync_labels.yml index 56fe526eb8e..d174170d804 100644 --- a/.github/workflows/sync_labels.yml +++ b/.github/workflows/sync_labels.yml @@ -64,3 +64,66 @@ jobs: GITHUB_TOKEN: ${{ env.TOKEN }} REPO_URL: ${{ github.event.repository.html_url }} LOG_LEVEL: ${{ vars.SYNC_LABELS_LOG_LEVEL }} # variable from repository settings, values can be "--debug", "--info" or "--warning" + + # add labels based on size + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Add labels based on size + run: | + git fetch origin ${{ github.base_ref }} + CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) + CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + + # ignore blank lines + CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') + + # count total no of lines + CHANGES=$(echo "$CHANGES" | wc -l) + + echo "CHANGES MADE: $CHANGES" + + MINIMAL_THRESHOLD=50 + + SMALL_THRESHOLD=100 + MODERATE_THRESHOLD=300 + + PR_NUMBER="${{ github.event.number }}" + API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" + AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" + + DELETE_LABELS=("v: minimal" "v: small" "v: moderate" "v: large") + + if [ "$CHANGES" -le "$MINIMAL_THRESHOLD" ]; then + LABEL="v: minimal" + elif [ "$CHANGES" -le "$SMALL_THRESHOLD" ]; then + LABEL="v: small" + elif [ "$CHANGES" -le "$MODERATE_THRESHOLD" ]; then + LABEL="v: moderate" + else + LABEL="v: large" + fi + + DELETE_LABELS=("${DELETE_LABELS[@]//${LABEL}}") + + echo "Adding label: $LABEL" + curl -X POST \ + -H "$AUTH_HEADER" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -d "{\"labels\":[\"$LABEL\"]}" \ + "$API_URL" >/dev/null + + echo "Deleting Labels:" + for DELETE_LABEL in "${DELETE_LABELS[@]}"; do + ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') + curl -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "$AUTH_HEADER" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$API_URL/$ENCODED_LABEL" >/dev/null + done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1b95968aa945727bfad4f63ef36d704c34f61a7b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Mar 2024 18:18:18 -0800 Subject: [PATCH 055/191] build/pkgs/{soplex,scip}: Re-add rebased rpath patches --- ....txt-Remove-hardcoded-RPATH-settings.patch | 46 ++++++++++++++++ ...rc-CMakeLists.txt-Remove-hardcoded-R.patch | 52 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 build/pkgs/scip/patches/0001-CMakeLists.txt-Remove-hardcoded-RPATH-settings.patch create mode 100644 build/pkgs/soplex/patches/0001-CMakeLists.txt-src-CMakeLists.txt-Remove-hardcoded-R.patch diff --git a/build/pkgs/scip/patches/0001-CMakeLists.txt-Remove-hardcoded-RPATH-settings.patch b/build/pkgs/scip/patches/0001-CMakeLists.txt-Remove-hardcoded-RPATH-settings.patch new file mode 100644 index 00000000000..ad9449c59cb --- /dev/null +++ b/build/pkgs/scip/patches/0001-CMakeLists.txt-Remove-hardcoded-RPATH-settings.patch @@ -0,0 +1,46 @@ +From 5a05bcd05b75ca8f6b2228b08f57ff71ba46329b Mon Sep 17 00:00:00 2001 +From: Matthias Koeppe +Date: Sun, 3 Mar 2024 18:15:12 -0800 +Subject: [PATCH] CMakeLists.txt: Remove hardcoded RPATH settings + +--- + src/CMakeLists.txt | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 5392127c5d..995d194aee 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -5,8 +5,7 @@ include(GNUInstallDirs) + + function(setLibProperties targetname outputname) + set_target_properties(${targetname} PROPERTIES +- OUTPUT_NAME ${outputname} +- MACOSX_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") ++ OUTPUT_NAME ${outputname}) + endfunction(setLibProperties) + + set(CMAKE_C_STANDARD 99) +@@ -1118,7 +1117,6 @@ add_dependencies(scip scip_update_githash) + set_target_properties(libscip PROPERTIES + VERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR}.${SCIP_VERSION_PATCH}.${SCIP_VERSION_SUB} + SOVERSION ${SCIP_VERSION_MAJOR}.${SCIP_VERSION_MINOR} +- INSTALL_RPATH_USE_LINK_PATH TRUE + CXX_VISIBILITY_PRESET hidden + C_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN 1) +@@ -1128,11 +1126,6 @@ target_include_directories(scip BEFORE PUBLIC + $ + $) + +-# set the install rpath to the installed destination +-set_target_properties(scip PROPERTIES +- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" +- INSTALL_RPATH_USE_LINK_PATH TRUE) +- + # install the header files of scip + install(FILES ${lpiheaders} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lpi) + install(FILES ${dijkstraheaders} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dijkstra) +-- +2.42.0 + diff --git a/build/pkgs/soplex/patches/0001-CMakeLists.txt-src-CMakeLists.txt-Remove-hardcoded-R.patch b/build/pkgs/soplex/patches/0001-CMakeLists.txt-src-CMakeLists.txt-Remove-hardcoded-R.patch new file mode 100644 index 00000000000..b875781ebc1 --- /dev/null +++ b/build/pkgs/soplex/patches/0001-CMakeLists.txt-src-CMakeLists.txt-Remove-hardcoded-R.patch @@ -0,0 +1,52 @@ +From d96dd5fbfb790ab961243ef2cb5f1d0137e1f8a5 Mon Sep 17 00:00:00 2001 +From: Matthias Koeppe +Date: Sun, 3 Mar 2024 18:09:53 -0800 +Subject: [PATCH] CMakeLists.txt, src/CMakeLists.txt: Remove hardcoded RPATH + settings + +--- + CMakeLists.txt | 3 --- + src/CMakeLists.txt | 6 +----- + 2 files changed, 1 insertion(+), 8 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 25317fc0..310d29a0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -65,9 +65,6 @@ if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) + endif() + +-# set the correct rpath for OS X +-set(CMAKE_MACOSX_RPATH ON) +- + # use C++14 standard + set(CMAKE_CXX_STANDARD 14) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index d259115d..ffdf0435 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -3,8 +3,7 @@ + # + function(setLibProperties targetname outputname) + set_target_properties(${targetname} PROPERTIES +- OUTPUT_NAME ${outputname} +- MACOSX_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") ++ OUTPUT_NAME ${outputname}) + endfunction(setLibProperties) + + include(GNUInstallDirs) +@@ -208,9 +207,6 @@ endif() + add_executable(example EXCLUDE_FROM_ALL example.cpp) + target_link_libraries(example libsoplex) + +-# set the install rpath to the installed destination +-set_target_properties(soplex PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") +- + # install the header files of soplex + install(FILES ${headers} ${PROJECT_BINARY_DIR}/soplex/config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/soplex) + install(FILES soplex.h soplex.hpp soplex_interface.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +-- +2.42.0 + From 0023d7d103be6001ed6311421a75e311b252eb0f Mon Sep 17 00:00:00 2001 From: Giacomo Pope <44242839+GiacomoPope@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:42:42 +0000 Subject: [PATCH 056/191] Update comment to show the degree is the total degree --- src/sage/rings/polynomial/laurent_polynomial_mpair.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index 3a75f349677..51cec89f3c5 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -1157,8 +1157,9 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): def degree(self, x=None): r""" - Return the degree of ``x`` in ``self``. If ``x`` is ``None`` - then insteads returns the degree of the highest degree term. + If ``x`` is ``None``, return the total degreee of ``self``. + Otherwise, if ``x`` is generator of the ring, returns the + degree of ``x`` in ``self``. EXAMPLES:: From 52a0b30a858343df1932c2bc2d0d01e66b344a93 Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Mon, 4 Mar 2024 14:52:03 +0000 Subject: [PATCH 057/191] Reformaty docstring --- .../rings/polynomial/laurent_polynomial_mpair.pyx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index 51cec89f3c5..74b6f57fd7b 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -1157,9 +1157,17 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): def degree(self, x=None): r""" - If ``x`` is ``None``, return the total degreee of ``self``. - Otherwise, if ``x`` is generator of the ring, returns the - degree of ``x`` in ``self``. + Return the degree of ``self``. + + INPUT: + + - ``x`` -- (default: ``None``) a generator of the parent ring + + OUTPUT: + + If ``x`` is ``None``, return the maximum degree of the monomials of + ``self``. If ``x`` is given and it is a generator of the parent + ring, the output is the maximum degree in ``x`` of ``self``. EXAMPLES:: From 171a3804396369b830499f71995a07525a63cbe0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Mar 2024 12:51:36 -0800 Subject: [PATCH 058/191] build/pkgs/pyscipopt: Update to 5.0.0 --- build/pkgs/pyscipopt/checksums.ini | 6 +++--- build/pkgs/pyscipopt/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pyscipopt/checksums.ini b/build/pkgs/pyscipopt/checksums.ini index 5b537d4c57d..1232c25dff5 100644 --- a/build/pkgs/pyscipopt/checksums.ini +++ b/build/pkgs/pyscipopt/checksums.ini @@ -1,5 +1,5 @@ tarball=PySCIPOpt-VERSION.tar.gz -sha1=5ae7f3d7e9d8b344ee9a4413154ae80a5ee137de -md5=32a4dced7e74a1c290b32ef0da751129 -cksum=2258510906 +sha1=713e32cc0ff112500c4f43487614094ece4a8bbf +md5=ee425a362744a4475228510b48781be9 +cksum=1541742154 upstream_url=https://pypi.io/packages/source/p/pyscipopt/PySCIPOpt-VERSION.tar.gz diff --git a/build/pkgs/pyscipopt/package-version.txt b/build/pkgs/pyscipopt/package-version.txt index fdc6698807a..0062ac97180 100644 --- a/build/pkgs/pyscipopt/package-version.txt +++ b/build/pkgs/pyscipopt/package-version.txt @@ -1 +1 @@ -4.4.0 +5.0.0 From d2f7adb875142bc7b7c09a800def67833b1e8fdb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Mar 2024 12:51:55 -0800 Subject: [PATCH 059/191] build/pkgs/pyscipopt/patches/792.patch: Remove --- build/pkgs/pyscipopt/patches/792.patch | 1217 ------------------------ 1 file changed, 1217 deletions(-) delete mode 100644 build/pkgs/pyscipopt/patches/792.patch diff --git a/build/pkgs/pyscipopt/patches/792.patch b/build/pkgs/pyscipopt/patches/792.patch deleted file mode 100644 index faff6076eb4..00000000000 --- a/build/pkgs/pyscipopt/patches/792.patch +++ /dev/null @@ -1,1217 +0,0 @@ -From 96acc6be39b6d153cfcfe7b14741956eaf7f5851 Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Sun, 18 Feb 2024 19:47:52 -0800 -Subject: [PATCH] src/pyscipopt: Add 'noexcept' to functions that use 'with - gil' - ---- - src/pyscipopt/benders.pxi | 30 ++++++++--------- - src/pyscipopt/benderscut.pxi | 14 ++++---- - src/pyscipopt/branchrule.pxi | 18 +++++----- - src/pyscipopt/conshdlr.pxi | 64 ++++++++++++++++++------------------ - src/pyscipopt/cutsel.pxi | 14 ++++---- - src/pyscipopt/event.pxi | 18 +++++----- - src/pyscipopt/heuristic.pxi | 14 ++++---- - src/pyscipopt/nodesel.pxi | 16 ++++----- - src/pyscipopt/presol.pxi | 14 ++++---- - src/pyscipopt/pricer.pxi | 16 ++++----- - src/pyscipopt/propagator.pxi | 22 ++++++------- - src/pyscipopt/reader.pxi | 8 ++--- - src/pyscipopt/relax.pxi | 14 ++++---- - src/pyscipopt/scip.pxd | 2 +- - src/pyscipopt/scip.pxi | 4 +-- - src/pyscipopt/sepa.pxi | 16 ++++----- - 16 files changed, 142 insertions(+), 142 deletions(-) - -diff --git a/src/pyscipopt/benders.pxi b/src/pyscipopt/benders.pxi -index 3e11db189..66a394d8d 100644 ---- a/src/pyscipopt/benders.pxi -+++ b/src/pyscipopt/benders.pxi -@@ -70,10 +70,10 @@ cdef Variable getPyVar(SCIP_VAR* var): - return vardata - - --cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_Bool threadsafe) with gil: -+cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_Bool threadsafe) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -81,56 +81,56 @@ cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) with gil: - Py_DECREF(PyBenders) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersInit (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersInit (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersExit (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersExit (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersInitpre (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersInitpre (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersinitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersExitpre (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersExitpre (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersexitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersInitsol (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersInitsol (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersExitsol (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersExitsol (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersCreatesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) with gil: -+cdef SCIP_RETCODE PyBendersCreatesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.benderscreatesub(probnumber) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint, SCIP_Bool* infeasible, SCIP_Bool* auxviol, SCIP_Bool* skipsolve, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint, SCIP_Bool* infeasible, SCIP_Bool* auxviol, SCIP_Bool* skipsolve, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -146,7 +146,7 @@ cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_ - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Bool onlyconvex, SCIP_Real* objective, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Bool onlyconvex, SCIP_Real* objective, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -159,7 +159,7 @@ cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SC - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Real* objective, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Real* objective, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -174,7 +174,7 @@ cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL - - cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, - SCIP_BENDERSENFOTYPE type, int* mergecands, int npriomergecands, int nmergecands, SCIP_Bool checkint, -- SCIP_Bool infeasible, SCIP_Bool* merged) with gil: -+ SCIP_Bool infeasible, SCIP_Bool* merged) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -190,7 +190,7 @@ cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SO - merged[0] = result_dict.get("merged", False) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) with gil: -+cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -198,7 +198,7 @@ cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probn - return SCIP_OKAY - - #TODO: Really need to ask about the passing and returning of variables --cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber) with gil: -+cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -diff --git a/src/pyscipopt/benderscut.pxi b/src/pyscipopt/benderscut.pxi -index 506a6f065..1ce561a06 100644 ---- a/src/pyscipopt/benderscut.pxi -+++ b/src/pyscipopt/benderscut.pxi -@@ -24,10 +24,10 @@ cdef class Benderscut: - print("python error in benderscutexec: this method needs to be implemented") - return {} - --cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata -@@ -35,35 +35,35 @@ cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) wit - Py_DECREF(PyBenderscut) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata -diff --git a/src/pyscipopt/branchrule.pxi b/src/pyscipopt/branchrule.pxi -index 251aa33b1..2d3411d2c 100644 ---- a/src/pyscipopt/branchrule.pxi -+++ b/src/pyscipopt/branchrule.pxi -@@ -39,10 +39,10 @@ cdef class Branchrule: - - - --cdef SCIP_RETCODE PyBranchruleCopy (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleCopy (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -@@ -50,35 +50,35 @@ cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) wit - Py_DECREF(PyBranchrule) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleInit (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleInit (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExit (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleExit (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleInitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleInitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleExitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -@@ -86,7 +86,7 @@ cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, S - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -@@ -94,7 +94,7 @@ cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, S - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExecps(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBranchruleExecps(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi -index 80c60c17c..1299ad35c 100644 ---- a/src/pyscipopt/conshdlr.pxi -+++ b/src/pyscipopt/conshdlr.pxi -@@ -150,16 +150,16 @@ cdef Constraint getPyCons(SCIP_CONS* cons): - - - --cdef SCIP_RETCODE PyConshdlrCopy (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_Bool* valid) with gil: -+cdef SCIP_RETCODE PyConshdlrCopy (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_Bool* valid) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) with gil: -+cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consfree() - Py_DECREF(PyConshdlr) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -167,7 +167,7 @@ cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c - PyConshdlr.consinit(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -175,7 +175,7 @@ cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c - PyConshdlr.consexit(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -183,7 +183,7 @@ cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consinitpre(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -191,7 +191,7 @@ cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consexitpre(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -199,7 +199,7 @@ cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consinitsol(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) with gil: -+cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -207,7 +207,7 @@ cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consexitsol(constraints, restart) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_CONSDATA** consdata) with gil: -+cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_CONSDATA** consdata) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - assert consdata[0] == PyCons -@@ -216,7 +216,7 @@ cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - Py_DECREF(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* sourcecons, SCIP_CONS** targetcons) with gil: -+cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* sourcecons, SCIP_CONS** targetcons) noexcept with gil: - cdef Constraint PyTargetCons - PyConshdlr = getPyConshdlr(conshdlr) - PySourceCons = getPyCons(sourcecons) -@@ -235,7 +235,7 @@ cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* s - PySourceCons.isRemovable(), PySourceCons.isStickingAtNode())) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) with gil: -+cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -244,7 +244,7 @@ cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - infeasible[0] = result_dict.get("infeasible", infeasible[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -254,7 +254,7 @@ cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, -- SCIP_SOL* sol, SCIP_RESULT* result) with gil: -+ SCIP_SOL* sol, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -265,7 +265,7 @@ cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, -- SCIP_Bool solinfeasible, SCIP_RESULT* result) with gil: -+ SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -274,7 +274,7 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -285,7 +285,7 @@ cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* con - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, -- SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) with gil: -+ SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -295,7 +295,7 @@ cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_SOL* sol, SCIP_Bool checkintegrality, -- SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) with gil: -+ SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -306,7 +306,7 @@ cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsProp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, int nmarkedconss, -- SCIP_PROPTIMING proptiming, SCIP_RESULT* result) with gil: -+ SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -319,7 +319,7 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, - int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, - int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, -- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: -+ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -354,12 +354,12 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsResprop (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR* infervar, int inferinfo, -- SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) with gil: -+ SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consresprop() - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) with gil: -+cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - if cons == NULL: - PyConshdlr.conslock(None, locktype, nlockspos, nlocksneg) -@@ -368,31 +368,31 @@ cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* co - PyConshdlr.conslock(PyCons, locktype, nlockspos, nlocksneg) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsActive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsActive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consactive(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDeactive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsDeactive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consdeactive(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsEnable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsEnable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consenable(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consdisable(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -400,7 +400,7 @@ cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consdelvars(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsPrint (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, FILE* file) with gil: -+cdef SCIP_RETCODE PyConsPrint (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, FILE* file) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - # TODO: pass file -@@ -411,7 +411,7 @@ cdef SCIP_RETCODE PyConsCopy (SCIP* scip, SCIP_CONS** cons, const char* name, SC - SCIP_CONS* sourcecons, SCIP_HASHMAP* varmap, SCIP_HASHMAP* consmap, SCIP_Bool initial, - SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, - SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, -- SCIP_Bool isglobal, SCIP_Bool* valid) with gil: -+ SCIP_Bool isglobal, SCIP_Bool* valid) noexcept with gil: - # TODO everything! - PyConshdlr = getPyConshdlr(sourceconshdlr) - PyConshdlr.conscopy() -@@ -421,14 +421,14 @@ cdef SCIP_RETCODE PyConsCopy (SCIP* scip, SCIP_CONS** cons, const char* name, SC - cdef SCIP_RETCODE PyConsParse (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cons, const char* name, const char* str, - SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, - SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, -- SCIP_Bool stickingatnode, SCIP_Bool* success) with gil: -+ SCIP_Bool stickingatnode, SCIP_Bool* success) noexcept with gil: - # TODO everything! - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consparse() - success[0] = False - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success) with gil: -+cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success) noexcept with gil: - # TODO - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) -@@ -436,7 +436,7 @@ cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - success[0] = False - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success) with gil: -+cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - result_dict = PyConshdlr.consgetnvars(PyCons) -@@ -445,7 +445,7 @@ cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsGetdivebdchgs (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_DIVESET* diveset, SCIP_SOL* sol, -- SCIP_Bool* success, SCIP_Bool* infeasible) with gil: -+ SCIP_Bool* success, SCIP_Bool* infeasible) noexcept with gil: - # TODO - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consgetdivebdchgs() -diff --git a/src/pyscipopt/cutsel.pxi b/src/pyscipopt/cutsel.pxi -index e953cb1e9..d259fb28e 100644 ---- a/src/pyscipopt/cutsel.pxi -+++ b/src/pyscipopt/cutsel.pxi -@@ -29,10 +29,10 @@ cdef class Cutsel: - return {} - - --cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata -@@ -40,7 +40,7 @@ cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: - Py_DECREF(PyCutsel) - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata -@@ -48,21 +48,21 @@ cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: - return SCIP_OKAY - - --cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata - PyCutsel.cutselexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata - PyCutsel.cutselinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata -@@ -71,7 +71,7 @@ cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: - - cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts, - SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts, -- int* nselectedcuts, SCIP_RESULT* result) with gil: -+ int* nselectedcuts, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cdef SCIP_ROW* scip_row - cutseldata = SCIPcutselGetData(cutsel) -diff --git a/src/pyscipopt/event.pxi b/src/pyscipopt/event.pxi -index 95c8bc1f4..914e882ed 100644 ---- a/src/pyscipopt/event.pxi -+++ b/src/pyscipopt/event.pxi -@@ -39,48 +39,48 @@ cdef class Eventhdlr: - - - # local helper functions for the interface --cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - cdef SCIP_EVENTHDLRDATA* eventhdlrdata - eventhdlrdata = SCIPeventhdlrGetData(eventhdlr) - return eventhdlrdata - --cdef SCIP_RETCODE PyEventCopy (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventCopy (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventcopy() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventFree (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventFree (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventfree() - Py_DECREF(PyEventhdlr) - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventInit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventInit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventExit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventExit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventInitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventInitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventExitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventExitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventDelete (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA** eventdata) with gil: -+cdef SCIP_RETCODE PyEventDelete (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA** eventdata) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventdelete() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventExec (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENT* event, SCIP_EVENTDATA* eventdata) with gil: -+cdef SCIP_RETCODE PyEventExec (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENT* event, SCIP_EVENTDATA* eventdata) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEvent = Event() - PyEvent.event = event -diff --git a/src/pyscipopt/heuristic.pxi b/src/pyscipopt/heuristic.pxi -index 2980a1aee..930315630 100644 ---- a/src/pyscipopt/heuristic.pxi -+++ b/src/pyscipopt/heuristic.pxi -@@ -31,10 +31,10 @@ cdef class Heur: - - - --cdef SCIP_RETCODE PyHeurCopy (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurCopy (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata -@@ -42,35 +42,35 @@ cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) with gil: - Py_DECREF(PyHeur) - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurInit (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurInit (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurExit (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurExit (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurInitsol (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurInitsol (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurExitsol (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurExitsol (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurExec (SCIP* scip, SCIP_HEUR* heur, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyHeurExec (SCIP* scip, SCIP_HEUR* heur, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata -diff --git a/src/pyscipopt/nodesel.pxi b/src/pyscipopt/nodesel.pxi -index 4d795bc9d..a3e832f15 100644 ---- a/src/pyscipopt/nodesel.pxi -+++ b/src/pyscipopt/nodesel.pxi -@@ -42,10 +42,10 @@ cdef class Nodesel: - return 0 - - --cdef SCIP_RETCODE PyNodeselCopy (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselCopy (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -@@ -53,7 +53,7 @@ cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) with gil: - Py_DECREF(PyNodesel) - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -@@ -61,28 +61,28 @@ cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: - return SCIP_OKAY - - --cdef SCIP_RETCODE PyNodeselExit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselExit (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata - PyNodesel.nodeexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselInitsol (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselInitsol (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata - PyNodesel.nodeinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselExitsol (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselExitsol (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata - PyNodesel.nodeexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE** selnode) with gil: -+cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE** selnode) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -@@ -91,7 +91,7 @@ cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* - selnode[0] = selected_node.scip_node - return SCIP_OKAY - --cdef int PyNodeselComp (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* node1, SCIP_NODE* node2) with gil: -+cdef int PyNodeselComp (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* node1, SCIP_NODE* node2) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -diff --git a/src/pyscipopt/presol.pxi b/src/pyscipopt/presol.pxi -index d2b9115a5..13bd9a623 100644 ---- a/src/pyscipopt/presol.pxi -+++ b/src/pyscipopt/presol.pxi -@@ -30,10 +30,10 @@ cdef class Presol: - - - --cdef SCIP_RETCODE PyPresolCopy (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolCopy (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -@@ -41,14 +41,14 @@ cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) with gil: - Py_DECREF(PyPresol) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolInit (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolInit (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata - PyPresol.presolinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -@@ -56,14 +56,14 @@ cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) with gil: - return SCIP_OKAY - - --cdef SCIP_RETCODE PyPresolInitpre (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolInitpre (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata - PyPresol.presolinitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolExitpre (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolExitpre (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -@@ -74,7 +74,7 @@ cdef SCIP_RETCODE PyPresolExec (SCIP* scip, SCIP_PRESOL* presol, int nrounds, SC - int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, - int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, - int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, -- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: -+ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -diff --git a/src/pyscipopt/pricer.pxi b/src/pyscipopt/pricer.pxi -index 1368572de..a218b254c 100644 ---- a/src/pyscipopt/pricer.pxi -+++ b/src/pyscipopt/pricer.pxi -@@ -33,10 +33,10 @@ cdef class Pricer: - - - --cdef SCIP_RETCODE PyPricerCopy (SCIP* scip, SCIP_PRICER* pricer, SCIP_Bool* valid) with gil: -+cdef SCIP_RETCODE PyPricerCopy (SCIP* scip, SCIP_PRICER* pricer, SCIP_Bool* valid) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata -@@ -44,35 +44,35 @@ cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) with gil: - Py_DECREF(PyPricer) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerInit (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerInit (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerExit (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerExit (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerInitsol (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerInitsol (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerExitsol (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerExitsol (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* lowerbound, SCIP_Bool* stopearly, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* lowerbound, SCIP_Bool* stopearly, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata -@@ -82,7 +82,7 @@ cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* l - stopearly[0] = result_dict.get("stopearly", stopearly[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerFarkas (SCIP* scip, SCIP_PRICER* pricer, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyPricerFarkas (SCIP* scip, SCIP_PRICER* pricer, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata -diff --git a/src/pyscipopt/propagator.pxi b/src/pyscipopt/propagator.pxi -index d792577d9..4508efe78 100644 ---- a/src/pyscipopt/propagator.pxi -+++ b/src/pyscipopt/propagator.pxi -@@ -47,10 +47,10 @@ cdef class Prop: - - - --cdef SCIP_RETCODE PyPropCopy (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropCopy (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -58,42 +58,42 @@ cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) with gil: - Py_DECREF(PyProp) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropInit (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropInit (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExit (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropExit (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropInitpre (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropInitpre (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propinitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExitpre (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropExitpre (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propexitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropInitsol (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropInitsol (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExitsol (SCIP* scip, SCIP_PROP* prop, SCIP_Bool restart) with gil: -+cdef SCIP_RETCODE PyPropExitsol (SCIP* scip, SCIP_PROP* prop, SCIP_Bool restart) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -104,7 +104,7 @@ cdef SCIP_RETCODE PyPropPresol (SCIP* scip, SCIP_PROP* prop, int nrounds, SCIP_P - int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, - int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, - int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, -- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: -+ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -137,7 +137,7 @@ cdef SCIP_RETCODE PyPropPresol (SCIP* scip, SCIP_PROP* prop, int nrounds, SCIP_P - nchgsides[0] = result_dict["nchgsides"] - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -147,7 +147,7 @@ cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING propt - return SCIP_OKAY - - cdef SCIP_RETCODE PyPropResProp (SCIP* scip, SCIP_PROP* prop, SCIP_VAR* infervar, int inferinfo, -- SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) with gil: -+ SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PROPDATA* propdata - cdef SCIP_VAR* tmp - tmp = infervar -diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi -index df0b3a288..2c45585d6 100644 ---- a/src/pyscipopt/reader.pxi -+++ b/src/pyscipopt/reader.pxi -@@ -18,10 +18,10 @@ cdef class Reader: - return {} - - --cdef SCIP_RETCODE PyReaderCopy (SCIP* scip, SCIP_READER* reader) with gil: -+cdef SCIP_RETCODE PyReaderCopy (SCIP* scip, SCIP_READER* reader) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) with gil: -+cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) noexcept with gil: - cdef SCIP_READERDATA* readerdata - readerdata = SCIPreaderGetData(reader) - PyReader = readerdata -@@ -29,7 +29,7 @@ cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) with gil: - Py_DECREF(PyReader) - return SCIP_OKAY - --cdef SCIP_RETCODE PyReaderRead (SCIP* scip, SCIP_READER* reader, const char* filename, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyReaderRead (SCIP* scip, SCIP_READER* reader, const char* filename, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_READERDATA* readerdata - readerdata = SCIPreaderGetData(reader) - PyReader = readerdata -@@ -44,7 +44,7 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, - SCIP_VAR** vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, - SCIP_VAR** fixedvars, int nfixedvars, int startnvars, - SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, -- SCIP_Bool genericnames, SCIP_RESULT* result) with gil: -+ SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_READERDATA* readerdata - readerdata = SCIPreaderGetData(reader) - cdef int fd = fileno(file) -diff --git a/src/pyscipopt/relax.pxi b/src/pyscipopt/relax.pxi -index 2b52c2643..81695e8bb 100644 ---- a/src/pyscipopt/relax.pxi -+++ b/src/pyscipopt/relax.pxi -@@ -30,10 +30,10 @@ cdef class Relax: - return{} - - --cdef SCIP_RETCODE PyRelaxCopy (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxCopy (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata -@@ -41,35 +41,35 @@ cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) with gil: - Py_DECREF(PyRelax) - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxInit (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxInit (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxExit (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxExit (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxInitsol (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxInitsol (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxExitsol (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxExitsol (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_RELAX* relax, SCIP_Real* lowerbound, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_RELAX* relax, SCIP_Real* lowerbound, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata -diff --git a/src/pyscipopt/scip.pxd b/src/pyscipopt/scip.pxd -index 12815dbc4..f35a42486 100644 ---- a/src/pyscipopt/scip.pxd -+++ b/src/pyscipopt/scip.pxd -@@ -501,7 +501,7 @@ cdef extern from "scip/scip.h": - ctypedef union SCIP_DOMCHG: - pass - -- ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) -+ ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept - ctypedef void (*errormessagecallback) (void *data, FILE *file, const char *msg) - ctypedef SCIP_RETCODE (*messagehdlrfree) (SCIP_MESSAGEHDLR *messagehdlr) - -diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi -index 0b2332d88..552197785 100644 ---- a/src/pyscipopt/scip.pxi -+++ b/src/pyscipopt/scip.pxi -@@ -975,10 +975,10 @@ cdef class Constraint: - and self.scip_cons == (other).scip_cons) - - --cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg): -+cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept: - sys.stdout.write(msg.decode('UTF-8')) - --cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg): -+cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg) noexcept: - sys.stderr.write(msg.decode('UTF-8')) - - # - remove create(), includeDefaultPlugins(), createProbBasic() methods -diff --git a/src/pyscipopt/sepa.pxi b/src/pyscipopt/sepa.pxi -index 271945db1..94355a7d2 100644 ---- a/src/pyscipopt/sepa.pxi -+++ b/src/pyscipopt/sepa.pxi -@@ -34,10 +34,10 @@ cdef class Sepa: - - - --cdef SCIP_RETCODE PySepaCopy (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaCopy (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata -@@ -45,35 +45,35 @@ cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) with gil: - Py_DECREF(PySepa) - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaInit (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaInit (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepainit() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExit (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaExit (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepaexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaInitsol (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaInitsol (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepainitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExitsol (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaExitsol (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepaexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result, unsigned int allowlocal, int depth) with gil: -+cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result, unsigned int allowlocal, int depth) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata -@@ -81,7 +81,7 @@ cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExecsol (SCIP* scip, SCIP_SEPA* sepa, SCIP_SOL* sol, SCIP_RESULT* result, unsigned int allowlocal, int depth) with gil: -+cdef SCIP_RETCODE PySepaExecsol (SCIP* scip, SCIP_SEPA* sepa, SCIP_SOL* sol, SCIP_RESULT* result, unsigned int allowlocal, int depth) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - solution = Solution.create(scip, sol) From 961a7c448f74ff677f25110257e76246b4c2853b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Mar 2024 17:44:49 -0800 Subject: [PATCH 060/191] build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch: Remove --- ...c73ca4d359621202399cc0c3c91058e56e79.patch | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch diff --git a/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch b/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch deleted file mode 100644 index a2e4d939311..00000000000 --- a/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch +++ /dev/null @@ -1,36 +0,0 @@ -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 { From 615db2334f5cbe4ffc9c07d6be61627631c79f4c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Mar 2024 22:02:43 -0800 Subject: [PATCH 061/191] src/sage/numerical/backends/scip_backend.pyx: Fix typo in doctest --- src/sage/numerical/backends/scip_backend.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/numerical/backends/scip_backend.pyx b/src/sage/numerical/backends/scip_backend.pyx index 1ae54f483aa..8e7d7fd1685 100644 --- a/src/sage/numerical/backends/scip_backend.pyx +++ b/src/sage/numerical/backends/scip_backend.pyx @@ -1274,7 +1274,7 @@ cdef class SCIPBackend(GenericBackend): EXAMPLES: sage: from sage.numerical.backends.generic_backend import get_solver - sage: lp = get_solver(solver="SCIP") + sage: p = get_solver(solver="SCIP") sage: p.solver_parameter("limits/time", 1) sage: p.solver_parameter("limits/time") 1.0 From 6dd48d7bd6fd9352477ba45e1da062609c7aba8a Mon Sep 17 00:00:00 2001 From: Giacomo Pope <44242839+GiacomoPope@users.noreply.github.com> Date: Thu, 7 Mar 2024 21:50:30 +0000 Subject: [PATCH 062/191] Update src/sage/rings/polynomial/laurent_polynomial_mpair.pyx Co-authored-by: Travis Scrimshaw --- src/sage/rings/polynomial/laurent_polynomial_mpair.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index 74b6f57fd7b..93fd74fcda9 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -1165,9 +1165,9 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): OUTPUT: - If ``x`` is ``None``, return the maximum degree of the monomials of - ``self``. If ``x`` is given and it is a generator of the parent - ring, the output is the maximum degree in ``x`` of ``self``. + If ``x`` is ``None``, return the total degree of ``self``. + If ``x`` is a given generator of the parent ring, + the output is the maximum degree of ``x`` in ``self``. EXAMPLES:: From da0903d961e3d878bf990d32d8a9a3a9dd561d5b Mon Sep 17 00:00:00 2001 From: adrinospy Date: Tue, 12 Mar 2024 12:27:58 +0530 Subject: [PATCH 063/191] no of changes depends on repo variable and checks if repo variables exists --- .github/workflows/pr-labeler.yml | 73 +++++++++++++++++++------------ .github/workflows/sync_labels.yml | 63 -------------------------- 2 files changed, 46 insertions(+), 90 deletions(-) diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index b4f3c76e3f3..3b5c28cf478 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -1,48 +1,67 @@ -# set labels on Pull-Requests based on size of changes -# size is compared form first to last commit in the pull request name: Size Labeler/Checker on: pull_request_target: types: - opened - synchronize + - edited jobs: label-changes: runs-on: ubuntu-latest permissions: pull-requests: write steps: - - name: Check changes and label - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - CHANGES=$((${{github.event.pull_request.additions}} + ${{github.event.pull_request.deletions}})) - echo "Changes Made: $CHANGES" - - MINIMAL_THRESHOLD=50 - SMALL_THRESHOLD=100 - MODERATE_THRESHOLD=300 + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Add labels based on size + run: | + if [[ -z "${{ vars.SMALL_THRESHOLD }}" || -z "${{ vars.MODERATE_THRESHOLD }}" || -z "${{ vars.LARGE_THRESHOLD }}" ]]; then + echo "One or more environment variables are not set." + exit 1 + fi + git fetch origin ${{ github.base_ref }} + CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) + CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + # ignore blank lines + CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') + # count total no of lines + CHANGES=$(echo "$CHANGES" | wc -l) + echo "CHANGES MADE: $CHANGES" + SMALL_THRESHOLD=${{vars.SMALL_THRESHOLD}} + MODERATE_THRESHOLD=${{vars.MODERATE_THRESHOLD}} + LARGE_THRESHOLD=${{vars.LARGE_THRESHOLD}} PR_NUMBER="${{ github.event.number }}" API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" - - DELETE_LABELS=("minimal" "small" "moderate" "large") - - if [ "$CHANGES" -le "$MINIMAL_THRESHOLD" ]; then - LABEL="minimal" - elif [ "$CHANGES" -le "$SMALL_THRESHOLD" ]; then - LABEL="small" - elif [ "$CHANGES" -le "$MODERATE_THRESHOLD" ]; then - LABEL="moderate" + DELETE_LABELS=("v: minimal" "v: small" "v: moderate" "v: large") + if [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then + LABEL="v: small" + elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then + LABEL="v: moderate" + elif [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then + LABEL="v: large" else - LABEL="large" + LABEL="v: minimal" fi - - DELETE_LABELS=("${DELETE_LABELS[@]/$LABEL}") - + DELETE_LABELS=("${DELETE_LABELS[@]//${LABEL}}") echo "Adding label: $LABEL" - curl -X POST -H "$AUTH_HEADER" -d "{\"labels\":[\"$LABEL\"]}" "$API_URL" + curl -X POST \ + -H "$AUTH_HEADER" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -d "{\"labels\":[\"$LABEL\"]}" \ + "$API_URL" >/dev/null + echo "Deleting Labels:" for DELETE_LABEL in "${DELETE_LABELS[@]}"; do - curl -X DELETE -H "$AUTH_HEADER" "$API_URL/$DELETE_LABEL" + ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') + curl -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "$AUTH_HEADER" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$API_URL/$ENCODED_LABEL" >/dev/null done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/sync_labels.yml b/.github/workflows/sync_labels.yml index d174170d804..56fe526eb8e 100644 --- a/.github/workflows/sync_labels.yml +++ b/.github/workflows/sync_labels.yml @@ -64,66 +64,3 @@ jobs: GITHUB_TOKEN: ${{ env.TOKEN }} REPO_URL: ${{ github.event.repository.html_url }} LOG_LEVEL: ${{ vars.SYNC_LABELS_LOG_LEVEL }} # variable from repository settings, values can be "--debug", "--info" or "--warning" - - # add labels based on size - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Add labels based on size - run: | - git fetch origin ${{ github.base_ref }} - CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) - CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') - - # ignore blank lines - CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') - - # count total no of lines - CHANGES=$(echo "$CHANGES" | wc -l) - - echo "CHANGES MADE: $CHANGES" - - MINIMAL_THRESHOLD=50 - - SMALL_THRESHOLD=100 - MODERATE_THRESHOLD=300 - - PR_NUMBER="${{ github.event.number }}" - API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" - AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" - - DELETE_LABELS=("v: minimal" "v: small" "v: moderate" "v: large") - - if [ "$CHANGES" -le "$MINIMAL_THRESHOLD" ]; then - LABEL="v: minimal" - elif [ "$CHANGES" -le "$SMALL_THRESHOLD" ]; then - LABEL="v: small" - elif [ "$CHANGES" -le "$MODERATE_THRESHOLD" ]; then - LABEL="v: moderate" - else - LABEL="v: large" - fi - - DELETE_LABELS=("${DELETE_LABELS[@]//${LABEL}}") - - echo "Adding label: $LABEL" - curl -X POST \ - -H "$AUTH_HEADER" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - -d "{\"labels\":[\"$LABEL\"]}" \ - "$API_URL" >/dev/null - - echo "Deleting Labels:" - for DELETE_LABEL in "${DELETE_LABELS[@]}"; do - ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') - curl -X DELETE \ - -H "Accept: application/vnd.github+json" \ - -H "$AUTH_HEADER" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "$API_URL/$ENCODED_LABEL" >/dev/null - done - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From dc7d14e2355255325039f639a97293ac535d0fc0 Mon Sep 17 00:00:00 2001 From: adrinospy Date: Tue, 12 Mar 2024 12:32:22 +0530 Subject: [PATCH 064/191] made code redable --- .github/workflows/pr-labeler.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 3b5c28cf478..214b9b19abe 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -18,25 +18,33 @@ jobs: - name: Add labels based on size run: | - if [[ -z "${{ vars.SMALL_THRESHOLD }}" || -z "${{ vars.MODERATE_THRESHOLD }}" || -z "${{ vars.LARGE_THRESHOLD }}" ]]; then + if [[ -z "${{ vars.SMALL_THRESHOLD }}" || -z "${{ vars.MODERATE_THRESHOLD }}" || -z "${{ vars.LARGE_THRESHOLD }}"]]; then echo "One or more environment variables are not set." exit 1 fi git fetch origin ${{ github.base_ref }} CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) + CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + # ignore blank lines CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') + # count total no of lines CHANGES=$(echo "$CHANGES" | wc -l) + echo "CHANGES MADE: $CHANGES" + SMALL_THRESHOLD=${{vars.SMALL_THRESHOLD}} MODERATE_THRESHOLD=${{vars.MODERATE_THRESHOLD}} LARGE_THRESHOLD=${{vars.LARGE_THRESHOLD}} + PR_NUMBER="${{ github.event.number }}" API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" + DELETE_LABELS=("v: minimal" "v: small" "v: moderate" "v: large") + if [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then LABEL="v: small" elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then @@ -46,7 +54,9 @@ jobs: else LABEL="v: minimal" fi + DELETE_LABELS=("${DELETE_LABELS[@]//${LABEL}}") + echo "Adding label: $LABEL" curl -X POST \ -H "$AUTH_HEADER" \ @@ -54,7 +64,9 @@ jobs: -H "X-GitHub-Api-Version: 2022-11-28" \ -d "{\"labels\":[\"$LABEL\"]}" \ "$API_URL" >/dev/null + echo "Deleting Labels:" + for DELETE_LABEL in "${DELETE_LABELS[@]}"; do ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') curl -X DELETE \ From cdf4d0b0c67afdbc7563740d4e75951009a05a0d Mon Sep 17 00:00:00 2001 From: adrinospy Date: Mon, 18 Mar 2024 02:24:04 +0530 Subject: [PATCH 065/191] adding labels of file changed --- .github/workflows/pr-labeler.yml | 52 ++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 214b9b19abe..91bd5fdc21f 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -1,3 +1,5 @@ +# This action automatically labels Pull-Requests +# based on files edited and no of lines changed. name: Size Labeler/Checker on: pull_request_target: @@ -18,27 +20,23 @@ jobs: - name: Add labels based on size run: | - if [[ -z "${{ vars.SMALL_THRESHOLD }}" || -z "${{ vars.MODERATE_THRESHOLD }}" || -z "${{ vars.LARGE_THRESHOLD }}"]]; then - echo "One or more environment variables are not set." - exit 1 - fi git fetch origin ${{ github.base_ref }} - CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) - CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + # get all the changes made and changed files + CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) + CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | awk -F'src/sage/' '{print $2}' | cut -d'/' -f1 | sed 's/\([^ ]\+\)/c: \1/g') # ignore blank lines CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') + # ignore non necessary lines from git diff + CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + # count total no of lines CHANGES=$(echo "$CHANGES" | wc -l) echo "CHANGES MADE: $CHANGES" - SMALL_THRESHOLD=${{vars.SMALL_THRESHOLD}} - MODERATE_THRESHOLD=${{vars.MODERATE_THRESHOLD}} - LARGE_THRESHOLD=${{vars.LARGE_THRESHOLD}} - PR_NUMBER="${{ github.event.number }}" API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" @@ -46,24 +44,29 @@ jobs: DELETE_LABELS=("v: minimal" "v: small" "v: moderate" "v: large") if [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then - LABEL="v: small" + SIZE_LABEL="v: small" elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then - LABEL="v: moderate" + SIZE_LABEL="v: moderate" elif [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then - LABEL="v: large" + SIZE_LABEL="v: large" else - LABEL="v: minimal" + SIZE_LABEL="v: minimal" fi - DELETE_LABELS=("${DELETE_LABELS[@]//${LABEL}}") + DELETE_LABELS=("${DELETE_LABELS[@]//${SIZE_LABEL}}") - echo "Adding label: $LABEL" - curl -X POST \ - -H "$AUTH_HEADER" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - -d "{\"labels\":[\"$LABEL\"]}" \ - "$API_URL" >/dev/null + readarray -t LABELS <<< "$CHANGED_FILES" + LABELS+=("$SIZE_LABEL") + + echo "Adding label: ${LABELS[@]}" + for LABEL in "${LABELS[@]}"; do + curl -X POST \ + -H "$AUTH_HEADER" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -d "{\"labels\":[\"$LABEL\"]}" \ + "$API_URL" >/dev/null + done echo "Deleting Labels:" @@ -76,4 +79,7 @@ jobs: "$API_URL/$ENCODED_LABEL" >/dev/null done env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SMALL_THRESHOLD: ${{ vars.SMALL_THRESHOLD }} + MODERATE_THRESHOLD: ${{ vars.MODERATE_THRESHOLD }} + LARGE_THRESHOLD: ${{ vars.LARGE_THRESHOLD }} From b21fa3b1d08d2c052c85cb2fb595ef41641632e7 Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Mon, 25 Mar 2024 23:06:26 +0100 Subject: [PATCH 066/191] Removed redundant calculations... ... and small refactoring of code --- .../algebras/quatalg/quaternion_algebra.py | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index d2c9de90176..4692d5a7075 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -768,17 +768,21 @@ def maximal_order(self, take_shortcuts=True): TESTS: - We check that :issue:`37417` and the first part of :issue:`37217` are fixed:: - - sage: invars = [(-4, -28), (-292, -732), (-48, -564), (-436, -768), (-752, -708), - ....: (885, 545), (411, -710), (-411, 593), (805, -591), (-921, 353), - ....: (409, 96), (394, 873), (353, -722), (730, 830), (-466, -427), (-213, -630), - ....: (-511, 608), (493, 880), (105, -709), (-213, 530), (97, 745)] - sage: all(QuaternionAlgebra(a, b).maximal_order().is_maximal() for (a, b) in invars) + Check that :issue:`37417` and the first part of :issue:`37217` are fixed:: + + sage: invars = [(-4, -28), (-292, -732), (-48, -564), (-436, -768), + ....: (-752, -708), (885, 545), (411, -710), (-411, 593), + ....: (805, -591), (-921, 353), (409, 96), (394, 873), + ....: (353, -722), (730, 830), (-466, -427), (-213, -630), + ....: (-511, 608), (493, 880), (105, -709), (-213, 530), + ....: (97, 745)] + sage: all(QuaternionAlgebra(a, b).maximal_order().is_maximal() + ....: for (a, b) in invars) True """ if self.base_ring() != QQ: - raise NotImplementedError("maximal order only implemented for rational quaternion algebras") + raise NotImplementedError("maximal order only implemented for" + " rational quaternion algebras") d_A = self.discriminant() @@ -821,15 +825,16 @@ def maximal_order(self, take_shortcuts=True): # The following code should always work (over QQ) # Start with <1,i,j,k> - R = self.quaternion_order((1,) + self.gens()) + order_basis = (self.one(),) + self.gens() + R = self.quaternion_order(order_basis) d_R = R.discriminant() e_new_gens = [] # For each prime at which R is not yet maximal, make it bigger for p, _ in d_R.factor(): - e = R.basis() - disc = self.quaternion_order(e).discriminant() + e = order_basis + disc = d_R while disc.valuation(p) > d_A.valuation(p): # Compute a normalized basis at p f = normalize_basis_at_p(list(e), p) @@ -903,12 +908,12 @@ def maximal_order(self, take_shortcuts=True): e_n = basis_for_quaternion_lattice(list(e) + e_n[1:], reverse=True) # e_n now contains elements that locally at p give a bigger order, - # but the basis may be messed up at other primes (it might not even - # be an order). We will join them all together at the end + # but the basis may be messed up at other primes (it might not + # even be an order). We will join them all together at the end e = e_n - # Since e might not define an order at this point, we need to manually - # calculate the updated discriminant + # Since e might not define an order at this point, we need to + # manually calculate the updated discriminant L = [] for x in e: MM = [] From 4e8e363e2e64334f8711b380f064bf6d2d8d1dd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 23:48:20 +0000 Subject: [PATCH 067/191] :arrow_up: Bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-conda.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 1bb08637099..996c46cb95e 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -54,7 +54,7 @@ jobs: SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }} - name: Cache conda packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/conda_pkgs_dir key: From 84b045370058cc1411b890ad02bb1d760dbe4a3b Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Tue, 26 Mar 2024 00:08:17 +0100 Subject: [PATCH 068/191] Extend `.maximal_order` to allow for base order --- .../algebras/quatalg/quaternion_algebra.py | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 4692d5a7075..c4452867966 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -687,14 +687,19 @@ def __init__(self, base_ring, a, b, names='i,j,k'): self._gens = (self([0, 1, 0, 0]), self([0, 0, 1, 0]), self([0, 0, 0, 1])) @cached_method - def maximal_order(self, take_shortcuts=True): + def maximal_order(self, order_basis=None, take_shortcuts=True): r""" Return a maximal order in this quaternion algebra. - The algorithm used is from [Voi2012]_. + If ``order_basis`` is specified, the resulting maximal order + will contain the quaternion order of ``self`` given by this + basis. The algorithm used is from [Voi2012]_. INPUT: + - ``order_basis`` -- (optional, default: ``None``) a basis of a + quaternion order of ``self`` + - ``take_shortcuts`` -- (default: ``True``) if the discriminant is prime and the invariants of the algebra are of a nice form, use Proposition 5.2 of [Piz1980]_. @@ -791,7 +796,8 @@ def maximal_order(self, take_shortcuts=True): # (every quaternion algebra of prime discriminant has a representation # of such a form though) a, b = self.invariants() - if take_shortcuts and d_A.is_prime() and a in ZZ and b in ZZ: + if (not order_basis and take_shortcuts and d_A.is_prime() + and a in ZZ and b in ZZ): a = ZZ(a) b = ZZ(b) i, j, k = self.gens() @@ -824,10 +830,20 @@ def maximal_order(self, take_shortcuts=True): return self.quaternion_order(basis) # The following code should always work (over QQ) - # Start with <1,i,j,k> - order_basis = (self.one(),) + self.gens() - R = self.quaternion_order(order_basis) - d_R = R.discriminant() + # If no order basis is given, start with <1,i,j,k> + if not order_basis: + order_basis = (self.one(),) + self.gens() + + try: + R = self.quaternion_order(order_basis) + d_R = R.discriminant() + except (TypeError, ValueError): + raise ValueError('order_basis is not a basis of an order of the' + ' given quaternion algebra') + + if order_basis[0] not in ZZ: + raise Warning('the algorithm might not work if the' + ' first basis vector is not an integer') e_new_gens = [] From 3672d91b693a4e76e82eef9913535354968ad69d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Mar 2024 11:24:35 -0800 Subject: [PATCH 069/191] MatrixSpace: When row_keys or column_keys are given, use Hom(CombinatorialFreeModule) --- src/sage/matrix/matrix_space.py | 186 ++++++++++++++++++++------------ 1 file changed, 117 insertions(+), 69 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 7f93cceb6ad..a3336a846b9 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -434,9 +434,78 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): class MatrixSpace(UniqueRepresentation, Parent): """ - The space of matrices of given size and base ring + The space of matrices of given size and base ring. - EXAMPLES: + INPUT: + + - ``base_ring`` -- a ring + + - ``nrows`` -- (nonnegative integer) the number of rows + + - ``row_keys`` -- a finite or enumerated family of arbitrary objects + that index the rows of the matrix + + - ``ncols`` -- (nonnegative integer, default ``nrows``) the number of + columns + + - ``column_keys`` -- a finite or enumerated family of arbitrary objects + that index the columns of the matrix + + - ``sparse`` -- (boolean, default ``False``) whether or not matrices + are given a sparse representation + + - ``implementation`` -- (optional, a string or a matrix class) a possible + implementation. Depending on the base ring, the string can be + + - ``'generic'`` -- on any base rings + + - ``'flint'`` -- for integers and rationals + + - ``'meataxe'`` -- finite fields using the optional package :ref:`spkg_meataxe` + + - ``'m4ri'`` -- for characteristic 2 using the :ref:`spkg_m4ri` library + + - ``'linbox-float'`` -- for integer mod rings up to `2^8 = 256` + + - ``'linbox-double'`` -- for integer mod rings up to + `floor(2^26*sqrt(2) + 1/2) = 94906266` + + - ``'numpy'`` -- for real and complex floating point numbers + + OUTPUT: a matrix space or, more generally, a homspace between free modules. + + This factory function creates instances of various specialized classes + depending on the input. Not all combinations of options are + implemented. + + - If the parameters ``row_keys`` or ``column_keys`` are provided, + they must be finite or enumerated families of objects. In this + case, instances of :class:`CombinatorialFreeModule` are created + via the factory function :func:`FreeModule`. Then the homspace + between these modules is returned. + + EXAMPLES:: + + sage: MatrixSpace(QQ, 2) + Full MatrixSpace of 2 by 2 dense matrices over Rational Field + sage: MatrixSpace(ZZ, 3, 2) + Full MatrixSpace of 3 by 2 dense matrices over Integer Ring + sage: MatrixSpace(ZZ, 3, sparse=False) + Full MatrixSpace of 3 by 3 dense matrices over Integer Ring + + sage: MatrixSpace(ZZ, 10, 5) + Full MatrixSpace of 10 by 5 dense matrices over Integer Ring + sage: MatrixSpace(ZZ, 10, 5).category() + Category of infinite enumerated finite dimensional modules with basis over + (Dedekind domains and euclidean domains + and infinite enumerated sets and metric spaces) + sage: MatrixSpace(ZZ, 10, 10).category() + Category of infinite enumerated finite dimensional algebras with basis over + (Dedekind domains and euclidean domains + and infinite enumerated sets and metric spaces) + sage: MatrixSpace(QQ, 10).category() + Category of infinite finite dimensional algebras with basis over + (number fields and quotient fields and metric spaces) Some examples of square 2 by 2 rational matrices:: @@ -463,8 +532,7 @@ class MatrixSpace(UniqueRepresentation, Parent): sage: B[1,1] [0 0] [0 1] - sage: A = MS.matrix([1,2,3,4]) - sage: A + sage: A = MS.matrix([1,2,3,4]); A [1 2] [3 4] @@ -476,19 +544,27 @@ class MatrixSpace(UniqueRepresentation, Parent): [ 9 12 15] [19 26 33] + Using ``row_keys`` and ``column_keys``:: + + sage: MS = MatrixSpace(ZZ, ['u', 'v'], ['a', 'b', 'c']); MS + Set of Morphisms + from Free module generated by {'a', 'b', 'c'} over Integer Ring + to Free module generated by {'u', 'v'} over Integer Ring + in Category of finite dimensional modules with basis over Integer Ring + Check categories:: - sage: MatrixSpace(ZZ,10,5) + sage: MatrixSpace(ZZ, 10, 5) Full MatrixSpace of 10 by 5 dense matrices over Integer Ring - sage: MatrixSpace(ZZ,10,5).category() + sage: MatrixSpace(ZZ, 10, 5).category() Category of infinite enumerated finite dimensional modules with basis over (Dedekind domains and euclidean domains and infinite enumerated sets and metric spaces) - sage: MatrixSpace(ZZ,10,10).category() + sage: MatrixSpace(ZZ, 10, 10).category() Category of infinite enumerated finite dimensional algebras with basis over (Dedekind domains and euclidean domains and infinite enumerated sets and metric spaces) - sage: MatrixSpace(QQ,10).category() + sage: MatrixSpace(QQ, 10).category() Category of infinite finite dimensional algebras with basis over (number fields and quotient fields and metric spaces) @@ -539,11 +615,14 @@ class MatrixSpace(UniqueRepresentation, Parent): """ @staticmethod - def __classcall__(cls, base_ring, nrows, ncols=None, sparse=False, implementation=None, **kwds): + def __classcall__(cls, base_ring, + nrows_or_row_keys=None, ncols_or_column_keys=None, + sparse=False, implementation=None, *, + nrows=None, ncols=None, + row_keys=None, column_keys=None, + **kwds): """ - Normalize the arguments to call the ``__init__`` constructor. - - See the documentation in ``__init__``. + Normalize the arguments to call the ``__init__`` constructor or delegate to another class. TESTS:: @@ -588,13 +667,35 @@ def __classcall__(cls, base_ring, nrows, ncols=None, sparse=False, implementatio """ if base_ring not in _Rings: raise TypeError("base_ring (=%s) must be a ring" % base_ring) - nrows = int(nrows) - if ncols is None: + + if ncols_or_column_keys is not None: + try: + ncols = int(ncols_or_column_keys) + except (TypeError, ValueError): + column_keys = ncols_or_column_keys + + if nrows_or_row_keys is not None: + try: + nrows = int(nrows_or_row_keys) + except (TypeError, ValueError): + row_keys = nrows_or_row_keys + + if ncols is None and column_keys is None: ncols = nrows - else: - ncols = int(ncols) + column_keys = row_keys + sparse = bool(sparse) + if row_keys is not None or column_keys is not None: + from sage.categories.homset import Hom + from sage.modules.free_module import FreeModule + + domain = FreeModule(base_ring, rank=ncols, basis_keys=column_keys, + sparse=sparse, **kwds) + codomain = FreeModule(base_ring, rank=nrows, basis_keys=row_keys, + sparse=sparse, **kwds) + return Hom(domain, codomain) + if nrows < 0: raise ArithmeticError("nrows must be nonnegative") if ncols < 0: @@ -608,59 +709,6 @@ def __classcall__(cls, base_ring, nrows, ncols=None, sparse=False, implementatio def __init__(self, base_ring, nrows, ncols, sparse, implementation): r""" - INPUT: - - - ``base_ring`` - - - ``nrows`` - (positive integer) the number of rows - - - ``ncols`` - (positive integer, default nrows) the number of - columns - - - ``sparse`` - (boolean, default false) whether or not matrices - are given a sparse representation - - - ``implementation`` -- (optional, a string or a matrix class) a possible - implementation. Depending on the base ring the string can be - - - ``'generic'`` - on any base rings - - - ``'flint'`` - for integers and rationals - - - ``'meataxe'`` - finite fields, needs to install the optional package meataxe - - - ``m4ri`` - for characteristic 2 using M4RI library - - - ``linbox-float`` - for integer mod rings up to `2^8 = 256` - - - ``linbox-double`` - for integer mod rings up to - `floor(2^26*sqrt(2) + 1/2) = 94906266` - - - ``numpy`` - for real and complex floating point numbers - - EXAMPLES:: - - sage: MatrixSpace(QQ, 2) - Full MatrixSpace of 2 by 2 dense matrices over Rational Field - sage: MatrixSpace(ZZ, 3, 2) - Full MatrixSpace of 3 by 2 dense matrices over Integer Ring - sage: MatrixSpace(ZZ, 3, sparse=False) - Full MatrixSpace of 3 by 3 dense matrices over Integer Ring - - sage: MatrixSpace(ZZ,10,5) - Full MatrixSpace of 10 by 5 dense matrices over Integer Ring - sage: MatrixSpace(ZZ,10,5).category() - Category of infinite enumerated finite dimensional modules with basis over - (Dedekind domains and euclidean domains - and infinite enumerated sets and metric spaces) - sage: MatrixSpace(ZZ,10,10).category() - Category of infinite enumerated finite dimensional algebras with basis over - (Dedekind domains and euclidean domains - and infinite enumerated sets and metric spaces) - sage: MatrixSpace(QQ,10).category() - Category of infinite finite dimensional algebras with basis over - (number fields and quotient fields and metric spaces) - TESTS: We test that in the real or complex double dense case, From b27e6e1455b2696ec055c08bfdb6c9b3e10eb711 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Mar 2024 11:49:31 -0800 Subject: [PATCH 070/191] src/sage/matrix/args.pyx: Doctest cosmetics --- src/sage/matrix/args.pyx | 64 ++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/sage/matrix/args.pyx b/src/sage/matrix/args.pyx index 6b247595059..b39f92986f7 100644 --- a/src/sage/matrix/args.pyx +++ b/src/sage/matrix/args.pyx @@ -156,24 +156,29 @@ cdef class MatrixArgs: sage: ma = MatrixArgs(2, 2, (x for x in range(4))); ma > sage: ma.finalized() - + Many types of input are possible:: sage: ma = MatrixArgs(2, 2, entries=None); ma.finalized(); ma.matrix() - + [0 0] [0 0] sage: ma = MatrixArgs(2, 2, entries={}); ma.finalized(); ma.matrix() - + [0 0] [0 0] sage: ma = MatrixArgs(2, 2, entries=[1,2,3,4]); ma.finalized(); ma.matrix() - + [1 2] [3 4] sage: ma = MatrixArgs(2, 2, entries=math.pi); ma.finalized(); ma.matrix() - + [3.141592653589793 0.0] [ 0.0 3.141592653589793] sage: ma = MatrixArgs(2, 2, entries=pi); ma.finalized() # needs sage.symbolic @@ -183,15 +188,18 @@ cdef class MatrixArgs: [pi 0] [ 0 pi] sage: ma = MatrixArgs(ZZ, 2, 2, entries={(0,0):7}); ma.finalized(); ma.matrix() - + [7 0] [0 0] sage: ma = MatrixArgs(ZZ, 2, 2, entries=((1,2),(3,4))); ma.finalized(); ma.matrix() - + [1 2] [3 4] sage: ma = MatrixArgs(ZZ, 2, 2, entries=(1,2,3,4)); ma.finalized(); ma.matrix() - + [1 2] [3 4] @@ -216,16 +224,19 @@ cdef class MatrixArgs: [ 0 3/5] sage: ma = MatrixArgs(entries=matrix(2,2)); ma.finalized(); ma.matrix() - [0 0] [0 0] sage: ma = MatrixArgs(2, 2, entries=lambda i,j: 1+2*i+j); ma.finalized(); ma.matrix() - + [1 2] [3 4] sage: ma = MatrixArgs(ZZ, 2, 2, entries=lambda i,j: 1+2*i+j); ma.finalized(); ma.matrix() - > + > [1 2] [3 4] @@ -263,9 +274,11 @@ cdef class MatrixArgs: [1 0 1] [1 1 0] - sage: ma = MatrixArgs([vector([0,1], sparse=True), vector([0,0], sparse=True)], sparse=True) + sage: ma = MatrixArgs([vector([0,1], sparse=True), vector([0,0], sparse=True)], + ....: sparse=True) sage: ma.finalized(); ma.matrix() - + [0 1] [0 0] @@ -615,8 +628,8 @@ cdef class MatrixArgs: INPUT: - - ``convert`` -- if True, the matrix is guaranteed to have - the correct parent matrix space. If False, the input matrix + - ``convert`` -- if ``True``, the matrix is guaranteed to have + the correct parent matrix space. If ``False``, the input matrix may be returned even if it lies in the wrong space. .. NOTE:: @@ -633,7 +646,8 @@ cdef class MatrixArgs: :: sage: ma = MatrixArgs(M); ma.finalized() - sage: ma.matrix() [0 1 2] @@ -642,7 +656,8 @@ cdef class MatrixArgs: :: sage: ma = MatrixArgs(M, sparse=False); ma.finalized() - sage: ma.matrix() [0 1 2] @@ -651,7 +666,8 @@ cdef class MatrixArgs: :: sage: ma = MatrixArgs(RDF, M); ma.finalized() - sage: ma.matrix(convert=False) [0 1 2] @@ -810,7 +826,8 @@ cdef class MatrixArgs: sage: S = MatrixSpace(QQ, 3, 2, sparse=True) sage: _ = ma.set_space(S) sage: ma.finalized() - + sage: M = ma.matrix(); M [0 0] [0 0] @@ -848,7 +865,8 @@ cdef class MatrixArgs: ... TypeError: the dimensions of the matrix must be specified sage: MatrixArgs(2, 3, 0.0).finalized() - + sage: MatrixArgs(RR, 2, 3, 1.0).finalized() Traceback (most recent call last): ... @@ -1023,10 +1041,12 @@ cdef class MatrixArgs: sage: ma = MatrixArgs({(2,5):1/2, (4,-3):1/3}) sage: ma = MatrixArgs(2, 2, {(-1,0):2, (0,-1):1}, sparse=True) sage: ma.finalized() - + sage: ma = MatrixArgs(2, 2, {(-1,0):2, (0,-1):1}, sparse=False) sage: ma.finalized() - + sage: ma = MatrixArgs(2, 1, {(1,0):88, (0,1):89}) sage: ma.finalized() Traceback (most recent call last): From 139d37ede9034c6c83de0b141e7e9b32085b90ea Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Mar 2024 14:06:47 -0800 Subject: [PATCH 071/191] src/sage/matrix/matrix_space.py: Docstring edits --- src/sage/matrix/matrix_space.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index a3336a846b9..1df9674ebd0 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -440,15 +440,12 @@ class MatrixSpace(UniqueRepresentation, Parent): - ``base_ring`` -- a ring - - ``nrows`` -- (nonnegative integer) the number of rows + - ``nrows`` or ``row_keys`` -- (nonnegative integer) the number of rows, or + a finite or enumerated family of arbitrary objects that index the rows + of the matrix - - ``row_keys`` -- a finite or enumerated family of arbitrary objects - that index the rows of the matrix - - - ``ncols`` -- (nonnegative integer, default ``nrows``) the number of - columns - - - ``column_keys`` -- a finite or enumerated family of arbitrary objects + - ``ncols`` or ``column_keys`` -- (nonnegative integer, default ``nrows``) + the number of columns, or a finite or enumerated family of arbitrary objects that index the columns of the matrix - ``sparse`` -- (boolean, default ``False``) whether or not matrices From 42fabd4bc43a24a8fd082f956a0cd4cfd8fc4443 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Mar 2024 14:08:31 -0800 Subject: [PATCH 072/191] src/sage/matrix/{args,constructor}.pyx: Docstring cosmetics --- src/sage/matrix/args.pyx | 29 ++++++++++++++++++----------- src/sage/matrix/constructor.pyx | 24 ++++++++++++------------ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/sage/matrix/args.pyx b/src/sage/matrix/args.pyx index b39f92986f7..56e79e70e45 100644 --- a/src/sage/matrix/args.pyx +++ b/src/sage/matrix/args.pyx @@ -313,21 +313,27 @@ cdef class MatrixArgs: sage: from sage.matrix.args import MatrixArgs sage: MatrixArgs().finalized() - + sage: MatrixArgs(1).finalized() - + sage: MatrixArgs(1, 1, 3).finalized() - + sage: MatrixArgs(1, 1, 1, 1).finalized() Traceback (most recent call last): ... TypeError: too many arguments in matrix constructor sage: MatrixArgs(3, nrows=1, ncols=1).finalized() - + sage: MatrixArgs(3, nrows=1).finalized() - + sage: MatrixArgs(3, ncols=1).finalized() - + """ self.base = ring if nrows is not None: @@ -719,7 +725,7 @@ cdef class MatrixArgs: INPUT: - - ``convert`` -- If True, the entries are converted to the base + - ``convert`` -- If ``True``, the entries are converted to the base ring. Otherwise, the entries are returned as given. .. NOTE:: @@ -779,11 +785,12 @@ cdef class MatrixArgs: cpdef dict dict(self, bint convert=True) noexcept: """ - Return the entries of the matrix as a dict. The keys of this - dict are the non-zero positions ``(i,j)``. The corresponding - value is the entry at that position. Zero values are skipped. + Return the entries of the matrix as a :class:`dict`. - If ``convert`` is True, the entries are converted to the base + The keys of this :class:`dict` are the non-zero positions ``(i,j)``. The + corresponding value is the entry at that position. Zero values are skipped. + + If ``convert`` is ``True``, the entries are converted to the base ring. Otherwise, the entries are returned as given. EXAMPLES:: diff --git a/src/sage/matrix/constructor.pyx b/src/sage/matrix/constructor.pyx index 665ae4fbde9..f1d6a72f133 100644 --- a/src/sage/matrix/constructor.pyx +++ b/src/sage/matrix/constructor.pyx @@ -37,7 +37,7 @@ def matrix(*args, **kwds): INPUT: - The matrix command takes the entries of a matrix, optionally + The :func:`matrix` command takes the entries of a matrix, optionally preceded by a ring and the dimensions of the matrix, and returns a matrix. @@ -49,11 +49,11 @@ def matrix(*args, **kwds): columns. You can create a matrix of zeros by passing an empty list or the integer zero for the entries. To construct a multiple of the identity (`cI`), you can specify square dimensions and pass in - `c`. Calling matrix() with a Sage object may return something that - makes sense. Calling matrix() with a NumPy array will convert the + `c`. Calling :func:`matrix` with a Sage object may return something that + makes sense. Calling :func:`matrix` with a NumPy array will convert the array to a matrix. - All arguments (even the positional) are optional. + All arguments (even the positional ones) are optional. Positional and keyword arguments: @@ -105,7 +105,7 @@ def matrix(*args, **kwds): :: - sage: m = matrix(QQ,[[1,2,3],[4,5,6]]); m; m.parent() + sage: m = matrix(QQ, [[1,2,3],[4,5,6]]); m; m.parent() [1 2 3] [4 5 6] Full MatrixSpace of 2 by 3 dense matrices over Rational Field @@ -135,8 +135,8 @@ def matrix(*args, **kwds): :: - sage: v1=vector((1,2,3)) - sage: v2=vector((4,5,6)) + sage: v1 = vector((1,2,3)) + sage: v2 = vector((4,5,6)) sage: m = matrix([v1,v2]); m; m.parent() [1 2 3] [4 5 6] @@ -144,28 +144,28 @@ def matrix(*args, **kwds): :: - sage: m = matrix(QQ,2,[1,2,3,4,5,6]); m; m.parent() + sage: m = matrix(QQ, 2, [1,2,3,4,5,6]); m; m.parent() [1 2 3] [4 5 6] Full MatrixSpace of 2 by 3 dense matrices over Rational Field :: - sage: m = matrix(QQ,2,3,[1,2,3,4,5,6]); m; m.parent() + sage: m = matrix(QQ, 2, 3, [1,2,3,4,5,6]); m; m.parent() [1 2 3] [4 5 6] Full MatrixSpace of 2 by 3 dense matrices over Rational Field :: - sage: m = matrix({(0,1): 2, (1,1):2/5}); m; m.parent() + sage: m = matrix({(0,1): 2, (1,1): 2/5}); m; m.parent() [ 0 2] [ 0 2/5] Full MatrixSpace of 2 by 2 sparse matrices over Rational Field :: - sage: m = matrix(QQ,2,3,{(1,1): 2}); m; m.parent() + sage: m = matrix(QQ, 2, 3, {(1,1): 2}); m; m.parent() [0 0 0] [0 2 0] Full MatrixSpace of 2 by 3 sparse matrices over Rational Field @@ -234,7 +234,7 @@ def matrix(*args, **kwds): :: - sage: M = Matrix([[1,2,3],[4,5,6],[7,8,9]], immutable=True) + sage: M = Matrix([[1,2,3], [4,5,6], [7,8,9]], immutable=True) sage: M[0] = [9,9,9] Traceback (most recent call last): ... From 0c1dfd0b84e58122ca0989759fe0f806e1b241db Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 7 Mar 2024 09:25:29 -0800 Subject: [PATCH 073/191] src/sage/matrix/matrix_space.py: Do not mention enumerated families as row/column keys --- src/sage/matrix/matrix_space.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 1df9674ebd0..95c099d5379 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -441,12 +441,11 @@ class MatrixSpace(UniqueRepresentation, Parent): - ``base_ring`` -- a ring - ``nrows`` or ``row_keys`` -- (nonnegative integer) the number of rows, or - a finite or enumerated family of arbitrary objects that index the rows - of the matrix + a finite family of arbitrary objects that index the rows of the matrix - ``ncols`` or ``column_keys`` -- (nonnegative integer, default ``nrows``) - the number of columns, or a finite or enumerated family of arbitrary objects - that index the columns of the matrix + the number of columns, or a finite family of arbitrary objects that index + the columns of the matrix - ``sparse`` -- (boolean, default ``False``) whether or not matrices are given a sparse representation @@ -475,11 +474,10 @@ class MatrixSpace(UniqueRepresentation, Parent): depending on the input. Not all combinations of options are implemented. - - If the parameters ``row_keys`` or ``column_keys`` are provided, - they must be finite or enumerated families of objects. In this - case, instances of :class:`CombinatorialFreeModule` are created - via the factory function :func:`FreeModule`. Then the homspace - between these modules is returned. + - If the parameters ``row_keys`` or ``column_keys`` are provided, they + must be finite families of objects. In this case, instances of + :class:`CombinatorialFreeModule` are created via the factory function + :func:`FreeModule`. Then the homspace between these modules is returned. EXAMPLES:: From 438f8cf7d38a952bfab595520933e9498394bdf7 Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Tue, 26 Mar 2024 15:05:35 +0100 Subject: [PATCH 074/191] Adapt to work with arbitrary order bases --- src/sage/algebras/quatalg/quaternion_algebra.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index c4452867966..57f8ae9490d 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -841,15 +841,15 @@ def maximal_order(self, order_basis=None, take_shortcuts=True): raise ValueError('order_basis is not a basis of an order of the' ' given quaternion algebra') - if order_basis[0] not in ZZ: - raise Warning('the algorithm might not work if the' - ' first basis vector is not an integer') + # Since Voight's algorithm only works for a starting basis having 1 as + # its first vector, we derive such a basis from the given order basis + basis = basis_for_quaternion_lattice(order_basis, reverse=True) e_new_gens = [] # For each prime at which R is not yet maximal, make it bigger for p, _ in d_R.factor(): - e = order_basis + e = basis disc = d_R while disc.valuation(p) > d_A.valuation(p): # Compute a normalized basis at p @@ -940,7 +940,7 @@ def maximal_order(self, order_basis=None, take_shortcuts=True): e_new_gens.extend(e[1:]) - e_new = basis_for_quaternion_lattice(list(R.basis()) + e_new_gens, reverse=True) + e_new = basis_for_quaternion_lattice(list(basis) + e_new_gens, reverse=True) return self.quaternion_order(e_new) def invariants(self): From 59436fe548cf2091a0c287e4d2a9aeec1719e02a Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Tue, 26 Mar 2024 15:45:10 +0100 Subject: [PATCH 075/191] Defined comparison operators for orders --- .../algebras/quatalg/quaternion_algebra.py | 80 +++++++++++++++++-- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 57f8ae9490d..62f92a1ee36 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -1633,7 +1633,7 @@ def gen(self, n): """ return self.__basis[n] - def __eq__(self, R): + def __eq__(self, other): """ Compare orders self and other. @@ -1654,17 +1654,17 @@ def __eq__(self, R): sage: Q.quaternion_order([1,-i,k,j+i*7]) == Q.quaternion_order([1,i,j,k]) True """ - if not isinstance(R, QuaternionOrder): + if not isinstance(other, QuaternionOrder): return False - return (self.__quaternion_algebra == R.__quaternion_algebra and - self.unit_ideal() == R.unit_ideal()) + return (self.__quaternion_algebra == other.__quaternion_algebra and + self.unit_ideal() == other.unit_ideal()) def __ne__(self, other): """ Compare orders self and other. - Two orders are equal if they - have the same basis and are in the same quaternion algebra. + Two orders are equal if they have the same + basis and are in the same quaternion algebra. EXAMPLES:: @@ -1676,6 +1676,74 @@ def __ne__(self, other): """ return not self.__eq__(other) + def __le__(self, other): + """ + Compare orders self and other. + + EXAMPLES:: + + sage: B. = QuaternionAlgebra(-1, -11) + sage: O = B.quaternion_order([1,i,j,k]) + sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) + sage: O <= R + True + sage: R <= O + False + """ + if not isinstance(other, QuaternionOrder): + return False + return self.unit_ideal().__le__(other.unit_ideal()) + + def __lt__(self, other): + """ + Compare orders self and other. + + EXAMPLES:: + + sage: B. = QuaternionAlgebra(-1, -11) + sage: O = B.quaternion_order([1,i,j,k]) + sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) + sage: O < R + True + sage: R < O + False + """ + return self.__le__(other) and self.__ne__(other) + + def __ge__(self, other): + """ + Compare orders self and other. + + EXAMPLES:: + + sage: B. = QuaternionAlgebra(-1, -11) + sage: O = B.quaternion_order([1,i,j,k]) + sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) + sage: O >= R + False + sage: R >= O + True + """ + if not isinstance(other, QuaternionOrder): + return False + return self.unit_ideal().__ge__(other.unit_ideal()) + + def __gt__(self, other): + """ + Compare orders self and other. + + EXAMPLES:: + + sage: B. = QuaternionAlgebra(-1, -11) + sage: O = B.quaternion_order([1,i,j,k]) + sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) + sage: O > R + False + sage: R > O + True + """ + return self.__ge__(other) and self.__ne__(other) + def __hash__(self): """ Compute the hash of ``self``. From 7ad48accfaa6e8ef812de9463fde74dd8117cd63 Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Tue, 26 Mar 2024 16:02:40 +0100 Subject: [PATCH 076/191] Added example for basis extension --- src/sage/algebras/quatalg/quaternion_algebra.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 62f92a1ee36..90960d44c9c 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -762,6 +762,19 @@ def maximal_order(self, order_basis=None, take_shortcuts=True): ....: A = QuaternionAlgebra(d) ....: assert A.maximal_order(take_shortcuts=False).is_maximal() + Specifying an order basis gives an extension of orders:: + + sage: A. = QuaternionAlgebra(-292, -732) + sage: alpha = A.random_element() + sage: while alpha.is_zero(): + ....: alpha = A.random_element() + sage: conj = [alpha * b * alpha.inverse() for b in [k,i,j]] + sage: order_basis = tuple(conj) + (A.one(),) + sage: O = A.quaternion_order(order_basis) + sage: R = A.maximal_order(order_basis) + sage: O <= R and R.is_maximal() + True + We do not support number fields other than the rationals yet:: sage: K = QuadraticField(5) From 5a00a8e8b3f885a67aea259bc76ffc0ffe232aac Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Tue, 26 Mar 2024 16:26:42 +0100 Subject: [PATCH 077/191] Small docstring modifications --- src/sage/algebras/quatalg/quaternion_algebra.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 90960d44c9c..f3f315e1f80 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -692,13 +692,13 @@ def maximal_order(self, order_basis=None, take_shortcuts=True): Return a maximal order in this quaternion algebra. If ``order_basis`` is specified, the resulting maximal order - will contain the quaternion order of ``self`` given by this + will contain the order of the quaternion algebra given by this basis. The algorithm used is from [Voi2012]_. INPUT: - - ``order_basis`` -- (optional, default: ``None``) a basis of a - quaternion order of ``self`` + - ``order_basis`` -- (optional, default: ``None``) a basis of an + order of this quaternion algebra - ``take_shortcuts`` -- (default: ``True``) if the discriminant is prime and the invariants of the algebra are of a nice form, use From 20b5d54adc0ebb308446c2b79546a011ec506d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 27 Mar 2024 10:48:36 +0100 Subject: [PATCH 078/191] pe8 and ruff fixes in the plot folder --- src/sage/plot/animate.py | 19 +-- src/sage/plot/arc.py | 2 +- src/sage/plot/arrow.py | 10 +- src/sage/plot/bezier_path.py | 2 +- src/sage/plot/circle.py | 2 +- src/sage/plot/colors.py | 14 +-- src/sage/plot/density_plot.py | 2 +- src/sage/plot/disk.py | 2 +- src/sage/plot/ellipse.py | 3 +- src/sage/plot/graphics.py | 79 ++++++------ src/sage/plot/histogram.py | 4 +- src/sage/plot/hyperbolic_arc.py | 7 +- src/sage/plot/hyperbolic_polygon.py | 1 + src/sage/plot/hyperbolic_regular_polygon.py | 6 +- src/sage/plot/matrix_plot.py | 14 +-- src/sage/plot/multigraphics.py | 20 ++-- src/sage/plot/plot.py | 30 ++++- src/sage/plot/plot3d/list_plot3d.py | 9 +- src/sage/plot/plot3d/plot3d.py | 30 +++-- src/sage/plot/plot3d/revolution_plot3d.py | 1 + src/sage/plot/plot3d/shapes2.py | 17 ++- src/sage/plot/plot3d/tachyon.py | 126 +++++++++----------- src/sage/plot/plot3d/texture.py | 8 +- src/sage/plot/plot3d/tri_plot.py | 6 +- src/sage/plot/plot_field.py | 4 +- src/sage/plot/point.py | 1 - src/sage/plot/primitive.py | 3 +- src/sage/plot/text.py | 2 +- 28 files changed, 226 insertions(+), 198 deletions(-) diff --git a/src/sage/plot/animate.py b/src/sage/plot/animate.py index 071bcd92622..b4b20e83754 100644 --- a/src/sage/plot/animate.py +++ b/src/sage/plot/animate.py @@ -154,6 +154,7 @@ def animate(frames, **kwds): """ return Animation(frames, **kwds) + class Animation(WithEqualityById, SageObject): r""" Return an animation of a sequence of plots of objects. @@ -1000,7 +1001,7 @@ def ffmpeg(self, savefile=None, show_path=False, output_format=None, # -loop_output option can be added with the # ffmpeg_options argument. if iterations is not None: - loop_cmd = '-loop {0} '.format(iterations) + loop_cmd = f'-loop {iterations} ' else: loop_cmd = '' # A pix_fmt value is required for some but not all @@ -1008,10 +1009,10 @@ def ffmpeg(self, savefile=None, show_path=False, output_format=None, # prevent sage from adding this option, and it may be # controlled separately through ffmpeg_options. if pix_fmt is not None: - pix_fmt_cmd = '-pix_fmt {0} '.format(pix_fmt) + pix_fmt_cmd = f'-pix_fmt {pix_fmt} ' else: pix_fmt_cmd = '' - ffmpeg_options += ' {0}{1}'.format(pix_fmt_cmd,loop_cmd) + ffmpeg_options += f' {pix_fmt_cmd}{loop_cmd}' if delay is not None and output_format != '.mpeg' and output_format != '.mpg': early_options += ' -r %s ' % int(100/delay) savefile = os.path.abspath(savefile) @@ -1023,7 +1024,7 @@ def ffmpeg(self, savefile=None, show_path=False, output_format=None, # afterwards. Hence 'early_options' and 'ffmpeg_options' # The `-nostdin` is needed to avoid the command to hang, see # https://stackoverflow.com/questions/16523746/ffmpeg-hangs-when-run-in-background - cmd = 'cd %s; ffmpeg -nostdin -y -f image2 %s -i %s %s %s' % ( + cmd = 'cd {}; ffmpeg -nostdin -y -f image2 {} -i {} {} {}'.format( shlex.quote(pngdir), early_options, shlex.quote(pngs), ffmpeg_options, shlex.quote(savefile)) from subprocess import check_call, CalledProcessError, PIPE try: @@ -1254,7 +1255,7 @@ def interactive(self, **kwds): except (AttributeError, TypeError): frame = None if not isinstance(frame, Graphics3d): - raise TypeError("Could not convert frame {} to Graphics3d".format(i)) + raise TypeError(f"Could not convert frame {i} to Graphics3d") g3d_frames.append(frame) # Give preference to this method's keyword arguments over those provided # to animate or the constructor. @@ -1265,7 +1266,7 @@ def interactive(self, **kwds): return KeyframeAnimationGroup(g3d_frames, **kwds) -class APngAssembler(): +class APngAssembler: r""" Builds an APNG_ (Animated PNG) from a sequence of PNG files. This is used by the :meth:`sage.plot.animate.Animation.apng` method. @@ -1322,7 +1323,7 @@ def __init__(self, out, num_frames, self.num_plays = num_plays self.default_delay_numerator = delay self.default_delay_denominator = delay_denominator - self._matchref = dict() + self._matchref = {} self.out.write(self.magic) def add_frame(self, pngfile, delay=None, delay_denominator=None): @@ -1449,7 +1450,7 @@ def _add_png(self, pngfile): """ with open(pngfile, 'rb') as png: if png.read(8) != self.magic: - raise ValueError("{} is not a PNG file".format(pngfile)) + raise ValueError(f"{pngfile} is not a PNG file") while True: chead = png.read(8) if len(chead) == 0: @@ -1466,7 +1467,7 @@ def _add_png(self, pngfile): self._copy() else: if cdata != ref: - raise ValueError("Chunk {} mismatch".format(utype)) + raise ValueError(f"Chunk {utype} mismatch") met = ("_first_" if self._first else "_next_") + utype try: met = getattr(self, met) diff --git a/src/sage/plot/arc.py b/src/sage/plot/arc.py index 8da333ee12b..c7d8d76ffae 100644 --- a/src/sage/plot/arc.py +++ b/src/sage/plot/arc.py @@ -346,7 +346,7 @@ def _repr_(self): sage: print(Arc(2,3,2.2,2.2,0,2,3,{})) Arc with center (2.0,3.0) radii (2.2,2.2) angle 0.0 inside the sector (2.0,3.0) """ - return "Arc with center (%s,%s) radii (%s,%s) angle %s inside the sector (%s,%s)" % (self.x, self.y, self.r1, self.r2, self.angle, self.s1, self.s2) + return "Arc with center ({},{}) radii ({},{}) angle {} inside the sector ({},{})".format(self.x, self.y, self.r1, self.r2, self.angle, self.s1, self.s2) def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/arrow.py b/src/sage/plot/arrow.py index 74da7b4b4f7..25fcf381c92 100644 --- a/src/sage/plot/arrow.py +++ b/src/sage/plot/arrow.py @@ -114,7 +114,7 @@ def _repr_(self): sage: CurveArrow(path=[[(0,0),(1,4),(2,3)]],options={})._repr_() 'CurveArrow from (0, 0) to (2, 3)' """ - return "CurveArrow from %s to %s" % (self.path[0][0], self.path[-1][-1]) + return f"CurveArrow from {self.path[0][0]} to {self.path[-1][-1]}" def _render_on_subplot(self, subplot): """ @@ -152,7 +152,7 @@ def _render_on_subplot(self, subplot): from matplotlib.path import Path bpath = Path(self.vertices, self.codes) p = FancyArrowPatch(path=bpath, - lw=width, arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), + lw=width, arrowstyle='{},head_width={},head_length={}'.format(style, head_width, head_length), fc=color, ec=color, linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_zorder(options['zorder']) @@ -319,7 +319,7 @@ def _repr_(self): sage: Arrow(0,0,2,3,{})._repr_() 'Arrow from (0.0,0.0) to (2.0,3.0)' """ - return "Arrow from (%s,%s) to (%s,%s)" % (self.xtail, self.ytail, self.xhead, self.yhead) + return f"Arrow from ({self.xtail},{self.ytail}) to ({self.xhead},{self.yhead})" def _render_on_subplot(self, subplot): r""" @@ -378,7 +378,7 @@ def _render_on_subplot(self, subplot): from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, - arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), + arrowstyle='{},head_width={},head_length={}'.format(style, head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long')) @@ -395,7 +395,7 @@ def _render_on_subplot(self, subplot): import matplotlib.patheffects as pe - class CheckNthSubPath(): + class CheckNthSubPath: def __init__(self, patch, n): """ creates a callable object that returns True if the diff --git a/src/sage/plot/bezier_path.py b/src/sage/plot/bezier_path.py index 14958fbbba8..16053ad0e7b 100644 --- a/src/sage/plot/bezier_path.py +++ b/src/sage/plot/bezier_path.py @@ -208,7 +208,7 @@ def _repr_(self): """ x0, y0 = self.vertices[0] x1, y1 = self.vertices[-1] - return "Bezier path from (%s, %s) to (%s, %s)" % (x0, y0, x1, y1) + return f"Bezier path from ({x0}, {y0}) to ({x1}, {y1})" def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/circle.py b/src/sage/plot/circle.py index c7fd3d9dfc0..7d5f04f2f9c 100644 --- a/src/sage/plot/circle.py +++ b/src/sage/plot/circle.py @@ -133,7 +133,7 @@ def _repr_(self): sage: c = C[0]; c Circle defined by (2.0,3.0) with r=5.0 """ - return "Circle defined by (%s,%s) with r=%s" % (self.x, self.y, self.r) + return f"Circle defined by ({self.x},{self.y}) with r={self.r}" def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py index 3322c6cfdbc..cdc4a9f1b21 100644 --- a/src/sage/plot/colors.py +++ b/src/sage/plot/colors.py @@ -254,7 +254,7 @@ def html_to_float(c): raise ValueError("'%s' must be a valid HTML hex color (e.g., '#f07' or '#d6e7da')" % c) h = c[1:] if len(h) == 3: - h = '%s%s%s%s%s%s' % (h[0], h[0], h[1], h[1], h[2], h[2]) + h = f'{h[0]}{h[0]}{h[1]}{h[1]}{h[2]}{h[2]}' elif len(h) != 6: raise ValueError("color hex string (= '%s') must have length 3 or 6" % h) return tuple([int(h[i:i + 2], base=16) / 255 for i in [0, 2, 4]]) @@ -338,7 +338,7 @@ def rgbcolor(c, space='rgb'): elif isinstance(c, (list, tuple)): if len(c) != 3: - raise ValueError("color list or tuple '%s' must have 3 entries, one for each RGB, HSV, HLS, or HSL channel" % (c, )) + raise ValueError("color list or tuple '{}' must have 3 entries, one for each RGB, HSV, HLS, or HSL channel".format(c )) c = [mod_one(_) for _ in list(c)] if space == 'rgb': return tuple(c) @@ -358,7 +358,7 @@ def rgbcolor(c, space='rgb'): to_mpl_color = rgbcolor -class Color(): +class Color: def __init__(self, r='#0000ff', g=None, b=None, space='rgb'): """ A Red-Green-Blue (RGB) color model color object. For most @@ -421,7 +421,7 @@ def __repr__(self): sage: Color(1, 0.5, 1/16, space='hsl').__repr__() 'RGB color (0.09375, 0.03125, 0.03125)' """ - return "RGB color %s" % (self._rgb, ) + return f"RGB color {self._rgb}" def __lt__(self, right): """ @@ -645,7 +645,7 @@ def blend(self, color, fraction=0.5): color = [float(_) for _ in color] return Color(rgbcolor([(1 - fraction) * a + fraction * b for a, b in zip(self._rgb, color)])) - raise TypeError("%s must be a Color or float-convertible 3-tuple/list" % (color, )) + raise TypeError(f"{color} must be a Color or float-convertible 3-tuple/list") def __add__(self, right): """ @@ -1104,7 +1104,7 @@ def __getattr__(self, name): try: return self[name] except KeyError: - raise AttributeError("'%s' has no attribute or colormap %s" % (type(self).__name__, name)) + raise AttributeError("'{}' has no attribute or colormap {}".format(type(self).__name__, name)) def __dir__(self): """ @@ -1611,7 +1611,7 @@ def __getattr__(self, name): try: return self[name] except KeyError: - raise AttributeError("'%s' has no attribute or colormap %s" % (type(self).__name__, name)) + raise AttributeError("'{}' has no attribute or colormap {}".format(type(self).__name__, name)) def __repr__(self): """ diff --git a/src/sage/plot/density_plot.py b/src/sage/plot/density_plot.py index ff27f2d126b..a69da22344a 100644 --- a/src/sage/plot/density_plot.py +++ b/src/sage/plot/density_plot.py @@ -127,7 +127,7 @@ def _repr_(self): sage: d = D[0]; d DensityPlot defined by a 25 x 25 data grid """ - return "DensityPlot defined by a %s x %s data grid" % (self.xy_array_row, self.xy_array_col) + return "DensityPlot defined by a {} x {} data grid".format(self.xy_array_row, self.xy_array_col) def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/disk.py b/src/sage/plot/disk.py index 4219cf35155..20831caf61f 100644 --- a/src/sage/plot/disk.py +++ b/src/sage/plot/disk.py @@ -149,7 +149,7 @@ def _repr_(self): sage: p = P[0]; p Disk defined by (3.0,3.0) with r=1.0 spanning (0.0, 1.5707963267...) radians """ - return "Disk defined by (%s,%s) with r=%s spanning (%s, %s) radians" % (self.x, self.y, self.r, self.rad1, self.rad2) + return "Disk defined by ({},{}) with r={} spanning ({}, {}) radians".format(self.x, self.y, self.r, self.rad1, self.rad2) def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/ellipse.py b/src/sage/plot/ellipse.py index 788db0fd76b..c606d8360db 100644 --- a/src/sage/plot/ellipse.py +++ b/src/sage/plot/ellipse.py @@ -170,7 +170,7 @@ def _repr_(self): sage: Ellipse(0,0,2,1,0,{})._repr_() 'Ellipse centered at (0.0, 0.0) with radii (2.0, 1.0) and angle 0.0' """ - return "Ellipse centered at (%s, %s) with radii (%s, %s) and angle %s" % (self.x, self.y, self.r1, self.r2, self.angle) + return "Ellipse centered at ({}, {}) with radii ({}, {}) and angle {}".format(self.x, self.y, self.r1, self.r2, self.angle) def _render_on_subplot(self, subplot): """ @@ -227,6 +227,7 @@ def plot3d(self): """ raise NotImplementedError + @rename_keyword(color='rgbcolor') @options(alpha=1, fill=False, thickness=1, edgecolor='blue', facecolor='blue', linestyle='solid', zorder=5, aspect_ratio=1.0, legend_label=None, legend_color=None) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 8a61068887f..0b6c1072ec4 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- r""" Graphics objects @@ -100,23 +99,23 @@ def _parse_figsize(figsize): # figsize should be a pair of positive numbers if len(figsize) != 2: raise ValueError("figsize should be a positive number or a list " - "of two positive numbers, not {0}".format(figsize)) + f"of two positive numbers, not {figsize}") figsize = (float(figsize[0]), float(figsize[1])) # floats for mpl if not (figsize[0] > 0 and figsize[1] > 0): raise ValueError("figsize should be positive numbers, " - "not {0} and {1}".format(figsize[0], figsize[1])) + f"not {figsize[0]} and {figsize[1]}") else: # in this case, figsize is a single number representing the width and # should be positive try: figsize = float(figsize) # to pass to mpl except TypeError: - raise TypeError("figsize should be a positive number, not {0}".format(figsize)) + raise TypeError(f"figsize should be a positive number, not {figsize}") if figsize > 0: default_width, default_height = rcParams['figure.figsize'] figsize = (figsize, default_height * figsize / default_width) else: - raise ValueError("figsize should be positive, not {0}".format(figsize)) + raise ValueError(f"figsize should be positive, not {figsize}") return figsize @@ -1398,7 +1397,7 @@ def _set_scale(self, subplot, scale=None, base=None): if scale not in ('linear', 'loglog', 'semilogx', 'semilogy'): raise ValueError("The scale must be one of 'linear', 'loglog'," - " 'semilogx' or 'semilogy' -- got '{0}'".format(scale)) + f" 'semilogx' or 'semilogy' -- got '{scale}'") if isinstance(base, (list, tuple)): basex, basey = base @@ -1437,37 +1436,37 @@ def _set_scale(self, subplot, scale=None, base=None): # NOTE: If you intend to use a new parameter in show(), you should update # this dictionary to contain the default value for that parameter. - SHOW_OPTIONS = dict(# axes options - axes=None, axes_labels=None, axes_labels_size=None, - axes_pad=None, base=None, scale=None, - xmin=None, xmax=None, ymin=None, ymax=None, - flip_x=False, flip_y=False, + SHOW_OPTIONS = {# axes options + 'axes': None, 'axes_labels': None, 'axes_labels_size': None, + 'axes_pad': None, 'base': None, 'scale': None, + 'xmin': None, 'xmax': None, 'ymin': None, 'ymax': None, + 'flip_x': False, 'flip_y': False, # Figure options - aspect_ratio=None, dpi=DEFAULT_DPI, fig_tight=True, - figsize=None, fontsize=None, frame=False, - title=None, title_pos=None, transparent=False, + 'aspect_ratio': None, 'dpi': DEFAULT_DPI, 'fig_tight': True, + 'figsize': None, 'fontsize': None, 'frame': False, + 'title': None, 'title_pos': None, 'transparent': False, # Grid options - gridlines=None, gridlinesstyle=None, - hgridlinesstyle=None, vgridlinesstyle=None, + 'gridlines': None, 'gridlinesstyle': None, + 'hgridlinesstyle': None, 'vgridlinesstyle': None, # Legend options - legend_options={}, show_legend=None, + 'legend_options': {}, 'show_legend': None, # Ticks options - ticks=None, tick_formatter=None, ticks_integer=False, + 'ticks': None, 'tick_formatter': None, 'ticks_integer': False, # Text options - typeset='default') + 'typeset': 'default'} # Default options for the legends: - LEGEND_OPTIONS = dict(back_color='white', borderpad=0.6, - borderaxespad=None, - columnspacing=None, - fancybox=False, font_family='sans-serif', - font_size='medium', font_style='normal', - font_variant='normal', font_weight='medium', - handlelength=0.05, handletextpad=0.5, - labelspacing=0.02, loc='best', - markerscale=0.6, ncol=1, numpoints=2, - shadow=True, title=None) + LEGEND_OPTIONS = {'back_color': 'white', 'borderpad': 0.6, + 'borderaxespad': None, + 'columnspacing': None, + 'fancybox': False, 'font_family': 'sans-serif', + 'font_size': 'medium', 'font_style': 'normal', + 'font_variant': 'normal', 'font_weight': 'medium', + 'handlelength': 0.05, 'handletextpad': 0.5, + 'labelspacing': 0.02, 'loc': 'best', + 'markerscale': 0.6, 'ncol': 1, 'numpoints': 2, + 'shadow': True, 'title': None} @suboptions('legend', **LEGEND_OPTIONS) def show(self, **kwds): @@ -2788,7 +2787,7 @@ def matplotlib(self, filename=None, rcParams['text.usetex'] = True elif typeset != 'default': # We won't change (maybe user-set) defaults raise ValueError("typeset must be set to one of 'default', 'latex'," - " or 'type1'; got '{}'.".format(typeset)) + f" or 'type1'; got '{typeset}'.") self.fontsize(fontsize) self.axes_labels(l=axes_labels) @@ -2805,7 +2804,7 @@ def matplotlib(self, filename=None, if not subplot: subplot = figure.add_subplot(111) # Add all the primitives to the subplot - old_opts = dict() + old_opts = {} for g in self._objects: opts, old_opts[g] = g.options(), g.options() for k, v in opts.items(): @@ -2867,7 +2866,7 @@ def matplotlib(self, filename=None, if show_legend: from matplotlib.font_manager import FontProperties - lopts = dict() + lopts = {} lopts.update(legend_options) lopts.update(self._legend_opts) prop = FontProperties( @@ -2898,8 +2897,8 @@ def matplotlib(self, filename=None, subplot.set_xlim([xmin, xmax]) subplot.set_ylim([ymin, ymax]) - locator_options = dict(nbins=9, steps=[1, 2, 5, 10], - integer=ticks_integer) + locator_options = {'nbins': 9, 'steps': [1, 2, 5, 10], + 'integer': ticks_integer} if axes is None: axes = self._show_axes @@ -3090,8 +3089,8 @@ def matplotlib(self, filename=None, if gridlinesstyle is None: # Set up the default grid style - gridlinesstyle = dict(color='black', linestyle=':', - linewidth=0.5) + gridlinesstyle = {'color': 'black', 'linestyle': ':', + 'linewidth': 0.5} vgridstyle = gridlinesstyle.copy() if vgridlinesstyle is not None: @@ -3341,7 +3340,7 @@ def save(self, filename, **kwds): Graphics object consisting of 1 graphics primitive """ - options = dict() + options = {} options.update(self.SHOW_OPTIONS) options.update(self._extra_kwds) options.update(kwds) @@ -3406,7 +3405,7 @@ def save(self, filename, **kwds): # tight_layout adjusts the *subplot* parameters so ticks aren't cut off, etc. figure.tight_layout() - opts = dict(dpi=dpi, transparent=transparent) + opts = {'dpi': dpi, 'transparent': transparent} if fig_tight is True: opts['bbox_inches'] = 'tight' if self._bbox_extra_artists: @@ -3438,7 +3437,7 @@ def _latex_(self, **kwds): """ tmpfilename = tmp_filename(ext='.pgf') self.save(filename=tmpfilename, **kwds) - with open(tmpfilename, "r") as tmpfile: + with open(tmpfilename) as tmpfile: latex_list = tmpfile.readlines() from sage.misc.latex import latex latex.add_package_to_preamble_if_available('pgf') @@ -3464,7 +3463,7 @@ def description(self): for g in self: g_zorder = g.options().get('zorder', 0) if hasattr(g, 'xdata'): - g_str = '{0}:\t{1}'.format(g, list(zip(g.xdata, g.ydata))) + g_str = f'{g}:\t{list(zip(g.xdata, g.ydata))}' else: g_str = repr(g) data.append([g_zorder, g_str, g]) diff --git a/src/sage/plot/histogram.py b/src/sage/plot/histogram.py index e10229417fc..959284fa2e1 100644 --- a/src/sage/plot/histogram.py +++ b/src/sage/plot/histogram.py @@ -180,9 +180,9 @@ def _repr_(self): """ L = len(self.datalist) if not hasattr(self.datalist[0], '__contains__'): - return "Histogram defined by a data list of size {}".format(L) + return f"Histogram defined by a data list of size {L}" else: - return "Histogram defined by {} data lists".format(L) + return f"Histogram defined by {L} data lists" def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/hyperbolic_arc.py b/src/sage/plot/hyperbolic_arc.py index 4e7fda8350d..9b89198c68f 100644 --- a/src/sage/plot/hyperbolic_arc.py +++ b/src/sage/plot/hyperbolic_arc.py @@ -227,7 +227,8 @@ def _repr_(self): sage: HyperbolicArc(0, 1/2+I*sqrt(3)/2, "UHP", {}) Hyperbolic arc (0.000000000000000, 0.500000000000000 + 0.866025403784439*I) """ - return "Hyperbolic arc (%s, %s)" % (self.A, self.B) + return f"Hyperbolic arc ({self.A}, {self.B})" + @rename_keyword(color='rgbcolor') @options(alpha=1, fill=False, thickness=1, rgbcolor="blue", zorder=2, linestyle='solid') @@ -389,9 +390,9 @@ def hyperbolic_arc(a, b, model="UHP", **options): # Check for valid points if a[2] < 0 or a[0]**2+a[1]**2-a[2]**2 + 1 > EPSILON: - raise ValueError("%s is not a valid point in the HM model" % (a,)) + raise ValueError(f"{a} is not a valid point in the HM model") if b[2] < 0 or b[0]**2+b[1]**2-b[2]**2 + 1 > EPSILON: - raise ValueError("%s is not a valid point in the HM model" % (b,)) + raise ValueError(f"{b} is not a valid point in the HM model") HM = HyperbolicPlane().HM() geodesic = HM.get_geodesic(a, b) diff --git a/src/sage/plot/hyperbolic_polygon.py b/src/sage/plot/hyperbolic_polygon.py index efe39697829..ba09c3de97c 100644 --- a/src/sage/plot/hyperbolic_polygon.py +++ b/src/sage/plot/hyperbolic_polygon.py @@ -109,6 +109,7 @@ def _repr_(self): """ return "Hyperbolic polygon ({})".format(", ".join(map(str, self._pts))) + def _winding_number(vertices, point): r""" Compute the winding number of the given point in the plane `z = 0`. diff --git a/src/sage/plot/hyperbolic_regular_polygon.py b/src/sage/plot/hyperbolic_regular_polygon.py index 9be2169ab63..17397dce3f4 100644 --- a/src/sage/plot/hyperbolic_regular_polygon.py +++ b/src/sage/plot/hyperbolic_regular_polygon.py @@ -117,7 +117,7 @@ def __init__(self, sides, i_angle, center, options): raise ValueError("interior angle %s must be in (0, pi) interval" % (i_angle)) if pi*(sides-2) - sides*i_angle <= 0: raise ValueError("there exists no hyperbolic regular compact polygon," - " for sides=%s the interior angle must be less than %s" % (sides, pi * (sides-2) / sides)) + " for sides={} the interior angle must be less than {}".format(sides, pi * (sides-2) / sides)) self.sides = sides self.i_angle = i_angle beta = 2 * pi / self.sides # compute the rotation angle to be used ahead @@ -168,8 +168,7 @@ def _repr_(self): sage: HyperbolicRegularPolygon(5,pi/2,I, {}) Hyperbolic regular polygon (sides=5, i_angle=1/2*pi, center=1.00000000000000*I) """ - return ("Hyperbolic regular polygon (sides=%s, i_angle=%s, center=%s)" - % (self.sides, self.i_angle, self.center)) + return ("Hyperbolic regular polygon (sides={}, i_angle={}, center={})".format(self.sides, self.i_angle, self.center)) def _i_rotation(self, z, alpha): r""" @@ -200,6 +199,7 @@ def _i_rotation(self, z, alpha): G = matrix([[_c, _s], [-_s, _c]]) return (G[0][0] * z + G[0][1]) / (G[1][0] * z + G[1][1]) + @rename_keyword(color='rgbcolor') @options(alpha=1, fill=False, thickness=1, rgbcolor="blue", zorder=2, linestyle='solid') diff --git a/src/sage/plot/matrix_plot.py b/src/sage/plot/matrix_plot.py index 96e966a6513..da55e540890 100644 --- a/src/sage/plot/matrix_plot.py +++ b/src/sage/plot/matrix_plot.py @@ -162,7 +162,7 @@ def _repr_(self): sage: m = M[0]; m # needs sage.symbolic MatrixPlot defined by a 5 x 5 data grid """ - return "MatrixPlot defined by a %s x %s data grid" % (self.xy_array_row, self.xy_array_col) + return "MatrixPlot defined by a {} x {} data grid".format(self.xy_array_row, self.xy_array_col) def _render_on_subplot(self, subplot): """ @@ -195,9 +195,9 @@ def _render_on_subplot(self, subplot): rowstyle = subdiv_options['style'] colstyle = subdiv_options['style'] if rowstyle is None: - rowstyle = dict() + rowstyle = {} if colstyle is None: - colstyle = dict() + colstyle = {} # Make line objects for subdivisions from .line import line2d @@ -224,10 +224,10 @@ def _render_on_subplot(self, subplot): extent = (lim['xmin'], lim['xmax'], lim['ymax' if flip_y else 'ymin'], lim['ymin' if flip_y else 'ymax']) - opts = dict(cmap=cmap, interpolation='nearest', aspect='equal', - norm=norm, vmin=options['vmin'], vmax=options['vmax'], - origin=('upper' if flip_y else 'lower'), - extent=extent, zorder=options.get('zorder')) + opts = {'cmap': cmap, 'interpolation': 'nearest', 'aspect': 'equal', + 'norm': norm, 'vmin': options['vmin'], 'vmax': options['vmax'], + 'origin': ('upper' if flip_y else 'lower'), + 'extent': extent, 'zorder': options.get('zorder')} image = subplot.imshow(self.xy_data_array, **opts) if options.get('colorbar', False): diff --git a/src/sage/plot/multigraphics.py b/src/sage/plot/multigraphics.py index f22febca152..f04755a7d09 100644 --- a/src/sage/plot/multigraphics.py +++ b/src/sage/plot/multigraphics.py @@ -151,7 +151,7 @@ def __init__(self, graphics_list): else: if not isinstance(ins, (list, tuple)) or len(ins) != 2: raise TypeError("a pair (Graphics, position) is " - "expected, not {}".format(ins)) + f"expected, not {ins}") self.append(ins[0], pos=ins[1]) def _repr_(self): @@ -490,7 +490,7 @@ def save(self, filename, figsize=None, **kwds): # tight_layout adjusts the *subplot* parameters so ticks aren't # cut off, etc. figure.tight_layout() - opts = dict(dpi=dpi, transparent=transparent) + opts = {"dpi": dpi, "transparent": transparent} if fig_tight is True: opts['bbox_inches'] = 'tight' figure.savefig(filename, **opts) @@ -545,7 +545,7 @@ def _latex_(self, **kwds): """ tmpfilename = tmp_filename(ext='.pgf') self.save(filename=tmpfilename, **kwds) - with open(tmpfilename, "r") as tmpfile: + with open(tmpfilename) as tmpfile: latex_list = tmpfile.readlines() return ''.join(latex_list) @@ -741,8 +741,8 @@ def __str__(self): """ n = len(self._glist) if n <= 1: - return "Multigraphics with {} element".format(n) - return "Multigraphics with {} elements".format(n) + return f"Multigraphics with {n} element" + return f"Multigraphics with {n} elements" def _add_subplot(self, figure, index, **options): r""" @@ -910,7 +910,7 @@ def append(self, graphics, pos=None): from matplotlib import rcParams if not isinstance(graphics, Graphics): raise TypeError("a Graphics object is expected, " - "not {}".format(graphics)) + f"not {graphics}") if pos is None: # Default position: left = rcParams['figure.subplot.left'] @@ -919,7 +919,7 @@ def append(self, graphics, pos=None): height = rcParams['figure.subplot.top'] - bottom pos = (left, bottom, width, height) elif not isinstance(pos, (list, tuple)) or len(pos) != 4: - raise TypeError("pos must be a 4-tuple, not {}".format(pos)) + raise TypeError(f"pos must be a 4-tuple, not {pos}") pos = tuple(float(p) for p in pos) self._glist.append(graphics) self._positions.append(pos) @@ -1142,7 +1142,7 @@ def __init__(self, array): MultiGraphics.__init__(self, []) if not isinstance(array, (list, tuple)): raise TypeError("array must be a list of lists of Graphics " - "objects, not {}".format(array)) + f"objects, not {array}") array = list(array) self._rows = len(array) if self._rows > 0: @@ -1155,7 +1155,7 @@ def __init__(self, array): for row in array: # basically flatten the list if not isinstance(row, (list, tuple)) or len(row) != self._cols: raise TypeError("array must be a list of equal-size lists of " - "Graphics objects, not {}".format(array)) + f"Graphics objects, not {array}") for g in row: if not isinstance(g, Graphics): raise TypeError("every element of array must be a " @@ -1179,7 +1179,7 @@ def __str__(self): 'Graphics Array of size 2 x 3' """ - return "Graphics Array of size {} x {}".format(self._rows, self._cols) + return f"Graphics Array of size {self._rows} x {self._cols}" def _add_subplot(self, figure, index, **options): r""" diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 20a71ef8bd1..2f830297d4b 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -673,6 +673,7 @@ def f(x): return (x-3)*(x-5)*(x-7)+40 _SelectiveFormatterClass = None + def SelectiveFormatter(formatter, skip_values): """ This matplotlib formatter selectively omits some tick values and @@ -773,6 +774,7 @@ def __call__(self, x, *args, **kwds): return _SelectiveFormatterClass(formatter, skip_values) + def xydata_from_point_list(points): r""" Return two lists (xdata, ydata), each coerced to a list of floats, @@ -837,6 +839,7 @@ def xydata_from_point_list(points): ydata.append(float(y)) return xdata, ydata + @options(alpha=1, thickness=1, fill=False, fillcolor='automatic', fillalpha=0.5, plot_points=200, adaptive_tolerance=0.01, adaptive_recursion=5, detect_poles=False, exclude=None, @@ -2066,13 +2069,14 @@ def f(x): return (floor(x)+0.5) / (1-(x-0.5)**2) xmax = kwds.pop('xmax', 1) G = _plot(funcs, (xmin, xmax), *args, **kwds) else: - sage.misc.verbose.verbose("there were %s extra arguments (besides %s)" % (n, funcs), level=0) + sage.misc.verbose.verbose("there were {} extra arguments (besides {})".format(n, funcs), level=0) G._set_extra_kwds(G_kwds) if do_show: G.show() return G + def _plot(funcs, xrange, parametric=False, polar=False, fill=False, label='', randomize=True, **options): """ @@ -2427,7 +2431,7 @@ def golden_rainbow(i,lightness=0.4): fstr = 'max' else: fstr = 'min' - msg = "WARNING: You use the built-in function %s for filling. You probably wanted the string '%s'." % (fstr, fstr) + msg = "WARNING: You use the built-in function {} for filling. You probably wanted the string '{}'.".format(fstr, fstr) sage.misc.verbose.verbose(msg, level=0) if not is_fast_float(fill): fill_f = fast_float(fill, expect_one_var=True) @@ -2760,6 +2764,7 @@ def parametric_plot(funcs, *args, **kwargs): else: raise ValueError("the number of functions and the number of variable ranges is not a supported combination for a 2d or 3d parametric plots") + @options(aspect_ratio=1.0) def polar_plot(funcs, *args, **kwds): r""" @@ -2865,6 +2870,7 @@ def polar_plot(funcs, *args, **kwds): kwds['polar'] = True return plot(funcs, *args, **kwds) + @options(aspect_ratio='automatic') def list_plot(data, plotjoined=False, **kwargs): r""" @@ -3154,6 +3160,8 @@ def list_plot(data, plotjoined=False, **kwargs): return point(data, **kwargs) #------------------------ Graphs on log scale ---------------------------# + + @options(base=10) def plot_loglog(funcs, *args, **kwds): """ @@ -3204,6 +3212,7 @@ def plot_loglog(funcs, *args, **kwds): """ return plot(funcs, *args, scale='loglog', **kwds) + @options(base=10) def plot_semilogx(funcs, *args, **kwds): """ @@ -3256,6 +3265,7 @@ def plot_semilogx(funcs, *args, **kwds): """ return plot(funcs, *args, scale='semilogx', **kwds) + @options(base=10) def plot_semilogy(funcs, *args, **kwds): """ @@ -3294,6 +3304,7 @@ def plot_semilogy(funcs, *args, **kwds): """ return plot(funcs, *args, scale='semilogy', **kwds) + @options(base=10) def list_plot_loglog(data, plotjoined=False, **kwds): """ @@ -3361,6 +3372,7 @@ def list_plot_loglog(data, plotjoined=False, **kwds): """ return list_plot(data, plotjoined=plotjoined, scale='loglog', **kwds) + @options(base=10) def list_plot_semilogx(data, plotjoined=False, **kwds): """ @@ -3416,6 +3428,7 @@ def list_plot_semilogx(data, plotjoined=False, **kwds): """ return list_plot(data, plotjoined=plotjoined, scale='semilogx', **kwds) + @options(base=10) def list_plot_semilogy(data, plotjoined=False, **kwds): """ @@ -3474,6 +3487,7 @@ def list_plot_semilogy(data, plotjoined=False, **kwds): """ return list_plot(data, plotjoined=plotjoined, scale='semilogy', **kwds) + def to_float_list(v): """ Given a list or tuple or iterable v, coerce each element of v to a @@ -3487,6 +3501,7 @@ def to_float_list(v): """ return [float(x) for x in v] + def reshape(v, n, m): """ Helper function for creating graphics arrays. @@ -3553,6 +3568,7 @@ def reshape(v, n, m): return L + def graphics_array(array, nrows=None, ncols=None): r""" Plot a list of lists (or tuples) of graphics objects on one canvas, @@ -3723,6 +3739,7 @@ def h(x): return sin(4*x) array = reshape(array, nrows, ncols) return GraphicsArray(array) + def multi_graphics(graphics_list): r""" Plot a list of graphics at specified positions on a single canvas. @@ -3797,6 +3814,7 @@ def multi_graphics(graphics_list): """ return MultiGraphics(graphics_list) + def minmax_data(xdata, ydata, dict=False): """ Return the minimums and maximums of ``xdata`` and ``ydata``. @@ -3832,6 +3850,7 @@ def minmax_data(xdata, ydata, dict=False): else: return xmin, xmax, ymin, ymax + def adaptive_refinement(f, p1, p2, adaptive_tolerance=0.01, adaptive_recursion=5, level=0, *, excluded=False): r""" @@ -3913,14 +3932,14 @@ def adaptive_refinement(f, p1, p2, adaptive_tolerance=0.01, try: y = float(f(x)) if str(y) in ['nan', 'NaN', 'inf', '-inf']: - sage.misc.verbose.verbose("%s\nUnable to compute f(%s)" % (msg, x),1) + sage.misc.verbose.verbose(f"{msg}\nUnable to compute f({x})",1) # give up for this branch if excluded: return [(x, 'NaN')] return [] except (ZeroDivisionError, TypeError, ValueError, OverflowError) as msg: - sage.misc.verbose.verbose("%s\nUnable to compute f(%s)" % (msg, x), 1) + sage.misc.verbose.verbose(f"{msg}\nUnable to compute f({x})", 1) # give up for this branch if excluded: return [(x, 'NaN')] @@ -3942,6 +3961,7 @@ def adaptive_refinement(f, p1, p2, adaptive_tolerance=0.01, else: return [] + def generate_plot_points(f, xrange, plot_points=5, adaptive_tolerance=0.01, adaptive_recursion=5, randomize=True, initial_points=None, *, excluded=False, @@ -4073,7 +4093,7 @@ def generate_plot_points(f, xrange, plot_points=5, adaptive_tolerance=0.01, exception_indices.append(i) except (ArithmeticError, TypeError, ValueError) as m: - sage.misc.verbose.verbose("%s\nUnable to compute f(%s)" % (m, xi), 1) + sage.misc.verbose.verbose(f"{m}\nUnable to compute f({xi})", 1) if i == 0: # Given an error for left endpoint, try to move it in slightly for j in range(1, 99): diff --git a/src/sage/plot/plot3d/list_plot3d.py b/src/sage/plot/plot3d/list_plot3d.py index 7bfd84f76a4..a2b0781796c 100644 --- a/src/sage/plot/plot3d/list_plot3d.py +++ b/src/sage/plot/plot3d/list_plot3d.py @@ -264,7 +264,7 @@ def list_plot3d(v, interpolation_type='default', point_list=None, **kwds): kwds['color'] = txtr if is_Matrix(v): if (interpolation_type == 'default' or - interpolation_type == 'linear' and 'num_points' not in kwds): + interpolation_type == 'linear' and 'num_points' not in kwds): return list_plot3d_matrix(v, **kwds) else: data = [(i, j, v[i, j]) @@ -563,7 +563,7 @@ def list_plot3d_tuples(v, interpolation_type, **kwds): # noise to avoid the problem if needed. corr_matrix = numpy.corrcoef(x, y) if not (-0.9 <= corr_matrix[0, 1] <= 0.9): - ep = float(.000001) + ep = .000001 x = [float(p[0]) + random() * ep for p in v] y = [float(p[1]) + random() * ep for p in v] @@ -607,6 +607,7 @@ def list_plot3d_tuples(v, interpolation_type, **kwds): def g(x, y): z = f(x, y) return (x, y, z) + G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points * j]), list(numpy.r_[ymin:ymax:num_points * j])), **kwds) @@ -623,6 +624,7 @@ def g(x, y): def g(x, y): z = f([x, y]).item() return (x, y, z) + G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points * j]), list(numpy.r_[ymin:ymax:num_points * j])), **kwds) @@ -636,10 +638,11 @@ def g(x, y): kx = kwds['degree'] ky = kwds['degree'] s = kwds.get('smoothing', len(x) - numpy.sqrt(2 * len(x))) - s = interpolate.bisplrep(x, y, z, [int(1)] * len(x), xmin, xmax, + s = interpolate.bisplrep(x, y, z, [1] * len(x), xmin, xmax, ymin, ymax, kx=kx, ky=ky, s=s) def f(x, y): return interpolate.bisplev(x, y, s) + return plot3d(f, (xmin, xmax), (ymin, ymax), plot_points=[num_points, num_points], **kwds) diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index 2e027e87dd2..83845dc9494 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -158,7 +158,7 @@ def f(x,y): return math.exp(x/5)*math.cos(y) from sage.misc.sageinspect import sage_getargspec, is_function_or_cython_function -class _Coordinates(): +class _Coordinates: """ This abstract class encapsulates a new coordinate system for plotting. Sub-classes must implement the :meth:`transform` method which, given @@ -348,14 +348,14 @@ def to_cartesian(self, func, params=None): def subs_func(t): # We use eval so that the lambda function has the same # variable names as the original function - ll = """lambda {x},{y}: t.subs({{ - dep_var_dummy: float(func({x}, {y})), - indep_var_dummies[0]: float({x}), - indep_var_dummies[1]: float({y}) - }})""".format(x=params[0], y=params[1]) - return eval(ll, dict(t=t, func=func, - dep_var_dummy=dep_var_dummy, - indep_var_dummies=indep_var_dummies)) + ll = f"""lambda {params[0]},{params[1]}: t.subs({{ + dep_var_dummy: float(func({params[0]}, {params[1]})), + indep_var_dummies[0]: float({params[0]}), + indep_var_dummies[1]: float({params[1]}) + }})""" + return eval(ll, {'t': t, 'func': func, + 'dep_var_dummy': dep_var_dummy, + 'indep_var_dummies': indep_var_dummies}) return [subs_func(m) for m in transformation] def __repr__(self): @@ -373,8 +373,7 @@ def __repr__(self): sage: c My Special Coordinates coordinate transform (z in terms of x, y) """ - return '%s coordinate transform (%s in terms of %s)' % \ - (self._name, self.dep_var, ', '.join(self.indep_vars)) + return '{} coordinate transform ({} in terms of {})'.format(self._name, self.dep_var, ', '.join(self.indep_vars)) def _find_arguments_for_callable(func): @@ -471,6 +470,7 @@ def transform(self, **kwds): """ return tuple(t.subs(**kwds) for t in self.custom_trans) + class Spherical(_Coordinates): """ A spherical coordinate system for use with ``plot3d(transformation=...)`` @@ -542,6 +542,7 @@ def transform(self, radius=None, azimuth=None, inclination=None): radius * sin(inclination) * sin(azimuth), radius * cos(inclination)) + class SphericalElevation(_Coordinates): """ A spherical coordinate system for use with ``plot3d(transformation=...)`` @@ -660,6 +661,7 @@ def transform(self, radius=None, azimuth=None, elevation=None): radius * cos(elevation) * sin(azimuth), radius * sin(elevation)) + class Cylindrical(_Coordinates): """ A cylindrical coordinate system for use with ``plot3d(transformation=...)`` @@ -730,6 +732,7 @@ def transform(self, radius=None, azimuth=None, height=None): radius * sin(azimuth), height) + class TrivialTriangleFactory: """ Class emulating behavior of :class:`~sage.plot.plot3d.tri_plot.TriangleFactory` @@ -794,6 +797,8 @@ def smooth_triangle(self, a, b, c, da, db, dc, color=None): from . import parametric_plot3d + + def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): """ Plots a function in 3d. @@ -1118,6 +1123,7 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): P.frame_aspect_ratio([1.0,1.0,0.5]) return P + def plot3d_adaptive(f, x_range, y_range, color="automatic", grad_f=None, max_bend=.5, max_depth=5, initial_depth=4, num_colors=128, **kwds): @@ -1323,6 +1329,7 @@ def spherical_plot3d(f, urange, vrange, **kwds): """ return plot3d(f, urange, vrange, transformation=Spherical('radius', ['azimuth', 'inclination']), **kwds) + def cylindrical_plot3d(f, urange, vrange, **kwds): """ Plots a function in cylindrical coordinates. This function is @@ -1397,6 +1404,7 @@ def cylindrical_plot3d(f, urange, vrange, **kwds): """ return plot3d(f, urange, vrange, transformation=Cylindrical('radius', ['azimuth', 'height']), **kwds) + def axes(scale=1, radius=None, **kwds): """ Creates basic axes in three dimensions. Each axis is a three diff --git a/src/sage/plot/plot3d/revolution_plot3d.py b/src/sage/plot/plot3d/revolution_plot3d.py index f3220dcd1a3..6349fabbdd5 100644 --- a/src/sage/plot/plot3d/revolution_plot3d.py +++ b/src/sage/plot/plot3d/revolution_plot3d.py @@ -25,6 +25,7 @@ from sage.plot.plot3d.parametric_plot3d import parametric_plot3d + @rename_keyword(alpha='opacity') def revolution_plot3d(curve,trange,phirange=None,parallel_axis='z',axis=(0,0),print_vector=False,show_curve=False,**kwds): r""" diff --git a/src/sage/plot/plot3d/shapes2.py b/src/sage/plot/plot3d/shapes2.py index 96e4646bbc4..7fe8aeb18a2 100644 --- a/src/sage/plot/plot3d/shapes2.py +++ b/src/sage/plot/plot3d/shapes2.py @@ -942,9 +942,8 @@ def tachyon_repr(self, render_params): radius = self.size * TACHYON_PIXEL texture = self.texture.id - return ("Sphere center {center[0]!r} {center[1]!r} {center[2]!r} " - "Rad {radius!r} {texture}").format(center=cen, radius=radius, - texture=texture) + return (f"Sphere center {cen[0]!r} {cen[1]!r} {cen[2]!r} " + f"Rad {radius!r} {texture}") def obj_repr(self, render_params): """ @@ -980,7 +979,7 @@ def jmol_repr(self, render_params): name = render_params.unique_name('point') transform = render_params.transform cen = self.loc if transform is None else transform(self.loc) - return ["draw %s DIAMETER %s {%s %s %s}\n%s" % (name, int(self.size), cen[0], cen[1], cen[2], self.texture.jmol_str('$' + name))] + return ["draw {} DIAMETER {} {{{} {} {}}}\n{}".format(name, int(self.size), cen[0], cen[1], cen[2], self.texture.jmol_str('$' + name))] def threejs_repr(self, render_params): r""" @@ -1010,7 +1009,7 @@ def threejs_repr(self, render_params): color = '#' + str(self.texture.hex_rgb()) opacity = float(self.texture.opacity) size = float(self.size) - point = dict(point=center, size=size, color=color, opacity=opacity) + point = {'point': center, 'size': size, 'color': color, 'opacity': opacity} return [('point', point)] def stl_binary_repr(self, render_params): @@ -1198,13 +1197,13 @@ def jmol_repr(self, render_params): TP = P if T is None else T(P) if P in corners: if cmd: - cmds.append(cmd + " {%s %s %s} " % TP) + cmds.append(cmd + " {{{} {} {}}} ".format(*TP)) cmds.append(self.texture.jmol_str('$' + name)) type = 'arrow' if self.arrow_head and P is last_corner else 'curve' name = render_params.unique_name('line') - cmd = "draw %s diameter %s %s {%s %s %s} " % (name, int(self.thickness), type, TP[0], TP[1], TP[2]) + cmd = "draw {} diameter {} {} {{{} {} {}}} ".format(name, int(self.thickness), type, TP[0], TP[1], TP[2]) else: - cmd += " {%s %s %s} " % TP + cmd += " {{{} {} {}}} ".format(*TP) cmds.append(cmd) cmds.append(self.texture.jmol_str('$' + name)) return cmds @@ -1392,7 +1391,7 @@ def threejs_repr(self, render_params): transform = render_params.transform if transform is not None: points = [transform(p) for p in points] - line = dict(points=points, color=color, opacity=opacity, linewidth=thickness) + line = {'points': points, 'color': color, 'opacity': opacity, 'linewidth': thickness} reprs.append(('line', line)) return reprs diff --git a/src/sage/plot/plot3d/tachyon.py b/src/sage/plot/plot3d/tachyon.py index 4e8184a7816..21a53787610 100644 --- a/src/sage/plot/plot3d/tachyon.py +++ b/src/sage/plot/plot3d/tachyon.py @@ -629,7 +629,7 @@ def _res(self): sage: t._res() '\nresolution 300 700\n' """ - return '\nresolution %s %s\n' % (self._xres, self._yres) + return f'\nresolution {self._xres} {self._yres}\n' def _camera(self): r""" @@ -651,20 +651,14 @@ def _camera(self): if self._aperture != '': camera_out = camera_out + r""" aperture %s""" % (float(self._aperture)) - camera_out = camera_out + r""" - zoom %s - aspectratio %s - antialiasing %s - raydepth %s - center %s - viewdir %s - updir %s""" % (float(self._zoom), - float(self._aspectratio), - int(self._antialiasing), - int(self._raydepth), - tostr(self._camera_position), - tostr(self._viewdir), - tostr(self._updir)) + camera_out = camera_out + fr""" + zoom {float(self._zoom)} + aspectratio {float(self._aspectratio)} + antialiasing {int(self._antialiasing)} + raydepth {int(self._raydepth)} + center {tostr(self._camera_position)} + viewdir {tostr(self._viewdir)} + updir {tostr(self._updir)}""" if self._frustum != '': camera_out = camera_out + r""" frustum %s""" % (tostr(self._frustum)) @@ -691,10 +685,10 @@ def str(self): """ return r""" begin_scene - %s - %s - %s - end_scene""" % (self._res(), + {} + {} + {} + end_scene""".format(self._res(), self._camera(), '\n'.join(x.str() for x in self._objects)) @@ -1083,7 +1077,7 @@ def parametric_plot(self, f, t_0, t_f, tex, r=.1, cylinders=True, e_rel=.01, e_abs=.01)) -class Light(): +class Light: r""" Represent lighting objects. @@ -1125,15 +1119,14 @@ def str(self): color 1.0 1.0 1.0 """ - return r""" - light center %s - rad %s - color %s - """ % (tostr(self._center), self._radius, - tostr(self._color)) + return fr""" + light center {tostr(self._center)} + rad {self._radius} + color {tostr(self._color)} + """ -class Texfunc(): +class Texfunc: def __init__(self, ttype=0, center=(0, 0, 0), rotate=(0, 0, 0), scale=(1, 1, 1), imagefile=''): @@ -1195,7 +1188,7 @@ def str(self): raise ValueError -class Texture(): +class Texture: def __init__(self, name, ambient=0.2, diffuse=0.8, specular=0.0, opacity=1.0, @@ -1255,10 +1248,10 @@ def str(self): ['ambient', '0.2', 'diffuse', '0.8'] """ return r""" - texdef %s ambient %s diffuse %s specular %s opacity %s - phong %s %s phong_size %s - color %s texfunc %s - """ % (self._name, + texdef {} ambient {} diffuse {} specular {} opacity {} + phong {} {} phong_size {} + color {} texfunc {} + """.format(self._name, self._ambient, self._diffuse, self._specular, @@ -1270,7 +1263,7 @@ def str(self): self._texfunc) -class Sphere(): +class Sphere: r""" A class for creating spheres in tachyon. """ @@ -1305,12 +1298,12 @@ def str(self): sage: s.str() '\n sphere center 1.0 1.0 1.0 rad 1.0 r\n ' """ - return r""" - sphere center %s rad %s %s - """ % (tostr(self._center), self._radius, self._texture) + return fr""" + sphere center {tostr(self._center)} rad {self._radius} {self._texture} + """ -class Ring(): +class Ring: r""" An annulus of zero thickness. """ @@ -1346,12 +1339,12 @@ def str(self): '\n ring center 0.0 0.0 0.0 normal 1.0 1.0 0.0 inner 1.0 outer 2.0 s\n ' """ return r""" - ring center %s normal %s inner %s outer %s %s - """ % (tostr(self._center), tostr(self._normal), + ring center {} normal {} inner {} outer {} {} + """.format(tostr(self._center), tostr(self._normal), self._inner, self._outer, self._texture) -class FractalLandscape(): +class FractalLandscape: r""" Axis-aligned fractal landscape. @@ -1388,12 +1381,12 @@ def str(self): '\n scape res 20 20 scale 30 30 center 1.0 2.0 3.0 s\n ' """ return r""" - scape res %s scale %s center %s %s - """ % (tostr(self._res, 2, int), tostr(self._scale, 2, int), + scape res {} scale {} center {} {} + """.format(tostr(self._res, 2, int), tostr(self._scale, 2, int), tostr(self._center), self._texture) -class Cylinder(): +class Cylinder: r""" An infinite cylinder. """ @@ -1429,11 +1422,11 @@ def str(self): '\n cylinder center 0.0 0.0 0.0 axis 1.0 1.0 1.0 rad 0.1 s\n ' """ return r""" - cylinder center %s axis %s rad %s %s - """ % (tostr(self._center), tostr(self._axis), self._radius, self._texture) + cylinder center {} axis {} rad {} {} + """.format(tostr(self._center), tostr(self._axis), self._radius, self._texture) -class Plane(): +class Plane: r""" An infinite plane. """ @@ -1465,12 +1458,12 @@ def str(self): sage: p.str() '\n plane center 1.0 2.0 3.0 normal 1.0 2.0 4.0 s\n ' """ - return r""" - plane center %s normal %s %s - """ % (tostr(self._center), tostr(self._normal), self._texture) + return fr""" + plane center {tostr(self._center)} normal {tostr(self._normal)} {self._texture} + """ -class FCylinder(): +class FCylinder: r""" A finite cylinder. """ @@ -1504,11 +1497,11 @@ def str(self): '\n fcylinder base 0.0 0.0 0.0 apex 1.0 1.0 1.0 rad 0.1 s\n ' """ return r""" - fcylinder base %s apex %s rad %s %s - """ % (tostr(self._center), tostr(self._axis), self._radius, self._texture) + fcylinder base {} apex {} rad {} {} + """.format(tostr(self._center), tostr(self._axis), self._radius, self._texture) -class Axis_aligned_box(): +class Axis_aligned_box: r""" Box with axis-aligned edges with the given min and max coordinates. """ @@ -1540,9 +1533,9 @@ def str(self): sage: aab.str() '\n box min 0.0 0.0 0.0 max 1.0 1.0 1.0 s\n ' """ - return r""" - box min %s max %s %s - """ % (tostr(self._min_p), tostr(self._max_p), self._texture) + return fr""" + box min {tostr(self._min_p)} max {tostr(self._max_p)} {self._texture} + """ class TachyonTriangle(Triangle): @@ -1560,10 +1553,10 @@ def str(self): sage: t.str() '\n TRI V0 -1.0 -1.0 -1.0 V1 0.0 0.0 0.0 V2 1.0 2.0 3.0 \n 0\n ' """ - return r""" - TRI V0 %s V1 %s V2 %s - %s - """ % (tostr(self._a), tostr(self._b), tostr(self._c), self._color) + return fr""" + TRI V0 {tostr(self._a)} V1 {tostr(self._b)} V2 {tostr(self._c)} + {self._color} + """ class TachyonSmoothTriangle(SmoothTriangle): @@ -1581,12 +1574,11 @@ def str(self): sage: t.str() '\n STRI V0 ... 1.0 0.0 0.0 N1 0.0 1.0 0.0 N2 0.0 0.0 1.0 \n 0\n ' """ - return r""" - STRI V0 %s V1 %s V2 %s - N0 %s N1 %s N2 %s - %s - """ % (tostr(self._a), tostr(self._b), tostr(self._c), - tostr(self._da), tostr(self._db), tostr(self._dc), self._color) + return fr""" + STRI V0 {tostr(self._a)} V1 {tostr(self._b)} V2 {tostr(self._c)} + N0 {tostr(self._da)} N1 {tostr(self._db)} N2 {tostr(self._dc)} + {self._color} + """ class TachyonTriangleFactory(TriangleFactory): @@ -1663,7 +1655,7 @@ def get_colors(self, list): return self._tachyon.texture_recolor(self._texture, list) -class ParametricPlot(): +class ParametricPlot: r""" Parametric plotting routines. """ diff --git a/src/sage/plot/plot3d/texture.py b/src/sage/plot/plot3d/texture.py index c4dee5d3ad5..7e67a08d590 100644 --- a/src/sage/plot/plot3d/texture.py +++ b/src/sage/plot/plot3d/texture.py @@ -339,9 +339,9 @@ def _repr_(self): Texture(texture..., ffff00) """ if self.name is not None: - return "Texture(%s, %s, %s)" % (self.id, self.name, self.hex_rgb()) + return f"Texture({self.id}, {self.name}, {self.hex_rgb()})" else: - return "Texture(%s, %s)" % (self.id, self.hex_rgb()) + return f"Texture({self.id}, {self.hex_rgb()})" def hex_rgb(self): """ @@ -353,7 +353,7 @@ def hex_rgb(self): sage: Texture((1, .5, 0)).hex_rgb() 'ff7f00' """ - return "%02x%02x%02x" % tuple(int(255 * s) for s in self.color) + return "{:02x}{:02x}{:02x}".format(*tuple(int(255 * s) for s in self.color)) def tachyon_str(self): r""" @@ -451,7 +451,7 @@ def jmol_str(self, obj): sage: sum([dodecahedron(center=[2.5*x, 0, 0], color=(1, 0, 0, x/10)) for x in range(11)]).show(aspect_ratio=[1,1,1], frame=False, zoom=2) """ translucent = "translucent %s" % float(1 - self.opacity) if self.opacity < 1 else "" - return "color %s %s [%s,%s,%s]" % (obj, translucent, + return "color {} {} [{},{},{}]".format(obj, translucent, int(255 * self.color[0]), int(255 * self.color[1]), int(255 * self.color[2])) diff --git a/src/sage/plot/plot3d/tri_plot.py b/src/sage/plot/plot3d/tri_plot.py index 256b0d348c3..5eb15299fe5 100644 --- a/src/sage/plot/plot3d/tri_plot.py +++ b/src/sage/plot/plot3d/tri_plot.py @@ -25,6 +25,7 @@ from math import sqrt import random + class Triangle: """ A graphical triangle class. @@ -64,7 +65,7 @@ class of the form sage: print(tri.str()) [0, 0, 0] [-1, 2, 3] [0, 2, 0] 0 """ - return "%s %s %s %s" % (self._a, self._b, self._c, self._color) + return f"{self._a} {self._b} {self._c} {self._color}" def set_color(self, color): """ @@ -95,6 +96,7 @@ def get_vertices(self): """ return (self._a, self._b, self._c) + class SmoothTriangle(Triangle): """ A class for smoothed triangles. @@ -135,7 +137,7 @@ def str(self): sage: print(t.str()) [1, 2, 3] [2, 3, 4] [0, 0, 0] 0 [0, 0, 1] [0, 1, 0] [1, 0, 0] """ - return "%s %s %s %s %s %s %s" % (self._a, self._b, self._c, self._color, self._da, self._db, self._dc) + return "{} {} {} {} {} {} {}".format(self._a, self._b, self._c, self._color, self._da, self._db, self._dc) def get_normals(self): """ diff --git a/src/sage/plot/plot_field.py b/src/sage/plot/plot_field.py index a54a6db185b..c8052fb1520 100644 --- a/src/sage/plot/plot_field.py +++ b/src/sage/plot/plot_field.py @@ -139,7 +139,7 @@ def _repr_(self): 20 """ - return "PlotField defined by a %s x %s vector grid" % ( + return "PlotField defined by a {} x {} vector grid".format( self._options['plot_points'], self._options['plot_points']) def _render_on_subplot(self, subplot): @@ -355,6 +355,6 @@ def plot_slope_field(f, xrange, yrange, **kwds): norm_inverse = lambda x,y: 1/sqrt(f(x, y)**2+1) f_normalized = lambda x,y: f(x, y)*norm_inverse(x, y) else: - norm_inverse = 1 / sqrt((f**2+1)) + norm_inverse = 1 / sqrt(f**2+1) f_normalized = f * norm_inverse return plot_vector_field((norm_inverse, f_normalized), xrange, yrange, **slope_options) diff --git a/src/sage/plot/point.py b/src/sage/plot/point.py index 9377d2bec85..0c2a2897368 100644 --- a/src/sage/plot/point.py +++ b/src/sage/plot/point.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- r""" Points diff --git a/src/sage/plot/primitive.py b/src/sage/plot/primitive.py index 20c2987142f..ee9966846b1 100644 --- a/src/sage/plot/primitive.py +++ b/src/sage/plot/primitive.py @@ -21,6 +21,7 @@ from sage.structure.sage_object import SageObject from sage.misc.verbose import verbose + class GraphicPrimitive(WithEqualityById, SageObject): """ Base class for graphics primitives, e.g., things that knows how to draw @@ -183,7 +184,7 @@ def options(self): for k in O.keys(): if k not in K: do_verify = False - verbose("WARNING: Ignoring option '%s'=%s" % (k, O[k]), + verbose(f"WARNING: Ignoring option '{k}'={O[k]}", level=0) t = True if t: diff --git a/src/sage/plot/text.py b/src/sage/plot/text.py index 602cdfebddf..1c49c102b62 100644 --- a/src/sage/plot/text.py +++ b/src/sage/plot/text.py @@ -85,7 +85,7 @@ def _repr_(self): sage: t = T[0];t # needs sage.symbolic Text 'I like cool constants' at the point (3.1415926535...,2.7182818284...) """ - return "Text '%s' at the point (%s,%s)" % (self.string, self.x, self.y) + return f"Text '{self.string}' at the point ({self.x},{self.y})" def _allowed_options(self): """ From 0c09460e3e1304753e189e7b46508d5d9cbbee24 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 26 Feb 2024 18:56:44 -0800 Subject: [PATCH 079/191] pkgs/sagemath-{objects,categories}: Add 'external' section according to draft PEP 725 --- pkgs/sagemath-categories/pyproject.toml.m4 | 17 +++++++++++++++++ pkgs/sagemath-objects/pyproject.toml.m4 | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/pkgs/sagemath-categories/pyproject.toml.m4 b/pkgs/sagemath-categories/pyproject.toml.m4 index eed48a1db15..edbafa59242 100644 --- a/pkgs/sagemath-categories/pyproject.toml.m4 +++ b/pkgs/sagemath-categories/pyproject.toml.m4 @@ -37,3 +37,20 @@ include-package-data = false [tool.setuptools.dynamic] version = {file = ["VERSION.txt"]} + +[external] +# External dependencies in the format proposed by https://peps.python.org/pep-0725 +build-requires = [ + "virtual:compiler/c", + "virtual:compiler/cpp", + "pkg:generic/pkg-config", +] + +host-requires = [ + "pkg:generic/gmp", + "pkg:generic/mpc", + "pkg:generic/mpfr", +] + +dependencies = [ +] diff --git a/pkgs/sagemath-objects/pyproject.toml.m4 b/pkgs/sagemath-objects/pyproject.toml.m4 index a8d7d83a44a..68cfbafe935 100644 --- a/pkgs/sagemath-objects/pyproject.toml.m4 +++ b/pkgs/sagemath-objects/pyproject.toml.m4 @@ -46,3 +46,20 @@ version = {file = ["VERSION.txt"]} "python_debug.h", ] "sage.rings" = ["integer_fake.h"] + +[external] +# External dependencies in the format proposed by https://peps.python.org/pep-0725 +build-requires = [ + "virtual:compiler/c", + "virtual:compiler/cpp", + "pkg:generic/pkg-config", +] + +host-requires = [ + "pkg:generic/gmp", + "pkg:generic/mpc", + "pkg:generic/mpfr", +] + +dependencies = [ +] From bcde7cac77ebc55c87e35fef70384873eb6f765c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 14:46:40 -0800 Subject: [PATCH 080/191] .github/workflows/dist.yml: Upgrade cibuildwheel to 2.16.5 --- .github/workflows/dist.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 5bf5729039c..b7406d6c8a0 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -156,7 +156,7 @@ jobs: mkdir -p unpacked for pkg in sagemath-objects sagemath-categories; do (cd unpacked && tar xfz - ) < dist/$pkg*.tar.gz - pipx run cibuildwheel==2.16.2 unpacked/$pkg* + pipx run cibuildwheel==2.16.5 unpacked/$pkg* done - uses: actions/upload-artifact@v3 From f254c8e1190afec15b970fcb7f26afa6964d5ef5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 14:57:16 -0800 Subject: [PATCH 081/191] .github/workflows/dist.yml: Also build wheels on macos-14 runners (arm64) --- .github/workflows/dist.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index b7406d6c8a0..e73ae6e83c3 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -116,7 +116,9 @@ jobs: - os: ubuntu-latest arch: i686 - os: macos-latest - arch: auto + arch: x86_64 + - os: macos-14 + arch: arm64 env: # SPKGs to install as system packages SPKGS: _bootstrap _prereq From 1457fed3f0276567954bb34b4fb19276c6b88427 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 15:55:17 -0800 Subject: [PATCH 082/191] .github/workflows/dist.yml: Install pipx --- .github/workflows/dist.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index e73ae6e83c3..4c509763d06 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -143,6 +143,14 @@ jobs: name: dist path: dist + - uses: actions/setup-python@v5 + # As of 2024-02-03, the macOS M1 runners do not have preinstalled python or pipx. + # Installing pipx follows the approach of https://github.com/pypa/cibuildwheel/pull/1743 + id: python + with: + python-version: "3.8 - 3.12" + update-environment: false + - name: Build platform wheels # We build the wheels from the sdists so that MANIFEST filtering becomes effective. # But we must run cibuildwheel with the unpacked source directory, not a tarball, @@ -153,12 +161,13 @@ jobs: # This is unfortunately repeated for each of the packages that we build wheels for # because CIBW starts with a fresh container on each invocation. run: | + "${{ steps.python.outputs.python-path }}" -m pip install pipx export PATH=build/bin:$PATH export CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || echo error ignored) ) && ./bootstrap && ./configure --enable-build-as-root && make -j4 V=0 $TARGETS_PRE" mkdir -p unpacked for pkg in sagemath-objects sagemath-categories; do (cd unpacked && tar xfz - ) < dist/$pkg*.tar.gz - pipx run cibuildwheel==2.16.5 unpacked/$pkg* + "${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.16.5 unpacked/$pkg* done - uses: actions/upload-artifact@v3 From 1af5b2ae7d52247cea20fecd1ca1f37e4386e2f1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 15 Mar 2024 23:50:44 -0700 Subject: [PATCH 083/191] .github/workflows/dist.yml: Use cibuildwheel==2.17.0 --- .github/workflows/dist.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 4c509763d06..4726969a45f 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -167,7 +167,7 @@ jobs: mkdir -p unpacked for pkg in sagemath-objects sagemath-categories; do (cd unpacked && tar xfz - ) < dist/$pkg*.tar.gz - "${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.16.5 unpacked/$pkg* + "${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.17.0 unpacked/$pkg* done - uses: actions/upload-artifact@v3 From 780dbf5544c81d8f12453d9fd1743879ebcd52d3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 29 Feb 2024 18:20:18 -0800 Subject: [PATCH 084/191] src/doc/*/tutorial/programming.rst: In 'standalone script', no need to import from sage.all --- src/doc/de/tutorial/programming.rst | 1 - src/doc/en/tutorial/programming.rst | 1 - src/doc/fr/tutorial/programming.rst | 1 - src/doc/ja/tutorial/programming.rst | 3 +-- src/doc/pt/tutorial/programming.rst | 1 - src/doc/ru/tutorial/programming.rst | 1 - 6 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/doc/de/tutorial/programming.rst b/src/doc/de/tutorial/programming.rst index 9da919fedae..ceeed63c84c 100644 --- a/src/doc/de/tutorial/programming.rst +++ b/src/doc/de/tutorial/programming.rst @@ -177,7 +177,6 @@ Polynome, usw.: #!/usr/bin/env sage import sys - from sage.all import * if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) diff --git a/src/doc/en/tutorial/programming.rst b/src/doc/en/tutorial/programming.rst index 57dac68ae1c..7e4fd9b3468 100644 --- a/src/doc/en/tutorial/programming.rst +++ b/src/doc/en/tutorial/programming.rst @@ -166,7 +166,6 @@ etc: #!/usr/bin/env sage import sys - from sage.all import * if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) diff --git a/src/doc/fr/tutorial/programming.rst b/src/doc/fr/tutorial/programming.rst index f109e121414..32f465cfc5c 100644 --- a/src/doc/fr/tutorial/programming.rst +++ b/src/doc/fr/tutorial/programming.rst @@ -176,7 +176,6 @@ entiers, des polynômes, etc. : #!/usr/bin/env sage import sys - from sage.all import * if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) diff --git a/src/doc/ja/tutorial/programming.rst b/src/doc/ja/tutorial/programming.rst index df8d6d4112c..1232c1bf1e6 100644 --- a/src/doc/ja/tutorial/programming.rst +++ b/src/doc/ja/tutorial/programming.rst @@ -140,10 +140,9 @@ Cythonソースファイルから生成されたC言語コードをコンパイ :: - #!/usr/bin/env sage -python + #!/usr/bin/env sage import sys - from sage.all import * if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) diff --git a/src/doc/pt/tutorial/programming.rst b/src/doc/pt/tutorial/programming.rst index 08c0a4713e3..ea1d6b2e348 100644 --- a/src/doc/pt/tutorial/programming.rst +++ b/src/doc/pt/tutorial/programming.rst @@ -192,7 +192,6 @@ O seguinte script em Sage fatora inteiros, polinômios, etc: #!/usr/bin/env sage import sys - from sage.all import * if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) diff --git a/src/doc/ru/tutorial/programming.rst b/src/doc/ru/tutorial/programming.rst index 826d3b6df4a..0ea10634c0b 100644 --- a/src/doc/ru/tutorial/programming.rst +++ b/src/doc/ru/tutorial/programming.rst @@ -162,7 +162,6 @@ C и обработан компилятором C. #!/usr/bin/env sage import sys - from sage.all import * if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) From b474439b71b3f7df2c887c6d0417746b63e98b2e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 31 Mar 2024 22:28:44 -0700 Subject: [PATCH 085/191] sage.modular: Docstring/doctest cosmetics --- .../modular/arithgroup/arithgroup_element.pyx | 7 +- src/sage/modular/cusps_nf.py | 4 +- src/sage/modular/dirichlet.py | 121 +++++++++---- src/sage/modular/hypergeometric_motive.py | 8 +- src/sage/modular/modform/ambient_R.py | 7 +- src/sage/modular/modform/ring.py | 2 +- .../graded_ring_element.py | 8 +- .../hecke_triangle_group_element.py | 68 ++++---- src/sage/modular/modsym/p1list_nf.py | 145 ++++++++-------- src/sage/modular/overconvergent/genus0.py | 159 +++++++++++------- 10 files changed, 307 insertions(+), 222 deletions(-) diff --git a/src/sage/modular/arithgroup/arithgroup_element.pyx b/src/sage/modular/arithgroup/arithgroup_element.pyx index 52c6a692866..15d426a9d0d 100644 --- a/src/sage/modular/arithgroup/arithgroup_element.pyx +++ b/src/sage/modular/arithgroup/arithgroup_element.pyx @@ -39,12 +39,11 @@ cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement): - ``parent`` -- an arithmetic subgroup - - `x` -- data defining a 2x2 matrix over ZZ - which lives in parent + - ``x`` -- data defining a 2x2 matrix over ZZ + which lives in ``parent`` - ``check`` -- if ``True``, check that parent is an arithmetic - subgroup, and that `x` defines a matrix of - determinant `1`. + subgroup, and that `x` defines a matrix of determinant `1`. We tend not to create elements of arithmetic subgroups that are not SL2Z, in order to avoid coercion issues (that is, the other arithmetic diff --git a/src/sage/modular/cusps_nf.py b/src/sage/modular/cusps_nf.py index 8d8b580a74e..d2a7eb8942e 100644 --- a/src/sage/modular/cusps_nf.py +++ b/src/sage/modular/cusps_nf.py @@ -944,7 +944,7 @@ def is_Gamma0_equivalent(self, other, N, Transformation=False): :: - sage: k. = NumberField(x^2+23) + sage: k. = NumberField(x^2 + 23) sage: N = k.ideal(3) sage: alpha1 = NFCusp(k, a+1, 4) sage: alpha2 = NFCusp(k, a-8, 29) @@ -1188,7 +1188,7 @@ def NFCusps_ideal_reps_for_levelN(N, nlists=1): :: - sage: k. = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133) + sage: k. = NumberField(x^4 - x^3 - 21*x^2 + 17*x + 133) sage: N = k.ideal(6) sage: from sage.modular.cusps_nf import NFCusps_ideal_reps_for_levelN sage: NFCusps_ideal_reps_for_levelN(N) diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index 7b0c28c5c32..3f871dadf91 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -16,14 +16,15 @@ sage: G = DirichletGroup(35) sage: x = G.gens() sage: e = x[0]*x[1]^2; e - Dirichlet character modulo 35 of conductor 35 mapping 22 |--> zeta12^3, 31 |--> zeta12^2 - 1 + Dirichlet character modulo 35 of conductor 35 + mapping 22 |--> zeta12^3, 31 |--> zeta12^2 - 1 sage: e.order() 12 This illustrates a canonical coercion:: sage: e = DirichletGroup(5, QQ).0 - sage: f = DirichletGroup(5,CyclotomicField(4)).0 + sage: f = DirichletGroup(5, CyclotomicField(4)).0 sage: e*f Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4 @@ -118,7 +119,8 @@ def kronecker_character(d): EXAMPLES:: sage: kronecker_character(97*389*997^2) - Dirichlet character modulo 37733 of conductor 37733 mapping 1557 |--> -1, 37346 |--> -1 + Dirichlet character modulo 37733 of conductor 37733 + mapping 1557 |--> -1, 37346 |--> -1 :: @@ -148,7 +150,8 @@ def kronecker_character_upside_down(d): EXAMPLES:: sage: kronecker_character_upside_down(97*389*997^2) - Dirichlet character modulo 37506941597 of conductor 37733 mapping 13533432536 |--> -1, 22369178537 |--> -1, 14266017175 |--> 1 + Dirichlet character modulo 37506941597 of conductor 37733 + mapping 13533432536 |--> -1, 22369178537 |--> -1, 14266017175 |--> 1 AUTHORS: @@ -213,7 +216,8 @@ def __init__(self, parent, x, check=True): sage: G. = DirichletGroup(13) sage: G - Group of Dirichlet characters modulo 13 with values in Cyclotomic Field of order 12 and degree 4 + Group of Dirichlet characters modulo 13 with values + in Cyclotomic Field of order 12 and degree 4 sage: e Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12 sage: loads(e.dumps()) == e @@ -223,7 +227,8 @@ def __init__(self, parent, x, check=True): sage: G, x = DirichletGroup(35).objgens() sage: e = x[0]*x[1]; e - Dirichlet character modulo 35 of conductor 35 mapping 22 |--> zeta12^3, 31 |--> zeta12^2 + Dirichlet character modulo 35 of conductor 35 + mapping 22 |--> zeta12^3, 31 |--> zeta12^2 sage: e.order() 12 sage: loads(e.dumps()) == e @@ -242,14 +247,16 @@ def __init__(self, parent, x, check=True): sage: G([i, -1, -1]) Traceback (most recent call last): ... - ValueError: values (= (zeta16^4, -1, -1)) must have multiplicative orders dividing (2, 16, 2), respectively + ValueError: values (= (zeta16^4, -1, -1)) must have + multiplicative orders dividing (2, 16, 2), respectively sage: from sage.modular.dirichlet import DirichletCharacter sage: M = FreeModule(Zmod(16), 3) sage: DirichletCharacter(G, M([4, 8, 8])) Traceback (most recent call last): ... - ValueError: values (= (4, 8, 8) modulo 16) must have additive orders dividing (2, 16, 2), respectively + ValueError: values (= (4, 8, 8) modulo 16) must have + additive orders dividing (2, 16, 2), respectively """ MultiplicativeGroupElement.__init__(self, parent) if check: @@ -360,7 +367,8 @@ def change_ring(self, R): sage: e = DirichletGroup(7, QQ).0 sage: f = e.change_ring(QuadraticField(3, 'a')) sage: f.parent() - Group of Dirichlet characters modulo 7 with values in Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878? + Group of Dirichlet characters modulo 7 with values in Number Field in a + with defining polynomial x^2 - 3 with a = 1.732050807568878? :: @@ -1054,11 +1062,14 @@ def decomposition(self): sage: G. = DirichletGroup(20) sage: c = a*b sage: d = c.decomposition(); d - [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4] + [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, + Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4] sage: d[0].parent() - Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2 + Group of Dirichlet characters modulo 4 with values + in Cyclotomic Field of order 4 and degree 2 sage: d[1].parent() - Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2 + Group of Dirichlet characters modulo 5 with values + in Cyclotomic Field of order 4 and degree 2 We cannot multiply directly, since coercion of one element into the other parent fails in both cases:: @@ -1066,7 +1077,10 @@ def decomposition(self): sage: d[0]*d[1] == c Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2' and 'Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2' + TypeError: unsupported operand parent(s) for *: 'Group of Dirichlet + characters modulo 4 with values in Cyclotomic Field of order 4 and + degree 2' and 'Group of Dirichlet characters modulo 5 with values + in Cyclotomic Field of order 4 and degree 2' We can multiply if we are explicit about where we want the multiplication to take place. @@ -1081,11 +1095,14 @@ def decomposition(self): trivial for `k = 1` and non-cyclic for `k \ge 3`:: sage: (DirichletGroup(18).0).decomposition() - [Dirichlet character modulo 2 of conductor 1, Dirichlet character modulo 9 of conductor 9 mapping 2 |--> zeta6] + [Dirichlet character modulo 2 of conductor 1, + Dirichlet character modulo 9 of conductor 9 mapping 2 |--> zeta6] sage: (DirichletGroup(36).0).decomposition() - [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1] + [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, + Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1] sage: (DirichletGroup(72).0).decomposition() - [Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1] + [Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1, + Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1] """ D = self.parent().decomposition() vals = [[z] for z in self.values_on_gens()] @@ -1264,7 +1281,8 @@ def galois_orbit(self, sort=True): sage: e = G.0^2; e Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2 sage: e.galois_orbit() - [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^2 + 1] + [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2, + Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^2 + 1] A non-example:: @@ -1322,7 +1340,12 @@ def gauss_sum(self, a=1): sage: G = DirichletGroup(13) sage: e = G.0 sage: e.gauss_sum() - -zeta156^46 + zeta156^45 + zeta156^42 + zeta156^41 + 2*zeta156^40 + zeta156^37 - zeta156^36 - zeta156^34 - zeta156^33 - zeta156^31 + 2*zeta156^30 + zeta156^28 - zeta156^24 - zeta156^22 + zeta156^21 + zeta156^20 - zeta156^19 + zeta156^18 - zeta156^16 - zeta156^15 - 2*zeta156^14 - zeta156^10 + zeta156^8 + zeta156^7 + zeta156^6 + zeta156^5 - zeta156^4 - zeta156^2 - 1 + -zeta156^46 + zeta156^45 + zeta156^42 + zeta156^41 + 2*zeta156^40 + + zeta156^37 - zeta156^36 - zeta156^34 - zeta156^33 - zeta156^31 + + 2*zeta156^30 + zeta156^28 - zeta156^24 - zeta156^22 + zeta156^21 + + zeta156^20 - zeta156^19 + zeta156^18 - zeta156^16 - zeta156^15 + - 2*zeta156^14 - zeta156^10 + zeta156^8 + zeta156^7 + zeta156^6 + + zeta156^5 - zeta156^4 - zeta156^2 - 1 sage: factor(norm(e.gauss_sum())) 13^24 @@ -1340,7 +1363,8 @@ def gauss_sum(self, a=1): sage: G = DirichletGroup(13, K) sage: chi = G([z^2]) sage: chi.gauss_sum() - zeta52^22 + zeta52^21 + zeta52^19 - zeta52^16 + zeta52^15 + zeta52^14 + zeta52^12 - zeta52^11 - zeta52^10 - zeta52^7 - zeta52^5 + zeta52^4 + zeta52^22 + zeta52^21 + zeta52^19 - zeta52^16 + zeta52^15 + zeta52^14 + + zeta52^12 - zeta52^11 - zeta52^10 - zeta52^7 - zeta52^5 + zeta52^4 Check that :issue:`25127` is fixed:: @@ -1487,8 +1511,10 @@ def jacobi_sum(self, char, check=True): ... NotImplementedError: Characters must be from the same Dirichlet Group. - sage: all_jacobi_sums = [(DP[i].values_on_gens(),DP[j].values_on_gens(),DP[i].jacobi_sum(DP[j])) - ....: for i in range(p-1) for j in range(i, p-1)] + sage: all_jacobi_sums = [(DP[i].values_on_gens(), + ....: DP[j].values_on_gens(), + ....: DP[i].jacobi_sum(DP[j])) + ....: for i in range(p - 1) for j in range(i, p - 1)] sage: for s in all_jacobi_sums: ....: print(s) ((1,), (1,), 5) @@ -1898,6 +1924,7 @@ def minimize_base_ring(self): A related bug (see :issue:`18086`):: + sage: x = polygen(ZZ, 'x') sage: K. = NumberField([x^2 + 1, x^2 - 3]) sage: chi = DirichletGroup(7, K).0 sage: chi.minimize_base_ring() @@ -2256,7 +2283,8 @@ class DirichletGroupFactory(UniqueFactory): of `(\ZZ/N\ZZ)^*`:: sage: DirichletGroup(20) - Group of Dirichlet characters modulo 20 with values in Cyclotomic Field of order 4 and degree 2 + Group of Dirichlet characters modulo 20 with values + in Cyclotomic Field of order 4 and degree 2 We create the group of Dirichlet character mod 20 with values in the rational numbers:: @@ -2272,7 +2300,10 @@ class DirichletGroupFactory(UniqueFactory): on the generators of `(Z/NZ)^*`:: sage: list(G) - [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1, Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1, Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1] + [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1, + Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, + Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1, + Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1] Next we construct the group of Dirichlet character mod 20, but with values in `\QQ(\zeta_n)`:: @@ -2284,7 +2315,8 @@ class DirichletGroupFactory(UniqueFactory): We next compute several invariants of ``G``:: sage: G.gens() - (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4) + (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, + Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4) sage: G.unit_gens() (11, 17) sage: G.zeta() @@ -2298,22 +2330,29 @@ class DirichletGroupFactory(UniqueFactory): sage: R. = PolynomialRing(QQ) sage: K. = NumberField(x^4 + 1) sage: DirichletGroup(5, K) - Group of Dirichlet characters modulo 5 with values in Number Field in a with defining polynomial x^4 + 1 + Group of Dirichlet characters modulo 5 with values + in Number Field in a with defining polynomial x^4 + 1 An example where we give ``zeta``, but not its order:: sage: G = DirichletGroup(5, K, a); G - Group of Dirichlet characters modulo 5 with values in the group of order 8 generated by a in Number Field in a with defining polynomial x^4 + 1 + Group of Dirichlet characters modulo 5 with values in the group of order 8 + generated by a in Number Field in a with defining polynomial x^4 + 1 sage: G.list() - [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -a^2] + [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1, + Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2, + Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1, + Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -a^2] We can also restrict the order of the characters, either with or without specifying a root of unity:: sage: DirichletGroup(5, K, zeta=-1, zeta_order=2) - Group of Dirichlet characters modulo 5 with values in the group of order 2 generated by -1 in Number Field in a with defining polynomial x^4 + 1 + Group of Dirichlet characters modulo 5 with values in the group of order 2 + generated by -1 in Number Field in a with defining polynomial x^4 + 1 sage: DirichletGroup(5, K, zeta_order=2) - Group of Dirichlet characters modulo 5 with values in the group of order 2 generated by -1 in Number Field in a with defining polynomial x^4 + 1 + Group of Dirichlet characters modulo 5 with values in the group of order 2 + generated by -1 in Number Field in a with defining polynomial x^4 + 1 :: @@ -2331,7 +2370,8 @@ class DirichletGroupFactory(UniqueFactory): sage: p = next_prime(10^40) sage: g = DirichletGroup(19, GF(p)); g - Group of Dirichlet characters modulo 19 with values in Finite Field of size 10000000000000000000000000000000000000121 + Group of Dirichlet characters modulo 19 with values + in Finite Field of size 10000000000000000000000000000000000000121 Note that the root of unity has small order, i.e., it is not the largest order root of unity in the field:: @@ -2344,19 +2384,24 @@ class DirichletGroupFactory(UniqueFactory): sage: r4 = CyclotomicField(4).ring_of_integers() sage: G = DirichletGroup(60, r4) sage: G.gens() - (Dirichlet character modulo 60 of conductor 4 mapping 31 |--> -1, 41 |--> 1, 37 |--> 1, Dirichlet character modulo 60 of conductor 3 mapping 31 |--> 1, 41 |--> -1, 37 |--> 1, Dirichlet character modulo 60 of conductor 5 mapping 31 |--> 1, 41 |--> 1, 37 |--> zeta4) + (Dirichlet character modulo 60 of conductor 4 + mapping 31 |--> -1, 41 |--> 1, 37 |--> 1, + Dirichlet character modulo 60 of conductor 3 + mapping 31 |--> 1, 41 |--> -1, 37 |--> 1, + Dirichlet character modulo 60 of conductor 5 + mapping 31 |--> 1, 41 |--> 1, 37 |--> zeta4) sage: val = G.gens()[2].values_on_gens()[2] ; val zeta4 sage: parent(val) Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2 - sage: r4.residue_field(r4.ideal(29).factor()[0][0])(val) + sage: r4_29_0 = r4.residue_field(r4.ideal(29).factor()[0][0]); r4_29_0(val) doctest:warning ... DeprecationWarning: ... 17 - sage: r4.residue_field(r4.ideal(29).factor()[0][0])(val) * GF(29)(3) + sage: r4_29_0(val) * GF(29)(3) 22 - sage: r4.residue_field(r4.ideal(29).factor()[0][0])(G.gens()[2].values_on_gens()[2]) * 3 + sage: r4_29_0(G.gens()[2].values_on_gens()[2]) * 3 22 - sage: parent(r4.residue_field(r4.ideal(29).factor()[0][0])(G.gens()[2].values_on_gens()[2]) * 3) + sage: parent(r4_29_0(G.gens()[2].values_on_gens()[2]) * 3) Residue field of Fractional ideal (-2*zeta4 + 5) :: @@ -2398,9 +2443,11 @@ class DirichletGroupFactory(UniqueFactory): sage: G.gens() Traceback (most recent call last): ... - NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented + NotImplementedError: factorization of polynomials over rings + with composite characteristic is not implemented sage: G = DirichletGroup(5, Zmod(15), zeta=2); G - Group of Dirichlet characters modulo 5 with values in the group of order 4 generated by 2 in Ring of integers modulo 15 + Group of Dirichlet characters modulo 5 with values in the group of order 4 + generated by 2 in Ring of integers modulo 15 sage: G.gens() (Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 2,) diff --git a/src/sage/modular/hypergeometric_motive.py b/src/sage/modular/hypergeometric_motive.py index 26a9ff00c7c..111c93ff07f 100644 --- a/src/sage/modular/hypergeometric_motive.py +++ b/src/sage/modular/hypergeometric_motive.py @@ -20,7 +20,7 @@ sage: H = Hyp(cyclotomic=([30], [1,2,3,5])) sage: H.alpha_beta() ([1/30, 7/30, 11/30, 13/30, 17/30, 19/30, 23/30, 29/30], - [0, 1/5, 1/3, 2/5, 1/2, 3/5, 2/3, 4/5]) + [0, 1/5, 1/3, 2/5, 1/2, 3/5, 2/3, 4/5]) sage: H.M_value() == 30**30 / (15**15 * 10**10 * 6**6) True sage: H.euler_factor(2, 7) @@ -1457,7 +1457,7 @@ def H_value(self, p, f, t, ring=None): - `t` -- a rational parameter - - ``ring`` -- optional (default ``UniversalCyclotomicfield``) + - ``ring`` -- optional (default :class:`UniversalCyclotomicfield`) The ring could be also ``ComplexField(n)`` or ``QQbar``. @@ -1468,9 +1468,9 @@ def H_value(self, p, f, t, ring=None): .. WARNING:: This is apparently working correctly as can be tested - using ComplexField(70) as value ring. + using ``ComplexField(70)`` as value ring. - Using instead UniversalCyclotomicfield, this is much + Using instead :class:`UniversalCyclotomicfield`, this is much slower than the `p`-adic version :meth:`padic_H_value`. EXAMPLES: diff --git a/src/sage/modular/modform/ambient_R.py b/src/sage/modular/modform/ambient_R.py index 9f416f49169..0d19eb36cd3 100644 --- a/src/sage/modular/modform/ambient_R.py +++ b/src/sage/modular/modform/ambient_R.py @@ -23,7 +23,7 @@ def __init__(self, M, base_ring): EXAMPLES:: - sage: M = ModularForms(23,2,base_ring=GF(7)) # indirect doctest + sage: M = ModularForms(23, 2, base_ring=GF(7)) # indirect doctest sage: M Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(23) of weight 2 over Finite Field of size 7 @@ -46,9 +46,10 @@ def modular_symbols(self,sign=0): sage: # needs sage.rings.number_field sage: K. = QuadraticField(-1) - sage: chi = DirichletGroup(5, base_ring = K).0 + sage: chi = DirichletGroup(5, base_ring=K).0 + sage: x = polygen(ZZ, 'x') sage: L. = K.extension(x^2 - 402*i) - sage: M = ModularForms(chi, 7, base_ring = L) + sage: M = ModularForms(chi, 7, base_ring=L) sage: symbs = M.modular_symbols() sage: symbs.character() == chi True diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index c0a69717cfa..d16ba084dbb 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -212,7 +212,7 @@ def __init__(self, group, base_ring=QQ): Traceback (most recent call last): ... ValueError: group (=3.40000000000000) should be a congruence subgroup - sage: ModularFormsRing(Gamma0(2), base_ring=PolynomialRing(ZZ,x)) + sage: ModularFormsRing(Gamma0(2), base_ring=PolynomialRing(ZZ, 'x')) Traceback (most recent call last): ... ValueError: base ring (=Univariate Polynomial Ring in x over Integer Ring) should be QQ, ZZ or a finite prime field diff --git a/src/sage/modular/modform_hecketriangle/graded_ring_element.py b/src/sage/modular/modform_hecketriangle/graded_ring_element.py index 0de1562677b..bd6d2a03a2c 100644 --- a/src/sage/modular/modform_hecketriangle/graded_ring_element.py +++ b/src/sage/modular/modform_hecketriangle/graded_ring_element.py @@ -143,7 +143,7 @@ def _richcmp_(self, other, op): EXAMPLES:: sage: from sage.modular.modform_hecketriangle.graded_ring import MeromorphicModularFormsRing - sage: (x,y,z,d) = MeromorphicModularFormsRing().pol_ring().gens() + sage: x, y, z, d = MeromorphicModularFormsRing().pol_ring().gens() sage: MeromorphicModularFormsRing(n=3)(x) == MeromorphicModularFormsRing(n=4)(x) False sage: MeromorphicModularFormsRing()(-1/x) is MeromorphicModularFormsRing()(1/(-x)) @@ -1249,7 +1249,7 @@ def order_at(self, tau=infinity): Return the (overall) order of ``self`` at ``tau`` if easily possible: Namely if ``tau`` is ``infinity`` or congruent to ``i`` resp. ``rho``. - It is possible to determine the order of points from ``HyperbolicPlane()``. + It is possible to determine the order of points from :class:`HyperbolicPlane`. In this case the coordinates of the upper half plane model are used. If ``self`` is homogeneous and modular then the rational function @@ -1834,7 +1834,7 @@ def evaluate(self, tau, prec=None, num_prec=None, check=False): (and fail) for certain (many) choices of (``base_ring``, ``tau.parent()``). - It is possible to evaluate at points of ``HyperbolicPlane()``. + It is possible to evaluate at points of :class:`HyperbolicPlane`. In this case the coordinates of the upper half plane model are used. To obtain a precise and fast result the parameters @@ -2123,7 +2123,7 @@ def evaluate(self, tau, prec=None, num_prec=None, check=False): sage: (f.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*az/G.lam())) # long time -140.471170232432551196978... + 469.079369280804086032719...*I - It is possible to evaluate at points of ``HyperbolicPlane()``:: + It is possible to evaluate at points of :class:`HyperbolicPlane`:: sage: # needs sage.symbolic sage: p = HyperbolicPlane().PD().get_point(-I/2) 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 2d52c934adf..0e48b78e008 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py @@ -2888,9 +2888,9 @@ def root_extension_embedding(self, K=None): INPUT: - ``K`` -- A field to which we want the (correct) embedding. - If ``K=None`` (default) then ``AlgebraicField()`` is - used for elliptic elements and ``AlgebraicRealField()`` - otherwise. + If ``K=None`` (default), then ``AlgebraicField()`` is + used for elliptic elements and ``AlgebraicRealField()`` + otherwise. EXAMPLES:: @@ -2955,26 +2955,25 @@ def fixed_points(self, embedded=False, order="default"): INPUT: - - ``embedded`` -- If ``True`` the fixed points are embedded into - ``AlgebraicRealField`` resp. ``AlgebraicField``. - Default: ``False``. + - ``embedded`` -- If ``True``, the fixed points are embedded into + ``AlgebraicRealField`` resp. ``AlgebraicField``. Default: ``False``. - - ``order`` -- If ``order="none"`` the fixed points are choosen - and ordered according to a fixed formula. + - ``order`` -- If ``order="none"`` the fixed points are choosen + and ordered according to a fixed formula. - If ``order="sign"`` the fixed points are always ordered - according to the sign in front of the square root. + If ``order="sign"`` the fixed points are always ordered + according to the sign in front of the square root. - If ``order="default"`` (default) then in case the fixed - points are hyperbolic they are ordered according to the - sign of the trace of ``self`` instead, such that the - attracting fixed point comes first. + If ``order="default"`` (default) then in case the fixed + points are hyperbolic they are ordered according to the + sign of the trace of ``self`` instead, such that the + attracting fixed point comes first. - If ``order="trace"`` the fixed points are always ordered - according to the sign of the trace of ``self``. - If the trace is zero they are ordered by the sign in - front of the square root. In particular the fixed_points - in this case remain the same for ``-self``. + If ``order="trace"`` the fixed points are always ordered + according to the sign of the trace of ``self``. + If the trace is zero they are ordered by the sign in + front of the square root. In particular the fixed_points + in this case remain the same for ``-self``. OUTPUT: @@ -3108,16 +3107,15 @@ def acton(self, tau): INPUT: - - ``tau`` -- Either an element of ``self`` or any - element to which a linear fractional - transformation can be applied in - the usual way. + - ``tau`` -- Either an element of ``self`` or any + element to which a linear fractional + transformation can be applied in the usual way. - In particular ``infinity`` is a possible - argument and a possible return value. + In particular ``infinity`` is a possible + argument and a possible return value. - As mentioned it is also possible to use - points of ``HyperbolicPlane()``. + As mentioned it is also possible to use + points of ``HyperbolicPlane()``. EXAMPLES:: @@ -3152,8 +3150,10 @@ def acton(self, tau): sage: p = HyperbolicPlane().PD().get_point(-I/2+1/8) sage: G.V(2).acton(p) - Point in PD -((-(47*I + 161)*sqrt(5) - 47*I - 161)/(145*sqrt(5) + 94*I + 177) + I)/(I*(-(47*I + 161)*sqrt(5) - 47*I - 161)/(145*sqrt(5) + 94*I + 177) + 1) - sage: bool(G.V(2).acton(p).to_model('UHP').coordinates() == G.V(2).acton(p.to_model('UHP').coordinates())) + Point in PD -((-(47*I + 161)*sqrt(5) - 47*I - 161)/(145*sqrt(5) + 94*I + 177) + + I)/(I*(-(47*I + 161)*sqrt(5) - 47*I - 161)/(145*sqrt(5) + 94*I + 177) + 1) + sage: bool(G.V(2).acton(p).to_model('UHP').coordinates() + ....: == G.V(2).acton(p.to_model('UHP').coordinates())) True sage: p = HyperbolicPlane().PD().get_point(I) @@ -3334,9 +3334,15 @@ def as_hyperbolic_plane_isometry(self, model="UHP"): [lam^2 - 1 lam] [lam^2 - 1 lam^2 - 1] sage: el.as_hyperbolic_plane_isometry().parent() - Set of Morphisms from Hyperbolic plane in the Upper Half Plane Model to Hyperbolic plane in the Upper Half Plane Model in Category of hyperbolic models of Hyperbolic plane + Set of Morphisms + from Hyperbolic plane in the Upper Half Plane Model + to Hyperbolic plane in the Upper Half Plane Model + in Category of hyperbolic models of Hyperbolic plane sage: el.as_hyperbolic_plane_isometry("KM").parent() - Set of Morphisms from Hyperbolic plane in the Klein Disk Model to Hyperbolic plane in the Klein Disk Model in Category of hyperbolic models of Hyperbolic plane + Set of Morphisms + from Hyperbolic plane in the Klein Disk Model + to Hyperbolic plane in the Klein Disk Model + in Category of hyperbolic models of Hyperbolic plane """ from sage.geometry.hyperbolic_space.hyperbolic_interface import HyperbolicPlane return HyperbolicPlane().UHP().get_isometry(self._matrix).to_model(model) diff --git a/src/sage/modular/modsym/p1list_nf.py b/src/sage/modular/modsym/p1list_nf.py index 25c68137e0c..29b5c087642 100644 --- a/src/sage/modular/modsym/p1list_nf.py +++ b/src/sage/modular/modsym/p1list_nf.py @@ -19,7 +19,8 @@ sage: k. = NumberField(x^3 + 11) sage: N = k.ideal(5, a^2 - a + 1) sage: P = P1NFList(N); P - The projective line over the ring of integers modulo the Fractional ideal (5, a^2 - a + 1) + The projective line over + the ring of integers modulo the Fractional ideal (5, a^2 - a + 1) List operations with the P1NFList: @@ -116,7 +117,7 @@ def P1NFList_clear_level_cache(): @richcmp_method class MSymbol(SageObject): - """ + r""" The constructor for an M-symbol over a number field. INPUT: @@ -127,15 +128,15 @@ class MSymbol(SageObject): level N. - ``d`` -- (optional) when present, it must be an integral element such - that + + N = R, where R is the corresponding ring of integers. + that `\la c\ra + \la d\ra + N = R, where `R` is the corresponding ring of integers. - - ``check`` -- bool (default True). If ``check=False`` the constructor does - not check the condition + + N = R. + - ``check`` -- bool (default ``True``). If ``check=False`` the constructor does + not check the condition `\la c\ra + \la d\ra + N = R`. OUTPUT: - An M-symbol modulo the given ideal N, i.e. an element of the - projective line `\\mathbb{P}^1(R/N)`, where R is the ring of integers of + An M-symbol modulo the given ideal `N`, i.e. an element of the + projective line `\mathbb{P}^1(R/N)`, where `R` is the ring of integers of the underlying number field. EXAMPLES:: @@ -153,7 +154,7 @@ class MSymbol(SageObject): sage: MSymbol(N, (1, 0)) M-symbol (1: 0) of level Fractional ideal (2, a + 1) - We get an error if , and N are not coprime: + We get an error if `\la c\ra`, `\la d\ra` and `N` are not coprime: :: @@ -216,7 +217,7 @@ def __init__(self, N, c, d=None, check=True): self.__c, self.__d = (c1, d1) def __repr__(self): - """ + r""" Return the string representation of this MSymbol. EXAMPLES:: @@ -245,7 +246,7 @@ def _latex_(self): return r"\(%s: %s\)" % (self.c._latex_(), self.d._latex_()) def __richcmp__(self, other, op): - """ + r""" Comparison function for objects of the class MSymbol. The order is the same as for the underlying lists of lists. @@ -269,7 +270,7 @@ def __richcmp__(self, other, op): [other.__c.list(), other.__d.list()], op) def N(self): - """ + r""" Return the level or modulus of this MSymbol. EXAMPLES:: @@ -284,8 +285,8 @@ def N(self): return self.__N def tuple(self): - """ - Return the MSymbol as a list (c, d). + r""" + Return the :class:`MSymbol` as a list `(c, d)`. EXAMPLES:: @@ -300,7 +301,7 @@ def tuple(self): return self.__c, self.__d def __getitem__(self, n): - """ + r""" Indexing function for the list defined by an M-symbol. INPUT: @@ -323,7 +324,7 @@ def __getitem__(self, n): return self.tuple()[n] def __get_c(self): - """ + r""" Return the first coefficient of the M-symbol. EXAMPLES:: @@ -339,7 +340,7 @@ def __get_c(self): c = property(__get_c) def __get_d(self): - """ + r""" Return the second coefficient of the M-symbol. EXAMPLES:: @@ -355,15 +356,15 @@ def __get_d(self): d = property(__get_d) def lift_to_sl2_Ok(self): - """ - Lift the MSymbol to an element of `SL(2, Ok)`, where `Ok` is the ring + r""" + Lift the :class:`MSymbol` to an element of `SL(2, O_k)`, where `O_k` is the ring of integers of the corresponding number field. OUTPUT: A list of integral elements `[a, b, c', d']` that are the entries of - a 2x2 matrix with determinant 1. The lower two entries are congruent - (modulo the level) to the coefficients `c, d` of the MSymbol self. + a `2\times 2` matrix with determinant 1. The lower two entries are congruent + (modulo the level) to the coefficients `c`, `d` of the :class:`MSymbol` ``self``. EXAMPLES:: @@ -378,12 +379,12 @@ def lift_to_sl2_Ok(self): def normalize(self, with_scalar=False): r""" - Return a normalized MSymbol (a canonical representative of an element - of `\mathbb{P}^1(R/N)` ) equivalent to ``self``. + Return a normalized :class:`MSymbol` (a canonical representative of an element + of `\mathbb{P}^1(R/N)`) equivalent to ``self``. INPUT: - - ``with_scalar`` -- bool (default False) + - ``with_scalar`` -- bool (default ``False``) OUTPUT: @@ -391,7 +392,7 @@ def normalize(self, with_scalar=False): `(u*c', u*d')` is congruent to `(c: d)` (mod `N`), where `(c: d)` are the coefficients of ``self`` and `N` is the level. - - a normalized MSymbol (c': d') equivalent to ``self``. + - a normalized :class:`MSymbol` `(c': d')` equivalent to ``self``. EXAMPLES:: @@ -487,7 +488,7 @@ class P1NFList(SageObject): OUTPUT: - A P1NFList object representing `\mathbb{P}^1(R/N)`. + A :class:`P1NFList` object representing `\mathbb{P}^1(R/N)`. EXAMPLES:: @@ -505,7 +506,7 @@ class P1NFList(SageObject): True """ def __init__(self, N): - """ + r""" The constructor for the class P1NFList. See ``P1NFList`` for full documentation. @@ -522,7 +523,7 @@ def __init__(self, N): self.__list.sort() def __richcmp__(self, other, op): - """ + r""" Comparison function for objects of the class P1NFList. The order is the same as for the underlying modulus. @@ -547,7 +548,7 @@ def __richcmp__(self, other, op): return richcmp(self.__N, other.__N, op) def __getitem__(self, n): - """ + r""" Standard indexing function for the class P1NFList. EXAMPLES:: @@ -565,7 +566,7 @@ def __getitem__(self, n): return self.__list[n] def __len__(self): - """ + r""" Return the length of this P1NFList. EXAMPLES:: @@ -580,22 +581,22 @@ def __len__(self): return len(self.__list) def __repr__(self): - """ + r""" Return the string representation of this P1NFList. EXAMPLES:: sage: x = polygen(QQ, 'x') sage: k. = NumberField(x^3 + 11) - sage: N = k.ideal(5, a+1) + sage: N = k.ideal(5, a + 1) sage: P = P1NFList(N); P The projective line over the ring of integers modulo the Fractional ideal (5, a + 1) """ return "The projective line over the ring of integers modulo the %s" % self.__N def list(self): - """ - Return the underlying list of this P1NFList object. + r""" + Return the underlying list of this :class:`P1NFList` object. EXAMPLES:: @@ -622,14 +623,14 @@ def normalize(self, c, d=None, with_scalar=False): - ``d`` -- (optional) when present, it must be an integral element of the number field such that `(c, d)` defines an M-symbol of level `N`. - - ``with_scalar`` -- bool (default False) + - ``with_scalar`` -- bool (default ``False``) OUTPUT: - (only if ``with_scalar=True``) a transforming scalar `u`, such that `(u*c', u*d')` is congruent to `(c: d)` (mod `N`). - - a normalized MSymbol (c': d') equivalent to `(c: d)`. + - a normalized :class:`MSymbol` `(c': d')` equivalent to `(c: d)`. EXAMPLES:: @@ -640,7 +641,7 @@ def normalize(self, c, d=None, with_scalar=False): sage: P.normalize(3, a) M-symbol (1: 2*a) of level Fractional ideal (5, 1/2*a + 3/2) - We can use an MSymbol as input: + We can use an :class:`MSymbol` as input: :: @@ -667,8 +668,8 @@ def normalize(self, c, d=None, with_scalar=False): return MSymbol(self.N(), c, d).normalize(with_scalar) def N(self): - """ - Return the level or modulus of this P1NFList. + r""" + Return the level or modulus of this :class:`P1NFList`. EXAMPLES:: @@ -689,12 +690,12 @@ def index(self, c, d=None, with_scalar=False): INPUT: - ``c`` -- integral element of the corresponding number field, or an - MSymbol. + :class:`MSymbol`. - ``d`` -- (optional) when present, it must be an integral element of the number field such that `(c, d)` defines an M-symbol of level `N`. - - ``with_scalar`` -- bool (default False) + - ``with_scalar`` -- bool (default ``False``) OUTPUT: @@ -713,7 +714,7 @@ def index(self, c, d=None, with_scalar=False): sage: P[5]==MSymbol(N, 3, a).normalize() True - We can give an MSymbol as input: + We can give an :class:`MSymbol` as input: :: @@ -721,7 +722,7 @@ def index(self, c, d=None, with_scalar=False): sage: P.index(alpha) 5 - We cannot look for the class of an MSymbol of a different level: + We cannot look for the class of an :class:`MSymbol` of a different level: :: @@ -773,7 +774,7 @@ def index_of_normalized_pair(self, c, d=None): INPUT: - ``c`` -- integral element of the corresponding number field, or a - normalized MSymbol. + normalized :class:`MSymbol`. - ``d`` -- (optional) when present, it must be an integral element of the number field such that `(c, d)` defines a normalized M-symbol of @@ -808,18 +809,18 @@ def index_of_normalized_pair(self, c, d=None): return False def lift_to_sl2_Ok(self, i): - """ - Lift the `i`-th element of this P1NFList to an element of `SL(2, R)`, + r""" + Lift the `i`-th element of this :class:`P1NFList` to an element of `SL(2, R)`, where `R` is the ring of integers of the corresponding number field. INPUT: - - ``i`` - integer (index of the element to lift) + - ``i`` -- integer (index of the element to lift) OUTPUT: If the `i`-th element is `(c : d)`, the function returns a list of - integral elements `[a, b, c', d']` that defines a 2x2 matrix with + integral elements `[a, b, c', d']` that defines a `2\times 2` matrix with determinant 1 and such that `c=c'` (mod `N`) and `d=d'` (mod `N`). EXAMPLES:: @@ -845,8 +846,8 @@ def lift_to_sl2_Ok(self, i): return self[i].lift_to_sl2_Ok() def apply_S(self, i): - """ - Applies the matrix S = [0, -1, 1, 0] to the i-th M-Symbol of the list. + r""" + Applies the matrix `S` = [0, -1, 1, 0] to the `i`-th M-Symbol of the list. INPUT: @@ -855,7 +856,7 @@ def apply_S(self, i): OUTPUT: integer -- the index of the M-Symbol obtained by the right action of - the matrix S = [0, -1, 1, 0] on the i-th M-Symbol. + the matrix `S` = [0, -1, 1, 0] on the `i`-th M-Symbol. EXAMPLES:: @@ -880,8 +881,8 @@ def apply_S(self, i): return j def apply_TS(self, i): - """ - Applies the matrix TS = [1, -1, 0, 1] to the i-th M-Symbol of the list. + r""" + Applies the matrix `TS` = [1, -1, 0, 1] to the `i`-th M-Symbol of the list. INPUT: @@ -890,7 +891,7 @@ def apply_TS(self, i): OUTPUT: integer -- the index of the M-Symbol obtained by the right action of - the matrix TS = [1, -1, 0, 1] on the i-th M-Symbol. + the matrix `TS` = [1, -1, 0, 1] on the `i`-th M-Symbol. EXAMPLES:: @@ -901,7 +902,7 @@ def apply_TS(self, i): sage: P.apply_TS(3) 2 - We test that TS has order 3: + We test that `TS` has order 3: :: @@ -914,20 +915,20 @@ def apply_TS(self, i): return j def apply_T_alpha(self, i, alpha=1): - """ - Applies the matrix T_alpha = [1, alpha, 0, 1] to the i-th M-Symbol of + r""" + Applies the matrix `T_alpha` = [1, alpha, 0, 1] to the `i`-th M-Symbol of the list. INPUT: - ``i`` -- integer - - ``alpha`` -- element of the corresponding ring of integers(default 1) + - ``alpha`` -- (default 1) element of the corresponding ring of integers OUTPUT: integer -- the index of the M-Symbol obtained by the right action of - the matrix T_alpha = [1, alpha, 0, 1] on the i-th M-Symbol. + the matrix `T_alpha` = [1, `alpha`, 0, 1] on the i-th M-Symbol. EXAMPLES:: @@ -938,7 +939,7 @@ def apply_T_alpha(self, i, alpha=1): sage: P.apply_T_alpha(4, a^ 2 - 2) 3 - We test that T_a*T_b = T_(a+b): + We test that `T_a*T_b = T_{(a+b)}`: :: @@ -951,7 +952,7 @@ def apply_T_alpha(self, i, alpha=1): def apply_J_epsilon(self, i, e1, e2=1): r""" - Apply the matrix `J_{\epsilon}` = [e1, 0, 0, e2] to the i-th + Apply the matrix `J_{\epsilon}` = [e1, 0, 0, e2] to the `i`-th M-Symbol of the list. e1, e2 are units of the underlying number field. @@ -967,7 +968,7 @@ def apply_J_epsilon(self, i, e1, e2=1): OUTPUT: integer -- the index of the M-Symbol obtained by the right action of - the matrix `J_{\epsilon}` = [e1, 0, 0, e2] on the i-th M-Symbol. + the matrix `J_{\epsilon}` = [e1, 0, 0, e2] on the `i`-th M-Symbol. EXAMPLES:: @@ -1006,8 +1007,8 @@ def apply_J_epsilon(self, i, e1, e2=1): # ************************************************************************* def p1NFlist(N): - """ - Return a list of the normalized elements of `\\mathbb{P}^1(R/N)`, where + r""" + Return a list of the normalized elements of `\mathbb{P}^1(R/N)`, where `N` is an integral ideal. INPUT: @@ -1054,7 +1055,7 @@ def p1NFlist(N): def lift_to_sl2_Ok(N, c, d): - """ + r""" Lift a pair (c, d) to an element of `SL(2, O_k)`, where `O_k` is the ring of integers of the corresponding number field. @@ -1068,9 +1069,9 @@ def lift_to_sl2_Ok(N, c, d): OUTPUT: - A list [a, b, c', d'] of integral elements that are the entries of - a 2x2 matrix with determinant 1. The lower two entries are congruent to - c, d modulo the ideal `N`. + A list `[a, b, c', d']` of integral elements that are the entries of + a `2\times 2` matrix with determinant 1. The lower two entries are congruent to + `c`, `d` modulo the ideal `N`. EXAMPLES:: @@ -1161,9 +1162,9 @@ def lift_to_sl2_Ok(N, c, d): def make_coprime(N, c, d): - """ + r""" Return (c, d') so d' is congruent to d modulo N, and such that c and d' are - coprime ( + = R). + coprime (`\la c\ra + \la d'\ra = R`). INPUT: @@ -1175,9 +1176,9 @@ def make_coprime(N, c, d): OUTPUT: - A pair (c, d') where c, d' are integral elements of the corresponding - number field, with d' congruent to d mod N, and such that + = R - (R being the corresponding ring of integers). + A pair `(c, d')` where `c`, `d'` are integral elements of the corresponding + number field, with `d'` congruent to `d` mod `N`, and such that `\la c\ra + \la d'\ra = R` + (`R` being the corresponding ring of integers). EXAMPLES:: diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 58f31f4af0c..fef0f95983a 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -73,7 +73,8 @@ :: sage: f2 = M(CuspForms(3, 8).0); f2 - 3-adic overconvergent modular form of weight-character 8 with q-expansion q + 6*q^2 - 27*q^3 - 92*q^4 + 390*q^5 - 162*q^6 ... + 3-adic overconvergent modular form of weight-character 8 with q-expansion + q + 6*q^2 - 27*q^3 - 92*q^4 + 390*q^5 - 162*q^6 ... We express this in a basis, and see that the coefficients go to zero very fast: @@ -82,7 +83,10 @@ :: sage: [x.valuation(3) for x in f2.coordinates(60)] - [+Infinity, -1, 3, 6, 10, 13, 18, 20, 24, 27, 31, 34, 39, 41, 45, 48, 52, 55, 61, 62, 66, 69, 73, 76, 81, 83, 87, 90, 94, 97, 102, 104, 108, 111, 115, 118, 124, 125, 129, 132, 136, 139, 144, 146, 150, 153, 157, 160, 165, 167, 171, 174, 178, 181, 188, 188, 192, 195, 199, 202] + [+Infinity, -1, 3, 6, 10, 13, 18, 20, 24, 27, 31, 34, 39, 41, 45, 48, 52, 55, 61, + 62, 66, 69, 73, 76, 81, 83, 87, 90, 94, 97, 102, 104, 108, 111, 115, 118, 124, 125, + 129, 132, 136, 139, 144, 146, 150, 153, 157, 160, 165, 167, 171, 174, 178, 181, + 188, 188, 192, 195, 199, 202] This form has more level at `p`, and hence is less overconvergent: @@ -91,7 +95,9 @@ :: sage: f3 = M(CuspForms(9, 8).0); [x.valuation(3) for x in f3.coordinates(60)] - [+Infinity, -1, -1, 0, -4, -4, -2, -3, 0, 0, -1, -1, 1, 0, 3, 3, 3, 3, 5, 3, 7, 7, 6, 6, 8, 7, 10, 10, 8, 8, 10, 9, 12, 12, 12, 12, 14, 12, 17, 16, 15, 15, 17, 16, 19, 19, 18, 18, 20, 19, 22, 22, 22, 22, 24, 21, 25, 26, 24, 24] + [+Infinity, -1, -1, 0, -4, -4, -2, -3, 0, 0, -1, -1, 1, 0, 3, 3, 3, 3, 5, 3, 7, 7, + 6, 6, 8, 7, 10, 10, 8, 8, 10, 9, 12, 12, 12, 12, 14, 12, 17, 16, 15, 15, 17, 16, + 19, 19, 18, 18, 20, 19, 22, 22, 22, 22, 24, 21, 25, 26, 24, 24] An error will be raised for forms which are not sufficiently overconvergent: @@ -216,23 +222,23 @@ def OverconvergentModularForms(prime, weight, radius, base_ring=QQ, prec=20, cha INPUT: - - ``prime`` - a prime number `p`, which must be one of the primes `\{2, 3, + - ``prime`` -- a prime number `p`, which must be one of the primes `\{2, 3, 5, 7, 13\}`, or the congruence subgroup `\Gamma_0(p)` where `p` is one of these primes. - - ``weight`` - an integer (which at present must be 0 or `\ge 2`), the + - ``weight`` -- an integer (which at present must be 0 or `\ge 2`), the weight. - - ``radius`` - a rational number in the interval `\left( 0, \frac{p}{p+1} + - ``radius`` -- a rational number in the interval `\left( 0, \frac{p}{p+1} \right)`, the radius of overconvergence. - - ``base_ring`` (default: `\QQ`), a ring over which to compute. This + - ``base_ring`` -- (default: `\QQ`), a ring over which to compute. This need not be a `p`-adic ring. - - ``prec`` - an integer (default: 20), the number of `q`-expansion terms to + - ``prec`` -- an integer (default: 20), the number of `q`-expansion terms to compute. - - ``char`` - a Dirichlet character modulo `p` or ``None`` (the default). + - ``char`` -- a Dirichlet character modulo `p` or ``None`` (the default). Here ``None`` is interpreted as the trivial character modulo `p`. The character `\chi` and weight `k` must satisfy `(-1)^k = \chi(-1)`, and @@ -243,11 +249,14 @@ def OverconvergentModularForms(prime, weight, radius, base_ring=QQ, prec=20, cha EXAMPLES:: sage: OverconvergentModularForms(3, 0, 1/2) - Space of 3-adic 1/2-overconvergent modular forms of weight-character 0 over Rational Field + Space of 3-adic 1/2-overconvergent modular forms + of weight-character 0 over Rational Field sage: OverconvergentModularForms(3, 16, 1/2) - Space of 3-adic 1/2-overconvergent modular forms of weight-character 16 over Rational Field - sage: OverconvergentModularForms(3, 3, 1/2, char = DirichletGroup(3,QQ).0) - Space of 3-adic 1/2-overconvergent modular forms of weight-character (3, 3, [-1]) over Rational Field + Space of 3-adic 1/2-overconvergent modular forms + of weight-character 16 over Rational Field + sage: OverconvergentModularForms(3, 3, 1/2, char=DirichletGroup(3,QQ).0) + Space of 3-adic 1/2-overconvergent modular forms + of weight-character (3, 3, [-1]) over Rational Field """ if is_Gamma0(prime) or is_Gamma1(prime): prime = prime.level() @@ -360,17 +369,19 @@ def _set_radius(self, radius): sage: M = OverconvergentModularForms(3, 2, 1/2) # indirect doctest sage: M._set_radius(1/3); M - Space of 3-adic 1/3-overconvergent modular forms of weight-character 2 over Rational Field + Space of 3-adic 1/3-overconvergent modular forms of weight-character 2 + over Rational Field sage: x = polygen(ZZ, 'x') sage: L. = Qp(3).extension(x^5 - 3) - sage: OverconvergentModularForms(3, 2, 1/30, base_ring=L).normalising_factor() # indirect doctest + sage: OverconvergentModularForms(3, 2, 1/30, base_ring=L).normalising_factor() # indirect doctest w + O(w^101) sage: OverconvergentModularForms(3, 2, 1/40, base_ring=L) Traceback (most recent call last): ... - ValueError: no element of base ring (=3-adic Eisenstein Extension ...) has normalised valuation 3/20 + ValueError: no element of base ring (=3-adic Eisenstein Extension ...) + has normalised valuation 3/20 """ p = ZZ(self.prime()) @@ -401,7 +412,7 @@ def is_exact(self): r""" True if elements of this space are represented exactly, i.e., there is no precision loss when doing arithmetic. As this is never true for - overconvergent modular forms spaces, this returns False. + overconvergent modular forms spaces, this returns ``False``. EXAMPLES:: @@ -412,13 +423,14 @@ def is_exact(self): def change_ring(self, ring): r""" - Return the space corresponding to self but over the given base ring. + Return the space corresponding to ``self`` but over the given base ring. EXAMPLES:: sage: M = OverconvergentModularForms(2, 0, 1/2) sage: M.change_ring(Qp(2)) - Space of 2-adic 1/2-overconvergent modular forms of weight-character 0 over 2-adic Field with ... + Space of 2-adic 1/2-overconvergent modular forms of weight-character 0 + over 2-adic Field with ... """ return OverconvergentModularForms(self.prime(), self.weight(), self.radius(), ring, self.prec(), self.character()) @@ -434,11 +446,13 @@ def base_extend(self, ring): sage: M = OverconvergentModularForms(2, 0, 1/2, base_ring=Qp(2)) sage: x = polygen(ZZ, 'x') sage: M.base_extend(Qp(2).extension(x^2 - 2, names="w")) - Space of 2-adic 1/2-overconvergent modular forms of weight-character 0 over 2-adic Eisenstein Extension ... + Space of 2-adic 1/2-overconvergent modular forms of weight-character 0 + over 2-adic Eisenstein Extension ... sage: M.base_extend(QQ) Traceback (most recent call last): ... - TypeError: Base extension of self (over '2-adic Field with capped relative precision 20') to ring 'Rational Field' not defined. + TypeError: Base extension of self (over '2-adic Field with capped + relative precision 20') to ring 'Rational Field' not defined. """ if ring.has_coerce_map_from(self.base_ring()): return self.change_ring(ring) @@ -451,16 +465,17 @@ def _an_element_(self): EXAMPLES:: - sage: OverconvergentModularForms(3, 2, 1/3, prec=4).an_element() # indirect doctest - 3-adic overconvergent modular form of weight-character 2 with q-expansion 9*q + 216*q^2 + 2430*q^3 + O(q^4) + sage: OverconvergentModularForms(3, 2, 1/3, prec=4).an_element() # indirect doctest + 3-adic overconvergent modular form of weight-character 2 + with q-expansion 9*q + 216*q^2 + 2430*q^3 + O(q^4) """ return self.element_class(self, self._gsr.an_element()) def character(self): r""" - Return the character of self. For overconvergent forms, the weight and + Return the character of ``self``. For overconvergent forms, the weight and the character are unified into the concept of a weight-character, so - this returns exactly the same thing as self.weight(). + this returns exactly the same thing as ``self.weight()``. EXAMPLES:: @@ -475,9 +490,9 @@ def character(self): def weight(self): r""" - Return the character of self. For overconvergent forms, the weight and + Return the character of ``self``. For overconvergent forms, the weight and the character are unified into the concept of a weight-character, so - this returns exactly the same thing as self.character(). + this returns exactly the same thing as ``self.character()``. EXAMPLES:: @@ -515,7 +530,7 @@ def __eq__(self, other): False sage: OverconvergentModularForms(3, 0, 1/2) == OverconvergentModularForms(3, 0, 1/3) False - sage: OverconvergentModularForms(3, 0, 1/2) == OverconvergentModularForms(3, 0, 1/2, base_ring = Qp(3)) + sage: OverconvergentModularForms(3, 0, 1/2) == OverconvergentModularForms(3, 0, 1/2, base_ring=Qp(3)) False sage: OverconvergentModularForms(3, 0, 1/2) == OverconvergentModularForms(3, 0, 1/2) True @@ -599,17 +614,20 @@ def __reduce__(self): def gen(self, i): r""" - Return the ith module generator of self. + Return the `i`-th module generator of ``self``. EXAMPLES:: sage: M = OverconvergentModularForms(3, 2, 1/2, prec=4) sage: M.gen(0) - 3-adic overconvergent modular form of weight-character 2 with q-expansion 1 + 12*q + 36*q^2 + 12*q^3 + O(q^4) + 3-adic overconvergent modular form of weight-character 2 + with q-expansion 1 + 12*q + 36*q^2 + 12*q^3 + O(q^4) sage: M.gen(1) - 3-adic overconvergent modular form of weight-character 2 with q-expansion 27*q + 648*q^2 + 7290*q^3 + O(q^4) + 3-adic overconvergent modular form of weight-character 2 + with q-expansion 27*q + 648*q^2 + 7290*q^3 + O(q^4) sage: M.gen(30) - 3-adic overconvergent modular form of weight-character 2 with q-expansion O(q^4) + 3-adic overconvergent modular form of weight-character 2 + with q-expansion O(q^4) """ return OverconvergentModularFormElement(self, gexp=self._gsr.gen()**i) @@ -627,7 +645,7 @@ def _repr_(self): def prime(self): r""" - Return the residue characteristic of self, i.e. the prime `p` such that + Return the residue characteristic of ``self``, i.e. the prime `p` such that this is a `p`-adic space. EXAMPLES:: @@ -651,16 +669,18 @@ def radius(self): def gens(self): r""" Return a generator object that iterates over the (infinite) set of - basis vectors of self. + basis vectors of ``self``. EXAMPLES:: sage: o = OverconvergentModularForms(3, 12, 1/2) sage: t = o.gens() sage: next(t) - 3-adic overconvergent modular form of weight-character 12 with q-expansion 1 - 32760/61203943*q - 67125240/61203943*q^2 - ... + 3-adic overconvergent modular form of weight-character 12 with q-expansion + 1 - 32760/61203943*q - 67125240/61203943*q^2 - ... sage: next(t) - 3-adic overconvergent modular form of weight-character 12 with q-expansion 27*q + 19829193012/61203943*q^2 + 146902585770/61203943*q^3 + ... + 3-adic overconvergent modular form of weight-character 12 with q-expansion + 27*q + 19829193012/61203943*q^2 + 146902585770/61203943*q^3 + ... """ i = 0 while True: @@ -844,10 +864,10 @@ def _coerce_map_from_(self, other): def coordinate_vector(self, x): r""" - Write x as a vector with respect to the basis given by self.basis(). - Here x must be an element of this space or something that can be - converted into one. If x has precision less than the default precision - of self, then the returned vector will be shorter. + Write ``x`` as a vector with respect to the basis given by ``self.basis()``. + Here ``x`` must be an element of this space or something that can be + converted into one. If ``x`` has precision less than the default precision + of ``self``, then the returned vector will be shorter. EXAMPLES:: @@ -873,7 +893,7 @@ def coordinate_vector(self, x): def ngens(self): r""" - The number of generators of self (as a module over its base ring), i.e. infinity. + The number of generators of ``self`` (as a module over its base ring), i.e. infinity. EXAMPLES:: @@ -893,7 +913,7 @@ def hecke_operator(self, f, m): `T_m` acting on `f`. The input may be either a "bare" power series, or an - OverconvergentModularFormElement object; the return value will be of + :class:`OverconvergentModularFormElement` object; the return value will be of the same type. EXAMPLES:: @@ -901,7 +921,8 @@ def hecke_operator(self, f, m): sage: M = OverconvergentModularForms(3, 0, 1/2) sage: f = M.1 sage: M.hecke_operator(f, 3) - 3-adic overconvergent modular form of weight-character 0 with q-expansion 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + 52494114852*q^6 + O(q^7) + 3-adic overconvergent modular form of weight-character 0 with q-expansion + 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + 52494114852*q^6 + O(q^7) sage: M.hecke_operator(f.q_expansion(), 3) 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + 52494114852*q^6 + O(q^7) """ @@ -964,11 +985,13 @@ def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): [ 0 24 64 0] [ 0 32 1152 4608] [ 0 0 3072 61440] - sage: OverconvergentModularForms(2, 12, 1/2, base_ring=pAdicField(2)).hecke_matrix(2, 3) * (1 + O(2^2)) + sage: o = OverconvergentModularForms(2, 12, 1/2, base_ring=pAdicField(2)) + sage: o.hecke_matrix(2, 3) * (1 + O(2^2)) [ 1 + O(2^2) 0 0] [ 0 2^3 + O(2^5) 2^6 + O(2^8)] [ 0 2^4 + O(2^6) 2^7 + 2^8 + O(2^9)] - sage: OverconvergentModularForms(2, 12, 1/2, base_ring=pAdicField(2)).hecke_matrix(2, 3, exact_arith=True) + sage: o = OverconvergentModularForms(2, 12, 1/2, base_ring=pAdicField(2)) + sage: o.hecke_matrix(2, 3, exact_arith=True) [ 1 0 0] [ 0 33881928/1414477 64] [ 0 -192898739923312/2000745183529 1626332544/1414477] @@ -1026,13 +1049,13 @@ def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): def slopes(self, n, use_recurrence=False): r""" - Compute the slopes of the `U_p` operator acting on self, using an n x n matrix. + Compute the slopes of the `U_p` operator acting on self, using an `n\times n` matrix. EXAMPLES:: - sage: OverconvergentModularForms(5,2,1/3,base_ring=Qp(5),prec=100).slopes(5) + sage: OverconvergentModularForms(5, 2, 1/3, base_ring=Qp(5), prec=100).slopes(5) [0, 2, 5, 6, 9] - sage: OverconvergentModularForms(2,1,1/3,char=DirichletGroup(4,QQ).0).slopes(5) + sage: OverconvergentModularForms(2, 1, 1/3, char=DirichletGroup(4,QQ).0).slopes(5) [0, 2, 4, 6, 8] """ if self.base_ring() == QQ: @@ -1045,22 +1068,22 @@ def slopes(self, n, use_recurrence=False): def eigenfunctions(self, n, F=None, exact_arith=True): """ - Calculate approximations to eigenfunctions of self. + Calculate approximations to eigenfunctions of ``self``. - These are the eigenfunctions of self.hecke_matrix(p, n), which + These are the eigenfunctions of ``self.hecke_matrix(p, n)``, which are approximations to the true eigenfunctions. Returns a list - of OverconvergentModularFormElement objects, in increasing + of :class:`OverconvergentModularFormElement` objects, in increasing order of slope. INPUT: - - ``n`` - integer. The size of the matrix to use. + - ``n`` -- integer. The size of the matrix to use. - - ``F`` - None, or a field over which to calculate eigenvalues. If the - field is None, the current base ring is used. If the base ring is not + - ``F`` -- either ``None`` or a field over which to calculate eigenvalues. If the + field is ``None``, the current base ring is used. If the base ring is not a `p`-adic ring, an error will be raised. - - ``exact_arith`` - True or False (default True). If True, use exact + - ``exact_arith`` -- ``True`` or ``False`` (default ``True``). If ``True``, use exact rational arithmetic to calculate the matrix of the `U` operator and its characteristic power series, even when the base ring is an inexact `p`-adic ring. This is typically slower, but more numerically stable. @@ -1073,7 +1096,8 @@ def eigenfunctions(self, n, F=None, exact_arith=True): sage: X = OverconvergentModularForms(2, 2, 1/6).eigenfunctions(8, Qp(2, 100)) sage: X[1] - 2-adic overconvergent modular form of weight-character 2 with q-expansion (1 + O(2^74))*q + (2^4 + 2^5 + 2^9 + 2^10 + 2^12 + 2^13 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^28 + 2^30 + 2^31 + 2^32 + 2^34 + 2^36 + 2^37 + 2^39 + 2^40 + 2^43 + 2^44 + 2^45 + 2^47 + 2^48 + 2^52 + 2^53 + 2^54 + 2^55 + 2^56 + 2^58 + 2^59 + 2^60 + 2^61 + 2^67 + 2^68 + 2^70 + 2^71 + 2^72 + 2^74 + 2^76 + O(2^78))*q^2 + (2^2 + 2^7 + 2^8 + 2^9 + 2^12 + 2^13 + 2^16 + 2^17 + 2^21 + 2^23 + 2^25 + 2^28 + 2^33 + 2^34 + 2^36 + 2^37 + 2^42 + 2^45 + 2^47 + 2^49 + 2^50 + 2^51 + 2^54 + 2^55 + 2^58 + 2^60 + 2^61 + 2^67 + 2^71 + 2^72 + O(2^76))*q^3 + (2^8 + 2^11 + 2^14 + 2^19 + 2^21 + 2^22 + 2^24 + 2^25 + 2^26 + 2^27 + 2^28 + 2^29 + 2^32 + 2^33 + 2^35 + 2^36 + 2^44 + 2^45 + 2^46 + 2^47 + 2^49 + 2^50 + 2^53 + 2^54 + 2^55 + 2^56 + 2^57 + 2^60 + 2^63 + 2^66 + 2^67 + 2^69 + 2^74 + 2^76 + 2^79 + 2^80 + 2^81 + O(2^82))*q^4 + (2 + 2^2 + 2^9 + 2^13 + 2^15 + 2^17 + 2^19 + 2^21 + 2^23 + 2^26 + 2^27 + 2^28 + 2^30 + 2^33 + 2^34 + 2^35 + 2^36 + 2^37 + 2^38 + 2^39 + 2^41 + 2^42 + 2^43 + 2^45 + 2^58 + 2^59 + 2^60 + 2^61 + 2^62 + 2^63 + 2^65 + 2^66 + 2^68 + 2^69 + 2^71 + 2^72 + O(2^75))*q^5 + (2^6 + 2^7 + 2^15 + 2^16 + 2^21 + 2^24 + 2^25 + 2^28 + 2^29 + 2^33 + 2^34 + 2^37 + 2^44 + 2^45 + 2^48 + 2^50 + 2^51 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^64 + 2^69 + 2^71 + 2^73 + 2^75 + 2^78 + O(2^80))*q^6 + (2^3 + 2^8 + 2^9 + 2^10 + 2^11 + 2^12 + 2^14 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^25 + 2^26 + 2^34 + 2^37 + 2^38 + 2^39 + 2^40 + 2^41 + 2^45 + 2^47 + 2^49 + 2^51 + 2^53 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^61 + 2^66 + 2^69 + 2^70 + 2^71 + 2^74 + 2^76 + O(2^77))*q^7 + O(q^8) + 2-adic overconvergent modular form of weight-character 2 with q-expansion + (1 + O(2^74))*q + (2^4 + 2^5 + 2^9 + 2^10 + 2^12 + 2^13 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^28 + 2^30 + 2^31 + 2^32 + 2^34 + 2^36 + 2^37 + 2^39 + 2^40 + 2^43 + 2^44 + 2^45 + 2^47 + 2^48 + 2^52 + 2^53 + 2^54 + 2^55 + 2^56 + 2^58 + 2^59 + 2^60 + 2^61 + 2^67 + 2^68 + 2^70 + 2^71 + 2^72 + 2^74 + 2^76 + O(2^78))*q^2 + (2^2 + 2^7 + 2^8 + 2^9 + 2^12 + 2^13 + 2^16 + 2^17 + 2^21 + 2^23 + 2^25 + 2^28 + 2^33 + 2^34 + 2^36 + 2^37 + 2^42 + 2^45 + 2^47 + 2^49 + 2^50 + 2^51 + 2^54 + 2^55 + 2^58 + 2^60 + 2^61 + 2^67 + 2^71 + 2^72 + O(2^76))*q^3 + (2^8 + 2^11 + 2^14 + 2^19 + 2^21 + 2^22 + 2^24 + 2^25 + 2^26 + 2^27 + 2^28 + 2^29 + 2^32 + 2^33 + 2^35 + 2^36 + 2^44 + 2^45 + 2^46 + 2^47 + 2^49 + 2^50 + 2^53 + 2^54 + 2^55 + 2^56 + 2^57 + 2^60 + 2^63 + 2^66 + 2^67 + 2^69 + 2^74 + 2^76 + 2^79 + 2^80 + 2^81 + O(2^82))*q^4 + (2 + 2^2 + 2^9 + 2^13 + 2^15 + 2^17 + 2^19 + 2^21 + 2^23 + 2^26 + 2^27 + 2^28 + 2^30 + 2^33 + 2^34 + 2^35 + 2^36 + 2^37 + 2^38 + 2^39 + 2^41 + 2^42 + 2^43 + 2^45 + 2^58 + 2^59 + 2^60 + 2^61 + 2^62 + 2^63 + 2^65 + 2^66 + 2^68 + 2^69 + 2^71 + 2^72 + O(2^75))*q^5 + (2^6 + 2^7 + 2^15 + 2^16 + 2^21 + 2^24 + 2^25 + 2^28 + 2^29 + 2^33 + 2^34 + 2^37 + 2^44 + 2^45 + 2^48 + 2^50 + 2^51 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^64 + 2^69 + 2^71 + 2^73 + 2^75 + 2^78 + O(2^80))*q^6 + (2^3 + 2^8 + 2^9 + 2^10 + 2^11 + 2^12 + 2^14 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^25 + 2^26 + 2^34 + 2^37 + 2^38 + 2^39 + 2^40 + 2^41 + 2^45 + 2^47 + 2^49 + 2^51 + 2^53 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^61 + 2^66 + 2^69 + 2^70 + 2^71 + 2^74 + 2^76 + O(2^77))*q^7 + O(q^8) sage: [x.slope() for x in X] [0, 4, 8, 14, 16, 18, 26, 30] """ @@ -1248,8 +1272,8 @@ def _discover_recurrence_matrix(self, use_smithline=True): def cps_u(self, n, use_recurrence=False): r""" - Compute the characteristic power series of `U_p` acting on self, using - an n x n matrix. + Compute the characteristic power series of `U_p` acting on ``self``, using + an `n\times n` matrix. EXAMPLES:: @@ -1440,12 +1464,16 @@ def eigenvalue(self): def q_expansion(self, prec=None): r""" - Return the `q`-expansion of self, to as high precision as it is known. + Return the `q`-expansion of ``self``, to as high precision as it is known. EXAMPLES:: sage: OverconvergentModularForms(3, 4, 1/2).gen(0).q_expansion() - 1 - 120/13*q - 1080/13*q^2 - 120/13*q^3 - 8760/13*q^4 - 15120/13*q^5 - 1080/13*q^6 - 41280/13*q^7 - 5400*q^8 - 120/13*q^9 - 136080/13*q^10 - 159840/13*q^11 - 8760/13*q^12 - 263760/13*q^13 - 371520/13*q^14 - 15120/13*q^15 - 561720/13*q^16 - 45360*q^17 - 1080/13*q^18 - 823200/13*q^19 + O(q^20) + 1 - 120/13*q - 1080/13*q^2 - 120/13*q^3 - 8760/13*q^4 - 15120/13*q^5 + - 1080/13*q^6 - 41280/13*q^7 - 5400*q^8 - 120/13*q^9 - 136080/13*q^10 + - 159840/13*q^11 - 8760/13*q^12 - 263760/13*q^13 - 371520/13*q^14 + - 15120/13*q^15 - 561720/13*q^16 - 45360*q^17 - 1080/13*q^18 + - 823200/13*q^19 + O(q^20) """ if prec is None: return self._qexp @@ -1668,7 +1696,7 @@ def weight(self): def additive_order(self): r""" Return the additive order of this element (required attribute for all - elements deriving from sage.modules.ModuleElement). + elements deriving from :class:`sage.modules.ModuleElement`). EXAMPLES:: @@ -1688,21 +1716,24 @@ def additive_order(self): def base_extend(self, R): r""" - Return a copy of self but with coefficients in the given ring. + Return a copy of ``self`` but with coefficients in the given ring. EXAMPLES:: sage: M = OverconvergentModularForms(7, 10, 1/2, prec=5) sage: f = M.1 sage: f.base_extend(Qp(7, 4)) - 7-adic overconvergent modular form of weight-character 10 with q-expansion (7 + O(7^5))*q + (6*7 + 4*7^2 + 7^3 + 6*7^4 + O(7^5))*q^2 + (5*7 + 5*7^2 + 7^4 + O(7^5))*q^3 + (7^2 + 4*7^3 + 3*7^4 + 2*7^5 + O(7^6))*q^4 + O(q^5) + 7-adic overconvergent modular form of weight-character 10 with q-expansion + (7 + O(7^5))*q + (6*7 + 4*7^2 + 7^3 + 6*7^4 + O(7^5))*q^2 + + (5*7 + 5*7^2 + 7^4 + O(7^5))*q^3 + (7^2 + 4*7^3 + 3*7^4 + 2*7^5 + + O(7^6))*q^4 + O(q^5) """ S = self.parent().base_extend(R) return S(self) def __pari__(self): r""" - Return the Pari object corresponding to self, which is just the + Return the Pari object corresponding to ``self``, which is just the `q`-expansion of self as a formal power series. EXAMPLES:: From 64ab9dedadd3a5eb89df16c94467792d1f4c8463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 2 Apr 2024 08:36:26 +0200 Subject: [PATCH 086/191] fix sugegsted details --- src/sage/plot/arc.py | 10 +++++----- src/sage/plot/colors.py | 4 ++-- src/sage/plot/matrix_plot.py | 17 +++++++++-------- src/sage/plot/plot.py | 30 +++++++++++++++--------------- src/sage/plot/plot_field.py | 21 ++++++++++++--------- 5 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/sage/plot/arc.py b/src/sage/plot/arc.py index c7d8d76ffae..c2a0f69ed1c 100644 --- a/src/sage/plot/arc.py +++ b/src/sage/plot/arc.py @@ -1,7 +1,7 @@ """ Arcs of circles and ellipses """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2010 Vincent Delecroix <20100.delecroix@gmail.com>, # # Distributed under the terms of the GNU General Public License (GPL) @@ -13,8 +13,8 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.plot.primitive import GraphicPrimitive from sage.plot.colors import to_mpl_color @@ -336,7 +336,7 @@ def theta_stretch(theta, scale): g.add_primitive(BezierPath(cutlist, opt)) return g - def _repr_(self): + def _repr_(self) -> str: """ String representation of ``Arc`` primitive. @@ -346,7 +346,7 @@ def _repr_(self): sage: print(Arc(2,3,2.2,2.2,0,2,3,{})) Arc with center (2.0,3.0) radii (2.2,2.2) angle 0.0 inside the sector (2.0,3.0) """ - return "Arc with center ({},{}) radii ({},{}) angle {} inside the sector ({},{})".format(self.x, self.y, self.r1, self.r2, self.angle, self.s1, self.s2) + return f"Arc with center ({self.x},{self.y}) radii ({self.r1},{self.r2}) angle {self.angle} inside the sector ({self.s1},{self.s2})" def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py index cdc4a9f1b21..573750498d7 100644 --- a/src/sage/plot/colors.py +++ b/src/sage/plot/colors.py @@ -338,8 +338,8 @@ def rgbcolor(c, space='rgb'): elif isinstance(c, (list, tuple)): if len(c) != 3: - raise ValueError("color list or tuple '{}' must have 3 entries, one for each RGB, HSV, HLS, or HSL channel".format(c )) - c = [mod_one(_) for _ in list(c)] + raise ValueError(f"color list or tuple '{c}' must have 3 entries, one for each RGB, HSV, HLS, or HSL channel") + c = [mod_one(comp) for comp in c] if space == 'rgb': return tuple(c) elif space == 'hsv': diff --git a/src/sage/plot/matrix_plot.py b/src/sage/plot/matrix_plot.py index da55e540890..3e3e5c7dd24 100644 --- a/src/sage/plot/matrix_plot.py +++ b/src/sage/plot/matrix_plot.py @@ -1,7 +1,7 @@ """ Matrix plots """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 Alex Clemesha , # William Stein , # 2008 Mike Hansen , @@ -15,8 +15,8 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.plot.primitive import GraphicPrimitive from sage.misc.decorators import options, suboptions @@ -224,10 +224,11 @@ def _render_on_subplot(self, subplot): extent = (lim['xmin'], lim['xmax'], lim['ymax' if flip_y else 'ymin'], lim['ymin' if flip_y else 'ymax']) - opts = {'cmap': cmap, 'interpolation': 'nearest', 'aspect': 'equal', - 'norm': norm, 'vmin': options['vmin'], 'vmax': options['vmax'], - 'origin': ('upper' if flip_y else 'lower'), - 'extent': extent, 'zorder': options.get('zorder')} + opts = {'cmap': cmap, 'interpolation': 'nearest', + 'aspect': 'equal', 'norm': norm, + 'vmin': options['vmin'], 'vmax': options['vmax'], + 'origin': ('upper' if flip_y else 'lower'), + 'extent': extent, 'zorder': options.get('zorder')} image = subplot.imshow(self.xy_data_array, **opts) if options.get('colorbar', False): @@ -240,7 +241,7 @@ def _render_on_subplot(self, subplot): subplot.xaxis.tick_top() else: subplot.xaxis.tick_bottom() - subplot.xaxis.set_ticks_position('both') #only tick marks, not tick labels + subplot.xaxis.set_ticks_position('both') # only tick marks, not tick labels @suboptions('colorbar', orientation='vertical', format=None) diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 2f830297d4b..4f650fa4613 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -580,17 +580,17 @@ def f(x): return (x-3)*(x-5)*(x-7)+40 from functools import reduce -## IMPORTANT: Do *not* import matplotlib at module scope. It takes a -## surprisingly long time to initialize itself. It's better if it is -## imported in functions, so it only gets started if it is actually -## going to be used. +# IMPORTANT: Do *not* import matplotlib at module scope. It takes a +# surprisingly long time to initialize itself. It's better if it is +# imported in functions, so it only gets started if it is actually +# going to be used. -#DEFAULT_FIGSIZE=(6, 3.70820393249937) +# DEFAULT_FIGSIZE=(6, 3.70820393249937) import sage.misc.verbose from sage.arith.srange import srange -from sage.misc.randstate import current_randstate #for plot adaptive refinement -from math import sin, cos, pi, log, exp #for polar_plot and log scaling +from sage.misc.randstate import current_randstate # for plot adaptive refinement +from math import sin, cos, pi, log, exp # for polar_plot and log scaling from sage.ext.fast_eval import fast_float, is_fast_float from sage.structure.element import Expression @@ -605,10 +605,10 @@ def f(x): return (x-3)*(x-5)*(x-7)+40 from sage.misc.lazy_import import lazy_import lazy_import('sage.plot.line', 'line2d', deprecation=28717) -#Currently not used - see comment immediately above about -#figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) +# Currently not used - see comment immediately above about +# figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) # TODO - figure out how to use this, add documentation -#def pad_for_tick_labels(event): +# def pad_for_tick_labels(event): # import matplotlib.transforms as mtransforms # figure=event.canvas.figure # bboxes = [] @@ -638,10 +638,10 @@ def f(x): return (x-3)*(x-5)*(x-7)+40 # figure.canvas.draw() # return False # -#Currently not used - see comment above about -#figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) +# Currently not used - see comment above about +# figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) # TODO - figure out how to use this, add documentation -#def adjust_figure_to_contain_bbox(fig, bbox,pad=1.1): +# def adjust_figure_to_contain_bbox(fig, bbox,pad=1.1): # """ # For each amount we are over (in axes coordinates), we adjust by over*pad # to give ourselves a bit of padding. @@ -2069,7 +2069,7 @@ def f(x): return (floor(x)+0.5) / (1-(x-0.5)**2) xmax = kwds.pop('xmax', 1) G = _plot(funcs, (xmin, xmax), *args, **kwds) else: - sage.misc.verbose.verbose("there were {} extra arguments (besides {})".format(n, funcs), level=0) + sage.misc.verbose.verbose(f"there were {n} extra arguments (besides {funcs})", level=0) G._set_extra_kwds(G_kwds) if do_show: @@ -2078,7 +2078,7 @@ def f(x): return (floor(x)+0.5) / (1-(x-0.5)**2) def _plot(funcs, xrange, parametric=False, - polar=False, fill=False, label='', randomize=True, **options): + polar=False, fill=False, label='', randomize=True, **options): """ Internal function which does the actual plotting. diff --git a/src/sage/plot/plot_field.py b/src/sage/plot/plot_field.py index c8052fb1520..b1a9505eb81 100644 --- a/src/sage/plot/plot_field.py +++ b/src/sage/plot/plot_field.py @@ -2,7 +2,7 @@ """ Plotting fields """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 Alex Clemesha , # William Stein , # 2008 Mike Hansen , @@ -16,8 +16,8 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.plot.primitive import GraphicPrimitive from sage.misc.decorators import options from sage.arith.srange import xsrange @@ -256,12 +256,12 @@ def plot_vector_field(f_g, xrange, yrange, **options): x,y = var('x,y') g = plot_vector_field((x,y), (x,-2,2), (y,-2,2), xmax=10) sphinx_plot(g) - """ - (f,g) = f_g + f, g = f_g from sage.plot.all import Graphics from sage.plot.misc import setup_for_eval_on_grid - z, ranges = setup_for_eval_on_grid([f,g], [xrange,yrange], options['plot_points']) + z, ranges = setup_for_eval_on_grid([f, g], [xrange, yrange], + options['plot_points']) f, g = z xpos_array, ypos_array, xvec_array, yvec_array = [], [], [], [] @@ -352,9 +352,12 @@ def plot_slope_field(f, xrange, yrange, **kwds): from sage.misc.functional import sqrt from sage.misc.sageinspect import is_function_or_cython_function if is_function_or_cython_function(f): - norm_inverse = lambda x,y: 1/sqrt(f(x, y)**2+1) - f_normalized = lambda x,y: f(x, y)*norm_inverse(x, y) + def norm_inverse(x, y): + return 1 / sqrt(f(x, y)**2 + 1) + + def f_normalized(x, y): + return f(x, y) * norm_inverse(x, y) else: - norm_inverse = 1 / sqrt(f**2+1) + norm_inverse = 1 / sqrt(f**2 + 1) f_normalized = f * norm_inverse return plot_vector_field((norm_inverse, f_normalized), xrange, yrange, **slope_options) From 5a4fdd298958a264f0db5261ffe7c01ad65fea4f Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Wed, 3 Apr 2024 11:58:15 +0100 Subject: [PATCH 087/191] Fix a failing docstring --- src/sage/rings/polynomial/laurent_polynomial_mpair.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index fc50f83406b..17834718d1c 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -1199,7 +1199,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: f.degree(1) Traceback (most recent call last): ... - TypeError: x must be a generator of parent + TypeError: 1 is not a generator of parent """ # The zero polynomial is defined to have degree -Infinity if self.is_zero(): From a2b5799e13c485e0a34b7f0664b03f08e9c55c1a Mon Sep 17 00:00:00 2001 From: Giacomo Pope Date: Wed, 3 Apr 2024 12:20:07 +0100 Subject: [PATCH 088/191] Add checks for failing doctests --- .../rings/polynomial/polynomial_modn_dense_ntl.pyx | 12 +++++++----- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 4 ++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index bed65411fd0..a487cebd702 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -1808,13 +1808,15 @@ cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n): TESTS: - Negative powers will not work:: + Negative powers work but use the generic + implementation of fraction fields:: sage: R. = PolynomialRing(Integers(101), implementation='NTL') - sage: (x-1)^(-5) - Traceback (most recent call last): - ... - NotImplementedError: Fraction fields not implemented for this type. + sage: f = (x-1)^(-5) + sage: type(f) + + sage: (f + 2).numerator() + 2*x^5 + 91*x^4 + 20*x^3 + 81*x^2 + 10*x + 100 We define ``0^0`` to be unity, :issue:`13895`:: diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 9ed9acbaa84..a2cf2f2f31f 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -670,6 +670,10 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): """ exp = Integer(exp) if modulus is not None: + # Handle when modulus is zero + if modulus.is_zero(): + raise ZeroDivisionError("modulus must be nonzero") + # Similar to coerce_binop if not have_same_parent(self, modulus): a, m = canonical_coercion(self, modulus) From f997788e1e1de5dd0d8eef8c0fdacbc904a53d00 Mon Sep 17 00:00:00 2001 From: adrinospy Date: Wed, 3 Apr 2024 22:40:54 +0530 Subject: [PATCH 089/191] added environment variables for repeated literals --- .github/workflows/get_changes.sh | 61 +++++++++++++++++++++++++++ .github/workflows/pr-labeler.yml | 72 ++++++-------------------------- 2 files changed, 74 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/get_changes.sh diff --git a/.github/workflows/get_changes.sh b/.github/workflows/get_changes.sh new file mode 100644 index 00000000000..b2e716c9da5 --- /dev/null +++ b/.github/workflows/get_changes.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# get all the changes made and changed files +CHANGES=$(git diff --ignore-all-space $PR_BASE_SHA $PR_HEAD_SHA) + +# ignore blank lines +CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') + +# ignore non necessary lines from git diff +CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + +# count total no of lines +CHANGES=$(echo "$CHANGES" | wc -l) + +echo "CHANGES MADE: $CHANGES" + +# get changed files +CHANGED_PATH=$(git diff --name-only $PR_BASE_SHA $PR_HEAD_SHA) + +# extract changed dir +CHANGED_DIR=$(echo "$CHANGED_PATH" | awk -F'src/sage/' '{print $2}' | cut -d'/' -f1 | sed 's/\([^ ]\+\)/c: \1/g') + +AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN" + +DELETE_LABELS=("$MINIMAL" "$SMALL" "$MODERATE" "$LARGE") + +if [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then +SIZE_LABEL="$LARGE" +elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then +SIZE_LABEL="$MODERATE" +elif [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then +SIZE_LABEL="$SMALL" +else +SIZE_LABEL="$MINIMAL" +fi + +DELETE_LABELS=("${DELETE_LABELS[@]//${SIZE_LABEL}}") + +readarray -t LABELS <<< "$CHANGED_DIR" +LABELS+=("$SIZE_LABEL") + +echo "Adding label: ${LABELS[@]}" +for LABEL in "${LABELS[@]}"; do + curl -X POST \ + -H "$AUTH_HEADER" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -d "{\"labels\":[\"$LABEL\"]}" \ + "$API_URL" >/dev/null +done + +echo "Deleting Labels:" + +for DELETE_LABEL in "${DELETE_LABELS[@]}"; do + ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') + curl -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "$AUTH_HEADER" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$API_URL/$ENCODED_LABEL" >/dev/null +done \ No newline at end of file diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 91bd5fdc21f..521e7a2901b 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -9,6 +9,7 @@ on: - edited jobs: label-changes: + if: vars.SMALL_THRESHOLD && vars.MODERATE_THRESHOLD && vars.LARGE_THRESHOLD runs-on: ubuntu-latest permissions: pull-requests: write @@ -20,66 +21,19 @@ jobs: - name: Add labels based on size run: | - git fetch origin ${{ github.base_ref }} - - # get all the changes made and changed files - CHANGES=$(git diff --ignore-all-space ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) - CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | awk -F'src/sage/' '{print $2}' | cut -d'/' -f1 | sed 's/\([^ ]\+\)/c: \1/g') - - # ignore blank lines - CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') - - # ignore non necessary lines from git diff - CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') - - # count total no of lines - CHANGES=$(echo "$CHANGES" | wc -l) - - echo "CHANGES MADE: $CHANGES" - - PR_NUMBER="${{ github.event.number }}" - API_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels" - AUTH_HEADER="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" - - DELETE_LABELS=("v: minimal" "v: small" "v: moderate" "v: large") - - if [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then - SIZE_LABEL="v: small" - elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then - SIZE_LABEL="v: moderate" - elif [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then - SIZE_LABEL="v: large" - else - SIZE_LABEL="v: minimal" - fi - - DELETE_LABELS=("${DELETE_LABELS[@]//${SIZE_LABEL}}") - - readarray -t LABELS <<< "$CHANGED_FILES" - LABELS+=("$SIZE_LABEL") - - echo "Adding label: ${LABELS[@]}" - for LABEL in "${LABELS[@]}"; do - curl -X POST \ - -H "$AUTH_HEADER" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - -d "{\"labels\":[\"$LABEL\"]}" \ - "$API_URL" >/dev/null - done - - echo "Deleting Labels:" - - for DELETE_LABEL in "${DELETE_LABELS[@]}"; do - ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') - curl -X DELETE \ - -H "Accept: application/vnd.github+json" \ - -H "$AUTH_HEADER" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "$API_URL/$ENCODED_LABEL" >/dev/null - done + git fetch origin $BASE_SHA + chmod a+x .github/workflows/get_changes.sh + .github/workflows/get_changes.sh env: + BASE_SHA: ${{ github.base_ref }} + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + API_URL: "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" + MINIMAL: 'v: minimal' + SMALL: 'v: small' + MODERATE: 'v: moderate' + LARGE: 'v: large' SMALL_THRESHOLD: ${{ vars.SMALL_THRESHOLD }} MODERATE_THRESHOLD: ${{ vars.MODERATE_THRESHOLD }} - LARGE_THRESHOLD: ${{ vars.LARGE_THRESHOLD }} + LARGE_THRESHOLD: ${{ vars.LARGE_THRESHOLD }} \ No newline at end of file From f2c9efbd4b837082631eb89ce11191d22e9e00da Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 3 Apr 2024 21:48:36 -0700 Subject: [PATCH 090/191] src/sage/matrix/matrix_space.py: Add doctests and input checking --- src/sage/matrix/matrix_space.py | 73 ++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index cc3133046e5..cef1c416385 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -607,6 +607,57 @@ class MatrixSpace(UniqueRepresentation, Parent): sage: M1 = MatrixSpace(GF(2), 5) sage: M1(m * m) == M1(m) * M1(m) True + + Check various combinations of dimensions and row/column keys:: + + sage: MatrixSpace(QQ, ['a','b'], 4) + Set of Morphisms (Linear Transformations) + from Vector space of dimension 4 over Rational Field + to Free module generated by {'a', 'b'} over Rational Field + sage: MatrixSpace(QQ, 4, ['a','b']) + Set of Morphisms + from Free module generated by {'a', 'b'} over Rational Field + to Vector space of dimension 4 over Rational Field + in Category of finite dimensional vector spaces with basis + over (number fields and quotient fields and metric spaces) + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2) + Set of Morphisms + from Free module generated by {'x', 'y'} over Rational Field + to Vector space of dimension 2 over Rational Field + in Category of finite dimensional vector spaces with basis + over (number fields and quotient fields and metric spaces) + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=4) + Traceback (most recent call last): + ... + ValueError: inconsistent number of rows: + should be cardinality of ['a', 'b'] but got 4 + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], ncols=2) + Set of Morphisms (Linear Transformations) + from Vector space of dimension 2 over Rational Field + to Free module generated by {'a', 'b'} over Rational Field + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], ncols=4) + Traceback (most recent call last): + ... + ValueError: inconsistent number of columns: + should be cardinality of ['x', 'y'] but got 4 + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2, ncols=2) + Set of Morphisms (Linear Transformations) + from Vector space of dimension 2 over Rational Field + to Vector space of dimension 2 over Rational Field + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2, ncols=4) + Traceback (most recent call last): + ... + ValueError: inconsistent number of columns: + should be cardinality of ['x', 'y'] but got 4 + sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=4, ncols=4) + Traceback (most recent call last): + ... + ValueError: inconsistent number of columns: + should be cardinality of ['x', 'y'] but got 4 + sage: MatrixSpace(QQ, 4, ['a','b'], nrows=4, ncols=2) + Traceback (most recent call last): + ... + ValueError: duplicate values for nrows """ @staticmethod @@ -665,15 +716,33 @@ def __classcall__(cls, base_ring, if ncols_or_column_keys is not None: try: - ncols = int(ncols_or_column_keys) + n = int(ncols_or_column_keys) except (TypeError, ValueError): + if column_keys is not None: + raise ValueError("duplicate values for column_keys") column_keys = ncols_or_column_keys + else: + if ncols is not None: + raise ValueError("duplicate values for ncols") + ncols = n + if column_keys is not None and ncols is not None and ncols != len(column_keys): + raise ValueError(f"inconsistent number of columns: should be cardinality of {column_keys} " + f"but got {ncols}") if nrows_or_row_keys is not None: try: - nrows = int(nrows_or_row_keys) + n = int(nrows_or_row_keys) except (TypeError, ValueError): + if row_keys is not None: + raise ValueError("duplicate values for row_keys") row_keys = nrows_or_row_keys + else: + if nrows is not None: + raise ValueError("duplicate values for nrows") + nrows = n + if row_keys is not None and nrows is not None and nrows != len(row_keys): + raise ValueError(f"inconsistent number of rows: should be cardinality of {row_keys} " + f"but got {nrows}") if ncols is None and column_keys is None: ncols = nrows From d969885c8d473a5ec98b89fc9be3bcd827aecee7 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Thu, 4 Apr 2024 20:10:58 +0200 Subject: [PATCH 091/191] be more specific also for ore polynomials, adapt doctests --- src/sage/categories/action.pyx | 4 ++-- src/sage/categories/map.pyx | 2 +- src/sage/categories/modules_with_basis.py | 2 +- .../dynamics/arithmetic_dynamics/dynamical_semigroup.py | 2 +- src/sage/matrix/matrix1.pyx | 2 +- src/sage/rings/polynomial/ore_polynomial_element.pyx | 4 ++-- src/sage/rings/polynomial/polynomial_element.pyx | 8 ++++---- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 3b3ba9d463b..9a9f9c45668 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -148,7 +148,7 @@ cdef class Action(Functor): sage: A(x, 5) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: x sage: A = IntegerMulAction(ZZ, R, False) # Right action sage: A(x, 5) 5*x @@ -157,7 +157,7 @@ cdef class Action(Functor): sage: A(5, x) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: x """ if len(args) == 2: # Normal case, called with (g, x) or (x, g) as arguments diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 29613f16285..e687cad229b 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -2087,7 +2087,7 @@ cdef class FormalCompositeMap(Map): sage: ZZ(3*x + 45) # indirect doctest Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: 3*x + 45 """ sections = [] for m in reversed(list(self)): diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index e1fa796ba3b..4d9049e1894 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1332,7 +1332,7 @@ def _from_dict(self, d, coerce=True, remove_zeros=True): sage: A._from_dict(d, coerce=True) # needs sage.modules Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: y """ R = self.base_ring() B = self.basis() diff --git a/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py index ebb8702a7db..a12c2d257fb 100644 --- a/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +++ b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py @@ -697,7 +697,7 @@ def orbit(self, p, n): sage: d.orbit(2, x) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: x :: diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index b15eb21da77..e13114eb849 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -1925,7 +1925,7 @@ cdef class Matrix(Matrix0): sage: D = A.augment(B) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: y sage: E = A.change_ring(R) sage: F = E.augment(B); F diff --git a/src/sage/rings/polynomial/ore_polynomial_element.pyx b/src/sage/rings/polynomial/ore_polynomial_element.pyx index 86c2a057353..d5c429b4d8e 100644 --- a/src/sage/rings/polynomial/ore_polynomial_element.pyx +++ b/src/sage/rings/polynomial/ore_polynomial_element.pyx @@ -3010,7 +3010,7 @@ cdef class ConstantOrePolynomialSection(Map): sage: m(S([0,1])-S([0,t])) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: (-t + 1)*x """ if x.degree() <= 0: try: @@ -3018,7 +3018,7 @@ cdef class ConstantOrePolynomialSection(Map): except AttributeError: return ((x).constant_coefficient()) else: - raise TypeError("not a constant polynomial") + raise TypeError(f"not a constant polynomial: {x}") cdef class OrePolynomialBaseringInjection(Morphism): diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 8b58e403d3d..7c5646aa267 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -1476,7 +1476,7 @@ cdef class Polynomial(CommutativePolynomial): sage: QQ(3*x + 45) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: 3*x + 45 """ return self._scalar_conversion(sage.rings.rational.Rational) @@ -12894,7 +12894,7 @@ cdef class ConstantPolynomialSection(Map): sage: phi(y_1) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: y_1 """ cpdef Element _call_(self, x) noexcept: """ @@ -12913,7 +12913,7 @@ cdef class ConstantPolynomialSection(Map): sage: m(x) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: x """ if x.degree() <= 0: try: @@ -12921,7 +12921,7 @@ cdef class ConstantPolynomialSection(Map): except AttributeError: return ((x).constant_coefficient()) else: - raise TypeError("not a constant polynomial") + raise TypeError(f"not a constant polynomial: {x}") cdef class PolynomialBaseringInjection(Morphism): """ diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 9a0384c643b..0f588b48d89 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -99,7 +99,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: R([3,x]) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: x Check that NTL contexts are correctly restored and that :issue:`9524` has been fixed:: From 14045bf73ae13f871812a5ca47b080f2a3e64c3a Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 5 Apr 2024 01:11:17 +0200 Subject: [PATCH 092/191] fix doctest --- src/doc/en/thematic_tutorials/coercion_and_categories.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index edd89ad3c42..f6cb67993ac 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -837,7 +837,7 @@ The four axioms requested for coercions sage: ZZ(P2.gen(1)) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: not a constant polynomial: v Hence, we only have a *partial* map. This is fine for a *conversion*, but a partial map does not qualify as a *coercion*. From 5e0ba2b2bc8b816537b95a2663160a17ca193259 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 5 Apr 2024 15:30:12 +0200 Subject: [PATCH 093/191] improve error message --- src/doc/en/thematic_tutorials/coercion_and_categories.rst | 2 +- src/sage/categories/action.pyx | 4 ++-- src/sage/categories/map.pyx | 2 +- src/sage/categories/modules_with_basis.py | 2 +- .../dynamics/arithmetic_dynamics/dynamical_semigroup.py | 2 +- src/sage/matrix/matrix1.pyx | 2 +- src/sage/rings/polynomial/ore_function_element.py | 4 ++-- src/sage/rings/polynomial/ore_polynomial_element.pyx | 4 ++-- src/sage/rings/polynomial/polynomial_element.pyx | 8 ++++---- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index f6cb67993ac..afa83bfa754 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -837,7 +837,7 @@ The four axioms requested for coercions sage: ZZ(P2.gen(1)) Traceback (most recent call last): ... - TypeError: not a constant polynomial: v + TypeError: v is not a constant polynomial Hence, we only have a *partial* map. This is fine for a *conversion*, but a partial map does not qualify as a *coercion*. diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 9a9f9c45668..4a026093411 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -148,7 +148,7 @@ cdef class Action(Functor): sage: A(x, 5) Traceback (most recent call last): ... - TypeError: not a constant polynomial: x + TypeError: x is not a constant polynomial sage: A = IntegerMulAction(ZZ, R, False) # Right action sage: A(x, 5) 5*x @@ -157,7 +157,7 @@ cdef class Action(Functor): sage: A(5, x) Traceback (most recent call last): ... - TypeError: not a constant polynomial: x + TypeError: x is not a constant polynomial """ if len(args) == 2: # Normal case, called with (g, x) or (x, g) as arguments diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index e687cad229b..439c7cf0ac9 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -2087,7 +2087,7 @@ cdef class FormalCompositeMap(Map): sage: ZZ(3*x + 45) # indirect doctest Traceback (most recent call last): ... - TypeError: not a constant polynomial: 3*x + 45 + TypeError: 3*x + 45 is not a constant polynomial """ sections = [] for m in reversed(list(self)): diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 4d9049e1894..fda93510d07 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1332,7 +1332,7 @@ def _from_dict(self, d, coerce=True, remove_zeros=True): sage: A._from_dict(d, coerce=True) # needs sage.modules Traceback (most recent call last): ... - TypeError: not a constant polynomial: y + TypeError: y is not a constant polynomial """ R = self.base_ring() B = self.basis() diff --git a/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py index a12c2d257fb..93c402d4695 100644 --- a/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +++ b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py @@ -697,7 +697,7 @@ def orbit(self, p, n): sage: d.orbit(2, x) Traceback (most recent call last): ... - TypeError: not a constant polynomial: x + TypeError: x is not a constant polynomial :: diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index e13114eb849..231b6f50333 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -1925,7 +1925,7 @@ cdef class Matrix(Matrix0): sage: D = A.augment(B) Traceback (most recent call last): ... - TypeError: not a constant polynomial: y + TypeError: y is not a constant polynomial sage: E = A.change_ring(R) sage: F = E.augment(B); F diff --git a/src/sage/rings/polynomial/ore_function_element.py b/src/sage/rings/polynomial/ore_function_element.py index f44dd8ad880..0c1a919351f 100644 --- a/src/sage/rings/polynomial/ore_function_element.py +++ b/src/sage/rings/polynomial/ore_function_element.py @@ -708,13 +708,13 @@ def _call_(self, x): sage: F(g) # needs sage.rings.function_field Traceback (most recent call last): ... - TypeError: not a constant function + TypeError: (x + t^2)^(-1) * x is not a constant function """ numerator = x._numerator denominator = x._denominator if numerator.degree() == denominator.degree() and denominator.right_divides(numerator): return numerator.leading_coefficient() / denominator.leading_coefficient() - raise TypeError("not a constant function") + raise TypeError(f"{x} is not a constant function") class OreFunctionBaseringInjection(Morphism): r""" diff --git a/src/sage/rings/polynomial/ore_polynomial_element.pyx b/src/sage/rings/polynomial/ore_polynomial_element.pyx index d5c429b4d8e..00fa90f2d11 100644 --- a/src/sage/rings/polynomial/ore_polynomial_element.pyx +++ b/src/sage/rings/polynomial/ore_polynomial_element.pyx @@ -3010,7 +3010,7 @@ cdef class ConstantOrePolynomialSection(Map): sage: m(S([0,1])-S([0,t])) Traceback (most recent call last): ... - TypeError: not a constant polynomial: (-t + 1)*x + TypeError: (-t + 1)*x is not a constant polynomial """ if x.degree() <= 0: try: @@ -3018,7 +3018,7 @@ cdef class ConstantOrePolynomialSection(Map): except AttributeError: return ((x).constant_coefficient()) else: - raise TypeError(f"not a constant polynomial: {x}") + raise TypeError(f"{x} is not a constant polynomial") cdef class OrePolynomialBaseringInjection(Morphism): diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 7c5646aa267..d2b8159696e 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -1476,7 +1476,7 @@ cdef class Polynomial(CommutativePolynomial): sage: QQ(3*x + 45) Traceback (most recent call last): ... - TypeError: not a constant polynomial: 3*x + 45 + TypeError: 3*x + 45 is not a constant polynomial """ return self._scalar_conversion(sage.rings.rational.Rational) @@ -12894,7 +12894,7 @@ cdef class ConstantPolynomialSection(Map): sage: phi(y_1) Traceback (most recent call last): ... - TypeError: not a constant polynomial: y_1 + TypeError: y_1 is not a constant polynomial """ cpdef Element _call_(self, x) noexcept: """ @@ -12913,7 +12913,7 @@ cdef class ConstantPolynomialSection(Map): sage: m(x) Traceback (most recent call last): ... - TypeError: not a constant polynomial: x + TypeError: x is not a constant polynomial """ if x.degree() <= 0: try: @@ -12921,7 +12921,7 @@ cdef class ConstantPolynomialSection(Map): except AttributeError: return ((x).constant_coefficient()) else: - raise TypeError(f"not a constant polynomial: {x}") + raise TypeError(f"{x} is not a constant polynomial") cdef class PolynomialBaseringInjection(Morphism): """ diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 0f588b48d89..e7ad9e35686 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -99,7 +99,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: R([3,x]) Traceback (most recent call last): ... - TypeError: not a constant polynomial: x + TypeError: x is not a constant polynomial Check that NTL contexts are correctly restored and that :issue:`9524` has been fixed:: From b6ecf3ce5ecbbc71bbc6699b5a8a4ccfc1879964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6ppe?= Date: Fri, 5 Apr 2024 16:33:45 -0700 Subject: [PATCH 094/191] Apply suggestions from code review Co-authored-by: Sebastian A. Spindler <153911337+S17A05@users.noreply.github.com> --- src/sage/modular/hypergeometric_motive.py | 2 +- src/sage/modular/modsym/p1list_nf.py | 14 +++++++------- src/sage/modular/overconvergent/genus0.py | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/modular/hypergeometric_motive.py b/src/sage/modular/hypergeometric_motive.py index 111c93ff07f..bcb719fef9b 100644 --- a/src/sage/modular/hypergeometric_motive.py +++ b/src/sage/modular/hypergeometric_motive.py @@ -1468,7 +1468,7 @@ def H_value(self, p, f, t, ring=None): .. WARNING:: This is apparently working correctly as can be tested - using ``ComplexField(70)`` as value ring. + using ``ComplexField(70)`` as the value ring. Using instead :class:`UniversalCyclotomicfield`, this is much slower than the `p`-adic version :meth:`padic_H_value`. diff --git a/src/sage/modular/modsym/p1list_nf.py b/src/sage/modular/modsym/p1list_nf.py index 29b5c087642..edb8248b6da 100644 --- a/src/sage/modular/modsym/p1list_nf.py +++ b/src/sage/modular/modsym/p1list_nf.py @@ -128,10 +128,10 @@ class MSymbol(SageObject): level N. - ``d`` -- (optional) when present, it must be an integral element such - that `\la c\ra + \la d\ra + N = R, where `R` is the corresponding ring of integers. + that `\langle c\rangle + \langle d\rangle + N = R`, where `R` is the corresponding ring of integers. - ``check`` -- bool (default ``True``). If ``check=False`` the constructor does - not check the condition `\la c\ra + \la d\ra + N = R`. + not check the condition `\langle c\rangle + \langle d\rangle + N = R`. OUTPUT: @@ -154,7 +154,7 @@ class MSymbol(SageObject): sage: MSymbol(N, (1, 0)) M-symbol (1: 0) of level Fractional ideal (2, a + 1) - We get an error if `\la c\ra`, `\la d\ra` and `N` are not coprime: + We get an error if `\langle c\rangle`, `\langle d\rangle` and `N` are not coprime: :: @@ -916,7 +916,7 @@ def apply_TS(self, i): def apply_T_alpha(self, i, alpha=1): r""" - Applies the matrix `T_alpha` = [1, alpha, 0, 1] to the `i`-th M-Symbol of + Applies the matrix `T_{alpha}` = [1, `alpha`, 0, 1] to the `i`-th M-Symbol of the list. INPUT: @@ -928,7 +928,7 @@ def apply_T_alpha(self, i, alpha=1): OUTPUT: integer -- the index of the M-Symbol obtained by the right action of - the matrix `T_alpha` = [1, `alpha`, 0, 1] on the i-th M-Symbol. + the matrix `T_{alpha}` = [1, `alpha`, 0, 1] on the i-th M-Symbol. EXAMPLES:: @@ -1164,7 +1164,7 @@ def lift_to_sl2_Ok(N, c, d): def make_coprime(N, c, d): r""" Return (c, d') so d' is congruent to d modulo N, and such that c and d' are - coprime (`\la c\ra + \la d'\ra = R`). + coprime (`\langle c\rangle + \langle d'\rangle = R`). INPUT: @@ -1177,7 +1177,7 @@ def make_coprime(N, c, d): OUTPUT: A pair `(c, d')` where `c`, `d'` are integral elements of the corresponding - number field, with `d'` congruent to `d` mod `N`, and such that `\la c\ra + \la d'\ra = R` + number field, with `d'` congruent to `d` mod `N`, and such that `\langle c\rangle + \langle d'\rangle = R` (`R` being the corresponding ring of integers). EXAMPLES:: diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index fef0f95983a..2d8a1f64532 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -1734,7 +1734,7 @@ def base_extend(self, R): def __pari__(self): r""" Return the Pari object corresponding to ``self``, which is just the - `q`-expansion of self as a formal power series. + `q`-expansion of ``self`` as a formal power series. EXAMPLES:: From 00c0c70dd0861184efdb4f9a51031226bbf77abf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Apr 2024 17:08:37 -0700 Subject: [PATCH 095/191] src/sage/modular/overconvergent/genus0.py: More docstring/doctest cosmetics --- src/sage/modular/overconvergent/genus0.py | 246 +++++++++++++++------- 1 file changed, 175 insertions(+), 71 deletions(-) diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 2d8a1f64532..50da43a3e08 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -116,7 +116,7 @@ :: - sage: M.hecke_matrix(3, 4).change_ring(Qp(3,prec=1)) + sage: M.hecke_matrix(3, 4).change_ring(Qp(3, prec=1)) [ 1 + O(3) 0 0 0] [ 0 2*3^3 + O(3^4) 2*3^3 + O(3^4) 3^2 + O(3^3)] [ 0 2*3^7 + O(3^8) 2*3^8 + O(3^9) 3^6 + O(3^7)] @@ -130,10 +130,25 @@ sage: efuncs = M.eigenfunctions(4) sage: for i in [1..3]: - ....: print(efuncs[i].q_expansion(prec=4).change_ring(Qp(3,prec=20))) - (1 + O(3^20))*q + (2*3 + 3^15 + 3^16 + 3^17 + 2*3^19 + 2*3^20 + O(3^21))*q^2 + (2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + 2*3^15 + 2*3^16 + 3^17 + 2*3^18 + 2*3^19 + 3^21 + 3^22 + O(3^23))*q^3 + O(q^4) - (1 + O(3^20))*q + (3 + 2*3^2 + 3^3 + 3^4 + 3^12 + 3^13 + 2*3^14 + 3^15 + 2*3^17 + 3^18 + 3^19 + 3^20 + O(3^21))*q^2 + (3^7 + 3^13 + 2*3^14 + 2*3^15 + 3^16 + 3^17 + 2*3^18 + 3^20 + 2*3^21 + 2*3^22 + 2*3^23 + 2*3^25 + O(3^27))*q^3 + O(q^4) - (1 + O(3^20))*q + (2*3 + 3^3 + 2*3^4 + 3^6 + 2*3^8 + 3^9 + 3^10 + 2*3^11 + 2*3^13 + 3^16 + 3^18 + 3^19 + 3^20 + O(3^21))*q^2 + (3^9 + 2*3^12 + 3^15 + 3^17 + 3^18 + 3^19 + 3^20 + 2*3^22 + 2*3^23 + 2*3^27 + 2*3^28 + O(3^29))*q^3 + O(q^4) + ....: print(efuncs[i].q_expansion(prec=4).change_ring(Qp(3, prec=20))) + (1 + O(3^20))*q + + (2*3 + 3^15 + 3^16 + 3^17 + 2*3^19 + 2*3^20 + O(3^21))*q^2 + + (2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + 2*3^15 + + 2*3^16 + 3^17 + 2*3^18 + 2*3^19 + 3^21 + 3^22 + O(3^23))*q^3 + + O(q^4) + (1 + O(3^20))*q + + (3 + 2*3^2 + 3^3 + 3^4 + 3^12 + 3^13 + 2*3^14 + + 3^15 + 2*3^17 + 3^18 + 3^19 + 3^20 + O(3^21))*q^2 + + (3^7 + 3^13 + 2*3^14 + 2*3^15 + 3^16 + 3^17 + 2*3^18 + + 3^20 + 2*3^21 + 2*3^22 + 2*3^23 + 2*3^25 + O(3^27))*q^3 + + O(q^4) + (1 + O(3^20))*q + + (2*3 + 3^3 + 2*3^4 + 3^6 + 2*3^8 + 3^9 + 3^10 + + 2*3^11 + 2*3^13 + 3^16 + 3^18 + 3^19 + 3^20 + O(3^21))*q^2 + + (3^9 + 2*3^12 + 3^15 + 3^17 + 3^18 + 3^19 + 3^20 + + 2*3^22 + 2*3^23 + 2*3^27 + 2*3^28 + O(3^29))*q^3 + + O(q^4) The first eigenfunction is a classical cusp form of level 3: @@ -163,7 +178,12 @@ :: sage: a3 = efuncs[3].q_expansion()[3]; a3 - 3^9 + 2*3^12 + 3^15 + 3^17 + 3^18 + 3^19 + 3^20 + 2*3^22 + 2*3^23 + 2*3^27 + 2*3^28 + 3^32 + 3^33 + 2*3^34 + 3^38 + 2*3^39 + 3^40 + 2*3^41 + 3^44 + 3^45 + 3^46 + 2*3^47 + 2*3^48 + 3^49 + 3^50 + 2*3^51 + 2*3^52 + 3^53 + 2*3^54 + 3^55 + 3^56 + 3^57 + 2*3^58 + 2*3^59 + 3^60 + 2*3^61 + 2*3^63 + 2*3^64 + 3^65 + 2*3^67 + 3^68 + 2*3^69 + 2*3^71 + 3^72 + 2*3^74 + 3^75 + 3^76 + 3^79 + 3^80 + 2*3^83 + 2*3^84 + 3^85 + 2*3^87 + 3^88 + 2*3^89 + 2*3^90 + 2*3^91 + 3^92 + O(3^98) + 3^9 + 2*3^12 + 3^15 + 3^17 + 3^18 + 3^19 + 3^20 + 2*3^22 + 2*3^23 + 2*3^27 + + 2*3^28 + 3^32 + 3^33 + 2*3^34 + 3^38 + 2*3^39 + 3^40 + 2*3^41 + 3^44 + 3^45 + + 3^46 + 2*3^47 + 2*3^48 + 3^49 + 3^50 + 2*3^51 + 2*3^52 + 3^53 + 2*3^54 + 3^55 + + 3^56 + 3^57 + 2*3^58 + 2*3^59 + 3^60 + 2*3^61 + 2*3^63 + 2*3^64 + 3^65 + 2*3^67 + + 3^68 + 2*3^69 + 2*3^71 + 3^72 + 2*3^74 + 3^75 + 3^76 + 3^79 + 3^80 + 2*3^83 + + 2*3^84 + 3^85 + 2*3^87 + 3^88 + 2*3^89 + 2*3^90 + 2*3^91 + 3^92 + O(3^98) sage: efuncs[3].slope() 9 """ @@ -410,9 +430,11 @@ def _set_radius(self, radius): def is_exact(self): r""" - True if elements of this space are represented exactly, i.e., there is - no precision loss when doing arithmetic. As this is never true for - overconvergent modular forms spaces, this returns ``False``. + Return ``True`` if elements of this space are represented exactly. + + This would mean that there is no precision loss when doing arithmetic. + As this is never true for overconvergent modular forms spaces, + this method returns ``False``. EXAMPLES:: @@ -473,9 +495,11 @@ def _an_element_(self): def character(self): r""" - Return the character of ``self``. For overconvergent forms, the weight and - the character are unified into the concept of a weight-character, so - this returns exactly the same thing as ``self.weight()``. + Return the character of ``self``. + + For overconvergent forms, the weight and the character are unified into + the concept of a weight-character, so this returns exactly the same + thing as :meth:`weight`. EXAMPLES:: @@ -490,9 +514,11 @@ def character(self): def weight(self): r""" - Return the character of ``self``. For overconvergent forms, the weight and - the character are unified into the concept of a weight-character, so - this returns exactly the same thing as ``self.character()``. + Return the weight of ``self``. + + For overconvergent forms, the weight and the character are unified into + the concept of a weight-character, so this returns exactly the same + thing as :meth:`character`. EXAMPLES:: @@ -507,6 +533,8 @@ def weight(self): def normalising_factor(self): r""" + Return the normalising factor of ``self``. + The normalising factor `c` such that `g = c f` is a parameter for the `r`-overconvergent disc in `X_0(p)`, where `f` is the standard uniformiser. @@ -550,7 +578,7 @@ def __ne__(self, other): True sage: OverconvergentModularForms(3, 0, 1/2) != OverconvergentModularForms(3, 0, 1/3) True - sage: OverconvergentModularForms(3, 0, 1/2) != OverconvergentModularForms(3, 0, 1/2, base_ring = Qp(3)) + sage: OverconvergentModularForms(3, 0, 1/2) != OverconvergentModularForms(3, 0, 1/2, base_ring=Qp(3)) True sage: OverconvergentModularForms(3, 0, 1/2) != OverconvergentModularForms(3, 0, 1/2) False @@ -594,7 +622,7 @@ def _params(self): def __reduce__(self): r""" - Return the function and arguments used to construct self. Used for pickling. + Return the function and arguments used to construct ``self``. Used for pickling. EXAMPLES:: @@ -634,7 +662,7 @@ def gen(self, i): def _repr_(self): r""" - Return a string representation of self. + Return a string representation of ``self``. EXAMPLES:: @@ -645,8 +673,9 @@ def _repr_(self): def prime(self): r""" - Return the residue characteristic of ``self``, i.e. the prime `p` such that - this is a `p`-adic space. + Return the residue characteristic of ``self``. + + This is the prime `p` such that this is a `p`-adic space. EXAMPLES:: @@ -689,14 +718,15 @@ def gens(self): def prec(self): r""" - Return the series precision of self. Note that this is different from - the `p`-adic precision of the base ring. + Return the series precision of ``self``. + + Note that this is different from the `p`-adic precision of the base ring. EXAMPLES:: sage: OverconvergentModularForms(3, 0, 1/2).prec() 20 - sage: OverconvergentModularForms(3, 0, 1/2,prec=40).prec() + sage: OverconvergentModularForms(3, 0, 1/2, prec=40).prec() 40 """ return self._prec @@ -715,7 +745,7 @@ def _element_constructor_(self, input): - arbitrary power series in `q` - lists of elements of the base ring (interpreted as vectors in the - basis given by self.gens()). + basis given by :meth:`gens`). Precision may be specified by padding lists at the end with zeros; inputs with a higher precision than the set precision of this space @@ -819,7 +849,7 @@ def zero(self): def _coerce_from_ocmf(self, f): r""" - Try to convert the overconvergent modular form `f` into an element of self. + Try to convert the overconvergent modular form `f` into an element of ``self``. An error will be raised if this is obviously nonsense. @@ -841,8 +871,9 @@ def _coerce_from_ocmf(self, f): def _coerce_map_from_(self, other): r""" - Canonical coercion of x into self. Here the possibilities for x are - more restricted. + Canonical coercion of ``x`` into ``self``. + + Here the possibilities for ``x`` are more restricted. TESTS:: @@ -865,6 +896,7 @@ def _coerce_map_from_(self, other): def coordinate_vector(self, x): r""" Write ``x`` as a vector with respect to the basis given by ``self.basis()``. + Here ``x`` must be an element of this space or something that can be converted into one. If ``x`` has precision less than the default precision of ``self``, then the returned vector will be shorter. @@ -922,9 +954,11 @@ def hecke_operator(self, f, m): sage: f = M.1 sage: M.hecke_operator(f, 3) 3-adic overconvergent modular form of weight-character 0 with q-expansion - 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + 52494114852*q^6 + O(q^7) + 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + + 52494114852*q^6 + O(q^7) sage: M.hecke_operator(f.q_expansion(), 3) - 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + 52494114852*q^6 + O(q^7) + 2430*q + 265356*q^2 + 10670373*q^3 + 249948828*q^4 + 4113612864*q^5 + + 52494114852*q^6 + O(q^7) """ # This should just be an instance of hecke_operator_on_qexp but that @@ -969,14 +1003,14 @@ def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): Calculate the matrix of the `T_m` operator in the basis of this space, truncated to an `n \times n` matrix. Conventions are that operators act on the left on column vectors (this is the opposite of the conventions - of the sage.modules.matrix_morphism class!) Uses naive `q`-expansion - arguments if use_recurrence=False and uses the Kolberg style - recurrences if use_recurrence=True. + of the :mod:`sage.modules.matrix_morphism` class!) Uses naive `q`-expansion + arguments if ``use_recurrence=False`` and uses the Kolberg style + recurrences if ``use_recurrence=True``. - The argument "exact_arith" causes the computation to be done with + The argument ``exact_arith`` causes the computation to be done with rational arithmetic, even if the base ring is an inexact `p`-adic ring. This is useful as there can be precision loss issues (particularly with - use_recurrence=False). + ``use_recurrence=False``). EXAMPLES:: @@ -1049,7 +1083,7 @@ def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): def slopes(self, n, use_recurrence=False): r""" - Compute the slopes of the `U_p` operator acting on self, using an `n\times n` matrix. + Compute the slopes of the `U_p` operator acting on ``self``, using an `n\times n` matrix. EXAMPLES:: @@ -1097,7 +1131,34 @@ def eigenfunctions(self, n, F=None, exact_arith=True): sage: X = OverconvergentModularForms(2, 2, 1/6).eigenfunctions(8, Qp(2, 100)) sage: X[1] 2-adic overconvergent modular form of weight-character 2 with q-expansion - (1 + O(2^74))*q + (2^4 + 2^5 + 2^9 + 2^10 + 2^12 + 2^13 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^28 + 2^30 + 2^31 + 2^32 + 2^34 + 2^36 + 2^37 + 2^39 + 2^40 + 2^43 + 2^44 + 2^45 + 2^47 + 2^48 + 2^52 + 2^53 + 2^54 + 2^55 + 2^56 + 2^58 + 2^59 + 2^60 + 2^61 + 2^67 + 2^68 + 2^70 + 2^71 + 2^72 + 2^74 + 2^76 + O(2^78))*q^2 + (2^2 + 2^7 + 2^8 + 2^9 + 2^12 + 2^13 + 2^16 + 2^17 + 2^21 + 2^23 + 2^25 + 2^28 + 2^33 + 2^34 + 2^36 + 2^37 + 2^42 + 2^45 + 2^47 + 2^49 + 2^50 + 2^51 + 2^54 + 2^55 + 2^58 + 2^60 + 2^61 + 2^67 + 2^71 + 2^72 + O(2^76))*q^3 + (2^8 + 2^11 + 2^14 + 2^19 + 2^21 + 2^22 + 2^24 + 2^25 + 2^26 + 2^27 + 2^28 + 2^29 + 2^32 + 2^33 + 2^35 + 2^36 + 2^44 + 2^45 + 2^46 + 2^47 + 2^49 + 2^50 + 2^53 + 2^54 + 2^55 + 2^56 + 2^57 + 2^60 + 2^63 + 2^66 + 2^67 + 2^69 + 2^74 + 2^76 + 2^79 + 2^80 + 2^81 + O(2^82))*q^4 + (2 + 2^2 + 2^9 + 2^13 + 2^15 + 2^17 + 2^19 + 2^21 + 2^23 + 2^26 + 2^27 + 2^28 + 2^30 + 2^33 + 2^34 + 2^35 + 2^36 + 2^37 + 2^38 + 2^39 + 2^41 + 2^42 + 2^43 + 2^45 + 2^58 + 2^59 + 2^60 + 2^61 + 2^62 + 2^63 + 2^65 + 2^66 + 2^68 + 2^69 + 2^71 + 2^72 + O(2^75))*q^5 + (2^6 + 2^7 + 2^15 + 2^16 + 2^21 + 2^24 + 2^25 + 2^28 + 2^29 + 2^33 + 2^34 + 2^37 + 2^44 + 2^45 + 2^48 + 2^50 + 2^51 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^64 + 2^69 + 2^71 + 2^73 + 2^75 + 2^78 + O(2^80))*q^6 + (2^3 + 2^8 + 2^9 + 2^10 + 2^11 + 2^12 + 2^14 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^25 + 2^26 + 2^34 + 2^37 + 2^38 + 2^39 + 2^40 + 2^41 + 2^45 + 2^47 + 2^49 + 2^51 + 2^53 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^61 + 2^66 + 2^69 + 2^70 + 2^71 + 2^74 + 2^76 + O(2^77))*q^7 + O(q^8) + (1 + O(2^74))*q + + (2^4 + 2^5 + 2^9 + 2^10 + 2^12 + 2^13 + 2^15 + 2^17 + 2^19 + 2^20 + + 2^21 + 2^23 + 2^28 + 2^30 + 2^31 + 2^32 + 2^34 + 2^36 + 2^37 + + 2^39 + 2^40 + 2^43 + 2^44 + 2^45 + 2^47 + 2^48 + 2^52 + 2^53 + + 2^54 + 2^55 + 2^56 + 2^58 + 2^59 + 2^60 + 2^61 + 2^67 + 2^68 + + 2^70 + 2^71 + 2^72 + 2^74 + 2^76 + O(2^78))*q^2 + + (2^2 + 2^7 + 2^8 + 2^9 + 2^12 + 2^13 + 2^16 + 2^17 + 2^21 + 2^23 + + 2^25 + 2^28 + 2^33 + 2^34 + 2^36 + 2^37 + 2^42 + 2^45 + 2^47 + + 2^49 + 2^50 + 2^51 + 2^54 + 2^55 + 2^58 + 2^60 + 2^61 + 2^67 + + 2^71 + 2^72 + O(2^76))*q^3 + + (2^8 + 2^11 + 2^14 + 2^19 + 2^21 + 2^22 + 2^24 + 2^25 + 2^26 + + 2^27 + 2^28 + 2^29 + 2^32 + 2^33 + 2^35 + 2^36 + 2^44 + 2^45 + + 2^46 + 2^47 + 2^49 + 2^50 + 2^53 + 2^54 + 2^55 + 2^56 + 2^57 + + 2^60 + 2^63 + 2^66 + 2^67 + 2^69 + 2^74 + 2^76 + 2^79 + 2^80 + + 2^81 + O(2^82))*q^4 + + (2 + 2^2 + 2^9 + 2^13 + 2^15 + 2^17 + 2^19 + 2^21 + 2^23 + 2^26 + + 2^27 + 2^28 + 2^30 + 2^33 + 2^34 + 2^35 + 2^36 + 2^37 + 2^38 + + 2^39 + 2^41 + 2^42 + 2^43 + 2^45 + 2^58 + 2^59 + 2^60 + 2^61 + + 2^62 + 2^63 + 2^65 + 2^66 + 2^68 + 2^69 + 2^71 + 2^72 + O(2^75))*q^5 + + (2^6 + 2^7 + 2^15 + 2^16 + 2^21 + 2^24 + 2^25 + 2^28 + 2^29 + 2^33 + + 2^34 + 2^37 + 2^44 + 2^45 + 2^48 + 2^50 + 2^51 + 2^54 + 2^55 + + 2^57 + 2^58 + 2^59 + 2^60 + 2^64 + 2^69 + 2^71 + 2^73 + 2^75 + + 2^78 + O(2^80))*q^6 + (2^3 + 2^8 + 2^9 + 2^10 + 2^11 + 2^12 + + 2^14 + 2^15 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^25 + 2^26 + + 2^34 + 2^37 + 2^38 + 2^39 + 2^40 + 2^41 + 2^45 + 2^47 + 2^49 + + 2^51 + 2^53 + 2^54 + 2^55 + 2^57 + 2^58 + 2^59 + 2^60 + 2^61 + + 2^66 + 2^69 + 2^70 + 2^71 + 2^74 + 2^76 + O(2^77))*q^7 + + O(q^8) sage: [x.slope() for x in X] [0, 4, 8, 14, 16, 18, 26, 30] """ @@ -1278,9 +1339,24 @@ def cps_u(self, n, use_recurrence=False): EXAMPLES:: sage: OverconvergentModularForms(3, 16, 1/2, base_ring=Qp(3)).cps_u(4) - 1 + O(3^20) + (2 + 2*3 + 2*3^2 + 2*3^4 + 3^5 + 3^6 + 3^7 + 3^11 + 3^12 + 2*3^14 + 3^16 + 3^18 + O(3^19))*T + (2*3^3 + 3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 3^11 + 3^12 + 2*3^13 + 2*3^16 + 2*3^18 + O(3^19))*T^2 + (2*3^15 + 2*3^16 + 2*3^19 + 2*3^20 + 2*3^21 + O(3^22))*T^3 + (3^17 + 2*3^18 + 3^19 + 3^20 + 3^22 + 2*3^23 + 2*3^25 + 3^26 + O(3^27))*T^4 + 1 + O(3^20) + + (2 + 2*3 + 2*3^2 + 2*3^4 + 3^5 + 3^6 + 3^7 + + 3^11 + 3^12 + 2*3^14 + 3^16 + 3^18 + O(3^19))*T + + (2*3^3 + 3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + + 3^11 + 3^12 + 2*3^13 + 2*3^16 + 2*3^18 + O(3^19))*T^2 + + (2*3^15 + 2*3^16 + 2*3^19 + 2*3^20 + 2*3^21 + O(3^22))*T^3 + + (3^17 + 2*3^18 + 3^19 + 3^20 + 3^22 + 2*3^23 + 2*3^25 + 3^26 + O(3^27))*T^4 sage: OverconvergentModularForms(3, 16, 1/2, base_ring=Qp(3), prec=30).cps_u(10) - 1 + O(3^20) + (2 + 2*3 + 2*3^2 + 2*3^4 + 3^5 + 3^6 + 3^7 + 2*3^15 + O(3^16))*T + (2*3^3 + 3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 3^14 + 3^15 + O(3^16))*T^2 + (3^14 + 2*3^15 + 2*3^16 + 3^17 + 3^18 + O(3^19))*T^3 + (3^17 + 2*3^18 + 3^19 + 3^20 + 3^21 + O(3^24))*T^4 + (3^29 + 2*3^32 + O(3^33))*T^5 + (2*3^44 + O(3^45))*T^6 + (2*3^59 + O(3^60))*T^7 + (2*3^78 + O(3^79))*T^8 + 1 + O(3^20) + + (2 + 2*3 + 2*3^2 + 2*3^4 + 3^5 + 3^6 + 3^7 + 2*3^15 + O(3^16))*T + + (2*3^3 + 3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + + 2*3^11 + 2*3^12 + 2*3^13 + 3^14 + 3^15 + O(3^16))*T^2 + + (3^14 + 2*3^15 + 2*3^16 + 3^17 + 3^18 + O(3^19))*T^3 + + (3^17 + 2*3^18 + 3^19 + 3^20 + 3^21 + O(3^24))*T^4 + + (3^29 + 2*3^32 + O(3^33))*T^5 + + (2*3^44 + O(3^45))*T^6 + + (2*3^59 + O(3^60))*T^7 + + (2*3^78 + O(3^79))*T^8 .. NOTE:: @@ -1325,7 +1401,8 @@ def __init__(self, parent, gexp=None, qexp=None): EXAMPLES:: sage: OverconvergentModularForms(3, 2, 1/6,prec=5).an_element() # indirect doctest - 3-adic overconvergent modular form of weight-character 2 with q-expansion 3*q + 72*q^2 + 810*q^3 + 6096*q^4 + O(q^5) + 3-adic overconvergent modular form of weight-character 2 + with q-expansion 3*q + 72*q^2 + 810*q^3 + 6096*q^4 + O(q^5) """ ModuleElement.__init__(self, parent) @@ -1390,22 +1467,23 @@ def _rmul_(self, x): def prec(self): r""" - Return the series expansion precision of this overconvergent modular - form. (This is not the same as the `p`-adic precision of the - coefficients.) + Return the series expansion precision of this overconvergent modular form. + + This is not the same as the `p`-adic precision of the coefficients. EXAMPLES:: - sage: OverconvergentModularForms(5, 6, 1/3,prec=15).gen(1).prec() + sage: OverconvergentModularForms(5, 6, 1/3, prec=15).gen(1).prec() 15 """ return self.gexp().prec() def is_eigenform(self): r""" - Return True if this is an eigenform. At present this returns False - unless this element was explicitly flagged as an eigenform, using the - _notify_eigen function. + Return ``True`` if this is an eigenform. + + At present this returns ``False`` unless this element was explicitly + flagged as an eigenform, using the method :meth:`_notify_eigen`. EXAMPLES:: @@ -1420,9 +1498,12 @@ def is_eigenform(self): def slope(self): r""" - Return the slope of this eigenform, i.e. the valuation of its - `U_p`-eigenvalue. Raises an error unless this element was explicitly - flagged as an eigenform, using the _notify_eigen function. + Return the slope of this eigenform. + + This is the valuation of its `U_p`-eigenvalue. + + Raises an error unless this element was explicitly + flagged as an eigenform, using the method :meth:`_notify_eigen`. EXAMPLES:: @@ -1443,16 +1524,22 @@ def eigenvalue(self): r""" Return the `U_p`-eigenvalue of this eigenform. - This raises an error unless - this element was explicitly flagged as an eigenform, using the - _notify_eigen function. + This raises an error unless this element was explicitly flagged + as an eigenform, using the method :meth:`_notify_eigen`. EXAMPLES:: sage: M = OverconvergentModularForms(3, 0, 1/2) sage: f = M.eigenfunctions(3)[1] sage: f.eigenvalue() - 3^2 + 3^4 + 2*3^6 + 3^7 + 3^8 + 2*3^9 + 2*3^10 + 3^12 + 3^16 + 2*3^17 + 3^18 + 3^20 + 2*3^21 + 3^22 + 2*3^23 + 3^25 + 3^26 + 2*3^27 + 2*3^29 + 3^30 + 3^31 + 3^32 + 3^33 + 3^34 + 3^36 + 3^40 + 2*3^41 + 3^43 + 3^44 + 3^45 + 3^46 + 3^48 + 3^49 + 3^50 + 2*3^51 + 3^52 + 3^54 + 2*3^57 + 2*3^59 + 3^60 + 3^61 + 2*3^63 + 2*3^66 + 2*3^67 + 3^69 + 2*3^72 + 3^74 + 2*3^75 + 3^76 + 2*3^77 + 2*3^78 + 2*3^80 + 3^81 + 2*3^82 + 3^84 + 2*3^85 + 2*3^86 + 3^87 + 3^88 + 2*3^89 + 2*3^91 + 3^93 + 3^94 + 3^95 + 3^96 + 3^98 + 2*3^99 + O(3^100) + 3^2 + 3^4 + 2*3^6 + 3^7 + 3^8 + 2*3^9 + 2*3^10 + 3^12 + 3^16 + 2*3^17 + + 3^18 + 3^20 + 2*3^21 + 3^22 + 2*3^23 + 3^25 + 3^26 + 2*3^27 + 2*3^29 + + 3^30 + 3^31 + 3^32 + 3^33 + 3^34 + 3^36 + 3^40 + 2*3^41 + 3^43 + 3^44 + + 3^45 + 3^46 + 3^48 + 3^49 + 3^50 + 2*3^51 + 3^52 + 3^54 + 2*3^57 + + 2*3^59 + 3^60 + 3^61 + 2*3^63 + 2*3^66 + 2*3^67 + 3^69 + 2*3^72 + + 3^74 + 2*3^75 + 3^76 + 2*3^77 + 2*3^78 + 2*3^80 + 3^81 + 2*3^82 + + 3^84 + 2*3^85 + 2*3^86 + 3^87 + 3^88 + 2*3^89 + 2*3^91 + 3^93 + 3^94 + + 3^95 + 3^96 + 3^98 + 2*3^99 + O(3^100) sage: M.gen(4).eigenvalue() Traceback (most recent call last): ... @@ -1484,17 +1571,27 @@ def q_expansion(self, prec=None): def gexp(self): r""" - Return the formal power series in `g` corresponding to this - overconvergent modular form (so the result is `F` where this modular form - is `E_k^\ast \times F(g)`, where `g` is the appropriately normalised - parameter of `X_0(p)`). + Return the formal power series in `g` corresponding to ``self``. + + If this overconvergent modular form is `E_k^\ast \times F(g)` + where `g` is the appropriately normalised parameter of `X_0(p)`, + the result is `F`. EXAMPLES:: sage: M = OverconvergentModularForms(3, 0, 1/2) sage: f = M.eigenfunctions(3)[1] sage: f.gexp() - (3^-3 + O(3^95))*g + (3^-1 + 1 + 2*3 + 3^2 + 2*3^3 + 3^5 + 3^7 + 3^10 + 3^11 + 3^14 + 3^15 + 3^16 + 2*3^19 + 3^21 + 3^22 + 2*3^23 + 2*3^24 + 3^26 + 2*3^27 + 3^29 + 3^31 + 3^34 + 2*3^35 + 2*3^36 + 3^38 + 2*3^39 + 3^41 + 2*3^42 + 2*3^43 + 2*3^44 + 2*3^46 + 2*3^47 + 3^48 + 2*3^49 + 2*3^50 + 3^51 + 2*3^54 + 2*3^55 + 2*3^56 + 3^57 + 2*3^58 + 2*3^59 + 2*3^60 + 3^61 + 3^62 + 3^63 + 3^64 + 2*3^65 + 3^67 + 3^68 + 2*3^69 + 3^70 + 2*3^71 + 2*3^74 + 3^76 + 2*3^77 + 3^78 + 2*3^79 + 2*3^80 + 3^84 + 2*3^85 + 2*3^86 + 3^88 + 2*3^89 + 3^91 + 3^92 + 2*3^94 + 3^95 + O(3^97))*g^2 + O(g^3) + (3^-3 + O(3^95))*g + + (3^-1 + 1 + 2*3 + 3^2 + 2*3^3 + 3^5 + 3^7 + 3^10 + 3^11 + 3^14 + 3^15 + + 3^16 + 2*3^19 + 3^21 + 3^22 + 2*3^23 + 2*3^24 + 3^26 + 2*3^27 + + 3^29 + 3^31 + 3^34 + 2*3^35 + 2*3^36 + 3^38 + 2*3^39 + 3^41 + 2*3^42 + + 2*3^43 + 2*3^44 + 2*3^46 + 2*3^47 + 3^48 + 2*3^49 + 2*3^50 + 3^51 + + 2*3^54 + 2*3^55 + 2*3^56 + 3^57 + 2*3^58 + 2*3^59 + 2*3^60 + 3^61 + + 3^62 + 3^63 + 3^64 + 2*3^65 + 3^67 + 3^68 + 2*3^69 + 3^70 + 2*3^71 + + 2*3^74 + 3^76 + 2*3^77 + 3^78 + 2*3^79 + 2*3^80 + 3^84 + 2*3^85 + + 2*3^86 + 3^88 + 2*3^89 + 3^91 + 3^92 + 2*3^94 + 3^95 + O(3^97))*g^2 + + O(g^3) """ return self._gexp @@ -1535,11 +1632,13 @@ def prime(self): def _notify_eigen(self, eigenvalue): """ - Flags this element as an eigenform. It then remembers some extra data. + Flag this element as an eigenform. + + It then remembers some extra data. EXAMPLES:: - sage: OverconvergentModularForms(3, 16, 1/3).eigenfunctions(4) # indirect doctest + sage: OverconvergentModularForms(3, 16, 1/3).eigenfunctions(4) # indirect doctest [...] """ self._is_eigen = True @@ -1548,9 +1647,10 @@ def _notify_eigen(self, eigenvalue): def is_integral(self): r""" - Test whether or not this element has `q`-expansion coefficients that - are `p`-adically integral. This should always be the case with eigenfunctions, but sometimes - if n is very large this breaks down for unknown reasons! + Test whether this element has `q`-expansion coefficients that are `p`-adically integral. + + This should always be the case with eigenfunctions, but sometimes + if `n` is very large this breaks down for unknown reasons! EXAMPLES:: @@ -1580,7 +1680,7 @@ def _repr_(self) -> str: def _richcmp_(self, other, op): r""" - Compare self to other. + Compare ``self`` to ``other``. EXAMPLES:: @@ -1594,7 +1694,7 @@ def _richcmp_(self, other, op): def r_ord(self, r): r""" - The `p`-adic valuation of the norm of self on the `r`-overconvergent region. + The `p`-adic valuation of the norm of ``self`` on the `r`-overconvergent region. EXAMPLES:: @@ -1620,8 +1720,9 @@ def r_ord(self, r): def valuation(self): r""" - Return the `p`-adic valuation of this form (i.e. the minimum of the - `p`-adic valuations of its coordinates). + Return the `p`-adic valuation of this form. + + This is the minimum of the `p`-adic valuations of its coordinates. EXAMPLES:: @@ -1695,8 +1796,10 @@ def weight(self): def additive_order(self): r""" - Return the additive order of this element (required attribute for all - elements deriving from :class:`sage.modules.ModuleElement`). + Return the additive order of this element. + + This implements a required method for all + elements deriving from :class:`sage.modules.ModuleElement`. EXAMPLES:: @@ -1733,8 +1836,9 @@ def base_extend(self, R): def __pari__(self): r""" - Return the Pari object corresponding to ``self``, which is just the - `q`-expansion of ``self`` as a formal power series. + Return the Pari object corresponding to ``self``. + + This is just the `q`-expansion of ``self`` as a formal power series. EXAMPLES:: From 737807e9ecf826e52574d0bd377b1cffafeac54c Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Sat, 6 Apr 2024 18:29:46 +0200 Subject: [PATCH 096/191] Implemented reviewer feedback --- .../algebras/quatalg/quaternion_algebra.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index f3f315e1f80..1e230f1a5e4 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -687,7 +687,7 @@ def __init__(self, base_ring, a, b, names='i,j,k'): self._gens = (self([0, 1, 0, 0]), self([0, 0, 1, 0]), self([0, 0, 0, 1])) @cached_method - def maximal_order(self, order_basis=None, take_shortcuts=True): + def maximal_order(self, take_shortcuts=True, order_basis=None): r""" Return a maximal order in this quaternion algebra. @@ -795,12 +795,11 @@ def maximal_order(self, order_basis=None, take_shortcuts=True): ....: (-511, 608), (493, 880), (105, -709), (-213, 530), ....: (97, 745)] sage: all(QuaternionAlgebra(a, b).maximal_order().is_maximal() - ....: for (a, b) in invars) + ....: for (a, b) in invars) True """ if self.base_ring() != QQ: - raise NotImplementedError("maximal order only implemented for" - " rational quaternion algebras") + raise NotImplementedError("maximal order only implemented for rational quaternion algebras") d_A = self.discriminant() @@ -1648,7 +1647,7 @@ def gen(self, n): def __eq__(self, other): """ - Compare orders self and other. + Compare orders ``self`` and ``other``. EXAMPLES:: @@ -1674,7 +1673,7 @@ def __eq__(self, other): def __ne__(self, other): """ - Compare orders self and other. + Compare orders ``self`` and ``other``. Two orders are equal if they have the same basis and are in the same quaternion algebra. @@ -1691,7 +1690,7 @@ def __ne__(self, other): def __le__(self, other): """ - Compare orders self and other. + Compare orders ``self`` and ``other``. EXAMPLES:: @@ -1709,7 +1708,7 @@ def __le__(self, other): def __lt__(self, other): """ - Compare orders self and other. + Compare orders ``self`` and ``other``. EXAMPLES:: @@ -1725,7 +1724,7 @@ def __lt__(self, other): def __ge__(self, other): """ - Compare orders self and other. + Compare orders ``self`` and ``other``. EXAMPLES:: @@ -1743,7 +1742,7 @@ def __ge__(self, other): def __gt__(self, other): """ - Compare orders self and other. + Compare orders ``self`` and ``other``. EXAMPLES:: @@ -3711,7 +3710,9 @@ def normalize_basis_at_p(e, p, B=QuaternionAlgebraElement_abstract.pair): # Ensures that (B(f0,f0)/2).valuation(p) <= B(f0,f1).valuation(p) if B(f0, f1).valuation(p) + 1 < B(f0, f0).valuation(p): - f0, f1 = f0 + f1, f0 + g = f0 + f0 += f1 + f1 = g # Make remaining vectors orthogonal to span of f0, f1 e[min_m] = e[0] From 8bd73349f0b08ef43d47d8e9d2123864fc821a90 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Apr 2024 11:06:33 -0700 Subject: [PATCH 097/191] src/sage/matrix/matrix_space.py: Add TestSuite(...).run() # known bug --- src/sage/matrix/matrix_space.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index cef1c416385..ec3ede933bc 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -610,22 +610,25 @@ class MatrixSpace(UniqueRepresentation, Parent): Check various combinations of dimensions and row/column keys:: - sage: MatrixSpace(QQ, ['a','b'], 4) + sage: M_ab_4 = MatrixSpace(QQ, ['a','b'], 4); M_ab_4 Set of Morphisms (Linear Transformations) from Vector space of dimension 4 over Rational Field to Free module generated by {'a', 'b'} over Rational Field - sage: MatrixSpace(QQ, 4, ['a','b']) + sage: TestSuite(M_ab_4).run() # known bug + sage: M_4_ab = MatrixSpace(QQ, 4, ['a','b']); M_4_ab Set of Morphisms from Free module generated by {'a', 'b'} over Rational Field to Vector space of dimension 4 over Rational Field in Category of finite dimensional vector spaces with basis over (number fields and quotient fields and metric spaces) - sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2) + sage: TestSuite(M_4_ab).run() # known bug + sage: M_ab_xy = MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2); M_ab_xy Set of Morphisms from Free module generated by {'x', 'y'} over Rational Field to Vector space of dimension 2 over Rational Field in Category of finite dimensional vector spaces with basis over (number fields and quotient fields and metric spaces) + sage: TestSuite(M_ab_xy).run() # known bug sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=4) Traceback (most recent call last): ... From eef4b409963bb1e561841f9405415e2cd505db2d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Apr 2024 11:30:52 -0700 Subject: [PATCH 098/191] src/sage/modular/overconvergent/genus0.py: Fix latex for dagger --- src/sage/modular/overconvergent/genus0.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 50da43a3e08..b7626ce2683 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -39,7 +39,7 @@ (This is Theorem 1 of [Loe2007]_.) Hence if we fix an element `c` with `|c| = p^{-\frac{12r}{p-1}}`, the space -`S_k^\dag(1, r)` of overconvergent `p`-adic modular forms has an orthonormal +`S_k^\dagger(1, r)` of overconvergent `p`-adic modular forms has an orthonormal basis given by the functions `(cf)^n`. So any element can be written in the form `E_k \times \sum_{n \ge 0} a_n (cf)^n`, where `a_n \to 0` as `N \to \infty`, and any such sequence `a_n` defines a unique overconvergent form. From 007ed6633a079e31e656b8a0e6e2edc7f9e4071a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Apr 2024 11:31:34 -0700 Subject: [PATCH 099/191] OverconvergentModularFormsSpace.hecke_matrix: Add keyword 'side', rewrite docstring --- src/sage/modular/overconvergent/genus0.py | 50 ++++++++++++++++------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index b7626ce2683..5c23a3aaa49 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -998,19 +998,30 @@ def _convert_to_basis(self, qexp): x = x - self._basis_cache[i] * answer[i] return answer + O(g**n) - def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): + def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False, side='left'): r""" - Calculate the matrix of the `T_m` operator in the basis of this space, - truncated to an `n \times n` matrix. Conventions are that operators act - on the left on column vectors (this is the opposite of the conventions - of the :mod:`sage.modules.matrix_morphism` class!) Uses naive `q`-expansion - arguments if ``use_recurrence=False`` and uses the Kolberg style - recurrences if ``use_recurrence=True``. - - The argument ``exact_arith`` causes the computation to be done with - rational arithmetic, even if the base ring is an inexact `p`-adic ring. - This is useful as there can be precision loss issues (particularly with - ``use_recurrence=False``). + Calculate the matrix of the `T_m` operator, truncated to `n \times n`. + + INPUT: + + - ``m`` -- integer; determines the operator `T_m` + + - ``n`` -- integer; truncate the matrix in the basis of this space + to an `n \times n` matrix + + - ``use_recurrence`` -- boolean (default: ``False``); whether to use + Kolberg style recurrences. If ``False``, use naive `q`-expansion + arguments. + + - ``exact_arith`` -- boolean (default: ``True``); whether to do the + computation to be done with rational arithmetic, even if the base ring + is an inexact `p`-adic ring. + + This is useful as there can be precision loss issues (particularly + with ``use_recurrence=False``). + + - ``side`` -- ``'left'`` (default) or ``'right'``; if ``'left'``, the + operator acts on the left on column vectors EXAMPLES:: @@ -1029,10 +1040,17 @@ def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): [ 1 0 0] [ 0 33881928/1414477 64] [ 0 -192898739923312/2000745183529 1626332544/1414477] - """ + Side switch:: + + sage: OverconvergentModularForms(2, 0, 1/2).hecke_matrix(2, 4, side='right') + [ 1 0 0 0] + [ 0 24 32 0] + [ 0 64 1152 3072] + [ 0 0 4608 61440] + """ if exact_arith and not self.base_ring().is_exact(): - return self.change_ring(QQ).hecke_matrix(m, n, use_recurrence) + return self.change_ring(QQ).hecke_matrix(m, n, use_recurrence, side=side) M = MatrixSpace(self.base_ring(), n) mat = M(0) @@ -1079,6 +1097,10 @@ def hecke_matrix(self, m, n, use_recurrence=False, exact_arith=False): l = self._convert_to_basis(self.hecke_operator(self._basis_cache[j], m)) for i in range(n): mat[i, j] = l[i] + + if side == 'right': + return mat.transpose() + return mat def slopes(self, n, use_recurrence=False): From 3ee561a0ef03a6dd428ae9e81b89aad8e2c2a1a9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Apr 2024 11:35:33 -0700 Subject: [PATCH 100/191] OverconvergentModularFormsSpace.recurrence_matrix: Docstring cosmetics --- src/sage/modular/overconvergent/genus0.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 5c23a3aaa49..d6359e53007 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -1262,10 +1262,13 @@ def eigenfunctions(self, n, F=None, exact_arith=True): def recurrence_matrix(self, use_smithline=True): r""" - Return the recurrence matrix satisfied by the coefficients of `U`, - that is a matrix `R =(r_{rs})_{r,s=1 \dots p}` such that `u_{ij} = - \sum_{r,s=1}^p r_{rs} u_{i-r, j-s}`. Uses an elegant construction which - I believe is due to Smithline. See [Loe2007]_. + Return the recurrence matrix satisfied by the coefficients of `U`. + + This is a matrix `R =(r_{rs})_{r,s=1,\dots,p}` such that `u_{ij} = + \sum_{r,s=1}^p r_{rs} u_{i-r, j-s}`. + + Uses an elegant construction which the author believes to be due + to Smithline. See [Loe2007]_. EXAMPLES:: From c29ee5c2c027025adb68ccc432b4acf0ed0b4f55 Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Sat, 6 Apr 2024 20:47:19 +0200 Subject: [PATCH 101/191] Fixed doctest error Caused by switched order of input arguments Amend: This time for real --- src/sage/algebras/quatalg/quaternion_algebra.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 1e230f1a5e4..1f7d3e3ac19 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -770,8 +770,8 @@ def maximal_order(self, take_shortcuts=True, order_basis=None): ....: alpha = A.random_element() sage: conj = [alpha * b * alpha.inverse() for b in [k,i,j]] sage: order_basis = tuple(conj) + (A.one(),) - sage: O = A.quaternion_order(order_basis) - sage: R = A.maximal_order(order_basis) + sage: O = A.quaternion_order(basis=order_basis) + sage: R = A.maximal_order(order_basis=order_basis) sage: O <= R and R.is_maximal() True From bc20ab28bc425374e751d78e4baba3e3ec3da7e6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 7 Apr 2024 20:08:40 -0700 Subject: [PATCH 102/191] FreeModule: Fix handling of overspecified rank and basis_keys --- src/sage/modules/free_module.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 6e2c9e4dc1d..0cb8a0be8fd 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -514,12 +514,32 @@ def FreeModule(base_ring, rank_or_basis_keys=None, sparse=False, inner_product_m Traceback (most recent call last): ... NotImplementedError: FiniteRankFreeModule only supports integer ranges as basis_keys, got [1, 3, 5] + + sage: FreeModule(QQ, ['a', 'b'], rank=2) + Free module generated by {'a', 'b'} over Rational Field + sage: FreeModule(QQ, 2, basis_keys=['a', 'b']) + Free module generated by {'a', 'b'} over Rational Field + sage: FreeModule(QQ, ['a', 'b'], rank=3) + Traceback (most recent call last): + ... + ValueError: inconsistent rank: should be cardinality of ['a', 'b'] but got 3 """ if rank_or_basis_keys is not None: try: - rank = sage.rings.integer_ring.ZZ(rank_or_basis_keys) + n = sage.rings.integer_ring.ZZ(rank_or_basis_keys) except (TypeError, ValueError): + if basis_keys is not None: + raise ValueError("duplicate values for basis_keys") basis_keys = rank_or_basis_keys + else: + if rank is not None: + raise ValueError("duplicate values for rank") + rank = n + + if rank is not None and basis_keys is not None and rank != len(basis_keys): + raise ValueError(f"inconsistent rank: should be cardinality of {basis_keys} " + f"but got {rank}") + if not with_basis: if inner_product_matrix is not None: raise NotImplementedError @@ -539,7 +559,7 @@ def FreeModule(base_ring, rank_or_basis_keys=None, sparse=False, inner_product_m return FiniteRankFreeModule(base_ring, rank, start_index=start_index, **args) return FiniteRankFreeModule(base_ring, rank, **args) elif with_basis == 'standard': - if rank is not None: + if basis_keys is None: return FreeModuleFactory_with_standard_basis(base_ring, rank, sparse, inner_product_matrix, **args) else: From 36a56d30756450110acd22ff5ea171791b70e3b4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 7 Apr 2024 20:12:59 -0700 Subject: [PATCH 103/191] MatrixSpace: Update doctests for overspecified rows/cols --- src/sage/matrix/matrix_space.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index ec3ede933bc..f7efb5432c8 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -625,9 +625,8 @@ class MatrixSpace(UniqueRepresentation, Parent): sage: M_ab_xy = MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2); M_ab_xy Set of Morphisms from Free module generated by {'x', 'y'} over Rational Field - to Vector space of dimension 2 over Rational Field - in Category of finite dimensional vector spaces with basis - over (number fields and quotient fields and metric spaces) + to Free module generated by {'a', 'b'} over Rational Field + in Category of finite dimensional vector spaces with basis over Rational Field sage: TestSuite(M_ab_xy).run() # known bug sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=4) Traceback (most recent call last): @@ -635,18 +634,20 @@ class MatrixSpace(UniqueRepresentation, Parent): ValueError: inconsistent number of rows: should be cardinality of ['a', 'b'] but got 4 sage: MatrixSpace(QQ, ['a','b'], ['x','y'], ncols=2) - Set of Morphisms (Linear Transformations) - from Vector space of dimension 2 over Rational Field + Set of Morphisms + from Free module generated by {'x', 'y'} over Rational Field to Free module generated by {'a', 'b'} over Rational Field + in Category of finite dimensional vector spaces with basis over Rational Field sage: MatrixSpace(QQ, ['a','b'], ['x','y'], ncols=4) Traceback (most recent call last): ... ValueError: inconsistent number of columns: should be cardinality of ['x', 'y'] but got 4 sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2, ncols=2) - Set of Morphisms (Linear Transformations) - from Vector space of dimension 2 over Rational Field - to Vector space of dimension 2 over Rational Field + Set of Morphisms + from Free module generated by {'x', 'y'} over Rational Field + to Free module generated by {'a', 'b'} over Rational Field + in Category of finite dimensional vector spaces with basis over Rational Field sage: MatrixSpace(QQ, ['a','b'], ['x','y'], nrows=2, ncols=4) Traceback (most recent call last): ... From 8c850c547da9268e15af6efe5d43c3b0201b9322 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 9 Feb 2024 16:53:36 +0100 Subject: [PATCH 104/191] make map_coefficients more general, in line with polynomials --- src/sage/categories/modules_with_basis.py | 49 +++++++++++++++++++---- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index e1fa796ba3b..006db5d34ab 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -28,6 +28,7 @@ from sage.categories.fields import Fields from sage.categories.modules import Modules from sage.categories.poor_man_map import PoorManMap +from sage.categories.map import Map from sage.structure.element import Element, parent @@ -2062,17 +2063,25 @@ def trailing_term(self, *args, **kwds): """ return self.parent().term(*self.trailing_item(*args, **kwds)) - def map_coefficients(self, f): + def map_coefficients(self, f, new_base_ring=None): """ - Mapping a function on coefficients. + Return the element obtained by applying ``f`` to the non-zero + coefficients of ``self``. + + If ``f`` is a :class:`sage.categories.map.Map`, then the resulting + polynomial will be defined over the codomain of ``f``. Otherwise, the + resulting polynomial will be over the same ring as ``self``. Set + ``new_base_ring`` to override this behaviour. + + An error is raised if the coefficients are not in the new base ring. INPUT: - - ``f`` -- an endofunction on the coefficient ring of the - free module + - ``f`` -- a callable that will be applied to the + coefficients of ``self``. - Return a new element of ``self.parent()`` obtained by applying the - function ``f`` to all of the coefficients of ``self``. + - ``new_base_ring`` (optional) -- if given, the resulting element + will be defined over this ring. EXAMPLES:: @@ -2096,8 +2105,32 @@ def map_coefficients(self, f): sage: a = s([2,1]) + 2*s([3,2]) # needs sage.combinat sage.modules sage: a.map_coefficients(lambda x: x * 2) # needs sage.combinat sage.modules 2*s[2, 1] + 4*s[3, 2] - """ - return self.parent().sum_of_terms( (m, f(c)) for m,c in self ) + + We can map into a different base ring:: + + sage: # needs sage.combinat + sage: e = SymmetricFunctions(QQ).elementary() + sage: a = 1/2*(e([2,1]) + e([1,1,1])); a + 1/2*e[1, 1, 1] + 1/2*e[2, 1] + sage: b = a.map_coefficients(lambda c: 2*c, ZZ); b + e[1, 1, 1] + e[2, 1] + sage: b.parent() + Symmetric Functions over Integer Ring in the elementary basis + sage: b.map_coefficients(lambda c: 1/2*c, ZZ) + Traceback (most recent call last): + ... + TypeError: no conversion of this rational to integer + """ + R = self.parent() + if new_base_ring is not None: + B = new_base_ring + R = R.change_ring(B) + elif isinstance(f, Map): + B = f.codomain() + R = R.change_ring(B) + else: + B = self.base_ring() + return R.sum_of_terms((m, B(f(c))) for m, c in self) def map_support(self, f): """ From 717b3a00fb576accffec4952f1f60519d0ca9ad8 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Mon, 8 Apr 2024 17:31:27 +0200 Subject: [PATCH 105/191] remove full stop Co-authored-by: Travis Scrimshaw --- src/sage/categories/modules_with_basis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 006db5d34ab..50d82b5a453 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -2078,7 +2078,7 @@ def map_coefficients(self, f, new_base_ring=None): INPUT: - ``f`` -- a callable that will be applied to the - coefficients of ``self``. + coefficients of ``self`` - ``new_base_ring`` (optional) -- if given, the resulting element will be defined over this ring. From 6e93f6c5307d2c791c7e9b6ef8b3eb9a39964596 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Mon, 8 Apr 2024 17:31:40 +0200 Subject: [PATCH 106/191] fix formatting Co-authored-by: Travis Scrimshaw --- src/sage/categories/modules_with_basis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 50d82b5a453..1d7bee8c63a 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -2080,8 +2080,8 @@ def map_coefficients(self, f, new_base_ring=None): - ``f`` -- a callable that will be applied to the coefficients of ``self`` - - ``new_base_ring`` (optional) -- if given, the resulting element - will be defined over this ring. + - ``new_base_ring`` -- (optional) if given, the resulting element + will be defined over this ring EXAMPLES:: From 084314a8087ca217bbe61d06d450a4905aaf837c Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Mon, 8 Apr 2024 17:33:04 +0200 Subject: [PATCH 107/191] do not assume that __iter__ returns monomial coefficients Co-authored-by: Travis Scrimshaw --- src/sage/categories/modules_with_basis.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 1d7bee8c63a..1490ca3354c 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -2130,7 +2130,8 @@ def map_coefficients(self, f, new_base_ring=None): R = R.change_ring(B) else: B = self.base_ring() - return R.sum_of_terms((m, B(f(c))) for m, c in self) + mc = self.monomial_coefficients(copy=False) + return R.sum_of_terms((m, B(f(c))) for m, c in mc.items()) def map_support(self, f): """ From 2ade4c015dbd443efb3da6e0d2417acd1a6307ff Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Mon, 8 Apr 2024 17:33:59 +0200 Subject: [PATCH 108/191] more consistency with multivariate polynomials Co-authored-by: Travis Scrimshaw --- src/sage/categories/modules_with_basis.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 1490ca3354c..ef6e43c5b19 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -2122,14 +2122,14 @@ def map_coefficients(self, f, new_base_ring=None): TypeError: no conversion of this rational to integer """ R = self.parent() - if new_base_ring is not None: - B = new_base_ring - R = R.change_ring(B) - elif isinstance(f, Map): + if isinstance(f, Map): B = f.codomain() - R = R.change_ring(B) else: B = self.base_ring() + if new_base_ring is not None: + B = new_base_ring + if B is not self.base_ring(): + R = R.change_ring(B) mc = self.monomial_coefficients(copy=False) return R.sum_of_terms((m, B(f(c))) for m, c in mc.items()) From b64e8b4f8a79837630dfb4455fbba4d3569cc068 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Tue, 9 Apr 2024 09:00:30 +0200 Subject: [PATCH 109/191] improve doc, remove dependency of doctest on symmetric functions --- src/sage/categories/modules_with_basis.py | 24 ++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index ef6e43c5b19..dcbd547fe53 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -2073,7 +2073,8 @@ def map_coefficients(self, f, new_base_ring=None): resulting polynomial will be over the same ring as ``self``. Set ``new_base_ring`` to override this behaviour. - An error is raised if the coefficients are not in the new base ring. + An error is raised if the coefficients cannot be + converted to the new base ring. INPUT: @@ -2108,18 +2109,27 @@ def map_coefficients(self, f, new_base_ring=None): We can map into a different base ring:: - sage: # needs sage.combinat - sage: e = SymmetricFunctions(QQ).elementary() - sage: a = 1/2*(e([2,1]) + e([1,1,1])); a - 1/2*e[1, 1, 1] + 1/2*e[2, 1] + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: a = 1/2*(B['a'] + 3*B['c']); a + 1/2*B['a'] + 3/2*B['c'] sage: b = a.map_coefficients(lambda c: 2*c, ZZ); b - e[1, 1, 1] + e[2, 1] + B['a'] + 3*B['c'] sage: b.parent() - Symmetric Functions over Integer Ring in the elementary basis + Free module generated by {'a', 'b', 'c'} over Integer Ring sage: b.map_coefficients(lambda c: 1/2*c, ZZ) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer + + Coefficients are converted to the new base ring after + applying the map:: + + sage: B['a'].map_coefficients(lambda c: 2*c, GF(2)) + 0 + sage: B['a'].map_coefficients(lambda c: GF(2)(c), QQ) + B['a'] + """ R = self.parent() if isinstance(f, Map): From f2b74276e19317a9f418f82d18b542a1780b8a5b Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Tue, 9 Apr 2024 09:04:41 +0200 Subject: [PATCH 110/191] pycodestyle fixes --- src/sage/categories/modules_with_basis.py | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index dcbd547fe53..7de5d7dcd91 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -174,7 +174,7 @@ def _call_(self, x): if M.base_ring() != self.base_ring(): M = M.change_ring(self.base_ring()) except (TypeError, AttributeError) as msg: - raise TypeError("%s\nunable to coerce x (=%s) into %s" % (msg,x,self)) + raise TypeError("%s\nunable to coerce x (=%s) into %s" % (msg, x, self)) return M def is_abelian(self): @@ -582,7 +582,7 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, return ModuleMorphismByLinearity( domain=self, on_basis=on_basis, **keywords) else: - return ModuleMorphismFromFunction( # Or just SetMorphism? + return ModuleMorphismFromFunction( # Or just SetMorphism? domain=self, function=function, **keywords) _module_morphism = module_morphism @@ -1265,7 +1265,7 @@ def _apply_module_morphism(self, x, on_basis, codomain=False): except Exception: raise ValueError('codomain could not be determined') - if hasattr( codomain, 'linear_combination' ): + if hasattr(codomain, 'linear_combination'): mc = x.monomial_coefficients(copy=False) return codomain.linear_combination((on_basis(key), coeff) for key, coeff in mc.items()) @@ -1289,8 +1289,8 @@ def _apply_module_endomorphism(self, x, on_basis): 2*s[2, 1] + 2*s[3] """ mc = x.monomial_coefficients(copy=False) - return self.linear_combination( (on_basis(key), coeff) - for key, coeff in mc.items()) + return self.linear_combination((on_basis(key), coeff) + for key, coeff in mc.items()) def dimension(self): """ @@ -2183,7 +2183,7 @@ def map_support(self, f): sage: y.parent() is B # needs sage.modules True """ - return self.parent().sum_of_terms( (f(m), c) for m,c in self ) + return self.parent().sum_of_terms((f(m), c) for m, c in self) def map_support_skip_none(self, f): """ @@ -2217,7 +2217,9 @@ def map_support_skip_none(self, f): sage: y.parent() is B # needs sage.modules True """ - return self.parent().sum_of_terms( (fm,c) for (fm,c) in ((f(m), c) for m,c in self) if fm is not None) + return self.parent().sum_of_terms((fm, c) + for fm, c in ((f(m), c) for m, c in self) + if fm is not None) def map_item(self, f): """ @@ -2251,7 +2253,7 @@ def map_item(self, f): sage: a.map_item(f) # needs sage.combinat sage.modules 2*s[2, 1] + 2*s[3] """ - return self.parent().sum_of_terms( f(m,c) for m,c in self ) + return self.parent().sum_of_terms(f(m, c) for m, c in self) def tensor(*elements): """ @@ -2587,11 +2589,13 @@ def apply_multilinear_morphism(self, f, codomain=None): except AttributeError: codomain = f(*[module.zero() for module in modules]).parent() if codomain in ModulesWithBasis(K): - return codomain.linear_combination((f(*[module.monomial(t) for (module,t) in zip(modules, m)]), c) - for m,c in self) + return codomain.linear_combination((f(*[module.monomial(t) + for module, t in zip(modules, m)]), c) + for m, c in self) else: - return sum((c * f(*[module.monomial(t) for (module,t) in zip(modules, m)]) - for m,c in self), + return sum((c * f(*[module.monomial(t) + for module, t in zip(modules, m)]) + for m, c in self), codomain.zero()) class DualObjects(DualObjectsCategory): From 48f2c22d0642e8dd0e06f7fbc0fcd58c0c6f281b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 9 Apr 2024 13:43:22 +0200 Subject: [PATCH 111/191] fix indentations --- src/sage/plot/graphics.py | 104 +++++++++++++++++---------------- src/sage/plot/plot3d/plot3d.py | 20 +++---- 2 files changed, 63 insertions(+), 61 deletions(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 0b6c1072ec4..258a6ca7047 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -1388,7 +1388,7 @@ def _set_scale(self, subplot, scale=None, base=None): if isinstance(scale, (list, tuple)): if len(scale) != 2 and len(scale) != 3: raise ValueError("If the input is a tuple, it must be of " - "the form (scale, base) or (scale, basex, basey)") + "the form (scale, base) or (scale, basex, basey)") if len(scale) == 2: base = scale[1] else: @@ -1397,7 +1397,7 @@ def _set_scale(self, subplot, scale=None, base=None): if scale not in ('linear', 'loglog', 'semilogx', 'semilogy'): raise ValueError("The scale must be one of 'linear', 'loglog'," - f" 'semilogx' or 'semilogy' -- got '{scale}'") + f" 'semilogx' or 'semilogy' -- got '{scale}'") if isinstance(base, (list, tuple)): basex, basey = base @@ -1436,37 +1436,37 @@ def _set_scale(self, subplot, scale=None, base=None): # NOTE: If you intend to use a new parameter in show(), you should update # this dictionary to contain the default value for that parameter. - SHOW_OPTIONS = {# axes options - 'axes': None, 'axes_labels': None, 'axes_labels_size': None, - 'axes_pad': None, 'base': None, 'scale': None, - 'xmin': None, 'xmax': None, 'ymin': None, 'ymax': None, - 'flip_x': False, 'flip_y': False, - # Figure options - 'aspect_ratio': None, 'dpi': DEFAULT_DPI, 'fig_tight': True, - 'figsize': None, 'fontsize': None, 'frame': False, - 'title': None, 'title_pos': None, 'transparent': False, - # Grid options - 'gridlines': None, 'gridlinesstyle': None, - 'hgridlinesstyle': None, 'vgridlinesstyle': None, - # Legend options - 'legend_options': {}, 'show_legend': None, - # Ticks options - 'ticks': None, 'tick_formatter': None, 'ticks_integer': False, - # Text options - 'typeset': 'default'} + SHOW_OPTIONS = { # axes options + 'axes': None, 'axes_labels': None, 'axes_labels_size': None, + 'axes_pad': None, 'base': None, 'scale': None, + 'xmin': None, 'xmax': None, 'ymin': None, 'ymax': None, + 'flip_x': False, 'flip_y': False, + # Figure options + 'aspect_ratio': None, 'dpi': DEFAULT_DPI, 'fig_tight': True, + 'figsize': None, 'fontsize': None, 'frame': False, + 'title': None, 'title_pos': None, 'transparent': False, + # Grid options + 'gridlines': None, 'gridlinesstyle': None, + 'hgridlinesstyle': None, 'vgridlinesstyle': None, + # Legend options + 'legend_options': {}, 'show_legend': None, + # Ticks options + 'ticks': None, 'tick_formatter': None, 'ticks_integer': False, + # Text options + 'typeset': 'default'} # Default options for the legends: LEGEND_OPTIONS = {'back_color': 'white', 'borderpad': 0.6, - 'borderaxespad': None, - 'columnspacing': None, - 'fancybox': False, 'font_family': 'sans-serif', - 'font_size': 'medium', 'font_style': 'normal', - 'font_variant': 'normal', 'font_weight': 'medium', - 'handlelength': 0.05, 'handletextpad': 0.5, - 'labelspacing': 0.02, 'loc': 'best', - 'markerscale': 0.6, 'ncol': 1, 'numpoints': 2, - 'shadow': True, 'title': None} + 'borderaxespad': None, + 'columnspacing': None, + 'fancybox': False, 'font_family': 'sans-serif', + 'font_size': 'medium', 'font_style': 'normal', + 'font_variant': 'normal', 'font_weight': 'medium', + 'handlelength': 0.05, 'handletextpad': 0.5, + 'labelspacing': 0.02, 'loc': 'best', + 'markerscale': 0.6, 'ncol': 1, 'numpoints': 2, + 'shadow': True, 'title': None} @suboptions('legend', **LEGEND_OPTIONS) def show(self, **kwds): @@ -2359,9 +2359,9 @@ def _limit_output_aspect_ratio(self, xmin, xmax, ymin, ymax): return {'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax} def _matplotlib_tick_formatter(self, subplot, base=(10, 10), - locator_options={}, scale=('linear', 'linear'), - tick_formatter=(None, None), ticks=(None, None), - xmax=None, xmin=None, ymax=None, ymin=None): + locator_options={}, scale=('linear', 'linear'), + tick_formatter=(None, None), ticks=(None, None), + xmax=None, xmin=None, ymax=None, ymin=None): r""" Take a matplotlib subplot instance representing the graphic and set the ticks formatting. This function is only for internal use. @@ -2387,8 +2387,10 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), # This function is created to refactor some code that is repeated # in the matplotlib function from matplotlib.ticker import (FixedLocator, Locator, - LogFormatterMathtext, LogLocator, MaxNLocator, - MultipleLocator, NullLocator, ScalarFormatter) + LogFormatterMathtext, + LogLocator, MaxNLocator, + MultipleLocator, + NullLocator, ScalarFormatter) x_locator, y_locator = ticks # ---------------------- Location of x-ticks --------------------- @@ -2410,8 +2412,8 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), x_locator = MultipleLocator(float(x_locator)) else: # not enough room for two major ticks raise ValueError('Expand the range of the independent ' - 'variable to allow two multiples of your tick locator ' - '(option `ticks`).') + 'variable to allow two multiples of your tick locator ' + '(option `ticks`).') # ---------------------- Location of y-ticks --------------------- if y_locator is None: @@ -2431,8 +2433,8 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), y_locator = MultipleLocator(float(y_locator)) else: # not enough room for two major ticks raise ValueError('Expand the range of the dependent ' - 'variable to allow two multiples of your tick locator ' - '(option `ticks`).') + 'variable to allow two multiples of your tick locator ' + '(option `ticks`).') x_formatter, y_formatter = tick_formatter from matplotlib.ticker import FuncFormatter, FixedFormatter @@ -2453,8 +2455,8 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), if scale[0] == 'log': # We need to strip out '\\mathdefault' from the string x_formatter = FuncFormatter(lambda n, pos: - LogFormatterMathtext(base=base[0])(n, pos).replace( - "\\mathdefault", "")) + LogFormatterMathtext(base=base[0])(n, pos).replace( + "\\mathdefault", "")) else: # circumvent the problem of symbolic tick values (trac #34693) if isinstance(x_locator, FixedLocator): @@ -2465,8 +2467,8 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), if (not isinstance(ticks[0], (list, tuple)) or len(ticks[0]) != len(x_formatter)): raise ValueError("If the first component of the list " - "`tick_formatter` is a list then the first component " - "of `ticks` must also be a list of equal length.") + "`tick_formatter` is a list then the first component " + "of `ticks` must also be a list of equal length.") x_formatter = FixedFormatter(x_formatter) # ---------------------- Formatting y-ticks ---------------------- if y_formatter is None: @@ -2482,8 +2484,8 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), if scale[1] == 'log': # We need to strip out '\\mathdefault' from the string y_formatter = FuncFormatter(lambda n, pos: - LogFormatterMathtext(base=base[1])(n, pos).replace( - "\\mathdefault", "")) + LogFormatterMathtext(base=base[1])(n, pos).replace( + "\\mathdefault", "")) else: # circumvent the problem of symbolic tick values (trac #34693) if isinstance(y_locator, FixedLocator): @@ -2494,8 +2496,8 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), if (not isinstance(ticks[1], (list, tuple)) or len(ticks[1]) != len(y_formatter)): raise ValueError("If the second component of the list " - "`tick_formatter` is a list then the second component " - "of `ticks` must also be a list of equal length.") + "`tick_formatter` is a list then the second component " + "of `ticks` must also be a list of equal length.") y_formatter = FixedFormatter(y_formatter) subplot.xaxis.set_major_locator(x_locator) @@ -2898,7 +2900,7 @@ def matplotlib(self, filename=None, subplot.set_ylim([ymin, ymax]) locator_options = {'nbins': 9, 'steps': [1, 2, 5, 10], - 'integer': ticks_integer} + 'integer': ticks_integer} if axes is None: axes = self._show_axes @@ -3054,7 +3056,7 @@ def matplotlib(self, filename=None, # We do this change only on linear scale, otherwise matplotlib # errors out with a memory error. from matplotlib.ticker import (AutoMinorLocator, FixedLocator, - LogLocator, NullLocator) + LogLocator, NullLocator) if isinstance(x_locator, (NullLocator, FixedLocator)): subplot.xaxis.set_minor_locator(NullLocator()) elif xscale == 'linear': @@ -3090,7 +3092,7 @@ def matplotlib(self, filename=None, if gridlinesstyle is None: # Set up the default grid style gridlinesstyle = {'color': 'black', 'linestyle': ':', - 'linewidth': 0.5} + 'linewidth': 0.5} vgridstyle = gridlinesstyle.copy() if vgridlinesstyle is not None: @@ -3179,7 +3181,7 @@ def matplotlib(self, filename=None, labeltrans = offset_copy(trans, figure, x=xaxis_labeloffset, y=0, units='points') subplot.xaxis.set_label_coords(x=xaxis_labelx, - y=xaxis_labely, transform=labeltrans) + y=xaxis_labely, transform=labeltrans) ylabel = subplot.yaxis.get_label() ylabel.set_horizontalalignment('center') @@ -3189,7 +3191,7 @@ def matplotlib(self, filename=None, labeltrans = offset_copy(trans, figure, x=0, y=yaxis_labeloffset, units='points') subplot.yaxis.set_label_coords(x=yaxis_labelx, - y=yaxis_labely, transform=labeltrans) + y=yaxis_labely, transform=labeltrans) # This option makes the xlim and ylim limits not take effect # todo: figure out which limits were specified, and let the diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index 83845dc9494..094ea89f254 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -354,8 +354,8 @@ def subs_func(t): indep_var_dummies[1]: float({params[1]}) }})""" return eval(ll, {'t': t, 'func': func, - 'dep_var_dummy': dep_var_dummy, - 'indep_var_dummies': indep_var_dummies}) + 'dep_var_dummy': dep_var_dummy, + 'indep_var_dummies': indep_var_dummies}) return [subs_func(m) for m in transformation] def __repr__(self): @@ -1114,13 +1114,13 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): elif adaptive: P = plot3d_adaptive(f, urange, vrange, **kwds) else: - arg1 = lambda u,v: u - arg2 = lambda u,v: v - P = parametric_plot3d.parametric_plot3d((arg1,arg2,f), + arg1 = lambda u, v: u + arg2 = lambda u, v: v + P = parametric_plot3d.parametric_plot3d((arg1, arg2, f), urange, vrange, **kwds) - P.frame_aspect_ratio([1.0,1.0,0.5]) + P.frame_aspect_ratio([1.0, 1.0, 0.5]) return P @@ -1441,7 +1441,7 @@ def axes(scale=1, radius=None, **kwds): sphinx_plot(T) """ if radius is None: - radius = scale/100.0 - return Graphics3dGroup([arrow3d((0,0,0),(scale,0,0), radius, **kwds), - arrow3d((0,0,0),(0,scale,0), radius, **kwds), - arrow3d((0,0,0),(0,0,scale), radius, **kwds)]) + radius = scale / 100.0 + return Graphics3dGroup([arrow3d((0, 0, 0), (scale, 0, 0), radius, **kwds), + arrow3d((0, 0, 0), (0, scale, 0), radius, **kwds), + arrow3d((0, 0, 0), (0, 0, scale), radius, **kwds)]) From e2fc4afc19d202bd2e9427203877a6bddee45f14 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 9 Apr 2024 22:08:22 +0900 Subject: [PATCH 112/191] Fixing bug with classical Lie algebras over positive characteristic fields. --- .../lie_algebras/classical_lie_algebra.py | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index 01dd668e711..28a148eb645 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -1700,6 +1700,26 @@ def _construct_struct_coeffs(self, R, p_roots): [((alpha[1], -alpha[1]), {alphacheck[1]: 1}), ((alpha[1], alphacheck[1]), {alpha[1]: -2}), ((alphacheck[1], -alpha[1]), {-alpha[1]: -2})] + + TESTS: + + Check that we can construct Lie algebras over positive characteristic + fields (:issue:`37773`):: + + sage: sl4 = lie_algebras.sl(GF(3), 4) + sage: sl4.is_nilpotent() + False + sage: sl4.lower_central_series() + (Lie algebra of ['A', 3] in the Chevalley basis,) + sage: sl4.is_solvable() + False + sage: sl4.is_semisimple() + True + sage: sl4.killing_form_matrix().det() + 2 + sage: sl5 = lie_algebras.sl(GF(3), 5) + sage: sl5.killing_form_matrix().det() + 2 """ alphacheck = self._Q.simple_coroots() roots = frozenset(self._Q.roots()) @@ -1727,12 +1747,12 @@ def _construct_struct_coeffs(self, R, p_roots): continue if b - x in roots: - t1 = ((b-x).norm_squared() / b.norm_squared() + t1 = (R((b-x).norm_squared()) / R(b.norm_squared()) * sp_sign[(x, b-x)] * sp_sign[(a, y-a)]) else: t1 = 0 if a - x in roots: - t2 = ((a-x).norm_squared() / a.norm_squared() + t2 = (R((a-x).norm_squared()) / R(a.norm_squared()) * sp_sign[(x, a-x)] * sp_sign[(b, y-b)]) else: t2 = 0 From d206b472e8b4163a499208a3d1671d409acda76c Mon Sep 17 00:00:00 2001 From: adrinospy Date: Tue, 9 Apr 2024 18:44:45 +0530 Subject: [PATCH 113/191] made suggested changes --- .github/workflows/get_changes.sh | 61 -------------------- .github/workflows/pr-labeler.yml | 18 +++--- .github/workflows/set_labels_by_changes.sh | 67 ++++++++++++++++++++++ 3 files changed, 76 insertions(+), 70 deletions(-) delete mode 100644 .github/workflows/get_changes.sh create mode 100644 .github/workflows/set_labels_by_changes.sh diff --git a/.github/workflows/get_changes.sh b/.github/workflows/get_changes.sh deleted file mode 100644 index b2e716c9da5..00000000000 --- a/.github/workflows/get_changes.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -# get all the changes made and changed files -CHANGES=$(git diff --ignore-all-space $PR_BASE_SHA $PR_HEAD_SHA) - -# ignore blank lines -CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') - -# ignore non necessary lines from git diff -CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') - -# count total no of lines -CHANGES=$(echo "$CHANGES" | wc -l) - -echo "CHANGES MADE: $CHANGES" - -# get changed files -CHANGED_PATH=$(git diff --name-only $PR_BASE_SHA $PR_HEAD_SHA) - -# extract changed dir -CHANGED_DIR=$(echo "$CHANGED_PATH" | awk -F'src/sage/' '{print $2}' | cut -d'/' -f1 | sed 's/\([^ ]\+\)/c: \1/g') - -AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN" - -DELETE_LABELS=("$MINIMAL" "$SMALL" "$MODERATE" "$LARGE") - -if [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then -SIZE_LABEL="$LARGE" -elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then -SIZE_LABEL="$MODERATE" -elif [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then -SIZE_LABEL="$SMALL" -else -SIZE_LABEL="$MINIMAL" -fi - -DELETE_LABELS=("${DELETE_LABELS[@]//${SIZE_LABEL}}") - -readarray -t LABELS <<< "$CHANGED_DIR" -LABELS+=("$SIZE_LABEL") - -echo "Adding label: ${LABELS[@]}" -for LABEL in "${LABELS[@]}"; do - curl -X POST \ - -H "$AUTH_HEADER" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - -d "{\"labels\":[\"$LABEL\"]}" \ - "$API_URL" >/dev/null -done - -echo "Deleting Labels:" - -for DELETE_LABEL in "${DELETE_LABELS[@]}"; do - ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') - curl -X DELETE \ - -H "Accept: application/vnd.github+json" \ - -H "$AUTH_HEADER" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "$API_URL/$ENCODED_LABEL" >/dev/null -done \ No newline at end of file diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 521e7a2901b..7eb62c8a498 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -5,11 +5,14 @@ on: pull_request_target: types: - opened + - reopened - synchronize + - ready_for_review + - review_requested - edited jobs: label-changes: - if: vars.SMALL_THRESHOLD && vars.MODERATE_THRESHOLD && vars.LARGE_THRESHOLD + if: vars.SMALL_THRESHOLD && vars.MODERATE_THRESHOLD && vars.LARGE_THRESHOLD && github.event.pull_request.draft == false runs-on: ubuntu-latest permissions: pull-requests: write @@ -22,18 +25,15 @@ jobs: - name: Add labels based on size run: | git fetch origin $BASE_SHA - chmod a+x .github/workflows/get_changes.sh - .github/workflows/get_changes.sh + chmod a+x .github/workflows/set_labels_by_changes.sh + .github/workflows/set_labels_by_changes.sh env: BASE_SHA: ${{ github.base_ref }} PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - API_URL: "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" - MINIMAL: 'v: minimal' - SMALL: 'v: small' - MODERATE: 'v: moderate' - LARGE: 'v: large' + REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number}} SMALL_THRESHOLD: ${{ vars.SMALL_THRESHOLD }} MODERATE_THRESHOLD: ${{ vars.MODERATE_THRESHOLD }} - LARGE_THRESHOLD: ${{ vars.LARGE_THRESHOLD }} \ No newline at end of file + LARGE_THRESHOLD: ${{ vars.LARGE_THRESHOLD }} diff --git a/.github/workflows/set_labels_by_changes.sh b/.github/workflows/set_labels_by_changes.sh new file mode 100644 index 00000000000..a182d539339 --- /dev/null +++ b/.github/workflows/set_labels_by_changes.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +echo 'set_labels_by_changes.sh called with environment:' +echo "BASE SHA: $PR_BASE_SHA" +echo "HEAD SHA: $PR_HEAD_SHA" +echo "SMALL THRESHOLD $SMALL_THRESHOLD" +echo "MODERATE THERESHOLD: $MODERATE_THRESHOLD" +echo "LARGE THRESHOLD: $LARGE_THRESHOLD" + +# get all the changes made and changed files +CHANGES=$(git diff --ignore-all-space $PR_BASE_SHA $PR_HEAD_SHA) + +# ignore blank lines +CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') + +# ignore non necessary lines from git diff +CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') + +# count total no of lines +CHANGES=$(echo "$CHANGES" | wc -l) + +echo "CHANGES MADE: $CHANGES" + +AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN" + +MINIMAL="v: minimal" +SMALL="v: small" +MODERATE="v: moderate" +LARGE="v: large" + +DELETE_LABELS=("$MINIMAL" "$SMALL" "$MODERATE" "$LARGE") + +if [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then + SIZE_LABEL="$LARGE" +elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then + SIZE_LABEL="$MODERATE" +elif [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then + SIZE_LABEL="$SMALL" +else + SIZE_LABEL="$MINIMAL" +fi + +DELETE_LABELS=("${DELETE_LABELS[@]//${SIZE_LABEL}/}") + +# API for adding labels on the Pull Request +API_URL="https://api.github.com/repos/$REPOSITORY/issues/$PR_NUMBER/labels" + +echo "Adding label: ${SIZE_LABEL[@]}" +for LABEL in "${SIZE_LABEL[@]}"; do + curl -X POST \ + -H "$AUTH_HEADER" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -d "{\"labels\":[\"$LABEL\"]}" \ + "$API_URL" >/dev/null +done + +echo "Deleting Labels:" + +for DELETE_LABEL in "${DELETE_LABELS[@]}"; do + ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') + curl -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "$AUTH_HEADER" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$API_URL/$ENCODED_LABEL" >/dev/null +done From e956798756a933ad15d05249804b4d11c7a1cdeb Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Tue, 9 Apr 2024 18:04:13 +0300 Subject: [PATCH 114/191] Add matroid `relabel` --- src/sage/matroids/basis_matroid.pyx | 63 +- .../matroids/circuit_closures_matroid.pxd | 1 + .../matroids/circuit_closures_matroid.pyx | 44 + src/sage/matroids/circuits_matroid.pxd | 3 +- src/sage/matroids/circuits_matroid.pyx | 44 + src/sage/matroids/database_matroids.py | 800 ++++++++++-------- src/sage/matroids/flats_matroid.pxd | 3 +- src/sage/matroids/flats_matroid.pyx | 45 + src/sage/matroids/graphic_matroid.py | 38 + src/sage/matroids/linear_matroid.pxd | 5 + src/sage/matroids/linear_matroid.pyx | 180 ++++ src/sage/matroids/matroid.pxd | 1 + src/sage/matroids/matroid.pyx | 83 ++ 13 files changed, 945 insertions(+), 365 deletions(-) diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 4c20102a621..43ce3f24962 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -77,6 +77,7 @@ from sage.structure.richcmp cimport rich_to_bool from sage.matroids.matroid cimport Matroid from sage.matroids.basis_exchange_matroid cimport BasisExchangeMatroid from sage.matroids.set_system cimport SetSystem +from sage.matroids.utilities import cmp_elements_key from cpython.object cimport Py_EQ, Py_NE from itertools import combinations @@ -189,15 +190,19 @@ cdef class BasisMatroid(BasisExchangeMatroid): if M is not None: rank = M.full_rank() nonbases = M.nonbases() - groundset = sorted(M.groundset()) + groundset = sorted(M.groundset(), key=cmp_elements_key) if groundset is None: groundset = frozenset() if rank is None: if bases is not None: - rank = len(min(bases)) + for B in bases: + rank = len(B) + break elif nonbases is not None: - rank = len(min(nonbases)) + for N in nonbases: + rank = len(N) + break else: rank = 0 @@ -515,42 +520,46 @@ cdef class BasisMatroid(BasisExchangeMatroid): cdef frozenset se = frozenset([e]) return BasisMatroid(groundset=self._E + (e,), bases=[B | se for B in self.bases()]) - cpdef relabel(self, l): - """ + cpdef relabel(self, f): + r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``l[e]``, - where ``l`` is a given injective map. If ``e not in l`` then the + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the identity map is assumed. INPUT: - - ``l`` -- a python object such that `l[e]` is the new label of `e`. - - OUTPUT: - - A matroid. - - .. TODO:: + - ``f`` -- a python object such that `f[e]` is the new label of `e` - Write abstract ``RelabeledMatroid`` class, and add ``relabel()`` - method to the main ``Matroid`` class, together with ``_relabel()`` - method that can be replaced by subclasses. Use the code from - ``is_isomorphism()`` in ``relabel()`` to deal with a variety of - input methods for the relabeling. + OUTPUT: a matroid EXAMPLES:: - sage: from sage.matroids.advanced import * + sage: from sage.matroids.advanced import BasisMatroid sage: M = BasisMatroid(matroids.catalog.Fano()) sage: sorted(M.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - sage: N = M.relabel({'g':'x'}) - sage: sorted(N.groundset()) - ['a', 'b', 'c', 'd', 'e', 'f', 'x'] + sage: N = M.relabel({'a':0, 'g':'x'}) + sage: from sage.matroids.utilities import cmp_elements_key + sage: sorted(N.groundset(), key=cmp_elements_key) + [0, 'b', 'c', 'd', 'e', 'f', 'x'] + sage: N.is_isomorphic(M) + True + + TESTS:: + + sage: from sage.matroids.advanced import BasisMatroid + sage: M = BasisMatroid(matroids.catalog.Fano()) + sage: f = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - M = BasisMatroid(M=self) - M._relabel(l) + d = self._relabel_map(f) + E = [d[x] for x in self.groundset()] + B = [[d[y] for y in list(x)] for x in self.bases()] + M = BasisMatroid(groundset=E, bases=B) return M # enumeration @@ -691,8 +700,8 @@ cdef class BasisMatroid(BasisExchangeMatroid): bi[bc[e]].append(e) else: bi[bc[e]] = [e] - self._bases_invariant_var = hash(tuple([(c, len(bi[c])) for c in sorted(bi)])) - self._bases_partition_var = SetSystem(self._E, [[self._E[e] for e in bi[c]] for c in sorted(bi)]) + self._bases_invariant_var = hash(tuple([(c, len(bi[c])) for c in sorted(bi, key=cmp_elements_key)])) + self._bases_partition_var = SetSystem(self._E, [[self._E[e] for e in bi[c]] for c in sorted(bi, key=cmp_elements_key)]) return self._bases_invariant_var cpdef _bases_partition(self): diff --git a/src/sage/matroids/circuit_closures_matroid.pxd b/src/sage/matroids/circuit_closures_matroid.pxd index 7c7b61ec35f..446d5ca3f86 100644 --- a/src/sage/matroids/circuit_closures_matroid.pxd +++ b/src/sage/matroids/circuit_closures_matroid.pxd @@ -13,3 +13,4 @@ cdef class CircuitClosuresMatroid(Matroid): cpdef _circuit(self, F) cpdef circuit_closures(self) cpdef _is_isomorphic(self, other, certificate=*) + cpdef relabel(self, f) diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index 42293cc2fc3..8480dd429c4 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -568,4 +568,48 @@ cdef class CircuitClosuresMatroid(Matroid): version = 0 return sage.matroids.unpickling.unpickle_circuit_closures_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: from sage.matroids.circuit_closures_matroid import CircuitClosuresMatroid + sage: M = CircuitClosuresMatroid(matroids.catalog.RelaxedNonFano()) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5, 6] + sage: N = M.relabel({'g':'x', 0:'z'}) # 'g':'x' is ignored + sage: from sage.matroids.utilities import cmp_elements_key + sage: sorted(N.groundset(), key=cmp_elements_key) + [1, 2, 3, 4, 5, 6, 'z'] + sage: M.is_isomorphic(N) + True + + TESTS:: + + sage: from sage.matroids.circuit_closures_matroid import CircuitClosuresMatroid + sage: M = CircuitClosuresMatroid(matroids.catalog.RelaxedNonFano()) + sage: f = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g'} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset()] + CC = {} + for i in self.circuit_closures(): + CC[i] = [[d[y] for y in x] for x in list(self._circuit_closures[i])] + M = CircuitClosuresMatroid(groundset=E, circuit_closures=CC) + return M + # todo: customized minor, extend methods. diff --git a/src/sage/matroids/circuits_matroid.pxd b/src/sage/matroids/circuits_matroid.pxd index 26f86b2dac0..b8995b08ef4 100644 --- a/src/sage/matroids/circuits_matroid.pxd +++ b/src/sage/matroids/circuits_matroid.pxd @@ -24,8 +24,9 @@ cdef class CircuitsMatroid(Matroid): cpdef girth(self) cpdef is_paving(self) - # isomorphism + # isomorphism and relabeling cpdef _is_isomorphic(self, other, certificate=*) + cpdef relabel(self, f) # verification cpdef is_valid(self) diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index 6c09c2dc07d..b8d3b8b18c0 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -413,6 +413,50 @@ cdef class CircuitsMatroid(Matroid): version = 0 return sage.matroids.unpickling.unpickle_circuits_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: from sage.matroids.circuits_matroid import CircuitsMatroid + sage: M = CircuitsMatroid(matroids.catalog.RelaxedNonFano()) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5, 6] + sage: N = M.relabel({'g':'x', 0:'z'}) # 'g':'x' is ignored + sage: from sage.matroids.utilities import cmp_elements_key + sage: sorted(N.groundset(), key=cmp_elements_key) + [1, 2, 3, 4, 5, 6, 'z'] + sage: M.is_isomorphic(N) + True + + TESTS:: + + sage: from sage.matroids.circuits_matroid import CircuitsMatroid + sage: M = CircuitsMatroid(matroids.catalog.RelaxedNonFano()) + sage: f = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g'} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self._groundset] + C = [] + for i in self._k_C: + C += [[d[y] for y in list(x)] for x in self._k_C[i]] + M = CircuitsMatroid(groundset=E, circuits=C) + return M + # enumeration cpdef bases(self): diff --git a/src/sage/matroids/database_matroids.py b/src/sage/matroids/database_matroids.py index 0017ce0627e..2e937874b06 100644 --- a/src/sage/matroids/database_matroids.py +++ b/src/sage/matroids/database_matroids.py @@ -38,7 +38,6 @@ from sage.matrix.constructor import Matrix from sage.matroids.constructor import Matroid -from sage.matroids.circuit_closures_matroid import CircuitClosuresMatroid from sage.matroids.linear_matroid import ( RegularMatroid, BinaryMatroid, @@ -59,7 +58,7 @@ # The order is the same as in Oxley. -def U24(): +def U24(groundset='abcd'): r""" The uniform matroid of rank `2` on `4` elements. @@ -70,7 +69,7 @@ def U24(): sage: M = matroids.catalog.U24(); M U(2, 4): Matroid of rank 2 on 4 elements with circuit-closures - {2: {{0, 1, 2, 3}}} + {2: {{'a', 'b', 'c', 'd'}}} sage: N = matroids.Uniform(2, 4) sage: M.is_isomorphic(N) True @@ -96,12 +95,21 @@ def U24(): REFERENCES: [Oxl2011]_, p. 639. + + TESTS:: + + sage: M = matroids.catalog.U24(range(4)) + sage: sorted(M.groundset()) + [0, 1, 2, 3] + sage: M.is_isomorphic(matroids.catalog.U24()) + True """ M = Uniform(2, 4) + M = _rename_and_relabel(M, "U(2, 4)", groundset) return M -def U25(): +def U25(groundset='abcde'): """ The uniform matroid of rank `2` on `5` elements. @@ -111,7 +119,7 @@ def U25(): sage: U25 = matroids.catalog.U25(); U25 U(2, 5): Matroid of rank 2 on 5 elements with circuit-closures - {2: {{0, 1, 2, 3, 4}}} + {2: {{'a', 'b', 'c', 'd', 'e'}}} sage: U35 = matroids.catalog.U35() sage: U25.is_isomorphic(U35.dual()) True @@ -119,12 +127,19 @@ def U25(): REFERENCES: [Oxl2011]_, p. 640. + + TESTS:: + + sage: M = matroids.catalog.U25(range(5)) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4] """ M = Uniform(2, 5) + M = _rename_and_relabel(M, "U(2, 5)", groundset) return M -def U35(): +def U35(groundset='abcde'): """ The uniform matroid of rank `3` on `5` elements. @@ -134,7 +149,7 @@ def U35(): sage: U35 = matroids.catalog.U35(); U35 U(3, 5): Matroid of rank 3 on 5 elements with circuit-closures - {3: {{0, 1, 2, 3, 4}}} + {3: {{'a', 'b', 'c', 'd', 'e'}}} sage: U25 = matroids.catalog.U25() sage: U35.is_isomorphic(U25.dual()) True @@ -142,12 +157,19 @@ def U35(): REFERENCES: [Oxl2011]_, p. 640. + + TESTS:: + + sage: M = matroids.catalog.U35(range(5)) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4] """ M = Uniform(3, 5) + M = _rename_and_relabel(M, "U(3, 5)", groundset) return M -def K4(): +def K4(groundset='abcdef'): r""" The graphic matroid of the complete graph `K_4`. @@ -176,12 +198,19 @@ def K4(): REFERENCES: [Oxl2011]_, p. 640. + + TESTS:: + + sage: M = matroids.catalog.K4(range(6)) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5] """ M = CompleteGraphic(4) + M = _rename_and_relabel(M, "M(K4)", groundset) return M -def Whirl3(): +def Whirl3(groundset='abcdef'): r""" The rank-`3` whirl. @@ -211,12 +240,19 @@ def Whirl3(): REFERENCES: [Oxl2011]_, p. 641. + + TESTS:: + + sage: W = matroids.catalog.Whirl3(range(6)) + sage: sorted(W.groundset()) + [0, 1, 2, 3, 4, 5] """ M = Whirl(3) + M = _rename_and_relabel(M, "Whirl(3)", groundset) return M -def Q6(): +def Q6(groundset='abcdef'): """ Return the matroid `Q_6`, represented over `GF(4)`. @@ -245,12 +281,12 @@ def Q6(): F = GF(4, 'x') x = F.gens()[0] A = Matrix(F, [[1, 0, 0, 1, 0, 1], [0, 1, 0, 1, 1, x], [0, 0, 1, 0, 1, 1]]) - M = QuaternaryMatroid(A, 'abcdef') - M.rename("Q6: " + repr(M)) + M = QuaternaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Q6") return M -def P6(): +def P6(groundset=None): """ Return the matroid `P_6`, represented as circuit closures. @@ -277,14 +313,13 @@ def P6(): [Oxl2011]_, p. 641-2. """ - E = 'abcdef' - CC = {2: ['abc'], 3: [E]} - M = CircuitClosuresMatroid(groundset=E, circuit_closures=CC) - M.rename("P6: " + repr(M)) + CC = {2: ['abc'], 3: ['abcdef']} + M = Matroid(groundset='abcdef', circuit_closures=CC) + M = _rename_and_relabel(M, "P6", groundset) return M -def U36(): +def U36(groundset='abcdef'): """ The uniform matroid of rank `3` on `6` elements. @@ -295,7 +330,7 @@ def U36(): sage: U36 = matroids.catalog.U36(); U36 U(3, 6): Matroid of rank 3 on 6 elements with circuit-closures - {3: {{0, 1, 2, 3, 4, 5}}} + {3: {{'a', 'b', 'c', 'd', 'e', 'f'}}} sage: Z = matroids.Spike(3, False) sage: U36.is_isomorphic(Z) True @@ -307,12 +342,21 @@ def U36(): REFERENCES: [Oxl2011]_, p. 642. + + TESTS:: + + sage: M = matroids.catalog.U36(range(6)) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5] + sage: M.is_isomorphic(matroids.catalog.U36()) + True """ M = Uniform(3, 6) + M = _rename_and_relabel(M, "U(3, 6)", groundset) return M -def R6(): +def R6(groundset='abcdef'): """ Return the matroid `R_6`, represented over `GF(3)`. @@ -340,12 +384,12 @@ def R6(): A = Matrix( GF(3), [[1, 0, 0, 1, 1, 1], [0, 1, 0, 1, 2, 1], [0, 0, 1, 1, 0, 2]] ) - M = TernaryMatroid(A, 'abcdef') - M.rename("R6: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "R6") return M -def Fano(): +def Fano(groundset='abcdefg'): r""" Return the Fano matroid, represented over `GF(2)`. @@ -390,12 +434,12 @@ def Fano(): GF(2), [[1, 0, 0, 0, 1, 1, 1], [0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 1, 1, 0, 1]] ) - M = BinaryMatroid(A, 'abcdefg') - M.rename("Fano: " + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Fano") return M -def FanoDual(): +def FanoDual(groundset='abcdefg'): """ Return the dual of the Fano matroid. @@ -424,13 +468,19 @@ def FanoDual(): REFERENCES: [Oxl2011]_, p. 643. + + TESTS:: + + sage: F7D = matroids.catalog.FanoDual(range(7)) + sage: sorted(F7D.groundset()) + [0, 1, 2, 3, 4, 5, 6] """ M = Fano().dual() - M.rename("F7*: " + repr(M)) + M = _rename_and_relabel(M, "F7*", groundset) return M -def NonFano(): +def NonFano(groundset='abcdefg'): """ Return the non-Fano matroid, represented over `GF(3)`. @@ -459,12 +509,12 @@ def NonFano(): GF(3), [[1, 0, 0, 0, 1, 1, 1], [0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 1, 1, 0, 1]] ) - M = TernaryMatroid(A, 'abcdefg') - M.rename("NonFano: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "NonFano") return M -def NonFanoDual(): +def NonFanoDual(groundset='abcdefg'): r""" Return the dual of the non-Fano matroid. @@ -492,13 +542,21 @@ def NonFanoDual(): REFERENCES: [Oxl2011]_, p. 643-4. + + TESTS:: + + sage: M = matroids.catalog.NonFanoDual(range(7)) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5, 6] + sage: M.is_isomorphic(matroids.catalog.NonFanoDual()) + True """ M = NonFano().dual() - M.rename("NonFano*: " + repr(M)) + M = _rename_and_relabel(M, "NonFano*", groundset) return M -def O7(): +def O7(groundset='abcdefg'): """ Return the matroid `O_7`, represented over `GF(3)`. @@ -523,12 +581,12 @@ def O7(): GF(3), [[1, 0, 0, 1, 1, 1, 1], [0, 1, 0, 0, 1, 2, 2], [0, 0, 1, 1, 0, 1, 0]] ) - M = TernaryMatroid(A, 'abcdefg') - M.rename("O7: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "O7") return M -def P7(): +def P7(groundset='abcdefg'): """ Return the matroid `P_7`, represented over `GF(3)`. @@ -556,12 +614,12 @@ def P7(): GF(3), [[1, 0, 0, 2, 1, 1, 0], [0, 1, 0, 1, 1, 0, 1], [0, 0, 1, 1, 0, 1, 1]] ) - M = TernaryMatroid(A, 'abcdefg') - M.rename("P7: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "P7") return M -def AG32(): +def AG32(groundset='abcdefgh'): """ Return the matroid `AG(3, 2)`. @@ -601,10 +659,11 @@ def AG32(): [Oxl2011]_, p. 645. """ M = AG(3, 2) + M = _rename_and_relabel(M, "AG(3, 2)", groundset) return M -def AG32prime(): +def AG32prime(groundset=None): """ Return the matroid `AG(3, 2)'`, represented as circuit closures. @@ -629,7 +688,7 @@ def AG32prime(): {'b', 'c', 'd', 'g'}, {'b', 'c', 'e', 'f'}, {'b', 'd', 'f', 'h'}, {'b', 'e', 'g', 'h'}, {'c', 'd', 'e', 'h'}, {'c', 'f', 'g', 'h'}, {'d', 'e', 'f', 'g'}] - sage: M.is_valid() # long time + sage: M.is_valid() True sage: M.automorphism_group().is_transitive() False @@ -665,12 +724,12 @@ def AG32prime(): ], 4: ['abcdefgh'], } - M = CircuitClosuresMatroid(groundset='abcdefgh', circuit_closures=CC) - M.rename("AG(3, 2)': " + repr(M)) + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "AG(3, 2)'", groundset) return M -def R8(): +def R8(groundset='abcdefgh'): """ Return the matroid `R_8`, represented over `GF(3)`. @@ -717,12 +776,12 @@ def R8(): [0, 0, 0, 1, 1, 1, 1, 2], ], ) - M = TernaryMatroid(A, 'abcdefgh') - M.rename("R8: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "R8") return M -def F8(): +def F8(groundset=None): """ Return the matroid `F_8`, represented as circuit closures. @@ -765,12 +824,12 @@ def F8(): ], 4: ['abcdefgh'], } - M = CircuitClosuresMatroid(groundset='abcdefgh', circuit_closures=CC) - M.rename("F8: " + repr(M)) + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "F8", groundset) return M -def Q8(): +def Q8(groundset=None): """ Return the matroid `Q_8`, represented as circuit closures. @@ -814,12 +873,12 @@ def Q8(): ], 4: ['abcdefgh'], } - M = CircuitClosuresMatroid(groundset='abcdefgh', circuit_closures=CC) - M.rename("Q8: " + repr(M)) + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "Q8", groundset) return M -def L8(): +def L8(groundset=None): """ Return the matroid `L_8`, represented as circuit closures. @@ -846,7 +905,7 @@ def L8(): Every single-element contraction is isomorphic to the free extension of `M(K_4)`:: - sage: K4 = matroids.catalog.K4() + sage: K4 = matroids.catalog.K4(range(6)) sage: Bext = [list(b) for b in K4.bases()] + [list(I)+[6] for I in ....: K4.independent_r_sets(2)] sage: K4ext = Matroid(bases=Bext) @@ -861,12 +920,12 @@ def L8(): """ CC = {3: ['abfg', 'bcdg', 'defg', 'cdeh', 'aefh', 'abch', 'aceg', 'bdfh'], 4: ['abcdefgh']} - M = CircuitClosuresMatroid(groundset='abcdefgh', circuit_closures=CC) - M.rename("L8: " + repr(M)) + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "L8", groundset) return M -def S8(): +def S8(groundset='abcdefgh'): """ Return the matroid `S_8`, represented over `GF(2)`. @@ -912,12 +971,12 @@ def S8(): [0, 0, 0, 1, 1, 1, 1, 1], ], ) - M = BinaryMatroid(A, 'abcdefgh') - M.rename("S8: " + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "S8") return M -def Vamos(): +def Vamos(groundset=None): r""" Return the `V\acute{a}mos` matroid, represented as circuit closures. @@ -938,7 +997,7 @@ def Vamos(): {'c', 'd', 'e', 'f'}, {'e', 'f', 'g', 'h'}] sage: M.is_dependent(['c', 'd', 'g', 'h']) False - sage: M.is_valid() # long time + sage: M.is_valid() and M.is_paving() # long time True sage: M.is_isomorphic(M.dual()) and not M.equals(M.dual()) True @@ -950,12 +1009,12 @@ def Vamos(): [Oxl2011]_, p. 649. """ CC = {3: ['abcd', 'abef', 'cdef', 'abgh', 'efgh'], 4: ['abcdefgh']} - M = CircuitClosuresMatroid(groundset='abcdefgh', circuit_closures=CC) - M.rename("Vamos: " + repr(M)) + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "Vamos", groundset) return M -def T8(): +def T8(groundset='abcdefgh'): """ Return the matroid `T_8`, represented over `GF(3)`. @@ -991,12 +1050,12 @@ def T8(): [0, 0, 0, 1, 1, 1, 1, 0], ], ) - M = TernaryMatroid(A, 'abcdefgh') - M.rename("T8: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "T8") return M -def J(): +def J(groundset='abcdefgh'): """ Return the matroid `J`, represented over `GF(3)`. @@ -1032,12 +1091,12 @@ def J(): [0, 0, 0, 1, 1, 0, 0, 1], ], ) - M = TernaryMatroid(A, 'abcdefgh') - M.rename("J: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "J") return M -def P8(): +def P8(groundset='abcdefgh'): """ Return the matroid `P_8`, represented over `GF(3)`. @@ -1070,12 +1129,12 @@ def P8(): [0, 0, 0, 1, 0, 1, 1, 2], ], ) - M = TernaryMatroid(A, 'abcdefgh') - M.rename("P8: " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "P8") return M -def P8pp(): +def P8pp(groundset=None): """ Return the matroid `P_8^=`, represented as circuit closures. @@ -1102,11 +1161,11 @@ def P8pp(): """ NSC = ['abfh', 'bceg', 'cdfh', 'adeg', 'acef', 'bdfg', 'acgh', 'bdeh'] M = Matroid(groundset='abcdefgh', rank=4, nonspanning_circuits=NSC) - M.rename("P8'': " + repr(M)) + M = _rename_and_relabel(M, "P8''", groundset) return M -def Wheel4(): +def Wheel4(groundset='abcdefgh'): """ Return the rank-`4` wheel. @@ -1129,10 +1188,11 @@ def Wheel4(): [Oxl2011]_, p. 651-2. """ M = Wheel(4) + M = _rename_and_relabel(M, "Wheel(4)", groundset) return M -def Whirl4(): +def Whirl4(groundset='abcdefgh'): """ Return the rank-`4` whirl. @@ -1155,10 +1215,11 @@ def Whirl4(): [Oxl2011]_, p. 652. """ M = Whirl(4) + M = _rename_and_relabel(M, "Whirl(4)", groundset) return M -def K33dual(): +def K33dual(groundset='abcdefghi'): """ Return the matroid `M*(K_{3, 3})`, represented over the regular partial field. @@ -1185,13 +1246,13 @@ def K33dual(): from sage.graphs.graph_generators import graphs G = graphs.CompleteBipartiteGraph(3, 3) - M = Matroid(groundset='abcdefghi', graph=G, regular=True) + M = Matroid(groundset=groundset, graph=G, regular=True) M = M.dual() - M.rename("M*(K3, 3): " + repr(M)) + M = _rename_and_relabel(M, "M*(K3, 3)") return M -def K33(): +def K33(groundset='abcdefghi'): r""" Return the graphic matroid `M(K_{3,3})`. @@ -1215,12 +1276,12 @@ def K33(): from sage.graphs.graph_generators import graphs G = graphs.CompleteBipartiteGraph(3, 3) - M = Matroid(groundset='abcdefghi', graph=G, regular=True) - M.rename("M(K3, 3): " + repr(M)) + M = Matroid(groundset=groundset, graph=G, regular=True) + M = _rename_and_relabel(M, "M(K3, 3)") return M -def AG23(): +def AG23(groundset='abcdefghi'): """ Return the matroid `AG(2, 3)`. @@ -1247,10 +1308,11 @@ def AG23(): [Oxl2011]_, p. 653. """ M = AG(2, 3) + M = _rename_and_relabel(M, "AG(2, 3)", groundset) return M -def TernaryDowling3(): +def TernaryDowling3(groundset='abcdefghi'): r""" Return the matroid `Q_3(GF(3)^\times)`, represented over `GF(3)`. @@ -1281,13 +1343,13 @@ def TernaryDowling3(): [0, 0, 1, 0, 0, 2, 1, 2, 1], ], ) - M = TernaryMatroid(A, 'abcdefghi') - M.rename("Q3(GF(3)x): " + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Q3(GF(3)x)") return M -def R9(): - r""" +def R9(groundset=None): + """ Return the matroid `R_9`. The ternary Reid geometry. The only `9`-element rank-`3` simple ternary @@ -1300,7 +1362,7 @@ def R9(): R9: Matroid of rank 3 on 9 elements with 15 nonspanning circuits sage: M.is_valid() True - sage: len(M.nonspanning_circuits()) + sage: len(list(M.nonspanning_circuits())) 15 sage: M.is_simple() and M.is_ternary() True @@ -1314,7 +1376,7 @@ def R9(): NSC = ['abc', 'abd', 'acd', 'aef', 'agh', 'bcd', 'bfh', 'bgi', 'ceg', 'cfi', 'deh', 'dei', 'dfg', 'dhi', 'ehi'] M = Matroid(rank=3, nonspanning_circuits=NSC) - M.rename("R9: " + repr(M)) + M = _rename_and_relabel(M, "R9", groundset) return M @@ -1338,7 +1400,7 @@ def Pappus(groundset=None): {'g', 'h', 'i'}] sage: M.is_dependent(['d', 'e', 'f']) True - sage: M.is_valid() # long time + sage: M.is_valid() True sage: M.automorphism_group().is_transitive() True @@ -1349,11 +1411,11 @@ def Pappus(groundset=None): """ NSC = ['abc', 'def', 'ceg', 'bfg', 'cdh', 'afh', 'bdi', 'aei', 'ghi'] M = Matroid(groundset='abcdefghi', rank=3, nonspanning_circuits=NSC) - M.rename("Pappus: " + repr(M)) + M = _rename_and_relabel(M, "Pappus", groundset) return M -def NonPappus(): +def NonPappus(groundset=None): """ Return the non-Pappus matroid. @@ -1363,15 +1425,16 @@ def NonPappus(): EXAMPLES:: - sage: from sage.matroids.advanced import setprint sage: M = matroids.catalog.NonPappus(); M NonPappus: Matroid of rank 3 on 9 elements with 8 nonspanning circuits - sage: setprint(M.nonspanning_circuits()) - [{'a', 'b', 'c'}, {'a', 'e', 'i'}, {'a', 'f', 'h'}, {'b', 'd', 'i'}, - {'b', 'f', 'g'}, {'c', 'd', 'h'}, {'c', 'e', 'g'}, {'g', 'h', 'i'}] + sage: NSC = set([('a', 'b', 'c'), ('a', 'e', 'i'), ('a', 'f', 'h'), + ....: ('b', 'd', 'i'), ('b', 'f', 'g'), ('c', 'd', 'h'), + ....: ('c', 'e', 'g'), ('g', 'h', 'i')]) + sage: NSC == set(tuple(sorted(C)) for C in M.nonspanning_circuits()) + True sage: M.is_dependent(['d', 'e', 'f']) False - sage: M.is_valid() # long time + sage: M.is_valid() and M.is_paving() True sage: M.automorphism_group().is_transitive() False @@ -1382,11 +1445,11 @@ def NonPappus(): """ NSC = ['abc', 'ceg', 'bfg', 'cdh', 'afh', 'bdi', 'aei', 'ghi'] M = Matroid(groundset='abcdefghi', rank=3, nonspanning_circuits=NSC) - M.rename("NonPappus: " + repr(M)) + M = _rename_and_relabel(M, "NonPappus", groundset) return M -def K5(): +def K5(groundset='abcdefghij'): """ Return the graphic matroid `M(K_5)`. @@ -1407,10 +1470,11 @@ def K5(): [Oxl2011]_, p. 656. """ M = CompleteGraphic(5) + M = _rename_and_relabel(M, "M(K5)", groundset) return M -def K5dual(): +def K5dual(groundset='abcdefghij'): """ Return the matroid `M^*(K_5)`. @@ -1419,7 +1483,7 @@ def K5dual(): EXAMPLES:: sage: M = matroids.catalog.K5dual(); M - M*(K5): Dual of 'M(K5): Graphic matroid of rank 4 on 10 elements' + M*(K5): Matroid of rank 6 on 10 elements with 15 circuits sage: M.is_3connected() True sage: G1 = M.automorphism_group() @@ -1432,16 +1496,16 @@ def K5dual(): [Oxl2011]_, p. 656. """ M = CompleteGraphic(5).dual() - # M = Matroid(circuits=M.circuits()) - M.rename("M*(K5): " + repr(M)) + M = Matroid(circuits=list(M.circuits())) + M = _rename_and_relabel(M, "M*(K5)", groundset) return M -def R10(): +def R10(groundset='abcdefghij'): """ Return the matroid `R_{10}`, represented over the regular partial field. - The matroid `R_{10}` is a 10-element regular matroid of rank-5. It is the + The NonDesargues matroid is a `10`-element matroid of rank-5. It is the unique splitter for the class of regular matroids. It is the graft matroid of `K_{3, 3}` in which every vertex is coloured. @@ -1492,8 +1556,8 @@ def R10(): [0, 0, 0, 0, 1, 1, 0, 0, 1, -1], ], ) - M = RegularMatroid(A, 'abcdefghij') - M.rename("R10: " + repr(M)) + M = RegularMatroid(A, groundset) + M = _rename_and_relabel(M, "R10") return M @@ -1520,7 +1584,7 @@ def NonDesargues(groundset=None): """ NSC = ['acj', 'aef', 'bce', 'bfj', 'bgi', 'chi', 'dfg', 'dij', 'egh'] M = Matroid(rank=3, nonspanning_circuits=NSC) - M.rename("NonDesargues: " + repr(M)) + M = _rename_and_relabel(M, "NonDesargues", groundset) return M @@ -1539,7 +1603,7 @@ def R12(groundset='abcdefghijkl'): R12: Regular matroid of rank 6 on 12 elements with 441 bases sage: M.is_isomorphic(M.dual()) and not M.equals(M.dual()) True - sage: M.is_valid() # long time + sage: M.is_valid() True sage: M.automorphism_group().is_transitive() False @@ -1559,12 +1623,12 @@ def R12(groundset='abcdefghijkl'): [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, -1, -1], ], ) - M = RegularMatroid(A, 'abcdefghijkl') - M.rename("R12: " + repr(M)) + M = RegularMatroid(A, groundset) + M = _rename_and_relabel(M, "R12") return M -def ExtendedTernaryGolayCode(): +def ExtendedTernaryGolayCode(groundset='abcdefghijkl'): """ Return the matroid of the extended ternary Golay code. @@ -1576,13 +1640,14 @@ def ExtendedTernaryGolayCode(): Extended Ternary Golay Code: Ternary matroid of rank 6 on 12 elements, type 6+ sage: C = LinearCode(M.representation()) - sage: C.is_permutation_equivalent(codes.GolayCode(GF(3))) # long time + sage: C.is_permutation_equivalent(codes.GolayCode(GF(3))) True sage: M.is_valid() True The automorphism group is the `5`-transitive Mathieu group `M12`: + sage: # long time sage: G = M.automorphism_group() sage: G.is_transitive() True @@ -1627,12 +1692,12 @@ def ExtendedTernaryGolayCode(): [0, 0, 0, 0, 1, 0, 1, 0, 2, 2, 1, 1], [0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1] ]) - M = TernaryMatroid(A, 'abcdefghijkl') - M.rename('Extended Ternary Golay Code: ' + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Extended Ternary Golay Code") return M -def T12(): +def T12(groundset='abcdefghijkl'): """ Return the matroid `T_{12}`. @@ -1668,12 +1733,12 @@ def T12(): [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1], ], ) - M = BinaryMatroid(A, 'abcdefghijkl') - M.rename("T12: " + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "T12") return M -def PG23(): +def PG23(groundset=None): """ Return the matroid `PG23`. @@ -1694,10 +1759,11 @@ def PG23(): [Oxl2011]_, p. 659. """ M = PG(2, 3) + M = _rename_and_relabel(M, groundset=groundset) return M -def Wheel(r, field=None, ring=None): +def Wheel(r, field=None, ring=None, groundset=None): r""" Return the rank-`r` wheel. @@ -1708,6 +1774,7 @@ def Wheel(r, field=None, ring=None): over the ring or field ``ring``. If the ring is `\ZZ`, then output will be a regular matroid. - ``field`` -- any field; same as ``ring``, but only fields are allowed + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: the rank-`r` wheel matroid, represented as a regular matroid @@ -1767,11 +1834,11 @@ def Wheel(r, field=None, ring=None): M = RegularMatroid(A) else: M = Matroid(A) - M.rename("Wheel(" + str(r) + "): " + repr(M)) + M = _rename_and_relabel(M, "Wheel(" + str(r) + ")", groundset) return M -def Whirl(r): +def Whirl(r, groundset=None): r""" Return the rank-`r` whirl. @@ -1780,6 +1847,7 @@ def Whirl(r): INPUT: - ``r`` -- a positive integer; the rank of the desired matroid. + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: the rank-`r` whirl matroid, represented as a ternary matroid @@ -1835,11 +1903,11 @@ def Whirl(r): else: A[i, 2 * r - 1] = 1 M = TernaryMatroid(A) - M.rename("Whirl(" + str(r) + "): " + repr(M)) + M = _rename_and_relabel(M, "Whirl(" + str(r) + ")", groundset) return M -def Uniform(r, n): +def Uniform(r, n, groundset=None): """ Return the uniform matroid of rank `r` on `n` elements. @@ -1852,6 +1920,7 @@ def Uniform(r, n): - ``r`` -- a nonnegative integer; the rank of the uniform matroid - ``n`` -- a nonnegative integer; the number of elements of the uniform matroid + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: the uniform matroid `U_{r,n}` @@ -1885,12 +1954,12 @@ def Uniform(r, n): CC = {r: [E]} else: CC = {} - M = CircuitClosuresMatroid(groundset=E, circuit_closures=CC) - M.rename("U(" + str(r) + ", " + str(n) + "): " + repr(M)) + M = Matroid(groundset=E, circuit_closures=CC) + M = _rename_and_relabel(M, "U(" + str(r) + ", " + str(n) + ")", groundset) return M -def PG(n, q, x=None): +def PG(n, q, x=None, groundset=None): """ Return the projective geometry of dimension ``n`` over the finite field of order ``q``. @@ -1904,6 +1973,7 @@ def PG(n, q, x=None): - ``x`` -- a string (default: ``None``); the name of the generator of a non-prime field, used for non-prime fields. If not supplied, ``'x'`` is used. + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: a linear matroid whose elements are the points of `PG(n, q)` @@ -1928,11 +1998,11 @@ def PG(n, q, x=None): P = ProjectiveSpace(n, F) A = Matrix(F, [list(p) for p in list(P)]).transpose() M = Matroid(A) - M.rename("PG(" + str(n) + ", " + str(q) + "): " + repr(M)) + M = _rename_and_relabel(M, "PG(" + str(n) + ", " + str(q) + ")", groundset) return M -def AG(n, q, x=None): +def AG(n, q, x=None, groundset=None): r""" Return the affine geometry of dimension ``n`` over the finite field of order ``q``. @@ -1949,6 +2019,7 @@ def AG(n, q, x=None): - ``x`` -- a string (default: ``None``); the name of the generator of a non-prime field, used for non-prime fields. If not supplied, ``'x'`` is used. + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: a linear matroid whose elements are the points of `AG(n, q)` @@ -1974,11 +2045,11 @@ def AG(n, q, x=None): F, [list(p) for p in list(P) if not list(p)[0] == 0] ).transpose() M = Matroid(A) - M.rename("AG(" + str(n) + ", " + str(q) + "): " + repr(M)) + M = _rename_and_relabel(M, "AG(" + str(n) + ", " + str(q) + ")", groundset) return M -def Z(r, t=True): +def Z(r, t=True, groundset=None): r""" Return the unique rank-`r` binary spike. @@ -1987,7 +2058,8 @@ def Z(r, t=True): INPUT: - ``r`` -- an integer (`r \ge 3`); the rank of the spike - - ``t`` -- a Boolean (default: ``True``); whether the spike is tipped + - ``t`` -- boolean (default: ``True``); whether the spike is tipped + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: a matroid; the unique rank-`r` binary spike (tipped or tipless) @@ -2004,7 +2076,9 @@ def Z(r, t=True): sage: import random sage: Z3 = matroids.Z(3) - sage: e = random.choice(list(Z3.groundset())) + sage: E = sorted(Z3.groundset()); E + ['t', 'x1', 'x2', 'x3', 'y1', 'y2', 'y3'] + sage: e = random.choice(E) sage: Z3.delete(e).is_isomorphic(matroids.catalog.K4()) True @@ -2020,6 +2094,18 @@ def Z(r, t=True): sage: Z4.is_isomorphic(matroids.catalog.AG32()) True + and `Z_4 \setminus e \cong S_8`, for all `e \neq t`:: + + sage: Z4 = matroids.Z(4) + sage: E = sorted(Z4.groundset()) + sage: E.remove('t') + sage: e = random.choice(E) + sage: S8 = matroids.catalog.S8() + sage: Z4.delete(e).is_isomorphic(S8) + True + sage: Z4.delete('t').is_isomorphic(S8) + False + The tipless binary spike is self-dual; it is identically self-dual if and only if r is even. It also has a transitive automorphism group:: @@ -2029,7 +2115,7 @@ def Z(r, t=True): True sage: Z.equals(Z.dual()) != (r % 2 == 1) # XOR True - sage: Z.automorphism_group().is_transitive() + sage: Z.automorphism_group().is_transitive() # long time True REFERENCES: @@ -2043,17 +2129,20 @@ def Z(r, t=True): A = Id.augment(J-Id).augment(tip) M = Matroid(A) + X = ['x'+str(i) for i in range(1, r+1)] + Y = ['y'+str(i) for i in range(1, r+1)] if t: - # M = M.relabel(X+Y+['t']) + M = M.relabel(X+Y+['t']) M.rename("Z_" + str(r) + ": " + repr(M)) else: M = M.delete(2*r) - # M = M.relabel(X+Y) + M = M.relabel(X+Y) M.rename("Z_" + str(r) + "\\t: " + repr(M)) + M = _rename_and_relabel(M, groundset=groundset) return M -def Spike(r, t=True, C3=[]): +def Spike(r, t=True, C3=[], groundset=None): r""" Return a rank-`r` spike. @@ -2076,6 +2165,7 @@ def Spike(r, t=True, C3=[]): - ``t`` -- boolean (default: ``True``); whether the spike is tipped - ``C3`` -- a list (default: ``[]``); a list of extra nonspanning circuits. The default (i.e. the empty list) results in a free `r`-spike + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: a matroid; a rank-`r` spike (tipped or tipless) @@ -2086,10 +2176,10 @@ def Spike(r, t=True, C3=[]): nonspanning circuits sage: M.is_isomorphic(matroids.Uniform(3, 6)) True - sage: len(matroids.Spike(8).bases()) + sage: len(list(matroids.Spike(8).bases())) 4864 sage: import random - sage: r = random.choice(range(3, 8)) + sage: r = random.choice(range(3, 20)) sage: M = matroids.Spike(r) sage: M.is_3connected() True @@ -2169,21 +2259,21 @@ def Spike(r, t=True, C3=[]): for i in range(1, r+1): NSC += [['t', 'x'+str(i), 'y'+str(i)]] for j in range(i+1, r+1): - NSC += [['t', 'x'+str(i), 'y'+str(i), 'x'+str(j), 'y'+str(j)]] + NSC += [['x'+str(i), 'y'+str(i), 'x'+str(j), 'y'+str(j)]] M = Matroid(groundset=E, rank=r, nonspanning_circuits=NSC) free = "Free " if C3 == [] else "" tip = "" if t else "\\t" M = M if t else M.delete('t') - M.rename(free + str(r) + "-spike" + tip + ": " + repr(M)) + M = _rename_and_relabel(M, free + str(r) + "-spike" + tip, groundset) return M # Q_r(A) -def Theta(n): +def Theta(n, groundset=None): r""" Return the matroid `\Theta_n`. @@ -2193,11 +2283,14 @@ def Theta(n): INPUT: - ``n`` -- an integer (`n \ge 2`); the rank of the matroid + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: a matroid (`\Theta_n`) EXAMPLES:: + sage: matroids.Theta(30) + Theta_30: Matroid of rank 30 on 60 elements with 16270 circuits sage: M = matroids.Theta(2) sage: U12 = matroids.Uniform(1, 2) sage: U = U12.direct_sum(U12) @@ -2251,11 +2344,11 @@ def Theta(n): C += [Yu + ['x'+str(s)] + ['x'+str(t)]] M = Matroid(groundset=E, circuits=C) - M.rename("Theta_" + str(n) + ": " + repr(M)) + M = _rename_and_relabel(M, "Theta_" + str(n), groundset) return M -def Psi(r): +def Psi(r, groundset=None): r""" Return the matroid `\Psi_r`. @@ -2264,6 +2357,7 @@ def Psi(r): INPUT: - ``r`` -- an integer (`r \ge 3`); the rank of the matroid + - ``groundset`` -- a string (optional); the groundset of the matroid OUTPUT: a matroid (`\Psi_r`) @@ -2294,7 +2388,7 @@ def Psi(r): sage: M = matroids.Psi(r) sage: M.equals(M.dual()) True - sage: M.automorphism_group().is_transitive() + sage: M.automorphism_group().is_transitive() # long time True REFERENCES: @@ -2333,7 +2427,7 @@ def genbin(n, bs=""): NSC += [C] M = Matroid(groundset=E, rank=r, nonspanning_circuits=NSC) - M.rename("Psi_" + str(r) + ": " + repr(M)) + M = _rename_and_relabel(M, "Psi_" + str(r), groundset) return M @@ -2346,7 +2440,7 @@ def genbin(n, bs=""): # 7 elements: -def RelaxedNonFano(): +def RelaxedNonFano(groundset=None): """ Return the relaxed NonFano matroid. @@ -2363,11 +2457,11 @@ def RelaxedNonFano(): w = GF4('w') A = Matrix(GF4, [[1, 1, 0, 1], [1, 0, 1, 1], [0, 1, w, 1]]) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("F7=: " + repr(M)) + M = _rename_and_relabel(M, "F7=", groundset) return M -def TippedFree3spike(): +def TippedFree3spike(groundset=None): """ Return the tipped free `3`-spike. @@ -2387,14 +2481,14 @@ def TippedFree3spike(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[0, 3, 5, 1, 4, 6, 2] ) - M.rename("Tipped rank-3 free spike: " + repr(M)) + M = _rename_and_relabel(M, "Tipped rank-3 free spike", groundset) return M # 8 elements: -def AG23minusDY(): +def AG23minusDY(groundset=None): r""" Return the matroid `AG23minusDY`. @@ -2411,11 +2505,11 @@ def AG23minusDY(): """ A = Matrix(GF(3), [[1, 1, 1, 1], [1, 0, 1, 2], [2, 0, 1, 2], [2, 1, 1, 0]]) M = TernaryMatroid(reduced_matrix=A) - M.rename("Delta-Y of AG(2,3)\\e: " + repr(M)) + M = _rename_and_relabel(M, "Delta-Y of AG(2,3)\\e", groundset) return M -def TQ8(): +def TQ8(groundset=None): """ Return the matroid `TQ8`. @@ -2436,11 +2530,11 @@ def TQ8(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 7, 5, 3, 8, 6, 4, 2] ) - M.rename("TQ8: " + repr(M)) + M = _rename_and_relabel(M, "TQ8", groundset) return M -def P8p(): +def P8p(groundset=None): """ Return the matroid `P8^-`. @@ -2463,11 +2557,11 @@ def P8p(): M = QuaternaryMatroid( reduced_matrix=A, groundset=['a', 'c', 'b', 'f', 'd', 'e', 'g', 'h'] ) - M.rename("P8-: " + repr(M)) + M = _rename_and_relabel(M, "P8-", groundset) return M -def KP8(): +def KP8(groundset=None): """ Return the matroid `KP8`. @@ -2490,11 +2584,11 @@ def KP8(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 4, 3, 5, 6, 7, 0, 2] ) - M.rename("KP8: " + repr(M)) + M = _rename_and_relabel(M, "KP8", groundset) return M -def Sp8(): +def Sp8(groundset=None): """ Return the matroid `Sp8`. @@ -2517,11 +2611,11 @@ def Sp8(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 2, 3, 5, 4, 6, 7, 8] ) - M.rename("Sp8: " + repr(M)) + M = _rename_and_relabel(M, "Sp8", groundset) return M -def Sp8pp(): +def Sp8pp(groundset=None): """ Return the matroid `Sp8=`. @@ -2542,11 +2636,11 @@ def Sp8pp(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 5, 6, 7, 2, 3, 4, 8] ) - M.rename("Sp8=: " + repr(M)) + M = _rename_and_relabel(M, "Sp8=", groundset) return M -def LP8(): +def LP8(groundset=None): """ Return the matroid `LP8`. @@ -2569,11 +2663,11 @@ def LP8(): M = QuaternaryMatroid( reduced_matrix=A, groundset=['a', 'b', 'd', 'e', 'c', 'f', 'g', 'h'] ) - M.rename("LP8: " + repr(M)) + M = _rename_and_relabel(M, "LP8", groundset) return M -def WQ8(): +def WQ8(groundset=None): r""" Return the matroid `WQ8`. @@ -2596,14 +2690,14 @@ def WQ8(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[0, 1, 3, 4, 2, 5, 6, 7] ) - M.rename("WQ8: " + repr(M)) + M = _rename_and_relabel(M, "WQ8", groundset) return M # 9 elements: -def BB9(): +def BB9(groundset=None): """ Return the matroid `BB9`. @@ -2638,11 +2732,11 @@ def BB9(): reduced_matrix=A, groundset=['i', 'b', 'd', 'j', 'h', 'f', 'c', 'a', 'k'] ) - M.rename("BB9: " + repr(M)) + M = _rename_and_relabel(M, "BB9", groundset) return M -def TQ9(): +def TQ9(groundset=None): """ Return the matroid `TQ9`. @@ -2673,11 +2767,11 @@ def TQ9(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 4, 6, 0, 2, 5, 3, 7, 8] ) - M.rename("TQ9: " + repr(M)) + M = _rename_and_relabel(M, "TQ9", groundset) return M -def TQ9p(): +def TQ9p(groundset=None): """ Return the matroid `TQ9^-`. @@ -2712,11 +2806,11 @@ def TQ9p(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 4, 7, 8, 0, 6, 5, 2, 3] ) - M.rename("TQ9': " + repr(M)) + M = _rename_and_relabel(M, "TQ9'", groundset) return M -def M8591(): +def M8591(groundset=None): r""" Return the matroid `M8591`. @@ -2740,11 +2834,11 @@ def M8591(): [0, 0, 1, 1, 0]] ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("M8591: " + repr(M)) + M = _rename_and_relabel(M, "M8591", groundset) return M -def PP9(): +def PP9(groundset=None): """ Return the matroid `PP9`. @@ -2780,11 +2874,11 @@ def PP9(): reduced_matrix=A, groundset=['a', 'c', 'b', 'f', 'd', 'e', 'g', 'h', 'z'] ) - M.rename("PP9: " + repr(M)) + M = _rename_and_relabel(M, "PP9", groundset) return M -def BB9gDY(): +def BB9gDY(groundset=None): r""" Return the matroid `BB9gDY`. @@ -2818,11 +2912,11 @@ def BB9gDY(): reduced_matrix=A, groundset=['c', 'd', 'i', 'f', 'h', 'a', 'j', 'k', 'b'] ) - M.rename("Segment cosegment exchange on BB9: " + repr(M)) + M = _rename_and_relabel(M, "Segment cosegment exchange on BB9", groundset) return M -def A9(): +def A9(groundset=None): """ Return the matroid `A9`. @@ -2847,11 +2941,11 @@ def A9(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[6, 5, 4, 1, 2, 3, 7, 8, 0] ) - M.rename("A9: " + repr(M)) + M = _rename_and_relabel(M, "A9", groundset) return M -def FN9(): +def FN9(groundset=None): """ Return the matroid `FN9`. @@ -2881,11 +2975,11 @@ def FN9(): reduced_matrix=A, groundset=['b0', 'a', 'y', 'z', 'x', "c0", 'b', 'c', 'a0'] ) - M.rename("FN9: " + repr(M)) + M = _rename_and_relabel(M, "FN9", groundset) return M -def FX9(): +def FX9(groundset=None): """ Return the matroid `FX9`. @@ -2913,11 +3007,11 @@ def FX9(): ) # M48806 M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FX9: " + repr(M)) + M = _rename_and_relabel(M, "FX9", groundset) return M -def KR9(): +def KR9(groundset=None): """ Return the matroid `KR9`. @@ -2948,11 +3042,11 @@ def KR9(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[2, 4, 0, 6, 1, 5, 3, 7, 8] ) - M.rename("KR9: " + repr(M)) + M = _rename_and_relabel(M, "KR9", groundset) return M -def KQ9(): +def KQ9(groundset=None): """ Return the matroid `KQ9`. @@ -2987,14 +3081,14 @@ def KQ9(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[5, 0, 4, 3, 2, 6, 8, 7, 1] ) - M.rename("KQ9: " + repr(M)) + M = _rename_and_relabel(M, "KQ9", groundset) return M # 10 elements: -def UG10(): +def UG10(groundset=None): """ Return the matroid `UG10`. @@ -3024,11 +3118,11 @@ def UG10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UG10: " + repr(M)) + M = _rename_and_relabel(M, "UG10", groundset) return M -def FF10(): +def FF10(groundset=None): """ Return the matroid `FF10`. @@ -3057,11 +3151,11 @@ def FF10(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ) - M.rename("FF10: " + repr(M)) + M = _rename_and_relabel(M, "FF10", groundset) return M -def GP10(): +def GP10(groundset=None): """ Return the matroid `GP10`. @@ -3087,11 +3181,11 @@ def GP10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("GP10: " + repr(M)) + M = _rename_and_relabel(M, "GP10", groundset) return M -def FZ10(): +def FZ10(groundset=None): """ Return the matroid `FZ10`. @@ -3118,11 +3212,11 @@ def FZ10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FZ10: " + repr(M)) + M = _rename_and_relabel(M, "FZ10", groundset) return M -def UQ10(): +def UQ10(groundset=None): """ Return the matroid `UQ10`. @@ -3150,11 +3244,11 @@ def UQ10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UQ10: " + repr(M)) + M = _rename_and_relabel(M, "UQ10", groundset) return M -def FP10(): +def FP10(groundset=None): """ Return the matroid `FP10`. @@ -3181,11 +3275,11 @@ def FP10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FP10: " + repr(M)) + M = _rename_and_relabel(M, "FP10", groundset) return M -def TQ10(): +def TQ10(groundset=None): """ Return the matroid `TQ10`. @@ -3218,11 +3312,11 @@ def TQ10(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 6, 8, 'c', 3, 7, 'd', 2, 5, 4] ) - M.rename("TQ10: " + repr(M)) + M = _rename_and_relabel(M, "TQ10", groundset) return M -def FY10(): +def FY10(groundset=None): """ Return the matroid `FY10`. @@ -3249,11 +3343,11 @@ def FY10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FY10: " + repr(M)) + M = _rename_and_relabel(M, "FY10", groundset) return M -def PP10(): +def PP10(groundset=None): """ Return the matroid `PP10`. @@ -3290,11 +3384,11 @@ def PP10(): reduced_matrix=A, groundset=['z', 'f', 'c', 'g', 'e', 'b', 'a', 'h', 'd', 'x'] ) - M.rename("PP10: " + repr(M)) + M = _rename_and_relabel(M, "PP10", groundset) return M -def FU10(): +def FU10(groundset=None): """ Return the matroid `FU10`. @@ -3320,11 +3414,11 @@ def FU10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FU10: " + repr(M)) + M = _rename_and_relabel(M, "FU10", groundset) return M -def D10(): +def D10(groundset=None): """ Return the matroid `D10`. @@ -3351,11 +3445,11 @@ def D10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("D10: " + repr(M)) + M = _rename_and_relabel(M, "D10", groundset) return M -def UK10(): +def UK10(groundset=None): """ Return the matroid `UK10`. @@ -3382,11 +3476,11 @@ def UK10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UK10: " + repr(M)) + M = _rename_and_relabel(M, "UK10", groundset) return M -def PK10(): +def PK10(groundset=None): """ Return the matroid `PK10`. @@ -3413,11 +3507,11 @@ def PK10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("PK10: " + repr(M)) + M = _rename_and_relabel(M, "PK10", groundset) return M -def GK10(): +def GK10(groundset=None): """ Return the matroid `GK10`. @@ -3444,11 +3538,11 @@ def GK10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("GK10: " + repr(M)) + M = _rename_and_relabel(M, "GK10", groundset) return M -def FT10(): +def FT10(groundset=None): """ Return the matroid `FT10`. @@ -3475,11 +3569,11 @@ def FT10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FT10: " + repr(M)) + M = _rename_and_relabel(M, "FT10", groundset) return M -def TK10(): +def TK10(groundset=None): """ Return the matroid `TK10`. @@ -3506,11 +3600,11 @@ def TK10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("TK10: " + repr(M)) + M = _rename_and_relabel(M, "TK10", groundset) return M -def KT10(): +def KT10(groundset=None): """ Return the matroid `KT10`. @@ -3537,11 +3631,11 @@ def KT10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("KT10: " + repr(M)) + M = _rename_and_relabel(M, "KT10", groundset) return M -def TU10(): +def TU10(groundset=None): """ Return the matroid `TU10`. @@ -3568,11 +3662,11 @@ def TU10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("TU10: " + repr(M)) + M = _rename_and_relabel(M, "TU10", groundset) return M -def UT10(): +def UT10(groundset=None): """ Return the matroid `UT10`. @@ -3599,11 +3693,11 @@ def UT10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UT10: " + repr(M)) + M = _rename_and_relabel(M, "UT10", groundset) return M -def FK10(): +def FK10(groundset=None): """ Return the matroid `FK10`. @@ -3630,11 +3724,11 @@ def FK10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FK10: " + repr(M)) + M = _rename_and_relabel(M, "FK10", groundset) return M -def KF10(): +def KF10(groundset=None): """ Return the matroid `KF10`. @@ -3661,14 +3755,14 @@ def KF10(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("KF10: " + repr(M)) + M = _rename_and_relabel(M, "KF10", groundset) return M # 11 elements: -def FA11(): +def FA11(groundset=None): """ Return the matroid `FA11`. @@ -3699,14 +3793,14 @@ def FA11(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[1, 3, 4, 2, 8, 7, 9, 0, 5, 10, 6] ) - M.rename("FA11: " + repr(M)) + M = _rename_and_relabel(M, "FA11", groundset) return M # 12 elements: -def FR12(): +def FR12(groundset=None): """ Return the matroid `FR12`. @@ -3734,11 +3828,11 @@ def FR12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FR12: " + repr(M)) + M = _rename_and_relabel(M, "FR12", groundset) return M -def GP12(): +def GP12(groundset=None): """ Return the matroid `GP12`. @@ -3766,11 +3860,11 @@ def GP12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("GP12: " + repr(M)) + M = _rename_and_relabel(M, "GP12", groundset) return M -def FQ12(): +def FQ12(groundset=None): """ Return the matroid `FQ12`. @@ -3807,11 +3901,11 @@ def FQ12(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[7, 4, 5, 9, 2, 1, 0, 6, 'd', 'c', 8, 3] ) - M.rename("FQ12: " + repr(M)) + M = _rename_and_relabel(M, "FQ12", groundset) return M -def FF12(): +def FF12(groundset=None): """ Return the matroid `FF12`. @@ -3846,11 +3940,11 @@ def FF12(): M = QuaternaryMatroid( reduced_matrix=A, groundset=[0, 4, 'c', 3, 5, 'd', 8, 9, 2, 7, 1, 6] ) - M.rename("FF12: " + repr(M)) + M = _rename_and_relabel(M, "FF12", groundset) return M -def FZ12(): +def FZ12(groundset=None): """ Return the matroid `FZ12`. @@ -3878,11 +3972,11 @@ def FZ12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FZ12: " + repr(M)) + M = _rename_and_relabel(M, "FZ12", groundset) return M -def UQ12(): +def UQ12(groundset=None): """ Return the matroid `UQ12`. @@ -3910,11 +4004,11 @@ def UQ12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UQ12: " + repr(M)) + M = _rename_and_relabel(M, "UQ12", groundset) return M -def FP12(): +def FP12(groundset=None): """ Return the matroid `FP12`. @@ -3942,11 +4036,11 @@ def FP12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FP12: " + repr(M)) + M = _rename_and_relabel(M, "FP12", groundset) return M -def FS12(): +def FS12(groundset=None): """ Return the matroid `FS12`. @@ -3973,11 +4067,11 @@ def FS12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FS12: " + repr(M)) + M = _rename_and_relabel(M, "FS12", groundset) return M -def UK12(): +def UK12(groundset=None): """ Return the matroid `UK12`. @@ -4005,11 +4099,11 @@ def UK12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UK12: " + repr(M)) + M = _rename_and_relabel(M, "UK12", groundset) return M -def UA12(): +def UA12(groundset=None): """ Return the matroid `UA12`. @@ -4037,11 +4131,11 @@ def UA12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UA12: " + repr(M)) + M = _rename_and_relabel(M, "UA12", groundset) return M -def AK12(): +def AK12(groundset=None): """ Return the matroid `AK12`. @@ -4069,11 +4163,11 @@ def AK12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("AK12: " + repr(M)) + M = _rename_and_relabel(M, "AK12", groundset) return M -def FK12(): +def FK12(groundset=None): """ Return the matroid `FK12`. @@ -4101,11 +4195,11 @@ def FK12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FK12: " + repr(M)) + M = _rename_and_relabel(M, "FK12", groundset) return M -def KB12(): +def KB12(groundset=None): """ Return the matroid `KB12`. @@ -4133,11 +4227,11 @@ def KB12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("KB12: " + repr(M)) + M = _rename_and_relabel(M, "KB12", groundset) return M -def AF12(): +def AF12(groundset=None): """ Return the matroid `AF12`. @@ -4165,11 +4259,11 @@ def AF12(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("AF12: " + repr(M)) + M = _rename_and_relabel(M, "AF12", groundset) return M -def NestOfTwistedCubes(): +def NestOfTwistedCubes(groundset=None): r""" Return the NestOfTwistedCubes matroid. @@ -4178,7 +4272,8 @@ def NestOfTwistedCubes(): EXAMPLES:: - sage: M = matroids.catalog.NestOfTwistedCubes() + sage: M = matroids.catalog.NestOfTwistedCubes(); M + NestOfTwistedCubes: Matroid of rank 6 on 12 elements with 57 circuits sage: M.is_3connected() True """ @@ -4188,7 +4283,7 @@ def complement(groundset, subset): gs = ["e1", "e2", "e3", "e4", "e5", "e6", "f1", "f2", "f3", "f4", "f5", "f6"] - M = CircuitClosuresMatroid( + M = Matroid( groundset=gs, circuit_closures={ 3: [ @@ -4228,15 +4323,15 @@ def complement(groundset, subset): 6: [gs], }, ) - M = Matroid(circuits=M.circuits()) - M.rename("NestOfTwistedCubes: " + repr(M)) + M = Matroid(circuits=list(M.circuits())) + M = _rename_and_relabel(M, "NestOfTwistedCubes", groundset) return M # 13 elements: -def XY13(): +def XY13(groundset=None): """ Return the matroid `XY13`. @@ -4264,14 +4359,14 @@ def XY13(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("XY13: " + repr(M)) + M = _rename_and_relabel(M, "XY13", groundset) return M # 14 elements: -def N3(): +def N3(groundset=None): """ Return the matroid `N3`. @@ -4302,11 +4397,11 @@ def N3(): ], ) M = TernaryMatroid(reduced_matrix=A) - M.rename("N3: " + repr(M)) + M = _rename_and_relabel(M, "N3", groundset) return M -def N3pp(): +def N3pp(groundset=None): """ Return the matroid `N3pp`. @@ -4338,11 +4433,11 @@ def N3pp(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("N3=: " + repr(M)) + M = _rename_and_relabel(M, "N3=", groundset) return M -def UP14(): +def UP14(groundset=None): """ Return the matroid `UP14`. @@ -4371,11 +4466,11 @@ def UP14(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("UP14: " + repr(M)) + M = _rename_and_relabel(M, "UP14", groundset) return M -def VP14(): +def VP14(groundset=None): """ Return the matroid `VP14`. @@ -4404,11 +4499,11 @@ def VP14(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("VP14: " + repr(M)) + M = _rename_and_relabel(M, "VP14", groundset) return M -def FV14(): +def FV14(groundset=None): """ Return the matroid `FV14` @@ -4437,11 +4532,11 @@ def FV14(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FV14: " + repr(M)) + M = _rename_and_relabel(M, "FV14", groundset) return M -def OW14(): +def OW14(groundset=None): """ Return the matroid `OW14`. @@ -4470,11 +4565,11 @@ def OW14(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("OW14: " + repr(M)) + M = _rename_and_relabel(M, "OW14", groundset) return M -def FM14(): +def FM14(groundset=None): """ Return the matroid `FM14`. @@ -4502,14 +4597,14 @@ def FM14(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FM14: " + repr(M)) + M = _rename_and_relabel(M, "FM14", groundset) return M # 15 elements: -def FA15(): +def FA15(groundset=None): """ Return the matroid `FA15`. @@ -4539,14 +4634,14 @@ def FA15(): ], ) M = QuaternaryMatroid(reduced_matrix=A) - M.rename("FA15: " + repr(M)) + M = _rename_and_relabel(M, "FA15", groundset) return M # 16 elements: -def N4(): +def N4(groundset=None): """ Return the matroid `N4`. @@ -4578,7 +4673,7 @@ def N4(): ], ) M = TernaryMatroid(reduced_matrix=A) - M.rename("N4: " + repr(M)) + M = _rename_and_relabel(M, "N4", groundset) return M @@ -4588,7 +4683,7 @@ def N4(): # ******************************** # -def NonVamos(): +def NonVamos(groundset=None): r""" Return the non-`V\acute{a}mos` matroid. @@ -4616,17 +4711,16 @@ def NonVamos(): [Oxl2011]_, p. 72, 84. """ - E = 'abcdefgh' CC = { 3: ['abcd', 'abef', 'cdef', 'abgh', 'cdgh', 'efgh'], - 4: [E] + 4: ['abcdefgh'] } - M = CircuitClosuresMatroid(groundset=E, circuit_closures=CC) - M.rename('NonVamos: ' + repr(M)) + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "NonVamos", groundset) return M -def NotP8(): +def NotP8(groundset='abcdefgh'): """ Return the matroid ``NotP8``. @@ -4650,12 +4744,12 @@ def NotP8(): [0, 0, 1, 0, 1, 1, 0, 1], [0, 0, 0, 1, -1, 1, 1, 1] ]) - M = TernaryMatroid(A, "abcdefgh") - M.rename('NotP8: ' + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "NotP8") return M -def AG23minus(): +def AG23minus(groundset=None): """ Return the ternary affine plane minus a point. @@ -4677,15 +4771,14 @@ class of near-regular matroids. [Oxl2011]_, p. 653. """ - E = 'abcdefgh' CC = {2: ['abc', 'ceh', 'fgh', 'adf', 'aeg', 'cdg', 'bdh', 'bef'], - 3: [E]} - M = CircuitClosuresMatroid(groundset=E, circuit_closures=CC) - M.rename('AG23minus: ' + repr(M)) + 3: ['abcdefgh']} + M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = _rename_and_relabel(M, "AG23minus", groundset) return M -def P9(): +def P9(groundset='abcdefghi'): """ Return the matroid `P_9`. @@ -4707,12 +4800,12 @@ def P9(): [0, 0, 1, 0, 0, 1, 1, 0, 1], [0, 0, 0, 1, 0, 0, 1, 1, 0] ]) - M = BinaryMatroid(A, "abcdefghi") - M.rename('P9: ' + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "P9") return M -def R9A(): +def R9A(groundset=None): """ Return the matroid `R_9^A`. @@ -4731,11 +4824,11 @@ def R9A(): NSC = ['abch', 'abde', 'abfi', 'acdi', 'aceg', 'adgh', 'aefh', 'bcdf', 'bdhi', 'begi', 'cehi', 'defi', 'fghi'] M = Matroid(groundset='abcdefghi', rank=4, nonspanning_circuits=NSC) - M.rename("R9A: " + repr(M)) + M = _rename_and_relabel(M, "R9A", groundset) return M -def R9B(): +def R9B(groundset=None): """ Return the matroid `R_9^B`. @@ -4754,11 +4847,11 @@ def R9B(): NSC = ['abde', 'bcdf', 'aceg', 'abch', 'befh', 'cdgh', 'bcei', 'adfi', 'abgi', 'degi', 'bdhi', 'aehi', 'fghi'] M = Matroid(groundset='abcdefghi', rank=4, nonspanning_circuits=NSC) - M.rename("R9B: " + repr(M)) + M = _rename_and_relabel(M, "R9B", groundset) return M -def Block_9_4(): +def Block_9_4(groundset=None): """ Return the paving matroid whose nonspanning circuits form the blocks of a `2-(9, 4, 3)` design. @@ -4770,7 +4863,7 @@ def Block_9_4(): circuits sage: M.is_valid() and M.is_paving() True - sage: BD = BlockDesign(M.groundset(), M.nonspanning_circuits()) + sage: BD = BlockDesign(M.groundset(), list(M.nonspanning_circuits())) sage: BD.is_t_design(return_parameters=True) (True, (2, 9, 4, 3)) """ @@ -4778,11 +4871,11 @@ def Block_9_4(): 'begh', 'dfgh', 'abei', 'cdfi', 'bcgi', 'adgi', 'efgi', 'bdhi', 'cehi', 'afhi'] M = Matroid(groundset='abcdefghi', rank=4, nonspanning_circuits=NSC) - M.rename("Block(9, 4): " + repr(M)) + M = _rename_and_relabel(M, "Block(9, 4)", groundset) return M -def TicTacToe(): +def TicTacToe(groundset=None): """ Return the TicTacToe matroid. @@ -4803,11 +4896,11 @@ def TicTacToe(): NSC = ['abcdg', 'adefg', 'abceh', 'abcfi', 'cdefi', 'adghi', 'beghi', 'cfghi'] M = Matroid(groundset='abcdefghi', rank=5, nonspanning_circuits=NSC) - M.rename("TicTacToe: " + repr(M)) + M = _rename_and_relabel(M, "TicTacToe", groundset) return M -def N1(): +def N1(groundset='abcdefghij'): r""" Return the matroid `N_1`, represented over `\GF{3}`. @@ -4833,12 +4926,12 @@ def N1(): [0, 0, 0, 1, 0, 0, 0, 1, 2, 2], [0, 0, 0, 0, 1, 1, 1, 1, 2, 0] ]) - M = TernaryMatroid(A, 'abcdefghij') - M.rename('N1: ' + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "N1") return M -def Block_10_5(): +def Block_10_5(groundset=None): """ Return the paving matroid whose nonspanning circuits form the blocks of a `3-(10, 5, 3)` design. @@ -4850,7 +4943,7 @@ def Block_10_5(): circuits sage: M.is_valid() and M.is_paving() True - sage: BD = BlockDesign(M.groundset(), M.nonspanning_circuits()) + sage: BD = BlockDesign(M.groundset(), list(M.nonspanning_circuits())) sage: BD.is_t_design(return_parameters=True) (True, (3, 10, 5, 3)) """ @@ -4861,11 +4954,11 @@ def Block_10_5(): 'abcij', 'bdeij', 'cdfij', 'adgij', 'efgij', 'aehij', 'bfhij', 'cghij'] M = Matroid(groundset='abcdefghij', rank=5, nonspanning_circuits=NSC) - M.rename("Block(10, 5): " + repr(M)) + M = _rename_and_relabel(M, "Block(10, 5)", groundset) return M -def Q10(): +def Q10(groundset='abcdefghij'): r""" Return the matroid `Q_{10}`, represented over `\GF{4}`. @@ -4876,7 +4969,8 @@ def Q10(): EXAMPLES:: - sage: M = matroids.catalog.Q10() + sage: M = matroids.catalog.Q10(); M + Q10: Quaternary matroid of rank 5 on 10 elements sage: M.is_isomorphic(M.dual()) True sage: M.is_valid() @@ -4901,12 +4995,12 @@ def Q10(): [0, 0, 0, 1, 0, 0, 0, x + 1, 1, x], [0, 0, 0, 0, 1, x, 0, 0, x + 1, 1] ]) - M = QuaternaryMatroid(A, "abcdefghij") - M.rename('Q10: ' + repr(M)) + M = QuaternaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Q10") return M -def BetsyRoss(): +def BetsyRoss(groundset=None): """ Return the Betsy Ross matroid, represented by circuit closures. @@ -4928,11 +5022,11 @@ def BetsyRoss(): 'bef', 'bej', 'bfj', 'bgh', 'bik', 'ceh', 'cei', 'cfg', 'chi', 'cjk', 'dfk', 'dgh', 'dij', 'efj', 'egk', 'ehi'] M = Matroid(groundset='abcdefghijk', rank=3, nonspanning_circuits=NSC) - M.rename("BetsyRoss: " + repr(M)) + M = _rename_and_relabel(M, "BetsyRoss", groundset) return M -def N2(): +def N2(groundset='abcdefghijkl'): r""" Return the matroid `N_2`, represented over `\GF{3}`. @@ -4959,8 +5053,8 @@ def N2(): [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 0, 1] ]) - M = TernaryMatroid(A, "abcdefghijkl") - M.rename('N2: ' + repr(M)) + M = TernaryMatroid(A, groundset) + M = _rename_and_relabel(M, "N2") return M @@ -4994,12 +5088,12 @@ def D16(groundset='abcdefghijklmnop'): # A.K.A. the Carolyn Chun Matroid [0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0] ]) - M = BinaryMatroid(A, "abcdefghijklmnop") - M.rename('D16: ' + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "D16") return M -def Terrahawk(): # A.K.A. the Dillon Mayhew Matroid +def Terrahawk(groundset='abcdefghijklmnop'): # aka the Dillon Mayhew Matroid """ Return the Terrahawk matroid. @@ -5027,12 +5121,12 @@ def Terrahawk(): # A.K.A. the Dillon Mayhew Matroid [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0] ]) - M = BinaryMatroid(A, "abcdefghijklmnop") - M.rename('Terrahawk: ' + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Terrahawk") return M -def ExtendedBinaryGolayCode(): +def ExtendedBinaryGolayCode(groundset='abcdefghijklmnopqrstuvwx'): """ Return the matroid of the extended binary Golay code. @@ -5076,12 +5170,12 @@ def ExtendedBinaryGolayCode(): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ]) - M = BinaryMatroid(A, "abcdefghijklmnopqrstuvwx") - M.rename('Extended Binary Golay Code: ' + repr(M)) + M = BinaryMatroid(A, groundset) + M = _rename_and_relabel(M, "Extended Binary Golay Code") return M -def CompleteGraphic(n): +def CompleteGraphic(n, groundset=None): """ Return the cycle matroid of the complete graph on `n` vertices. @@ -5115,5 +5209,39 @@ def CompleteGraphic(n): groundset=list(range((n * (n - 1)) // 2)), graph=graphs.CompleteGraph(n) ) - M.rename("M(K" + str(n) + "): " + repr(M)) + M = _rename_and_relabel(M, "M(K" + str(n) + ")", groundset) + return M + + +# helper function + + +def _rename_and_relabel(M, name=None, groundset=None): + """ + Return a renamed and relabeled matroid. + + This is a helper function for easily renaming and relabeling matroids upon + definition in the context of the database of matroids. + + INPUT: + + - ``M`` -- a matroid + - ``name`` -- a string (optional) + - ``groundset`` -- a string (optional) + + OUTPUT: + + a matroid + """ + if groundset is not None: + if len(groundset) != len(M.groundset()): + raise ValueError( + "The groundset should be of size %s (%s given)." % + (len(M.groundset()), len(groundset)) + ) + M = M.relabel(dict(zip(M.groundset(), groundset))) + + if name is not None: + M.rename(name+": " + repr(M)) + return M diff --git a/src/sage/matroids/flats_matroid.pxd b/src/sage/matroids/flats_matroid.pxd index e97b929429b..026c934a185 100644 --- a/src/sage/matroids/flats_matroid.pxd +++ b/src/sage/matroids/flats_matroid.pxd @@ -13,8 +13,9 @@ cdef class FlatsMatroid(Matroid): cpdef flats(self, k) cpdef whitney_numbers2(self) - # isomorphism + # isomorphism and relabeling cpdef _is_isomorphic(self, other, certificate=*) + cpdef relabel(self, f) # verification cpdef is_valid(self) diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index ae95455bb2f..23951d666f6 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -300,6 +300,51 @@ cdef class FlatsMatroid(Matroid): version = 0 return sage.matroids.unpickling.unpickle_flats_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: from sage.matroids.flats_matroid import FlatsMatroid + sage: M = FlatsMatroid(matroids.catalog.RelaxedNonFano()) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5, 6] + sage: N = M.relabel({'g':'x', 0:'z'}) # 'g':'x' is ignored + sage: from sage.matroids.utilities import cmp_elements_key + sage: sorted(N.groundset(), key=cmp_elements_key) + [1, 2, 3, 4, 5, 6, 'z'] + sage: M.is_isomorphic(N) + True + + TESTS:: + + sage: from sage.matroids.flats_matroid import FlatsMatroid + sage: M = FlatsMatroid(matroids.catalog.RelaxedNonFano()) + sage: f = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g'} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self._groundset] + F = {} + for i in self._F: + F[i] = [] + F[i] += [[d[y] for y in list(x)] for x in self._F[i]] + M = FlatsMatroid(groundset=E, flats=F) + return M + # enumeration cpdef flats(self, k): diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 57bbae15f22..f1e8840f281 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -2001,3 +2001,41 @@ def regular_matroid(self): from sage.matroids.constructor import Matroid as ConstructorMatroid X = [l for u, v, l in self._G.edge_iterator()] return ConstructorMatroid(groundset=X, graph=self._G, regular=True) + + def relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: M = matroids.CompleteGraphic(4) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5] + sage: N = M.relabel({0:6, 5:'e'}) + sage: sorted(N.groundset(), key=str) + [1, 2, 3, 4, 6, 'e'] + sage: N.is_isomorphic(M) + True + + TESTS:: + + sage: M = matroids.CompleteGraphic(4) + sage: f = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g'} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset()] + M = GraphicMatroid(self.graph(), groundset=E) + return M diff --git a/src/sage/matroids/linear_matroid.pxd b/src/sage/matroids/linear_matroid.pxd index 4902ccef6ef..89e9580024e 100644 --- a/src/sage/matroids/linear_matroid.pxd +++ b/src/sage/matroids/linear_matroid.pxd @@ -28,6 +28,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): cpdef is_field_isomorphism(self, other, morphism) # cpdef is_field_isomorphic(self, other) # TODO: currently only works as ``def`` cpdef _fast_isom_test(self, other) + cpdef relabel(self, f) cpdef _minor(self, contractions, deletions) cpdef dual(self) @@ -88,6 +89,7 @@ cdef class BinaryMatroid(LinearMatroid): cpdef BinaryMatrix _projection(self) cpdef BinaryMatrix _projection_partition(self) cpdef _fast_isom_test(self, other) + cpdef relabel(self, f) cpdef is_graphic(self) cpdef is_valid(self) @@ -118,6 +120,7 @@ cdef class TernaryMatroid(LinearMatroid): cpdef _principal_quadripartition(self) cpdef TernaryMatrix _projection(self) cpdef _fast_isom_test(self, other) + cpdef relabel(self, f) cpdef is_valid(self) @@ -144,6 +147,7 @@ cdef class QuaternaryMatroid(LinearMatroid): cpdef bicycle_dimension(self) cpdef _principal_tripartition(self) cpdef _fast_isom_test(self, other) + cpdef relabel(self, f) cpdef is_valid(self) @@ -159,6 +163,7 @@ cdef class RegularMatroid(LinearMatroid): cpdef _invariant(self) cpdef _fast_isom_test(self, other) + cpdef relabel(self, f) cpdef bases_count(self) cpdef _projection(self) diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index 7b6eb9bb711..1fb95238100 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -2973,6 +2973,42 @@ cdef class LinearMatroid(BasisExchangeMatroid): data = (A, gs, reduced, self.get_custom_name()) return sage.matroids.unpickling.unpickle_linear_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: M = matroids.catalog.Fano() + sage: sorted(M.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + sage: N = M.relabel({'g':'x'}) + sage: sorted(N.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'x'] + + TESTS:: + + sage: M = matroids.catalog.Fano() + sage: f = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset_list()] + M = LinearMatroid(groundset=E, matrix=self._matrix_()) + return M + # Binary matroid cdef class BinaryMatroid(LinearMatroid): @@ -4038,6 +4074,42 @@ cdef class BinaryMatroid(LinearMatroid): data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_binary_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: M = matroids.catalog.Fano() + sage: sorted(M.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + sage: N = M.relabel({'g':'x'}) + sage: sorted(N.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'x'] + + TESTS:: + + sage: M = matroids.catalog.Fano() + sage: f = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset_list()] + M = BinaryMatroid(groundset=E, matrix=self._matrix_()) + return M + cdef class TernaryMatroid(LinearMatroid): r""" Ternary matroids. @@ -4932,6 +5004,42 @@ cdef class TernaryMatroid(LinearMatroid): data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_ternary_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: M = matroids.catalog.NonFano() + sage: sorted(M.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + sage: N = M.relabel({'g':'x'}) + sage: sorted(N.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'x'] + + TESTS:: + + sage: M = matroids.catalog.NonFano() + sage: f = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset_list()] + M = TernaryMatroid(groundset=E, matrix=self._matrix_()) + return M + # Quaternary Matroids cdef class QuaternaryMatroid(LinearMatroid): @@ -5657,6 +5765,42 @@ cdef class QuaternaryMatroid(LinearMatroid): data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_quaternary_matroid, (version, data) + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: M = matroids.catalog.RelaxedNonFano("abcdefg") + sage: sorted(M.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + sage: N = M.relabel({'g':'x'}) + sage: sorted(N.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'x'] + + TESTS:: + + sage: M = matroids.catalog.RelaxedNonFano("abcdefg") + sage: f = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset_list()] + M = QuaternaryMatroid(groundset=E, matrix=self._matrix_()) + return M + # Regular Matroids cdef class RegularMatroid(LinearMatroid): @@ -6575,3 +6719,39 @@ cdef class RegularMatroid(LinearMatroid): reduced = True data = (A, gs, reduced, self.get_custom_name()) return sage.matroids.unpickling.unpickle_regular_matroid, (version, data) + + cpdef relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: M = matroids.catalog.R10() + sage: sorted(M.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] + sage: N = M.relabel({'g':'x'}) + sage: sorted(N.groundset()) + ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'x'] + + TESTS:: + + sage: M = matroids.catalog.R10() + sage: f = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([M._relabel_map(f)[x] for x in S]) + """ + d = self._relabel_map(f) + E = [d[x] for x in self.groundset_list()] + M = RegularMatroid(groundset=E, matrix=self._matrix_()) + return M diff --git a/src/sage/matroids/matroid.pxd b/src/sage/matroids/matroid.pxd index 5103bcf2a4b..7aa97843c7e 100644 --- a/src/sage/matroids/matroid.pxd +++ b/src/sage/matroids/matroid.pxd @@ -141,6 +141,7 @@ cdef class Matroid(SageObject): cpdef equals(self, other) cpdef is_isomorphism(self, other, morphism) cpdef _is_isomorphism(self, other, morphism) + cpdef _relabel_map(self, f) # minors, dual, truncation cpdef minor(self, contractions=*, deletions=*) diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 781f72592ac..23cfee2f9b4 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -120,6 +120,7 @@ additional functionality (e.g. linear extensions). - :meth:`is_binary() ` - :meth:`ternary_matroid() ` - :meth:`is_ternary() ` + - :meth:`relabel() ` - Optimization - :meth:`max_weight_independent() ` @@ -8389,3 +8390,85 @@ cdef class Matroid(SageObject): # place this matroid at the beginning of the list matroids.insert(0, self) return union_matroid.MatroidSum(iter(matroids)) + + cpdef _relabel_map(self, f): + """ + Return a dictionary from the groundset to the relabeled groundset + and check that the mapping defined by ``f`` is valid. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e`; if + ``e not in f`` then the identity map is assumed + + EXAMPLES:: + + sage: M = matroids.catalog.Vamos([1,2,3,4,5,6,7,8]) + sage: M._relabel_map({1:'a', 8:'h', 9:'i'}) + {1: 'a', 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 'h'} + sage: M._relabel_map({1:2}) + Traceback (most recent call last): + ... + ValueError: given map doesn't relabel the groundset properly + """ + E = set() + d = {} + for x in self.groundset(): + try: + E.add(f[x]) + d[x] = f[x] + except LookupError: + E.add(x) + d[x] = x + if len(E) != len(self.groundset()): + raise ValueError("given map doesn't relabel the groundset properly") + return d + + def relabel(self, f): + r""" + Return an isomorphic matroid with relabeled groundset. + + The output is obtained by relabeling each element ``e`` by ``f[e]``, + where ``f`` is a given injective map. If ``e not in f`` then the + identity map is assumed. + + INPUT: + + - ``f`` -- a python object such that `f[e]` is the new label of `e` + + OUTPUT: a matroid + + EXAMPLES:: + + sage: from sage.matroids.rank_matroid import RankMatroid + sage: N = matroids.catalog.Sp8pp() + sage: M = RankMatroid(groundset=N.groundset(), rank_function=N.rank) + sage: sorted(M.groundset()) + [1, 2, 3, 4, 5, 6, 7, 8] + sage: N = M.relabel({8:0}) + sage: sorted(N.groundset()) + [0, 1, 2, 3, 4, 5, 6, 7] + sage: M.is_isomorphic(N) + True + + TESTS:: + + sage: from sage.matroids.rank_matroid import RankMatroid + sage: N = matroids.catalog.Sp8pp() + sage: M = RankMatroid(groundset=N.groundset(), rank_function=N.rank) + sage: f = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f', 7:'g', 8:'h'} + sage: N = M.relabel(f) + sage: for S in powerset(M.groundset()): + ....: assert M.rank(S) == N.rank([f[x] for x in S]) + """ + from sage.matroids.rank_matroid import RankMatroid + d = self._relabel_map(f) + E = [d[x] for x in self.groundset()] + + def f_relabel(X): + d_inv = {d[x]: x for x in self.groundset()} + X_inv = [d_inv[x] for x in X] + return self.rank(X_inv) + + M = RankMatroid(groundset=E, rank_function=f_relabel) + return M From 18487f30bb8f4c5c055c06fa824d1d7ec00e9ca3 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 10 Apr 2024 10:17:06 +0900 Subject: [PATCH 115/191] Allow characteristic 2 and adding some more tests. --- .../lie_algebras/classical_lie_algebra.py | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index 28a148eb645..fae28403d4f 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -1706,7 +1706,12 @@ def _construct_struct_coeffs(self, R, p_roots): Check that we can construct Lie algebras over positive characteristic fields (:issue:`37773`):: + sage: sl3 = LieAlgebra(GF(3), cartan_type=['A',2]) + sage: sl3.center().basis() + Family (2*h1 + h2,) sage: sl4 = lie_algebras.sl(GF(3), 4) + sage: sl4.center().dimension() + 0 sage: sl4.is_nilpotent() False sage: sl4.lower_central_series() @@ -1720,10 +1725,28 @@ def _construct_struct_coeffs(self, R, p_roots): sage: sl5 = lie_algebras.sl(GF(3), 5) sage: sl5.killing_form_matrix().det() 2 + + This also includes characteristic 2:: + + sage: sl4 = LieAlgebra(GF(2), cartan_type=['A',3]) + sage: sl4.center().basis() + Family (h1 + h3,) + sage: sp6 = LieAlgebra(GF(2), cartan_type=['C',3]) + sage: sp6.killing_form_matrix().det() + 0 + sage: F4 = LieAlgebra(GF(2), cartan_type=['F',4]) + sage: F4.killing_form_matrix().det() # long time + 0 + sage: G2 = LieAlgebra(GF(2), cartan_type=['G',2]) + sage: G2.killing_form_matrix().det() + 0 """ alphacheck = self._Q.simple_coroots() roots = frozenset(self._Q.roots()) - one = R.one() + # We do everything initially over QQ and then convert to R at the end + # since this is a ZZ-basis. + from sage.rings.rational_field import QQ + one = QQ.one() # Determine the signs for the structure coefficients from the root system # We first create the special roots @@ -1747,12 +1770,12 @@ def _construct_struct_coeffs(self, R, p_roots): continue if b - x in roots: - t1 = (R((b-x).norm_squared()) / R(b.norm_squared()) + t1 = ((b-x).norm_squared() / b.norm_squared() * sp_sign[(x, b-x)] * sp_sign[(a, y-a)]) else: t1 = 0 if a - x in roots: - t2 = (R((a-x).norm_squared()) / R(a.norm_squared()) + t2 = ((a-x).norm_squared() / a.norm_squared() * sp_sign[(x, a-x)] * sp_sign[(b, y-b)]) else: t2 = 0 @@ -1775,15 +1798,15 @@ def e_coeff(r, s): for i,r in enumerate(p_roots): # [e_r, h_i] and [h_i, f_r] for ac in alphacheck: - c = r.scalar(ac) + c = R(r.scalar(ac)) if c == 0: continue s_coeffs[(r, ac)] = {r: -c} s_coeffs[(ac, -r)] = {-r: -c} # [e_r, f_r] - s_coeffs[(r, -r)] = {alphacheck[j]: c - for j, c in r.associated_coroot()} + s_coeffs[(r, -r)] = {alphacheck[j]: Rc + for j, c in r.associated_coroot() if (Rc := R(c))} # [e_r, e_s] and [e_r, f_s] with r != +/-s # We assume s is positive, as otherwise we negate @@ -1799,16 +1822,19 @@ def e_coeff(r, s): c *= -sp_sign[(b, a)] else: c *= sp_sign[(a, b)] - s_coeffs[(-r, s)] = {a: -c} - s_coeffs[(r, -s)] = {-a: c} + c = R(c) + if c: + s_coeffs[(-r, s)] = {a: -c} + s_coeffs[(r, -s)] = {-a: c} # [e_r, e_s] a = r + s if a in p_roots: # (r, s) is a special pair - c = e_coeff(r, s) * sp_sign[(r, s)] - s_coeffs[(r, s)] = {a: c} - s_coeffs[(-r, -s)] = {-a: -c} + c = R(e_coeff(r, s) * sp_sign[(r, s)]) + if c: + s_coeffs[(r, s)] = {a: c} + s_coeffs[(-r, -s)] = {-a: -c} return s_coeffs From da3d9de837ad3f62cd410ef17bac89a83dd0b599 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 10 Apr 2024 11:31:43 +0900 Subject: [PATCH 116/191] Laurent polynomials: Fixing xgcd to match gcd. Adding euclidean_degree() method. --- .../rings/polynomial/laurent_polynomial.pyx | 75 ++++++++++++++++--- .../polynomial/laurent_polynomial_ring.py | 4 +- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index a830ef7f510..5ae5dee4a9b 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1318,22 +1318,59 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): return ~self raise ArithmeticError("element is not a unit") + @coerce_binop def xgcd(self, other): - """ + r""" Extended `gcd` for univariate Laurent polynomial rings over a field. + OUTPUT: + + A triple ``(g, p, q)`` such that ``g`` is the :meth:`gcd` of + ``self`` (`= a`) and ``other`` (`= b`), and ``p`` and ``q`` are + cofactors satisfying the Bezout identity + + .. MATH:: + + g = p \cdot a + q \cdot b. + EXAMPLES:: sage: S. = LaurentPolynomialRing(QQ) - sage: (t^-2 + 1).xgcd(t^-3 + 1) - (1, 1/2*t^2 - 1/2*t^3 - 1/2*t^4, 1/2*t^3 + 1/2*t^4) + sage: a = t^-2 + 1 + sage: b = t^-3 + 1 + sage: g, p, q = a.xgcd(b); (g, p, q) + (t^-3, 1/2*t^-1 - 1/2 - 1/2*t, 1/2 + 1/2*t) + sage: g == p * a + q * b + True + sage: g == a.gcd(b) + True + sage: t.xgcd(t) + (t, 0, 1) + sage: t.xgcd(5) + (1, 0, 1/5) """ - R = self.parent() - S = R.polynomial_ring() - f, df = self.monomial_reduction() - g, dg = other.monomial_reduction() - h, p, q = f.xgcd(g) - return R(h), p / df, q / dg + cdef LaurentPolynomial_univariate elt = other + cdef LaurentPolynomial_univariate ret_gcd, ret_p, ret_q + cdef long n = min(self.__n, elt.__n) + + h, p, q = self.__u.xgcd(elt.__u) + + ret_gcd = self._new_c() + ret_gcd.__u = h + ret_gcd.__n = n + ret_gcd._normalize() + + ret_p = self._new_c() + ret_p.__u = p + ret_p.__n = n - self.__n + ret_p._normalize() + + ret_q = self._new_c() + ret_q.__u = q + ret_q.__n = n - elt.__n + ret_q._normalize() + + return (ret_gcd, ret_p, ret_q) def inverse_mod(a, m): """ @@ -1424,6 +1461,26 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): ret._normalize() return ret + def euclidean_degree(self): + r""" + Return the degree of ``self`` as an element of an Euclidean domain. + + This is the Euclidean degree of the underlying polynomial. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(QQ) + sage: (x^-5 + x^2).euclidean_degree() + 7 + + sage: R. = LaurentPolynomialRing(ZZ) + sage: (x^-5 + x^2).euclidean_degree() + Traceback (most recent call last): + ... + NotImplementedError + """ + return self.__u.euclidean_degree() + @coerce_binop def quo_rem(self, other): r""" diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring.py b/src/sage/rings/polynomial/laurent_polynomial_ring.py index 6d24de9f96f..808e897b49c 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring.py @@ -436,9 +436,7 @@ def __init__(self, R): sage: L = LaurentPolynomialRing(QQ,'x') sage: type(L) - sage: L == loads(dumps(L)) - True - + sage: TestSuite(L).run() TESTS:: From ee2ca64f0e11bb4af1526568f0cb8a279abe9a17 Mon Sep 17 00:00:00 2001 From: Nolord <33145668+Nolord@users.noreply.github.com> Date: Wed, 10 Apr 2024 10:30:26 +0200 Subject: [PATCH 117/191] verifies set partition argument before yield --- src/sage/combinat/set_partition_iterator.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/set_partition_iterator.pyx b/src/sage/combinat/set_partition_iterator.pyx index 7c9bc0eaaf5..39eb7d0d645 100644 --- a/src/sage/combinat/set_partition_iterator.pyx +++ b/src/sage/combinat/set_partition_iterator.pyx @@ -129,5 +129,6 @@ def set_partition_iterator_blocks(base_set, Py_ssize_t k): cdef Py_ssize_t n = len(base) cdef list a = list(range(n)) # TODO: implement _set_partition_block_gen as an iterative algorithm - for P in _set_partition_block_gen(n, k, a): - yield from_word( P, base) + if n >= k: + for P in _set_partition_block_gen(n, k, a): + yield from_word( P, base) From ba1c78671246676dc09776efbf770588f5b11b64 Mon Sep 17 00:00:00 2001 From: Nolord <33145668+Nolord@users.noreply.github.com> Date: Wed, 10 Apr 2024 10:34:39 +0200 Subject: [PATCH 118/191] removed if condition and error --- src/sage/combinat/set_partition.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 0c22c6a2edc..c174f49582b 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -2061,18 +2061,17 @@ def __classcall_private__(cls, s=None, part=None): pass s = frozenset(s) - if part is not None: + if part is None: + return SetPartitions_set(s) + else: if isinstance(part, (int, Integer)): - if len(s) < part: - raise ValueError("part must be <= len(set)") return SetPartitions_setn(s, part) else: part = sorted(part, reverse=True) if part not in Partitions(len(s)): raise ValueError("part must be an integer partition of %s" % len(s)) return SetPartitions_setparts(s, Partition(part)) - else: - return SetPartitions_set(s) + def __contains__(self, x): """ From 1b3afcdd857708c84a686ed5b955357c9bdcb027 Mon Sep 17 00:00:00 2001 From: Nolord <33145668+Nolord@users.noreply.github.com> Date: Wed, 10 Apr 2024 10:36:59 +0200 Subject: [PATCH 119/191] removed newline --- src/sage/combinat/set_partition.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index c174f49582b..2c3f70bfa6b 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -2071,7 +2071,6 @@ def __classcall_private__(cls, s=None, part=None): if part not in Partitions(len(s)): raise ValueError("part must be an integer partition of %s" % len(s)) return SetPartitions_setparts(s, Partition(part)) - def __contains__(self, x): """ From a0ba82f26bb09f9e92710c4faab26fdb8ec5c49e Mon Sep 17 00:00:00 2001 From: Nolord <33145668+Nolord@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:09:00 +0200 Subject: [PATCH 120/191] added example --- src/sage/combinat/set_partition.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 2c3f70bfa6b..4c0a3ec186d 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -2033,6 +2033,14 @@ class SetPartitions(UniqueRepresentation, Parent): sage: SetPartitions('aabcd').cardinality() # needs sage.libs.flint 15 + If the number of parts exceeds the length of the set, + an empty iterator is returned (:issue:`37643`):: + + sage: SetPartitions(range(3), 4).list() + [] + sage: SetPartitions('abcd', 6).list() + [] + REFERENCES: - :wikipedia:`Partition_of_a_set` From 16635e4895d3aa9132dd3e91a07288750915fb4f Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Wed, 10 Apr 2024 14:20:00 +0300 Subject: [PATCH 121/191] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstring suggestions by mkoeppe Co-authored-by: Matthias Köppe --- src/sage/matroids/basis_matroid.pyx | 2 +- src/sage/matroids/circuit_closures_matroid.pyx | 4 ++-- src/sage/matroids/circuits_matroid.pyx | 4 ++-- src/sage/matroids/flats_matroid.pyx | 2 +- src/sage/matroids/graphic_matroid.py | 2 +- src/sage/matroids/linear_matroid.pyx | 18 +++++++++--------- src/sage/matroids/matroid.pyx | 14 +++++++------- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 43ce3f24962..991017467be 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -540,7 +540,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): sage: M = BasisMatroid(matroids.catalog.Fano()) sage: sorted(M.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - sage: N = M.relabel({'a':0, 'g':'x'}) + sage: N = M.relabel({'a': 0, 'g': 'x'}) sage: from sage.matroids.utilities import cmp_elements_key sage: sorted(N.groundset(), key=cmp_elements_key) [0, 'b', 'c', 'd', 'e', 'f', 'x'] diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index 8480dd429c4..01fe81b9374 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -578,7 +578,7 @@ cdef class CircuitClosuresMatroid(Matroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -588,7 +588,7 @@ cdef class CircuitClosuresMatroid(Matroid): sage: M = CircuitClosuresMatroid(matroids.catalog.RelaxedNonFano()) sage: sorted(M.groundset()) [0, 1, 2, 3, 4, 5, 6] - sage: N = M.relabel({'g':'x', 0:'z'}) # 'g':'x' is ignored + sage: N = M.relabel({'g': 'x', 0: 'z'}) # 'g': 'x' is ignored sage: from sage.matroids.utilities import cmp_elements_key sage: sorted(N.groundset(), key=cmp_elements_key) [1, 2, 3, 4, 5, 6, 'z'] diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index b8d3b8b18c0..d5d64f07bb4 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -423,7 +423,7 @@ cdef class CircuitsMatroid(Matroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -433,7 +433,7 @@ cdef class CircuitsMatroid(Matroid): sage: M = CircuitsMatroid(matroids.catalog.RelaxedNonFano()) sage: sorted(M.groundset()) [0, 1, 2, 3, 4, 5, 6] - sage: N = M.relabel({'g':'x', 0:'z'}) # 'g':'x' is ignored + sage: N = M.relabel({'g': 'x', 0: 'z'}) # 'g': 'x' is ignored sage: from sage.matroids.utilities import cmp_elements_key sage: sorted(N.groundset(), key=cmp_elements_key) [1, 2, 3, 4, 5, 6, 'z'] diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index 23951d666f6..16ee733d902 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -320,7 +320,7 @@ cdef class FlatsMatroid(Matroid): sage: M = FlatsMatroid(matroids.catalog.RelaxedNonFano()) sage: sorted(M.groundset()) [0, 1, 2, 3, 4, 5, 6] - sage: N = M.relabel({'g':'x', 0:'z'}) # 'g':'x' is ignored + sage: N = M.relabel({'g': 'x', 0: 'z'}) # 'g': 'x' is ignored sage: from sage.matroids.utilities import cmp_elements_key sage: sorted(N.groundset(), key=cmp_elements_key) [1, 2, 3, 4, 5, 6, 'z'] diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index f1e8840f281..62614e4acbf 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -2012,7 +2012,7 @@ def relabel(self, f): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index 1fb95238100..aaff053982c 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -2983,7 +2983,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -2992,7 +2992,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): sage: M = matroids.catalog.Fano() sage: sorted(M.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - sage: N = M.relabel({'g':'x'}) + sage: N = M.relabel({'g': 'x'}) sage: sorted(N.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'x'] @@ -4084,7 +4084,7 @@ cdef class BinaryMatroid(LinearMatroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -4093,7 +4093,7 @@ cdef class BinaryMatroid(LinearMatroid): sage: M = matroids.catalog.Fano() sage: sorted(M.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - sage: N = M.relabel({'g':'x'}) + sage: N = M.relabel({'g': 'x'}) sage: sorted(N.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'x'] @@ -5014,7 +5014,7 @@ cdef class TernaryMatroid(LinearMatroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -5023,7 +5023,7 @@ cdef class TernaryMatroid(LinearMatroid): sage: M = matroids.catalog.NonFano() sage: sorted(M.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - sage: N = M.relabel({'g':'x'}) + sage: N = M.relabel({'g': 'x'}) sage: sorted(N.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'x'] @@ -5775,7 +5775,7 @@ cdef class QuaternaryMatroid(LinearMatroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -6730,7 +6730,7 @@ cdef class RegularMatroid(LinearMatroid): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -6739,7 +6739,7 @@ cdef class RegularMatroid(LinearMatroid): sage: M = matroids.catalog.R10() sage: sorted(M.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] - sage: N = M.relabel({'g':'x'}) + sage: N = M.relabel({'g': 'x'}) sage: sorted(N.groundset()) ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'x'] diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 23cfee2f9b4..67062623bb6 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -8398,15 +8398,15 @@ cdef class Matroid(SageObject): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e`; if + - ``f`` -- a python object such that ``f[e]`` is the new label of `e`; if ``e not in f`` then the identity map is assumed EXAMPLES:: - sage: M = matroids.catalog.Vamos([1,2,3,4,5,6,7,8]) - sage: M._relabel_map({1:'a', 8:'h', 9:'i'}) + sage: M = matroids.catalog.Vamos([1, 2, 3, 4, 5, 6, 7, 8]) + sage: M._relabel_map({1: 'a', 8: 'h', 9: 'i'}) {1: 'a', 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 'h'} - sage: M._relabel_map({1:2}) + sage: M._relabel_map({1: 2}) Traceback (most recent call last): ... ValueError: given map doesn't relabel the groundset properly @@ -8434,7 +8434,7 @@ cdef class Matroid(SageObject): INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``f`` -- a python object such that ``f[e]`` is the new label of `e` OUTPUT: a matroid @@ -8445,7 +8445,7 @@ cdef class Matroid(SageObject): sage: M = RankMatroid(groundset=N.groundset(), rank_function=N.rank) sage: sorted(M.groundset()) [1, 2, 3, 4, 5, 6, 7, 8] - sage: N = M.relabel({8:0}) + sage: N = M.relabel({8: 0}) sage: sorted(N.groundset()) [0, 1, 2, 3, 4, 5, 6, 7] sage: M.is_isomorphic(N) @@ -8456,7 +8456,7 @@ cdef class Matroid(SageObject): sage: from sage.matroids.rank_matroid import RankMatroid sage: N = matroids.catalog.Sp8pp() sage: M = RankMatroid(groundset=N.groundset(), rank_function=N.rank) - sage: f = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f', 7:'g', 8:'h'} + sage: f = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h'} sage: N = M.relabel(f) sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) From 5491e7bf370ffa623f7c6148414e6f418ca20591 Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Wed, 10 Apr 2024 15:08:11 +0300 Subject: [PATCH 122/191] Rename keyword to `mapping` --- src/sage/matroids/basis_matroid.pxd | 2 +- src/sage/matroids/basis_matroid.pyx | 16 +++-- .../matroids/circuit_closures_matroid.pxd | 2 +- .../matroids/circuit_closures_matroid.pyx | 13 ++-- src/sage/matroids/circuits_matroid.pxd | 2 +- src/sage/matroids/circuits_matroid.pyx | 13 ++-- src/sage/matroids/flats_matroid.pxd | 2 +- src/sage/matroids/flats_matroid.pyx | 13 ++-- src/sage/matroids/graphic_matroid.py | 13 ++-- src/sage/matroids/linear_matroid.pxd | 10 +-- src/sage/matroids/linear_matroid.pyx | 65 ++++++++++--------- src/sage/matroids/matroid.pyx | 13 ++-- 12 files changed, 88 insertions(+), 76 deletions(-) diff --git a/src/sage/matroids/basis_matroid.pxd b/src/sage/matroids/basis_matroid.pxd index 3782b51c5fa..98400ba26ca 100644 --- a/src/sage/matroids/basis_matroid.pxd +++ b/src/sage/matroids/basis_matroid.pxd @@ -25,7 +25,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): cpdef truncation(self) cpdef _extension(self, e, H) cpdef _with_coloop(self, e) - cpdef relabel(self, l) + # cpdef relabel(self, mapping) cpdef _bases_invariant(self) cpdef _bases_partition(self) diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 991017467be..1dc2ff755a3 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -79,7 +79,7 @@ from sage.matroids.basis_exchange_matroid cimport BasisExchangeMatroid from sage.matroids.set_system cimport SetSystem from sage.matroids.utilities import cmp_elements_key from cpython.object cimport Py_EQ, Py_NE - +from sage.misc.decorators import rename_keyword from itertools import combinations # class of general matroids, represented by their list of bases @@ -520,17 +520,19 @@ cdef class BasisMatroid(BasisExchangeMatroid): cdef frozenset se = frozenset([e]) return BasisMatroid(groundset=self._E + (e,), bases=[B | se for B in self.bases()]) - cpdef relabel(self, f): + @rename_keyword(deprecation=37775, l='mapping') + def relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -556,7 +558,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset()] B = [[d[y] for y in list(x)] for x in self.bases()] M = BasisMatroid(groundset=E, bases=B) diff --git a/src/sage/matroids/circuit_closures_matroid.pxd b/src/sage/matroids/circuit_closures_matroid.pxd index 446d5ca3f86..4c6ef771057 100644 --- a/src/sage/matroids/circuit_closures_matroid.pxd +++ b/src/sage/matroids/circuit_closures_matroid.pxd @@ -13,4 +13,4 @@ cdef class CircuitClosuresMatroid(Matroid): cpdef _circuit(self, F) cpdef circuit_closures(self) cpdef _is_isomorphic(self, other, certificate=*) - cpdef relabel(self, f) + cpdef relabel(self, mapping) diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index 01fe81b9374..eced2f7ce35 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -568,17 +568,18 @@ cdef class CircuitClosuresMatroid(Matroid): version = 0 return sage.matroids.unpickling.unpickle_circuit_closures_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -604,7 +605,7 @@ cdef class CircuitClosuresMatroid(Matroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset()] CC = {} for i in self.circuit_closures(): diff --git a/src/sage/matroids/circuits_matroid.pxd b/src/sage/matroids/circuits_matroid.pxd index b8995b08ef4..f495a1eff81 100644 --- a/src/sage/matroids/circuits_matroid.pxd +++ b/src/sage/matroids/circuits_matroid.pxd @@ -26,7 +26,7 @@ cdef class CircuitsMatroid(Matroid): # isomorphism and relabeling cpdef _is_isomorphic(self, other, certificate=*) - cpdef relabel(self, f) + cpdef relabel(self, mapping) # verification cpdef is_valid(self) diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index d5d64f07bb4..455a4d8464a 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -413,17 +413,18 @@ cdef class CircuitsMatroid(Matroid): version = 0 return sage.matroids.unpickling.unpickle_circuits_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -449,7 +450,7 @@ cdef class CircuitsMatroid(Matroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self._groundset] C = [] for i in self._k_C: diff --git a/src/sage/matroids/flats_matroid.pxd b/src/sage/matroids/flats_matroid.pxd index 026c934a185..440dac7012c 100644 --- a/src/sage/matroids/flats_matroid.pxd +++ b/src/sage/matroids/flats_matroid.pxd @@ -15,7 +15,7 @@ cdef class FlatsMatroid(Matroid): # isomorphism and relabeling cpdef _is_isomorphic(self, other, certificate=*) - cpdef relabel(self, f) + cpdef relabel(self, mapping) # verification cpdef is_valid(self) diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index 16ee733d902..1d736eddfe7 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -300,17 +300,18 @@ cdef class FlatsMatroid(Matroid): version = 0 return sage.matroids.unpickling.unpickle_flats_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that `f[e]` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -336,7 +337,7 @@ cdef class FlatsMatroid(Matroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self._groundset] F = {} for i in self._F: diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 62614e4acbf..8d7fdd89757 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -2002,17 +2002,18 @@ def regular_matroid(self): X = [l for u, v, l in self._G.edge_iterator()] return ConstructorMatroid(groundset=X, graph=self._G, regular=True) - def relabel(self, f): + def relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -2035,7 +2036,7 @@ def relabel(self, f): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset()] M = GraphicMatroid(self.graph(), groundset=E) return M diff --git a/src/sage/matroids/linear_matroid.pxd b/src/sage/matroids/linear_matroid.pxd index 89e9580024e..76027b61a9f 100644 --- a/src/sage/matroids/linear_matroid.pxd +++ b/src/sage/matroids/linear_matroid.pxd @@ -28,7 +28,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): cpdef is_field_isomorphism(self, other, morphism) # cpdef is_field_isomorphic(self, other) # TODO: currently only works as ``def`` cpdef _fast_isom_test(self, other) - cpdef relabel(self, f) + cpdef relabel(self, mapping) cpdef _minor(self, contractions, deletions) cpdef dual(self) @@ -89,7 +89,7 @@ cdef class BinaryMatroid(LinearMatroid): cpdef BinaryMatrix _projection(self) cpdef BinaryMatrix _projection_partition(self) cpdef _fast_isom_test(self, other) - cpdef relabel(self, f) + cpdef relabel(self, mapping) cpdef is_graphic(self) cpdef is_valid(self) @@ -120,7 +120,7 @@ cdef class TernaryMatroid(LinearMatroid): cpdef _principal_quadripartition(self) cpdef TernaryMatrix _projection(self) cpdef _fast_isom_test(self, other) - cpdef relabel(self, f) + cpdef relabel(self, mapping) cpdef is_valid(self) @@ -147,7 +147,7 @@ cdef class QuaternaryMatroid(LinearMatroid): cpdef bicycle_dimension(self) cpdef _principal_tripartition(self) cpdef _fast_isom_test(self, other) - cpdef relabel(self, f) + cpdef relabel(self, mapping) cpdef is_valid(self) @@ -163,7 +163,7 @@ cdef class RegularMatroid(LinearMatroid): cpdef _invariant(self) cpdef _fast_isom_test(self, other) - cpdef relabel(self, f) + cpdef relabel(self, mapping) cpdef bases_count(self) cpdef _projection(self) diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index aaff053982c..80795c5272a 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -2973,17 +2973,18 @@ cdef class LinearMatroid(BasisExchangeMatroid): data = (A, gs, reduced, self.get_custom_name()) return sage.matroids.unpickling.unpickle_linear_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -3004,7 +3005,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset_list()] M = LinearMatroid(groundset=E, matrix=self._matrix_()) return M @@ -4074,17 +4075,18 @@ cdef class BinaryMatroid(LinearMatroid): data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_binary_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -4105,7 +4107,7 @@ cdef class BinaryMatroid(LinearMatroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset_list()] M = BinaryMatroid(groundset=E, matrix=self._matrix_()) return M @@ -5004,17 +5006,18 @@ cdef class TernaryMatroid(LinearMatroid): data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_ternary_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -5035,7 +5038,7 @@ cdef class TernaryMatroid(LinearMatroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset_list()] M = TernaryMatroid(groundset=E, matrix=self._matrix_()) return M @@ -5765,17 +5768,18 @@ cdef class QuaternaryMatroid(LinearMatroid): data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_quaternary_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -5796,7 +5800,7 @@ cdef class QuaternaryMatroid(LinearMatroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset_list()] M = QuaternaryMatroid(groundset=E, matrix=self._matrix_()) return M @@ -6720,17 +6724,18 @@ cdef class RegularMatroid(LinearMatroid): data = (A, gs, reduced, self.get_custom_name()) return sage.matroids.unpickling.unpickle_regular_matroid, (version, data) - cpdef relabel(self, f): + cpdef relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -6751,7 +6756,7 @@ cdef class RegularMatroid(LinearMatroid): sage: for S in powerset(M.groundset()): ....: assert M.rank(S) == N.rank([M._relabel_map(f)[x] for x in S]) """ - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset_list()] M = RegularMatroid(groundset=E, matrix=self._matrix_()) return M diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 67062623bb6..3529d5bc5b9 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -8424,17 +8424,18 @@ cdef class Matroid(SageObject): raise ValueError("given map doesn't relabel the groundset properly") return d - def relabel(self, f): + def relabel(self, mapping): r""" Return an isomorphic matroid with relabeled groundset. - The output is obtained by relabeling each element ``e`` by ``f[e]``, - where ``f`` is a given injective map. If ``e not in f`` then the - identity map is assumed. + The output is obtained by relabeling each element ``e`` by + ``mapping[e]``, where ``mapping`` is a given injective map. If + ``mapping[e]`` is not defined, then the identity map is assumed. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e` + - ``mapping`` -- a python object such that `mapping[e]` is the new + label of `e` OUTPUT: a matroid @@ -8462,7 +8463,7 @@ cdef class Matroid(SageObject): ....: assert M.rank(S) == N.rank([f[x] for x in S]) """ from sage.matroids.rank_matroid import RankMatroid - d = self._relabel_map(f) + d = self._relabel_map(mapping) E = [d[x] for x in self.groundset()] def f_relabel(X): From 39fc350c4d2c6e3dd7cb9ca40f4666842539268a Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Wed, 10 Apr 2024 15:53:45 +0300 Subject: [PATCH 123/191] Remove `groundset=...` redundancies --- src/sage/matroids/database_matroids.py | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sage/matroids/database_matroids.py b/src/sage/matroids/database_matroids.py index 2e937874b06..3ab8e0c7816 100644 --- a/src/sage/matroids/database_matroids.py +++ b/src/sage/matroids/database_matroids.py @@ -314,7 +314,7 @@ def P6(groundset=None): [Oxl2011]_, p. 641-2. """ CC = {2: ['abc'], 3: ['abcdef']} - M = Matroid(groundset='abcdef', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "P6", groundset) return M @@ -724,7 +724,7 @@ def AG32prime(groundset=None): ], 4: ['abcdefgh'], } - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "AG(3, 2)'", groundset) return M @@ -824,7 +824,7 @@ def F8(groundset=None): ], 4: ['abcdefgh'], } - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "F8", groundset) return M @@ -873,7 +873,7 @@ def Q8(groundset=None): ], 4: ['abcdefgh'], } - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "Q8", groundset) return M @@ -920,7 +920,7 @@ def L8(groundset=None): """ CC = {3: ['abfg', 'bcdg', 'defg', 'cdeh', 'aefh', 'abch', 'aceg', 'bdfh'], 4: ['abcdefgh']} - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "L8", groundset) return M @@ -1009,7 +1009,7 @@ def Vamos(groundset=None): [Oxl2011]_, p. 649. """ CC = {3: ['abcd', 'abef', 'cdef', 'abgh', 'efgh'], 4: ['abcdefgh']} - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "Vamos", groundset) return M @@ -1160,7 +1160,7 @@ def P8pp(groundset=None): [Oxl2011]_, p. 651. """ NSC = ['abfh', 'bceg', 'cdfh', 'adeg', 'acef', 'bdfg', 'acgh', 'bdeh'] - M = Matroid(groundset='abcdefgh', rank=4, nonspanning_circuits=NSC) + M = Matroid(rank=4, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "P8''", groundset) return M @@ -1410,7 +1410,7 @@ def Pappus(groundset=None): [Oxl2011]_, p. 655. """ NSC = ['abc', 'def', 'ceg', 'bfg', 'cdh', 'afh', 'bdi', 'aei', 'ghi'] - M = Matroid(groundset='abcdefghi', rank=3, nonspanning_circuits=NSC) + M = Matroid(rank=3, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "Pappus", groundset) return M @@ -1444,7 +1444,7 @@ def NonPappus(groundset=None): [Oxl2011]_, p. 655. """ NSC = ['abc', 'ceg', 'bfg', 'cdh', 'afh', 'bdi', 'aei', 'ghi'] - M = Matroid(groundset='abcdefghi', rank=3, nonspanning_circuits=NSC) + M = Matroid(rank=3, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "NonPappus", groundset) return M @@ -2239,7 +2239,7 @@ def Spike(r, t=True, C3=[], groundset=None): planes = [['t', 'x'+str(i), 'y'+str(i), 'x'+str(j), 'y'+str(j)] for i in range(1, r+1) for j in range(i+1, r+1)] CC = {2: lines, 3: planes, r: [E]} - M = Matroid(groundset=E, circuit_closures=CC) + M = Matroid(circuit_closures=CC) else: for S in C3: for xy in S: @@ -2261,7 +2261,7 @@ def Spike(r, t=True, C3=[], groundset=None): for j in range(i+1, r+1): NSC += [['x'+str(i), 'y'+str(i), 'x'+str(j), 'y'+str(j)]] - M = Matroid(groundset=E, rank=r, nonspanning_circuits=NSC) + M = Matroid(rank=r, nonspanning_circuits=NSC) free = "Free " if C3 == [] else "" tip = "" if t else "\\t" @@ -2343,7 +2343,7 @@ def Theta(n, groundset=None): Yu = [Y[i] for i in range(len(Y)) if i != u] C += [Yu + ['x'+str(s)] + ['x'+str(t)]] - M = Matroid(groundset=E, circuits=C) + M = Matroid(circuits=C) M = _rename_and_relabel(M, "Theta_" + str(n), groundset) return M @@ -4715,7 +4715,7 @@ def NonVamos(groundset=None): 3: ['abcd', 'abef', 'cdef', 'abgh', 'cdgh', 'efgh'], 4: ['abcdefgh'] } - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "NonVamos", groundset) return M @@ -4773,7 +4773,7 @@ class of near-regular matroids. """ CC = {2: ['abc', 'ceh', 'fgh', 'adf', 'aeg', 'cdg', 'bdh', 'bef'], 3: ['abcdefgh']} - M = Matroid(groundset='abcdefgh', circuit_closures=CC) + M = Matroid(circuit_closures=CC) M = _rename_and_relabel(M, "AG23minus", groundset) return M @@ -4823,7 +4823,7 @@ def R9A(groundset=None): """ NSC = ['abch', 'abde', 'abfi', 'acdi', 'aceg', 'adgh', 'aefh', 'bcdf', 'bdhi', 'begi', 'cehi', 'defi', 'fghi'] - M = Matroid(groundset='abcdefghi', rank=4, nonspanning_circuits=NSC) + M = Matroid(rank=4, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "R9A", groundset) return M @@ -4846,7 +4846,7 @@ def R9B(groundset=None): """ NSC = ['abde', 'bcdf', 'aceg', 'abch', 'befh', 'cdgh', 'bcei', 'adfi', 'abgi', 'degi', 'bdhi', 'aehi', 'fghi'] - M = Matroid(groundset='abcdefghi', rank=4, nonspanning_circuits=NSC) + M = Matroid(rank=4, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "R9B", groundset) return M @@ -4870,7 +4870,7 @@ def Block_9_4(groundset=None): NSC = ['abcd', 'acef', 'bdef', 'cdeg', 'abfg', 'adeh', 'bcfh', 'acgh', 'begh', 'dfgh', 'abei', 'cdfi', 'bcgi', 'adgi', 'efgi', 'bdhi', 'cehi', 'afhi'] - M = Matroid(groundset='abcdefghi', rank=4, nonspanning_circuits=NSC) + M = Matroid(rank=4, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "Block(9, 4)", groundset) return M @@ -4895,7 +4895,7 @@ def TicTacToe(groundset=None): """ NSC = ['abcdg', 'adefg', 'abceh', 'abcfi', 'cdefi', 'adghi', 'beghi', 'cfghi'] - M = Matroid(groundset='abcdefghi', rank=5, nonspanning_circuits=NSC) + M = Matroid(rank=5, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "TicTacToe", groundset) return M @@ -4953,7 +4953,7 @@ def Block_10_5(groundset=None): 'cdegj', 'bcfgj', 'acdhj', 'bcehj', 'defhj', 'bdghj', 'afghj', 'abcij', 'bdeij', 'cdfij', 'adgij', 'efgij', 'aehij', 'bfhij', 'cghij'] - M = Matroid(groundset='abcdefghij', rank=5, nonspanning_circuits=NSC) + M = Matroid(rank=5, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "Block(10, 5)", groundset) return M @@ -5021,7 +5021,7 @@ def BetsyRoss(groundset=None): NSC = ['acf', 'acg', 'adi', 'adj', 'afg', 'ahk', 'aij', 'bdg', 'bdh', 'bef', 'bej', 'bfj', 'bgh', 'bik', 'ceh', 'cei', 'cfg', 'chi', 'cjk', 'dfk', 'dgh', 'dij', 'efj', 'egk', 'ehi'] - M = Matroid(groundset='abcdefghijk', rank=3, nonspanning_circuits=NSC) + M = Matroid(rank=3, nonspanning_circuits=NSC) M = _rename_and_relabel(M, "BetsyRoss", groundset) return M From 6cf17196f55df5ddc78517cf93a4f33893fa3c26 Mon Sep 17 00:00:00 2001 From: Jackson Walters Date: Thu, 4 Apr 2024 14:54:21 -0400 Subject: [PATCH 124/191] dft for symmetric group algebra when p|n The DFT for the SGA throws a ZeroDivisionError p|n. Uses the idempotents as computed in [Murphy '83] to build the Pierce decomposition of the group algebra over a finite field. The "modular" Fourier transform is the homomorphic projection onto each block via v |--> v*e_i. This change of basis matrix is the modular Fourier transform, and works even when p|n. Co-Authored-By: Travis Scrimshaw --- src/sage/combinat/symmetric_group_algebra.py | 58 ++++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index b0214063e3b..3b7673a5425 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -1885,10 +1885,15 @@ def seminormal_basis(self, mult='l2r'): basis.append(self.epsilon_ik(t1, t2, mult=mult)) return basis - def dft(self, form="seminormal", mult='l2r'): - """ + def dft(self, form=None, mult='l2r'): + r""" Return the discrete Fourier transform for ``self``. + See [Mur1983]_ for the construction of central primitive orthogonal idempotents. + For each idempotent `e_i` we have a homomorphic projection `v \mapsto v e_i`. + Choose a basis for each submodule spanned by `\{\sigma e_i | \sigma \in S_n\}`. + The change-of-basis from the standard basis `\{\sigma\}_\sigma` is returned. + INPUT: - ``mult`` -- string (default: `l2r`). If set to `r2l`, @@ -1906,15 +1911,32 @@ def dft(self, form="seminormal", mult='l2r'): [ 0 1 0 -1 1 -1] [ 1 -1/2 1 -1/2 -1/2 -1/2] [ 1 -1 -1 1 1 -1] + + Over fields of characteristic `p > 0` such that `p \mid n!`, we use the + modular Fourier transform (:issue:`37751`):: + + sage: GF2S3 = SymmetricGroupAlgebra(GF(2), 3) + sage: GF2S3.dft() + [1 0 0 0 1 0] + [0 1 0 0 0 1] + [0 0 1 0 0 1] + [0 0 0 1 1 0] + [1 0 0 1 1 0] + [0 1 1 0 0 1] """ + if form is None: + form = "modular" if self.base_ring().characteristic().divides(self.group().cardinality()) else "seminormal" if form == "seminormal": + if self.base_ring().characteristic().divides(self.group().cardinality()): + raise ValueError("seminormal does not work when p | n!") return self._dft_seminormal(mult=mult) - else: - raise ValueError("invalid form (= %s)" % form) + if form == "modular": + return self._dft_modular() + raise ValueError("invalid form (= %s)" % form) def _dft_seminormal(self, mult='l2r'): """ - Return the seminormal form of the discrete Fourier for ``self``. + Return the seminormal form of the discrete Fourier transform for ``self``. INPUT: @@ -1941,6 +1963,32 @@ def _dft_seminormal(self, mult='l2r'): snb = self.seminormal_basis(mult=mult) return matrix([vector(b) for b in snb]).inverse().transpose() + def _dft_modular(self): + r""" + Return the discrete Fourier transform when the characteristic divides the order of the group. + + EXAMPLES:: + + sage: GF3S3 = SymmetricGroupAlgebra(GF(3), 3) + sage: GF3S3._dft_modular() + [1 0 0 0 0 0] + [0 1 0 0 0 0] + [0 0 1 0 0 0] + [0 0 0 1 0 0] + [0 0 0 0 1 0] + [0 0 0 0 0 1] + """ + idempotents = self.central_orthogonal_idempotents() + # project v onto each block U_i = F_p[S_n]*e_i via \pi_i: v |--> v*e_i + B = self.basis() + blocks = [self.submodule([b * idem for b in B]) for idem in idempotents] + # compute the list of basis vectors lifted to the SGA from each block + block_decomposition_basis = [u.lift() for block in blocks for u in block.basis()] + # construct the matrix to the standard basis in the order given by the group + G = self.group() + mat = [[b[g] for b in block_decomposition_basis] for g in G] + return matrix(self.base_ring(), mat) + def epsilon_ik(self, itab, ktab, star=0, mult='l2r'): r""" Return the seminormal basis element of ``self`` corresponding to the From 6c9ff6c85448419ce878ded626e38d32fb365fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 Apr 2024 20:57:07 +0200 Subject: [PATCH 125/191] various changes about is_field and is_ring --- src/sage/combinat/descent_algebra.py | 83 ++++++++----------- src/sage/geometry/polyhedron/parent.py | 12 ++- src/sage/modular/pollack_stevens/dist.pyx | 26 +++--- .../modular/pollack_stevens/distributions.py | 40 ++++----- src/sage/modular/ssmod/ssmod.py | 15 ++-- .../polynomes_doctest.py | 2 +- src/sage/topology/simplicial_complex.py | 44 +++++----- 7 files changed, 105 insertions(+), 117 deletions(-) diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index bb7db9e326e..3cc463b54bb 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -13,25 +13,26 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.misc.cachefunc import cached_method -from sage.misc.bindable_class import BindableClass -from sage.misc.lazy_attribute import lazy_attribute -from sage.structure.parent import Parent -from sage.structure.unique_representation import UniqueRepresentation +from sage.arith.misc import factorial from sage.categories.algebras import Algebras from sage.categories.commutative_rings import CommutativeRings -from sage.categories.realizations import Realizations, Category_realization_of_parent +from sage.categories.fields import Fields from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.arith.misc import factorial -from sage.combinat.free_module import CombinatorialFreeModule -from sage.combinat.permutation import Permutations +from sage.categories.realizations import Realizations, Category_realization_of_parent from sage.combinat.composition import Compositions +from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.integer_matrices import IntegerMatrices +from sage.combinat.ncsf_qsym.ncsf import NonCommutativeSymmetricFunctions +from sage.combinat.permutation import Permutations from sage.combinat.subset import SubsetsSorted from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra -from sage.combinat.ncsf_qsym.ncsf import NonCommutativeSymmetricFunctions +from sage.misc.bindable_class import BindableClass +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation class DescentAlgebra(UniqueRepresentation, Parent): @@ -134,9 +135,30 @@ def __init__(self, R, n): EXAMPLES:: sage: TestSuite(DescentAlgebra(QQ, 4)).run() + + TESTS:: + + sage: B = DescentAlgebra(QQ, 4).B() + sage: B.is_commutative() + False + sage: B = DescentAlgebra(QQ, 1).B() + sage: B.is_commutative() + True + + sage: B = DescentAlgebra(QQ, 4).B() + sage: B.is_field() + False + sage: B = DescentAlgebra(QQ, 1).B() + sage: B.is_field() + True """ self._n = n - self._category = FiniteDimensionalAlgebrasWithBasis(R) + cat = FiniteDimensionalAlgebrasWithBasis(R) + if R in CommutativeRings() and n <= 2: + cat = cat.Commutative() + if R in Fields() and n <= 1: + cat &= Fields() + self._category = cat Parent.__init__(self, base=R, category=self._category.WithRealizations()) def _repr_(self): @@ -838,7 +860,7 @@ def __init__(self, base): """ Category_realization_of_parent.__init__(self, base) - def _repr_(self): + def _repr_(self) -> str: r""" Return the representation of ``self``. @@ -913,39 +935,6 @@ def __getitem__(self, p): p = [p] return self.monomial(C(p)) - def is_field(self, proof=True): - """ - Return whether this descent algebra is a field. - - EXAMPLES:: - - sage: B = DescentAlgebra(QQ, 4).B() - sage: B.is_field() - False - sage: B = DescentAlgebra(QQ, 1).B() - sage: B.is_field() - True - """ - if self.realization_of()._n <= 1: - return self.base_ring().is_field() - return False - - def is_commutative(self) -> bool: - """ - Return whether this descent algebra is commutative. - - EXAMPLES:: - - sage: B = DescentAlgebra(QQ, 4).B() - sage: B.is_commutative() - False - sage: B = DescentAlgebra(QQ, 1).B() - sage: B.is_commutative() - True - """ - return (self.base_ring() in CommutativeRings() - and self.realization_of()._n <= 2) - @lazy_attribute def to_symmetric_group_algebra(self): """ diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 2d87ac6f202..7dafad76437 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -480,9 +480,8 @@ def Vrepresentation_space(self): if self.base_ring() in Fields(): from sage.modules.free_module import VectorSpace return VectorSpace(self.base_ring(), self.ambient_dim()) - else: - from sage.modules.free_module import FreeModule - return FreeModule(self.base_ring(), self.ambient_dim()) + from sage.modules.free_module import FreeModule + return FreeModule(self.base_ring(), self.ambient_dim()) ambient_space = Vrepresentation_space @@ -521,7 +520,6 @@ def _repr_base_ring(self): sage: Polyhedra(K, 4)._repr_base_ring() # needs sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)' """ - if self.base_ring() is ZZ: return 'ZZ' if self.base_ring() is QQ: @@ -535,9 +533,9 @@ def _repr_base_ring(self): else: if self.base_ring() is AA: return 'AA' - return '({0})'.format(self.base_ring()) + return f'({self.base_ring()})' - def _repr_ambient_module(self): + def _repr_ambient_module(self) -> str: """ Return an abbreviated string representation of the ambient space. @@ -885,7 +883,7 @@ def _coerce_base_ring(self, other): from sage.structure.element import Element if isinstance(other, Element): other = other.parent() - if hasattr(other, "is_ring") and other.is_ring(): + if other in Rings(): other_ring = other else: try: diff --git a/src/sage/modular/pollack_stevens/dist.pyx b/src/sage/modular/pollack_stevens/dist.pyx index 1f79133f2f5..cd1ce2a722f 100644 --- a/src/sage/modular/pollack_stevens/dist.pyx +++ b/src/sage/modular/pollack_stevens/dist.pyx @@ -26,26 +26,26 @@ REFERENCES: # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** +import operator -from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.power_series_ring import PowerSeriesRing -from sage.rings.finite_rings.integer_mod_ring import Zmod from sage.arith.misc import binomial, bernoulli -from sage.matrix.matrix cimport Matrix +from sage.categories.fields import Fields from sage.matrix.constructor import matrix -from sage.structure.element cimport Element -import operator -from sage.rings.padics.padic_generic import pAdicGeneric -from sage.rings.integer cimport Integer +from sage.matrix.matrix cimport Matrix from sage.misc.verbose import verbose +from sage.modular.pollack_stevens.sigma0 import Sigma0 +from sage.rings.finite_rings.integer_mod_ring import Zmod from sage.rings.infinity import Infinity +from sage.rings.integer cimport Integer +from sage.rings.integer_ring import ZZ +from sage.rings.padics.padic_generic import pAdicGeneric +from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.rational_field import QQ +from sage.structure.element cimport Element +from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool #from sage.libs.flint.ulong_extras cimport * -from sage.modular.pollack_stevens.sigma0 import Sigma0 - cdef long overflow = 1 << (4 * sizeof(long) - 1) cdef long underflow = -overflow cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) - 1 @@ -1167,7 +1167,7 @@ cdef class Dist_vector(Dist): p = self.parent().prime() cdef Dist_vector ans if p == 0: - if R.is_field(): + if R in Fields(): ans = self._new_c() ans.ordp = 0 ans._moments = V(v) diff --git a/src/sage/modular/pollack_stevens/distributions.py b/src/sage/modular/pollack_stevens/distributions.py index f33b4022842..422f319ed6e 100644 --- a/src/sage/modular/pollack_stevens/distributions.py +++ b/src/sage/modular/pollack_stevens/distributions.py @@ -31,32 +31,31 @@ (1 + O(11^5), 2 + O(11^4), 3 + O(11^3), 4 + O(11^2), 5 + O(11)) """ -# **************************************************************************** +# ************************************************************************* # Copyright (C) 2012 Robert Pollack # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ -# **************************************************************************** +# ************************************************************************* +from sage.categories.fields import Fields +from sage.categories.modules import Modules +from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import lazy_import from sage.modules.module import Module -from sage.structure.parent import Parent -from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ -from sage.misc.cachefunc import cached_method -from sage.categories.modules import Modules -from sage.structure.factory import UniqueFactory - +from sage.rings.rational_field import QQ from sage.rings.ring import Ring +from sage.structure.factory import UniqueFactory +from sage.structure.parent import Parent +from .sigma0 import _default_adjuster lazy_import('sage.modular.pollack_stevens.dist', 'get_dist_classes') lazy_import('sage.rings.padics.factory', ['ZpCA', 'QpCR']) lazy_import('sage.rings.padics.padic_generic', 'pAdicGeneric') -from .sigma0 import _default_adjuster - class OverconvergentDistributions_factory(UniqueFactory): """ @@ -283,7 +282,7 @@ def __init__(self, k, p=None, prec_cap=None, base=None, character=None, """ if not isinstance(base, Ring): raise TypeError("base must be a ring") - #from sage.rings.padics.pow_computer import PowComputer + # from sage.rings.padics.pow_computer import PowComputer # should eventually be the PowComputer on ZpCA once that uses longs. Dist, WeightKAction = get_dist_classes(p, prec_cap, base, self.is_symk(), implementation) @@ -317,9 +316,9 @@ def _element_constructor_(self, val, **kwargs): sage: v = V([1,2,3,4,5,6,7]); v (1, 2, 3, 4, 5, 6, 7) """ - ordp = kwargs.get('ord',0) - check = kwargs.get('check',True) - normalize = kwargs.get('normalize',True) + ordp = kwargs.get('ord', 0) + check = kwargs.get('check', True) + normalize = kwargs.get('normalize', True) return self.Element(val, self, ordp, check, normalize) def _coerce_map_from_(self, other): @@ -409,13 +408,14 @@ def prime(self): def weight(self): """ - Return the weight of this distribution space. The standard - caveat applies, namely that the weight of `Sym^k` is - defined to be `k`, not `k+2`. + Return the weight of this distribution space. + + The standard caveat applies, namely that the weight of `Sym^k` + is defined to be `k`, not `k+2`. OUTPUT: - - nonnegative integer + nonnegative integer EXAMPLES:: @@ -472,7 +472,7 @@ def lift(self, p=None, M=None, new_base_ring=None): """ if self._character is not None: if self._character.base_ring() != QQ: - # need to change coefficient ring for character + # need to change coefficient ring for character raise NotImplementedError if M is None: M = self._prec_cap + 1 @@ -689,7 +689,7 @@ def _repr_(self): elif self.base_ring() is ZZ: V = 'Z^2' elif isinstance(self.base_ring(), pAdicGeneric) and self.base_ring().degree() == 1: - if self.base_ring().is_field(): + if self.base_ring() in Fields(): V = 'Q_%s^2' % self._p else: V = 'Z_%s^2' % self._p diff --git a/src/sage/modular/ssmod/ssmod.py b/src/sage/modular/ssmod/ssmod.py index d2d2d717cbc..550e0e29ec4 100644 --- a/src/sage/modular/ssmod/ssmod.py +++ b/src/sage/modular/ssmod/ssmod.py @@ -69,6 +69,7 @@ # **************************************************************************** from sage.arith.misc import kronecker, next_prime +from sage.categories.fields import Fields from sage.matrix.matrix_space import MatrixSpace from sage.misc.lazy_import import lazy_import from sage.modular.arithgroup.all import Gamma0 @@ -333,7 +334,7 @@ def supersingular_j(FF): - Iftikhar Burhanuddin -- burhanud@usc.edu """ - if not FF.is_field() or not FF.is_finite(): + if FF not in Fields().Finite(): raise ValueError("%s is not a finite field" % FF) prime = FF.characteristic() if not Integer(prime).is_prime(): @@ -417,7 +418,7 @@ def __init__(self, prime=2, level=1, base_ring=ZZ): HeckeModule_free_module.__init__(self, base_ring, prime * level, weight=2) - def _repr_(self): + def _repr_(self) -> str: """ String representation of self. @@ -429,7 +430,7 @@ def _repr_(self): return "Module of supersingular points on X_0(%s)/F_%s over %s" % ( self.__level, self.__prime, self.base_ring()) - def __richcmp__(self, other, op): + def __richcmp__(self, other, op) -> bool: r""" Compare ``self`` to ``other``. @@ -675,7 +676,7 @@ def supersingular_points(self): dim = dimension_supersingular_module(prime, level) - pos = int(0) + pos = 0 # using list to keep track of explored nodes using pos ss_points = [jinv] @@ -697,7 +698,7 @@ def supersingular_points(self): # root finding (??) neighbors = Phi2_quad(X, ss_points[j_prev], ss_points[pos]).roots() - for (xj, ej) in neighbors: + for xj, ej in neighbors: if xj not in ss_points_dic: j = len(ss_points) ss_points += [xj] @@ -710,7 +711,7 @@ def supersingular_points(self): if pos != 0: # also record the root from j_prev T2_matrix[pos, j_prev] += 1 - pos += int(1) + pos += 1 self.__hecke_matrices[2] = T2_matrix return (ss_points, ss_points_dic) @@ -836,7 +837,7 @@ def hecke_matrix(self, L): Fp2 = self.__finite_field h = len(SS) R = self.base_ring() - T_L = MatrixSpace(R, h)(0) + T_L = MatrixSpace(R, h).zero() S, X = Fp2['x'].objgen() for i in range(len(SS)): diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/polynomes_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/polynomes_doctest.py index 5ac636c433a..86ab2edd193 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/polynomes_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/polynomes_doctest.py @@ -97,7 +97,7 @@ Sage example in ./polynomes.tex, line 551:: sage: A = QQ['x'] - sage: A.is_ring() and A.is_noetherian() + sage: A in Rings() and A.is_noetherian() True Sage example in ./polynomes.tex, line 559:: diff --git a/src/sage/topology/simplicial_complex.py b/src/sage/topology/simplicial_complex.py index aba3289607e..f7870435782 100644 --- a/src/sage/topology/simplicial_complex.py +++ b/src/sage/topology/simplicial_complex.py @@ -159,22 +159,24 @@ # cohomology: compute cup products (and Massey products?) from copy import copy -from sage.misc.lazy_import import lazy_import -from sage.misc.cachefunc import cached_method +from itertools import combinations, chain +from functools import total_ordering + from .cell_complex import GenericCellComplex -from sage.structure.sage_object import SageObject -from sage.structure.parent import Parent +from sage.categories.fields import Fields +from sage.misc.cachefunc import cached_method +from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import +from sage.misc.superseded import deprecation from sage.rings.integer import Integer -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.polynomial.polynomial_ring import polygens -from sage.sets.set import Set from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring import polygens +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import QQ +from sage.sets.set import Set from sage.structure.category_object import normalize_names -from sage.misc.latex import latex -from sage.misc.superseded import deprecation -from functools import total_ordering -from itertools import combinations, chain +from sage.structure.parent import Parent +from sage.structure.sage_object import SageObject lazy_import('sage.categories.simplicial_complexes', 'SimplicialComplexes') lazy_import('sage.matrix.constructor', 'matrix') @@ -321,10 +323,7 @@ def rename_vertex(n, keep, left=True): try: return lookup[n] except KeyError: - if left: - return "L" + str(n) - else: - return "R" + str(n) + return ("L" + str(n)) if left else ("R" + str(n)) @total_ordering @@ -644,7 +643,7 @@ def product(self, other, rename_vertices=True): answer = [] for x in lattice_paths(self.tuple(), other.tuple()): - new = tuple(["L" + str(v) + "R" + str(w) for (v, w) in x]) + new = tuple(["L" + str(v) + "R" + str(w) for v, w in x]) answer.append(Simplex(new)) return answer @@ -2435,10 +2434,10 @@ def _homology_(self, dim=None, base_ring=ZZ, subcomplex=None, if H_with_gens: chains = self.n_chains(i, base_ring=base_ring) new_H = [] - for (H, gen) in H_with_gens: + for H, gen in H_with_gens: v = gen.vector(i) new_gen = chains.zero() - for (coeff, chaine) in zip(v, chains.gens()): + for coeff, chaine in zip(v, chains.gens()): new_gen += coeff * chaine new_H.append((H, new_gen)) answer[i] = new_H @@ -2450,7 +2449,7 @@ def _homology_(self, dim=None, base_ring=ZZ, subcomplex=None, # Fix non-reduced answer. if subcomplex is None and not reduced and 0 in dim: try: - if base_ring.is_field(): + if base_ring in Fields(): rank = answer[0].dimension() else: rank = len(answer[0].invariants()) @@ -3076,7 +3075,7 @@ def is_cohen_macaulay(self, base_ring=QQ, ncpus=0): def all_homologies_vanish(F): S = self.link(F) H = S.homology(base_ring=base_ring) - if base_ring.is_field(): + if base_ring in Fields(): return all(H[j].dimension() == 0 for j in range(S.dimension())) else: return not any(H[j].invariants() for j in range(S.dimension())) @@ -4998,7 +4997,7 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ, verbose=False): """ if b % 2: return ZZ.zero() - if a == 0 and b == 0: + if a == 0 == b: return ZZ.one() if base_ring in self._bbn and not verbose: if base_ring in self._bbn_all_computed: @@ -5049,7 +5048,7 @@ def is_golod(self) -> bool: sage: Y.is_golod() True """ - H = [a+b for (a, b) in self.bigraded_betti_numbers()] + H = [a+b for a, b in self.bigraded_betti_numbers()] if 0 in H: H.remove(0) @@ -5121,6 +5120,7 @@ def moment_angle_complex(self): from .moment_angle_complex import MomentAngleComplex return MomentAngleComplex(self) + # Miscellaneous utility functions. # The following two functions can be used to generate the facets for From 19d6ce3ba6c61785ac35f21695a1ce696c786494 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 11 Apr 2024 12:39:49 +0900 Subject: [PATCH 126/191] Speed up symmetric group simple_module_rank(). --- src/sage/combinat/specht_module.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index 127903829f7..260a3fbde43 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -1351,12 +1351,12 @@ def tabloid_gram_matrix(la, base_ring): [4 1 1 2 4] """ from sage.combinat.tableau import StandardTableaux - ST = StandardTableaux(la) + ST = list(StandardTableaux(la)) def bilinear_form(p1, p2): if len(p2) < len(p1): p1, p2 = p2, p1 - return sum(c1 * p2.get(T1, 0) for T1, c1 in p1.items() if c1) + return sum(c1 * p2[T1] for T1, c1 in p1.items() if c1 and T1 in p2) PT = {T: polytabloid(T) for T in ST} gram_matrix = [[bilinear_form(PT[T1], PT[T2]) for T1 in ST] for T2 in ST] From f87b6fdd845ea8a36220634fbd01709ac029bef8 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 11 Apr 2024 14:41:23 +0900 Subject: [PATCH 127/191] Make the gcd look nice in xgcd --- src/sage/rings/polynomial/laurent_polynomial.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 5ae5dee4a9b..742475231c8 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1321,7 +1321,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): @coerce_binop def xgcd(self, other): r""" - Extended `gcd` for univariate Laurent polynomial rings over a field. + Extended :meth:`gcd` for univariate Laurent polynomial rings over a field. OUTPUT: From ededb5980198a783d0cbcf1c08edecc8ef12326e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 10 Apr 2024 22:56:26 -0700 Subject: [PATCH 128/191] build/bin/sage-logger: Suppress error message output when /usr/bin/time is not available --- build/bin/sage-logger | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 6945ba98182..1661e52f5f8 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -63,7 +63,7 @@ fi timefile="$logdir/$logname.time" rm -f "$timefile" -if /usr/bin/time -h -o /dev/null true; then +if /usr/bin/time -h -o /dev/null true 2>/dev/null; then TIME="/usr/bin/time -h -o $timefile" else TIME="" @@ -71,7 +71,7 @@ fi report_time () { - time=$(echo $(cat $timefile)) + time=$(echo $(cat $timefile 2>/dev/null)) case "$time" in *m*real*|*h*real*|*[1-9][0-9].*real*|*[1-9][0-9],*real*) # at least 10 seconds wall time From d3c60a2ed9ad38f78e06a8bb18e706a968e9441e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 11 Apr 2024 08:05:19 +0200 Subject: [PATCH 129/191] undo wrong move --- src/sage/modular/ssmod/ssmod.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modular/ssmod/ssmod.py b/src/sage/modular/ssmod/ssmod.py index 550e0e29ec4..e00da45a87e 100644 --- a/src/sage/modular/ssmod/ssmod.py +++ b/src/sage/modular/ssmod/ssmod.py @@ -837,7 +837,7 @@ def hecke_matrix(self, L): Fp2 = self.__finite_field h = len(SS) R = self.base_ring() - T_L = MatrixSpace(R, h).zero() + T_L = MatrixSpace(R, h)(0) # mutable S, X = Fp2['x'].objgen() for i in range(len(SS)): From 4d23d18c71382d4b6e3d5f419a0553c17eeff579 Mon Sep 17 00:00:00 2001 From: gmou3 <32706872+gmou3@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:13:54 +0300 Subject: [PATCH 130/191] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``mapping[e]`` Co-authored-by: Matthias Köppe --- src/sage/matroids/circuit_closures_matroid.pyx | 2 +- src/sage/matroids/circuits_matroid.pyx | 2 +- src/sage/matroids/flats_matroid.pyx | 2 +- src/sage/matroids/graphic_matroid.py | 4 ++-- src/sage/matroids/linear_matroid.pyx | 10 +++++----- src/sage/matroids/matroid.pyx | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index eced2f7ce35..cabd077202d 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -578,7 +578,7 @@ cdef class CircuitClosuresMatroid(Matroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index 455a4d8464a..2f9ad33d028 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -423,7 +423,7 @@ cdef class CircuitsMatroid(Matroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index 1d736eddfe7..06d0d249353 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -310,7 +310,7 @@ cdef class FlatsMatroid(Matroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 8d7fdd89757..6b7e54340ad 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -2012,7 +2012,7 @@ def relabel(self, mapping): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid @@ -2022,7 +2022,7 @@ def relabel(self, mapping): sage: M = matroids.CompleteGraphic(4) sage: sorted(M.groundset()) [0, 1, 2, 3, 4, 5] - sage: N = M.relabel({0:6, 5:'e'}) + sage: N = M.relabel({0: 6, 5: 'e'}) sage: sorted(N.groundset(), key=str) [1, 2, 3, 4, 6, 'e'] sage: N.is_isomorphic(M) diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index 80795c5272a..cfa0698178e 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -2983,7 +2983,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid @@ -4085,7 +4085,7 @@ cdef class BinaryMatroid(LinearMatroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid @@ -5016,7 +5016,7 @@ cdef class TernaryMatroid(LinearMatroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid @@ -5778,7 +5778,7 @@ cdef class QuaternaryMatroid(LinearMatroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid @@ -6734,7 +6734,7 @@ cdef class RegularMatroid(LinearMatroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 3529d5bc5b9..7e20e58d75b 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -8434,7 +8434,7 @@ cdef class Matroid(SageObject): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of `e` OUTPUT: a matroid From f2bdbb2af3c9063c40a7860840ed599148e641c3 Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Thu, 11 Apr 2024 14:19:15 +0300 Subject: [PATCH 131/191] Add is_graphic/regular --- src/sage/matroids/database_matroids.py | 6 +++ src/sage/matroids/graphic_matroid.py | 28 +++++++++++ src/sage/matroids/linear_matroid.pyx | 14 ++++++ src/sage/matroids/matroid.pxd | 2 + src/sage/matroids/matroid.pyx | 67 ++++++++++++++++++++++++++ 5 files changed, 117 insertions(+) diff --git a/src/sage/matroids/database_matroids.py b/src/sage/matroids/database_matroids.py index 0017ce0627e..6da7c02b902 100644 --- a/src/sage/matroids/database_matroids.py +++ b/src/sage/matroids/database_matroids.py @@ -112,6 +112,8 @@ def U25(): sage: U25 = matroids.catalog.U25(); U25 U(2, 5): Matroid of rank 2 on 5 elements with circuit-closures {2: {{0, 1, 2, 3, 4}}} + sage: U25.is_graphic() or U25.is_regular() + False sage: U35 = matroids.catalog.U35() sage: U25.is_isomorphic(U35.dual()) True @@ -135,6 +137,8 @@ def U35(): sage: U35 = matroids.catalog.U35(); U35 U(3, 5): Matroid of rank 3 on 5 elements with circuit-closures {3: {{0, 1, 2, 3, 4}}} + sage: U35.is_graphic() or U35.is_regular() + False sage: U25 = matroids.catalog.U25() sage: U35.is_isomorphic(U25.dual()) True @@ -155,6 +159,8 @@ def K4(): sage: M = matroids.catalog.K4(); M M(K4): Graphic matroid of rank 3 on 6 elements + sage: M.is_graphic() + True `M(K_4)` is isomorphic to `M(\mathcal{W}_3)`, the rank-`3` wheel:: diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 57bbae15f22..4a425cb896c 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -1161,6 +1161,34 @@ def is_valid(self): """ return True + def is_graphic(self): + r""" + Return if ``self`` is graphic. + + This is trivially ``True`` for a class:`GraphicMatroid`. + + EXAMPLES:: + + sage: M = Matroid(graphs.PetersenGraph()) + sage: M.is_graphic() + True + """ + return True + + def is_regular(self): + r""" + Return if ``self`` is regular. + + This is always ``True`` for a class:`GraphicMatroid`. + + EXAMPLES:: + + sage: M = Matroid(graphs.DesarguesGraph()) + sage: M.is_regular() + True + """ + return True + # Graphic methods: def graph(self): diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index 7b6eb9bb711..e710c1777da 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -6367,6 +6367,20 @@ cdef class RegularMatroid(LinearMatroid): # representation + def is_regular(self): + r""" + Return if ``self`` is regular. + + This is trivially ``True`` for a class:`RegularMatroid`. + + EXAMPLES:: + + sage: M = matroids.catalog.R10() + sage: M.is_regular() + True + """ + return True + cpdef binary_matroid(self, randomized_tests=1, verify = True): r""" Return a binary matroid representing ``self``. diff --git a/src/sage/matroids/matroid.pxd b/src/sage/matroids/matroid.pxd index 5103bcf2a4b..9a2b6f9eaa9 100644 --- a/src/sage/matroids/matroid.pxd +++ b/src/sage/matroids/matroid.pxd @@ -193,6 +193,8 @@ cdef class Matroid(SageObject): cpdef _local_ternary_matroid(self, basis=*) cpdef ternary_matroid(self, randomized_tests=*, verify=*) cpdef is_ternary(self, randomized_tests=*) + cpdef is_regular(self) + cpdef is_graphic(self) # matroid k-closed cpdef is_k_closed(self, int k) diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 781f72592ac..56eb6d0269d 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -116,6 +116,8 @@ additional functionality (e.g. linear extensions). - :meth:`girth() ` - Representation + - :meth:`is_graphic() ` + - :meth:`is_regular() ` - :meth:`binary_matroid() ` - :meth:`is_binary() ` - :meth:`ternary_matroid() ` @@ -6465,6 +6467,71 @@ cdef class Matroid(SageObject): """ return self.ternary_matroid(randomized_tests=randomized_tests, verify=True) is not None + cpdef is_graphic(self): + r""" + Return if ``self`` is graphic. + + A matroid is graphic if and only if it has no minor isomorphic to any + of the matroids `U_{2, 4}`, `F_7`, `F_7^*`, `M^*(K_5)`, and + `M^*(K_{3, 3})`. + + EXAMPLES:: + + sage: M = matroids.catalog.Wheel4() + sage: M.is_graphic() + True + sage: M = matroids.catalog.U24() + sage: M.is_graphic() + False + + REFERENCES: + + [Oxl2011]_, p. 385. + """ + from sage.matroids.database_matroids import ( + U24, + Fano, + FanoDual, + K5dual, + K33dual + ) + excluded_minors = [U24(), Fano(), FanoDual(), K5dual(), K33dual()] + for M in excluded_minors: + if self.has_minor(M): + return False + return True + + cpdef is_regular(self): + r""" + Return if ``self`` is regular. + + A regular matroid is one that can be represented by a totally + unimodular matrix, the latter being a matrix over `\mathbb{R}` for + which every square submatrix has determinant in `\{0, 1, -1\}`. A + matroid is regular if and only if it is representable over every field. + Alternatively, a matroid is regular if and only if it has no minor + isomorphic to `U_{2, 4}`, `F_7`, or `F_7^*`. + + EXAMPLES:: + + sage: M = matroids.catalog.Wheel4() + sage: M.is_regular() + True + sage: M = matroids.catalog.R9() + sage: M.is_regular() + False + + REFERENCES: + + [Oxl2011]_, p. 373. + """ + if not self.is_binary(): # equivalent to checking for a U24 minor + return False + from sage.matroids.database_matroids import Fano, FanoDual + if self.has_minor(Fano()) or self.has_minor(FanoDual()): + return False + return True + # matroid k-closed cpdef is_k_closed(self, int k): From 0c49d81a6571d1f1c8e85fb95fd51e1f10124129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 11 Apr 2024 13:41:52 +0200 Subject: [PATCH 132/191] various ruff fixes in groups (PERF, etc) --- .../additive_abelian_wrapper.py | 31 ++++++------ src/sage/groups/braid.py | 4 +- src/sage/groups/class_function.py | 28 +++++------ src/sage/groups/cubic_braid.py | 47 +++++++++--------- src/sage/groups/finitely_presented.py | 7 ++- src/sage/groups/generic.py | 3 +- src/sage/groups/kernel_subgroup.py | 1 + src/sage/groups/libgap_mixin.py | 12 ++--- .../matrix_gps/finitely_generated_gap.py | 10 ++-- src/sage/groups/matrix_gps/orthogonal.py | 19 ++++---- src/sage/groups/perm_gps/permgroup.py | 48 ++++++++++--------- src/sage/groups/perm_gps/permgroup_named.py | 25 +++++----- .../semimonomial_transformation_group.py | 4 +- 13 files changed, 116 insertions(+), 123 deletions(-) diff --git a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py index bf16874d97f..3edddea25e7 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py +++ b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py @@ -77,6 +77,7 @@ from sage.misc.superseded import deprecated_function_alias + class UnwrappingMorphism(Morphism): r""" The embedding into the ambient group. Used by the coercion framework. @@ -213,7 +214,7 @@ def __init__(self, universe, gens, invariants): self._universe = universe self._gen_elements = tuple(universe(x) for x in gens) self._gen_orders = invariants - cover,rels = addgp.cover_and_relations_from_invariants(invariants) + cover, rels = addgp.cover_and_relations_from_invariants(invariants) addgp.AdditiveAbelianGroup_fixed_gens.__init__(self, cover, rels, cover.gens()) self._unset_coercions_used() self.register_embedding(UnwrappingMorphism(self)) @@ -488,13 +489,13 @@ def torsion_subgroup(self, n=None): if n <= 0: raise ValueError('n must be a positive integer') gens, ords = [], [] - for g,o in genords: + for g, o in genords: if not o: continue d = n.gcd(o) if d == 1: continue - gens.append(o//d * g) + gens.append(o // d * g) ords.append(d) return AdditiveAbelianGroupWrapper(self.universe(), gens, ords) @@ -691,9 +692,9 @@ def _expand_basis_pgroup(p, alphas, vals, beta, h, rel): if not (isinstance(alphas, list) and isinstance(vals, list)): raise TypeError('alphas and vals must be lists for mutability') if not len(alphas) == len(vals) == k - 1: - raise ValueError(f'alphas and/or vals have incorrect length') -# assert not sum(r*a for r,a in zip(rel, alphas+[beta])) -# assert all(a.order() == p**v for a,v in zip(alphas,vals)) + raise ValueError('alphas and/or vals have incorrect length') + # assert not sum(r*a for r,a in zip(rel, alphas+[beta])) + # assert all(a.order() == p**v for a,v in zip(alphas,vals)) if rel[-1] < 0: raise ValueError('rel must have nonnegative entries') @@ -726,8 +727,8 @@ def _expand_basis_pgroup(p, alphas, vals, beta, h, rel): return # step 3 - j = next(j for j,r in enumerate(rel) if r == min_r) - alphas[j] = sum(a * (r//rel[j]) for a,r in zip(alphas+[beta], rel)) + j = next(j for j, r in enumerate(rel) if r == min_r) + alphas[j] = sum(a * (r // rel[j]) for a, r in zip(alphas + [beta], rel)) # step 4 if not alphas[j]: @@ -752,7 +753,8 @@ def _expand_basis_pgroup(p, alphas, vals, beta, h, rel): else: alphas.append(beta) vals.append(h) -# assert alphas[-1].order() == p**vals[-1] + # assert alphas[-1].order() == p**vals[-1] + def basis_from_generators(gens, ords=None): r""" @@ -803,7 +805,8 @@ def basis_from_generators(gens, ords=None): gammas = [] ms = [] for p in ps: - pgens = [(o.prime_to_m_part(p) * g, o.p_primary_part(p)) for g, o in zip(gens, ords) if not o % p] + pgens = [(o.prime_to_m_part(p) * g, o.p_primary_part(p)) + for g, o in zip(gens, ords) if not o % p] assert pgens pgens.sort(key=lambda tup: tup[1]) @@ -814,7 +817,7 @@ def basis_from_generators(gens, ords=None): while pgens: beta, ord_beta = pgens.pop() try: - dlog = _discrete_log_pgroup(p, vals, alphas, beta) + _ = _discrete_log_pgroup(p, vals, alphas, beta) except ValueError: pass else: @@ -845,8 +848,8 @@ def basis_from_generators(gens, ords=None): gammas.append(a) ms.append(p ** v) -## assert len({sum(i*g for i,g in zip(vec,gammas)) -## for vec in __import__('itertools').product(*map(range,ms))}) \ -## == __import__('sage').misc.misc_c.prod(ms) +# assert len({sum(i*g for i,g in zip(vec,gammas)) +# for vec in __import__('itertools').product(*map(range,ms))}) \ +# == __import__('sage').misc.misc_c.prod(ms) return gammas, ms diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index fb52b074218..3b48e00effd 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -2590,8 +2590,8 @@ def __init__(self, names): rels = [] for i in range(1, n): rels.append(free_group([i, i + 1, i, -i - 1, -i, -i - 1])) - for j in range(i + 2, n + 1): - rels.append(free_group([i, j, -i, -j])) + rels.extend(free_group([i, j, -i, -j]) + for j in range(i + 2, n + 1)) cat = Groups().Infinite() FinitelyPresentedGroup.__init__(self, free_group, tuple(rels), category=cat) diff --git a/src/sage/groups/class_function.py b/src/sage/groups/class_function.py index 901b0083b49..6ca0d9ee2cb 100644 --- a/src/sage/groups/class_function.py +++ b/src/sage/groups/class_function.py @@ -605,10 +605,9 @@ def irreducible_constituents(self): L = self._gap_classfunction.ConstituentsOfCharacter() return tuple(ClassFunction(self._group, list(l)) for l in L) - def decompose(self): + def decompose(self) -> tuple: r""" - Returns a list of the characters that appear in the decomposition - of chi. + Return a list of the characters appearing the decomposition of ``self``. EXAMPLES:: @@ -618,14 +617,13 @@ def decompose(self): ((3, Character of Symmetric group of order 5! as a permutation group), (2, Character of Symmetric group of order 5! as a permutation group)) """ - L = [] - for irr in self.irreducible_constituents(): - L.append((self.scalar_product(irr), irr)) + L = [(self.scalar_product(irr), irr) + for irr in self.irreducible_constituents()] return tuple(L) def norm(self): r""" - Returns the norm of self. + Return the norm of ``self``. EXAMPLES:: @@ -635,7 +633,7 @@ def norm(self): """ return self._gap_classfunction.Norm() - def values(self): + def values(self) -> list: r""" Return the list of values of self on the conjugacy classes. @@ -665,7 +663,7 @@ def values(self): def central_character(self): r""" - Returns the central character of self. + Return the central character of ``self``. EXAMPLES:: @@ -677,7 +675,7 @@ def central_character(self): def determinant_character(self): r""" - Returns the determinant character of self. + Return the determinant character of ``self``. EXAMPLES:: @@ -1310,10 +1308,9 @@ def irreducible_constituents(self): L = self._gap_classfunction.ConstituentsOfCharacter() return tuple(ClassFunction_libgap(self._group, l) for l in L) - def decompose(self): + def decompose(self) -> tuple: r""" - Return a list of the characters that appear in the decomposition - of ``self``. + Return a list of the characters appearing the decomposition of ``self``. EXAMPLES:: @@ -1323,9 +1320,8 @@ def decompose(self): ((3, Character of Symmetric group of order 5! as a permutation group), (2, Character of Symmetric group of order 5! as a permutation group)) """ - L = [] - for irr in self.irreducible_constituents(): - L.append((self.scalar_product(irr), irr)) + L = [(self.scalar_product(irr), irr) + for irr in self.irreducible_constituents()] return tuple(L) def norm(self): diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 9dd59e069f9..c80da80520e 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -128,7 +128,7 @@ def eliminate_item(tietze_list): return None first = tietze_list[0] second = None - for i in range(1,l): + for i in range(1, l): if tietze_list[i] in (first, -first): if i == 1: second = tietze_list[i] @@ -502,9 +502,9 @@ def find_root(domain): # -------------------------------------------------------------------- cbg_type = self.parent()._cbg_type if cbg_type == CubicBraidGroup.type.AssionS: - characteristic = 3 # making Assion type S relations vanish + characteristic = 3 # making Assion type S relations vanish elif cbg_type == CubicBraidGroup.type.AssionU: - characteristic = 2 # making Assion type U relations vanish + characteristic = 2 # making Assion type U relations vanish else: characteristic = 0 try: @@ -512,7 +512,7 @@ def find_root(domain): except ValueError: raise ValueError('characteristic must be in integer') - if not characteristic.is_zero() and not characteristic.is_prime(): + if not characteristic.is_zero() and not characteristic.is_prime(): raise ValueError('characteristic must be a prime') if characteristic.is_zero(): from sage.rings.number_field.number_field import CyclotomicField @@ -526,7 +526,7 @@ def find_root(domain): root_bur = find_root(domain) domain = root_bur.parent() - else: # domain is not None + else: # domain is not None root_bur = find_root(domain) else: # root_bur is not None @@ -550,11 +550,11 @@ def conv2domain(laur_pol): from sage.matrix.constructor import matrix d1, d2 = burau_ori.dimensions() - burau_mat = matrix(d1, d2, lambda i,j: conv2domain(burau_ori[i,j])) + burau_mat = matrix(d1, d2, lambda i, j: conv2domain(burau_ori[i, j])) if unitary: - burau_mat_adj = matrix(d1, d2, lambda i,j: conv2domain(burau_ori_adj[i,j])) - herm_form = matrix(d1, d2, lambda i,j: conv2domain(herm_form_ori[i,j])) + burau_mat_adj = matrix(d1, d2, lambda i, j: conv2domain(burau_ori_adj[i, j])) + herm_form = matrix(d1, d2, lambda i, j: conv2domain(herm_form_ori[i, j])) return burau_mat, burau_mat_adj, herm_form return burau_mat @@ -764,15 +764,14 @@ def __init__(self, names, cbg_type=None): # internal naming of elements for convenience b = [free_group([i]) for i in range(1, n+1)] - t = [free_group([i, i+1]) ** 3 for i in range(1, n)] + t = [free_group([i, i+1]) ** 3 for i in range(1, n)] ti = [free_group([-i, -i-1]) ** 3 for i in range(1, n)] - # first the braid relation + # first the braid relations rels = list(self._braid_group.relations()) - # than the cubic relation - for i in range(n): - rels.append(b[i]**3) + # than the cubic relations + rels.extend(b[i]**3 for i in range(n)) # than Assion's relation Satz 2.2 for cbg_type=CubicBraidGroup.type.AssionS # and Satz 2.4 for cbg_type=CubicBraidGroup.type.AssionU @@ -1276,7 +1275,7 @@ def create_unitary_realization(self, m): if pos + 1 < m: transvections.append(xbas[pos-1]+xbas[pos]+xbas[pos+1]) # t_{3i+1} = x_{3i-1} + x_{3i} + x_{3i+1} if pos + 3 < m: - transvections.append(xbas[pos+1]+xbas[pos+2]+xbas[pos+3]) # t_{3i+2} = x_{3i+1} + x_{3i+2} + x_{3i+3} + transvections.append(xbas[pos+1]+xbas[pos+2]+xbas[pos+3]) # t_{3i+2} = x_{3i+1} + x_{3i+2} + x_{3i+3} # ----------------------------------------------------------- # Conversion-Map from transvection vector to transvection @@ -1299,15 +1298,14 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices) return - #---------------------------------------------------------------------------------------------------------- - #---------------------------------------------------------------------------------------------------------- + # ---------------------------------------------------------------- # local functions declaration section finishes here - #---------------------------------------------------------------------------------------------------------- - #---------------------------------------------------------------------------------------------------------- + # ---------------------------------------------------------------- - # ------------------------------------------------------------------------------- + # ---------------------------------------------------------------- # initialization of constants - # ------------------------------------------------------------------------------- + # ---------------------------------------------------------------- + n = self.strands() # ------------------------------------------------------------------------------- @@ -1317,7 +1315,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): dim_sympl_group = n-1 # S(n-1) = Sp(n-1, 3) if n % 2 == 0: dim_sympl_group = n # S(n-1) = subgroup of PSp(n, 3) - create_sympl_realization(self, dim_sympl_group) + create_sympl_realization(self, dim_sympl_group) elif self._cbg_type == CubicBraidGroup.type.AssionU: dim_unitary_group = n-1 # U(n-1) = GU(n-1, 2) if n % 3 == 0: @@ -1543,8 +1541,9 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' unitary = True gen_list = [] for braid_gen in self.gens(): - bur_mat = braid_gen.burau_matrix(root_bur=root_bur, domain=domain, characteristic=characteristic, - var=var, reduced=reduced) + bur_mat = braid_gen.burau_matrix(root_bur=root_bur, domain=domain, + characteristic=characteristic, + var=var, reduced=reduced) if unitary: bur_mat, bur_mat_ad, herm_form = bur_mat @@ -1809,7 +1808,7 @@ def as_reflection_group(self): if not is_chevie_available(): raise ImportError("the GAP3 package 'CHEVIE' is needed to obtain the corresponding reflection groups") - if self._cbg_type != CubicBraidGroup.type.Coxeter or self.strands() > 5 or self.strands() < 2: + if self._cbg_type != CubicBraidGroup.type.Coxeter or self.strands() > 5 or self.strands() < 2: raise ValueError("no reflection group defined") # ------------------------------------------------------------------------------- diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 3388c41d954..7d96975fe22 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -1005,7 +1005,7 @@ def as_permutation_group(self, limit=4096000): from sage.combinat.permutation import Permutation from sage.groups.perm_gps.permgroup import PermutationGroup return PermutationGroup([ - Permutation(coset_table[2*i]) for i in range(len(coset_table)//2)]) + Permutation(coset_table[2*i]) for i in range(len(coset_table)//2)]) def direct_product(self, H, reduced=False, new_names=True): r""" @@ -1548,14 +1548,13 @@ def sorted_presentation(self): L1 = [] for rel in L0: C = [rel] - for j in range(len(rel) - 1): - C.append(rel[j + 1:] + rel[:j + 1]) + C.extend(rel[j + 1:] + rel[:j + 1] for j in range(len(rel) - 1)) C1 = [tuple(-j for j in reversed(l)) for l in C] C += C1 C.sort() L1.append(C[0]) L1.sort() - return F/L1 + return F / L1 def epimorphisms(self, H): r""" diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index cb406b444af..fccb76fe0ef 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -901,7 +901,7 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i power = lambda x, y: multiple(x, y, operation=operation, identity=identity, inverse=inverse, op=op) if bounds: lb, ub = map(integer_ring.ZZ, bounds) - if (op is None or identity is None or inverse is None or ord is None) and operation not in addition_names+multiplication_names: + if (op is None or identity is None or inverse is None or ord is None) and operation not in addition_names + multiplication_names: raise ValueError("ord, op, identity, and inverse must all be specified for this operation") if ord is None: if operation in multiplication_names: @@ -1500,7 +1500,6 @@ def has_order(P, n, operation='+'): return False n = n.factor() - G = P.parent() if operation in addition_names: isid = lambda el: not el mult = lambda el, n: multiple(el, n, operation='+') diff --git a/src/sage/groups/kernel_subgroup.py b/src/sage/groups/kernel_subgroup.py index dec7a0be573..6a20b673c57 100644 --- a/src/sage/groups/kernel_subgroup.py +++ b/src/sage/groups/kernel_subgroup.py @@ -21,6 +21,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation + class KernelSubgroup(UniqueRepresentation, Parent): r""" The kernel (normal) subgroup. diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 50f8fdf2678..476fb4e9416 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -277,7 +277,7 @@ def conjugacy_classes_representatives(self): if not self.is_finite(): raise NotImplementedError("only implemented for finite groups") G = self.gap() - reps = [ cc.Representative() for cc in G.ConjugacyClasses() ] + reps = [cc.Representative() for cc in G.ConjugacyClasses()] return tuple(self(g) for g in reps) def conjugacy_classes(self): @@ -676,9 +676,7 @@ def irreducible_characters(self): if not self.is_finite(): raise NotImplementedError("only implemented for finite groups") Irr = self.gap().Irr() - L = [] - for irr in Irr: - L.append(ClassFunction_libgap(self, irr)) + L = [ClassFunction_libgap(self, irr) for irr in Irr] return tuple(L) def character(self, values): @@ -731,7 +729,7 @@ def trivial_character(self): """ if not self.is_finite(): raise NotImplementedError("only implemented for finite groups") - values = [1]*self._gap_().NrConjugacyClasses().sage() + values = [1] * self._gap_().NrConjugacyClasses().sage() return self.character(values) def character_table(self): @@ -763,8 +761,8 @@ def character_table(self): [ 4 0 -1 -1 2 1 0] [ 1 1 1 1 1 1 1] """ - #code from function in permgroup.py, but modified for - #how gap handles these groups. + # code from function in permgroup.py, but modified for + # how gap handles these groups. G = self._gap_() cl = self.conjugacy_classes() from sage.rings.integer import Integer diff --git a/src/sage/groups/matrix_gps/finitely_generated_gap.py b/src/sage/groups/matrix_gps/finitely_generated_gap.py index 14bf551789f..b1623f543f9 100644 --- a/src/sage/groups/matrix_gps/finitely_generated_gap.py +++ b/src/sage/groups/matrix_gps/finitely_generated_gap.py @@ -29,7 +29,6 @@ from sage.groups.matrix_gps.finitely_generated import MatrixGroup from sage.groups.matrix_gps.matrix_group_gap import MatrixGroup_gap from sage.matrix.matrix_space import MatrixSpace -from sage.misc.cachefunc import cached_method from sage.misc.functional import cyclotomic_polynomial from sage.modules.free_module_element import vector from sage.rings.fraction_field import FractionField @@ -72,7 +71,7 @@ def __reduce__(self): ) """ return (MatrixGroup, - tuple(g.matrix() for g in self.gens()) + ({'check':False},)) + tuple(g.matrix() for g in self.gens()) + ({'check': False},)) def as_permutation_group(self, algorithm=None, seed=None): r""" @@ -321,7 +320,7 @@ def invariant_generators(self): # test if the field is admissible if F.gen() == 1: # we got the rationals or GF(prime) FieldStr = str(F.characteristic()) - elif hasattr(F,'polynomial'): # we got an algebraic extension + elif hasattr(F, 'polynomial'): # we got an algebraic extension if len(F.gens()) > 1: raise NotImplementedError("can only deal with finite fields and (simple algebraic extensions of) the rationals") FieldStr = '(%d,%s)' % (F.characteristic(), str(F.gen())) @@ -794,10 +793,7 @@ def reynolds_operator(self, poly, chi=None): elif not C.is_absolute() or not K.is_absolute() or not R.is_absolute(): raise NotImplementedError("only implemented for absolute fields") else: - fields = [] - for M in [R,K,C]: - if M.absolute_degree() != 1: - fields.append(M) + fields = [M for M in [R, K, C] if M.absolute_degree() != 1] l = len(fields) if l == 0: # all are QQ diff --git a/src/sage/groups/matrix_gps/orthogonal.py b/src/sage/groups/matrix_gps/orthogonal.py index 3ce9915dfec..c30fc14a331 100644 --- a/src/sage/groups/matrix_gps/orthogonal.py +++ b/src/sage/groups/matrix_gps/orthogonal.py @@ -196,18 +196,18 @@ def _OG(n, R, special, e=0, var='a', invariant_form=None): inserted_text = "with respect to symmetric form" name = '{0} Orthogonal Group of degree {1} over {2} {3}\n{4}'.format( - prefix, degree, ring, inserted_text,invariant_form) + prefix, degree, ring, inserted_text, invariant_form) ltx = r'\text{{{0}O}}_{{{1}}}({2})\text{{ {3} }}{4}'.format( - ltx_prefix, degree, latex(ring), inserted_text, - latex(invariant_form)) + ltx_prefix, degree, latex(ring), inserted_text, + latex(invariant_form)) else: name = '{0} Orthogonal Group of degree {1} over {2}'.format(prefix, degree, ring) ltx = r'\text{{{0}O}}_{{{1}}}({2})'.format(ltx_prefix, degree, latex(ring)) else: name = '{0} Orthogonal Group of degree {1} and form parameter {2} over {3}'.format(prefix, degree, e, ring) ltx = r'\text{{{0}O}}_{{{1}}}({2}, {3})'.format(ltx_prefix, degree, - latex(ring), - '+' if e == 1 else '-') + latex(ring), + '+' if e == 1 else '-') if isinstance(ring, FiniteField): try: @@ -522,11 +522,14 @@ def invariant_bilinear_form(self): m.set_immutable() return m - invariant_quadratic_form = invariant_bilinear_form # this is identical in the generic case - invariant_form = invariant_bilinear_form # alias (analogues to symplectic and unitary cases) + invariant_quadratic_form = invariant_bilinear_form + # this is identical in the generic case + + invariant_form = invariant_bilinear_form + # alias (analogues to symplectic and unitary cases) def _check_matrix(self, x, *args): - """a + """ Check whether the matrix ``x`` is orthogonal. See :meth:`~sage.groups.matrix_gps.matrix_group._check_matrix` diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index f001126ed84..3f6431948ea 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -203,6 +203,7 @@ def wrapped(self, n, p=0): return f(self, n, p=p) return wrapped + def direct_product_permgroups(P): """ Takes the direct product of the permutation groups listed in ``P``. @@ -230,6 +231,7 @@ def direct_product_permgroups(P): G = libgap.DirectProduct(*P) return PermutationGroup(gap_group=G) + def from_gap_list(G, src): r""" Convert a string giving a list of GAP permutations into a list of @@ -249,7 +251,7 @@ def from_gap_list(G, src): # src is a list of strings, each of which is a permutation of # integers in cycle notation. It may contain \n and spaces. src = [str(g)[1:].split(")(") - for g in str(src).replace(" ","").replace("\n","")[1:-2].split("),")] + for g in str(src).replace(" ", "").replace("\n", "")[1:-2].split("),")] # src is a list of list of strings. Each string is a list of # integers separated by ',' @@ -260,6 +262,7 @@ def from_gap_list(G, src): # src is now a list of group elements return src + def PermutationGroup(gens=None, *args, **kwds): """ Return the permutation group associated to `x` (typically a @@ -539,7 +542,7 @@ def __init__(self, gens=None, gap_group=None, canonicalize=True, # to make the domain contain all integers up to the max. # This is needed for backward compatibility if all(isinstance(p, (int, Integer)) for p in domain): - domain = list(range(min([1] + domain), max([1] + domain)+1)) + domain = list(range(min([1] + domain), max([1] + domain) + 1)) if domain not in FiniteEnumeratedSets(): domain = FiniteEnumeratedSet(domain) @@ -823,7 +826,7 @@ def __richcmp__(self, right, op): gSelf = self._libgap_() gRight = right._libgap_() - if op in [op_EQ,op_NE]: + if op in [op_EQ, op_NE]: return gSelf._richcmp_(gRight, op) if gSelf.IsSubgroup(gRight): @@ -906,7 +909,7 @@ def _element_constructor_(self, x, check=True): # We check if we can lift ``x`` to ``self`` directly # so we can pass check=False for speed. if (isinstance(x_parent, PermutationGroup_subgroup) - and x_parent._ambient_group is self): + and x_parent._ambient_group is self): return self.element_class(x, self, check=False) from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -1268,9 +1271,9 @@ def elements(SGS): else: enumeration = "depth" return iter(RecursivelyEnumeratedSet( - seeds=seeds, - successors=successors, - enumeration=enumeration)) + seeds=seeds, + successors=successors, + enumeration=enumeration)) else: raise ValueError("the input algorithm (='%s') must be 'SGS', 'BFS' or 'DFS'" % algorithm) @@ -1558,12 +1561,12 @@ def _domain_gap(self, domain=None): '[1, 2, 3, 4, 5]' """ if domain is None: - return repr(list(range(1, self.degree()+1))) - else: - try: - return repr([self._domain_to_gap[point] for point in domain]) - except KeyError: - raise ValueError("domain must be a subdomain of self.domain()") + return repr(list(range(1, self.degree() + 1))) + + try: + return repr([self._domain_to_gap[point] for point in domain]) + except KeyError: + raise ValueError("domain must be a subdomain of self.domain()") @cached_method def smallest_moved_point(self): @@ -1588,7 +1591,7 @@ def smallest_moved_point(self): p = self._libgap_().SmallestMovedPoint() return self._domain_from_gap[Integer(p)] - def representative_action(self,x,y): + def representative_action(self, x, y): r""" Return an element of self that maps `x` to `y` if it exists. @@ -3709,12 +3712,9 @@ def subgroups(self): - Rob Beezer (2011-01-24) """ - all_sg = [] ccs = self._libgap_().ConjugacyClassesSubgroups() - for cc in ccs: - for h in cc.Elements(): - all_sg.append(self.subgroup(gap_group=h)) - return all_sg + return [self.subgroup(gap_group=h) for cc in ccs + for h in cc.Elements()] @cached_method def _regular_subgroup_gap(self): @@ -4166,7 +4166,7 @@ def maximal_normal_subgroups(self): return [self.subgroup(gap_group=gap_subgroup) for gap_subgroup in self._libgap_().MaximalNormalSubgroups()] - ###################### Boolean tests ##################### + # ##################### Boolean tests ##################### def is_abelian(self): """ @@ -4715,7 +4715,7 @@ def normalizes(self, other): """ return bool(self._libgap_().IsNormal(other)) - ############## Series ###################### + # ############# Series ###################### def composition_series(self): """ @@ -4857,7 +4857,8 @@ def molien_series(self): sage: PG.molien_series() == PG1.molien_series()*(1-x)^2 True """ - pi = self._libgap_().PermutationCharacter(list(self.domain()),libgap.OnPoints) + pi = self._libgap_().PermutationCharacter(list(self.domain()), + libgap.OnPoints) M = pi.MolienSeries() R = QQ['x'] @@ -5217,7 +5218,7 @@ def _latex_(self): gens = '\\langle ' + \ ', '.join([x._latex_() for x in self.gens()]) + ' \\rangle' return '\\hbox{Subgroup } %s \\hbox{ of } %s' % \ - (gens, self.ambient_group()._latex_()) + (gens, self.ambient_group()._latex_()) def ambient_group(self): """ @@ -5263,6 +5264,7 @@ def is_normal(self, other=None): # Allow for subclasses to use a different subgroup class PermutationGroup_generic.Subgroup = PermutationGroup_subgroup + class PermutationGroup_action(PermutationGroup_generic): """ A permutation group given by a finite group action. diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index 69014066364..6e979561e43 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -191,7 +191,7 @@ def __classcall__(cls, domain): if domain < 0: raise ValueError("domain (={}) must be an integer >= 0 or a list".format(domain)) - domain = list(range(1, domain+1)) + domain = list(range(1, domain + 1)) v = FiniteEnumeratedSet(domain) else: v = domain @@ -469,17 +469,17 @@ def young_subgroup(self, comp): gens = [] pos = 0 for c in comp: - for i in range(c - 1): - gens.append(self((domain[pos + i], domain[pos + i + 1]))) + gens.extend(self((domain[pos + i], domain[pos + i + 1])) + for i in range(c - 1)) pos += c return self.subgroup(gens) def major_index(self, parameter=None): r""" - Return the *major index generating polynomial* of ``self``, - which is a gadget counting the elements of ``self`` by major - index. + Return the *major index generating polynomial* of ``self``. + + This is a gadget counting the elements of ``self`` by major index. INPUT: @@ -1395,13 +1395,12 @@ def __init__(self, factors): jumppoint = Integer(1) for a in simplified: # create one of the generators for the abelian group - gens.append([tuple(range(jumppoint, jumppoint+a))]) + gens.append([tuple(range(jumppoint, jumppoint + a))]) # make contribution to the generator that dihedralizes the # abelian group - for i in range(1, (a//2)+1): - if i != a-i: - genx.append((jumppoint+i, jumppoint+a-i)) - jumppoint = jumppoint + a + genx.extend((jumppoint+i, jumppoint+a-i) + for i in range(1, (a//2)+1) if i != a-i) + jumppoint += a # If all of the direct factors are C2, then the action turning # each element into its inverse is trivial, and the # semi-direct product becomes a direct product, so we simply @@ -1419,9 +1418,7 @@ def _repr_(self): sage: G Generalized dihedral group generated by C2 x C4 x C8 """ - grouplist = [] - for n in self.factors: - grouplist.append('C{}'.format(n)) + grouplist = [f'C{n}' for n in self.factors] return 'Generalized dihedral group generated by ' + ' x '.join(grouplist) diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py b/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py index e61c7bf64c7..602896e3ee8 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py @@ -311,8 +311,8 @@ def gens(self) -> tuple: from sage.groups.perm_gps.permgroup_named import SymmetricGroup R = self.base_ring() l = [self(v=([R.primitive_element()] + [R.one()] * (self.degree() - 1)))] - for g in SymmetricGroup(self.degree()).gens(): - l.append(self(perm=Permutation(g))) + l.extend(self(perm=Permutation(g)) + for g in SymmetricGroup(self.degree()).gens()) if R.is_field() and not R.is_prime_field(): l.append(self(autom=R.hom([R.primitive_element()**R.characteristic()]))) return tuple(l) From 3e6c11336ed008ae2a834afc3e233ba2b2541b41 Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Thu, 11 Apr 2024 14:55:24 +0300 Subject: [PATCH 133/191] Suggestions by mkoeppe --- src/sage/matroids/basis_exchange_matroid.pxd | 2 +- src/sage/matroids/basis_exchange_matroid.pyx | 29 +++++++++++--------- src/sage/matroids/basis_matroid.pyx | 2 +- src/sage/matroids/circuits_matroid.pyx | 2 +- src/sage/matroids/flats_matroid.pyx | 2 +- src/sage/matroids/matroid.pxd | 2 +- src/sage/matroids/matroid.pyx | 13 +++++---- src/sage/matroids/set_system.pxd | 2 +- src/sage/matroids/set_system.pyx | 17 ++++++------ 9 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/sage/matroids/basis_exchange_matroid.pxd b/src/sage/matroids/basis_exchange_matroid.pxd index 97cc4391633..6bcc9e0236e 100644 --- a/src/sage/matroids/basis_exchange_matroid.pxd +++ b/src/sage/matroids/basis_exchange_matroid.pxd @@ -15,7 +15,7 @@ cdef class BasisExchangeMatroid(Matroid): cdef _weak_invariant_var, _strong_invariant_var, _heuristic_invariant_var cdef SetSystem _weak_partition_var, _strong_partition_var, _heuristic_partition_var - cdef _relabel(self, l) + cdef _relabel(self, mapping) cdef _pack(self, bitset_t, X) cdef __unpack(self, bitset_t) diff --git a/src/sage/matroids/basis_exchange_matroid.pyx b/src/sage/matroids/basis_exchange_matroid.pyx index 835092678e2..4e21994cca1 100644 --- a/src/sage/matroids/basis_exchange_matroid.pyx +++ b/src/sage/matroids/basis_exchange_matroid.pyx @@ -191,27 +191,30 @@ cdef class BasisExchangeMatroid(Matroid): bitset_free(self._output) bitset_free(self._temp) - cdef _relabel(self, l): + cdef _relabel(self, mapping): """ - Relabel each element `e` as `l[e]`, where `l` is a given injective map. + Relabel each element ``e`` as ``mapping[e]``, where ``mapping`` is a + given injective map. INPUT: - - `l`, a python object such that `l[e]` is the new label of e. + - ``mapping`` -- a python object such that ``mapping[e]`` is the new + label of `e` - OUTPUT: + OUTPUT: ``None`` - ``None``. + .. NOTE:: - NOTE: - For internal use. Matroids are immutable but this method does modify the matroid. The use this method will only - be safe in very limited circumstances, such as perhaps on a fresh copy of a matroid. + For internal use. Matroids are immutable but this method does + modify the matroid. The use of this method will only be safe in + very limited circumstances, such as perhaps on a fresh copy of a + matroid. """ cdef long i E = [] for i in range(self._groundset_size): - if self._E[i] in l: - E.append(l[self._E[i]]) + if self._E[i] in mapping: + E.append(mapping[self._E[i]]) else: E.append(self._E[i]) self._E = tuple(E) @@ -222,12 +225,12 @@ cdef class BasisExchangeMatroid(Matroid): self._idx[self._E[i]] = i if self._weak_partition_var: - self._weak_partition_var._relabel(l) + self._weak_partition_var._relabel(mapping) if self._strong_partition_var: - self._strong_partition_var._relabel(l) + self._strong_partition_var._relabel(mapping) if self._heuristic_partition_var: - self._heuristic_partition_var._relabel(l) + self._heuristic_partition_var._relabel(mapping) # the engine cdef _pack(self, bitset_t I, F): diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 1dc2ff755a3..e1dea45531e 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -560,7 +560,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): """ d = self._relabel_map(mapping) E = [d[x] for x in self.groundset()] - B = [[d[y] for y in list(x)] for x in self.bases()] + B = [[d[y] for y in x] for x in self.bases()] M = BasisMatroid(groundset=E, bases=B) return M diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index 2f9ad33d028..9173f0d791a 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -454,7 +454,7 @@ cdef class CircuitsMatroid(Matroid): E = [d[x] for x in self._groundset] C = [] for i in self._k_C: - C += [[d[y] for y in list(x)] for x in self._k_C[i]] + C += [[d[y] for y in x] for x in self._k_C[i]] M = CircuitsMatroid(groundset=E, circuits=C) return M diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index 06d0d249353..20a89f9ffd7 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -342,7 +342,7 @@ cdef class FlatsMatroid(Matroid): F = {} for i in self._F: F[i] = [] - F[i] += [[d[y] for y in list(x)] for x in self._F[i]] + F[i] += [[d[y] for y in x] for x in self._F[i]] M = FlatsMatroid(groundset=E, flats=F) return M diff --git a/src/sage/matroids/matroid.pxd b/src/sage/matroids/matroid.pxd index 7aa97843c7e..398abb7f2cb 100644 --- a/src/sage/matroids/matroid.pxd +++ b/src/sage/matroids/matroid.pxd @@ -141,7 +141,7 @@ cdef class Matroid(SageObject): cpdef equals(self, other) cpdef is_isomorphism(self, other, morphism) cpdef _is_isomorphism(self, other, morphism) - cpdef _relabel_map(self, f) + cpdef _relabel_map(self, mapping) # minors, dual, truncation cpdef minor(self, contractions=*, deletions=*) diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 7e20e58d75b..37ceec05874 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -8391,15 +8391,16 @@ cdef class Matroid(SageObject): matroids.insert(0, self) return union_matroid.MatroidSum(iter(matroids)) - cpdef _relabel_map(self, f): + cpdef _relabel_map(self, mapping): """ Return a dictionary from the groundset to the relabeled groundset - and check that the mapping defined by ``f`` is valid. + and check that the mapping defined by ``mapping`` is valid. INPUT: - - ``f`` -- a python object such that ``f[e]`` is the new label of `e`; if - ``e not in f`` then the identity map is assumed + - ``mapping`` -- a python object such that ``mapping[e]`` is the new + label of ``e``; if ``mapping[e]`` is not defined then the identity + map is assumed EXAMPLES:: @@ -8415,8 +8416,8 @@ cdef class Matroid(SageObject): d = {} for x in self.groundset(): try: - E.add(f[x]) - d[x] = f[x] + E.add(mapping[x]) + d[x] = mapping[x] except LookupError: E.add(x) d[x] = x diff --git a/src/sage/matroids/set_system.pxd b/src/sage/matroids/set_system.pxd index a283244b53b..3b3a4902a22 100644 --- a/src/sage/matroids/set_system.pxd +++ b/src/sage/matroids/set_system.pxd @@ -9,7 +9,7 @@ cdef class SetSystem: cdef bitset_t _temp cdef copy(self) - cdef _relabel(self, l) + cdef _relabel(self, mapping) cpdef _complements(self) cdef resize(self, k=*) diff --git a/src/sage/matroids/set_system.pyx b/src/sage/matroids/set_system.pyx index 606231a1734..66468756fe5 100644 --- a/src/sage/matroids/set_system.pyx +++ b/src/sage/matroids/set_system.pyx @@ -207,24 +207,23 @@ cdef class SetSystem: S._append(self._subsets[i]) return S - cdef _relabel(self, l): + cdef _relabel(self, mapping): """ - Relabel each element `e` of the ground set as `l(e)`, where `l` is a - given injective map. + Relabel each element ``e`` of the ground set as ``mapping[e]``, where + ``mapping`` is a given injective map. INPUT: - - ``l`` -- a python object such that `l[e]` is the new label of e. + - ``mapping`` -- a python object such that ``mapping[e]`` is the new + label of `e` - OUTPUT: - - ``None``. + OUTPUT: ``None`` """ cdef long i E = [] for i in range(self._groundset_size): - if self._groundset[i] in l: - E.append(l[self._E[i]]) + if self._groundset[i] in mapping: + E.append(mapping[self._E[i]]) else: E.append(self._E[i]) self._groundset = E From b7005f68ecf9b92f4c7957ddc2bf4418a593e0e3 Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Thu, 11 Apr 2024 15:03:59 +0300 Subject: [PATCH 134/191] Change `e` to ``e`` --- src/sage/matroids/basis_exchange_matroid.pyx | 2 +- src/sage/matroids/basis_matroid.pyx | 2 +- src/sage/matroids/circuit_closures_matroid.pyx | 2 +- src/sage/matroids/circuits_matroid.pyx | 2 +- src/sage/matroids/flats_matroid.pyx | 2 +- src/sage/matroids/graphic_matroid.py | 2 +- src/sage/matroids/linear_matroid.pyx | 10 +++++----- src/sage/matroids/matroid.pyx | 2 +- src/sage/matroids/set_system.pyx | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sage/matroids/basis_exchange_matroid.pyx b/src/sage/matroids/basis_exchange_matroid.pyx index 4e21994cca1..9db2f296679 100644 --- a/src/sage/matroids/basis_exchange_matroid.pyx +++ b/src/sage/matroids/basis_exchange_matroid.pyx @@ -199,7 +199,7 @@ cdef class BasisExchangeMatroid(Matroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: ``None`` diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index e1dea45531e..72bb8368b4e 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -532,7 +532,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): INPUT: - ``mapping`` -- a python object such that `mapping[e]` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index cabd077202d..709b40c4dd1 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -579,7 +579,7 @@ cdef class CircuitClosuresMatroid(Matroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index 9173f0d791a..7b46b8ff102 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -424,7 +424,7 @@ cdef class CircuitsMatroid(Matroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index 20a89f9ffd7..8e701c56198 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -311,7 +311,7 @@ cdef class FlatsMatroid(Matroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 6b7e54340ad..21be785969a 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -2013,7 +2013,7 @@ def relabel(self, mapping): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index cfa0698178e..b2fd28c99ea 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -2984,7 +2984,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid @@ -4086,7 +4086,7 @@ cdef class BinaryMatroid(LinearMatroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid @@ -5017,7 +5017,7 @@ cdef class TernaryMatroid(LinearMatroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid @@ -5779,7 +5779,7 @@ cdef class QuaternaryMatroid(LinearMatroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid @@ -6735,7 +6735,7 @@ cdef class RegularMatroid(LinearMatroid): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 37ceec05874..36d7c7f7352 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -8436,7 +8436,7 @@ cdef class Matroid(SageObject): INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/set_system.pyx b/src/sage/matroids/set_system.pyx index 66468756fe5..d4e306abfdd 100644 --- a/src/sage/matroids/set_system.pyx +++ b/src/sage/matroids/set_system.pyx @@ -215,7 +215,7 @@ cdef class SetSystem: INPUT: - ``mapping`` -- a python object such that ``mapping[e]`` is the new - label of `e` + label of ``e`` OUTPUT: ``None`` """ From abc9ef8c9270bea6e455c70bbce820e5a507aced Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Thu, 11 Apr 2024 18:05:24 +0300 Subject: [PATCH 135/191] Docstring improvements in groups --- src/sage/groups/abelian_gps/abelian_aut.py | 8 +- src/sage/groups/abelian_gps/abelian_group.py | 44 ++---- .../abelian_gps/abelian_group_element.py | 18 +-- .../groups/abelian_gps/abelian_group_gap.py | 44 ++---- .../abelian_gps/abelian_group_morphism.py | 8 +- .../groups/abelian_gps/dual_abelian_group.py | 12 +- .../abelian_gps/dual_abelian_group_element.py | 10 +- src/sage/groups/abelian_gps/element_base.py | 16 +-- src/sage/groups/abelian_gps/values.py | 30 ++-- .../additive_abelian_group.py | 11 +- .../additive_abelian_wrapper.py | 4 +- src/sage/groups/additive_abelian/qmodnz.py | 4 +- .../groups/additive_abelian/qmodnz_element.py | 6 +- src/sage/groups/affine_gps/affine_group.py | 12 +- src/sage/groups/affine_gps/group_element.py | 16 +-- src/sage/groups/artin.py | 29 ++-- src/sage/groups/braid.py | 136 ++++++------------ src/sage/groups/class_function.py | 111 ++++++-------- src/sage/groups/conjugacy_classes.py | 2 - src/sage/groups/cubic_braid.py | 14 +- src/sage/groups/finitely_presented.py | 56 ++------ src/sage/groups/finitely_presented_named.py | 34 ++--- src/sage/groups/fqf_orthogonal.py | 5 +- src/sage/groups/free_group.py | 29 ++-- src/sage/groups/generic.py | 30 ++-- src/sage/groups/group.pyx | 15 +- src/sage/groups/group_exp.py | 21 ++- src/sage/groups/group_semidirect_product.py | 4 +- src/sage/groups/libgap_mixin.py | 33 ++--- src/sage/groups/libgap_morphism.py | 23 ++- src/sage/groups/libgap_wrapper.pxd | 1 - src/sage/groups/libgap_wrapper.pyx | 61 +++----- .../groups/matrix_gps/finitely_generated.py | 15 +- src/sage/groups/matrix_gps/group_element.pyx | 4 +- .../groups/matrix_gps/group_element_gap.pyx | 2 +- src/sage/groups/matrix_gps/linear.py | 2 +- src/sage/groups/matrix_gps/matrix_group.py | 25 ++-- .../groups/matrix_gps/matrix_group_gap.py | 11 +- src/sage/groups/matrix_gps/named_group.py | 18 +-- src/sage/groups/matrix_gps/orthogonal.py | 20 +-- src/sage/groups/matrix_gps/symplectic.py | 2 +- src/sage/groups/matrix_gps/symplectic_gap.py | 2 +- src/sage/groups/matrix_gps/unitary.py | 14 +- src/sage/groups/matrix_gps/unitary_gap.py | 4 +- src/sage/groups/misc_gps/argument_groups.py | 60 ++------ src/sage/groups/misc_gps/imaginary_groups.py | 8 +- src/sage/groups/old.pyx | 12 +- src/sage/groups/perm_gps/constructor.py | 6 +- .../automorphism_group_canonical_label.pyx | 10 +- .../partn_ref/canonical_augmentation.pyx | 4 +- .../perm_gps/partn_ref/data_structures.pxd | 11 +- .../perm_gps/partn_ref/data_structures.pyx | 8 +- .../perm_gps/partn_ref/double_coset.pyx | 11 +- .../perm_gps/partn_ref/refinement_binary.pyx | 49 ++++--- .../perm_gps/partn_ref/refinement_graphs.pyx | 6 +- .../perm_gps/partn_ref/refinement_lists.pxd | 1 - .../partn_ref/refinement_matrices.pyx | 9 +- .../perm_gps/partn_ref/refinement_python.pyx | 28 +--- .../perm_gps/partn_ref/refinement_sets.pyx | 12 +- .../partn_ref2/refinement_generic.pyx | 19 +-- src/sage/groups/perm_gps/permgroup.py | 95 ++++-------- .../groups/perm_gps/permgroup_element.pyx | 42 +++--- src/sage/groups/perm_gps/permgroup_named.py | 128 ++++++----------- .../groups/perm_gps/symgp_conjugacy_class.py | 6 +- .../semimonomial_transformation.pyx | 4 +- .../semimonomial_transformation_group.py | 6 +- 66 files changed, 492 insertions(+), 1009 deletions(-) diff --git a/src/sage/groups/abelian_gps/abelian_aut.py b/src/sage/groups/abelian_gps/abelian_aut.py index b27f9bdb220..894b54f6736 100644 --- a/src/sage/groups/abelian_gps/abelian_aut.py +++ b/src/sage/groups/abelian_gps/abelian_aut.py @@ -176,9 +176,7 @@ def matrix(self): The `i`-th row is the exponent vector of the image of the `i`-th generator. - OUTPUT: - - - a square matrix over the integers + OUTPUT: a square matrix over the integers EXAMPLES:: @@ -315,9 +313,7 @@ def _coerce_map_from_(self, S): - ``S`` -- anything - OUTPUT: - - Boolean or nothing + OUTPUT: boolean or nothing EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index 90cdcaa42fd..a3db5c46179 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -448,7 +448,7 @@ def AbelianGroup(n, gens_orders=None, names="f"): def is_AbelianGroup(x): """ - Return True if ``x`` is an Abelian group. + Return ``True`` if ``x`` is an Abelian group. EXAMPLES:: @@ -558,9 +558,7 @@ def is_isomorphic(left, right): - ``right`` -- anything. - OUTPUT: - - Boolean. Whether ``left`` and ``right`` are isomorphic as abelian groups. + OUTPUT: boolean; whether ``left`` and ``right`` are isomorphic as abelian groups EXAMPLES:: @@ -682,9 +680,7 @@ def dual_group(self, names="X", base_ring=None): - ``base_ring`` -- the base ring. If ``None`` (default), then a suitable cyclotomic field is picked automatically. - OUTPUT: - - The :class:`dual abelian group `. + OUTPUT: the :class:`dual abelian group ` EXAMPLES:: @@ -721,7 +717,7 @@ def elementary_divisors(self): r""" This returns the elementary divisors of the group, using Pari. - .. note:: + .. NOTE:: Here is another algorithm for computing the elementary divisors `d_1, d_2, d_3, \ldots`, of a finite abelian group (where `d_1 | d_2 | d_3 | \ldots` @@ -736,9 +732,7 @@ def elementary_divisors(self): on these "smaller invariants" to compute `d_{i-1}`, and so on. (Thanks to Robert Miller for communicating this algorithm.) - OUTPUT: - - A tuple of integers. + OUTPUT: a tuple of integers EXAMPLES:: @@ -806,15 +800,13 @@ def identity(self): def _group_notation(self, eldv): """ - Return abstract group notation for generator orders ``eldv`` + Return abstract group notation for generator orders ``eldv``. INPUT: - ``eldv`` -- iterable of integers. - OUTPUT: - - String. + OUTPUT: a string EXAMPLES:: @@ -955,9 +947,7 @@ def gens_orders(self): Use :meth:`elementary_divisors` if you are looking for an invariant of the group. - OUTPUT: - - A tuple of integers. + OUTPUT: a tuple of integers EXAMPLES:: @@ -1018,9 +1008,7 @@ def invariants(self): Use :meth:`elementary_divisors` if you are looking for an invariant of the group. - OUTPUT: - - A tuple of integers. Zero means infinite cyclic factor. + OUTPUT: a tuple of integers; zero means infinite cyclic factor EXAMPLES:: @@ -1043,7 +1031,7 @@ def invariants(self): def is_cyclic(self): """ - Return True if the group is a cyclic group. + Return ``True`` if the group is a cyclic group. EXAMPLES:: @@ -1153,7 +1141,7 @@ def permutation_group(self): def is_commutative(self): """ - Return True since this group is commutative. + Return ``True`` since this group is commutative. EXAMPLES:: @@ -1787,11 +1775,9 @@ def __contains__(self, x): def ambient_group(self): """ - Return the ambient group related to self. + Return the ambient group related to ``self``. - OUTPUT: - - A multiplicative Abelian group. + OUTPUT: a multiplicative Abelian group EXAMPLES:: @@ -1879,9 +1865,7 @@ def gens(self) -> tuple: """ Return the generators for this subgroup. - OUTPUT: - - A tuple of group elements generating the subgroup. + OUTPUT: a tuple of group elements generating the subgroup EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/abelian_group_element.py b/src/sage/groups/abelian_gps/abelian_group_element.py index b081f1e1c4e..501872aaedd 100644 --- a/src/sage/groups/abelian_gps/abelian_group_element.py +++ b/src/sage/groups/abelian_gps/abelian_group_element.py @@ -120,22 +120,24 @@ def as_permutation(self): def word_problem(self, words): """ - TODO - this needs a rewrite - see stuff in the matrix_grp - directory. - - G and H are abelian groups, g in G, H is a subgroup of G generated - by a list (words) of elements of G. If self is in H, return the - expression for self as a word in the elements of (words). + ``G`` and ``H`` are abelian groups, ``g`` in ``G``, ``H`` is a + subgroup of ``G`` generated by a list (words) of elements of ``G``. If + ``self`` is in ``H``, return the expression for ``self`` as a word in + the elements of (words). This function does not solve the word problem in Sage. Rather it pushes it over to GAP, which has optimized (non-deterministic) algorithms for the word problem. - .. warning:: + .. WARNING:: - Don't use E (or other GAP-reserved letters) as a generator + Don't use ``E`` (or other GAP-reserved letters) as a generator name. + .. TODO:: + + This needs a rewrite - see stuff in the ``matrix_grp`` directory. + EXAMPLES:: sage: # needs sage.libs.gap diff --git a/src/sage/groups/abelian_gps/abelian_group_gap.py b/src/sage/groups/abelian_gps/abelian_group_gap.py index 9ce83a6e33c..41316f3b433 100644 --- a/src/sage/groups/abelian_gps/abelian_group_gap.py +++ b/src/sage/groups/abelian_gps/abelian_group_gap.py @@ -92,9 +92,7 @@ def __reduce__(self): r""" Implement pickling. - OUTPUT: - - - a tuple ``f`` such that this element is ``f[0](*f[1])`` + OUTPUT: a tuple ``f`` such that this element is ``f[0](*f[1])`` EXAMPLES:: @@ -112,9 +110,7 @@ def exponents(self): r""" Return the tuple of exponents of this element. - OUTPUT: - - - a tuple of integers + OUTPUT: a tuple of integers EXAMPLES:: @@ -172,9 +168,7 @@ def order(self): r""" Return the order of this element. - OUTPUT: - - - an integer or infinity + OUTPUT: an integer or infinity EXAMPLES:: @@ -204,9 +198,7 @@ def exponents(self): r""" Return the tuple of exponents of ``self``. - OUTPUT: - - - a tuple of integers + OUTPUT: a tuple of integers EXAMPLES:: @@ -272,9 +264,7 @@ def _coerce_map_from_(self, S): - ``S`` -- anything - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -492,9 +482,7 @@ def gens_orders(self): Use :meth:`elementary_divisors` if you are looking for an invariant of the group. - OUTPUT: - - - a tuple of integers + OUTPUT: a tuple of integers EXAMPLES:: @@ -598,9 +586,7 @@ def subgroup(self, gens): - ``gens`` -- a list of elements coercible into this group - OUTPUT: - - - a subgroup + OUTPUT: a subgroup EXAMPLES:: @@ -643,9 +629,7 @@ class AbelianGroupGap(AbelianGroup_gap): - ``generator_orders`` -- a list of nonnegative integers where `0` gives a factor isomorphic to `\ZZ` - OUTPUT: - - - an abelian group + OUTPUT: an abelian group EXAMPLES:: @@ -850,9 +834,7 @@ def lift(self, x): - ``x`` -- an element of this subgroup - OUTPUT: - - The corresponding element of the ambient group + OUTPUT: the corresponding element of the ambient group EXAMPLES:: @@ -881,9 +863,7 @@ def retract(self, x): - ``x`` -- an element of the ambient group that actually lies in this subgroup. - OUTPUT: - - The corresponding element of this subgroup + OUTPUT: the corresponding element of this subgroup EXAMPLES:: @@ -980,9 +960,7 @@ def _coerce_map_from_(self, S): - ``S`` -- anything - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/abelian_group_morphism.py b/src/sage/groups/abelian_gps/abelian_group_morphism.py index e4b7b82b42b..a44abb83df9 100644 --- a/src/sage/groups/abelian_gps/abelian_group_morphism.py +++ b/src/sage/groups/abelian_gps/abelian_group_morphism.py @@ -44,10 +44,10 @@ def _repr_type(self): class AbelianGroupMorphism(Morphism): """ - Some python code for wrapping GAP's GroupHomomorphismByImages - function for abelian groups. Returns "fail" if gens does not - generate self or if the map does not extend to a group - homomorphism, self - other. + Some python code for wrapping GAP's ``GroupHomomorphismByImages`` + function for abelian groups. Returns "fail" if ``gens`` does not + generate ``self`` or if the map does not extend to a group + homomorphism, ``self`` - ``other``. EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/dual_abelian_group.py b/src/sage/groups/abelian_gps/dual_abelian_group.py index 4aecfd69816..7b1bbaee40d 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group.py @@ -78,7 +78,7 @@ def is_DualAbelianGroup(x): """ - Return True if `x` is the dual group of an abelian group. + Return ``True`` if `x` is the dual group of an abelian group. EXAMPLES:: @@ -271,9 +271,7 @@ def gens(self) -> tuple: """ Return the generators for the group. - OUTPUT: - - A tuple of group elements generating the group. + OUTPUT: a tuple of group elements generating the group EXAMPLES:: @@ -301,9 +299,7 @@ def gens_orders(self): """ The orders of the generators of the dual group. - OUTPUT: - - A tuple of integers. + OUTPUT: a tuple of integers EXAMPLES:: @@ -361,7 +357,7 @@ def order(self): def is_commutative(self): """ - Return True since this group is commutative. + Return ``True`` since this group is commutative. EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/dual_abelian_group_element.py b/src/sage/groups/abelian_gps/dual_abelian_group_element.py index 6fdb8a68c4e..ecf17404bdd 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -64,9 +64,7 @@ def is_DualAbelianGroupElement(x) -> bool: - ``x`` -- anything - OUTPUT: - - Boolean + OUTPUT: boolean EXAMPLES:: @@ -89,10 +87,8 @@ def __call__(self, g): """ Evaluate ``self`` on a group element ``g``. - OUTPUT: - - An element in - :meth:`~sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class.base_ring`. + OUTPUT: an element in + :meth:`~sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class.base_ring` EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/element_base.py b/src/sage/groups/abelian_gps/element_base.py index 0435c9835b9..43d77c29494 100644 --- a/src/sage/groups/abelian_gps/element_base.py +++ b/src/sage/groups/abelian_gps/element_base.py @@ -165,10 +165,6 @@ def _repr_(self): """ Return a string representation of ``self``. - OUTPUT: - - String. - EXAMPLES:: sage: G = AbelianGroup([2]) @@ -199,9 +195,7 @@ def _richcmp_(self, other, op): The comparison is based on the exponents. - OUTPUT: - - boolean + OUTPUT: boolean EXAMPLES:: @@ -220,9 +214,7 @@ def order(self): """ Return the order of this element. - OUTPUT: - - An integer or ``infinity``. + OUTPUT: an integer or ``infinity`` EXAMPLES:: @@ -335,9 +327,7 @@ def is_trivial(self): """ Test whether ``self`` is the trivial group element ``1``. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/values.py b/src/sage/groups/abelian_gps/values.py index 3db117123f0..eda0858b1f8 100644 --- a/src/sage/groups/abelian_gps/values.py +++ b/src/sage/groups/abelian_gps/values.py @@ -193,16 +193,12 @@ def __init__(self, domain, codomain): def _call_(self, x): """ - Return the value associated to ``x`` + Return the value associated to ``x``. INPUT: - ``x`` -- a group element - OUTPUT: - - Its value. - EXAMPLES:: sage: # needs sage.symbolic @@ -257,10 +253,8 @@ def value(self): """ Return the value of the group element. - OUTPUT: - - The value according to the values for generators, see - :meth:`~AbelianGroupWithValues.gens_values`. + OUTPUT: the value according to the values for generators; see + :meth:`~AbelianGroupWithValues.gens_values` EXAMPLES:: @@ -414,9 +408,7 @@ def gen(self, i=0): - ``i`` -- integer (default: 0). The index of the generator. - OUTPUT: - - A group element. + OUTPUT: a group element EXAMPLES:: @@ -442,9 +434,7 @@ def gens_values(self): """ Return the values associated to the generators. - OUTPUT: - - A tuple. + OUTPUT: a tuple EXAMPLES:: @@ -465,10 +455,8 @@ def values_group(self): units in a ring then the :meth:`values_group` would be the whole ring. - OUTPUT: - - The common parent of the values, containing the group - generated by all values. + OUTPUT: the common parent of the values, containing the group + generated by all values EXAMPLES:: @@ -486,9 +474,7 @@ def values_embedding(self): """ Return the embedding of ``self`` in :meth:`values_group`. - OUTPUT: - - A morphism. + OUTPUT: a morphism EXAMPLES:: diff --git a/src/sage/groups/additive_abelian/additive_abelian_group.py b/src/sage/groups/additive_abelian/additive_abelian_group.py index 167b38a9cc0..394ef807944 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_group.py +++ b/src/sage/groups/additive_abelian/additive_abelian_group.py @@ -25,9 +25,8 @@ def AdditiveAbelianGroup(invs, remember_generators=True): generators (corresponding to the given invariants, which need not be in Smith form). - OUTPUT: - - The abelian group `\bigoplus_i \ZZ / n_i \ZZ`, where `n_i` are the invariants. + OUTPUT: the abelian group `\bigoplus_i \ZZ / n_i \ZZ`, where `n_i` are the + invariants EXAMPLES:: @@ -246,7 +245,7 @@ def _repr_(self): def _latex_(self): r""" - Returns a Latex representation of the group, using the invariants. + Return a Latex representation of the group, using the invariants. EXAMPLES:: @@ -375,7 +374,7 @@ def is_multiplicative(self): def is_cyclic(self): r""" - Returns ``True`` if the group is cyclic. + Return ``True`` if the group is cyclic. EXAMPLES: @@ -422,7 +421,7 @@ def __init__(self, cover, rels, gens): def gens(self) -> tuple: r""" - Return the specified generators for self (as a tuple). Compare + Return the specified generators for ``self`` (as a tuple). Compare ``self.smithform_gens()``. EXAMPLES:: diff --git a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py index 3edddea25e7..c12a67725b6 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py +++ b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py @@ -160,7 +160,7 @@ def element(self): def _repr_(self): r""" - String representation of self. + String representation of ``self``. EXAMPLES:: @@ -290,7 +290,7 @@ def discrete_exp(self, v): r""" Given a list (or other iterable) of length equal to the number of generators of this group, compute the element of the ambient group - with those exponents in terms of the generators of self. + with those exponents in terms of the generators of ``self``. EXAMPLES:: diff --git a/src/sage/groups/additive_abelian/qmodnz.py b/src/sage/groups/additive_abelian/qmodnz.py index db0b23d5fe4..34e9a0e9132 100644 --- a/src/sage/groups/additive_abelian/qmodnz.py +++ b/src/sage/groups/additive_abelian/qmodnz.py @@ -54,9 +54,7 @@ class QmodnZ(Parent, UniqueRepresentation): - `n` -- an integer (including 0 or negative integers). - OUTPUT: - - The abelian group `\Q/n\Z`. + OUTPUT: the abelian group `\Q/n\Z` EXAMPLES:: diff --git a/src/sage/groups/additive_abelian/qmodnz_element.py b/src/sage/groups/additive_abelian/qmodnz_element.py index 10f92f76bf9..73557159161 100644 --- a/src/sage/groups/additive_abelian/qmodnz_element.py +++ b/src/sage/groups/additive_abelian/qmodnz_element.py @@ -38,9 +38,7 @@ class QmodnZ_Element(AdditiveGroupElement): - ``parent`` -- the parent abelian group `\Q/n\Z`. - OUTPUT: - - The element `q` of abelian group `\Q/n\Z`, in standard form. + OUTPUT: the element `q` of abelian group `\Q/n\Z`, in standard form EXAMPLES:: @@ -330,7 +328,7 @@ def _richcmp_(self, right, op): def additive_order(self): r""" - Returns the order of this element in the abelian group `\Q/n\Z`. + Return the order of this element in the abelian group `\Q/n\Z`. EXAMPLES:: diff --git a/src/sage/groups/affine_gps/affine_group.py b/src/sage/groups/affine_gps/affine_group.py index a811640c3c0..38fa05058e0 100644 --- a/src/sage/groups/affine_gps/affine_group.py +++ b/src/sage/groups/affine_gps/affine_group.py @@ -308,7 +308,7 @@ def degree(self): """ Return the dimension of the affine space. - OUTPUT: An integer. + OUTPUT: an integer EXAMPLES:: @@ -327,10 +327,8 @@ def matrix_space(self): Return the space of matrices representing the general linear transformations. - OUTPUT: - - The parent of the matrices `A` defining the affine group - element `Ax+b`. + OUTPUT: the parent of the matrices `A` defining the affine group + element `Ax+b` EXAMPLES:: @@ -393,7 +391,7 @@ def linear(self, A): - ``A`` -- anything that determines a matrix - OUTPUT: The affine group element `x \mapsto A x`. + OUTPUT: The affine group element `x \mapsto A x` EXAMPLES:: @@ -414,7 +412,7 @@ def translation(self, b): - ``b`` -- anything that determines a vector - OUTPUT: The affine group element `x \mapsto x + b`. + OUTPUT: The affine group element `x \mapsto x + b` EXAMPLES:: diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index 42546194bb6..703137784e4 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -145,7 +145,7 @@ def A(self): """ Return the general linear part of an affine group element. - OUTPUT: The matrix `A` of the affine group element `Ax + b`. + OUTPUT: The matrix `A` of the affine group element `Ax + b` EXAMPLES:: @@ -162,7 +162,7 @@ def b(self): """ Return the translation part of an affine group element. - OUTPUT: The vector `b` of the affine group element `Ax + b`. + OUTPUT: The vector `b` of the affine group element `Ax + b` EXAMPLES:: @@ -328,11 +328,8 @@ def _mul_(self, other): - ``other`` -- another element of the same affine group. - OUTPUT: - - The product of the affine group elements ``self`` and - ``other`` defined by the composition of the two affine - transformations. + OUTPUT: the product of the affine group elements ``self`` and + ``other`` defined by the composition of the two affine transformations EXAMPLES:: @@ -359,7 +356,7 @@ def __call__(self, v): - ``v`` -- a polynomial, a multivariate polynomial, a polyhedron, a vector, or anything that can be converted into a vector. - OUTPUT: The image of ``v`` under the affine group element. + OUTPUT: the image of ``v`` under the affine group element EXAMPLES:: @@ -402,7 +399,6 @@ def __call__(self, v): sage: cube = polytopes.cube() # needs sage.geometry.polyhedron sage: f(cube) # needs sage.geometry.polyhedron A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices - """ parent = self.parent() @@ -455,7 +451,7 @@ def __invert__(self): """ Return the inverse group element. - OUTPUT: Another affine group element. + OUTPUT: another affine group element EXAMPLES:: diff --git a/src/sage/groups/artin.py b/src/sage/groups/artin.py index afb40463206..a198bccef69 100644 --- a/src/sage/groups/artin.py +++ b/src/sage/groups/artin.py @@ -51,9 +51,7 @@ def _latex_(self): r""" Return a LaTeX representation of ``self``. - OUTPUT: - - String. A valid LaTeX math command sequence. + OUTPUT: a string; a valid LaTeX math command sequence TESTS:: @@ -79,9 +77,7 @@ def exponent_sum(self): """ Return the exponent sum of ``self``. - OUTPUT: - - Integer. + OUTPUT: an integer EXAMPLES:: @@ -111,11 +107,10 @@ def coxeter_group_element(self, W=None): INPUT: - - ``W`` -- (default: ``self.parent().coxeter_group()``) the image Coxeter group - - OUTPUT: + - ``W`` -- (default: ``self.parent().coxeter_group()``) the image + Coxeter group - An element of the Coxeter group ``W``. + OUTPUT: an element of the Coxeter group ``W`` EXAMPLES:: @@ -263,10 +258,8 @@ def _left_normal_form_coxeter(self): Return the left normal form of the element, in the `\Delta` exponent and Coxeter group element form. - OUTPUT: - - A tuple whose first element is the power of `\Delta`, and the rest - are the Coxeter elements corresponding to the simple factors. + OUTPUT: a tuple whose first element is the power of `\Delta`, and the + rest are the Coxeter elements corresponding to the simple factors EXAMPLES:: @@ -515,9 +508,7 @@ def cardinality(self): """ Return the number of elements of ``self``. - OUTPUT: - - Infinity. + OUTPUT: Infinity EXAMPLES:: @@ -605,9 +596,7 @@ def index_set(self): """ Return the index set of ``self``. - OUTPUT: - - A tuple. + OUTPUT: a tuple EXAMPLES:: diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index 3b48e00effd..71550739296 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -170,9 +170,7 @@ def components_in_closure(self): """ Return the number of components of the trace closure of the braid. - OUTPUT: - - Positive integer. + OUTPUT: a positive integer EXAMPLES:: @@ -442,9 +440,7 @@ def permutation(self, W=None): - ``W`` -- (optional) the permutation group to project ``self`` to; the default is ``self.parent().coxeter_group()`` - OUTPUT: - - The image of ``self`` under the natural projection map to ``W``. + OUTPUT: the image of ``self`` under the natural projection map to ``W`` EXAMPLES:: @@ -676,9 +672,8 @@ def LKB_matrix(self, variables='x,y'): - ``variables`` -- string (default: ``'x,y'``). A string containing the names of the variables, separated by a comma. - OUTPUT: - - The matrix corresponding to the Lawrence-Krammer-Bigelow representation of the braid. + OUTPUT: the matrix corresponding to the Lawrence-Krammer-Bigelow + representation of the braid EXAMPLES:: @@ -811,10 +806,9 @@ def links_gould_matrix(self, symbolics=False): are elements of a quotient ring of a three variate Laurent polynomial ring. - OUTPUT: - - The representation matrix of ``self`` over the ring according to the choice - of the keyword ``symbolics`` (see the corresponding explanation). + OUTPUT: the representation matrix of ``self`` over the ring according + to the choice of the keyword ``symbolics`` (see the corresponding + explanation) EXAMPLES:: @@ -849,9 +843,7 @@ def links_gould_polynomial(self, varnames=None, use_symbolics=False): - ``varnames`` -- string (default ``t0, t1``) - OUTPUT: - - A Laurent polynomial in the given variable names. + OUTPUT: a Laurent polynomial in the given variable names EXAMPLES:: @@ -908,9 +900,7 @@ def tropical_coordinates(self): r""" Return the tropical coordinates of ``self`` in the braid group `B_n`. - OUTPUT: - - - a list of `2n` tropical integers + OUTPUT: a list of `2n` tropical integers EXAMPLES:: @@ -1325,9 +1315,7 @@ def _annular_khovanov_complex_cached(self, qagrad, ring=None): - ``ring`` -- (default: ``ZZ``) the coefficient ring - OUTPUT: - - The annular Khovanov complex of the braid in the given grading. + OUTPUT: the annular Khovanov complex of the braid in the given grading .. NOTE:: @@ -1380,8 +1368,8 @@ def annular_khovanov_complex(self, qagrad=None, ring=None): OUTPUT: The annular Khovanov complex of the braid, given as a dictionary whose - keys are tuples of quantum and annular grading. - If ``qagrad`` is specified only return the chain complex of that grading. + keys are tuples of quantum and annular grading. If ``qagrad`` is + specified only return the chain complex of that grading. EXAMPLES:: @@ -1437,9 +1425,9 @@ def annular_khovanov_homology(self, qagrad=None, ring=IntegerRing()): OUTPUT: - If ``qagrad`` is ``None``, return a dictionary of homogies in all - gradings indexed by grading. If qagrad is specified, return homology - of that grading. + If ``qagrad`` is ``None``, return a dictionary of homologies in all + gradings indexed by grading. If ``qagrad`` is specified, return the + homology of that grading. .. NOTE:: @@ -1535,10 +1523,8 @@ def _left_normal_form_coxeter(self): r""" Return the left normal form of the braid, in permutation form. - OUTPUT: - - A tuple whose first element is the power of `\Delta`, and the - rest are the permutations corresponding to the simple factors. + OUTPUT: a tuple whose first element is the power of `\Delta`, and the + rest are the permutations corresponding to the simple factors EXAMPLES:: @@ -1633,7 +1619,6 @@ def centralizer(self): sage: b = B([2, 1, 3, 2]) sage: b.centralizer() [s1*s0*s2*s1, s0*s2] - """ c = centralizer(self) B = self.parent() @@ -1652,7 +1637,6 @@ def super_summit_set(self): (s0^-1*s1^-1*s0^-1)^2*s1^2*s0^3*s1, (s0^-1*s1^-1*s0^-1)^2*s1*s0^3*s1^2, s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^3*s0] - """ sss = supersummitset(self) B = self.parent() @@ -1710,10 +1694,8 @@ def conjugating_braid(self, other): OUTPUT: - A conjugating braid. - - More precisely, if the output is `d`, `o` equals ``other``, and `s` equals ``self`` - then `o = d^{-1} \cdot s \cdot d`. + A conjugating braid. More precisely, if the output is `d`, `o` equals + ``other``, and `s` equals ``self`` then `o = d^{-1} \cdot s \cdot d`. EXAMPLES:: @@ -1798,10 +1780,9 @@ def pure_conjugating_braid(self, other): OUTPUT: - A pure conjugating braid. - - More precisely, if the output is `d`, `o` equals ``other``, and `s` equals ``self`` - then `o = d^{-1} \cdot s \cdot d`. + A pure conjugating braid. More precisely, if the output is `d`, `o` + equals ``other``, and `s` equals ``self`` then + `o = d^{-1} \cdot s \cdot d`. EXAMPLES:: @@ -1914,9 +1895,7 @@ def thurston_type(self): """ Return the thurston_type of ``self``. - OUTPUT: - - One of ``'reducible'``, ``'periodic'`` or ``'pseudo-anosov'``. + OUTPUT: one of ``'reducible'``, ``'periodic'`` or ``'pseudo-anosov'`` EXAMPLES:: @@ -1946,7 +1925,6 @@ def is_reducible(self): sage: a = B([2, 2, -1, -1, 2, 2]) sage: a.is_reducible() False - """ return self.thurston_type() == 'reducible' @@ -2002,9 +1980,7 @@ def sliding_circuits(self): """ Return the sliding circuits of the braid. - OUTPUT: - - A list of sliding circuits. Each sliding circuit is itself + OUTPUT: a list of sliding circuits. Each sliding circuit is itself a list of braids. EXAMPLES:: @@ -2081,9 +2057,7 @@ def deformed_burau_matrix(self, variab='q'): resulting laurent polynomial, which is the base ring for the free algebra constructed - OUTPUT: - - A matrix with elements in the free algebra ``self._algebra``. + OUTPUT: a matrix with elements in the free algebra ``self._algebra`` EXAMPLES:: @@ -2333,10 +2307,8 @@ def tuples(self): This is in the reduced form as outlined in Definition 4.1 of [HL2018]_. - OUTPUT: - - A dict of tuples of ints corresponding to the exponents in the - generators with values in the algebra's base ring. + OUTPUT: a dict of tuples of ints corresponding to the exponents in the + generators with values in the algebra's base ring EXAMPLES:: @@ -2384,9 +2356,7 @@ def reduced_word(self): r""" Return the (reduced) right quantum word. - OUTPUT: - - An element in the free algebra. + OUTPUT: an element in the free algebra EXAMPLES:: @@ -2619,11 +2589,7 @@ def __reduce__(self): def _repr_(self): """ - Return a string representation - - OUTPUT: - - String. + Return a string representation. TESTS:: @@ -2637,9 +2603,7 @@ def cardinality(self): """ Return the number of group elements. - OUTPUT: - - Infinity. + OUTPUT: Infinity TESTS:: @@ -2656,10 +2620,8 @@ def as_permutation_group(self): """ Return an isomorphic permutation group. - OUTPUT: - - This raises a :class:`ValueError` error since braid groups - are infinite. + OUTPUT: this raises a :class:`ValueError` error since braid groups + are infinite TESTS:: @@ -2675,9 +2637,7 @@ def strands(self): """ Return the number of strands. - OUTPUT: - - Integer. + OUTPUT: an integer EXAMPLES:: @@ -2753,10 +2713,7 @@ def _standard_lift_Tietze(self, p): - Every two strands cross each other at most once. - OUTPUT: - - A shortest word that represents the braid, - in Tietze list form. + OUTPUT: a shortest word that represents the braid, in Tietze list form EXAMPLES:: @@ -2887,9 +2844,7 @@ def _LKB_matrix_(self, braid, variab): appear in the matrix. They must be given as a string, separated by a comma - OUTPUT: - - The LKB matrix of the braid, with respect to the variables. + OUTPUT: the LKB matrix of the braid, with respect to the variables TESTS:: @@ -3036,9 +2991,7 @@ def TL_basis_with_drain(self, drain_size): - ``drain_size`` -- integer between 0 and the number of strands (both inclusive) - OUTPUT: - - A list of basis elements, each of which is a list of integers. + OUTPUT: a list of basis elements, each of which is a list of integers EXAMPLES: @@ -3220,10 +3173,8 @@ def TL_representation(self, drain_size, variab=None): entries of the matrices; if ``None``, then use a default variable in `\ZZ[A,A^{-1}]` - OUTPUT: - - A list of matrices corresponding to the representations of each - of the standard generators and their inverses. + OUTPUT: a list of matrices corresponding to the representations of each + of the standard generators and their inverses EXAMPLES:: @@ -3311,7 +3262,8 @@ def TL_representation(self, drain_size, variab=None): def mapping_class_action(self, F): """ - Return the action of self in the free group F as mapping class group. + Return the action of ``self`` in the free group F as mapping class + group. This action corresponds to the action of the braid over the punctured disk, whose fundamental group is the free group on @@ -3321,9 +3273,7 @@ def mapping_class_action(self, F): element with a braid. So you generally do not have to construct this action yourself. - OUTPUT: - - A :class:`MappingClassGroupAction`. + OUTPUT: a :class:`MappingClassGroupAction` EXAMPLES:: @@ -3650,9 +3600,7 @@ def _act_(self, b, x): - ``x`` -- a free group element. - OUTPUT: - - A new braid. + OUTPUT: a new braid TESTS:: diff --git a/src/sage/groups/class_function.py b/src/sage/groups/class_function.py index 6ca0d9ee2cb..0af4d5ce646 100644 --- a/src/sage/groups/class_function.py +++ b/src/sage/groups/class_function.py @@ -4,11 +4,13 @@ This module implements a wrapper of GAP's ClassFunction function. -NOTE: The ordering of the columns of the character table of a group -corresponds to the ordering of the list. However, in general there is -no way to canonically list (or index) the conjugacy classes of a group. -Therefore the ordering of the columns of the character table of -a group is somewhat random. +.. NOTE: + + The ordering of the columns of the character table of a group + corresponds to the ordering of the list. However, in general there is + no way to canonically list (or index) the conjugacy classes of a group. + Therefore the ordering of the columns of the character table of + a group is somewhat random. AUTHORS: @@ -53,7 +55,6 @@ def ClassFunction(group, values): - ``values`` -- list/tuple/iterable of numbers. The values of the class function on the conjugacy classes, in that order. - EXAMPLES:: sage: G = CyclicPermutationGroup(4) @@ -132,7 +133,7 @@ def __init__(self, G, values): def _gap_init_(self): r""" - Return a string showing how to declare / initialize self in Gap. + Return a string showing how to declare / initialize ``self`` in Gap. Stored in the \code{self._gap_string} attribute. EXAMPLES:: @@ -146,7 +147,7 @@ def _gap_init_(self): def _gap_(self, *args): r""" - Coerce self into a GAP element. + Coerce ``self`` into a GAP element. EXAMPLES:: @@ -182,7 +183,7 @@ def __repr__(self): def __iter__(self): r""" - Iterate through the values of self evaluated on the conjugacy + Iterate through the values of ``self`` evaluated on the conjugacy classes. EXAMPLES:: @@ -296,16 +297,13 @@ def __call__(self, g): def __add__(self, other): r""" - Return the sum of the characters self and other. + Return the sum of the characters of ``self`` and other. INPUT: - - ``other`` -- a :class:`ClassFunction` of the same group as - ``self``. - - OUTPUT: + - ``other`` -- a :class:`ClassFunction` of the same group as ``self`` - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -330,9 +328,7 @@ def __sub__(self, other): - ``other`` -- a :class:`ClassFunction` of the same group as ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -361,9 +357,7 @@ def __mul__(self, other): can be converted into GAP: integers, rational, and elements of certain number fields. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -376,7 +370,6 @@ def __mul__(self, other): sage: (3*chi1).values() [9, 3, -3, 0, -3] - sage: (1/2*chi1).values() [3/2, 1/2, -1/2, 0, -1/2] @@ -420,9 +413,7 @@ def __pos__(self): r""" Return ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -440,9 +431,7 @@ def __neg__(self): r""" Return the additive inverse of ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -458,7 +447,7 @@ def __neg__(self): def __pow__(self, other): r""" - Return the product of self with itself other times. + Return the product of ``self`` with itself other times. EXAMPLES:: @@ -475,7 +464,7 @@ def __pow__(self, other): def symmetric_power(self, n): r""" - Return the symmetrized product of self with itself ``n`` times. + Return the symmetrized product of ``self`` with itself ``n`` times. INPUT: @@ -501,21 +490,20 @@ def symmetric_power(self, n): def exterior_power(self, n): r""" - Return the anti-symmetrized product of self with itself ``n`` times. + Return the antisymmetrized product of ``self`` with itself ``n`` + times. INPUT: - ``n`` -- a positive integer. - OUTPUT: - - The ``n``-th anti-symmetrized power of ``self`` as a - :class:`ClassFunction`. + OUTPUT: the ``n``-th antisymmetrized power of ``self`` as a + :class:`ClassFunction` EXAMPLES:: sage: chi = ClassFunction(SymmetricGroup(4), gap([3, 1, -1, 0, -1])) - sage: p = chi.exterior_power(3) # the highest anti-symmetric power for a 3-d character + sage: p = chi.exterior_power(3) # the highest antisymmetric power for a 3-d character sage: p Character of Symmetric group of order 4! as a permutation group sage: p.values() @@ -529,7 +517,7 @@ def exterior_power(self, n): def scalar_product(self, other): r""" - Return the scalar product of self with other. + Return the scalar product of ``self`` with other. EXAMPLES:: @@ -546,8 +534,8 @@ def scalar_product(self, other): def is_irreducible(self): r""" - Return True if self cannot be written as the sum of two nonzero - characters of self. + Return ``True`` if ``self`` cannot be written as the sum of two nonzero + characters of ``self``. EXAMPLES:: @@ -635,7 +623,7 @@ def norm(self): def values(self) -> list: r""" - Return the list of values of self on the conjugacy classes. + Return the list of values of ``self`` on the conjugacy classes. EXAMPLES:: @@ -1005,9 +993,7 @@ def __add__(self, other): - ``other`` -- a :class:`ClassFunction` of the same group as ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -1032,9 +1018,7 @@ def __sub__(self, other): - ``other`` -- a :class:`ClassFunction` of the same group as ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -1063,9 +1047,7 @@ def __mul__(self, other): can be converted into GAP: integers, rational, and elements of certain number fields. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -1078,7 +1060,6 @@ def __mul__(self, other): sage: (3*chi1).values() [9, 3, -3, 0, -3] - sage: (1/2*chi1).values() [3/2, 1/2, -1/2, 0, -1/2] @@ -1122,9 +1103,7 @@ def __pos__(self): r""" Return ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -1142,9 +1121,7 @@ def __neg__(self): r""" Return the additive inverse of ``self``. - OUTPUT: - - A :class:`ClassFunction` + OUTPUT: a :class:`ClassFunction` EXAMPLES:: @@ -1183,10 +1160,8 @@ def symmetric_power(self, n): - ``n`` -- a positive integer - OUTPUT: - - The ``n``-th symmetrized power of ``self`` as a - :class:`ClassFunction`. + OUTPUT: the ``n``-th symmetrized power of ``self`` as a + :class:`ClassFunction` EXAMPLES:: @@ -1203,21 +1178,19 @@ def symmetric_power(self, n): def exterior_power(self, n): r""" - Return the anti-symmetrized product of ``self`` with itself ``n`` times. + Return the antisymmetrized product of ``self`` with itself ``n`` times. INPUT: - ``n`` -- a positive integer - OUTPUT: - - The ``n``-th anti-symmetrized power of ``self`` as a - :class:`ClassFunction`. + OUTPUT: the ``n``-th antisymmetrized power of ``self`` as a + :class:`ClassFunction` EXAMPLES:: sage: chi = ClassFunction(SymmetricGroup(4), [3, 1, -1, 0, -1]) - sage: p = chi.exterior_power(3) # the highest anti-symmetric power for a 3-d character + sage: p = chi.exterior_power(3) # the highest antisymmetric power for a 3-d character sage: p Character of Symmetric group of order 4! as a permutation group sage: p.values() @@ -1338,7 +1311,7 @@ def norm(self): def values(self): r""" - Return the list of values of self on the conjugacy classes. + Return the list of values of ``self`` on the conjugacy classes. EXAMPLES:: @@ -1410,9 +1383,7 @@ def restrict(self, H): - ``H`` -- a subgroup of the underlying group of ``self``. - OUTPUT: - - A :class:`ClassFunction` of ``H`` defined by restriction. + OUTPUT: a :class:`ClassFunction` of ``H`` defined by restriction EXAMPLES:: diff --git a/src/sage/groups/conjugacy_classes.py b/src/sage/groups/conjugacy_classes.py index 147cc803842..2208389e17d 100644 --- a/src/sage/groups/conjugacy_classes.py +++ b/src/sage/groups/conjugacy_classes.py @@ -216,7 +216,6 @@ def __iter__(self): True sage: any(x == m2 for x in C) True - """ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet g = self._representative @@ -517,7 +516,6 @@ def set(self): sage: S = [(1,3,2,4), (1,4,3,2), (1,3,4,2), (1,2,3,4), (1,4,2,3), (1,2,4,3)] sage: C.set() == Set(G(x) for x in S) True - """ from sage.sets.set import Set try: diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index c80da80520e..17e543687a4 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -807,10 +807,6 @@ def _repr_(self): r""" Return a string representation. - OUTPUT: - - String describing ``self``. - EXAMPLES:: sage: CubicBraidGroup(2) @@ -1423,10 +1419,8 @@ def braid_group(self): Return a :class:`BraidGroup` with identical generators, such that there exists an epimorphism to ``self``. - OUTPUT: - - A :class:`BraidGroup` having conversion maps to and from ``self`` - (which is just a section in the latter case). + OUTPUT: a :class:`BraidGroup` having conversion maps to and from + ``self`` (which is just a section in the latter case) EXAMPLES:: @@ -1973,9 +1967,7 @@ def order(self): To avoid long wait-time on calculations the order will be obtained using the classical realization. - OUTPUT: - - Cardinality of the group as Integer or infinity. + OUTPUT: cardinality of the group as integer or infinity EXAMPLES:: diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 7d96975fe22..adb166093cd 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -269,10 +269,6 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. - EXAMPLES:: sage: G. = FreeGroup() @@ -300,9 +296,7 @@ def Tietze(self): the letter corresponding to the `i`-th generator of the group. Negative integers represent the inverses of generators. - OUTPUT: - - A tuple of integers. + OUTPUT: a tuple of integers EXAMPLES:: @@ -332,10 +326,8 @@ def __call__(self, *values, **kwds): ``True``). Whether to verify that ``values`` satisfy the relations in the finitely presented group. - OUTPUT: - - The product of ``values`` in the order and with exponents - specified by ``self``. + OUTPUT: the product of ``values`` in the order and with exponents + specified by ``self`` EXAMPLES:: @@ -386,9 +378,7 @@ def wrap_FpGroup(libgap_fpgroup): - ``libgap_fpgroup`` -- a LibGAP finitely presented group - OUTPUT: - - A Sage :class:`FinitelyPresentedGroup`. + OUTPUT: a Sage :class:`FinitelyPresentedGroup` EXAMPLES: @@ -813,10 +803,6 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. - TESTS:: sage: G. = FreeGroup() @@ -834,9 +820,7 @@ def _latex_(self): """ Return a LaTeX representation - OUTPUT: - - String. A valid LaTeX math command sequence. + OUTPUT: a string; a valid LaTeX math command sequence TESTS:: @@ -864,9 +848,7 @@ def free_group(self): """ Return the free group (without relations). - OUTPUT: - - A :func:`~sage.groups.free_group.FreeGroup`. + OUTPUT: a :func:`~sage.groups.free_group.FreeGroup` EXAMPLES:: @@ -883,9 +865,7 @@ def relations(self): """ Return the relations of the group. - OUTPUT: - - The relations as a tuple of elements of :meth:`free_group`. + OUTPUT: the relations as a tuple of elements of :meth:`free_group` EXAMPLES:: @@ -910,9 +890,7 @@ def cardinality(self, limit=4096000): - ``limit`` -- integer (default: 4096000). The maximal number of cosets before the computation is aborted. - OUTPUT: - - Integer or ``Infinity``. The number of elements in the group. + OUTPUT: integer or ``Infinity``; the number of elements in the group EXAMPLES:: @@ -1036,10 +1014,8 @@ def direct_product(self, H, reduced=False, new_names=True): to keep the old variable names, as they may change meaning in the output group if its presentation is reduced. - OUTPUT: - - The direct product of ``self`` with ``H`` as a finitely - presented group. + OUTPUT: the direct product of ``self`` with ``H`` as a finitely + presented group EXAMPLES:: @@ -1358,9 +1334,8 @@ def abelianization_map(self): r""" Return the abelianization map of ``self``. - OUTPUT: - - The abelianization map of ``self`` as a homomorphism of finitely presented groups. + OUTPUT: the abelianization map of ``self`` as a homomorphism of + finitely presented groups EXAMPLES:: @@ -1530,11 +1505,10 @@ def simplified(self): def sorted_presentation(self): """ - Return the same presentation with the relations sorted to ensure equality. - - OUTPUT: + Return the same presentation with the relations sorted to ensure + equality. - A new finitely presented group with the relations sorted. + OUTPUT: a new finitely presented group with the relations sorted EXAMPLES:: diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py index d800bf014d0..256ad33404f 100644 --- a/src/sage/groups/finitely_presented_named.py +++ b/src/sage/groups/finitely_presented_named.py @@ -79,9 +79,7 @@ def CyclicPresentation(n): - ``n`` -- The order of the cyclic presentation to be returned. - OUTPUT: - - The cyclic group of order `n` as finite presentation. + OUTPUT: the cyclic group of order `n` as finite presentation EXAMPLES:: @@ -219,10 +217,8 @@ def FinitelyGeneratedHeisenbergPresentation(n=1, p=0): - ``p`` -- (optional) a prime number, where we construct the Heisenberg group over the finite field `\ZZ/p\ZZ` - OUTPUT: - - Finitely generated Heisenberg group over the finite field - of order ``p`` or over the integers. + OUTPUT: finitely generated Heisenberg group over the finite field + of order ``p`` or over the integers .. SEEALSO:: @@ -304,9 +300,7 @@ def DihedralPresentation(n): - ``n`` -- The size of the set that `D_n` is acting on. - OUTPUT: - - Dihedral group of order `2n`. + OUTPUT: Dihedral group of order `2n` EXAMPLES:: @@ -343,9 +337,7 @@ def DiCyclicPresentation(n): - ``n`` -- positive integer, 2 or greater, determining the order of the group (`4n`). - OUTPUT: - - The dicyclic group of order `4n` is defined by the presentation + OUTPUT: the dicyclic group of order `4n` is defined by the presentation .. MATH:: @@ -441,9 +433,7 @@ def QuaternionPresentation(): r""" Build the Quaternion group of order 8 as a finitely presented group. - OUTPUT: - - Quaternion group as a finite presentation. + OUTPUT: Quaternion group as a finite presentation EXAMPLES:: @@ -520,9 +510,7 @@ def KleinFourPresentation(): r""" Build the Klein group of order `4` as a finitely presented group. - OUTPUT: - - Klein four group (`C_2 \times C_2`) as a finitely presented group. + OUTPUT: Klein four group (`C_2 \times C_2`) as a finitely presented group EXAMPLES:: @@ -548,9 +536,7 @@ def BinaryDihedralPresentation(n): - ``n`` -- the value `n` - OUTPUT: - - The binary dihedral group of order `4n` as finite presentation. + OUTPUT: the binary dihedral group of order `4n` as finite presentation EXAMPLES:: @@ -579,9 +565,7 @@ def CactusPresentation(n): r""" Build the `n`-fruit cactus group as a finitely presented group. - OUTPUT: - - Cactus group `J_n` as a finitely presented group. + OUTPUT: Cactus group `J_n` as a finitely presented group EXAMPLES:: diff --git a/src/sage/groups/fqf_orthogonal.py b/src/sage/groups/fqf_orthogonal.py index 8c996ad3c6a..f810e8dccb3 100644 --- a/src/sage/groups/fqf_orthogonal.py +++ b/src/sage/groups/fqf_orthogonal.py @@ -5,7 +5,6 @@ consists of all linear self-maps of `T` which preserve the torsion quadratic form. - EXAMPLES:: sage: L = IntegralLattice("A2").twist(2) # needs sage.graphs @@ -436,9 +435,7 @@ def _act_(self, g, a): - ``a`` -- an element of the invariant submodule - ``g`` -- an element of the acting group - OUTPUT: - - - an element of the invariant submodule + OUTPUT: an element of the invariant submodule EXAMPLES:: diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index 471940f6b95..1da411b3036 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -82,9 +82,7 @@ def is_FreeGroup(x): - ``x`` -- anything. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -245,9 +243,7 @@ def _latex_(self): r""" Return a LaTeX representation - OUTPUT: - - String. A valid LaTeX math command sequence. + OUTPUT: a string; a valid LaTeX math command sequence EXAMPLES:: @@ -305,9 +301,7 @@ def Tietze(self): the letter corresponding to the `i`-th generator of the group. Negative integers represent the inverses of generators. - OUTPUT: - - A tuple of integers. + OUTPUT: a tuple of integers EXAMPLES:: @@ -527,10 +521,8 @@ def __call__(self, *values): list/tuple/iterable of the same length as the number of generators of the free group. - OUTPUT: - - The product of ``values`` in the order and with exponents - specified by ``self``. + OUTPUT: the product of ``values`` in the order and with exponents + specified by ``self`` EXAMPLES:: @@ -700,9 +692,7 @@ def wrap_FreeGroup(libgap_free_group): - ``libgap_free_group`` -- a LibGAP free group. - OUTPUT: - - A Sage :class:`FreeGroup_class`. + OUTPUT: a Sage :class:`FreeGroup_class` EXAMPLES: @@ -792,13 +782,11 @@ def _repr_(self): def rank(self): """ - Return the number of generators of self. + Return the number of generators of ``self``. Alias for :meth:`ngens`. - OUTPUT: - - Integer. + OUTPUT: an integer EXAMPLES:: @@ -951,7 +939,6 @@ def quotient(self, relations, **kwds): Free Group on generators {a, b} sage: F1/[r] Finitely presented group < a, b, c, d | a*b*a^-1 > - """ from sage.groups.finitely_presented import FinitelyPresentedGroup return FinitelyPresentedGroup(self, tuple(map(self, relations) ), **kwds) diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index fccb76fe0ef..5a540088d2c 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -15,7 +15,6 @@ multiplication_names = ('multiplication', 'times', 'product', '*') addition_names = ('addition', 'plus', 'sum', '+') - Also included are a generic function for computing multiples (or powers), and an iterator for general multiples and powers. @@ -401,10 +400,12 @@ def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): An integer `n` such that `a^n = b` (or `na = b`). If no such `n` exists, this function raises a :class:`ValueError` exception. - NOTE: This is a generalization of discrete logarithm. One - situation where this version is useful is to find the order of - an element in a group where we only have bounds on the group - order (see the elliptic curve example below). + .. NOTE:: + + This is a generalization of discrete logarithm. One + situation where this version is useful is to find the order of + an element in a group where we only have bounds on the group + order (see the elliptic curve example below). ALGORITHM: Baby step giant step. Time and space are soft `O(\sqrt{n})` where `n` is the difference between upper and lower @@ -992,7 +993,7 @@ def discrete_log_lambda(a, base, bounds, operation='*', identity=None, inverse=N - op() -- function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group - hash_function -- having an efficient hash function is critical for this algorithm - OUTPUT: Returns an integer `n` such that `a=base^n` (or `a=n*base`) + OUTPUT: an integer `n` such that `a=base^n` (or `a=n*base`) ALGORITHM: Pollard Lambda, if bounds are (lb,ub) it has time complexity O(sqrt(ub-lb)) and space complexity O(log(ub-lb)) @@ -1213,10 +1214,10 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True, - ``inverse()`` -- function of 1 argument ``x``, returning inverse of ``x``; - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group. - .. note:: + .. NOTE:: - It is more efficient for the caller to factor ``m`` and cache - the factors for subsequent calls. + It is more efficient for the caller to factor ``m`` and cache + the factors for subsequent calls. EXAMPLES:: @@ -1362,8 +1363,7 @@ def order_from_bounds(P, bounds, d=None, operation='+', - ``op()`` -- a function of 2 arguments defining the group binary operation. - - .. note:: + .. NOTE:: Typically ``lb`` and ``ub`` will be bounds on the group order, and from previous calculation we know that the group order is @@ -1549,9 +1549,7 @@ def merge_points(P1, P2, operation='+', - ``op()`` -- a function of 2 arguments defining the group binary operation. - OUTPUT: - - A pair `(g_3,n_3)` where `g_3` has order `n_3=\hbox{lcm}(n_1,n_2)`. + OUTPUT: a pair `(g_3,n_3)` where `g_3` has order `n_3=\hbox{lcm}(n_1,n_2)` EXAMPLES:: @@ -1631,9 +1629,7 @@ def structure_description(G, latex=False): - ``latex`` -- a boolean (default: ``False``). If ``True``, return a LaTeX formatted string. - OUTPUT: - - string + OUTPUT: a string .. WARNING:: diff --git a/src/sage/groups/group.pyx b/src/sage/groups/group.pyx index 9ecbfde9d6f..2f1a6cc1846 100644 --- a/src/sage/groups/group.pyx +++ b/src/sage/groups/group.pyx @@ -29,9 +29,7 @@ def is_Group(x): - ``x`` -- anything. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -175,7 +173,7 @@ cdef class Group(Parent): def is_finite(self): """ - Returns True if this group is finite. + Return ``True`` if this group is finite. EXAMPLES:: @@ -223,8 +221,7 @@ cdef class Group(Parent): def is_multiplicative(self): r""" - Returns True if the group operation is given by \* (rather than - +). + Return ``True`` if the group operation is given by \* (rather than +). Override for additive groups. @@ -239,11 +236,9 @@ cdef class Group(Parent): def _an_element_(self): """ - Return an element - - OUTPUT: + Return an element. - An element of the group. + OUTPUT: an element of the group EXAMPLES:: diff --git a/src/sage/groups/group_exp.py b/src/sage/groups/group_exp.py index ffae5e73cb2..58d9ba4b512 100644 --- a/src/sage/groups/group_exp.py +++ b/src/sage/groups/group_exp.py @@ -111,9 +111,8 @@ def _apply_functor(self, x): - A commutative additive group `x` - OUTPUT: - - - An isomorphic group whose operation is multiplication rather than addition. + OUTPUT: an isomorphic group whose operation is multiplication rather + than addition In the following example, ``self`` is the functor `GroupExp()`, `x` is the additive group `QQ^2`, and the output group is stored as `EQ2`. @@ -143,12 +142,13 @@ def _apply_functor_to_morphism(self, f): - A homomorphism `f` of commutative additive groups. - OUTPUT: + OUTPUT: the above homomorphism, but between the corresponding + multiplicative groups - The above homomorphism, but between the corresponding multiplicative groups. - In the following example, ``self`` is the functor `GroupExp()` and `f` is an endomorphism of the - additive group of integers. + In the following example, ``self`` is the functor `GroupExp()` and `f` + is an endomorphism of the additive group of integers. EXAMPLES:: @@ -245,11 +245,9 @@ class GroupExp_Class(UniqueRepresentation, Parent): INPUT: - - `G`: a commutative additive group - - OUTPUT: + - `G` -- a commutative additive group - - The multiplicative form of `G`. + OUTPUT: the multiplicative form of `G` EXAMPLES:: @@ -263,7 +261,6 @@ def __init__(self, G): sage: EG = GroupExp()(QQ^2) sage: TestSuite(EG).run(skip = "_test_elements") - """ if G not in CommutativeAdditiveGroups(): raise TypeError("%s must be a commutative additive group" % G) @@ -307,7 +304,6 @@ def one(self): (1, 0) sage: x == x * G.one() True - """ return GroupExpElement(self, self._G.zero()) @@ -349,7 +345,6 @@ def group_generators(self): sage: GroupExp()(ZZ).group_generators() (1,) - """ if hasattr(self._G, 'gens'): additive_generators = self._G.gens() diff --git a/src/sage/groups/group_semidirect_product.py b/src/sage/groups/group_semidirect_product.py index 1805dbbc53a..0c8ba8a96aa 100644 --- a/src/sage/groups/group_semidirect_product.py +++ b/src/sage/groups/group_semidirect_product.py @@ -291,8 +291,8 @@ def check_implemented_group(x): def act_to_right(self): r""" - True if the left factor acts on the right factor and - False if the right factor acts on the left factor. + Return ``True`` if the left factor acts on the right factor and + ``False`` if the right factor acts on the left factor. EXAMPLES:: diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 476fb4e9416..aeb100f2ca2 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -56,10 +56,8 @@ def is_abelian(self): r""" Return whether the group is Abelian. - OUTPUT: - - Boolean. ``True`` if this group is an Abelian group and ``False`` - otherwise. + OUTPUT: boolean; ``True`` if this group is an Abelian group and + ``False`` otherwise EXAMPLES:: @@ -184,9 +182,7 @@ def is_finite(self): """ Test whether the matrix group is finite. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -272,7 +268,6 @@ def conjugacy_classes_representatives(self): Traceback (most recent call last): ... NotImplementedError: only implemented for finite groups - """ if not self.is_finite(): raise NotImplementedError("only implemented for finite groups") @@ -352,9 +347,7 @@ def center(self): """ Return the center of this group as a subgroup. - OUTPUT: - - The center as a subgroup. + OUTPUT: the center as a subgroup EXAMPLES:: @@ -654,9 +647,7 @@ def irreducible_characters(self): """ Return the irreducible characters of the group. - OUTPUT: - - A tuple containing all irreducible characters. + OUTPUT: a tuple containing all irreducible characters EXAMPLES:: @@ -784,9 +775,7 @@ def random_element(self): """ Return a random element of this group. - OUTPUT: - - A group element. + OUTPUT: a group element EXAMPLES:: @@ -864,10 +853,8 @@ def list(self): """ List all elements of this group. - OUTPUT: - - A tuple containing all group elements in a random but fixed - order. + OUTPUT: a tuple containing all group elements in a random but fixed + order EXAMPLES:: @@ -941,9 +928,7 @@ def is_isomorphic(self, H): - ``H`` -- a group. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: diff --git a/src/sage/groups/libgap_morphism.py b/src/sage/groups/libgap_morphism.py index daac871629b..5b780ceb922 100644 --- a/src/sage/groups/libgap_morphism.py +++ b/src/sage/groups/libgap_morphism.py @@ -378,9 +378,7 @@ def pushforward(self, J, *args, **kwds): - ``J`` -- a subgroup or an element of the domain of ``self`` - OUTPUT: - - The image of ``J`` under ``self``. + OUTPUT: the image of ``J`` under ``self`` .. NOTE:: @@ -558,13 +556,11 @@ def preimage(self, S): def section(self): r""" - This method returns a section map of self by use of :meth:`lift`. + This method returns a section map of ``self`` by use of :meth:`lift`. See :meth:`section` of :class:`sage.categories.map.Map`, as well. - OUTPUT: - - an instance of :class:`sage.categories.morphism.SetMorphism` - mapping an element of the codomain of self to one of its preimages + OUTPUT: an instance of :class:`sage.categories.morphism.SetMorphism` + mapping an element of the codomain of ``self`` to one of its preimages EXAMPLES:: @@ -596,9 +592,7 @@ class GroupHomset_libgap(HomsetWithBase): - ``H`` -- a libgap group - ``category`` -- a category - OUTPUT: - - The homset of two libgap groups. + OUTPUT: the homset of two libgap groups EXAMPLES:: @@ -730,9 +724,10 @@ def natural_map(self): OUTPUT: - an instance of the element class of self if there exists a group homomorphism - mapping the generators of the domain of self to the according generators of - the codomain. Else the method falls back to the default. + An instance of the element class of ``self`` if there exists a group + homomorphism mapping the generators of the domain of ``self`` to the + according generators of the codomain. Otherwise, the method falls back + to the default. EXAMPLES:: diff --git a/src/sage/groups/libgap_wrapper.pxd b/src/sage/groups/libgap_wrapper.pxd index 0c43b098140..2f76d978afd 100644 --- a/src/sage/groups/libgap_wrapper.pxd +++ b/src/sage/groups/libgap_wrapper.pxd @@ -1,7 +1,6 @@ from sage.structure.element cimport MultiplicativeGroupElement from sage.libs.gap.element cimport GapElement - cdef class ElementLibGAP(MultiplicativeGroupElement): cdef GapElement _libgap cpdef GapElement gap(self) diff --git a/src/sage/groups/libgap_wrapper.pyx b/src/sage/groups/libgap_wrapper.pyx index 3d27ec44ea0..0834a304c66 100644 --- a/src/sage/groups/libgap_wrapper.pyx +++ b/src/sage/groups/libgap_wrapper.pyx @@ -159,9 +159,7 @@ class ParentLibGAP(SageObject): You can access the containing group with :meth:`ambient`. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -180,9 +178,7 @@ class ParentLibGAP(SageObject): - ``G`` -- group; the codomain - ``cat`` -- category - OUTPUT: - - The set of homomorphisms from ``self`` to ``G``. + OUTPUT: the set of homomorphisms from ``self`` to ``G`` EXAMPLES:: @@ -201,10 +197,7 @@ class ParentLibGAP(SageObject): You should override this with a derived class. Its constructor must accept the same arguments as :meth:`__init__`. - OUTPUT: - - A new instance of a group (derived class of - :class:`ParentLibGAP`). + OUTPUT: a new instance of a group (derived class of :class:`ParentLibGAP`) TESTS:: @@ -225,9 +218,7 @@ class ParentLibGAP(SageObject): - ``generators`` -- a list/tuple/iterable of group elements. - OUTPUT: - - The subgroup generated by ``generators``. + OUTPUT: the subgroup generated by ``generators`` EXAMPLES:: @@ -269,11 +260,9 @@ class ParentLibGAP(SageObject): def gap(self): """ - Return the gap representation of self. - - OUTPUT: + Return the gap representation of ``self``. - A :class:`~sage.libs.gap.element.GapElement` + OUTPUT: a :class:`~sage.libs.gap.element.GapElement` EXAMPLES:: @@ -309,11 +298,9 @@ class ParentLibGAP(SageObject): def ngens(self): """ - Return the number of generators of self. + Return the number of generators of ``self``. - OUTPUT: - - Integer. + OUTPUT: an integer EXAMPLES:: @@ -332,10 +319,6 @@ class ParentLibGAP(SageObject): """ Return a string representation. - OUTPUT: - - String. - TESTS:: sage: from sage.groups.libgap_wrapper import ElementLibGAP, ParentLibGAP @@ -407,7 +390,7 @@ class ParentLibGAP(SageObject): def gen(self, i): """ - Return the `i`-th generator of self. + Return the `i`-th generator of ``self``. .. warning:: @@ -419,9 +402,7 @@ class ParentLibGAP(SageObject): - ``i`` -- integer between `0` (inclusive) and :meth:`ngens` (exclusive). The index of the generator. - OUTPUT: - - The `i`-th generator of the group. + OUTPUT: the `i`-th generator of the group EXAMPLES:: @@ -438,7 +419,7 @@ class ParentLibGAP(SageObject): @cached_method def one(self): """ - Return the identity element of self. + Return the identity element of ``self``. EXAMPLES:: @@ -454,7 +435,7 @@ class ParentLibGAP(SageObject): def _an_element_(self): """ - Return an element of self. + Return an element of ``self``. EXAMPLES:: @@ -522,9 +503,7 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): """ Return a LibGAP representation of the element. - OUTPUT: - - A :class:`~sage.libs.gap.element.GapElement` + OUTPUT: a :class:`~sage.libs.gap.element.GapElement` EXAMPLES:: @@ -572,9 +551,7 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): """ Test whether the group element is the trivial element. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -591,10 +568,6 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): """ Return a string representation. - OUTPUT: - - String. - EXAMPLES:: sage: G. = FreeGroup() @@ -622,9 +595,7 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): r""" Return a LaTeX representation - OUTPUT: - - String. A valid LaTeX math command sequence. + OUTPUT: a string; a valid LaTeX math command sequence EXAMPLES:: @@ -727,7 +698,7 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): def __invert__(self): """ - Return the inverse of self. + Return the inverse of ``self``. TESTS:: diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index 6d487e5d123..3ad8719a5dd 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -83,9 +83,7 @@ def normalize_square_matrices(matrices): """ Find a common space for all matrices. - OUTPUT: - - A list of matrices, all elements of the same matrix space. + OUTPUT: a list of matrices, all elements of the same matrix space EXAMPLES:: @@ -151,7 +149,8 @@ def QuaternionMatrixGroupGF3(): is not isomorphic to the group of symmetries of a square (the dihedral group `D_4`). - .. note:: + .. NOTE:: + This group is most easily available via ``groups.matrix.QuaternionGF3()``. EXAMPLES: @@ -413,9 +412,7 @@ def gen(self, i): """ Return the `i`-th generator - OUTPUT: - - The `i`-th generator of the group. + OUTPUT: the `i`-th generator of the group EXAMPLES:: @@ -435,9 +432,7 @@ def ngens(self): """ Return the number of generators - OUTPUT: - - An integer. The number of generators. + OUTPUT: an integer; the number of generators EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/group_element.pyx b/src/sage/groups/matrix_gps/group_element.pyx index 38bf1f03279..2e6428fc714 100644 --- a/src/sage/groups/matrix_gps/group_element.pyx +++ b/src/sage/groups/matrix_gps/group_element.pyx @@ -97,7 +97,7 @@ cpdef is_MatrixGroupElement(x): - ``x`` -- anything. - OUTPUT: Boolean. + OUTPUT: boolean EXAMPLES:: @@ -372,7 +372,7 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): """ Return the inverse group element - OUTPUT: A matrix group element. + OUTPUT: a matrix group element EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/group_element_gap.pyx b/src/sage/groups/matrix_gps/group_element_gap.pyx index b07c0f01a44..2f7eb82cb8d 100644 --- a/src/sage/groups/matrix_gps/group_element_gap.pyx +++ b/src/sage/groups/matrix_gps/group_element_gap.pyx @@ -306,7 +306,7 @@ cdef class MatrixGroupElement_gap(ElementLibGAP): This method writes the group element as a product of the elements of the list ``gens``, or the standard generators of - the parent of self if ``gens`` is None. + the parent of ``self`` if ``gens`` is ``None``. INPUT: diff --git a/src/sage/groups/matrix_gps/linear.py b/src/sage/groups/matrix_gps/linear.py index ef2bf1aa0be..759faf2db18 100644 --- a/src/sage/groups/matrix_gps/linear.py +++ b/src/sage/groups/matrix_gps/linear.py @@ -201,7 +201,7 @@ def SL(n, R, var='a'): matrices that are invertible over the ring `R` with determinant one. - .. note:: + .. NOTE:: This group is also available via ``groups.matrix.SL()``. diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index 2b87493fbc5..e7ad5183e45 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -131,9 +131,7 @@ def _check_matrix(self, x, *args): - ``*args`` -- optional other representations of ``x``, depending on the group implementation. Ignored by default. - OUTPUT: - - A :class:`TypeError` must be raised if ``x`` is invalid. + OUTPUT: a :class:`TypeError` must be raised if ``x`` is invalid EXAMPLES:: @@ -186,9 +184,11 @@ def subgroup(self, generators, check=True): INPUT: - ``generators`` -- a list/tuple/iterable of group elements of ``self`` - - ``check`` -- boolean (optional, default: ``True``). Whether to check that each matrix is invertible. + - ``check`` -- boolean (optional, default: ``True``). Whether to check + that each matrix is invertible. - OUTPUT: The subgroup generated by ``generators`` as an instance of :class:`FinitelyGeneratedMatrixGroup_gap` + OUTPUT: the subgroup generated by ``generators`` as an instance of + :class:`FinitelyGeneratedMatrixGroup_gap` EXAMPLES:: @@ -262,10 +262,6 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. - EXAMPLES:: sage: F = GF(5); MS = MatrixSpace(F, 2, 2) @@ -429,10 +425,8 @@ def degree(self): """ Return the degree of this matrix group. - OUTPUT: - - Integer. The size (number of rows equals number of columns) of - the matrices. + OUTPUT: an integer; the size (number of rows equals number of columns) + of the matrices EXAMPLES:: @@ -474,9 +468,7 @@ def __richcmp__(self, other, op): - ``op`` -- comparison operator - OUTPUT: - - boolean + OUTPUT: boolean EXAMPLES:: @@ -573,6 +565,5 @@ def is_trivial(self): 2 sage: G.is_trivial() True - """ return all(g.is_one() for g in self.gens()) diff --git a/src/sage/groups/matrix_gps/matrix_group_gap.py b/src/sage/groups/matrix_gps/matrix_group_gap.py index 84fd3d74996..f413c87bdde 100644 --- a/src/sage/groups/matrix_gps/matrix_group_gap.py +++ b/src/sage/groups/matrix_gps/matrix_group_gap.py @@ -137,7 +137,6 @@ def __init__(self, degree, base_ring, libgap_group, ambient=None, category=None) Traceback (most recent call last): ... NotImplementedError: group must be finite - """ ParentLibGAP.__init__(self, libgap_group, ambient=ambient) MatrixGroup_generic.__init__(self, degree, base_ring, category=category) @@ -202,9 +201,7 @@ def _check_matrix(self, x_sage, x_gap): - ``x_gap`` -- the corresponding LibGAP matrix. - OUTPUT: - - A :class:`TypeError` must be raised if ``x`` is invalid. + OUTPUT: a :class:`TypeError` must be raised if ``x`` is invalid EXAMPLES:: @@ -232,9 +229,11 @@ def subgroup(self, generators, check=True): INPUT: - ``generators`` -- a list/tuple/iterable of group elements of ``self`` - - ``check`` -- boolean (optional, default: ``True``). Whether to check that each matrix is invertible. + - ``check`` -- boolean (optional, default: ``True``). Whether to check + that each matrix is invertible. - OUTPUT: The subgroup generated by ``generators`` as an instance of :class:`FinitelyGeneratedMatrixGroup_gap` + OUTPUT: The subgroup generated by ``generators`` as an instance of + :class:`FinitelyGeneratedMatrixGroup_gap` EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/named_group.py b/src/sage/groups/matrix_gps/named_group.py index 90c01e232e7..1aae7019e3c 100644 --- a/src/sage/groups/matrix_gps/named_group.py +++ b/src/sage/groups/matrix_gps/named_group.py @@ -78,9 +78,7 @@ def normalize_args_vectorspace(*args, **kwds): field generator name in the case where ``ring`` is a prime power. - OUTPUT: - - A pair ``(degree, ring)``. + OUTPUT: a pair ``(degree, ring)`` TESTS:: @@ -237,9 +235,7 @@ def _an_element_(self): """ Return an element. - OUTPUT: - - A group element. + OUTPUT: a group element EXAMPLES:: @@ -253,10 +249,6 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. - EXAMPLES:: sage: GL(2, QQ)._repr_() @@ -266,11 +258,9 @@ def _repr_(self): def _latex_(self): """ - Return a LaTeX representation - - OUTPUT: + Return a LaTeX representation. - String. + OUTPUT: a string EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/orthogonal.py b/src/sage/groups/matrix_gps/orthogonal.py index c30fc14a331..ab1b770e4cf 100644 --- a/src/sage/groups/matrix_gps/orthogonal.py +++ b/src/sage/groups/matrix_gps/orthogonal.py @@ -116,9 +116,7 @@ def normalize_args_e(degree, ring, e): finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. - OUTPUT: - - The integer ``e`` with values required by GAP. + OUTPUT: the integer ``e`` with values required by GAP TESTS:: @@ -263,10 +261,8 @@ def GO(n, R, e=0, var='a', invariant_form=None): by the orthogonal group; the form is checked to be non-degenerate and symmetric but not to be positive definite - OUTPUT: - - The general orthogonal group of given degree, base ring, and - choice of invariant form. + OUTPUT: the general orthogonal group of given degree, base ring, and + choice of invariant form EXAMPLES:: @@ -373,10 +369,8 @@ def SO(n, R, e=None, var='a', invariant_form=None): by the orthogonal group; the form is checked to be non-degenerate and symmetric but not to be positive definite - OUTPUT: - - The special orthogonal group of given degree, base ring, and choice of - invariant form. + OUTPUT: the special orthogonal group of given degree, base ring, and choice + of invariant form EXAMPLES:: @@ -482,9 +476,7 @@ def invariant_bilinear_form(self): """ Return the symmetric bilinear form preserved by ``self``. - OUTPUT: - - A matrix. + OUTPUT: a matrix EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/symplectic.py b/src/sage/groups/matrix_gps/symplectic.py index 0e378b4d153..d139034107d 100644 --- a/src/sage/groups/matrix_gps/symplectic.py +++ b/src/sage/groups/matrix_gps/symplectic.py @@ -211,7 +211,7 @@ def invariant_form(self): """ Return the quadratic form preserved by the symplectic group. - OUTPUT: A matrix. + OUTPUT: a matrix EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/symplectic_gap.py b/src/sage/groups/matrix_gps/symplectic_gap.py index d348ed9f40f..b0d05c3be6e 100644 --- a/src/sage/groups/matrix_gps/symplectic_gap.py +++ b/src/sage/groups/matrix_gps/symplectic_gap.py @@ -48,7 +48,7 @@ def invariant_form(self): """ Return the quadratic form preserved by the symplectic group. - OUTPUT: A matrix. + OUTPUT: a matrix EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py index 43ac69c3983..37a9cb826ee 100644 --- a/src/sage/groups/matrix_gps/unitary.py +++ b/src/sage/groups/matrix_gps/unitary.py @@ -68,11 +68,7 @@ def finite_field_sqrt(ring): """ Helper function. - INPUT: A ring. - - OUTPUT: - - Integer `q` such that ``ring`` is the finite field with `q^2` elements. + OUTPUT: an integer `q` such that ``ring`` is the finite field with `q^2` elements EXAMPLES:: @@ -189,7 +185,7 @@ def GU(n, R, var='a', invariant_form=None): by the unitary group; the form is checked to be non-degenerate and hermitian but not to be positive definite - OUTPUT: The general unitary group. + OUTPUT: the general unitary group EXAMPLES:: @@ -301,9 +297,7 @@ def SU(n, R, var='a', invariant_form=None): by the unitary group; the form is checked to be non-degenerate and hermitian but not to be positive definite - OUTPUT: - - Return the special unitary group. + OUTPUT: the special unitary group EXAMPLES:: @@ -396,7 +390,7 @@ def invariant_form(self): Return the hermitian form preserved by the unitary group. - OUTPUT: A square matrix describing the bilinear form + OUTPUT: a square matrix describing the bilinear form EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/unitary_gap.py b/src/sage/groups/matrix_gps/unitary_gap.py index ac2de20f96b..ab0512a4803 100644 --- a/src/sage/groups/matrix_gps/unitary_gap.py +++ b/src/sage/groups/matrix_gps/unitary_gap.py @@ -41,9 +41,7 @@ def invariant_form(self): """ Return the hermitian form preserved by the unitary group. - OUTPUT: - - A square matrix describing the bilinear form + OUTPUT: a square matrix describing the bilinear form EXAMPLES:: diff --git a/src/sage/groups/misc_gps/argument_groups.py b/src/sage/groups/misc_gps/argument_groups.py index 1c949a57f51..5cf9ead8c7d 100644 --- a/src/sage/groups/misc_gps/argument_groups.py +++ b/src/sage/groups/misc_gps/argument_groups.py @@ -114,9 +114,7 @@ def _normalize_(element): - ``element`` -- an element of the parent's base - OUTPUT: - - An element. + OUTPUT: an element TESTS:: @@ -151,9 +149,7 @@ def _symbolic_(self, R=None): The output will be an element of ``R``. If ``None``, then the symbolic ring is used. - OUTPUT: - - A symbolic expression. + OUTPUT: a symbolic expression EXAMPLES:: @@ -337,9 +333,7 @@ def _determine_category_(category): - ``category`` -- a category or ``None`` (in which case the output equals ``category``) - OUTPUT: - - A category. + OUTPUT: a category EXAMPLES:: @@ -414,9 +408,7 @@ def _normalize_(exponent): - ``exponent`` -- an element of the parent's base - OUTPUT: - - An element. + OUTPUT: an element TESTS:: @@ -463,9 +455,7 @@ def _symbolic_(self, R=None): The output will be an element of ``R``. If ``None``, then the symbolic ring is used. - OUTPUT: - - A symbolic expression. + OUTPUT: a symbolic expression EXAMPLES:: @@ -681,9 +671,7 @@ def _element_constructor_(self, data, exponent=None, **kwds): - ``kwds`` -- are passed on to element - OUTPUT: - - A :class:`UnitCirclePoint`. + OUTPUT: a :class:`UnitCirclePoint` TESTS:: @@ -796,9 +784,7 @@ def _create_element_in_extension_(self, exponent): - ``exponent`` -- the element data. - OUTPUT: - - An element. + OUTPUT: an element EXAMPLES:: @@ -828,9 +814,7 @@ def _coerce_map_from_(self, R): - ``R`` -- a parent. - OUTPUT: - - A boolean. + OUTPUT: boolean TESTS:: @@ -1088,9 +1072,7 @@ def _normalize_(element): - ``element`` -- an element of the parent's base - OUTPUT: - - An element. + OUTPUT: an element TESTS:: @@ -1123,9 +1105,7 @@ def _symbolic_(self, R=None): The output will be an element of ``R``. If ``None``, then the symbolic ring is used. - OUTPUT: - - A symbolic expression. + OUTPUT: a symbolic expression EXAMPLES:: @@ -1275,9 +1255,7 @@ def _element_constructor_(self, data, **kwds): - ``kwds`` -- are passed on to element - OUTPUT: - - A :class:`ArgumentByElement`. + OUTPUT: a :class:`ArgumentByElement` TESTS:: @@ -1345,9 +1323,7 @@ def _create_element_in_extension_(self, element): - ``element`` -- the element data. - OUTPUT: - - An element. + OUTPUT: an element EXAMPLES:: @@ -1379,9 +1355,7 @@ def _coerce_map_from_(self, R): - ``R`` -- a parent. - OUTPUT: - - A boolean. + OUTPUT: boolean TESTS:: @@ -1436,9 +1410,7 @@ def _normalize_(element): - ``element`` -- an element of the parent's base - OUTPUT: - - An element. + OUTPUT: an element TESTS:: @@ -1689,9 +1661,7 @@ def _element_constructor_(self, data): - ``data`` -- an object - OUTPUT: - - A :class:`Sign`. + OUTPUT: a :class:`Sign` TESTS:: diff --git a/src/sage/groups/misc_gps/imaginary_groups.py b/src/sage/groups/misc_gps/imaginary_groups.py index 41fe79f9959..428db810921 100644 --- a/src/sage/groups/misc_gps/imaginary_groups.py +++ b/src/sage/groups/misc_gps/imaginary_groups.py @@ -284,9 +284,7 @@ def _determine_category_(category): - ``category`` -- a category or ``None`` (in which case the output equals ``category``) - OUTPUT: - - A category. + OUTPUT: a category EXAMPLES:: @@ -376,9 +374,7 @@ def _element_constructor_(self, data, imag=None): - ``imag`` -- a number (of a subset of the reals) or ``None`` - OUTPUT: - - A :class:`ImaginaryElement`. + OUTPUT: a :class:`ImaginaryElement` TESTS:: diff --git a/src/sage/groups/old.pyx b/src/sage/groups/old.pyx index 1833b4a2b74..08df0405ffa 100644 --- a/src/sage/groups/old.pyx +++ b/src/sage/groups/old.pyx @@ -69,7 +69,7 @@ cdef class Group(sage.structure.parent.Parent): def __contains__(self, x): r""" - True if coercion of `x` into self is defined. + Return ``True`` if coercion of ``x`` into ``self`` is defined. EXAMPLES:: @@ -88,7 +88,7 @@ cdef class Group(sage.structure.parent.Parent): def is_abelian(self): """ - Return True if this group is abelian. + Return ``True`` if this group is abelian. EXAMPLES:: @@ -103,7 +103,7 @@ cdef class Group(sage.structure.parent.Parent): def is_commutative(self): r""" - Return True if this group is commutative. This is an alias for + Return ``True`` if this group is commutative. This is an alias for is_abelian, largely to make groups work well with the Factorization class. @@ -119,7 +119,7 @@ cdef class Group(sage.structure.parent.Parent): def order(self): """ - Returns the number of elements of this group, which is either a + Return the number of elements of this group, which is either a positive integer or infinity. EXAMPLES:: @@ -135,8 +135,7 @@ cdef class Group(sage.structure.parent.Parent): def is_multiplicative(self): r""" - Returns True if the group operation is given by \* (rather than - +). + Return ``True`` if the group operation is given by \* (rather than +). Override for additive groups. @@ -214,7 +213,6 @@ cdef class FiniteGroup(Group): """ return True - cdef class AlgebraicGroup(Group): """ Generic algebraic group. diff --git a/src/sage/groups/perm_gps/constructor.py b/src/sage/groups/perm_gps/constructor.py index 5a130eb19be..ab912f7667d 100644 --- a/src/sage/groups/perm_gps/constructor.py +++ b/src/sage/groups/perm_gps/constructor.py @@ -170,10 +170,8 @@ def standardize_generator(g, convert_dict=None, as_cycles=False): - ``as_cycles`` -- (default: ``False``) whether the output should be as cycles or in one-line notation - OUTPUT: - - The permutation in as a list in one-line notation or a list of cycles - as tuples. + OUTPUT: the permutation in as a list in one-line notation or a list of + cycles as tuples. EXAMPLES:: diff --git a/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx b/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx index 803f2533b7d..dd2647238f2 100644 --- a/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +++ b/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx @@ -438,12 +438,12 @@ cdef aut_gp_and_can_lab *get_aut_gp_and_can_lab(void *S, int -- 0 if gamma_1(S1) = gamma_2(S2), otherwise -1 or 1 (see docs for cmp), such that the set of all structures is well-ordered - NOTE: - The partition ``partition1`` *must* satisfy the property that in each cell, - the smallest element occurs first! + .. NOTE:: - OUTPUT: - pointer to a aut_gp_and_can_lab struct + The partition ``partition1`` *must* satisfy the property that in each + cell, the smallest element occurs first! + + OUTPUT: a pointer to a ``aut_gp_and_can_lab`` struct """ cdef PartitionStack *current_ps diff --git a/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx b/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx index 6143e509caa..245ec5f7c06 100644 --- a/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +++ b/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx @@ -467,9 +467,7 @@ cdef iterator *setup_canonical_generator(int degree, - ``max_depth`` - maximum depth of augmentations to be made from the seed object S - OUTPUT: - - pointer to an iterator of objects + OUTPUT: a pointer to an iterator of objects """ if max_depth <= 1: diff --git a/src/sage/groups/perm_gps/partn_ref/data_structures.pxd b/src/sage/groups/perm_gps/partn_ref/data_structures.pxd index f53184bd082..408fe26a15a 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures.pxd +++ b/src/sage/groups/perm_gps/partn_ref/data_structures.pxd @@ -85,8 +85,7 @@ cdef inline OrbitPartition *OP_copy(OrbitPartition *OP) noexcept: """ Allocate and return a pointer to a copy of a OrbitPartition of degree n. - Returns a - null pointer in the case of an allocation failure. + Returns a null pointer in the case of an allocation failure. """ cdef OrbitPartition *OP2 = OP_new(OP.degree) if OP is NULL: @@ -172,7 +171,7 @@ cdef inline int PS_copy_from_to(PartitionStack *PS, PartitionStack *PS2) noexcep cdef inline bint PS_is_discrete(PartitionStack *PS) noexcept: """ - Returns whether the deepest partition consists only of singleton cells. + Return whether the deepest partition consists only of singleton cells. """ cdef int i for i from 0 <= i < PS.degree: @@ -182,7 +181,7 @@ cdef inline bint PS_is_discrete(PartitionStack *PS) noexcept: cdef inline int PS_num_cells(PartitionStack *PS) noexcept: """ - Returns the number of cells. + Return the number of cells. """ cdef int i, ncells = 0 for i from 0 <= i < PS.degree: @@ -206,13 +205,13 @@ cdef inline void PS_move_min_to_front(PartitionStack *PS, int start, int end) no cdef inline bint PS_is_mcr(PartitionStack *PS, int m) noexcept: """ - Returns whether PS.elements[m] (not m!) is the smallest element of its cell. + Return whether PS.elements[m] (not m!) is the smallest element of its cell. """ return m == 0 or PS.levels[m-1] <= PS.depth cdef inline bint PS_is_fixed(PartitionStack *PS, int m) noexcept: """ - Returns whether PS.elements[m] (not m!) is in a singleton cell, assuming + Return whether PS.elements[m] (not m!) is in a singleton cell, assuming PS_is_mcr(PS, m) is already true. """ return PS.levels[m] <= PS.depth diff --git a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx index cb25f23a4d3..e7a3e8c55f8 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx +++ b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx @@ -659,7 +659,7 @@ cdef inline void SC_dealloc(StabilizerChain *SC) noexcept: cdef StabilizerChain *SC_symmetric_group(int n) noexcept: """ - Returns a stabilizer chain for the symmetric group on {0, 1, ..., n-1}. + Return a stabilizer chain for the symmetric group on {0, 1, ..., n-1}. Returns NULL in the case of an allocation failure. """ @@ -700,7 +700,7 @@ cdef StabilizerChain *SC_symmetric_group(int n) noexcept: cdef StabilizerChain *SC_alternating_group(int n) noexcept: """ - Returns a stabilizer chain for the alternating group on {0, 1, ..., n-1}. + Return a stabilizer chain for the alternating group on {0, 1, ..., n-1}. Returns NULL in the case of an allocation failure. """ @@ -1142,8 +1142,8 @@ cdef bint SC_is_giant(int n, int num_perms, int *perms, float p, bitset_t suppor If the group is not a giant, this routine will return False. This could also indicate an allocation failure. - If the group is a giant, this routine will return True with approximate - probability p. It will set `support' to the support of the group in this + If the group is a giant, this routine will return ``True`` with approximate + probability ``p``. It will set `support' to the support of the group in this case. Use bitset_len to get the size of support. The bitset `support' must be initialized. Must have 0 <= p < 1. diff --git a/src/sage/groups/perm_gps/partn_ref/double_coset.pyx b/src/sage/groups/perm_gps/partn_ref/double_coset.pyx index 73631b395c4..051e3f78fa4 100644 --- a/src/sage/groups/perm_gps/partn_ref/double_coset.pyx +++ b/src/sage/groups/perm_gps/partn_ref/double_coset.pyx @@ -313,14 +313,13 @@ cdef int double_coset(void *S1, void *S2, PartitionStack *partition1, int *order isom -- space to store the isomorphism to, or NULL if isomorphism is not needed - NOTE: - The partition ``partition1`` and the resulting partition from ``ordering2`` - *must* satisfy the property that in each cell, the smallest element occurs - first! + .. NOTE:: - OUTPUT: - 1 if S1 and S2 are isomorphic, otherwise 0. + The partition ``partition1`` and the resulting partition from + ``ordering2`` *must* satisfy the property that in each cell, the + smallest element occurs first! + OUTPUT: ``1`` if ``S1`` and ``S2`` are isomorphic, otherwise ``0`` """ cdef PartitionStack *current_ps cdef PartitionStack *first_ps diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx index 6a3c07ac75d..c01634e1772 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx @@ -114,7 +114,7 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): def run(self, partition=None): """ Perform the canonical labeling and automorphism group computation, - storing results to self. + storing results to ``self``. INPUT: partition -- an optional list of lists partition of the columns. @@ -257,13 +257,13 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): order and a base for which the list of generators is a strong generating set. - EXAMPLES: (For more examples, see self.run()) + EXAMPLES: (For more examples, see self.run()):: + sage: from sage.groups.perm_gps.partn_ref.refinement_binary import LinearBinaryCodeStruct sage: B = LinearBinaryCodeStruct(matrix(GF(2),[[1,1,1,1]])) sage: B.automorphism_group() ([[0, 1, 3, 2], [0, 2, 1, 3], [1, 0, 2, 3]], 24, [0, 1, 2]) - """ cdef int i, j cdef list generators, base @@ -282,7 +282,8 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): """ Returns a canonical relabeling (in list permutation format). - EXAMPLES: (For more examples, see self.run()) + EXAMPLES: (For more examples, see self.run()):: + sage: from sage.groups.perm_gps.partn_ref.refinement_binary import LinearBinaryCodeStruct sage: B = LinearBinaryCodeStruct(matrix(GF(2), [[1,1,0]])) @@ -295,7 +296,6 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): ([[2, 1, 0]], 2, [0]) sage: B.canonical_relabeling() [1, 0, 2] - """ cdef int i if self.output is NULL: @@ -304,7 +304,7 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): def is_isomorphic(self, LinearBinaryCodeStruct other): """ - Calculate whether self is isomorphic to other. + Calculate whether ``self`` is isomorphic to ``other``. EXAMPLES:: @@ -314,7 +314,6 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): sage: C = LinearBinaryCodeStruct(Matrix(GF(2), [[1,1,1,0,0,1],[1,1,0,1,1,0]])) sage: B.is_isomorphic(C) [0, 1, 2, 5, 3, 4] - """ cdef int i, n = self.degree cdef int *output @@ -512,7 +511,6 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): [4, 0, 1, 2]) sage: B.canonical_relabeling() [2, 3, 4, 5, 0, 1] - """ cdef int n = self.degree cdef PartitionStack *part @@ -534,7 +532,8 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): order and a base for which the list of generators is a strong generating set. - EXAMPLES: (For more examples, see self.run()) + EXAMPLES: (For more examples, see self.run()):: + sage: from sage.groups.perm_gps.partn_ref.refinement_binary import NonlinearBinaryCodeStruct sage: B = NonlinearBinaryCodeStruct(Matrix(GF(2), [[1,1,1,0,0,0],[1,1,0,1,0,0],[1,0,1,1,0,0],[0,1,1,1,0,0],[0,0,0,0,1,0],[0,0,0,0,0,1]])) @@ -546,7 +545,6 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): [0, 1, 2, 3, 5, 4]], 48, [4, 0, 1, 2]) - """ cdef int i, j cdef list generators, base @@ -565,14 +563,14 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): """ Returns a canonical relabeling (in list permutation format). - EXAMPLES: (For more examples, see self.run()) + EXAMPLES: (For more examples, see self.run()):: + sage: from sage.groups.perm_gps.partn_ref.refinement_binary import NonlinearBinaryCodeStruct sage: B = NonlinearBinaryCodeStruct(Matrix(GF(2), [[1,1,1,0,0,0],[1,1,0,1,0,0],[1,0,1,1,0,0],[0,1,1,1,0,0],[0,0,0,0,1,0],[0,0,0,0,0,1]])) sage: B.run() sage: B.canonical_relabeling() [2, 3, 4, 5, 0, 1] - """ cdef int i if self.output is NULL: @@ -581,7 +579,7 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): def is_isomorphic(self, NonlinearBinaryCodeStruct other): """ - Calculate whether self is isomorphic to other. + Calculate whether ``self`` is isomorphic to ``other``. EXAMPLES:: @@ -591,7 +589,6 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): sage: C = NonlinearBinaryCodeStruct(Matrix(GF(2), [[1,1,0,0,1,1],[1,1,1,1,0,0]])) sage: B.is_isomorphic(C) [2, 3, 0, 1, 4, 5] - """ cdef int i, n = self.degree cdef int *output @@ -914,17 +911,19 @@ cdef int compare_nonlinear_codes(int *gamma_1, int *gamma_2, void *S1, void *S2, cdef bint all_children_are_equivalent(PartitionStack *col_ps, void *S) noexcept: """ - Returns True if any refinement of the current partition results in the same - structure. - - WARNING: - Converse does not hold in general! See Lemma 2.25 of [1] for details, noting - that the binary code is interpreted as a bipartite graph (see module docs - for details). + Return ``True`` if any refinement of the current partition results in the + same structure. INPUT: - col_ps -- the partition stack to be checked - S -- a binary code struct object + + - ``col_ps`` -- the partition stack to be checked + - ``S`` -- a binary code struct object + + .. WARNING:: + + Converse does not hold in general! See Lemma 2.25 of [1] for details, noting + that the binary code is interpreted as a bipartite graph (see module docs + for details). """ cdef BinaryCodeStruct BCS = S cdef PartitionStack *word_ps = BCS.word_ps @@ -957,7 +956,7 @@ cdef bint all_children_are_equivalent(PartitionStack *col_ps, void *S) noexcept: cdef inline int word_degree(PartitionStack *word_ps, BinaryCodeStruct BCS, int entry, int cell_index, PartitionStack *col_ps) noexcept: """ - Returns the number of edges from the vertex corresponding to entry to + Return the number of edges from the vertex corresponding to entry to vertices in the cell corresponding to cell_index. INPUT: @@ -987,7 +986,7 @@ cdef inline int word_degree(PartitionStack *word_ps, BinaryCodeStruct BCS, int e cdef inline int col_degree(PartitionStack *col_ps, BinaryCodeStruct BCS, int entry, int cell_index, PartitionStack *word_ps) noexcept: """ - Returns the number of edges from the vertex corresponding to entry to + Return the number of edges from the vertex corresponding to entry to vertices in the cell corresponding to cell_index. INPUT: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx index 1b588487d1c..2ebf9e08b56 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx @@ -676,12 +676,12 @@ cdef int compare_graphs(int *gamma_1, int *gamma_2, void *S1, void *S2, int degr cdef bint all_children_are_equivalent(PartitionStack *PS, void *S) noexcept: """ - Return True if every refinement of the current partition results in the + Return ``True`` if every refinement of the current partition results in the same structure. - WARNING: + .. WARNING:: - Converse does not hold in general! See Lemma 2.25 of [1] for details. + Converse does not hold in general! See Lemma 2.25 of [1] for details. INPUT: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_lists.pxd b/src/sage/groups/perm_gps/partn_ref/refinement_lists.pxd index e7b6cf42f6d..43cf567dc40 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_lists.pxd +++ b/src/sage/groups/perm_gps/partn_ref/refinement_lists.pxd @@ -11,7 +11,6 @@ from sage.groups.perm_gps.partn_ref.data_structures cimport * - # name of the three functions to customize cdef int refine_list(PartitionStack *, void *, int *, int) noexcept cdef int compare_lists(int *, int *, void *, void *, int) noexcept diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx index c8d4f86a8f1..1366fa8ceee 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx @@ -110,7 +110,6 @@ cdef class MatrixStruct: 00011 01100 4 - """ print(self.matrix) print("") @@ -127,7 +126,7 @@ cdef class MatrixStruct: def run(self, partition=None): """ Perform the canonical labeling and automorphism group computation, - storing results to self. + storing results to ``self``. INPUT: @@ -153,7 +152,6 @@ cdef class MatrixStruct: sage: M = MatrixStruct(matrix(GF(3),[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2]])) sage: M.automorphism_group()[1] == factorial(14) True - """ cdef int i, n = self.degree cdef PartitionStack *part @@ -189,7 +187,6 @@ cdef class MatrixStruct: sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]])) sage: M.automorphism_group() ([[0, 2, 1]], 2, [1]) - """ cdef int i, j cdef list generators, base @@ -217,7 +214,6 @@ cdef class MatrixStruct: sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]])) sage: M.canonical_relabeling() [0, 1, 2] - """ cdef int i if self.output is NULL: @@ -226,7 +222,7 @@ cdef class MatrixStruct: def is_isomorphic(self, MatrixStruct other): """ - Calculate whether self is isomorphic to other. + Calculate whether ``self`` is isomorphic to ``other``. EXAMPLES:: @@ -235,7 +231,6 @@ cdef class MatrixStruct: sage: N = MatrixStruct(Matrix(GF(11), [[0,1,0,2,0,3],[1,0,2,0,3,0]])) sage: M.is_isomorphic(N) [0, 2, 4, 1, 3, 5] - """ cdef int i, n = self.degree cdef int *output diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx index 23d5e7576c7..b73406b13a7 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx @@ -12,12 +12,11 @@ in pure Python, and still use the Cython algorithms. Experimentation with specific partition backtrack implementations no longer requires compilation, as the input functions can be dynamically changed at runtime. -NOTE: - -This is not intended for production quality implementations of partition -refinement, but instead for experimentation, learning, and use of the Python -debugger. +.. NOTE:: + This is not intended for production quality implementations of partition + refinement, but instead for experimentation, learning, and use of the + Python debugger. """ #***************************************************************************** @@ -53,7 +52,6 @@ cdef class PythonPartitionStack: sage: from sage.groups.perm_gps.partn_ref.refinement_python import PythonPartitionStack sage: P = PythonPartitionStack(7) # implicit doctest - """ self.c_ps = PS_new(n, 1) @@ -66,7 +64,6 @@ cdef class PythonPartitionStack: sage: from sage.groups.perm_gps.partn_ref.refinement_python import PythonPartitionStack sage: P = PythonPartitionStack(7) sage: del(P) # implicit doctest - """ PS_dealloc(self.c_ps) @@ -80,7 +77,6 @@ cdef class PythonPartitionStack: sage: P = PythonPartitionStack(7) sage: P # implicit doctest PythonPartitionStack of degree 7 and depth 0. - """ return "PythonPartitionStack of degree %d and depth %d."%(self.c_ps.degree, self.c_ps.depth) @@ -98,7 +94,6 @@ cdef class PythonPartitionStack: sage: P.display() (0 1 2 3 4 5 6) (0 1 2|3 4 5 6) - """ PS_print(self.c_ps) @@ -116,7 +111,6 @@ cdef class PythonPartitionStack: [None, None, None, None, None, None, None] sage: P.is_discrete() True - """ return PS_is_discrete(self.c_ps) @@ -130,7 +124,6 @@ cdef class PythonPartitionStack: sage: P = PythonPartitionStack(7) sage: P.num_cells() 1 - """ return PS_num_cells(self.c_ps) @@ -150,7 +143,6 @@ cdef class PythonPartitionStack: sage: P.move_min_to_front(0,1) sage: P.display() (0 1 2 3 4 5 6) - """ PS_move_min_to_front(self.c_ps, start, end) @@ -166,7 +158,6 @@ cdef class PythonPartitionStack: (0 1 2 3 4 5 6) sage: Q.display() (0 1 2 3 4 5 6) - """ cdef PythonPartitionStack cpy cpy = PythonPartitionStack(self.c_ps.degree) @@ -192,7 +183,6 @@ cdef class PythonPartitionStack: sage: P.display() (0 1 2 3 4 5 6) (0 1 2 3 4 5 6) - """ PS_clear(self.c_ps) @@ -208,7 +198,6 @@ cdef class PythonPartitionStack: [0, 1, 2, 3, 4, 5, 6] sage: P.levels() [7, 7, 7, 7, 7, 7, -1] - """ cdef int i return [self.c_ps.entries[i] for i from 0 <= i < self.c_ps.degree] @@ -225,7 +214,6 @@ cdef class PythonPartitionStack: sage: P.set_entry(0,1) sage: P.display() (1 0 2 3 4 5 6) - """ self.c_ps.entries[i] = entry @@ -239,7 +227,6 @@ cdef class PythonPartitionStack: sage: P = PythonPartitionStack(7) sage: P.get_entry(0) 0 - """ return self.c_ps.entries[i] @@ -255,7 +242,6 @@ cdef class PythonPartitionStack: [0, 1, 2, 3, 4, 5, 6] sage: P.levels() [7, 7, 7, 7, 7, 7, -1] - """ return [self.c_ps.levels[i] for i from 0 <= i < self.c_ps.degree] @@ -273,7 +259,6 @@ cdef class PythonPartitionStack: sage: P.display() (0 1 2 3 4 5 6) (0 1 2|3 4 5 6) - """ self.c_ps.levels[i] = level @@ -287,7 +272,6 @@ cdef class PythonPartitionStack: sage: P = PythonPartitionStack(7) sage: P.get_level(0) 7 - """ return self.c_ps.levels[i] @@ -302,7 +286,6 @@ cdef class PythonPartitionStack: sage: P = PythonPartitionStack(7) sage: P.depth() 0 - """ if new is not None: self.c_ps.depth = new @@ -319,7 +302,6 @@ cdef class PythonPartitionStack: sage: P = PythonPartitionStack(7) sage: P.degree() 7 - """ if new is not None: self.c_ps.degree = new @@ -340,7 +322,6 @@ cdef class PythonPartitionStack: [[0, 1, 2, 3, 4, 5, 6]] sage: P.partition(1) [[0, 1, 2], [3, 4, 5, 6]] - """ cdef int i cdef list partition = [], cell = [] @@ -380,7 +361,6 @@ class PythonObjectWrapper: sage: P.cs_fn - """ self.degree = degree self.obj = obj diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx index 6ccc0b28c45..c3a42da04d8 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx @@ -536,7 +536,7 @@ cdef void deallocate_sgd(void *data) noexcept: cdef void *subset_generator_next(void *data, int *degree, bint *mem_err) noexcept: r""" - Returns the next element to consider adding to the set. + Return the next element to consider adding to the set. """ cdef subset_generator_data *sgd = data while True: @@ -694,11 +694,11 @@ def sets_modulo_perm_group(list generators, int max_size, INPUT: - - ``generators`` - (list of lists) list of generators in list form - - ``max_size`` - (int) maximum size of subsets to be generated - - ``indicate_mem_err`` - (bool) whether to raise an error - if we run out of memory, or simply append a MemoryError - instance to the end of the output + - ``generators`` -- (list of lists) list of generators in list form + - ``max_size`` -- (int) maximum size of subsets to be generated + - ``indicate_mem_err`` -- (bool) whether to raise an error + if we run out of memory, or simply append a MemoryError + instance to the end of the output EXAMPLES:: diff --git a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx index 261d1987897..89529f4e8ce 100644 --- a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx +++ b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx @@ -252,7 +252,6 @@ cdef tuple PS_refinement(PartitionStack * part, long *refine_vals, long *best, j += 1 - loc_begin = i + 1 i += 1 return (True, newly_fixed) @@ -495,17 +494,15 @@ cdef class PartitionRefinement_generic: ##################################################################### cdef bint _inner_min_(self, int pos, bint * inner_group_changed) noexcept: """ - Minimize the node by the action of the inner group on the i-th position. + Minimize the node by the action of the inner group on the ith position. INPUT: - - `pos` - A position in `range(self.n)` - - `inner_group_changed` - will be set to true if `G_y` got smaller - - OUTPUT: + - ``pos`` -- A position in ``range(self.n)`` + - ``inner_group_changed`` -- will be set to ``True`` if `G_y` got smaller - - `True` if and only if the actual node compares less or equal to - the candidate for the canonical form. + OUTPUT: ``True`` if and only if the actual node compares less or equal + to the candidate for the canonical form. """ raise NotImplementedError @@ -517,10 +514,8 @@ cdef class PartitionRefinement_generic: to a smaller subgroup of `S_n`. This function also has to take care on ``self._is_candidate_initialized``. - OUTPUT: - - - `False` only if the actual node compares larger than the candidate - for the canonical form. + OUTPUT: ``False`` only if the actual node compares larger than the + candidate for the canonical form """ raise NotImplementedError diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 3f6431948ea..09c6f8ceab5 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -119,12 +119,12 @@ - Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996. -.. note:: +.. NOTE:: - Though Suzuki groups are okay, Ree groups should *not* be wrapped - as permutation groups - the construction is too slow - unless (for - small values or the parameter) they are made using explicit - generators. + Though Suzuki groups are okay, Ree groups should *not* be wrapped + as permutation groups - the construction is too slow - unless (for + small values or the parameter) they are made using explicit + generators. """ # **************************************************************************** @@ -277,9 +277,7 @@ def PermutationGroup(gens=None, *args, **kwds): - ``canonicalize`` -- boolean (default: ``True``); if ``True``, sort generators and remove duplicates - OUTPUT: - - - a permutation group + OUTPUT: a permutation group EXAMPLES:: @@ -457,9 +455,7 @@ def __init__(self, gens=None, gap_group=None, canonicalize=True, - ``canonicalize`` -- bool (default: ``True``); if ``True``, sort generators and remove duplicates - OUTPUT: - - - A permutation group. + OUTPUT: a permutation group EXAMPLES: @@ -665,9 +661,8 @@ def gap(self): compatibility and have :class:`sage.groups.libgap_morphism.GroupHomset_libgap` work for permutation groups, as well - OUTPUT: - - an instance of :class:`sage.libs.gap.element.GapElement` representing this group + OUTPUT: an instance of :class:`sage.libs.gap.element.GapElement` + representing this group EXAMPLES:: @@ -730,9 +725,7 @@ def _Hom_(self, G, category=None, check=True): - ``G`` -- group; the codomain - ``cat`` -- category - OUTPUT: - - The set of homomorphisms from ``self`` to ``G``. + OUTPUT: the set of homomorphisms from ``self`` to ``G`` EXAMPLES:: @@ -751,7 +744,7 @@ def _Hom_(self, G, category=None, check=True): def _magma_init_(self, magma): r""" - Return a string showing how to declare / initialize self in Magma. + Return a string showing how to declare / initialize ``self`` in Magma. EXAMPLES: @@ -816,7 +809,6 @@ def __richcmp__(self, right, op): False sage: G != H False - """ if not isinstance(right, PermutationGroup_generic): return NotImplemented @@ -1467,7 +1459,6 @@ def exponent(self): sage: G = AlternatingGroup(4) sage: G.exponent() 6 - """ return Integer(self._libgap_().Exponent()) @@ -1593,7 +1584,7 @@ def smallest_moved_point(self): def representative_action(self, x, y): r""" - Return an element of self that maps `x` to `y` if it exists. + Return an element of ``self`` that maps `x` to `y` if it exists. This method wraps the gap function ``RepresentativeAction``, which can also return elements that map a given set of points on another set of @@ -1945,7 +1936,6 @@ def base(self, seed=None): [1, 2, 3, 4, 5] sage: S.base([1,3,5,7,9,11]) # create a base for M12 with only odd integers [1, 3, 5, 7, 9] - """ if seed is None: seed = self.domain() @@ -1992,10 +1982,8 @@ def strong_generating_system(self, base_of_group=None, implementation="sage"): * ``"gap"`` -- if used, the ``base_of_group`` must be ``None`` and the computation is directly performed in GAP - OUTPUT: - - A list of lists of permutations from the group, which form a strong - generating system. + OUTPUT: a list of lists of permutations from the group, which forms a + strong generating system .. WARNING:: @@ -2433,7 +2421,6 @@ def frattini_subgroup(self): sage: G.frattini_subgroup() Subgroup generated by [()] of (Symmetric group of order 4! as a permutation group) - """ return self.subgroup(gap_group=self._libgap_().FrattiniSubgroup()) @@ -2525,7 +2512,6 @@ def intersection(self, other): Traceback (most recent call last): ... TypeError: junk is not a permutation group - """ from sage.categories.finite_permutation_groups import FinitePermutationGroups @@ -2881,7 +2867,6 @@ def semidirect_product(self, N, mapping, check=True): AUTHOR: - Kevin Halasz (2012-8-12) - """ if check: @@ -2927,10 +2912,8 @@ def holomorph(self): See :wikipedia:`Holomorph (mathematics)` - OUTPUT: - - Return the holomorph of a given group as permutation group - via a wrapping of GAP's semidirect product function. + OUTPUT: the holomorph of a given group as permutation group + via a wrapping of GAP's semidirect product function EXAMPLES: @@ -3010,9 +2993,7 @@ def _subgroup_constructor(self, libgap_group): - ``libgap_group`` -- an instance of :class:`sage.libs.gap.element.GapElement` representing a GAP group whose generators belong to ``self.gap()`` - OUTPUT: - - The corresponding subgroup of ``self`` as an instance of this class + OUTPUT: the corresponding subgroup of ``self`` as an instance of this class EXAMPLES:: @@ -3045,10 +3026,9 @@ def as_finitely_presented_group(self, reduced=False): is called, attempting to simplify the presentation of the finitely presented group to be returned. - OUTPUT: - - Finite presentation of ``self``, obtained by taking the image - of the isomorphism returned by the GAP function ``IsomorphismFpGroupByGenerators``. + OUTPUT: finite presentation of ``self``, obtained by taking the image + of the isomorphism returned by the GAP function + ``IsomorphismFpGroupByGenerators`` ALGORITHM: @@ -3195,7 +3175,7 @@ def commutator(self, other=None): The two groups need only be permutation groups, there is no notion of requiring them to explicitly be subgroups of some other group. - .. note:: + .. NOTE:: For the identical statement, the generators of the returned group can vary from one execution to the next. @@ -3511,7 +3491,6 @@ def character_table(self): AUTHORS: - David Joyner and William Stein (2006-01-04) - """ G = self._libgap_() cl = G.ConjugacyClasses() @@ -3734,7 +3713,6 @@ def _regular_subgroup_gap(self): sage: S4._regular_subgroup_gap() # random ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 4 ] ),Group( [ (1,4)(2,3), (1,3)(2,4) ] )) - """ filt = libgap.eval('x -> IsRegular(Representative(x), [1..{}])'.format( self.degree())) @@ -3774,7 +3752,6 @@ def has_regular_subgroup(self, return_group=False): sage: G = graphs.PetersenGraph().automorphism_group() sage: G.has_regular_subgroup() False - """ b = False G = None @@ -3909,7 +3886,7 @@ def cosets(self, S, side='right'): the list of cosets, due to the ordering of the representatives). See below for examples of this. - .. note:: + .. NOTE:: This is a naive implementation intended for instructional purposes, and hence is slow for larger groups. Sage and GAP @@ -4237,15 +4214,11 @@ def isomorphism_to(self, right): INPUT: - - ``self`` -- this group - ``right`` -- a permutation group - - OUTPUT: - - - ``None`` or a morphism of permutation groups. + OUTPUT: ``None``, or a morphism of permutation groups EXAMPLES:: @@ -4290,16 +4263,12 @@ def is_isomorphic(self, right): INPUT: - - ``self`` -- this group - ``right`` -- a permutation group - - OUTPUT: - - - boolean; ``True`` if ``self`` and ``right`` are isomorphic groups; - ``False`` otherwise. + OUTPUT: boolean; ``True`` if ``self`` and ``right`` are isomorphic + groups; ``False`` otherwise EXAMPLES:: @@ -4392,7 +4361,6 @@ def is_pgroup(self): sage: G = PermutationGroup(['(1,2,3,4,5)']) sage: G.is_pgroup() True - """ return bool(self._libgap_().IsPGroup()) @@ -4425,7 +4393,6 @@ def is_simple(self): sage: G = PermutationGroup(['(1,2,3)(4,5)']) sage: G.is_simple() False - """ return bool(self._libgap_().IsSimpleGroup()) @@ -4610,7 +4577,6 @@ def is_primitive(self, domain=None): sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]]) sage: G.is_primitive([1,2,3]) False - """ #If the domain is not a subset of self.domain(), then the #action isn't primitive. @@ -4646,7 +4612,6 @@ def is_semi_regular(self, domain=None): True sage: G.is_semi_regular(G.non_fixed_points()) False - """ try: domain = libgap.eval(self._domain_gap(domain)) @@ -4679,7 +4644,6 @@ def is_regular(self, domain=None): True sage: G.is_regular(G.non_fixed_points()) False - """ try: domain = libgap.eval(self._domain_gap(domain)) @@ -4916,7 +4880,6 @@ def poincare_series(self, p=2, n=10): AUTHORS: - David Joyner and Graham Ellis - """ load_hap() from sage.arith.misc import is_prime @@ -4957,7 +4920,6 @@ def sylow_subgroup(self, p): sage: PSL(10,2).sylow_subgroup(7) Subgroup generated by... - """ return self.subgroup(gap_group=self._libgap_().SylowSubgroup(p)) @@ -5159,7 +5121,6 @@ def __richcmp__(self, other, op): True sage: G.subgroup([G((1,2,3))]) == G.subgroup([G((1,3,2))]) True - """ if self is other: return rich_to_bool(op, 0) @@ -5254,7 +5215,6 @@ def is_normal(self, other=None): (Symmetric group of order 3! as a permutation group) sage: H.is_normal() True - """ if other is None: other = self.ambient_group() @@ -5316,9 +5276,7 @@ def __init__(self, gens, action, domain, gap_group=None, category=None, canonica - ``canonicalize`` -- bool (default: ``True``); if ``True``, sort generators and remove duplicates - OUTPUT: - - - A finite group action given as a permutation group. + OUTPUT: a finite group action given as a permutation group. EXAMPLES:: @@ -5326,7 +5284,6 @@ def __init__(self, gens, action, domain, gap_group=None, category=None, canonica sage: G = PermutationGroup(action=a, domain=range(7)) # needs sage.combinat sage: G.orbits() # needs sage.combinat ((0,), (1, 2, 4), (3, 6, 5)) - """ from sage.combinat.cyclic_sieving_phenomenon import orbit_decomposition from sage.sets.disjoint_set import DisjointSet diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 0d80d04a8af..4c52b386294 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -794,7 +794,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def __reduce__(self): r""" - Returns a function and its arguments needed to create this + Return a function and its arguments needed to create this permutation group element. This is used in pickling. EXAMPLES:: @@ -899,7 +899,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def _gap_init_(self): r""" - Returns a GAP string representation for this + Return a GAP string representation for this PermutationGroupElement. EXAMPLES:: @@ -961,7 +961,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def __getitem__(self, i): r""" Return the ``i``-th permutation cycle in the disjoint cycle - representation of self. + representation of ``self``. INPUT: @@ -1028,7 +1028,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def __call__(self, i): r""" - Returns the image of the integer i under this permutation. + Return the image of the integer i under this permutation. Alternately, if i is a list, tuple or string, returns the result of self acting on i. @@ -1091,7 +1091,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cpdef list _act_on_list_on_position(self, list x): r""" - Returns the right action of ``self`` on the list ``x``. This is the + Return the right action of ``self`` on the list ``x``. This is the action on positions. EXAMPLES:: @@ -1119,7 +1119,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cpdef ClonableIntArray _act_on_array_on_position(self, ClonableIntArray x): r""" - Returns the right action of ``self`` on the ClonableIntArray + Return the right action of ``self`` on the ClonableIntArray ``x``. This is the action on positions. EXAMPLES:: @@ -1422,7 +1422,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cpdef _gap_list(self): r""" - Returns this permutation in list notation compatible with the + Return this permutation in list notation compatible with the GAP numbering. EXAMPLES:: @@ -1446,7 +1446,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def _gap_cycle_string(self): r""" - Returns a cycle string for this permutation compatible with + Return a cycle string for this permutation compatible with the GAP numbering. EXAMPLES:: @@ -1871,10 +1871,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): type should be returned as a :class:`list` or as a :class:`Partition` (default: ``False``) - OUTPUT: - - A :class:`Partition`, or :class:`list` if ``is_list`` is ``True``, - giving the cycle type of ``self`` + OUTPUT: a :class:`Partition`, or :class:`list` if ``is_list`` is + ``True``, giving the cycle type of ``self`` If speed is a concern, then ``as_list=True`` should be used. @@ -1905,13 +1903,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def has_descent(self, i, side="right", positive=False): r""" - INPUT: - - - ``i`` -- an element of the index set - - ``side`` -- ``"left"`` or ``"right"`` (default: ``"right"``) - - ``positive`` -- a boolean (default: ``False``) - - Returns whether ``self`` has a left (resp. right) descent at + Return whether ``self`` has a left (resp. right) descent at position ``i``. If ``positive`` is ``True``, then test for a non descent instead. @@ -1920,6 +1912,12 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): convention. Hence, ``self`` has a left descent at position ``i`` if ``self(i) > self(i+1)``. + INPUT: + + - ``i`` -- an element of the index set + - ``side`` -- ``"left"`` or ``"right"`` (default: ``"right"``) + - ``positive`` -- a boolean (default: ``False``) + EXAMPLES:: sage: S = SymmetricGroup([1,2,3]) @@ -2124,10 +2122,10 @@ cdef class SymmetricGroupElement(PermutationGroupElement): cdef bint is_valid_permutation(int* perm, int n) noexcept: r""" - This is used in the __init__ method. + This is used in the ``__init__`` method. - Returns True iff the first n elements of perm are literally a - permutation of [0, ..., n-1]. + Return ``True`` iff the first ``n`` elements of perm are literally a + permutation of ``[0, ..., n-1]``. TESTS:: diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index 6e979561e43..514b676efbf 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -594,9 +594,7 @@ def conjugacy_class(self, g): - ``g`` -- a partition or an element of the symmetric group ``self`` - OUTPUT: - - A conjugacy class of a symmetric group. + OUTPUT: a conjugacy class of a symmetric group EXAMPLES:: @@ -678,7 +676,7 @@ def __init__(self, domain=None): - ``n`` -- a positive integer, or list or tuple thereof - .. note:: + .. NOTE:: This group is also available via ``groups.permutation.Alternating()``. @@ -753,7 +751,7 @@ def __init__(self, n): - ``n`` -- a positive integer - .. note:: + .. NOTE:: This group is also available via ``groups.permutation.Cyclic()``. @@ -874,7 +872,7 @@ class DiCyclicGroup(PermutationGroup_unique): `i+1` and code `a^{i}x` as the symbol `2n+i+1`. The two generators are then represented using a left regular representation. - .. note:: + .. NOTE:: This group is also available via ``groups.permutation.DiCyclic()``. @@ -1004,7 +1002,7 @@ def _repr_(self): def is_commutative(self): r""" - Return True if this group is commutative. + Return ``True`` if this group is commutative. EXAMPLES:: @@ -1016,7 +1014,7 @@ def is_commutative(self): def is_abelian(self): r""" - Return True if this group is abelian. + Return ``True`` if this group is abelian. EXAMPLES:: @@ -1033,13 +1031,11 @@ def __init__(self): The Klein 4 Group, which has order `4` and exponent `2`, viewed as a subgroup of `S_4`. - OUTPUT: + OUTPUT: the Klein 4 group of order 4, as a permutation group of degree 4 - the Klein 4 group of order 4, as a permutation group of degree 4. - - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.KleinFour()``. + This group is also available via ``groups.permutation.KleinFour()``. EXAMPLES:: @@ -1152,7 +1148,7 @@ class QuaternionGroup(DiCyclicGroup): See the :class:`DiCyclicGroup` class for a generalization of this construction. - .. note:: + .. NOTE:: This group is also available via ``groups.permutation.Quaternion()``. @@ -1431,9 +1427,7 @@ def __init__(self, n): - ``n`` -- a positive integer - OUTPUT: - - The dihedral group of order `2n`, as a permutation group + OUTPUT: the dihedral group of order `2n`, as a permutation group .. NOTE:: @@ -1730,7 +1724,6 @@ def __init__(self, m): AUTHOR: - Kevin Halasz (2012-8-7) - """ if not isinstance(m, Integer): raise TypeError('m must be an integer, not %s' % m) @@ -1776,13 +1769,11 @@ def __init__(self, n): - ``n`` -- a positive integer in {9, 10, 11, 12, 21, 22, 23, 24}. - OUTPUT: + OUTPUT: the Mathieu group of degree `n`, as a permutation group - the Mathieu group of degree `n`, as a permutation group - - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.Mathieu()``. + This group is also available via ``groups.permutation.Mathieu()``. EXAMPLES:: @@ -1830,13 +1821,11 @@ def __init__(self, d, n): - ``n`` -- positive integer; the index of the group in the GAP database, starting at 1 - OUTPUT: - - the `n`-th transitive group of degree `d` + OUTPUT: the `n`-th transitive group of degree `d` - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.Transitive()``. + This group is also available via ``groups.permutation.Transitive()``. EXAMPLES:: @@ -2225,9 +2214,7 @@ class PrimitiveGroup(PermutationGroup_unique): - ``n`` -- positive integer. the index of the group in the GAP database, starting at 1 - OUTPUT: - - The ``n``-th primitive group of degree ``d``. + OUTPUT: Tthe ``n``-th primitive group of degree ``d`` EXAMPLES:: @@ -2302,10 +2289,6 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. - EXAMPLES:: sage: G = PrimitiveGroup(5,1); G @@ -2317,9 +2300,7 @@ def group_primitive_id(self): """ Return the index of this group in the GAP database of primitive groups. - OUTPUT: - - A positive integer, following GAP's conventions. + OUTPUT: a positive integer, following GAP's conventions EXAMPLES:: @@ -2417,9 +2398,7 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. + OUTPUT: a string TESTS:: @@ -2436,9 +2415,7 @@ def __contains__(self, G): - `G` -- anything. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -2494,9 +2471,7 @@ def _repr_(self): """ Return a string representation. - OUTPUT: - - String. + OUTPUT: a string TESTS:: @@ -2513,9 +2488,7 @@ def __contains__(self, G): - `G` -- anything. - OUTPUT: - - Boolean. + OUTPUT: boolean EXAMPLES:: @@ -2568,10 +2541,8 @@ def cardinality(self): r""" Return the cardinality of ``self``. - OUTPUT: - - An integer. The number of primitive groups of a given degree - up to isomorphism. + OUTPUT: an integer; the number of primitive groups of a given degree + up to isomorphism EXAMPLES:: @@ -2648,13 +2619,11 @@ def __init__(self, n, q, name='a'): - ``q`` -- prime power; the size of the ground field - ``name`` -- (default: ``'a'``) variable name of indeterminate of finite field `\GF(q)` - OUTPUT: - - PGL(`n`, `q`) + OUTPUT: PGL(`n`, `q`) - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.PGL()``. + This group is also available via ``groups.permutation.PGL()``. EXAMPLES:: @@ -2710,11 +2679,9 @@ def __init__(self, n, q, name='a'): - ``q`` -- either a prime power (the size of the ground field) or a finite field - ``name`` -- (default: ``'a'``) variable name of indeterminate of finite field `\GF(q)` - OUTPUT: + OUTPUT: the group PSL(`n`, `q`) - the group PSL(`n`, `q`) - - .. note:: + .. NOTE:: This group is also available via ``groups.permutation.PSL()``. @@ -2892,13 +2859,11 @@ def __init__(self, n, q, name='a'): - ``q`` -- prime power; the size of the ground field - ``name`` -- (default: ``'a'``) variable name of indeterminate of finite field `\GF(q)` - OUTPUT: + OUTPUT: PSp(`n`, `q`) - PSp(`n`, `q`) - - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.PSp()``. + This group is also available via ``groups.permutation.PSp()``. EXAMPLES:: @@ -2970,13 +2935,11 @@ def __init__(self, n, q, name='a'): - q -- prime power; the size of the ground field - name -- (default: 'a') variable name of indeterminate of finite field GF(q) - OUTPUT: - - PSU(n,q) + OUTPUT: PSU(n,q) - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.PSU()``. + This group is also available via ``groups.permutation.PSU()``. EXAMPLES:: @@ -3006,7 +2969,6 @@ def _repr_(self): sage: PSU(2,3) # needs sage.rings.finite_rings The projective special unitary group of degree 2 over Finite Field of size 3 - """ return "The projective special unitary group of degree %s over %s" % (self._n, self.base_ring()) @@ -3022,13 +2984,11 @@ def __init__(self, n, q, name='a'): - ``q`` -- prime power; the size of the ground field - ``name`` -- (default: ``'a'``) variable name of indeterminate of finite field `\GF(q)` - OUTPUT: - - PGU(`n`, `q`) + OUTPUT: PGU(`n`, `q`) - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.PGU()``. + This group is also available via ``groups.permutation.PGU()``. EXAMPLES:: @@ -3059,7 +3019,6 @@ def _repr_(self): sage: PGU(2,3) # needs sage.rings.finite_rings The projective general unitary group of degree 2 over Finite Field of size 3 - """ return "The projective general unitary group of degree %s over %s" % (self._n, self.base_ring()) @@ -3080,13 +3039,11 @@ def __init__(self, q, name='a'): - ``name`` -- (default: ``'a'``) variable name of indeterminate of finite field `\GF(q)` - OUTPUT: + OUTPUT: a Suzuki group - A Suzuki group. - - .. note:: + .. NOTE:: - This group is also available via ``groups.permutation.Suzuki()``. + This group is also available via ``groups.permutation.Suzuki()``. EXAMPLES:: @@ -3141,7 +3098,6 @@ def __str__(self): sage: G = SuzukiGroup(32, name='alpha') # needs sage.rings.finite_rings sage: print(G) # needs sage.rings.finite_rings The Suzuki group over Finite Field in alpha of size 2^5 - """ return "The Suzuki group over %s" % self.base_ring() diff --git a/src/sage/groups/perm_gps/symgp_conjugacy_class.py b/src/sage/groups/perm_gps/symgp_conjugacy_class.py index 23f5cdab15c..da051a72523 100644 --- a/src/sage/groups/perm_gps/symgp_conjugacy_class.py +++ b/src/sage/groups/perm_gps/symgp_conjugacy_class.py @@ -307,10 +307,8 @@ def conjugacy_class_iterator(part, S=None): - ``S`` -- (optional, default: `\{ 1, 2, \ldots, n \}`, where `n` is the size of ``part``) a set - OUTPUT: - - An iterator over the conjugacy class consisting of all - permutations of the set ``S`` whose cycle type is ``part``. + OUTPUT: an iterator over the conjugacy class consisting of all + permutations of the set ``S`` whose cycle type is ``part`` EXAMPLES:: diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx index baaefa1950e..c1fc37fda84 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx @@ -30,8 +30,6 @@ with and an elementwisely defined multiplication of vectors. (The indexing of vectors is `0`-based here, so `\psi = (\psi_0, \psi_1, \ldots, \psi_{n-1})`.) - - The parent is :class:`~sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroup`. @@ -77,7 +75,7 @@ def _is_id(f, R): def _inverse(f, R): """ - Returns the inverse to the automorphism `f` of a ring `R`. + Return the inverse to the automorphism `f` of a ring `R`. EXAMPLES:: diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py b/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py index 602896e3ee8..50b5e5741d5 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py @@ -128,11 +128,9 @@ def __init__(self, R, len): - ``R`` -- a ring - - ``len`` -- the degree of the monomial group + - ``len`` -- the degree of the monomial group - OUTPUT: - - - the complete semimonomial group + OUTPUT: the complete semimonomial group EXAMPLES:: From 9fbaf6fae3933a1de422bdbe07e6d0e7ecb56736 Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Thu, 11 Apr 2024 21:32:16 +0300 Subject: [PATCH 136/191] More recommendations by mkoeppe --- src/sage/matroids/basis_exchange_matroid.pyx | 4 +- src/sage/matroids/basis_matroid.pyx | 4 +- .../matroids/circuit_closures_matroid.pyx | 2 +- src/sage/matroids/circuits_matroid.pyx | 4 +- src/sage/matroids/database_matroids.py | 83 +++++++++---------- src/sage/matroids/flats_matroid.pyx | 2 +- src/sage/matroids/graphic_matroid.py | 3 +- src/sage/matroids/linear_matroid.pyx | 14 ++-- src/sage/matroids/matroid.pyx | 4 +- 9 files changed, 55 insertions(+), 65 deletions(-) diff --git a/src/sage/matroids/basis_exchange_matroid.pyx b/src/sage/matroids/basis_exchange_matroid.pyx index 9db2f296679..30038d1d3c0 100644 --- a/src/sage/matroids/basis_exchange_matroid.pyx +++ b/src/sage/matroids/basis_exchange_matroid.pyx @@ -213,9 +213,9 @@ cdef class BasisExchangeMatroid(Matroid): cdef long i E = [] for i in range(self._groundset_size): - if self._E[i] in mapping: + try: E.append(mapping[self._E[i]]) - else: + except LookupError: E.append(self._E[i]) self._E = tuple(E) self._groundset = frozenset(E) diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 72bb8368b4e..c079abe8c46 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -263,7 +263,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): sage: repr(M) # indirect doctest 'Matroid of rank 3 on 7 elements with 28 bases' """ - return Matroid._repr_(self) + " with " + str(self.bases_count()) + " bases" + return f'{Matroid._repr_(self)} with {self.bases_count()} bases' # support for parent BasisExchangeMatroid @@ -531,7 +531,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): INPUT: - - ``mapping`` -- a python object such that `mapping[e]` is the new + - ``mapping`` -- a python object such that ``mapping[e]`` is the new label of ``e`` OUTPUT: a matroid diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index 709b40c4dd1..5e2dcbf9c38 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -609,7 +609,7 @@ cdef class CircuitClosuresMatroid(Matroid): E = [d[x] for x in self.groundset()] CC = {} for i in self.circuit_closures(): - CC[i] = [[d[y] for y in x] for x in list(self._circuit_closures[i])] + CC[i] = [[d[y] for y in x] for x in self._circuit_closures[i]] M = CircuitClosuresMatroid(groundset=E, circuit_closures=CC) return M diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index 7b46b8ff102..3478154867b 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -269,9 +269,9 @@ cdef class CircuitsMatroid(Matroid): NonDesargues: Matroid of rank 3 on 10 elements with 9 nonspanning circuits """ if self._nsc_defined: - return Matroid._repr_(self) + " with " + str(len(self.nonspanning_circuits())) + " nonspanning circuits" + return f'{Matroid._repr_(self)} with {len(self.nonspanning_circuits())} nonspanning circuits' else: - return Matroid._repr_(self) + " with " + str(len(self._C)) + " circuits" + return f'{Matroid._repr_(self)} with {len(self._C)} circuits' # comparison diff --git a/src/sage/matroids/database_matroids.py b/src/sage/matroids/database_matroids.py index 3ab8e0c7816..188fdaab1db 100644 --- a/src/sage/matroids/database_matroids.py +++ b/src/sage/matroids/database_matroids.py @@ -1362,7 +1362,7 @@ def R9(groundset=None): R9: Matroid of rank 3 on 9 elements with 15 nonspanning circuits sage: M.is_valid() True - sage: len(list(M.nonspanning_circuits())) + sage: len(M.nonspanning_circuits()) 15 sage: M.is_simple() and M.is_ternary() True @@ -1834,7 +1834,7 @@ def Wheel(r, field=None, ring=None, groundset=None): M = RegularMatroid(A) else: M = Matroid(A) - M = _rename_and_relabel(M, "Wheel(" + str(r) + ")", groundset) + M = _rename_and_relabel(M, f'Wheel({r})', groundset) return M @@ -1903,7 +1903,7 @@ def Whirl(r, groundset=None): else: A[i, 2 * r - 1] = 1 M = TernaryMatroid(A) - M = _rename_and_relabel(M, "Whirl(" + str(r) + ")", groundset) + M = _rename_and_relabel(M, f'Whirl({r})', groundset) return M @@ -1955,7 +1955,7 @@ def Uniform(r, n, groundset=None): else: CC = {} M = Matroid(groundset=E, circuit_closures=CC) - M = _rename_and_relabel(M, "U(" + str(r) + ", " + str(n) + ")", groundset) + M = _rename_and_relabel(M, f'U({r}, {n})', groundset) return M @@ -1998,7 +1998,7 @@ def PG(n, q, x=None, groundset=None): P = ProjectiveSpace(n, F) A = Matrix(F, [list(p) for p in list(P)]).transpose() M = Matroid(A) - M = _rename_and_relabel(M, "PG(" + str(n) + ", " + str(q) + ")", groundset) + M = _rename_and_relabel(M, f'PG({n}, {q})', groundset) return M @@ -2045,7 +2045,7 @@ def AG(n, q, x=None, groundset=None): F, [list(p) for p in list(P) if not list(p)[0] == 0] ).transpose() M = Matroid(A) - M = _rename_and_relabel(M, "AG(" + str(n) + ", " + str(q) + ")", groundset) + M = _rename_and_relabel(M, f'AG({n}, {q})', groundset) return M @@ -2129,15 +2129,15 @@ def Z(r, t=True, groundset=None): A = Id.augment(J-Id).augment(tip) M = Matroid(A) - X = ['x'+str(i) for i in range(1, r+1)] - Y = ['y'+str(i) for i in range(1, r+1)] + X = [f'x{i}' for i in range(1, r + 1)] + Y = [f'y{i}' for i in range(1, r + 1)] if t: - M = M.relabel(X+Y+['t']) - M.rename("Z_" + str(r) + ": " + repr(M)) + M = M.relabel(X + Y + ['t']) + M.rename(f'Z_{r}: ' + repr(M)) else: - M = M.delete(2*r) - M = M.relabel(X+Y) - M.rename("Z_" + str(r) + "\\t: " + repr(M)) + M = M.delete(2 * r) + M = M.relabel(X + Y) + M.rename(f'Z_{r}\\t: ' + repr(M)) M = _rename_and_relabel(M, groundset=groundset) return M @@ -2176,7 +2176,7 @@ def Spike(r, t=True, C3=[], groundset=None): nonspanning circuits sage: M.is_isomorphic(matroids.Uniform(3, 6)) True - sage: len(list(matroids.Spike(8).bases())) + sage: len(matroids.Spike(8).bases()) 4864 sage: import random sage: r = random.choice(range(3, 20)) @@ -2228,16 +2228,16 @@ def Spike(r, t=True, C3=[], groundset=None): E = ['t'] X, Y = [], [] for i in range(1, r + 1): - X.append('x' + str(i)) - Y.append('y' + str(i)) + X.append(f'x{i}') + Y.append(f'y{i}') E += X E += Y if C3 == [] and r > 3: # free spike (can be defined fast through circuit closures) - lines = [['t', 'x'+str(i), 'y'+str(i)] for i in range(1, r+1)] - planes = [['t', 'x'+str(i), 'y'+str(i), 'x'+str(j), 'y'+str(j)] - for i in range(1, r+1) for j in range(i+1, r+1)] + lines = [['t', f'x{i}', f'y{i}'] for i in range(1, r + 1)] + planes = [['t', f'x{i}', f'y{i}', f'x{j}', f'y{j}'] + for i in range(1, r + 1) for j in range(i + 1, r + 1)] CC = {2: lines, 3: planes, r: [E]} M = Matroid(circuit_closures=CC) else: @@ -2256,17 +2256,17 @@ def Spike(r, t=True, C3=[], groundset=None): NSC = [] # nonspanning_circuits NSC += C3 - for i in range(1, r+1): - NSC += [['t', 'x'+str(i), 'y'+str(i)]] - for j in range(i+1, r+1): - NSC += [['x'+str(i), 'y'+str(i), 'x'+str(j), 'y'+str(j)]] + for i in range(1, r + 1): + NSC += [['t', f'x{i}', f'y{i}']] + for j in range(i + 1, r + 1): + NSC += [[f'x{i}', f'y{i}', f'x{j}', f'y{j}']] M = Matroid(rank=r, nonspanning_circuits=NSC) free = "Free " if C3 == [] else "" tip = "" if t else "\\t" M = M if t else M.delete('t') - M = _rename_and_relabel(M, free + str(r) + "-spike" + tip, groundset) + M = _rename_and_relabel(M, f'{free}{r}-spike{tip}', groundset) return M @@ -2325,26 +2325,25 @@ def Theta(n, groundset=None): [Oxl2011]_, p. 663-4. """ - X = ['x'+str(i) for i in range(n)] - Y = ['y'+str(i) for i in range(n)] - E = X + Y + X = [f'x{i}' for i in range(n)] + Y = [f'y{i}' for i in range(n)] import itertools C = [] C += list(itertools.combinations(X, 3)) for i in range(n): Yi = [Y[j] for j in range(len(Y)) if j != i] - C += [Yi + ['x'+str(i)]] + C += [Yi + [f'x{i}']] for u in range(n): for s in range(n): - for t in range(s+1, n): + for t in range(s + 1, n): if u != s and u != t and s != t: Yu = [Y[i] for i in range(len(Y)) if i != u] - C += [Yu + ['x'+str(s)] + ['x'+str(t)]] + C += [Yu + [f'x{s}'] + [f'x{t}']] M = Matroid(circuits=C) - M = _rename_and_relabel(M, "Theta_" + str(n), groundset) + M = _rename_and_relabel(M, f'Theta_{n}', groundset) return M @@ -2395,8 +2394,8 @@ def Psi(r, groundset=None): [Oxl2011]_, p. 664. """ - A = ['a'+str(i) for i in range(0, r)] - B = ['b'+str(i) for i in range(0, r)] + A = [f'a{i}' for i in range(0, r)] + B = [f'b{i}' for i in range(0, r)] E = A + B def generate_binary_strings(bit_count): @@ -2414,20 +2413,20 @@ def genbin(n, bs=""): NSC = [] # nonspanning circuits for i in range(0, r): - for k in range(1, r-2): - I0 = ['a'+str(i), 'b'+str(i)] - IK = ['a'+str((i+k) % r), 'b'+str((i+k) % r)] - for AB in generate_binary_strings(k-1): + for k in range(1, r - 2): + I0 = [f'a{i}', f'b{i}'] + IK = [f'a{(i+k) % r}', f'b{(i+k) % r}'] + for AB in generate_binary_strings(k - 1): C = [] C += I0 + IK j = 1 for z in AB: - C += [z+str((i+j) % r)] + C += [f'{z}{(i+j) % r}'] j += 1 NSC += [C] M = Matroid(groundset=E, rank=r, nonspanning_circuits=NSC) - M = _rename_and_relabel(M, "Psi_" + str(r), groundset) + M = _rename_and_relabel(M, f'Psi_{r}', groundset) return M @@ -5209,7 +5208,7 @@ def CompleteGraphic(n, groundset=None): groundset=list(range((n * (n - 1)) // 2)), graph=graphs.CompleteGraph(n) ) - M = _rename_and_relabel(M, "M(K" + str(n) + ")", groundset) + M = _rename_and_relabel(M, f'M(K{n})', groundset) return M @@ -5229,9 +5228,7 @@ def _rename_and_relabel(M, name=None, groundset=None): - ``name`` -- a string (optional) - ``groundset`` -- a string (optional) - OUTPUT: - - a matroid + OUTPUT: a matroid """ if groundset is not None: if len(groundset) != len(M.groundset()): diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index 8e701c56198..74f64621dd1 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -205,7 +205,7 @@ cdef class FlatsMatroid(Matroid): Matroid of rank 6 on 6 elements with 64 flats """ flats_num = sum(1 for i in self._F for F in self._F[i]) - return Matroid._repr_(self) + " with " + str(flats_num) + " flats" + return f'{Matroid._repr_(self)} with {flats_num} flats' # comparison diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 21be785969a..53f30e7ed88 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -306,8 +306,7 @@ def _repr_(self): """ self._mrank = str(self._rank(self._groundset)) self._elts = str(len(self._groundset)) - - return "Graphic matroid of rank " + self._mrank + " on " + self._elts + " elements" + return f'Graphic matroid of rank {self._mrank} on {self._elts} elements' # Comparison: diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index b2fd28c99ea..f996aceca57 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -466,8 +466,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): 'Linear matroid of rank 2 on 5 elements represented over the Finite Field of size 5' """ - S = "Linear matroid of rank " + str(self.rank()) + " on " + str(self.size()) + " elements represented over the " + repr(self.base_ring()) - return S + return f'Linear matroid of rank {self.rank()} on {self.size()} elements represented over the {repr(self.base_ring())}' # representations @@ -3247,8 +3246,7 @@ cdef class BinaryMatroid(LinearMatroid): sage: repr(M) # indirect doctest 'Binary matroid of rank 3 on 7 elements, type (3, 0)' """ - S = "Binary matroid of rank " + str(self.rank()) + " on " + str(self.size()) + " elements, type (" + str(self.bicycle_dimension()) + ', ' + str(self.brown_invariant()) + ')' - return S + return f'Binary matroid of rank {self.rank()} on {self.size()} elements, type ({self.bicycle_dimension()}, {self.brown_invariant()})' cpdef _current_rows_cols(self, B=None): """ @@ -4351,7 +4349,7 @@ cdef class TernaryMatroid(LinearMatroid): sage: repr(M) # indirect doctest 'Ternary matroid of rank 3 on 7 elements, type 0-' """ - S = "Ternary matroid of rank " + str(self.rank()) + " on " + str(self.size()) + " elements, type " + str(self.bicycle_dimension()) + S = f'Ternary matroid of rank {self.rank()} on {self.size()} elements, type {self.bicycle_dimension()}' if self.character() == 1: S = S + '+' else: @@ -5278,8 +5276,7 @@ cdef class QuaternaryMatroid(LinearMatroid): sage: repr(M) # indirect doctest # needs sage.rings.finite_rings 'Quaternary matroid of rank 2 on 3 elements' """ - S = "Quaternary matroid of rank " + str(self.rank()) + " on " + str(self.size()) + " elements" - return S + return f'Quaternary matroid of rank {self.rank()} on {self.size()} elements' cpdef _current_rows_cols(self, B=None): """ @@ -6023,8 +6020,7 @@ cdef class RegularMatroid(LinearMatroid): sage: repr(M) # indirect doctest 'Regular matroid of rank 5 on 10 elements with 162 bases' """ - S = "Regular matroid of rank " + str(self.rank()) + " on " + str(self.size()) + " elements with " + str(self.bases_count()) + " bases" - return S + return f'Regular matroid of rank {self.rank()} on {self.size()} elements with {self.bases_count()} bases' cpdef bases_count(self): """ diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 36d7c7f7352..eec3a331fe6 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -1197,9 +1197,7 @@ cdef class Matroid(SageObject): sage: sage.matroids.matroid.Matroid._repr_(M) 'Matroid of rank 4 on 8 elements' """ - S = "Matroid of rank " - S = S + str(self.rank()) + " on " + str(self.size()) + " elements" - return S + return f'Matroid of rank {self.rank()} on {self.size()} elements' # cpdef show(self): # Show either the graph, or the matrix with labels, or the lattice, From acfc96250eab0edd7e9c50d688042d27ee011762 Mon Sep 17 00:00:00 2001 From: gmou3 <32706872+gmou3@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:45:31 +0300 Subject: [PATCH 137/191] Update src/sage/matroids/linear_matroid.pyx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/matroids/linear_matroid.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index f996aceca57..142c461e297 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -466,7 +466,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): 'Linear matroid of rank 2 on 5 elements represented over the Finite Field of size 5' """ - return f'Linear matroid of rank {self.rank()} on {self.size()} elements represented over the {repr(self.base_ring())}' + return f'Linear matroid of rank {self.rank()} on {self.size()} elements represented over the {self.base_ring()!r}' # representations From ad196d956f9bbb67c4746ad2cbab0aa5cb0c5ed6 Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Fri, 12 Apr 2024 02:30:44 +0300 Subject: [PATCH 138/191] More docstring improvements in groups --- src/sage/groups/abelian_gps/abelian_group.py | 101 +++++++++--------- .../abelian_gps/abelian_group_element.py | 8 +- .../groups/abelian_gps/abelian_group_gap.py | 18 ++-- src/sage/groups/abelian_gps/all.py | 7 +- .../groups/abelian_gps/dual_abelian_group.py | 10 +- src/sage/groups/abelian_gps/element_base.py | 8 +- src/sage/groups/abelian_gps/values.py | 44 ++++---- .../additive_abelian_group.py | 20 ++-- .../additive_abelian_wrapper.py | 10 +- src/sage/groups/additive_abelian/qmodnz.py | 2 +- .../groups/additive_abelian/qmodnz_element.py | 4 +- src/sage/groups/affine_gps/affine_group.py | 10 +- src/sage/groups/affine_gps/euclidean_group.py | 4 +- src/sage/groups/affine_gps/group_element.py | 18 ++-- src/sage/groups/artin.py | 10 +- src/sage/groups/braid.py | 22 ++-- src/sage/groups/cactus_group.py | 2 +- src/sage/groups/class_function.py | 64 ++++------- src/sage/groups/cubic_braid.py | 35 +++--- src/sage/groups/finitely_presented.py | 42 ++++---- src/sage/groups/finitely_presented_named.py | 18 ++-- src/sage/groups/fqf_orthogonal.py | 2 +- src/sage/groups/free_group.py | 44 ++++---- src/sage/groups/galois_group.py | 28 ++--- src/sage/groups/galois_group_perm.py | 10 +- src/sage/groups/generic.py | 40 +++---- src/sage/groups/group.pyx | 6 +- src/sage/groups/group_exp.py | 4 +- src/sage/groups/group_semidirect_product.py | 3 +- src/sage/groups/indexed_free_group.py | 5 +- src/sage/groups/libgap_mixin.py | 12 +-- src/sage/groups/libgap_morphism.py | 5 +- src/sage/groups/libgap_wrapper.pyx | 18 ++-- .../groups/matrix_gps/finitely_generated.py | 12 +-- .../matrix_gps/finitely_generated_gap.py | 8 +- src/sage/groups/matrix_gps/group_element.pyx | 6 +- .../groups/matrix_gps/group_element_gap.pyx | 4 +- src/sage/groups/matrix_gps/isometries.py | 17 +-- src/sage/groups/matrix_gps/linear.py | 8 +- src/sage/groups/matrix_gps/matrix_group.py | 21 ++-- .../groups/matrix_gps/matrix_group_gap.py | 22 ++-- src/sage/groups/matrix_gps/named_group.py | 4 +- src/sage/groups/matrix_gps/named_group_gap.py | 18 ++-- src/sage/groups/matrix_gps/orthogonal.py | 8 +- src/sage/groups/matrix_gps/unitary.py | 2 +- src/sage/groups/misc_gps/argument_groups.py | 10 +- src/sage/groups/old.pyx | 5 +- src/sage/groups/pari_group.py | 4 +- .../perm_gps/partn_ref/data_structures.pyx | 39 +++---- .../perm_gps/partn_ref/refinement_binary.pyx | 62 +++++------ .../perm_gps/partn_ref/refinement_graphs.pyx | 28 ++--- .../partn_ref/refinement_matrices.pyx | 11 +- .../perm_gps/partn_ref/refinement_python.pyx | 43 ++++---- .../perm_gps/partn_ref/refinement_sets.pyx | 28 ++--- .../partn_ref2/refinement_generic.pyx | 8 +- src/sage/groups/perm_gps/permgroup.py | 2 +- src/sage/groups/perm_gps/permgroup_named.py | 24 ++--- .../semimonomial_transformation.pyx | 12 +-- 58 files changed, 520 insertions(+), 520 deletions(-) diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index a3db5c46179..b0752d92908 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -40,21 +40,21 @@ invariant factors of the group. You should now use :meth:`~AbelianGroup_class.gens_orders` instead:: - sage: J = AbelianGroup([2,0,3,2,4]); J - Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4 - sage: J.gens_orders() # use this instead - (2, 0, 3, 2, 4) - sage: J.invariants() # deprecated - (2, 0, 3, 2, 4) - sage: J.elementary_divisors() # these are the "invariant factors" - (2, 2, 12, 0) - sage: for i in range(J.ngens()): - ....: print((i, J.gen(i), J.gen(i).order())) # or use this form - (0, f0, 2) - (1, f1, +Infinity) - (2, f2, 3) - (3, f3, 2) - (4, f4, 4) + sage: J = AbelianGroup([2,0,3,2,4]); J + Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4 + sage: J.gens_orders() # use this instead + (2, 0, 3, 2, 4) + sage: J.invariants() # deprecated + (2, 0, 3, 2, 4) + sage: J.elementary_divisors() # these are the "invariant factors" + (2, 2, 12, 0) + sage: for i in range(J.ngens()): + ....: print((i, J.gen(i), J.gen(i).order())) # or use this form + (0, f0, 2) + (1, f1, +Infinity) + (2, f2, 3) + (3, f3, 2) + (4, f4, 4) Background on invariant factors and the Smith normal form (according to section 4.1 of [Cohen1]_): An abelian group is a @@ -160,7 +160,7 @@ .. [Rotman] \J. Rotman, An introduction to the theory of groups, 4th ed, Springer, 1995. -.. warning:: +.. WARNING:: Many basic properties for infinite abelian groups are not implemented. @@ -221,15 +221,17 @@ from sage.structure.unique_representation import UniqueRepresentation -# TODO: this uses perm groups - the AbelianGroupElement instance method -# uses a different implementation. +# .. TODO:: + +# this uses perm groups - the AbelianGroupElement instance method +# uses a different implementation. def word_problem(words, g, verbose=False): r""" - G and H are abelian, g in G, H is a subgroup of G generated by a - list (words) of elements of G. If g is in H, return the expression - for g as a word in the elements of (words). + `G` and `H` are abelian, `g` in `G`, `H` is a subgroup of `G` generated by + a list (words) of elements of `G`. If `g` is in `H`, return the expression + for `g` as a word in the elements of (words). - The 'word problem' for a finite abelian group G boils down to the + The 'word problem' for a finite abelian group `G` boils down to the following matrix-vector analog of the Chinese remainder theorem. Problem: Fix integers `1 tuple: """ Return the generators for this subgroup. - OUTPUT: a tuple of group elements generating the subgroup + OUTPUT: tuple of group elements generating the subgroup EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/abelian_group_element.py b/src/sage/groups/abelian_gps/abelian_group_element.py index 501872aaedd..3dc764dd7d0 100644 --- a/src/sage/groups/abelian_gps/abelian_group_element.py +++ b/src/sage/groups/abelian_gps/abelian_group_element.py @@ -49,8 +49,8 @@ def is_AbelianGroupElement(x): """ - Return true if x is an abelian group element, i.e., an element of - type AbelianGroupElement. + Return ``True`` if x is an abelian group element, i.e., an element of + type ``AbelianGroupElement``. EXAMPLES: Though the integer 3 is in the integers, and the integers have an abelian group structure, 3 is not an AbelianGroupElement:: @@ -92,8 +92,8 @@ class AbelianGroupElement(AbelianGroupElementBase): """ def as_permutation(self): r""" - Return the element of the permutation group G (isomorphic to the - abelian group A) associated to a in A. + Return the element of the permutation group ``G`` (isomorphic to the + abelian group ``A``) associated to ``a`` in ``A``. EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/abelian_group_gap.py b/src/sage/groups/abelian_gps/abelian_group_gap.py index 41316f3b433..45a6a8bdd1a 100644 --- a/src/sage/groups/abelian_gps/abelian_group_gap.py +++ b/src/sage/groups/abelian_gps/abelian_group_gap.py @@ -92,7 +92,7 @@ def __reduce__(self): r""" Implement pickling. - OUTPUT: a tuple ``f`` such that this element is ``f[0](*f[1])`` + OUTPUT: tuple ``f`` such that this element is ``f[0](*f[1])`` EXAMPLES:: @@ -110,7 +110,7 @@ def exponents(self): r""" Return the tuple of exponents of this element. - OUTPUT: a tuple of integers + OUTPUT: tuple of integers EXAMPLES:: @@ -168,7 +168,7 @@ def order(self): r""" Return the order of this element. - OUTPUT: an integer or infinity + OUTPUT: integer or infinity EXAMPLES:: @@ -198,7 +198,7 @@ def exponents(self): r""" Return the tuple of exponents of ``self``. - OUTPUT: a tuple of integers + OUTPUT: tuple of integers EXAMPLES:: @@ -283,7 +283,7 @@ def _coerce_map_from_(self, S): def _element_constructor_(self, x, check=True): r""" - Defines coercions and conversions. + Define coercions and conversions. INPUT: @@ -482,7 +482,7 @@ def gens_orders(self): Use :meth:`elementary_divisors` if you are looking for an invariant of the group. - OUTPUT: a tuple of integers + OUTPUT: tuple of integers EXAMPLES:: @@ -715,7 +715,7 @@ def _repr_(self): def __reduce__(self): r""" - Implements pickling. + Implement pickling. We have to work around the fact that gap does not provide pickling. @@ -804,7 +804,7 @@ def _repr_(self): def __reduce__(self): r""" - Implements pickling. + Implement pickling. We have to work around the fact that gap does not provide pickling. @@ -935,7 +935,7 @@ def _repr_(self): def __reduce__(self): r""" - Implements pickling. + Implement pickling. We have to work around the fact that gap does not provide pickling. diff --git a/src/sage/groups/abelian_gps/all.py b/src/sage/groups/abelian_gps/all.py index 2bb91f85f3b..fa418e36c0c 100644 --- a/src/sage/groups/abelian_gps/all.py +++ b/src/sage/groups/abelian_gps/all.py @@ -20,10 +20,11 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -#from dual_abelian_group import DualAbelianGroup +# from dual_abelian_group import DualAbelianGroup from .abelian_group import AbelianGroup, word_problem from .values import AbelianGroupWithValues -# TODO: -# Implement group homset, conversion of generator images to morphism +# .. TODO:: + +# Implement group homset, conversion of generator images to morphism from .abelian_group_morphism import AbelianGroupMorphism diff --git a/src/sage/groups/abelian_gps/dual_abelian_group.py b/src/sage/groups/abelian_gps/dual_abelian_group.py index 7b1bbaee40d..86966cf74d6 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group.py @@ -117,7 +117,7 @@ class DualAbelianGroup_class(UniqueRepresentation, AbelianGroupBase): def __init__(self, G, names, base_ring): """ - The Python constructor + The Python constructor. EXAMPLES:: @@ -271,7 +271,7 @@ def gens(self) -> tuple: """ Return the generators for the group. - OUTPUT: a tuple of group elements generating the group + OUTPUT: tuple of group elements generating the group EXAMPLES:: @@ -299,7 +299,7 @@ def gens_orders(self): """ The orders of the generators of the dual group. - OUTPUT: a tuple of integers + OUTPUT: tuple of integers EXAMPLES:: @@ -328,7 +328,7 @@ def invariants(self): def __contains__(self, X): """ - Implements "in". + Implement "in". EXAMPLES:: @@ -373,7 +373,7 @@ def is_commutative(self): @cached_method def list(self): """ - Return tuple of all elements of this group. + Return a tuple of all elements of this group. EXAMPLES:: diff --git a/src/sage/groups/abelian_gps/element_base.py b/src/sage/groups/abelian_gps/element_base.py index 43d77c29494..7712049e219 100644 --- a/src/sage/groups/abelian_gps/element_base.py +++ b/src/sage/groups/abelian_gps/element_base.py @@ -214,7 +214,7 @@ def order(self): """ Return the order of this element. - OUTPUT: an integer or ``infinity`` + OUTPUT: integer or ``infinity`` EXAMPLES:: @@ -248,7 +248,7 @@ def order(self): def _div_(left, right): """ - Divide ``left`` and ``right`` + Divide ``left`` and ``right``. TESTS:: @@ -266,7 +266,7 @@ def _div_(left, right): def _mul_(left, right): """ - Multiply ``left`` and ``right`` + Multiply ``left`` and ``right``. TESTS:: @@ -284,7 +284,7 @@ def _mul_(left, right): def __pow__(self, n): """ - Exponentiate ``self`` + Exponentiate ``self``. TESTS:: diff --git a/src/sage/groups/abelian_gps/values.py b/src/sage/groups/abelian_gps/values.py index eda0858b1f8..c38edcfb9f9 100644 --- a/src/sage/groups/abelian_gps/values.py +++ b/src/sage/groups/abelian_gps/values.py @@ -16,7 +16,7 @@ number field. The :func:`AbelianGroupWithValues` keeps track of these associated values. -.. warning:: +.. WARNING:: Really, this requires a group homomorphism from the abstract Abelian group to the set of values. This is only checked if you @@ -85,10 +85,10 @@ def AbelianGroupWithValues(values, n, gens_orders=None, names='f', check=False, INPUT: - ``values`` -- a list/tuple/iterable of values that you want to - associate to the generators. + associate to the generators - ``n`` -- integer (optional). If not specified, will be derived - from ``gens_orders``. + from ``gens_orders`` - ``gens_orders`` -- a list of non-negative integers in the form `[a_0, a_1, \dots, a_{n-1}]`, typically written in increasing @@ -156,7 +156,7 @@ class AbelianGroupWithValuesEmbedding(Morphism): - ``domain`` -- a :class:`AbelianGroupWithValues_class` - ``codomain`` -- the values group (need not be in the category of - groups, e.g. symbolic ring). + groups, e.g. symbolic ring) EXAMPLES:: @@ -176,7 +176,7 @@ class AbelianGroupWithValuesEmbedding(Morphism): def __init__(self, domain, codomain): """ - Construct the morphism + Construct the morphism. TESTS:: @@ -218,13 +218,13 @@ class AbelianGroupWithValuesElement(AbelianGroupElement): INPUT: - - ``exponents`` -- tuple of integers. The exponent vector defining - the group element. + - ``exponents`` -- tuple of integers; the exponent vector defining + the group element - - ``parent`` -- the parent. + - ``parent`` -- the parent - ``value`` -- the value assigned to the group element or ``None`` - (default). In the latter case, the value is computed as needed. + (default); in the latter case, the value is computed as needed EXAMPLES:: @@ -235,7 +235,7 @@ class AbelianGroupWithValuesElement(AbelianGroupElement): def __init__(self, parent, exponents, value=None): """ - Create an element + Create an element. EXAMPLES:: @@ -269,7 +269,7 @@ def value(self): def _div_(left, right): """ - Divide ``left`` by ``right`` + Divide ``left`` by ``right``. TESTS:: @@ -287,7 +287,7 @@ def _div_(left, right): def _mul_(left, right): """ - Multiply ``left`` and ``right`` + Multiply ``left`` and ``right``. TESTS:: @@ -305,11 +305,11 @@ def _mul_(left, right): def __pow__(self, n): """ - Exponentiate ``self`` + Exponentiate ``self``. INPUT: - - ``n`` -- integer. The exponent. + - ``n`` -- integer; the exponent TESTS:: @@ -357,15 +357,15 @@ class AbelianGroupWithValues_class(AbelianGroup_class): INPUT: - - ``generator_orders`` -- tuple of integers. The orders of the + - ``generator_orders`` -- tuple of integers; the orders of the generators. - - ``names`` -- string or list of strings. The names for the generators. + - ``names`` -- string or list of strings; the names for the generators - - ``values`` -- Tuple the same length as the number of - generators. The values assigned to the generators. + - ``values`` -- tuple the same length as the number of + generators; the values assigned to the generators. - - ``values_group`` -- the common parent of the values. + - ``values_group`` -- the common parent of the values EXAMPLES:: @@ -376,7 +376,7 @@ class AbelianGroupWithValues_class(AbelianGroup_class): def __init__(self, generator_orders, names, values, values_group): """ - The Python constructor + The Python constructor. TESTS:: @@ -406,7 +406,7 @@ def gen(self, i=0): INPUT: - - ``i`` -- integer (default: 0). The index of the generator. + - ``i`` -- integer (default: 0); the index of the generator OUTPUT: a group element @@ -434,7 +434,7 @@ def gens_values(self): """ Return the values associated to the generators. - OUTPUT: a tuple + OUTPUT: tuple EXAMPLES:: diff --git a/src/sage/groups/additive_abelian/additive_abelian_group.py b/src/sage/groups/additive_abelian/additive_abelian_group.py index 394ef807944..bbf91165437 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_group.py +++ b/src/sage/groups/additive_abelian/additive_abelian_group.py @@ -18,12 +18,12 @@ def AdditiveAbelianGroup(invs, remember_generators=True): INPUT: - - ``invs`` (list of integers): the invariants. + - ``invs`` -- list of integers; the invariants. These should all be greater than or equal to zero. - - ``remember_generators`` (boolean): whether or not to fix a set of - generators (corresponding to the given invariants, which need not be in - Smith form). + - ``remember_generators`` -- boolean (default: ``True``); whether or not + to fix a set of generators (corresponding to the given invariants, which + need not be in Smith form). OUTPUT: the abelian group `\bigoplus_i \ZZ / n_i \ZZ`, where `n_i` are the invariants @@ -206,9 +206,9 @@ class AdditiveAbelianGroup_class(FGP_Module_class): INPUT: - - ``cover`` -- the covering group as `\ZZ`-module. + - ``cover`` -- the covering group as `\ZZ`-module - - ``relations`` -- the relations as submodule of ``cover``. + - ``relations`` -- the relations as submodule of ``cover`` """ # The element class must be overridden in derived classes @@ -295,11 +295,11 @@ def _module_constructor(self, cover, relations, check=True): INPUT: - - ``cover`` -- the covering group as `\ZZ`-module. + - ``cover`` -- the covering group as `\ZZ`-module - - ``relations`` -- the relations as submodule of ``cover``. + - ``relations`` -- the relations as submodule of ``cover`` - - ``check`` -- ignored, present for compatibility with ``fg_pid`` code. + - ``check`` -- ignored, present for compatibility with ``fg_pid`` code EXAMPLES:: @@ -325,7 +325,7 @@ def _module_constructor(self, cover, relations, check=True): def order(self): r""" - Return the order of this group (an integer or infinity) + Return the order of this group (integer or infinity). EXAMPLES:: diff --git a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py index c12a67725b6..966b3137cdb 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py +++ b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py @@ -2,7 +2,7 @@ Wrapper class for abelian groups This class is intended as a template for anything in Sage that needs the -functionality of abelian groups. One can create an AdditiveAbelianGroupWrapper +functionality of abelian groups. One can create an ``AdditiveAbelianGroupWrapper`` object from any given set of elements in some given parent, as long as an ``_add_`` method has been defined. @@ -41,10 +41,10 @@ .. TODO:: - - Think about subgroups and quotients, which probably won't work - in the current implementation -- some fiddly adjustments will be - needed in order to be able to pass extra arguments to the - subquotient's init method. + Think about subgroups and quotients, which probably won't work + in the current implementation -- some fiddly adjustments will be + needed in order to be able to pass extra arguments to the + subquotient's init method. AUTHORS: diff --git a/src/sage/groups/additive_abelian/qmodnz.py b/src/sage/groups/additive_abelian/qmodnz.py index 34e9a0e9132..8ae0dd35728 100644 --- a/src/sage/groups/additive_abelian/qmodnz.py +++ b/src/sage/groups/additive_abelian/qmodnz.py @@ -51,7 +51,7 @@ class QmodnZ(Parent, UniqueRepresentation): #. ``QQ/(n*ZZ)``, where - - `n` -- an integer (including 0 or negative integers). + - `n` -- integer (including 0 or negative integers). OUTPUT: the abelian group `\Q/n\Z` diff --git a/src/sage/groups/additive_abelian/qmodnz_element.py b/src/sage/groups/additive_abelian/qmodnz_element.py index 73557159161..b3ebe8e2335 100644 --- a/src/sage/groups/additive_abelian/qmodnz_element.py +++ b/src/sage/groups/additive_abelian/qmodnz_element.py @@ -34,9 +34,9 @@ class QmodnZ_Element(AdditiveGroupElement): INPUT: - - ``q`` -- a rational number. + - ``q`` -- a rational number - - ``parent`` -- the parent abelian group `\Q/n\Z`. + - ``parent`` -- the parent abelian group `\Q/n\Z` OUTPUT: the element `q` of abelian group `\Q/n\Z`, in standard form diff --git a/src/sage/groups/affine_gps/affine_group.py b/src/sage/groups/affine_gps/affine_group.py index 38fa05058e0..f0e4b3d27f4 100644 --- a/src/sage/groups/affine_gps/affine_group.py +++ b/src/sage/groups/affine_gps/affine_group.py @@ -186,11 +186,11 @@ def __init__(self, degree, ring): INPUT: - - ``degree`` -- integer. The degree of the affine group, that + - ``degree`` -- integer; The degree of the affine group, that is, the dimension of the affine space the group is acting on - naturally. + naturally - - ``ring`` -- a ring. The base ring of the affine space. + - ``ring`` -- a ring; the base ring of the affine space EXAMPLES:: @@ -308,7 +308,7 @@ def degree(self): """ Return the dimension of the affine space. - OUTPUT: an integer + OUTPUT: integer EXAMPLES:: @@ -435,7 +435,7 @@ def reflection(self, v): INPUT: - - ``v`` -- a vector, or something that determines a vector. + - ``v`` -- a vector, or something that determines a vector OUTPUT: diff --git a/src/sage/groups/affine_gps/euclidean_group.py b/src/sage/groups/affine_gps/euclidean_group.py index 3154eee7a01..000210ddeab 100644 --- a/src/sage/groups/affine_gps/euclidean_group.py +++ b/src/sage/groups/affine_gps/euclidean_group.py @@ -164,9 +164,9 @@ def _element_constructor_check(self, A, b): INPUT: - - ``A`` -- an element of :meth:`matrix_space`. + - ``A`` -- an element of :meth:`matrix_space` - - ``b`` -- an element of :meth:`vector_space`. + - ``b`` -- an element of :meth:`vector_space` OUTPUT: diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index 703137784e4..c4ffa997e94 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -53,20 +53,20 @@ class AffineGroupElement(MultiplicativeGroupElement): INPUT: - ``A`` -- an invertible matrix, or something defining a - matrix if ``convert==True``. + matrix if ``convert==True`` - ``b``-- a vector, or something defining a vector if ``convert==True`` (default: ``0``, defining the zero - vector). + vector) - - ``parent`` -- the parent affine group. + - ``parent`` -- the parent affine group - - ``convert`` - bool (default: ``True``). Whether to convert + - ``convert`` - bool (default: ``True``); whether to convert ``A`` into the correct matrix space and ``b`` into the - correct vector space. + correct vector space - - ``check`` - bool (default: ``True``). Whether to do some - checks or just accept the input as valid. + - ``check`` - bool (default: ``True``); whether to do some + checks or just accept the input as valid As a special case, ``A`` can be a matrix obtained from :meth:`matrix`, that is, one row and one column larger. In @@ -326,7 +326,7 @@ def _mul_(self, other): INPUT: - - ``other`` -- another element of the same affine group. + - ``other`` -- another element of the same affine group OUTPUT: the product of the affine group elements ``self`` and ``other`` defined by the composition of the two affine transformations @@ -354,7 +354,7 @@ def __call__(self, v): INPUT: - ``v`` -- a polynomial, a multivariate polynomial, a polyhedron, a - vector, or anything that can be converted into a vector. + vector, or anything that can be converted into a vector OUTPUT: the image of ``v`` under the affine group element diff --git a/src/sage/groups/artin.py b/src/sage/groups/artin.py index a198bccef69..306569e546b 100644 --- a/src/sage/groups/artin.py +++ b/src/sage/groups/artin.py @@ -77,7 +77,7 @@ def exponent_sum(self): """ Return the exponent sum of ``self``. - OUTPUT: an integer + OUTPUT: integer EXAMPLES:: @@ -258,7 +258,7 @@ def _left_normal_form_coxeter(self): Return the left normal form of the element, in the `\Delta` exponent and Coxeter group element form. - OUTPUT: a tuple whose first element is the power of `\Delta`, and the + OUTPUT: tuple whose first element is the power of `\Delta`, and the rest are the Coxeter elements corresponding to the simple factors EXAMPLES:: @@ -596,7 +596,7 @@ def index_set(self): """ Return the index set of ``self``. - OUTPUT: a tuple + OUTPUT: tuple EXAMPLES:: @@ -654,7 +654,7 @@ def _standard_lift_Tietze(self, w): INPUT: - - ``w`` -- an element of the Coxeter group of ``self``. + - ``w`` -- an element of the Coxeter group of ``self`` EXAMPLES:: @@ -672,7 +672,7 @@ def _standard_lift(self, w): INPUT: - - ``w`` -- an element of the Coxeter group of ``self``. + - ``w`` -- an element of the Coxeter group of ``self`` EXAMPLES:: diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index 71550739296..7721d3d602f 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -1523,7 +1523,7 @@ def _left_normal_form_coxeter(self): r""" Return the left normal form of the braid, in permutation form. - OUTPUT: a tuple whose first element is the power of `\Delta`, and the + OUTPUT: tuple whose first element is the power of `\Delta`, and the rest are the permutations corresponding to the simple factors EXAMPLES:: @@ -1626,7 +1626,7 @@ def centralizer(self): def super_summit_set(self): """ - Return a list with the super summit set of the braid + Return a list with the super summit set of the braid. EXAMPLES:: @@ -1864,7 +1864,7 @@ def pure_conjugating_braid(self, other): def ultra_summit_set(self): """ - Return a list with the orbits of the ultra summit set of ``self`` + Return a list with the orbits of the ultra summit set of ``self``. EXAMPLES:: @@ -2411,7 +2411,7 @@ def eps(self, N): INPUT: - - ``N`` -- an integer; the number of colors + - ``N`` -- integer; the number of colors EXAMPLES:: @@ -2637,7 +2637,7 @@ def strands(self): """ Return the number of strands. - OUTPUT: an integer + OUTPUT: integer EXAMPLES:: @@ -2837,10 +2837,10 @@ def _LKB_matrix_(self, braid, variab): INPUT: - - ``braid`` -- tuple of integers. The Tietze list of the - braid. + - ``braid`` -- tuple of integers; the Tietze list of the + braid - - ``variab`` -- string. the names of the variables that will + - ``variab`` -- string. The names of the variables that will appear in the matrix. They must be given as a string, separated by a comma @@ -3452,7 +3452,7 @@ def epimorphisms(self, H): def BraidGroup(n=None, names='s'): """ - Construct a Braid Group + Construct a Braid Group. INPUT: @@ -3596,9 +3596,9 @@ def _act_(self, b, x): INPUT: - - ``b`` -- a braid. + - ``b`` -- a braid - - ``x`` -- a free group element. + - ``x`` -- a free group element OUTPUT: a new braid diff --git a/src/sage/groups/cactus_group.py b/src/sage/groups/cactus_group.py index a4a6fe629b0..c8d6ba7241f 100644 --- a/src/sage/groups/cactus_group.py +++ b/src/sage/groups/cactus_group.py @@ -43,7 +43,7 @@ class CactusGroup(UniqueRepresentation, Group): INPUT: - - ``n`` -- an integer + - ``n`` -- integer EXAMPLES: diff --git a/src/sage/groups/class_function.py b/src/sage/groups/class_function.py index 0af4d5ce646..c7978b4283e 100644 --- a/src/sage/groups/class_function.py +++ b/src/sage/groups/class_function.py @@ -50,10 +50,10 @@ def ClassFunction(group, values): INPUT: - - ``group`` -- a group. + - ``group`` -- a group - - ``values`` -- list/tuple/iterable of numbers. The values of the - class function on the conjugacy classes, in that order. + - ``values`` -- list/tuple/iterable of numbers; the values of the + class function on the conjugacy classes, in that order EXAMPLES:: @@ -168,10 +168,6 @@ def __repr__(self): r""" Return a string representation. - OUTPUT: - - A string. - EXAMPLES:: sage: G = SymmetricGroup(4) @@ -326,7 +322,7 @@ def __sub__(self, other): INPUT: - ``other`` -- a :class:`ClassFunction` of the same group as - ``self``. + ``self`` OUTPUT: a :class:`ClassFunction` @@ -353,9 +349,9 @@ def __mul__(self, other): INPUT: - ``other`` -- either a number or a :class:`ClassFunction` of - the same group as ``self``. A number can be anything that + the same group as ``self``; A number can be anything that can be converted into GAP: integers, rational, and elements - of certain number fields. + of certain number fields OUTPUT: a :class:`ClassFunction` @@ -468,12 +464,9 @@ def symmetric_power(self, n): INPUT: - - ``n`` -- a positive integer. + - ``n`` -- positive integer - OUTPUT: - - The ``n``-th symmetrized power of ``self`` as a - :class:`ClassFunction`. + OUTPUT: the ``n``-th symmetrized power of ``self`` as a :class:`ClassFunction` EXAMPLES:: @@ -495,10 +488,9 @@ def exterior_power(self, n): INPUT: - - ``n`` -- a positive integer. + - ``n`` -- positive integer. - OUTPUT: the ``n``-th antisymmetrized power of ``self`` as a - :class:`ClassFunction` + OUTPUT: the ``n``-th antisymmetrized power of ``self`` as a :class:`ClassFunction` EXAMPLES:: @@ -690,11 +682,9 @@ def restrict(self, H): INPUT: - - ``H`` -- a subgroup of the underlying group of ``self``. + - ``H`` -- a subgroup of the underlying group of ``self`` - OUTPUT: - - A :class:`ClassFunction` of ``H`` defined by restriction. + OUTPUT: a :class:`ClassFunction` of ``H`` defined by restriction EXAMPLES:: @@ -717,7 +707,7 @@ def induct(self, G): INPUT: - - ``G`` -- A supergroup of the underlying group of ``self``. + - ``G`` -- a supergroup of the underlying group of ``self`` OUTPUT: @@ -851,10 +841,6 @@ def _repr_(self): r""" Return a string representation. - OUTPUT: - - A string. - EXAMPLES:: sage: G = SymmetricGroup(4) @@ -941,9 +927,7 @@ def domain(self): r""" Return the domain of ``self``. - OUTPUT: - - The underlying group of the class function. + OUTPUT: the underlying group of the class function EXAMPLES:: @@ -990,8 +974,7 @@ def __add__(self, other): INPUT: - - ``other`` -- a :class:`ClassFunction` of the same group as - ``self``. + - ``other`` -- a :class:`ClassFunction` of the same group as ``self`` OUTPUT: a :class:`ClassFunction` @@ -1015,8 +998,7 @@ def __sub__(self, other): INPUT: - - ``other`` -- a :class:`ClassFunction` of the same group as - ``self``. + - ``other`` -- a :class:`ClassFunction` of the same group as ``self`` OUTPUT: a :class:`ClassFunction` @@ -1158,10 +1140,9 @@ def symmetric_power(self, n): INPUT: - - ``n`` -- a positive integer + - ``n`` -- positive integer - OUTPUT: the ``n``-th symmetrized power of ``self`` as a - :class:`ClassFunction` + OUTPUT: the ``n``-th symmetrized power of ``self`` as a :class:`ClassFunction` EXAMPLES:: @@ -1182,10 +1163,9 @@ def exterior_power(self, n): INPUT: - - ``n`` -- a positive integer + - ``n`` -- positive integer - OUTPUT: the ``n``-th antisymmetrized power of ``self`` as a - :class:`ClassFunction` + OUTPUT: the ``n``-th antisymmetrized power of ``self`` as a :class:`ClassFunction` EXAMPLES:: @@ -1381,7 +1361,7 @@ def restrict(self, H): INPUT: - - ``H`` -- a subgroup of the underlying group of ``self``. + - ``H`` -- a subgroup of the underlying group of ``self`` OUTPUT: a :class:`ClassFunction` of ``H`` defined by restriction @@ -1411,7 +1391,7 @@ def induct(self, G): INPUT: - - ``G`` -- A supergroup of the underlying group of ``self``. + - ``G`` -- a supergroup of the underlying group of ``self`` OUTPUT: diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 17e543687a4..6f357c91b58 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -579,7 +579,7 @@ class CubicBraidGroup(FinitelyPresentedGroup): INPUT: - - ``names`` -- see the corresponding documentation of :class:`BraidGroup_class`. + - ``names`` -- see the corresponding documentation of :class:`BraidGroup_class` - ``cbg_type`` -- (default: ``CubicBraidGroup.type.Coxeter``; see explanation below) enum type :class:`CubicBraidGroup.type` @@ -1072,18 +1072,17 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, This is a local function of :meth:`_create_classical_realization`. - It handles the common part of symplectic and unitary version and creates conversion maps. + It handles the common part of symplectic and unitary version and + creates conversion maps. INPUT: - - ``base_group`` -- The symplectic or unitary groups Sp(m,3) resp. GU(m,2). - - ``proj_group`` -- The corresponding projective group of base_group. - - ``centralizing_matrix`` -- The centralizing matrix according to Assion. - - ``transvec_matrices`` -- List of transvection matrices according to Assion. + - ``base_group`` -- the symplectic or unitary groups Sp(m,3) resp. GU(m,2) + - ``proj_group`` -- the corresponding projective group of base_group + - ``centralizing_matrix`` -- the centralizing matrix according to Assion + - ``transvec_matrices`` -- list of transvection matrices according to Assion - OUTPUT: - - No output, but the function sets the attributes of ``self`` described above. + OUTPUT: no output, but the function sets the attributes of ``self`` described above """ centralizing_element = None @@ -1151,10 +1150,12 @@ def create_sympl_realization(self, m): INPUT: - - ``m`` -- Integer, the dimension of the classical groups vector-space of operation. + - ``m`` -- integer; the dimension of the classical groups + vector-space of operation - The function calculates the centralizing matrix and the transvections as given by Assion - and then uses set_classical_realization to complete the construction. + The function calculates the centralizing matrix and the + transvections as given by Assion and then uses + ``set_classical_realization`` to complete the construction. """ # ----------------------------------------------------------- # getting the invariant bilinear form of the group @@ -1222,10 +1223,12 @@ def create_unitary_realization(self, m): INPUT: - - ``m`` -- Integer, the dimension of the classical groups vector-space of operation. + - ``m`` -- integer; the dimension of the classical groups + vector-space of operation - The function calculates the centralizing_matrix and the transvections as given by Assion - and then uses set_classical_realization to complete the construction. + The function calculates the centralizing_matrix and the + transvections as given by Assion and then uses + ``set_classical_realization`` to complete the construction. """ # --------------------------------------------------------------------- # getting the invariant bilinear form of the group @@ -1459,7 +1462,7 @@ def braid_group(self): @cached_method def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var='t', reduced=False): r""" - Creates an epimorphic image of ``self`` as a matrix group by use of + Create an epimorphic image of ``self`` as a matrix group by use of the burau representation. INPUT: diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index adb166093cd..69bc261a17c 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -296,7 +296,7 @@ def Tietze(self): the letter corresponding to the `i`-th generator of the group. Negative integers represent the inverses of generators. - OUTPUT: a tuple of integers + OUTPUT: tuple of integers EXAMPLES:: @@ -320,11 +320,11 @@ def __call__(self, *values, **kwds): INPUT: - ``*values`` -- a list/tuple/iterable of the same length as - the number of generators. + the number of generators - - ``check=True`` -- boolean keyword (default: - ``True``). Whether to verify that ``values`` satisfy the - relations in the finitely presented group. + - ``check=True`` -- boolean keyword (default: ``True``); whether to + verify that ``values`` satisfy the relations in the finitely + presented group OUTPUT: the product of ``values`` in the order and with exponents specified by ``self`` @@ -553,7 +553,7 @@ def finitely_presented_group(self): def reduce(self, element): """ - Applies the rules in the rewriting system to the element, to obtain + Apply the rules in the rewriting system to the element, to obtain a reduced form. If the rewriting system is confluent, this reduced form is unique @@ -683,7 +683,7 @@ def is_confluent(self): def make_confluent(self): """ - Applies Knuth-Bendix algorithm to try to transform the rewriting + Apply the Knuth-Bendix algorithm to try to transform the rewriting system into a confluent one. Note that this method does not return any object, just changes the @@ -818,9 +818,9 @@ def _repr_(self): def _latex_(self): """ - Return a LaTeX representation + Return a LaTeX representation. - OUTPUT: a string; a valid LaTeX math command sequence + OUTPUT: string; a valid LaTeX math command sequence TESTS:: @@ -887,8 +887,8 @@ def cardinality(self, limit=4096000): INPUT: - - ``limit`` -- integer (default: 4096000). The maximal number - of cosets before the computation is aborted. + - ``limit`` -- integer (default: 4096000); the maximal number + of cosets before the computation is aborted OUTPUT: integer or ``Infinity``; the number of elements in the group @@ -937,8 +937,8 @@ def as_permutation_group(self, limit=4096000): INPUT: - - ``limit`` -- integer (default: 4096000). The maximal number - of cosets before the computation is aborted. + - ``limit`` -- integer (default: 4096000); the maximal number + of cosets before the computation is aborted OUTPUT: @@ -1536,7 +1536,7 @@ def epimorphisms(self, H): INPUT: - - `H` -- Another group + - `H` -- another group EXAMPLES:: @@ -1654,8 +1654,9 @@ def abelian_alexander_matrix(self, ring=QQ, simplified=True): OUTPUT: - ``A`` -- a matrix with coefficients in ``R`` - - ``ideal`` -- an list of generators of an ideal ``I`` of ``R = A.base_ring()`` such that ``R/I`` is - the group algebra of the abelianization of ``self`` + - ``ideal`` -- an list of generators of an ideal ``I`` of + ``R = A.base_ring()`` such that ``R/I`` is the group algebra of the + abelianization of ``self`` EXAMPLES:: @@ -1720,10 +1721,11 @@ def characteristic_varieties(self, ring=QQ, matrix_ideal=None, groebner=False): r""" Return the characteristic varieties of the group ``self``. - There are several definitions of the characteristic varieties of a group `G`, see e.g. [CS1999a]_. Let `\Lambda` be the - group algebra of `G/G'` and `\mathbb{T}` its associated algebraic variety (a torus). Each - element `\xi\in\mathbb{T}` defines a local system of coefficients and the `k` th-characteristic - variety is + There are several definitions of the characteristic varieties of a + group `G`, see e.g. [CS1999a]_. Let `\Lambda` be the group algebra of + `G/G'` and `\mathbb{T}` its associated algebraic variety (a torus). + Each element `\xi\in\mathbb{T}` defines a local system of coefficients + and the `k` th-characteristic variety is .. MATH:: diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py index 256ad33404f..8b07c5af7df 100644 --- a/src/sage/groups/finitely_presented_named.py +++ b/src/sage/groups/finitely_presented_named.py @@ -77,7 +77,7 @@ def CyclicPresentation(n): INPUT: - - ``n`` -- The order of the cyclic presentation to be returned. + - ``n`` -- the order of the cyclic presentation to be returned OUTPUT: the cyclic group of order `n` as finite presentation @@ -110,9 +110,9 @@ def FinitelyGeneratedAbelianPresentation(int_list): INPUT: - - ``int_list`` -- List of integers defining the group to be returned, the defining list + - ``int_list`` -- list of integers defining the group to be returned, the defining list is reduced to the invariants of the input list before generating the corresponding - group. + group OUTPUT: @@ -298,7 +298,7 @@ def DihedralPresentation(n): INPUT: - - ``n`` -- The size of the set that `D_n` is acting on. + - ``n`` -- the size of the set that `D_n` is acting on OUTPUT: Dihedral group of order `2n` @@ -335,7 +335,7 @@ def DiCyclicPresentation(n): INPUT: - ``n`` -- positive integer, 2 or greater, determining the order of - the group (`4n`). + the group (`4n`) OUTPUT: the dicyclic group of order `4n` is defined by the presentation @@ -384,8 +384,8 @@ def SymmetricPresentation(n): INPUT: - - ``n`` -- The size of the underlying set of arbitrary symbols being acted - on by the Symmetric group of order `n!`. + - ``n`` -- the size of the underlying set of arbitrary symbols being acted + on by the Symmetric group of order `n!` OUTPUT: @@ -461,8 +461,8 @@ def AlternatingPresentation(n): INPUT: - - ``n`` -- The size of the underlying set of arbitrary symbols being acted - on by the Alternating group of order `n!/2`. + - ``n`` -- the size of the underlying set of arbitrary symbols being acted + on by the Alternating group of order `n!/2` OUTPUT: diff --git a/src/sage/groups/fqf_orthogonal.py b/src/sage/groups/fqf_orthogonal.py index f810e8dccb3..47dac17281b 100644 --- a/src/sage/groups/fqf_orthogonal.py +++ b/src/sage/groups/fqf_orthogonal.py @@ -124,7 +124,7 @@ class FqfOrthogonalGroup(AbelianGroupAutomorphismGroup_subgroup): INPUT: - - ``T`` -- a non degenerate torsion quadratic module. + - ``T`` -- a non degenerate torsion quadratic module EXAMPLES:: diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index 1da411b3036..09eb12d6a1c 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -80,7 +80,7 @@ def is_FreeGroup(x): INPUT: - - ``x`` -- anything. + - ``x`` -- anything OUTPUT: boolean @@ -107,9 +107,9 @@ def _lexi_gen(zeroes=False): INPUT: - - ``zeroes`` -- Boolean defaulting as ``False``. If ``True``, the + - ``zeroes`` -- boolean (default: ``False``); if ``True``, the integers appended to the output string begin at zero at the - first iteration through the alphabet. + first iteration through the alphabet OUTPUT: @@ -162,11 +162,11 @@ class FreeGroupElement(ElementLibGAP): INPUT: - - ``x`` -- something that determines the group element. Either a + - ``x`` -- something that determines the group element; either a :class:`~sage.libs.gap.element.GapElement` or the Tietze list - (see :meth:`Tietze`) of the group element. + (see :meth:`Tietze`) of the group element - - ``parent`` -- the parent :class:`FreeGroup`. + - ``parent`` -- the parent :class:`FreeGroup` EXAMPLES:: @@ -241,7 +241,7 @@ def __hash__(self): def _latex_(self): r""" - Return a LaTeX representation + Return a LaTeX representation. OUTPUT: a string; a valid LaTeX math command sequence @@ -301,7 +301,7 @@ def Tietze(self): the letter corresponding to the `i`-th generator of the group. Negative integers represent the inverses of generators. - OUTPUT: a tuple of integers + OUTPUT: tuple of integers EXAMPLES:: @@ -519,7 +519,7 @@ def __call__(self, *values): - ``*values`` -- a sequence of values, or a list/tuple/iterable of the same length as the number of - generators of the free group. + generators of the free group OUTPUT: the product of ``values`` in the order and with exponents specified by ``self`` @@ -597,11 +597,11 @@ def FreeGroup(n=None, names='x', index_set=None, abelian=False, **kwds): INPUT: - - ``n`` -- integer or ``None`` (default). The number of - generators. If not specified the ``names`` are counted. + - ``n`` -- integer (default: ``None``); the number of + generators (if not specified the ``names`` are counted) - ``names`` -- string or list/tuple/iterable of strings (default: - ``'x'``). The generator names or name prefix. + ``'x'``); the generator names or name prefix - ``index_set`` -- (optional) an index set for the generators; if specified then the optional keyword ``abelian`` can be used @@ -690,7 +690,7 @@ def wrap_FreeGroup(libgap_free_group): INPUT: - - ``libgap_free_group`` -- a LibGAP free group. + - ``libgap_free_group`` -- a LibGAP free group OUTPUT: a Sage :class:`FreeGroup_class` @@ -743,12 +743,12 @@ def __init__(self, generator_names, libgap_free_group=None): INPUT: - - ``generator_names`` -- a tuple of strings. The names of the - generators. + - ``generator_names`` -- a tuple of strings; the names of the + generators - - ``libgap_free_group`` -- a LibGAP free group or ``None`` - (default). The LibGAP free group to wrap. If ``None``, a - suitable group will be constructed. + - ``libgap_free_group`` -- a LibGAP free group (default: ``None``); + the LibGAP free group to wrap (if ``None``, a suitable group will be + constructed) TESTS:: @@ -786,7 +786,7 @@ def rank(self): Alias for :meth:`ngens`. - OUTPUT: an integer + OUTPUT: integer EXAMPLES:: @@ -907,10 +907,10 @@ def quotient(self, relations, **kwds): INPUT: - - ``relations`` -- A list/tuple/iterable with the elements of - the free group. + - ``relations`` -- a list/tuple/iterable with the elements of + the free group - further named arguments, that are passed to the constructor - of a finitely presented group. + of a finitely presented group OUTPUT: diff --git a/src/sage/groups/galois_group.py b/src/sage/groups/galois_group.py index a7439d18ab3..b3460f32be8 100644 --- a/src/sage/groups/galois_group.py +++ b/src/sage/groups/galois_group.py @@ -25,9 +25,11 @@ def _alg_key(self, algorithm=None, recompute=False): r""" Return a key for use in cached_method calls. - If recompute is false, will cache using ``None`` as the key, so no recomputation will be done. + If recompute is false, will cache using ``None`` as the key, so no + recomputation will be done. - If recompute is true, will cache by algorithm, yielding a recomputation for each different algorithm. + If recompute is true, will cache by algorithm, yielding a recomputation + for each different algorithm. EXAMPLES:: @@ -45,10 +47,11 @@ def _alg_key(self, algorithm=None, recompute=False): class _GMixin: r""" - This class provides some methods for Galois groups to be used for both permutation groups - and abelian groups, subgroups and full Galois groups. + This class provides some methods for Galois groups to be used for both + permutation groups and abelian groups, subgroups and full Galois groups. - It is just intended to provide common functionality between various different Galois group classes. + It is just intended to provide common functionality between various + different Galois group classes. """ @lazy_attribute def _default_algorithm(self): @@ -90,7 +93,7 @@ def _gcdata(self): def _get_algorithm(self, algorithm): r""" - Allows overriding the default algorithm specified at object creation. + Allow overriding the default algorithm specified at object creation. EXAMPLES:: @@ -177,7 +180,7 @@ def _field(self): def _repr_(self): """ - String representation of this Galois group + String representation of this Galois group. EXAMPLES:: @@ -309,13 +312,14 @@ def fixed_field(self, name=None, polred=None, threshold=None): INPUT: - - ``name`` -- a variable name for the new field. + - ``name`` -- a variable name for the new field - ``polred`` -- whether to optimize the generator of the newly created field - for a simpler polynomial, using pari's polredbest. - Defaults to ``True`` when the degree of the fixed field is at most 8. + for a simpler polynomial, using pari's polredbest; + defaults to ``True`` when the degree of the fixed field is at most 8 - - ``threshold`` -- positive number; polred only performed if the cost is at most this threshold + - ``threshold`` -- positive number; polred only performed if the cost + is at most this threshold EXAMPLES:: @@ -377,7 +381,7 @@ def is_galois(self): @lazy_attribute def _gcdata(self): r""" - Return the Galois closure (ie, the finite field itself) together with the identity + Return the Galois closure (ie, the finite field itself) together with the identity. EXAMPLES:: diff --git a/src/sage/groups/galois_group_perm.py b/src/sage/groups/galois_group_perm.py index 7a640bcfe29..3b81e0d5908 100644 --- a/src/sage/groups/galois_group_perm.py +++ b/src/sage/groups/galois_group_perm.py @@ -17,11 +17,13 @@ class GaloisGroup_perm(_GaloisMixin, PermutationGroup_generic): - ``field`` -- a field, separable over its base - - ``names`` -- a string or tuple of length 1, giving a variable name for the splitting field + - ``names`` -- a string or tuple of length 1, giving a variable name for + the splitting field - - ``gc_numbering`` -- boolean, whether to express permutations in terms of the - roots of the defining polynomial of the splitting field (versus the defining polynomial - of the original extension). The default value may vary based on the type of field. + - ``gc_numbering`` -- boolean, whether to express permutations in terms of + the roots of the defining polynomial of the splitting field (versus the + defining polynomial of the original extension); the default value may + vary based on the type of field """ @abstract_method def transitive_number(self, algorithm=None, recompute=False): diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index 5a540088d2c..86aebc74709 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -534,7 +534,7 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No - ``hash_function`` -- having an efficient hash function is critical for this algorithm (see examples) - OUTPUT: an integer `n` such that `a = base^n` (or `a = n*base`) + OUTPUT: integer `n` such that `a = base^n` (or `a = n*base`) ALGORITHM: Pollard rho for discrete logarithm, adapted from the article of Edlyn Teske, 'A space efficient algorithm for group @@ -600,7 +600,6 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No AUTHOR: - Yann Laigle-Chapuy (2009-09-05) - """ from sage.rings.integer import Integer from sage.rings.finite_rings.integer_mod_ring import IntegerModRing @@ -701,7 +700,8 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i - ``identity`` -- the group's identity - ``inverse()`` - function of 1 argument ``x``, returning inverse of ``x`` - ``op()`` - function of 2 arguments ``x``, ``y``, returning ``x*y`` in the group - - ``algorithm`` -- string denoting what algorithm to use for prime-order logarithms: ``'bsgs'``, ``'rho'``, ``'lambda'`` + - ``algorithm`` -- string denoting what algorithm to use for prime-order + logarithms: ``'bsgs'``, ``'rho'``, ``'lambda'`` ``a`` and ``base`` must be elements of some group with identity given by ``identity``, inverse of ``x`` by ``inverse(x)``, and group @@ -719,7 +719,7 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i If no such `n` exists, this function raises a :class:`ValueError` exception. - .. warning:: + .. WARNING:: If ``x`` has a ``log`` method, it is likely to be vastly faster than using this function. E.g., if ``x`` is an integer modulo @@ -993,7 +993,7 @@ def discrete_log_lambda(a, base, bounds, operation='*', identity=None, inverse=N - op() -- function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group - hash_function -- having an efficient hash function is critical for this algorithm - OUTPUT: an integer `n` such that `a=base^n` (or `a=n*base`) + OUTPUT: integer `n` such that `a=base^n` (or `a=n*base`) ALGORITHM: Pollard Lambda, if bounds are (lb,ub) it has time complexity O(sqrt(ub-lb)) and space complexity O(log(ub-lb)) @@ -1200,19 +1200,19 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True, INPUT: - - ``P`` -- a Sage object which is a group element; + - ``P`` -- a Sage object which is a group element - ``m`` -- a Sage integer which is a multiple of the order of ``P``, - i.e. we require that ``m*P=0`` (or ``P**m=1``); + i.e. we require that ``m*P=0`` (or ``P**m=1``) - ``check`` -- a Boolean (default: ``True``), indicating whether we check if ``m`` - really is a multiple of the order; + really is a multiple of the order - ``factorization`` -- the factorization of ``m``, or ``None`` in which - case this function will need to factor ``m``; + case this function will need to factor ``m`` - ``plist`` -- a list of the prime factors of ``m``, or ``None``. Kept for compatibility only, - prefer the use of ``factorization``; - - ``operation`` -- string: ``'+'`` (default), ``'*'`` or ``None``; - - ``identity`` -- the identity element of the group; - - ``inverse()`` -- function of 1 argument ``x``, returning inverse of ``x``; - - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group. + prefer the use of ``factorization`` + - ``operation`` -- string: ``'+'`` (default), ``'*'`` or ``None`` + - ``identity`` -- the identity element of the group + - ``inverse()`` -- function of 1 argument ``x``, returning inverse of ``x`` + - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group .. NOTE:: @@ -1298,7 +1298,7 @@ def _multiple(A, B): # we use an internal recursive function to avoid unnecessary computations. def _order_from_multiple_helper(Q, L, S): """ - internal use, to minimize the number of group operations. + For internal use, to minimize the number of group operations. """ l = len(L) if l == 1: @@ -1349,10 +1349,10 @@ def order_from_bounds(P, bounds, d=None, operation='+', - ``P`` -- a Sage object which is a group element - ``bounds`` -- a 2-tuple ``(lb,ub)`` such that ``m*P=0`` (or - ``P**m=1``) for some ``m`` with ``lb<=m<=ub``. + ``P**m=1``) for some ``m`` with ``lb<=m<=ub`` - ``d`` -- (optional) a positive integer; only ``m`` which are - multiples of this will be considered. + multiples of this will be considered - ``operation`` -- string: ``'+'`` (default ) or ``'*'`` or other. If other, the following must be supplied: @@ -1626,10 +1626,10 @@ def structure_description(G, latex=False): INPUT: - - ``latex`` -- a boolean (default: ``False``). If ``True``, return a - LaTeX formatted string. + - ``latex`` -- a boolean (default: ``False``); if ``True``, return a + LaTeX formatted string - OUTPUT: a string + OUTPUT: string .. WARNING:: diff --git a/src/sage/groups/group.pyx b/src/sage/groups/group.pyx index 2f1a6cc1846..32fe6d13941 100644 --- a/src/sage/groups/group.pyx +++ b/src/sage/groups/group.pyx @@ -27,7 +27,7 @@ def is_Group(x): INPUT: - - ``x`` -- anything. + - ``x`` -- anything OUTPUT: boolean @@ -48,7 +48,7 @@ def is_Group(x): cdef class Group(Parent): """ - Base class for all groups + Base class for all groups. TESTS:: @@ -76,7 +76,7 @@ cdef class Group(Parent): """ def __init__(self, base=None, category=None): """ - The Python constructor + The Python constructor. TESTS:: diff --git a/src/sage/groups/group_exp.py b/src/sage/groups/group_exp.py index 58d9ba4b512..ccf6d62f147 100644 --- a/src/sage/groups/group_exp.py +++ b/src/sage/groups/group_exp.py @@ -140,7 +140,7 @@ def _apply_functor_to_morphism(self, f): INPUT: - - A homomorphism `f` of commutative additive groups. + - A homomorphism `f` of commutative additive groups OUTPUT: the above homomorphism, but between the corresponding multiplicative groups @@ -180,7 +180,7 @@ class GroupExpElement(ElementWrapper, MultiplicativeGroupElement): - ``self`` -- the exponentiated group element being created - ``parent`` -- the exponential group (parent of ``self``) - - ``x`` -- the commutative additive group element being wrapped to form ``self``. + - ``x`` -- the commutative additive group element being wrapped to form ``self`` EXAMPLES:: diff --git a/src/sage/groups/group_semidirect_product.py b/src/sage/groups/group_semidirect_product.py index 0c8ba8a96aa..7adc1868f8d 100644 --- a/src/sage/groups/group_semidirect_product.py +++ b/src/sage/groups/group_semidirect_product.py @@ -136,7 +136,8 @@ def to_opposite(self): class GroupSemidirectProduct(CartesianProduct): r""" - Return the semidirect product of the groups ``G`` and ``H`` using the homomorphism ``twist``. + Return the semidirect product of the groups ``G`` and ``H`` using the + homomorphism ``twist``. INPUT: diff --git a/src/sage/groups/indexed_free_group.py b/src/sage/groups/indexed_free_group.py index 79be1df663d..02a4838d77c 100644 --- a/src/sage/groups/indexed_free_group.py +++ b/src/sage/groups/indexed_free_group.py @@ -24,7 +24,8 @@ from sage.categories.poor_man_map import PoorManMap from sage.groups.group import Group, AbelianGroup from sage.monoids.indexed_free_monoid import (IndexedMonoid, - IndexedFreeMonoidElement, IndexedFreeAbelianMonoidElement) + IndexedFreeMonoidElement, + IndexedFreeAbelianMonoidElement) from sage.misc.cachefunc import cached_method import sage.data_structures.blas_dict as blas from sage.rings.integer import Integer @@ -165,7 +166,7 @@ def __init__(self, indices, prefix, category=None, **kwds): def _repr_(self): """ - Return a string representation of ``self`` + Return a string representation of ``self``. TESTS:: diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index aeb100f2ca2..931d22ccdc5 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -196,7 +196,7 @@ def is_finite(self): def cardinality(self): """ - Implements :meth:`EnumeratedSets.ParentMethods.cardinality`. + Implement :meth:`EnumeratedSets.ParentMethods.cardinality`. EXAMPLES:: @@ -329,8 +329,8 @@ def class_function(self, values): INPUT: - - ``values`` -- list/tuple/iterable of numbers. The values of the - class function on the conjugacy classes, in that order. + - ``values`` -- list/tuple/iterable of numbers; the values of the + class function on the conjugacy classes, in that order EXAMPLES:: @@ -647,7 +647,7 @@ def irreducible_characters(self): """ Return the irreducible characters of the group. - OUTPUT: a tuple containing all irreducible characters + OUTPUT: tuple containing all irreducible characters EXAMPLES:: @@ -853,7 +853,7 @@ def list(self): """ List all elements of this group. - OUTPUT: a tuple containing all group elements in a random but fixed + OUTPUT: tuple containing all group elements in a random but fixed order EXAMPLES:: @@ -926,7 +926,7 @@ def is_isomorphic(self, H): INPUT: - - ``H`` -- a group. + - ``H`` -- a group OUTPUT: boolean diff --git a/src/sage/groups/libgap_morphism.py b/src/sage/groups/libgap_morphism.py index 5b780ceb922..ec48dda3776 100644 --- a/src/sage/groups/libgap_morphism.py +++ b/src/sage/groups/libgap_morphism.py @@ -46,7 +46,8 @@ class GroupMorphism_libgap(Morphism): INPUT: - ``homset`` -- the parent - - ``gap_hom`` -- a :class:`sage.libs.gap.element.GapElement` consisting of a group homomorphism + - ``gap_hom`` -- a :class:`sage.libs.gap.element.GapElement` consisting of + a group homomorphism - ``check`` -- (default: ``True``) check if the ``gap_hom`` is a group homomorphism; this can be expensive @@ -283,7 +284,7 @@ def __init__(self, homset, gap_hom, check=True): def __reduce__(self): r""" - Implements pickling. + Implement pickling. We have to work around the fact that GAP does not provide pickling. diff --git a/src/sage/groups/libgap_wrapper.pyx b/src/sage/groups/libgap_wrapper.pyx index 0834a304c66..abaf17f11d9 100644 --- a/src/sage/groups/libgap_wrapper.pyx +++ b/src/sage/groups/libgap_wrapper.pyx @@ -86,11 +86,11 @@ class ParentLibGAP(SageObject): INPUT: - ``libgap_parent`` -- the libgap element that is the parent in - GAP. + GAP - ``ambient`` -- A derived class of :class:`ParentLibGAP` or - ``None`` (default). The ambient class if ``libgap_parent`` has - been defined as a subgroup. + ``None`` (default); the ambient class if ``libgap_parent`` has + been defined as a subgroup EXAMPLES:: @@ -300,7 +300,7 @@ class ParentLibGAP(SageObject): """ Return the number of generators of ``self``. - OUTPUT: an integer + OUTPUT: integer EXAMPLES:: @@ -392,7 +392,7 @@ class ParentLibGAP(SageObject): """ Return the `i`-th generator of ``self``. - .. warning:: + .. WARNING:: Indexing starts at `0` as usual in Sage/Python. Not as in GAP, where indexing starts at `1`. @@ -400,7 +400,7 @@ class ParentLibGAP(SageObject): INPUT: - ``i`` -- integer between `0` (inclusive) and :meth:`ngens` - (exclusive). The index of the generator. + (exclusive); The index of the generator OUTPUT: the `i`-th generator of the group @@ -453,7 +453,7 @@ class ParentLibGAP(SageObject): cdef class ElementLibGAP(MultiplicativeGroupElement): """ - A class for LibGAP-based Sage group elements + A class for LibGAP-based Sage group elements. INPUT: @@ -593,7 +593,7 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): def _latex_(self): r""" - Return a LaTeX representation + Return a LaTeX representation. OUTPUT: a string; a valid LaTeX math command sequence @@ -613,7 +613,7 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): cpdef _mul_(left, right): """ - Multiplication of group elements + Multiplication of group elements. TESTS:: diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index 3ad8719a5dd..1df22e6c3a6 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -211,10 +211,10 @@ def MatrixGroup(*gens, **kwds): INPUT: - ``*gens`` -- matrices, or a single list/tuple/iterable of - matrices, or a matrix group. + matrices, or a matrix group - - ``check`` -- boolean keyword argument (optional, default: - ``True``). Whether to check that each matrix is invertible. + - ``check`` -- boolean keyword argument (default: ``True``); + whether to check that each matrix is invertible EXAMPLES:: @@ -410,7 +410,7 @@ def gens(self) -> tuple: def gen(self, i): """ - Return the `i`-th generator + Return the `i`-th generator. OUTPUT: the `i`-th generator of the group @@ -430,9 +430,9 @@ def gen(self, i): def ngens(self): """ - Return the number of generators + Return the number of generators. - OUTPUT: an integer; the number of generators + OUTPUT: integer; the number of generators EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/finitely_generated_gap.py b/src/sage/groups/matrix_gps/finitely_generated_gap.py index b1623f543f9..70c45d59162 100644 --- a/src/sage/groups/matrix_gps/finitely_generated_gap.py +++ b/src/sage/groups/matrix_gps/finitely_generated_gap.py @@ -85,13 +85,13 @@ def as_permutation_group(self, algorithm=None, seed=None): INPUT: - - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter + - ``algorithm`` -- ``None`` or ``'smaller'``; in the latter case, try harder to find a permutation representation of - small degree. + small degree - ``seed`` -- ``None`` or an integer specifying the seed - to fix results depending on pseudo-random-numbers. Here + to fix results depending on pseudo-random-numbers; here it makes sense to be used with respect to the ``'smaller'`` - option, since GAP produces random output in that context. + option, since GAP produces random output in that context OUTPUT: diff --git a/src/sage/groups/matrix_gps/group_element.pyx b/src/sage/groups/matrix_gps/group_element.pyx index 2e6428fc714..99c21b2589a 100644 --- a/src/sage/groups/matrix_gps/group_element.pyx +++ b/src/sage/groups/matrix_gps/group_element.pyx @@ -91,11 +91,11 @@ except ImportError: cpdef is_MatrixGroupElement(x): """ - Test whether ``x`` is a matrix group element + Test whether ``x`` is a matrix group element. INPUT: - - ``x`` -- anything. + - ``x`` -- anything OUTPUT: boolean @@ -370,7 +370,7 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): def __invert__(self): """ - Return the inverse group element + Return the inverse group element. OUTPUT: a matrix group element diff --git a/src/sage/groups/matrix_gps/group_element_gap.pyx b/src/sage/groups/matrix_gps/group_element_gap.pyx index 2f7eb82cb8d..2b363f7c303 100644 --- a/src/sage/groups/matrix_gps/group_element_gap.pyx +++ b/src/sage/groups/matrix_gps/group_element_gap.pyx @@ -312,8 +312,8 @@ cdef class MatrixGroupElement_gap(ElementLibGAP): - ``gens`` -- a list/tuple/iterable of elements (or objects that can be converted to group elements), or ``None`` - (default). By default, the generators of the parent group - are used. + (default); by default, the generators of the parent group + are used OUTPUT: diff --git a/src/sage/groups/matrix_gps/isometries.py b/src/sage/groups/matrix_gps/isometries.py index 424e5a0edf0..baf0925d706 100644 --- a/src/sage/groups/matrix_gps/isometries.py +++ b/src/sage/groups/matrix_gps/isometries.py @@ -46,8 +46,9 @@ class GroupOfIsometries(FinitelyGeneratedMatrixGroup_gap): r""" A base class for Orthogonal matrix groups with a gap backend. - Main difference to :class:`~sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_gap` is that we can - specify generators and a bilinear form. Following gap the group action is from the right. + Main difference to :class:`~sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_gap` + is that we can specify generators and a bilinear form. Following gap the group action is + from the right. INPUT: @@ -59,10 +60,10 @@ class GroupOfIsometries(FinitelyGeneratedMatrixGroup_gap): - ``check`` -- bool (default: ``True``) check if the generators preserve the bilinear form - ``invariant_submodule`` -- a submodule preserved by the group action - (default: ``None``) registers an action on this submodule. + (default: ``None``) registers an action on this submodule - ``invariant_quotient_module`` -- a quotient module preserved by the group action (default: ``None``) - registers an action on this quotient module. + registers an action on this quotient module EXAMPLES:: @@ -134,7 +135,7 @@ def _repr_(self): r""" Return the string representation of this matrix group. - OUTPUT: a string + OUTPUT: string EXAMPLES:: @@ -159,7 +160,7 @@ def _repr_(self): def __reduce__(self): r""" - Implements pickling. + Implement pickling. EXAMPLES:: @@ -358,7 +359,7 @@ class GroupActionOnQuotientModule(Action): - ``MatrixGroup`` -- the group acting :class:`GroupOfIsometries` - ``submodule`` -- an invariant quotient module - - ``is_left`` -- bool (default: ``False``) + - ``is_left`` -- boolean (default: ``False``) EXAMPLES:: @@ -376,7 +377,7 @@ class GroupActionOnQuotientModule(Action): """ def __init__(self, MatrixGroup, quotient_module, is_left=False): r""" - Initialize the action + Initialize the action. TESTS:: diff --git a/src/sage/groups/matrix_gps/linear.py b/src/sage/groups/matrix_gps/linear.py index 759faf2db18..e8c7ddd08a3 100644 --- a/src/sage/groups/matrix_gps/linear.py +++ b/src/sage/groups/matrix_gps/linear.py @@ -207,13 +207,13 @@ def SL(n, R, var='a'): INPUT: - - ``n`` -- a positive integer. + - ``n`` -- positive integer - - ``R`` -- ring or an integer. If an integer is specified, the - corresponding finite field is used. + - ``R`` -- ring or integer; if an integer is specified, the + corresponding finite field is used - ``var`` -- variable used to represent generator of the finite - field, if needed. + field, if needed EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index e7ad5183e45..709a88a6d8e 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -126,10 +126,10 @@ def _check_matrix(self, x, *args): INPUT: - ``x`` -- a Sage matrix in the correct matrix space (degree - and base ring). + and base ring) - ``*args`` -- optional other representations of ``x``, - depending on the group implementation. Ignored by default. + depending on the group implementation. Ignored by default OUTPUT: a :class:`TypeError` must be raised if ``x`` is invalid @@ -184,8 +184,8 @@ def subgroup(self, generators, check=True): INPUT: - ``generators`` -- a list/tuple/iterable of group elements of ``self`` - - ``check`` -- boolean (optional, default: ``True``). Whether to check - that each matrix is invertible. + - ``check`` -- boolean (default: ``True``); whether to check that each + matrix is invertible OUTPUT: the subgroup generated by ``generators`` as an instance of :class:`FinitelyGeneratedMatrixGroup_gap` @@ -345,7 +345,8 @@ def sign_representation(self, base_ring=None, side="twosided"): .. WARNING:: - Assumes ``self`` is a matrix group over a field which has embedding over real numbers. + Assumes ``self`` is a matrix group over a field which has + embedding over real numbers. INPUT: @@ -390,17 +391,17 @@ class MatrixGroup_generic(MatrixGroup_base): def __init__(self, degree, base_ring, category=None): """ - Base class for matrix groups over generic base rings + Base class for matrix groups over generic base rings. You should not use this class directly. Instead, use one of the more specialized derived classes. INPUT: - - ``degree`` -- integer. The degree (matrix size) of the - matrix group. + - ``degree`` -- integer; the degree (matrix size) of the + matrix group - - ``base_ring`` -- ring. The base ring of the matrices. + - ``base_ring`` -- ring; the base ring of the matrices TESTS:: @@ -425,7 +426,7 @@ def degree(self): """ Return the degree of this matrix group. - OUTPUT: an integer; the size (number of rows equals number of columns) + OUTPUT: integer; the size (number of rows equals number of columns) of the matrices EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/matrix_group_gap.py b/src/sage/groups/matrix_gps/matrix_group_gap.py index f413c87bdde..d7de4c75f6e 100644 --- a/src/sage/groups/matrix_gps/matrix_group_gap.py +++ b/src/sage/groups/matrix_gps/matrix_group_gap.py @@ -37,16 +37,16 @@ def __init__(self, degree, base_ring, libgap_group, ambient=None, category=None) INPUT: - - ``degree`` -- integer. The degree (matrix size) of the - matrix group. + - ``degree`` -- integer; the degree (matrix size) of the + matrix group - - ``base_ring`` -- ring. The base ring of the matrices. + - ``base_ring`` -- ring; the base ring of the matrices - - ``libgap_group`` -- the defining libgap group. + - ``libgap_group`` -- the defining libgap group - - ``ambient`` -- A derived class of :class:`ParentLibGAP` or - ``None`` (default). The ambient class if ``libgap_group`` - has been defined as a subgroup. + - ``ambient`` -- a derived class of :class:`ParentLibGAP` or + ``None`` (default); the ambient class if ``libgap_group`` + has been defined as a subgroup TESTS: @@ -197,9 +197,9 @@ def _check_matrix(self, x_sage, x_gap): INPUT: - ``x_sage`` -- a Sage matrix in the correct matrix space (degree - and base ring). + and base ring) - - ``x_gap`` -- the corresponding LibGAP matrix. + - ``x_gap`` -- the corresponding LibGAP matrix OUTPUT: a :class:`TypeError` must be raised if ``x`` is invalid @@ -229,8 +229,8 @@ def subgroup(self, generators, check=True): INPUT: - ``generators`` -- a list/tuple/iterable of group elements of ``self`` - - ``check`` -- boolean (optional, default: ``True``). Whether to check - that each matrix is invertible. + - ``check`` -- boolean (default: ``True``). Whether to check that each + matrix is invertible OUTPUT: The subgroup generated by ``generators`` as an instance of :class:`FinitelyGeneratedMatrixGroup_gap` diff --git a/src/sage/groups/matrix_gps/named_group.py b/src/sage/groups/matrix_gps/named_group.py index 1aae7019e3c..142ea68ddfb 100644 --- a/src/sage/groups/matrix_gps/named_group.py +++ b/src/sage/groups/matrix_gps/named_group.py @@ -188,7 +188,7 @@ class NamedMatrixGroup_generic(CachedRepresentation, MatrixGroup_generic): def __init__(self, degree, base_ring, special, sage_name, latex_string, category=None, invariant_form=None): """ - Base class for "named" matrix groups + Base class for "named" matrix groups. INPUT: @@ -260,7 +260,7 @@ def _latex_(self): """ Return a LaTeX representation. - OUTPUT: a string + OUTPUT: string EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/named_group_gap.py b/src/sage/groups/matrix_gps/named_group_gap.py index b8b1f54722c..699e351f06d 100644 --- a/src/sage/groups/matrix_gps/named_group_gap.py +++ b/src/sage/groups/matrix_gps/named_group_gap.py @@ -23,22 +23,22 @@ class NamedMatrixGroup_gap(NamedMatrixGroup_generic, MatrixGroup_gap): def __init__(self, degree, base_ring, special, sage_name, latex_string, gap_command_string, category=None): """ - Base class for "named" matrix groups using LibGAP + Base class for "named" matrix groups using LibGAP. INPUT: - - ``degree`` -- integer. The degree (number of rows/columns of - matrices). + - ``degree`` -- integer; the degree (number of rows/columns of + matrices) - - ``base_ring`` -- ring. The base ring of the matrices. + - ``base_ring`` -- ring; the base ring of the matrices - - ``special`` -- boolean. Whether the matrix group is special, - that is, elements have determinant one. + - ``special`` -- boolean; whether the matrix group is special, + that is, elements have determinant one - - ``latex_string`` -- string. The latex representation. + - ``latex_string`` -- string; the latex representation - - ``gap_command_string`` -- string. The GAP command to construct - the matrix group. + - ``gap_command_string`` -- string; the GAP command to construct + the matrix group EXAMPLES:: diff --git a/src/sage/groups/matrix_gps/orthogonal.py b/src/sage/groups/matrix_gps/orthogonal.py index ab1b770e4cf..adfa3248204 100644 --- a/src/sage/groups/matrix_gps/orthogonal.py +++ b/src/sage/groups/matrix_gps/orthogonal.py @@ -21,7 +21,7 @@ of `SO(e,d,q)` in `GO(e,d,q)` is `2` if `q` is odd, but `SO(e,d,q) = GO(e,d,q)` if `q` is even.) -.. warning:: +.. WARNING:: GAP and Sage use different notations: @@ -107,10 +107,10 @@ def normalize_args_e(degree, ring, e): INPUT: - - ``degree`` -- integer. The degree of the affine group, that is, - the dimension of the affine space the group is acting on. + - ``degree`` -- integer; the degree of the affine group, that is, + the dimension of the affine space the group is acting on - - ``ring`` -- a ring. The base ring of the affine space. + - ``ring`` -- a ring; the base ring of the affine space - ``e`` -- integer, one of `+1`, `0`, `-1`. Only relevant for finite fields and if the degree is even. A parameter that diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py index 37a9cb826ee..e706abcfda7 100644 --- a/src/sage/groups/matrix_gps/unitary.py +++ b/src/sage/groups/matrix_gps/unitary.py @@ -68,7 +68,7 @@ def finite_field_sqrt(ring): """ Helper function. - OUTPUT: an integer `q` such that ``ring`` is the finite field with `q^2` elements + OUTPUT: integer `q` such that ``ring`` is the finite field with `q^2` elements EXAMPLES:: diff --git a/src/sage/groups/misc_gps/argument_groups.py b/src/sage/groups/misc_gps/argument_groups.py index 5cf9ead8c7d..edbdb7b7bad 100644 --- a/src/sage/groups/misc_gps/argument_groups.py +++ b/src/sage/groups/misc_gps/argument_groups.py @@ -281,7 +281,7 @@ def _act_on_(self, other, is_left): def __abs__(self): r""" - Return the absolute value of this argument which equals `1` + Return the absolute value of this argument which equals `1`. TESTS:: @@ -782,7 +782,7 @@ def _create_element_in_extension_(self, exponent): INPUT: - - ``exponent`` -- the element data. + - ``exponent`` -- the element data OUTPUT: an element @@ -812,7 +812,7 @@ def _coerce_map_from_(self, R): INPUT: - - ``R`` -- a parent. + - ``R`` -- a parent OUTPUT: boolean @@ -1321,7 +1321,7 @@ def _create_element_in_extension_(self, element): INPUT: - - ``element`` -- the element data. + - ``element`` -- the element data OUTPUT: an element @@ -1353,7 +1353,7 @@ def _coerce_map_from_(self, R): INPUT: - - ``R`` -- a parent. + - ``R`` -- a parent OUTPUT: boolean diff --git a/src/sage/groups/old.pyx b/src/sage/groups/old.pyx index 08df0405ffa..564dbd75c23 100644 --- a/src/sage/groups/old.pyx +++ b/src/sage/groups/old.pyx @@ -26,7 +26,7 @@ from sage.misc.superseded import deprecation cdef class Group(sage.structure.parent.Parent): """ - Generic group class + Generic group class. """ def __init__(self, category=None): """ @@ -165,8 +165,7 @@ cdef class Group(sage.structure.parent.Parent): def quotient(self, H, **kwds): """ - Return the quotient of this group by the normal subgroup - `H`. + Return the quotient of this group by the normal subgroup `H`. EXAMPLES:: diff --git a/src/sage/groups/pari_group.py b/src/sage/groups/pari_group.py index 62dc75cb821..fb460e5b902 100644 --- a/src/sage/groups/pari_group.py +++ b/src/sage/groups/pari_group.py @@ -29,7 +29,7 @@ def __init__(self, x, degree): def __repr__(self): """ - String representation of this group + String representation of this group. EXAMPLES:: @@ -159,7 +159,7 @@ def order(self): def permutation_group(self): """ - Return the corresponding GAP transitive group + Return the corresponding GAP transitive group. EXAMPLES:: diff --git a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx index e7a3e8c55f8..6f4d9b2b430 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx +++ b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx @@ -42,7 +42,7 @@ from sage.arith.misc import is_prime as n_is_prime cdef inline OrbitPartition *OP_new(int n) noexcept: """ - Allocate and return a pointer to a new OrbitPartition of degree n. Returns a + Allocate and return a pointer to a new OrbitPartition of degree n. Return a null pointer in the case of an allocation failure. """ cdef OrbitPartition *OP = \ @@ -181,7 +181,7 @@ def OP_represent(int n, merges, perm): cdef inline PartitionStack *PS_new(int n, bint unit_partition) noexcept: """ - Allocate and return a pointer to a new PartitionStack of degree n. Returns a + Allocate and return a pointer to a new PartitionStack of degree n. Return a null pointer in the case of an allocation failure. """ cdef PartitionStack *PS = \ @@ -213,7 +213,7 @@ cdef void PS_unit_partition(PartitionStack *PS) noexcept: cdef inline PartitionStack *PS_copy(PartitionStack *PS) noexcept: """ - Allocate and return a pointer to a copy of PartitionStack PS. Returns a null + Allocate and return a pointer to a copy of PartitionStack PS. Return a null pointer in the case of an allocation failure. """ cdef int n = PS.degree @@ -237,7 +237,7 @@ cdef inline void PS_dealloc(PartitionStack *PS) noexcept: cdef PartitionStack *PS_from_list(list L) noexcept: """ - Allocate and return a pointer to a PartitionStack representing L. Returns a + Allocate and return a pointer to a PartitionStack representing L. Return a null pointer in the case of an allocation failure. """ cdef int cell, i, num_cells = len(L), cur_start = 0, cur_len, n = 0 @@ -286,7 +286,7 @@ cdef int PS_first_smallest(PartitionStack *PS, bitset_t b, int *second_pos=NULL) """ Find the first occurrence of the smallest cell of size greater than one, which is admissible (checked by the function ``test_allowance``). - Its entries are stored to b and its minimum element is returned. + Its entries are stored to `b` and its minimum element is returned. """ cdef int i = 0, j = 0, location = 0, n = PS.degree bitset_zero(b) @@ -383,7 +383,7 @@ cdef int PS_find_element(PartitionStack *PS, bitset_t b, int x) except -1: cdef list PS_singletons(PartitionStack * part): """ - Return the list of all singletons in the PartitionStack. + Return the list of all singletons in the ``PartitionStack``. """ cdef list l = [] cdef int i @@ -552,7 +552,7 @@ cdef enum: cdef StabilizerChain *SC_new(int n, bint init_gens=True) noexcept: """ - Allocate and return a pointer to a new StabilizerChain of degree n. Returns + Allocate and return a pointer to a new StabilizerChain of degree n. Return a null pointer in the case of an allocation failure. """ cdef int i @@ -624,7 +624,7 @@ cdef inline int SC_realloc_gens(StabilizerChain *SC, int level, int size) noexce """ Reallocate generator array at level `level` to size `size`. - Returns 1 in case of an allocation failure. + Return 1 in case of an allocation failure. """ cdef int *temp cdef int n = SC.degree @@ -661,7 +661,7 @@ cdef StabilizerChain *SC_symmetric_group(int n) noexcept: """ Return a stabilizer chain for the symmetric group on {0, 1, ..., n-1}. - Returns NULL in the case of an allocation failure. + Return ``NULL`` in the case of an allocation failure. """ cdef int i, j, b cdef StabilizerChain *SC = SC_new(n, False) @@ -702,7 +702,7 @@ cdef StabilizerChain *SC_alternating_group(int n) noexcept: """ Return a stabilizer chain for the alternating group on {0, 1, ..., n-1}. - Returns NULL in the case of an allocation failure. + Return ``NULL`` in the case of an allocation failure. """ cdef int i, j, b cdef StabilizerChain *SC = SC_new(n, False) @@ -747,7 +747,7 @@ cdef int SC_realloc_bitsets(StabilizerChain *SC, unsigned long size) noexcept: If size is larger than current allocation, double the size of the bitsets until it is not. - Returns 1 in case of an allocation failure. + Return 1 in case of an allocation failure. """ cdef unsigned long size_old = SC.gen_used.size if size <= size_old: @@ -780,7 +780,7 @@ cdef StabilizerChain *SC_copy(StabilizerChain *SC, int level) noexcept: """ Creates a copy of the first `level` levels of SC. Must have 0 < level. - Returns a null pointer in case of allocation failure. + Return a null pointer in case of allocation failure. """ cdef int i, n = SC.degree cdef StabilizerChain *SCC = SC_new(n, False) @@ -847,7 +847,7 @@ cdef StabilizerChain *SC_new_base(StabilizerChain *SC, int *base, int base_len) Use SC_cleanup to remove redundant base points. - Returns a null pointer in case of an allocation failure. + Return a null pointer in case of an allocation failure. """ cdef StabilizerChain *NEW = SC_new(SC.degree) if NEW is NULL: @@ -908,7 +908,7 @@ cdef StabilizerChain *SC_insert_base_point(StabilizerChain *SC, int level, int p Use SC_cleanup to remove redundant base points. - Returns a null pointer in case of an allocation failure. + Return a null pointer in case of an allocation failure. """ cdef int i, b, n = SC.degree cdef StabilizerChain *NEW @@ -994,7 +994,7 @@ cdef int SC_sift(StabilizerChain *SC, int level, int x, int *gens, int num_gens, num_gens - how many of these there are new_gens - space of size at least num_gens*n for the sifted perms to go - Returns 1 in case of an allocation failure. + Return 1 in case of an allocation failure. """ cdef int n = SC.degree if num_gens == 0: @@ -1619,10 +1619,11 @@ cdef int sort_by_function(PartitionStack *PS, int start, int *degrees) noexcept: A simple counting sort, given the degrees of vertices to a certain cell. INPUT: - PS -- the partition stack to be checked - start -- beginning index of the cell to be sorted - degrees -- the values to be sorted by, must have extra scratch space for a - total of 3*n+1 + + - PS -- the partition stack to be checked + - start -- beginning index of the cell to be sorted + - degrees -- the values to be sorted by, must have extra scratch space for a + total of `3*n+1` """ cdef int n = PS.degree diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx index c01634e1772..41891938e7a 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx @@ -117,8 +117,9 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): storing results to ``self``. INPUT: - partition -- an optional list of lists partition of the columns. - default is the unit partition. + + - partition -- an optional list of lists partition of the columns; + default is the unit partition EXAMPLES:: @@ -253,7 +254,7 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): def automorphism_group(self): """ - Returns a list of generators of the automorphism group, along with its + Return a list of generators of the automorphism group, along with its order and a base for which the list of generators is a strong generating set. @@ -280,7 +281,7 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): def canonical_relabeling(self): """ - Returns a canonical relabeling (in list permutation format). + Return a canonical relabeling (in list permutation format). EXAMPLES: (For more examples, see self.run()):: @@ -528,7 +529,7 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): def automorphism_group(self): """ - Returns a list of generators of the automorphism group, along with its + Return a list of generators of the automorphism group, along with its order and a base for which the list of generators is a strong generating set. @@ -561,7 +562,7 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): def canonical_relabeling(self): """ - Returns a canonical relabeling (in list permutation format). + Return a canonical relabeling (in list permutation format). EXAMPLES: (For more examples, see self.run()):: @@ -625,17 +626,17 @@ cdef int ith_word_nonlinear(BinaryCodeStruct self, int i, bitset_s *word) noexce cdef int refine_by_bip_degree(PartitionStack *col_ps, void *S, int *cells_to_refine_by, int ctrb_len) noexcept: r""" - Refines the input partition by checking degrees of vertices to the given + Refine the input partition by checking degrees of vertices to the given cells in the associated bipartite graph (vertices split into columns and words). INPUT: - col_ps -- a partition stack, whose finest partition is the partition to be - refined. - S -- a binary code struct object - cells_to_refine_by -- a list of pointers to cells to check degrees against - in refining the other cells (updated in place) - ctrb_len -- how many cells in cells_to_refine_by + + - col_ps -- a partition stack, whose finest partition is the partition to be refined + - S -- a binary code struct object + - cells_to_refine_by -- a list of pointers to cells to check degrees against + in refining the other cells (updated in place) + - ctrb_len -- how many cells in cells_to_refine_by OUTPUT: @@ -960,12 +961,12 @@ cdef inline int word_degree(PartitionStack *word_ps, BinaryCodeStruct BCS, int e vertices in the cell corresponding to cell_index. INPUT: - word_ps -- the partition stack to be checked - col_ps -- corresponding partition stack on columns - BCS -- a binary code struct object - entry -- the position of the vertex in question in the entries of word_ps - cell_index -- the starting position of the cell in question in the entries - of PS + + - word_ps -- the partition stack to be checked + - col_ps -- corresponding partition stack on columns + - BCS -- a binary code struct object + - entry -- the position of the vertex in question in the entries of word_ps + - cell_index -- the starting position of the cell in question in the entries of PS """ cdef bitset_t cell, word cdef int h @@ -990,12 +991,12 @@ cdef inline int col_degree(PartitionStack *col_ps, BinaryCodeStruct BCS, int ent vertices in the cell corresponding to cell_index. INPUT: - col_ps -- the partition stack to be checked - word_ps -- corresponding partition stack on words - BCS -- a binary code struct object - entry -- the position of the vertex in question in the entries of word_ps - cell_index -- the starting position of the cell in question in the entries - of PS + + - col_ps -- the partition stack to be checked + - word_ps -- corresponding partition stack on words + - BCS -- a binary code struct object + - entry -- the position of the vertex in question in the entries of word_ps + - cell_index -- the starting position of the cell in question in the entries of PS """ cdef bitset_t word bitset_init(word, BCS.degree) @@ -1054,14 +1055,15 @@ cdef inline int sort_by_function_codes(PartitionStack *PS, int start, int *degre def random_tests(num=50, n_max=50, k_max=6, nwords_max=200, perms_per_code=10, density_range=(.1,.9)): """ - Tests to make sure that C(gamma(B)) == C(B) for random permutations gamma + Test to make sure that C(gamma(B)) == C(B) for random permutations gamma and random codes B, and that is_isomorphic returns an isomorphism. INPUT: - num -- run tests for this many codes - n_max -- test codes with at most this many columns - k_max -- test codes with at most this for dimension - perms_per_code -- test each code with this many random permutations + + - num -- run tests for this many codes + - n_max -- test codes with at most this many columns + - k_max -- test codes with at most this for dimension + - perms_per_code -- test each code with this many random permutations DISCUSSION: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx index 2ebf9e08b56..5cad4cb0a0b 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx @@ -1163,7 +1163,7 @@ cdef void *apply_dg_edge_aug(void *parent, void *aug, void *child, int *degree, cdef void *allocate_dg_edge(int n, bint loops) noexcept: r""" - Allocates an object for this augmentation scheme. + Allocate an object for this augmentation scheme. """ cdef GraphStruct GS cdef DenseGraph G @@ -1187,7 +1187,7 @@ cdef void *allocate_dg_edge(int n, bint loops) noexcept: cdef void free_dg_edge(void *child) noexcept: r""" - Deallocates an object for this augmentation scheme. + Deallocate an object for this augmentation scheme. """ cdef GraphStruct GS = child sig_free(GS.scratch) @@ -1196,9 +1196,9 @@ cdef void free_dg_edge(void *child) noexcept: cdef void *canonical_dg_edge_parent(void *child, void *parent, int *permutation, int *degree, bint *mem_err) noexcept: r""" - Applies ``permutation`` to ``child``, determines an arbitrary parent by - deleting the lexicographically largest edge, applies the inverse of - ``permutation`` to the result and stores the result in ``parent``. + Apply ``permutation`` to ``child``, determine an arbitrary parent by + deleting the lexicographically largest edge, apply the inverse of + ``permutation`` to the result and store the result in ``parent``. """ cdef GraphStruct GS_par = parent, GS = child cdef DenseGraph DG_par = GS_par.G, DG = GS.G @@ -1226,7 +1226,7 @@ cdef void *canonical_dg_edge_parent(void *child, void *parent, int *permutation, cdef iterator *allocate_dg_edge_gen(int degree, int depth, bint loops) noexcept: r""" - Allocates the iterator for generating graphs. + Allocate the iterator for generating graphs. """ cdef iterator *dg_edge_gen = sig_malloc(sizeof(iterator)) cdef canonical_generator_data *cgd = allocate_cgd(depth, degree) @@ -1256,7 +1256,7 @@ cdef iterator *allocate_dg_edge_gen(int degree, int depth, bint loops) noexcept: cdef void free_dg_edge_gen(iterator *dg_edge_gen) noexcept: r""" - Deallocates the iterator for generating graphs. + Deallocate the iterator for generating graphs. """ cdef canonical_generator_data *cgd = dg_edge_gen.data deallocate_cgd(cgd) @@ -1431,7 +1431,7 @@ cdef void *apply_dg_vert_aug(void *parent, void *aug, void *child, int *degree, cdef void *allocate_dg_vert(int n, int depth) noexcept: r""" - Allocates an object for this augmentation scheme. + Allocate an object for this augmentation scheme. """ cdef GraphStruct GS cdef DenseGraph G @@ -1457,7 +1457,7 @@ cdef void *allocate_dg_vert(int n, int depth) noexcept: cdef void free_dg_vert(void *child) noexcept: r""" - Deallocates an object for this augmentation scheme. + Deallocate an object for this augmentation scheme. """ cdef GraphStruct GS = child sig_free(GS.scratch) @@ -1466,9 +1466,9 @@ cdef void free_dg_vert(void *child) noexcept: cdef void *canonical_dg_vert_parent(void *child, void *parent, int *permutation, int *degree, bint *mem_err) noexcept: r""" - Applies ``permutation`` to ``child``, determines an arbitrary parent by - deleting the lexicographically largest vertex, applies the inverse of - ``permutation`` to the result and stores the result in ``parent``. + Apply ``permutation`` to ``child``, determines an arbitrary parent by + deleting the lexicographically largest vertex, apply the inverse of + ``permutation`` to the result and store the result in ``parent``. """ cdef GraphStruct GS_par = parent, GS = child cdef DenseGraph DG_par = GS_par.G, DG = GS.G @@ -1488,7 +1488,7 @@ cdef void *canonical_dg_vert_parent(void *child, void *parent, int *permutation, cdef iterator *allocate_dg_vert_gen(int degree, int depth) noexcept: r""" - Allocates the iterator for generating graphs. + Allocate the iterator for generating graphs. """ cdef iterator *dg_vert_gen = sig_malloc(sizeof(iterator)) cdef canonical_generator_data *cgd = allocate_cgd(depth, degree) @@ -1529,7 +1529,7 @@ cdef iterator *allocate_dg_vert_gen(int degree, int depth) noexcept: cdef void free_dg_vert_gen(iterator *dg_vert_gen) noexcept: r""" - Deallocates the iterator for generating graphs. + Deallocate the iterator for generating graphs. """ cdef canonical_generator_data *cgd = dg_vert_gen.data deallocate_cgd(cgd) diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx index 1366fa8ceee..9fb97741746 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx @@ -130,9 +130,8 @@ cdef class MatrixStruct: INPUT: - partition -- an optional list of lists partition of the columns. - - Default is the unit partition. + - partition -- an optional list of lists partition of the columns; + default is the unit partition. EXAMPLES:: @@ -174,7 +173,7 @@ cdef class MatrixStruct: def automorphism_group(self): """ - Returns a list of generators of the automorphism group, along with its + Return a list of generators of the automorphism group, along with its order and a base for which the list of generators is a strong generating set. @@ -203,7 +202,7 @@ cdef class MatrixStruct: def canonical_relabeling(self): """ - Returns a canonical relabeling (in list permutation format). + Return a canonical relabeling (in list permutation format). For more examples, see self.run(). @@ -299,7 +298,7 @@ cdef bint all_matrix_children_are_equivalent(PartitionStack *PS, void *S) noexce def random_tests(n=10, nrows_max=50, ncols_max=50, nsymbols_max=10, perms_per_matrix=5, density_range=(.1,.9)): """ - Tests to make sure that C(gamma(M)) == C(M) for random permutations gamma + Test to make sure that C(gamma(M)) == C(M) for random permutations gamma and random matrices M, and that M.is_isomorphic(gamma(M)) returns an isomorphism. diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx index b73406b13a7..0dd869c1c95 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx @@ -69,7 +69,7 @@ cdef class PythonPartitionStack: def __repr__(self): """ - Returns a string representing the stack. + Return a string representing the stack. EXAMPLES:: @@ -82,7 +82,7 @@ cdef class PythonPartitionStack: def display(self): """ - Prints a representation of the stack. + Print a representation of the stack. EXAMPLES:: @@ -99,7 +99,7 @@ cdef class PythonPartitionStack: def is_discrete(self): """ - Returns whether the deepest partition consists only of singleton cells. + Return whether the deepest partition consists only of singleton cells. EXAMPLES:: @@ -116,7 +116,7 @@ cdef class PythonPartitionStack: def num_cells(self): """ - Returns the number of cells in the deepest partition. + Return the number of cells in the deepest partition. EXAMPLES:: @@ -129,7 +129,7 @@ cdef class PythonPartitionStack: def move_min_to_front(self, int start, int end): """ - Makes sure that the first element of the segment of entries i with + Make sure that the first element of the segment of entries i with start <= i <= end is minimal. EXAMPLES:: @@ -166,7 +166,7 @@ cdef class PythonPartitionStack: def clear(self): """ - Sets the current partition to the first shallower one, i.e. forgets about + Set the current partition to the first shallower one, i.e. forget about boundaries between cells that are new to the current level. EXAMPLES:: @@ -188,7 +188,7 @@ cdef class PythonPartitionStack: def entries(self): """ - Returns the entries array as a Python list of ints. + Return the entries array as a Python list of ints. EXAMPLES:: @@ -204,7 +204,7 @@ cdef class PythonPartitionStack: def set_entry(self, int i, int entry): """ - Sets the ith entry of the entries array to entry. + Set the ith entry of the entries array to entry. EXAMPLES:: @@ -219,7 +219,7 @@ cdef class PythonPartitionStack: def get_entry(self, int i): """ - Gets the ith entry of the entries array. + Get the ith entry of the entries array. EXAMPLES:: @@ -247,7 +247,7 @@ cdef class PythonPartitionStack: def set_level(self, int i, int level): """ - Sets the ith entry of the levels array to entry. + Set the ith entry of the levels array to entry. EXAMPLES:: @@ -264,7 +264,7 @@ cdef class PythonPartitionStack: def get_level(self, int i): """ - Gets the ith entry of the levels array. + Get the ith entry of the levels array. EXAMPLES:: @@ -277,7 +277,7 @@ cdef class PythonPartitionStack: def depth(self, new=None): """ - Returns the depth of the deepest partition in the stack, setting it to + Return the depth of the deepest partition in the stack, setting it to new if new is not None. EXAMPLES:: @@ -293,7 +293,7 @@ cdef class PythonPartitionStack: def degree(self, new=None): """ - Returns the degree of the partition stack, setting it to + Return the degree of the partition stack, setting it to new if new is not None. EXAMPLES:: @@ -404,13 +404,13 @@ def aut_gp_and_can_lab_python(S, partition, n, compare_structures, canonical_label, base, order): """ - Calls the automorphism group and canonical label function. + Call the automorphism group and canonical label function. INPUT: - S -- the object to examine - partition -- an ordered partition, as a list of lists - n -- the degree of the automorphism group to be computed + - S -- the object to examine + - partition -- an ordered partition, as a list of lists + - n -- the degree of the automorphism group to be computed :: @@ -493,11 +493,10 @@ def double_coset_python(S1, S2, partition1, ordering2, n, INPUT: - S1, S2 -- the objects to examine - partition1 -- an ordered partition, as a list of lists - ordering2 -- represents a partition of the points of S2, - as a relabeling of partition1 - n -- the degree + - S1, S2 -- the objects to examine + - partition1 -- an ordered partition, as a list of lists + - ordering2 -- represents a partition of the points of S2, as a relabeling of partition1 + - n -- the degree :: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx index c3a42da04d8..a613b7b9c4a 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx @@ -183,9 +183,9 @@ def set_stab_py(generators, sett, relab=False): cdef aut_gp_and_can_lab *set_stab(StabilizerChain *supergroup, subset *sett, bint relab) noexcept: r""" - Computes the set stabilizer of ``sett`` within ``supergroup``. (Note that + Compute the set stabilizer of ``sett`` within ``supergroup``. (Note that ``set`` is a reserved Python keyword.) If ``relab`` is specified then - computes the canonical label of the set under the action of the group. + compute the canonical label of the set under the action of the group. """ cdef aut_gp_and_can_lab *output cdef int n = supergroup.degree @@ -202,7 +202,7 @@ cdef aut_gp_and_can_lab *set_stab(StabilizerChain *supergroup, subset *sett, bin def sets_isom_py(generators, set1, set2): r""" - Computes whether ``set1`` and ``set2`` are isomorphic under the action of + Compute whether ``set1`` and ``set2`` are isomorphic under the action of the group generated by the generators given in list form. EXAMPLES:: @@ -486,7 +486,7 @@ cdef int compare_sets(int *gamma_1, int *gamma_2, void *S1, void *S2, int degree cdef void *allocate_subset(int n) noexcept: r""" - Allocates a subset struct of degree n. + Allocate a subset struct of degree n. """ cdef subset *set1 = sig_malloc(sizeof(subset)) cdef int *scratch = sig_malloc((3*n+1) * sizeof(int)) @@ -505,7 +505,7 @@ cdef void *allocate_subset(int n) noexcept: cdef void free_subset(void *child) noexcept: r""" - Deallocates a subset struct. + Deallocate a subset struct. """ cdef subset *set1 = child if set1 is not NULL: @@ -515,7 +515,7 @@ cdef void free_subset(void *child) noexcept: cdef void *allocate_sgd(int degree) noexcept: r""" - Allocates the data part of an iterator which generates augmentations, i.e., + Allocate the data part of an iterator which generates augmentations, i.e., elements to add to the set. """ cdef subset_generator_data *sgd = sig_malloc(sizeof(subset_generator_data)) @@ -527,7 +527,7 @@ cdef void *allocate_sgd(int degree) noexcept: cdef void deallocate_sgd(void *data) noexcept: r""" - Deallocates the data part of the augmentation iterator. + Deallocate the data part of the augmentation iterator. """ cdef subset_generator_data *sgd = data if sgd is not NULL: @@ -552,7 +552,7 @@ cdef void *subset_generator_next(void *data, int *degree, bint *mem_err) noexcep cdef int generate_child_subsets(void *S, aut_gp_and_can_lab *group, iterator *child_iterator) noexcept: r""" - Sets up an iterator of augmentations, i.e., elements to add to the given set. + Set up an iterator of augmentations, i.e., elements to add to the given set. """ cdef subset *subset1 = S cdef int i, j, n = group.group.degree @@ -572,7 +572,7 @@ cdef int generate_child_subsets(void *S, aut_gp_and_can_lab *group, iterator *ch cdef void *apply_subset_aug(void *parent, void *aug, void *child, int *degree, bint *mem_err) noexcept: r""" - Adds the element represented by ``aug`` to ``parent``, storing the result to + Add the element represented by ``aug`` to ``parent``, storing the result to ``child``. """ cdef subset *set1 = child @@ -589,7 +589,7 @@ cdef void free_subset_aug(void *aug) noexcept: cdef void *canonical_set_parent(void *child, void *parent, int *permutation, int *degree, bint *mem_err) noexcept: r""" - Determines the canonical parent of the set ``child`` by applying + Determine the canonical parent of the set ``child`` by applying ``permutation``, deleting the largest element in lexicographic order, and storing the result to ``parent``. """ @@ -619,7 +619,7 @@ cdef void *canonical_set_parent(void *child, void *parent, int *permutation, int cdef iterator *allocate_subset_gen(int degree, int max_size) noexcept: r""" - Allocates the generator of subsets. + Allocate the generator of subsets. """ cdef iterator *subset_gen = sig_malloc(sizeof(iterator)) if subset_gen is not NULL: @@ -630,7 +630,7 @@ cdef iterator *allocate_subset_gen(int degree, int max_size) noexcept: cdef int allocate_subset_gen_2(int degree, int max_size, iterator *it) noexcept: r""" - Given an already allocated iterator, allocates the generator of subsets. + Given an already allocated iterator, allocate the generator of subsets. """ cdef canonical_generator_data *cgd = allocate_cgd(max_size + 1, degree) if cgd is NULL: @@ -656,7 +656,7 @@ cdef int allocate_subset_gen_2(int degree, int max_size, iterator *it) noexcept: cdef void free_subset_gen(iterator *subset_gen) noexcept: r""" - Frees the iterator of subsets. + Free the iterator of subsets. """ if subset_gen is NULL: return @@ -666,7 +666,7 @@ cdef void free_subset_gen(iterator *subset_gen) noexcept: cdef iterator *setup_set_gen(iterator *subset_gen, int degree, int max_size) noexcept: r""" - Initiates the iterator of subsets. + Initiate the iterator of subsets. """ cdef subset *empty_set cdef iterator *subset_iterator = setup_canonical_generator(degree, diff --git a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx index 89529f4e8ce..ff54ecdb023 100644 --- a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx +++ b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx @@ -1,5 +1,5 @@ r""" -Automorphism groups and canonical labels. +Automorphism groups and canonical labels For details see section 3 of [Feu2013]_. @@ -454,7 +454,7 @@ cdef class LabelledBranching: cdef class PartitionRefinement_generic: r""" - Implements the partition and refinement framework for + Implement the partition and refinement framework for group actions `G \rtimes S_n` on `X^n` as described in :mod:`sage.groups.perm_gps.partn_ref2.refinement_generic`. """ @@ -592,7 +592,7 @@ cdef class PartitionRefinement_generic: def get_autom_order_permutation(self): r""" - Return the order of the automorphism group we have computes + Return the order of the automorphism group we have computed. EXAMPLES:: @@ -869,7 +869,7 @@ cdef class PartitionRefinement_generic: cdef void _latex_act_node(self, str comment="", int printlvl=0) noexcept: r""" Append the actual node as a string of latex-commands to - ``self._latex_debug_string`` + ``self._latex_debug_string``. """ raise NotImplementedError # must be implemented by derived classes diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 09c6f8ceab5..5b76232e336 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1481,7 +1481,7 @@ def largest_moved_point(self): sage: G.largest_moved_point() 'e' - .. warning:: + .. WARNING:: The name of this function is not good; this function should be deprecated in term of degree:: diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index 514b676efbf..cfc38b639de 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -157,7 +157,7 @@ def __classcall__(cls, domain): INPUT: - - ``n`` -- an integer or list or tuple thereof + - ``n`` -- integer or list or tuple thereof Calls the constructor with a tuple representing the set. @@ -1077,7 +1077,7 @@ def __init__(self, n): INPUT: - - ``n`` -- an integer among `\{1,2,3\}`. + - ``n`` -- integer among `\{1,2,3\}`. EXAMPLES:: @@ -1841,7 +1841,7 @@ def __init__(self, d, n): sage: G.category() Category of finite enumerated permutation groups - .. warning:: this follows GAP's naming convention of indexing + .. WARNING:: this follows GAP's naming convention of indexing the transitive groups starting from ``1``:: sage: TransitiveGroup(5,0) @@ -1849,7 +1849,7 @@ def __init__(self, d, n): ... ValueError: index n must be in {1,..,5} - .. warning:: only transitive groups of "small" degree are + .. WARNING:: only transitive groups of "small" degree are available in GAP's database:: sage: TransitiveGroup(32,1) @@ -1922,7 +1922,7 @@ def TransitiveGroups(d=None): """ INPUT: - - ``d`` -- an integer (optional) + - ``d`` -- integer (optional) Return the set of all transitive groups of a given degree ``d`` up to isomorphisms. If ``d`` is not specified, it returns the set of all @@ -1940,7 +1940,7 @@ def TransitiveGroups(d=None): sage: TransitiveGroups() Transitive Groups - .. warning:: in practice, the database currently only contains + .. WARNING:: in practice, the database currently only contains transitive groups up to degree 31:: sage: TransitiveGroups(32).cardinality() @@ -2229,7 +2229,7 @@ class PrimitiveGroup(PermutationGroup_unique): sage: G.category() Category of finite enumerated permutation groups - .. warning:: + .. WARNING:: this follows GAP's naming convention of indexing the primitive groups starting from ``1``:: @@ -2316,7 +2316,7 @@ def PrimitiveGroups(d=None): INPUT: - - ``d`` -- an integer (optional) + - ``d`` -- integer (optional) OUTPUT: @@ -2398,7 +2398,7 @@ def _repr_(self): """ Return a string representation. - OUTPUT: a string + OUTPUT: string TESTS:: @@ -2471,7 +2471,7 @@ def _repr_(self): """ Return a string representation. - OUTPUT: a string + OUTPUT: string TESTS:: @@ -2514,7 +2514,7 @@ def __getitem__(self, n): sage: PrimitiveGroups(5)[3] AGL(1, 5) - .. warning:: + .. WARNING:: this follows GAP's naming convention of indexing the primitive groups starting from ``1``:: @@ -2541,7 +2541,7 @@ def cardinality(self): r""" Return the cardinality of ``self``. - OUTPUT: an integer; the number of primitive groups of a given degree + OUTPUT: integer; the number of primitive groups of a given degree up to isomorphism EXAMPLES:: diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx index c1fc37fda84..b59facdd3ce 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx @@ -265,8 +265,8 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): def __reduce__(self): """ - Returns a function and its arguments needed to create this - semimonomial group element. This is used in pickling. + Return a function and its arguments needed to create this + semimonomial group element. This is used in pickling. EXAMPLES:: @@ -279,7 +279,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): def get_v(self): """ - Returns the component corresponding to `{R^{\times}}^n` of ``self``. + Return the component corresponding to `{R^{\times}}^n` of ``self``. EXAMPLES:: @@ -291,7 +291,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): def get_v_inverse(self): """ - Returns the (elementwise) inverse of the component corresponding to + Return the (elementwise) inverse of the component corresponding to `{R^{\times}}^n` of ``self``. EXAMPLES:: @@ -304,7 +304,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): def get_perm(self): """ - Returns the component corresponding to `S_n` of ``self``. + Return the component corresponding to `S_n` of ``self``. EXAMPLES:: @@ -316,7 +316,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): def get_autom(self): """ - Returns the component corresponding to `Aut(R)` of ``self``. + Return the component corresponding to `Aut(R)` of ``self``. EXAMPLES:: From 57af00f376e888da05ed796b5f4c0873495c68c8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 29 Feb 2024 22:09:35 -0800 Subject: [PATCH 139/191] sage.categories.morphism.SetIsomorphism: New --- src/sage/categories/map.pyx | 3 +- src/sage/categories/morphism.pxd | 3 + src/sage/categories/morphism.pyx | 158 ++++++++++++++++++++++++++++++- 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index b41b7538c59..a3355563d34 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -1272,7 +1272,7 @@ cdef class Map(Element): def section(self): """ - Return a section of self. + Return a section of ``self``. .. NOTE:: @@ -1439,6 +1439,7 @@ cdef class Section(Map): """ return self._inverse + cdef class FormalCompositeMap(Map): """ Formal composite maps. diff --git a/src/sage/categories/morphism.pxd b/src/sage/categories/morphism.pxd index e5befc8207e..52847fd83b7 100644 --- a/src/sage/categories/morphism.pxd +++ b/src/sage/categories/morphism.pxd @@ -8,3 +8,6 @@ cdef class Morphism(Map): cdef class SetMorphism(Morphism): cdef object _function cpdef bint _eq_c_impl(left, Element right) noexcept + +cdef class SetIsomorphism(SetMorphism): + cdef object _inverse diff --git a/src/sage/categories/morphism.pyx b/src/sage/categories/morphism.pyx index 0e4805ef1b4..d4b412dd126 100644 --- a/src/sage/categories/morphism.pyx +++ b/src/sage/categories/morphism.pyx @@ -570,7 +570,7 @@ cdef class SetMorphism(Morphism): - ``parent`` -- a Homset - ``function`` -- a Python function that takes elements - of the domain as input and returns elements of the domain. + of the domain as input and returns elements of the codomain. EXAMPLES:: @@ -736,3 +736,159 @@ cdef class SetMorphism(Morphism): return not (isinstance(right, Element) and self._eq_c_impl(right)) else: return False + + +cdef class SetIsomorphism(SetMorphism): + r""" + An isomorphism of sets. + + INPUT: + + - ``parent`` -- a Homset + - ``function`` -- a Python function that takes elements + of the domain as input and returns elements of the codomain. + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__); f + Generic endomorphism of Integer Ring + sage: f._set_inverse(f) + sage: ~f is f + True + """ + def _set_inverse(self, inverse): + r""" + Set the inverse morphism of ``self`` to be ``inverse``. + + INPUT: + + - ``inverse`` -- a :class:`SetIsomorphism` + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: f._set_inverse(f) + sage: ~f is f + True + """ + self._inverse = inverse + + def __invert__(self): + r""" + Return the inverse morphism of ``self``. + + If :meth:`_set_inverse` has not been called yet, an error is raised. + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: ~f + Traceback (most recent call last): + ... + RuntimeError: inverse morphism has not been set + sage: f._set_inverse(f) + sage: ~f + Generic endomorphism of Integer Ring + """ + if not self._inverse: + raise RuntimeError('inverse morphism has not been set') + return self._inverse + + cdef dict _extra_slots(self) noexcept: + """ + Extend the dictionary with extra slots for this class. + + INPUT: + + - ``_slots`` -- a dictionary + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: f._set_inverse(f) + sage: f._extra_slots_test() + {'_codomain': Integer Ring, + '_domain': Integer Ring, + '_function': , + '_inverse': Generic endomorphism of Integer Ring, + '_is_coercion': False, + '_repr_type_str': None} + """ + slots = SetMorphism._extra_slots(self) + slots['_inverse'] = self._inverse + return slots + + cdef _update_slots(self, dict _slots) noexcept: + """ + Update the slots of ``self`` from the data in the dictionary. + + INPUT: + + - ``_slots`` -- a dictionary + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: f._update_slots_test({'_function': operator.__neg__, + ....: '_inverse': f, + ....: '_domain': QQ, + ....: '_codomain': QQ, + ....: '_repr_type_str': 'bla'}) + sage: f(3) + -3 + sage: f._repr_type() + 'bla' + sage: f.domain() + Rational Field + sage: f.codomain() + Rational Field + sage: f.inverse() == f + True + """ + self._inverse = _slots['_inverse'] + SetMorphism._update_slots(self, _slots) + + def section(self): + """ + Return a section of this morphism. + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: f._set_inverse(f) + sage: f.section() is f + True + """ + return self.__invert__() + + def is_surjective(self): + r""" + Return whether this morphism is surjective. + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: f.is_surjective() + True + """ + return True + + def is_injective(self): + r""" + Return whether this morphism is injective. + + EXAMPLES:: + + sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()), + ....: operator.__neg__) + sage: f.is_injective() + True + """ + return True From 6903923fb4efd63aac13bdb0de473c8fde90a16c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 29 Feb 2024 22:11:04 -0800 Subject: [PATCH 140/191] FiniteRankFreeModule_abstract.isomorphism_with_fixed_basis: Return a SetIsomorphism --- .../tensor/modules/finite_rank_free_module.py | 109 +++++++++++++----- 1 file changed, 81 insertions(+), 28 deletions(-) diff --git a/src/sage/tensor/modules/finite_rank_free_module.py b/src/sage/tensor/modules/finite_rank_free_module.py index 0434ed84c53..cb0922eaa10 100644 --- a/src/sage/tensor/modules/finite_rank_free_module.py +++ b/src/sage/tensor/modules/finite_rank_free_module.py @@ -539,7 +539,9 @@ class :class:`~sage.modules.free_module.FreeModule_generic` from typing import Generator, Optional from sage.categories.fields import Fields +from sage.categories.homset import Hom from sage.categories.modules import Modules +from sage.categories.morphism import SetIsomorphism from sage.categories.rings import Rings from sage.misc.cachefunc import cached_method from sage.rings.integer import Integer @@ -755,15 +757,15 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): - ``codomain`` -- (default: ``None``) the codomain of the isomorphism represented by a free module within the category :class:`~sage.categories.modules_with_basis.ModulesWithBasis` with - the same rank and base ring as ``self``; if ``None`` a free module + the same rank and base ring as ``self``; if ``None``, a free module represented by :class:`~sage.combinat.free_module.CombinatorialFreeModule` is constructed OUTPUT: - - a module morphism represented by - :class:`~sage.modules.with_basis.morphism.ModuleMorphismFromFunction` + - a module isomorphism represented by + :class:`~sage.categories.morphism.SetIsomorphism` EXAMPLES:: @@ -800,6 +802,12 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): To: Free module generated by {'a', 'b', 'c'} over Rational Field sage: phi_eW(e[1] + 2 * e[2]) B['a'] + 2*B['b'] + sage: ~phi_eW + Generic morphism: + From: Free module generated by {'a', 'b', 'c'} over Rational Field + To: 3-dimensional vector space over the Rational Field + sage: (~phi_eW)(W.basis()['b']).display() + e_2 Providing a :class:`~sage.modules.free_module.Module_free_ambient` as the codomain:: @@ -814,7 +822,8 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): Sending (1,1)-tensors to matrices:: sage: T11 = V.tensor_module(1, 1); T11 - Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field + Free module of type-(1,1) tensors on the + 3-dimensional vector space over the Rational Field sage: e_T11 = T11.basis("e"); e_T11 Standard basis on the Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field @@ -822,7 +831,8 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): sage: W = MatrixSpace(QQ, 3) sage: phi_e_T11 = T11.isomorphism_with_fixed_basis(e_T11, codomain=W); phi_e_T11 Generic morphism: - From: Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field + From: Free module of type-(1,1) tensors on the + 3-dimensional vector space over the Rational Field To: Full MatrixSpace of 3 by 3 dense matrices over Rational Field sage: t = T11.an_element(); t.display() 1/2 e_1⊗e^1 @@ -830,20 +840,33 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): [1/2 0 0] [ 0 0 0] [ 0 0 0] + sage: ~phi_e_T11 + Generic morphism: + From: Full MatrixSpace of 3 by 3 dense matrices over Rational Field + To: Free module of type-(1,1) tensors on the + 3-dimensional vector space over the Rational Field + sage: (~phi_e_T11)(W([[0, 1/2, 1/3], + ....: [-1/2, 0, 0], + ....: [-1/3, 0, 0]])).display() + 1/2 e_1⊗e^2 + 1/3 e_1⊗e^3 - 1/2 e_2⊗e^1 - 1/3 e_3⊗e^1 Sending symmetric bilinear forms to matrices (note that they are currently elements of `T^{(0,2)}(M)`, not the symmetric power of `M`):: sage: T02 = V.tensor_module(0, 2); T02 - Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field + Free module of type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field sage: e_T02 = T02.basis("e"); e_T02 Standard basis on the - Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field - induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field + Free module of type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field + induced by Basis (e_1,e_2,e_3) on the + 3-dimensional vector space over the Rational Field sage: W = MatrixSpace(QQ, 3) sage: phi_e_T02 = T02.isomorphism_with_fixed_basis(e_T02, codomain=W); phi_e_T02 Generic morphism: - From: Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field + From: Free module of type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field To: Full MatrixSpace of 3 by 3 dense matrices over Rational Field sage: a = V.sym_bilinear_form() @@ -851,7 +874,8 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): sage: a[2,2], a[2,3] = 4, 5 sage: a[3,3] = 6 sage: a.display() - e^1⊗e^1 + 2 e^1⊗e^2 + 3 e^1⊗e^3 + 2 e^2⊗e^1 + 4 e^2⊗e^2 + 5 e^2⊗e^3 + 3 e^3⊗e^1 + 5 e^3⊗e^2 + 6 e^3⊗e^3 + e^1⊗e^1 + 2 e^1⊗e^2 + 3 e^1⊗e^3 + 2 e^2⊗e^1 + 4 e^2⊗e^2 + 5 e^2⊗e^3 + + 3 e^3⊗e^1 + 5 e^3⊗e^2 + 6 e^3⊗e^3 sage: phi_e_T02(a) [1 2 3] [2 4 5] @@ -860,15 +884,18 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): Same but explicitly in the subspace of symmetric bilinear forms:: sage: Sym2Vdual = V.dual_symmetric_power(2); Sym2Vdual - Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field + Free module of fully symmetric type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field sage: Sym2Vdual.is_submodule(T02) True sage: Sym2Vdual.rank() 6 sage: e_Sym2Vdual = Sym2Vdual.basis("e"); e_Sym2Vdual Standard basis on the - Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field - induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field + Free module of fully symmetric type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field + induced by Basis (e_1,e_2,e_3) on the + 3-dimensional vector space over the Rational Field sage: W_basis = [phi_e_T02(b) for b in e_Sym2Vdual]; W_basis [ [1 0 0] [0 1 0] [0 0 1] [0 0 0] [0 0 0] [0 0 0] @@ -877,25 +904,34 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): ] sage: W = MatrixSpace(QQ, 3).submodule(W_basis); W Free module generated by {0, 1, 2, 3, 4, 5} over Rational Field - sage: phi_e_Sym2Vdual = Sym2Vdual.isomorphism_with_fixed_basis(e_Sym2Vdual, codomain=W); phi_e_Sym2Vdual + sage: phi_e_Sym2Vdual = Sym2Vdual.isomorphism_with_fixed_basis(e_Sym2Vdual, + ....: codomain=W) + sage: phi_e_Sym2Vdual Generic morphism: - From: Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field + From: Free module of fully symmetric type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field To: Free module generated by {0, 1, 2, 3, 4, 5} over Rational Field Sending tensors to elements of the tensor square of :class:`CombinatorialFreeModule`:: sage: T20 = V.tensor_module(2, 0); T20 - Free module of type-(2,0) tensors on the 3-dimensional vector space over the Rational Field + Free module of type-(2,0) tensors on the + 3-dimensional vector space over the Rational Field sage: e_T20 = T02.basis("e"); e_T20 Standard basis on the - Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field - induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field + Free module of type-(0,2) tensors on the + 3-dimensional vector space over the Rational Field + induced by Basis (e_1,e_2,e_3) on the + 3-dimensional vector space over the Rational Field sage: W = CombinatorialFreeModule(QQ, [1, 2, 3]).tensor_square(); W - Free module generated by {1, 2, 3} over Rational Field # Free module generated by {1, 2, 3} over Rational Field + Free module generated by {1, 2, 3} over Rational Field + # Free module generated by {1, 2, 3} over Rational Field sage: phi_e_T20 = T20.isomorphism_with_fixed_basis(e_T20, codomain=W); phi_e_T20 Generic morphism: - From: Free module of type-(2,0) tensors on the 3-dimensional vector space over the Rational Field - To: Free module generated by {1, 2, 3} over Rational Field # Free module generated by {1, 2, 3} over Rational Field + From: Free module of type-(2,0) tensors on the + 3-dimensional vector space over the Rational Field + To: Free module generated by {1, 2, 3} over Rational Field + # Free module generated by {1, 2, 3} over Rational Field sage: t = T20.an_element(); t.display() 1/2 e_1⊗e_1 sage: phi_e_T20(t) @@ -940,13 +976,17 @@ def isomorphism_with_fixed_basis(self, basis=None, codomain=None): codomain_basis = Family(codomain.basis()) if isinstance(codomain_basis, TrivialFamily): - # assume that codomain basis keys are to be ignored - key_pairs = enumerate(basis.keys()) + # assume that codomain basis keys are to be ignored; + # need them several times, can't keep as generators + key_pairs = tuple(enumerate(basis.keys())) + basis_by_codomain_key = basis else: # assume that the keys of the codomain should be used - key_pairs = zip(codomain_basis.keys(), basis.keys()) - # Need them several times, can't keep as generators - key_pairs = tuple(key_pairs) + # need them several times, can't keep as generators + key_pairs = tuple(zip(codomain_basis.keys(), basis.keys())) + basis_by_codomain_key = {} + for codomain_key, domain_key in key_pairs: + basis_by_codomain_key[codomain_key] = basis[domain_key] def _isomorphism(x): r""" @@ -955,7 +995,21 @@ def _isomorphism(x): return codomain.sum(x[basis, domain_key] * codomain_basis[codomain_key] for codomain_key, domain_key in key_pairs) - return self.module_morphism(function=_isomorphism, codomain=codomain) + def _inverse(y): + r""" + Concrete isomorphism from ``codomain`` to ``self``. + """ + return self.linear_combination( + (basis_by_codomain_key[codomain_key], coefficient) + for codomain_key, coefficient in y.monomial_coefficients().items()) + + category = Modules(self.base_ring()) + homset = Hom(self, codomain, category) + isomorphism = SetIsomorphism(homset, _isomorphism) + inverse = SetIsomorphism(homset.reversed(), _inverse) + isomorphism._set_inverse(inverse) + inverse._set_inverse(isomorphism) + return isomorphism def _test_isomorphism_with_fixed_basis(self, **options): r""" @@ -3160,7 +3214,6 @@ def hom(self, codomain, matrix_rep, bases=None, name=None, for more documentation. """ - from sage.categories.homset import Hom homset = Hom(self, codomain) return homset(matrix_rep, bases=bases, name=name, latex_name=latex_name) From 9a95ad4a2a465c7150e638a7912808ada5364de5 Mon Sep 17 00:00:00 2001 From: gmou3 <32706872+gmou3@users.noreply.github.com> Date: Fri, 12 Apr 2024 09:33:35 +0300 Subject: [PATCH 141/191] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- .../groups/abelian_gps/abelian_group_element.py | 4 ++-- src/sage/groups/affine_gps/affine_group.py | 2 +- src/sage/groups/class_function.py | 2 +- src/sage/groups/finitely_presented.py | 2 +- src/sage/groups/galois_group.py | 4 ++-- src/sage/groups/generic.py | 8 ++++---- src/sage/groups/group.pyx | 2 +- src/sage/groups/group_exp.py | 2 +- src/sage/groups/libgap_morphism.py | 3 ++- src/sage/groups/libgap_wrapper.pyx | 4 ++-- src/sage/groups/matrix_gps/isometries.py | 2 +- .../perm_gps/partn_ref/refinement_binary.pyx | 14 +++++++------- .../perm_gps/partn_ref/refinement_matrices.pyx | 6 +++--- .../perm_gps/partn_ref/refinement_python.pyx | 14 +++++++------- .../groups/perm_gps/partn_ref/refinement_sets.pyx | 2 +- src/sage/groups/perm_gps/permgroup_element.pyx | 2 +- src/sage/groups/perm_gps/permgroup_named.py | 6 +++--- 17 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/sage/groups/abelian_gps/abelian_group_element.py b/src/sage/groups/abelian_gps/abelian_group_element.py index 3dc764dd7d0..ac279f71011 100644 --- a/src/sage/groups/abelian_gps/abelian_group_element.py +++ b/src/sage/groups/abelian_gps/abelian_group_element.py @@ -49,8 +49,8 @@ def is_AbelianGroupElement(x): """ - Return ``True`` if x is an abelian group element, i.e., an element of - type ``AbelianGroupElement``. + Return ``True`` if ``x`` is an abelian group element, i.e., an element of + type :class:`AbelianGroupElement`. EXAMPLES: Though the integer 3 is in the integers, and the integers have an abelian group structure, 3 is not an AbelianGroupElement:: diff --git a/src/sage/groups/affine_gps/affine_group.py b/src/sage/groups/affine_gps/affine_group.py index f0e4b3d27f4..7d27488ec59 100644 --- a/src/sage/groups/affine_gps/affine_group.py +++ b/src/sage/groups/affine_gps/affine_group.py @@ -186,7 +186,7 @@ def __init__(self, degree, ring): INPUT: - - ``degree`` -- integer; The degree of the affine group, that + - ``degree`` -- integer; the degree of the affine group, that is, the dimension of the affine space the group is acting on naturally diff --git a/src/sage/groups/class_function.py b/src/sage/groups/class_function.py index c7978b4283e..5d4dc0c1505 100644 --- a/src/sage/groups/class_function.py +++ b/src/sage/groups/class_function.py @@ -349,7 +349,7 @@ def __mul__(self, other): INPUT: - ``other`` -- either a number or a :class:`ClassFunction` of - the same group as ``self``; A number can be anything that + the same group as ``self``; a number can be anything that can be converted into GAP: integers, rational, and elements of certain number fields diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 69bc261a17c..75a33a190f6 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -1536,7 +1536,7 @@ def epimorphisms(self, H): INPUT: - - `H` -- another group + - ``H`` -- another group EXAMPLES:: diff --git a/src/sage/groups/galois_group.py b/src/sage/groups/galois_group.py index b3460f32be8..36495c846ad 100644 --- a/src/sage/groups/galois_group.py +++ b/src/sage/groups/galois_group.py @@ -315,7 +315,7 @@ def fixed_field(self, name=None, polred=None, threshold=None): - ``name`` -- a variable name for the new field - ``polred`` -- whether to optimize the generator of the newly created field - for a simpler polynomial, using pari's polredbest; + for a simpler polynomial, using Pari's :pari:`polredbest`; defaults to ``True`` when the degree of the fixed field is at most 8 - ``threshold`` -- positive number; polred only performed if the cost @@ -381,7 +381,7 @@ def is_galois(self): @lazy_attribute def _gcdata(self): r""" - Return the Galois closure (ie, the finite field itself) together with the identity. + Return the Galois closure (i.e., the finite field itself) together with the identity. EXAMPLES:: diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index 86aebc74709..e69462ecc6b 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -698,8 +698,8 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i - ``bounds`` -- a priori bounds on the log - ``operation`` -- string: ``'*'``, ``'+'``, other - ``identity`` -- the group's identity - - ``inverse()`` - function of 1 argument ``x``, returning inverse of ``x`` - - ``op()`` - function of 2 arguments ``x``, ``y``, returning ``x*y`` in the group + - ``inverse`` -- function of 1 argument ``x``, returning inverse of ``x`` + - ``op`` -- function of 2 arguments ``x``, ``y``, returning ``x*y`` in the group - ``algorithm`` -- string denoting what algorithm to use for prime-order logarithms: ``'bsgs'``, ``'rho'``, ``'lambda'`` @@ -1211,8 +1211,8 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True, prefer the use of ``factorization`` - ``operation`` -- string: ``'+'`` (default), ``'*'`` or ``None`` - ``identity`` -- the identity element of the group - - ``inverse()`` -- function of 1 argument ``x``, returning inverse of ``x`` - - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group + - ``inverse`` -- function of 1 argument ``x``, returning inverse of ``x`` + - ``op`` -- function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group .. NOTE:: diff --git a/src/sage/groups/group.pyx b/src/sage/groups/group.pyx index 32fe6d13941..3f1fb92e756 100644 --- a/src/sage/groups/group.pyx +++ b/src/sage/groups/group.pyx @@ -221,7 +221,7 @@ cdef class Group(Parent): def is_multiplicative(self): r""" - Return ``True`` if the group operation is given by \* (rather than +). + Return ``True`` if the group operation is given by ``*`` (rather than ``+``). Override for additive groups. diff --git a/src/sage/groups/group_exp.py b/src/sage/groups/group_exp.py index ccf6d62f147..49f2315eae3 100644 --- a/src/sage/groups/group_exp.py +++ b/src/sage/groups/group_exp.py @@ -147,7 +147,7 @@ def _apply_functor_to_morphism(self, f): - The above homomorphism, but between the corresponding multiplicative groups. - In the following example, ``self`` is the functor `GroupExp()` and `f` + In the following example, ``self`` is the functor :class:`GroupExp` and `f` is an endomorphism of the additive group of integers. EXAMPLES:: diff --git a/src/sage/groups/libgap_morphism.py b/src/sage/groups/libgap_morphism.py index ec48dda3776..e0f75e7bd4f 100644 --- a/src/sage/groups/libgap_morphism.py +++ b/src/sage/groups/libgap_morphism.py @@ -557,7 +557,8 @@ def preimage(self, S): def section(self): r""" - This method returns a section map of ``self`` by use of :meth:`lift`. + Return a section map of ``self`` by use of :meth:`lift`. + See :meth:`section` of :class:`sage.categories.map.Map`, as well. OUTPUT: an instance of :class:`sage.categories.morphism.SetMorphism` diff --git a/src/sage/groups/libgap_wrapper.pyx b/src/sage/groups/libgap_wrapper.pyx index abaf17f11d9..0cf0e8bfb31 100644 --- a/src/sage/groups/libgap_wrapper.pyx +++ b/src/sage/groups/libgap_wrapper.pyx @@ -260,7 +260,7 @@ class ParentLibGAP(SageObject): def gap(self): """ - Return the gap representation of ``self``. + Return the GAP representation of ``self``. OUTPUT: a :class:`~sage.libs.gap.element.GapElement` @@ -400,7 +400,7 @@ class ParentLibGAP(SageObject): INPUT: - ``i`` -- integer between `0` (inclusive) and :meth:`ngens` - (exclusive); The index of the generator + (exclusive); the index of the generator OUTPUT: the `i`-th generator of the group diff --git a/src/sage/groups/matrix_gps/isometries.py b/src/sage/groups/matrix_gps/isometries.py index baf0925d706..4763b13721a 100644 --- a/src/sage/groups/matrix_gps/isometries.py +++ b/src/sage/groups/matrix_gps/isometries.py @@ -47,7 +47,7 @@ class GroupOfIsometries(FinitelyGeneratedMatrixGroup_gap): A base class for Orthogonal matrix groups with a gap backend. Main difference to :class:`~sage.groups.matrix_gps.orthogonal.OrthogonalMatrixGroup_gap` - is that we can specify generators and a bilinear form. Following gap the group action is + is that we can specify generators and a bilinear form. Following GAP, the group action is from the right. INPUT: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx index 41891938e7a..1abbf635d9c 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx @@ -118,7 +118,7 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): INPUT: - - partition -- an optional list of lists partition of the columns; + - ``partition`` -- an optional list of lists partition of the columns; default is the unit partition EXAMPLES:: @@ -1055,15 +1055,15 @@ cdef inline int sort_by_function_codes(PartitionStack *PS, int start, int *degre def random_tests(num=50, n_max=50, k_max=6, nwords_max=200, perms_per_code=10, density_range=(.1,.9)): """ - Test to make sure that C(gamma(B)) == C(B) for random permutations gamma - and random codes B, and that is_isomorphic returns an isomorphism. + Test to make sure that ``C(gamma(B)) == C(B)`` for random permutations ``gamma`` + and random codes ``B``, and that :meth:`is_isomorphic` returns an isomorphism. INPUT: - - num -- run tests for this many codes - - n_max -- test codes with at most this many columns - - k_max -- test codes with at most this for dimension - - perms_per_code -- test each code with this many random permutations + - ``num`` -- run tests for this many codes + - ``n_max`` -- test codes with at most this many columns + - ``k_max`` -- test codes with at most this for dimension + - ``perms_per_code`` -- test each code with this many random permutations DISCUSSION: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx index 9fb97741746..7fa11c28343 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx @@ -130,7 +130,7 @@ cdef class MatrixStruct: INPUT: - - partition -- an optional list of lists partition of the columns; + - ``partition`` -- an optional list of lists partition of the columns; default is the unit partition. EXAMPLES:: @@ -298,8 +298,8 @@ cdef bint all_matrix_children_are_equivalent(PartitionStack *PS, void *S) noexce def random_tests(n=10, nrows_max=50, ncols_max=50, nsymbols_max=10, perms_per_matrix=5, density_range=(.1,.9)): """ - Test to make sure that C(gamma(M)) == C(M) for random permutations gamma - and random matrices M, and that M.is_isomorphic(gamma(M)) returns an + Test to make sure that ``C(gamma(M)) == C(M)`` for random permutations ``gamma`` + and random matrices ``M``, and that ``M.is_isomorphic(gamma(M))`` returns an isomorphism. INPUT: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx index 0dd869c1c95..96e3497fe42 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_python.pyx @@ -408,9 +408,9 @@ def aut_gp_and_can_lab_python(S, partition, n, INPUT: - - S -- the object to examine - - partition -- an ordered partition, as a list of lists - - n -- the degree of the automorphism group to be computed + - ``S`` -- the object to examine + - ``partition`` -- an ordered partition, as a list of lists + - ``n`` -- the degree of the automorphism group to be computed :: @@ -493,10 +493,10 @@ def double_coset_python(S1, S2, partition1, ordering2, n, INPUT: - - S1, S2 -- the objects to examine - - partition1 -- an ordered partition, as a list of lists - - ordering2 -- represents a partition of the points of S2, as a relabeling of partition1 - - n -- the degree + - ``S1``, ``S2`` -- the objects to examine + - ``partition1`` -- an ordered partition, as a list of lists + - ``ordering2`` -- represents a partition of the points of ``S2``, as a relabeling of ``partition1`` + - ``n`` -- the degree :: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx index a613b7b9c4a..0f951e7e097 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx @@ -697,7 +697,7 @@ def sets_modulo_perm_group(list generators, int max_size, - ``generators`` -- (list of lists) list of generators in list form - ``max_size`` -- (int) maximum size of subsets to be generated - ``indicate_mem_err`` -- (bool) whether to raise an error - if we run out of memory, or simply append a MemoryError + if we run out of memory, or simply append a :class:`MemoryError` instance to the end of the output EXAMPLES:: diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 4c52b386294..c2a462d9727 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -1119,7 +1119,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cpdef ClonableIntArray _act_on_array_on_position(self, ClonableIntArray x): r""" - Return the right action of ``self`` on the ClonableIntArray + Return the right action of ``self`` on the :class:`ClonableIntArray` ``x``. This is the action on positions. EXAMPLES:: diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index cfc38b639de..c000d2cf105 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -1394,8 +1394,8 @@ def __init__(self, factors): gens.append([tuple(range(jumppoint, jumppoint + a))]) # make contribution to the generator that dihedralizes the # abelian group - genx.extend((jumppoint+i, jumppoint+a-i) - for i in range(1, (a//2)+1) if i != a-i) + genx.extend((jumppoint + i, jumppoint + a - i) + for i in range(1, (a//2) + 1) if i != a - i) jumppoint += a # If all of the direct factors are C2, then the action turning # each element into its inverse is trivial, and the @@ -2214,7 +2214,7 @@ class PrimitiveGroup(PermutationGroup_unique): - ``n`` -- positive integer. the index of the group in the GAP database, starting at 1 - OUTPUT: Tthe ``n``-th primitive group of degree ``d`` + OUTPUT: the ``n``-th primitive group of degree ``d`` EXAMPLES:: From 19f157ea4f57cd226f1cb30bd2e164abfd2cbb0a Mon Sep 17 00:00:00 2001 From: Giorgos Mousa Date: Fri, 12 Apr 2024 09:44:50 +0300 Subject: [PATCH 142/191] Revert abelian_gps/all.py and move a dash --- src/sage/groups/abelian_gps/all.py | 7 +++---- src/sage/groups/finitely_presented.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/groups/abelian_gps/all.py b/src/sage/groups/abelian_gps/all.py index fa418e36c0c..2bb91f85f3b 100644 --- a/src/sage/groups/abelian_gps/all.py +++ b/src/sage/groups/abelian_gps/all.py @@ -20,11 +20,10 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -# from dual_abelian_group import DualAbelianGroup +#from dual_abelian_group import DualAbelianGroup from .abelian_group import AbelianGroup, word_problem from .values import AbelianGroupWithValues -# .. TODO:: - -# Implement group homset, conversion of generator images to morphism +# TODO: +# Implement group homset, conversion of generator images to morphism from .abelian_group_morphism import AbelianGroupMorphism diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 75a33a190f6..a6ef6bb7395 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -1725,7 +1725,7 @@ def characteristic_varieties(self, ring=QQ, matrix_ideal=None, groebner=False): group `G`, see e.g. [CS1999a]_. Let `\Lambda` be the group algebra of `G/G'` and `\mathbb{T}` its associated algebraic variety (a torus). Each element `\xi\in\mathbb{T}` defines a local system of coefficients - and the `k` th-characteristic variety is + and the `k`-th characteristic variety is .. MATH:: From b807676f91e4b3027f9617d45a161670869db65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 12 Apr 2024 13:10:10 +0200 Subject: [PATCH 143/191] fix the doctests to use "in Fields()" --- src/sage/combinat/descent_algebra.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index 3cc463b54bb..8ab3886012f 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -146,10 +146,10 @@ def __init__(self, R, n): True sage: B = DescentAlgebra(QQ, 4).B() - sage: B.is_field() + sage: B in Fields() False sage: B = DescentAlgebra(QQ, 1).B() - sage: B.is_field() + sage: B in Fields() True """ self._n = n @@ -161,7 +161,7 @@ def __init__(self, R, n): self._category = cat Parent.__init__(self, base=R, category=self._category.WithRealizations()) - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of ``self``. @@ -261,7 +261,7 @@ def _element_constructor_(self, x): return CombinatorialFreeModule._element_constructor_(self, x) # We need to overwrite this since our basis elements must be indexed by tuples - def _repr_term(self, S): + def _repr_term(self, S) -> str: r""" EXAMPLES:: @@ -285,7 +285,7 @@ def product_on_basis(self, S, T): return self(self.to_B_basis(S) * self.to_B_basis(T)) @cached_method - def one_basis(self): + def one_basis(self) -> tuple: r""" Return the identity element, as per ``AlgebrasWithBasis.ParentMethods.one_basis``. @@ -331,7 +331,8 @@ def to_B_basis(self, S): n = self.realization_of()._n C = Compositions(n) - return B.sum_of_terms([(C.from_subset(T, n), (-1)**(len(S) - len(T))) + lenS = len(S) + return B.sum_of_terms([(C.from_subset(T, n), (-1)**(lenS - len(T))) for T in SubsetsSorted(S)]) def to_symmetric_group_algebra_on_basis(self, S): @@ -873,7 +874,7 @@ def _repr_(self) -> str: """ return "Category of bases of {}".format(self.base()) - def super_categories(self): + def super_categories(self) -> list: r""" The super categories of ``self``. @@ -889,7 +890,7 @@ def super_categories(self): return [self.base()._category, Realizations(self.base())] class ParentMethods: - def _repr_(self): + def _repr_(self) -> str: """ Text representation of this basis of a descent algebra. From f3ac6dcaedcd385c50e652db8853261ba2e49429 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 14 Apr 2024 16:47:35 +0900 Subject: [PATCH 144/191] Add Jacobians to function fields and curves --- src/doc/en/reference/curves/index.rst | 24 +- .../en/reference/function_fields/index.rst | 13 + src/doc/en/reference/references/index.rst | 6 + src/sage/categories/all.py | 2 +- src/sage/categories/category.py | 1 + src/sage/categories/schemes.py | 40 +- .../drinfeld_modules/drinfeld_module.py | 2 +- .../rings/function_field/function_field.py | 99 ++ .../function_field/function_field_polymod.py | 88 +- .../rings/function_field/jacobian_base.py | 796 +++++++++++++ .../rings/function_field/jacobian_hess.py | 1046 +++++++++++++++++ .../function_field/jacobian_khuri_makdisi.py | 1029 ++++++++++++++++ .../rings/function_field/khuri_makdisi.pyx | 893 ++++++++++++++ src/sage/schemes/curves/projective_curve.py | 40 + src/sage/schemes/elliptic_curves/ell_point.py | 56 + src/sage/schemes/elliptic_curves/jacobian.py | 2 +- .../hyperelliptic_curves/jacobian_morphism.py | 96 +- .../schemes/jacobians/abstract_jacobian.py | 67 +- 18 files changed, 4187 insertions(+), 113 deletions(-) create mode 100644 src/sage/rings/function_field/jacobian_base.py create mode 100644 src/sage/rings/function_field/jacobian_hess.py create mode 100644 src/sage/rings/function_field/jacobian_khuri_makdisi.py create mode 100644 src/sage/rings/function_field/khuri_makdisi.pyx diff --git a/src/doc/en/reference/curves/index.rst b/src/doc/en/reference/curves/index.rst index 2bc0d098cba..583b331ea28 100644 --- a/src/doc/en/reference/curves/index.rst +++ b/src/doc/en/reference/curves/index.rst @@ -1,5 +1,11 @@ +Plane and Space Curves +====================== + +Sage enables computations with curves in affine and projective ambient spaces, +curves over `\CC` as Riemann surfaces, and Jacobians of projective curves. + Curves -====== +------ .. toctree:: :maxdepth: 1 @@ -12,10 +18,8 @@ Curves sage/schemes/curves/closed_point sage/schemes/curves/zariski_vankampen - sage/schemes/jacobians/abstract_jacobian - Plane conics -============ +------------ .. toctree:: :maxdepth: 1 @@ -28,7 +32,7 @@ Plane conics sage/schemes/plane_conics/con_rational_function_field Plane quartics -========================= +-------------- .. toctree:: :maxdepth: 1 @@ -37,11 +41,19 @@ Plane quartics sage/schemes/plane_quartics/quartic_generic Riemann surfaces -================ +---------------- .. toctree:: :maxdepth: 1 sage/schemes/riemann_surfaces/riemann_surface +Jacobians +--------- + +.. toctree:: + :maxdepth: 1 + + sage/schemes/jacobians/abstract_jacobian + .. include:: ../footer.txt diff --git a/src/doc/en/reference/function_fields/index.rst b/src/doc/en/reference/function_fields/index.rst index 9f9a7e8c42d..7100f300b47 100644 --- a/src/doc/en/reference/function_fields/index.rst +++ b/src/doc/en/reference/function_fields/index.rst @@ -38,6 +38,19 @@ algebraic closure of `\QQ`. A basic reference for the theory of algebraic function fields is [Stich2009]_. +Jacobians of function fields +---------------------------- + +Arithmetic in Jacobians of function fields are available in two flavors. + +.. toctree:: + :maxdepth: 1 + + sage/rings/function_field/jacobian_base + sage/rings/function_field/jacobian_hess + sage/rings/function_field/jacobian_khuri_makdisi + sage/rings/function_field/khuri_makdisi + A Support Module ---------------- diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 4c2d05b1ec7..24b0a47324c 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3181,6 +3181,9 @@ REFERENCES: Cryptanalysis* ; 2002' available at http://www.engr.mun.ca/~howard/PAPERS/ldc_tutorial.pdf +.. [Hes2004] Florian Hess, "Computing relations in divisor class groups of + algebraic curves over finite fields," Preprint, 2004. + .. [Hes2002] Florian Hess, "Computing Riemann-Roch spaces in algebraic function fields and related topics," J. Symbolic Comput. 33 (2002), no. 4, 425--445. @@ -3776,6 +3779,9 @@ REFERENCES: block cipher*, Lightweight Cryptography Workshop, 2016. https://www.nist.gov/sites/default/files/documents/2016/10/18/karpman-paper-lwc2016.pdf +.. [Khu2004] \K. Khuri-Makdisi. *Linear algebra algorithms for divisors on an algebraic curve*, + Mathematics of Computation 73, no. 245 (2004) pp. 333-357. + .. [Kin1992] Nancy G. Kinnersley, *The vertex separation number of a graph equals its path-width*, Information Processing Letters 42(6):345-350, 1992. :doi:`10.1016/0020-0190(92)90234-M`. diff --git a/src/sage/categories/all.py b/src/sage/categories/all.py index 0be0369ef76..7393a5ee028 100644 --- a/src/sage/categories/all.py +++ b/src/sage/categories/all.py @@ -105,7 +105,7 @@ # schemes and varieties from sage.categories.modular_abelian_varieties import ModularAbelianVarieties -from sage.categories.schemes import Schemes, AbelianVarieties +from sage.categories.schemes import Schemes, AbelianVarieties, Jacobians # * with basis from sage.categories.modules_with_basis import ModulesWithBasis diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index 18ac6c211f4..c92d9d42d76 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -2598,6 +2598,7 @@ def category_sample(): Category of Hecke modules over Rational Field, Category of Hopf algebras over Rational Field, Category of Hopf algebras with basis over Rational Field, + Category of Jacobians over Rational Field, Category of Lie algebras over Rational Field, Category of Weyl groups, Category of abelian varieties over Rational Field, diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index 5b6d1939a54..f2d0170fd2d 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -2,14 +2,18 @@ r""" Schemes """ + # **************************************************************************** -# Copyright (C) 2005 David Kohel +# Copyright (C) 2013 David Kohel # William Stein -# 2008-2012 Nicolas M. Thiery +# 2008-2012 Nicolas M. Thiery # -# Distributed under the terms of the GNU General Public License (GPL) +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # https://www.gnu.org/licenses/ -# ***************************************************************************** +# **************************************************************************** from sage.categories.category import Category from sage.categories.category_types import Category_over_base @@ -156,9 +160,6 @@ def _call_(self, x): raise TypeError("No way to create an object or morphism in %s from %s" % (self, x)) -############################################################# -# Schemes over a given base scheme. -############################################################# class Schemes_over_base(Category_over_base): """ The category of schemes over a given base scheme. @@ -206,6 +207,7 @@ def _repr_object_names(self): else: return "schemes over %s" % self.base_scheme() + class AbelianVarieties(Schemes_over_base): r""" The category of abelian varieties over a given field. @@ -295,3 +297,27 @@ def extra_super_categories(self): True """ return [Rings()] + + +class Jacobians(AbelianVarieties): + """ + The category of Jacobians attached to curves or function fields. + """ + def super_categories(self): + """ + EXAMPLES:: + + sage: Jacobians(QQ).super_categories() + [Category of abelian varieties over Rational Field] + """ + return [AbelianVarieties(self.base_scheme())] + + def _repr_object_names(self): + """ + EXAMPLES:: + + sage: Jacobians(Spec(QQ)) # indirect doctest + Category of Jacobians over Rational Field + """ + return "Jacobians over %s" % self.base_scheme() + diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 02f2d0be604..958347113c0 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -2066,7 +2066,7 @@ def scalar_multiplication(self, x): sage: phi = DrinfeldModule(A, [z, 0, 1, z]) sage: phi Drinfeld module defined by T |--> z*t^3 + t^2 + z - sage: phi.hom(T) + sage: phi.hom(T) # indirect doctest Endomorphism of Drinfeld module defined by T |--> z*t^3 + t^2 + z Defn: z*t^3 + t^2 + z diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 0ef020bad9a..0c46e4cb94e 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -1367,3 +1367,102 @@ def extension_constant_field(self, k): """ from .extensions import ConstantFieldExtension return ConstantFieldExtension(self, k) + + @cached_method + def jacobian(self, model=None, base_div=None, **kwds): + """ + Return the Jacobian of the function field. + + INPUT: + + - ``model`` -- (default: ``'hess'``) model to use for arithmetic + + - ``base_div`` -- an effective divisor + + The degree of the base divisor should satisfy certain degree condition + corresponding to the model used. The following table lists these + conditions. Let `g` be the genus of the function field. + + - ``hess``: ideal-based arithmetic; requires base divisor of degree `g` + + - ``km_large``: Khuri-Makdisi's large model; requires base divisor of + degree at least `2g + 1` + + - ``km_medium``: Khuri-Makdisi's medium model; requires base divisor of + degree at least `2g + 1` + + - ``km_small``: Khuri-Makdisi's small model requires base divisor of + degree at least `g + 1` + + We assume the function field has a rational place. If a base divisor is + not given, one is constructed using an arbitrary rational place. + + EXAMPLES:: + + sage: A. = AffineSpace(GF(5), 2) + sage: C = Curve(y^2*(x^3 - 1) - (x^3 - 2)) + sage: F = C.function_field() + sage: F.jacobian() + Jacobian of Function field in y defined by (x^3 + 4)*y^2 + 4*x^3 + 2 (Hess model) + + TESTS: + + sage: A. = AffineSpace(QQ, 2) + sage: C = Curve(y^2 - x^3 - 1, A).projective_closure() + sage: C.jacobian(model='hess') + Traceback (most recent call last): + ... + ValueError: failed to obtain a rational place; provide a base divisor + """ + from .place import FunctionFieldPlace + + if model is None: + model = 'hess' + + if base_div is None: + try: + base_place = self.get_place(1) + except AttributeError: + raise ValueError('failed to obtain a rational place; provide a base divisor') + if base_place is None: + raise ValueError('the function field has no rational place') + # appropriate base divisor is constructed below. + else: + if isinstance(base_div, FunctionFieldPlace): + base_div = base_div.divisor() + + g = self.genus() + curve = kwds.get('curve') + + if model.startswith('km'): + from .jacobian_khuri_makdisi import Jacobian + if model == 'km' or model.endswith('large'): + if base_div is None: + base_div = (2*g + 1) * base_place + if not base_div.degree() >= 2*g + 1: + raise ValueError("Khuri-Makdisi large model requires base divisor of degree " + "at least 2*g + 1 for genus g") + return Jacobian(self, base_div, model='large', curve=curve) + elif model.endswith('medium'): + if base_div is None: + base_div = (2*g + 1) * base_place + if not base_div.degree() >= 2*g + 1: + raise ValueError("Khuri-Makdisi medium model requires base divisor of degree " + "at least 2*g + 1 for genus g") + return Jacobian(self, base_div, model='medium', curve=curve) + elif model.endswith('small'): + if base_div is None: + base_div = (g + 1) * base_place + if not base_div.degree() >= g + 1: + raise ValueError("Khuri-Makdisi small model requires base divisor of degree " + "at least g + 1 for genus g") + return Jacobian(self, base_div, model='small', curve=curve) + elif model == 'hess': + from .jacobian_hess import Jacobian + if base_div is None: + base_div = g * base_place + if base_div.degree() != g: + raise ValueError("Hess model requires base divisor of degree g for genus g") + return Jacobian(self, base_div, curve=curve) + + raise ValueError("unknown model") diff --git a/src/sage/rings/function_field/function_field_polymod.py b/src/sage/rings/function_field/function_field_polymod.py index 0fa7d1f3476..0218e6967f4 100644 --- a/src/sage/rings/function_field/function_field_polymod.py +++ b/src/sage/rings/function_field/function_field_polymod.py @@ -1926,6 +1926,50 @@ def residue_field(self, place, name=None): """ return place.residue_field(name=name) + def places_infinite(self, degree=1): + """ + Return a list of the infinite places with ``degree``. + + INPUT: + + - ``degree`` -- positive integer (default: `1`) + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: F. = GF(2) + sage: K. = FunctionField(F) + sage: R. = PolynomialRing(K) + sage: L. = K.extension(t^4 + t - x^5) + sage: L.places_infinite(1) + [Place (1/x, 1/x^4*y^3)] + """ + return list(self._places_infinite(degree)) + + def _places_infinite(self, degree): + """ + Return a generator of *infinite* places with ``degree``. + + INPUT: + + - ``degree`` -- positive integer + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: F. = GF(2) + sage: K. = FunctionField(F) + sage: R. = PolynomialRing(K) + sage: L. = K.extension(t^4 + t - x^5) + sage: L._places_infinite(1) + + """ + Oinf = self.maximal_order_infinite() + for prime, _, _ in Oinf.decomposition(): + place = prime.place() + if place.degree() == degree: + yield place + class FunctionField_char_zero(FunctionField_simple): """ @@ -2159,50 +2203,6 @@ def _places_finite(self, degree): if place.degree() == degree: yield place - def places_infinite(self, degree=1): - """ - Return a list of the infinite places with ``degree``. - - INPUT: - - - ``degree`` -- positive integer (default: `1`) - - EXAMPLES:: - - sage: # needs sage.rings.finite_rings - sage: F. = GF(2) - sage: K. = FunctionField(F) - sage: R. = PolynomialRing(K) - sage: L. = K.extension(t^4 + t - x^5) - sage: L.places_infinite(1) - [Place (1/x, 1/x^4*y^3)] - """ - return list(self._places_infinite(degree)) - - def _places_infinite(self, degree): - """ - Return a generator of *infinite* places with ``degree``. - - INPUT: - - - ``degree`` -- positive integer - - EXAMPLES:: - - sage: # needs sage.rings.finite_rings - sage: F. = GF(2) - sage: K. = FunctionField(F) - sage: R. = PolynomialRing(K) - sage: L. = K.extension(t^4 + t - x^5) - sage: L._places_infinite(1) - - """ - Oinf = self.maximal_order_infinite() - for prime, _, _ in Oinf.decomposition(): - place = prime.place() - if place.degree() == degree: - yield place - def gaps(self): """ Return the gaps of the function field. diff --git a/src/sage/rings/function_field/jacobian_base.py b/src/sage/rings/function_field/jacobian_base.py new file mode 100644 index 00000000000..0fa7ba14c82 --- /dev/null +++ b/src/sage/rings/function_field/jacobian_base.py @@ -0,0 +1,796 @@ +r""" +Jacobians of function fields + +This module provides base classes for Jacobians of function fields. + +Jacobian +-------- + +The Jacobian of a function field is created by default in the Hess model, with +a base divisor of degree `g` the genus of the function field. The base divisor +is automatically chosen if not given. :: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: J = F.jacobian() + sage: J + Jacobian of Function field in z defined by z^3 + 23*y^2*z + 6 (Hess model) + sage: J.base_divisor().degree() + 1 + +Explicitly specify a model if you want Jacobians in different models. :: + + sage: J_km = F.jacobian(model='km_large') + sage: J_km + Jacobian of Function field in z defined by z^3 + 23*y^2*z + 6 (Khuri-Makdisi large model) + +Group of rational points +------------------------ + +The group of rational points of a Jacobian is created from the Jacobian. A +point of the Jacobian group is determined by a divisor of degree zero. To +represent the point, a divisor of the form `D-B` is selected where `D` is an +effective divisor of the same degree with the base divisor `B`. Hence the point +is simply represented by the divisor `D`. :: + + sage: G = J.group() + sage: G.order() + 30 + sage: pl1 = C([1,8,1]).place() + sage: pl2 = C([2,10,1]).place() + sage: p1 = G.point(pl1 - pl2) + sage: p1 + [Place (y + 1, z + 6)] + sage: p2 = G.point(pl2 - pl1) + sage: p2 + [Place (y + 28, z + 6)] + sage: p1 + p2 == G.zero() + True + sage: p1.order() + 5 + +We can get the corresponding point in the Jacobian in a different model. :: + + sage: p1km = J_km(p1) + sage: p1km.order() + 5 + sage: p1km + Point of Jacobian determined by + [ 1 0 0 0 0 0 11 0 0] + [ 0 1 0 0 0 0 18 0 0] + [ 0 0 1 0 0 0 11 0 0] + [ 0 0 0 1 0 0 18 1 0] + [ 0 0 0 0 1 0 25 0 19] + [ 0 0 0 0 0 1 8 8 0] + +AUTHORS: + +- Kwankyu Lee (2022-01-24): initial version + +""" + +# **************************************************************************** +# Copyright (C) 2022 Kwankyu Lee +# +# 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/ +# **************************************************************************** + +import math + +from sage.arith.misc import integer_floor, integer_ceil + +from sage.structure.parent import Parent +from sage.structure.element import ModuleElement + +from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups +from sage.categories.schemes import Jacobians +from sage.categories.pushout import ConstructionFunctor, pushout + +from sage.rings.integer_ring import IntegerRing +from sage.rings.integer import Integer + + +class JacobianPoint_base(ModuleElement): + """ + Abstract base class of points of Jacobian groups. + """ + pass + + +class JacobianPoint_finite_field_base(JacobianPoint_base): + """ + Points of Jacobians over finite fields. + """ + def order(self): + """ + Return the order of this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: b = F.get_place(1) + sage: pl = C([-1,2,1]).place() + sage: p = G.point(pl - b) + sage: p.order() + 15 + + ALGORITHM: Shanks' Baby Step Giant Step + """ + G = self.parent() + B = G._bound_on_order() + q = integer_ceil(B.sqrt()) + zero = G.zero() + + # baby steps + b = [zero] + g = self + for i in range(q - 1): + if g == zero: + return i + 1 + b.append(g) + g = g + self + + # giant steps + g0 = self.multiple(-q) + g = g0 + for i in range(q - 1): + for r in range(q): + if g == b[r]: + return q * (i + 1) + r + g = g + g0 + + # order is neither smaller or nor larger than this + return q**2 + + def frobenius(self): + """ + Return the image of the point acted by the Frobenius automorphism. + + EXAMPLES:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='hess') + sage: G1 = J.group() + sage: G1.order() + 11 + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: pts1 = G1.get_points(11) + sage: pts3 = G3.get_points(12) + sage: pt = next(pt for pt in pts3 if pt not in pts1) + sage: pt.frobenius() == pt + False + sage: pt.frobenius().frobenius().frobenius() == pt + True + """ + G = self.parent() + return G._frobenius_on(self) + + +class JacobianGroupFunctor(ConstructionFunctor): + """ + A construction functor for Jacobian groups. + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: G = J.group() + sage: F, obj = G.construction() + sage: F + JacobianGroupFunctor + """ + rank = 20 + + def __init__(self, base_field, field): + """ + Initialize. + + TESTS:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: K = k.extension(2) + sage: G = J.group(K) + sage: F, obj = G.construction() + sage: TestSuite(F).run() + """ + super().__init__(Jacobians(base_field), CommutativeAdditiveGroups()) + + self._field = field + + def _apply_functor(self, jacobian): + """ + Apply this functor to ``jacobian``. + + INPUT: + + - ``jacobian`` -- a Jacobian + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: K = k.extension(2) + sage: G = J.group(K) + sage: F, obj = G.construction() + sage: F(obj) is G # indirect doctest + True + """ + return jacobian.group(self._field) + + def merge(self, other): + """ + Return the functor merging ``self`` and ``other`` + + INPUT: + + - ``other`` -- a functor + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: K2 = k.extension(2) + sage: G2 = J.group(K2) + sage: K3 = k.extension(3) + sage: G3 = J.group(K3) + sage: sage.categories.pushout.pushout(G2, G3) # indirect doctest + Group of rational points of Jacobian over Finite Field in z6 of size 7^6 (Hess model) + """ + if not isinstance(other, JacobianGroupFunctor): + return None + if not self.domain() == other.domain(): + return None + K = pushout(self._field, other._field) + return JacobianGroupFunctor(self.domain().base(), K) + + +class JacobianGroup_base(Parent): + """ + Groups of rational points of Jacobians. + + INPUT: + + - ``parent`` -- a Jacobian + + - ``function_field`` -- a function field + + - ``base_div`` -- an effective divisor of the function field + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: J.group() + Group of rational points of Jacobian over Finite Field of size 7 (Hess model) + """ + _embedding_map_class = None + + def __init__(self, parent, function_field, base_div): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: G = J.group() + sage: TestSuite(G).run(skip=['_test_elements', '_test_pickling']) + """ + super().__init__(base=IntegerRing(), category=CommutativeAdditiveGroups()) + + self._parent = parent + self._function_field = function_field + self._genus = parent._function_field.genus() # equals function_field.genus() + self._base_div = base_div + + def _repr_(self): + """ + Return the string representation of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: J.group() + Group of rational points of Jacobian over Finite Field of size 7 (Hess model) + """ + F = self._function_field + k = F.constant_base_field() + return f'Group of rational points of Jacobian over {k}' + + def _coerce_map_from_(self, S): + """ + Return the coerce map from ``S`` if ``S`` is embedded to ``self``. + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: G3.has_coerce_map_from(G1) + True + """ + if isinstance(S, JacobianGroup_base) and S.parent() is self.parent(): + K = self._function_field.constant_base_field() + k = S._function_field.constant_base_field() + if K.has_coerce_map_from(k): + return self._embedding_map_class(S, self) + return None + + def construction(self): + """ + Return the data for a functorial construction of this Jacobian group. + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: K2 = k.extension(2) + sage: G2 = J.group(K2) + sage: K3= k.extension(3) + sage: G3 = J.group(K3) + sage: p1, p2 = G2.get_points(2) + sage: q1, q2 = G3.get_points(2) + sage: (p1 + q1).parent() is (p2 + q2).parent() + True + """ + k = self._parent._function_field.constant_base_field() + K = self._function_field.constant_base_field() + return (JacobianGroupFunctor(k, K), self._parent) + + def parent(self): + """ + Return the Jacobian to which this Jacobian group belongs. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: G = J.group() + sage: G.parent() + Jacobian of Projective Plane Curve over Finite Field of size 7 + defined by x^3 - y^2*z - 2*z^3 (Hess model) + """ + return self._parent + + def function_field(self): + """ + Return the function field to which this Jacobian group attached. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='hess') + sage: G = J.group() + sage: G.function_field() + Function field in z defined by z^3 + 4*y^2*z + 3 + """ + return self._function_field + + def base_divisor(self): + """ + Return the base divisor that is used to represent points of this group. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: G.base_divisor() + Place (1/y, 1/y*z) + sage: _ == 1*b + True + + The base divisor is the denominator (negative part) of the divisor of + degree zero that represents a point. :: + + sage: p = C([-1,2,1]).place() + sage: G.point(p - b).divisor() + - Place (1/y, 1/y*z) + + Place (y + 2, z + 1) + """ + return self._base_div + + +class JacobianGroup_finite_field_base(JacobianGroup_base): + """ + Jacobian groups of function fields over finite fields. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: J.group() + Group of rational points of Jacobian over Finite Field of size 7 (Hess model) + """ + def _bound_on_order(self): + """ + Return an upper bound on the order of the abelian group. + + This bound depends on the genus and the order of the constant field + of the function field. This simple bound is from [Hes2004]_. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: G._bound_on_order() + 23 + """ + F = self._function_field + q = F.constant_base_field().order() + g = self._genus + + c = 2*g/(q.sqrt() - 1) + return integer_floor(math.exp(c)*q**g) + + def order(self, algorithm='numeric'): + """ + Return the order of the Jacobian group. + + INPUT: + + - ``algorithm`` -- ``'numeric'`` (default) or ``'algebraic'`` + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: G.order() + 7 + """ + F = self._parent._function_field + g = F.genus() + b = self._function_field.constant_base_field().degree() // F.constant_base_field().degree() + + f = F.L_polynomial() + + if algorithm == 'numeric': + # numeric method - fast but might be inaccurate by numerical noise + from sage.rings.qqbar import AlgebraicField + h = Integer(math.prod([(1-a**(-b))**m for a, m in f.change_ring(AlgebraicField()).roots()])) + return h + + # algebraic method - slow + + es = [] + s = -1 + for i in range(1, 2*g + 1): + es.append(s*f[i]) + s = -s + es + + ps = [es[0]] + for i in range(1, 2*g): + p = 0 + s = 1 + for j in range(i): + p = p + s*es[j]*ps[-j-1] + s = -s + ps.append(p + s*(i + 1)*es[i]) + + while len(ps) < b*2*g: + p = 0 + s = 1 + for j in range(2*g): + p = p + s*es[j]*ps[-j-1] + s = -s + ps.append(p) + + qs = [ps[b*(i + 1) - 1] for i in range(2*g)] + + fs = [qs[0]] + for i in range(1, 2*g): + k = qs[i] + s = -1 + for j in range(i): + k = k + s*fs[j]*qs[i - j - 1] + s = -s + fs.append(-s*k // (i + 1)) + + bs = [1] + s = -1 + for i in range(2*g): + bs.append(s*fs[i]) + s = -s + + return sum(bs) + + def get_points(self, n): + """ + Return `n` points of the Jacobian group. + + If `n` is greater than the order of the group, then returns + all points of the group. + + INPUT: + + - ``n`` -- an integer + + EXAMPLES:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='hess') + sage: G = J.group() + sage: pts = G.get_points(G.order()) + sage: len(pts) + 11 + """ + lst = [] + S = iter(self) + try: + for i in range(n): + lst.append(next(S)) + except StopIteration: + pass + + return lst + + +class Jacobian_base(Parent): + """ + Jacobians of function fields. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: F.jacobian() + Jacobian of Function field in y defined by y^2 + y + (x^2 + 1)/x (Hess model) + """ + def __init__(self, function_field, base_div, **kwds): + """ + Initialize. + + TESTS:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J = F.jacobian() + sage: TestSuite(J).run() + """ + self._function_field = function_field + self._base_div = base_div + self._system = {} + self._base_place = None + self._curve = kwds.get('curve') + super().__init__(category=Jacobians(function_field.constant_base_field()), + base=function_field.constant_base_field(), + facade=True) + + def _repr_(self): + """ + Return the string representation of ``self``. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: F.jacobian() + Jacobian of Function field in y defined by y^2 + y + (x^2 + 1)/x (Hess model) + """ + if self._curve is not None: + F = self._curve + else: + F = self._function_field + return f'Jacobian of {F}' + + def _an_element_(self): + """ + Return an element of ``self``. + + TESTS:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J = F.jacobian() + sage: J.an_element() + [Place (1/x, 1/x*y)] + """ + return next(iter(self.group())) + + def __call__(self, x): + """ + Return the point of ``self`` constructed from ``x`` + + It is assumed that ``self`` and ``x`` are points of the Jacobians + attached to the same function field. + + TESTS:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J_hess = F.jacobian(model='hess') + sage: G = J_hess.group() + sage: p = G.get_points(3)[2] + sage: Jkm = F.jacobian(model='km_large') + sage: q = Jkm(p) + sage: p.order() == q.order() + True + sage: J_hess(q) == p + True + """ + F = self._function_field + if isinstance(x, JacobianPoint_base): + Gx = x.parent() + Jx = Gx.parent() + if Jx._function_field is F: + k = Gx._function_field.constant_base_field() + G = self.group(k) + K = G._function_field + return G.point(K.divisor_group()(x.divisor())) + if x in F.place_set(): + return self(x - x.degree()*self._base_place) + if x == 0: + return self.group().zero() + if x in F.divisor_group(): + G = self.group() + return G.point(x) + raise ValueError(f"Cannot create a point of the Jacobian from {x}") + + def curve(self): + """ + Return the projective curve to which this Jacobian is attached. + + If the Jacobian was constructed from a function field, then returns nothing. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J = F.jacobian() + sage: J.curve() + """ + return self._curve + + def facade_for(self): + """ + Return the system of groups that this Jacobian is a facade for. + + The Jacobian can be seen as a facade for all groups of rational points + over field extensions of the base constant field of the function field. + This method returns only the internally constructed system of such + groups. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J = F.jacobian() + sage: J.facade_for() + [Group of rational points of Jacobian over Finite Field of size 2 (Hess model)] + """ + if not self._system: + return [self.group()] + return list(self.group(k) for k in self._system) + + def base_divisor(self): + """ + Return the base divisor used to construct the Jacobian. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: b = F.get_place(1) + sage: J = F.jacobian(base_div=b) + sage: J.base_divisor() == b + True + """ + return self._base_div + + def group(self, k_ext=None): + """ + Return the group of rational points of the Jacobian. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: b = F.get_place(1) + sage: J = F.jacobian(base_div=b) + sage: J.group() + Group of rational points of Jacobian over Finite Field of size 2 (Hess model) + """ + F = self._function_field + k = F.constant_base_field() + + if k_ext in self._system: + return self._system[k_ext][0] + + if k_ext is None or k_ext is k: + ext = F.extension_constant_field(k) + grp = self._group_class(self, F, self._base_div) + if self._base_place is not None: + grp._base_place = self._base_place + self._system[k] = (grp, ext) + else: + ext = F.extension_constant_field(k_ext) + base_div = ext.conorm_divisor(self._base_div) + grp = self._group_class(self, ext.top(), base_div) + if self._base_place is not None: + grp._base_place = ext.conorm_place(self._base_place) + self._system[k_ext] = (grp, ext) + + return grp + + def set_base_place(self, place): + """ + Set ``place`` as the base place. + + INPUT: + + - ``place`` -- a rational place of the function field. + + The base place `B` is used to map a rational place `P` of the function + field to the point of the Jacobian defined by the divisor `P - B`. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J = F.jacobian() + sage: B = F.get_place(1) + sage: J.set_base_place(B) + sage: Q = F.places()[-1] + sage: J(Q) + [Place (x + 1, x*y + 1)] + sage: J(Q).parent() + Group of rational points of Jacobian over Finite Field of size 2 (Hess model) + sage: J(B) + [Place (x, x*y)] + sage: J(B).is_zero() + True + """ + self._base_place = place + + for k in self._system: + grp, ext = self._system[k] + grp._base_place = ext.conorm_place(place) diff --git a/src/sage/rings/function_field/jacobian_hess.py b/src/sage/rings/function_field/jacobian_hess.py new file mode 100644 index 00000000000..54980870b37 --- /dev/null +++ b/src/sage/rings/function_field/jacobian_hess.py @@ -0,0 +1,1046 @@ +r""" +Jacobians in Hess model + +This module implements Jacobian arithmetic based on divisor representation by +ideals. This approach to Jacobian arithmetic implementation is attributed to +Hess [Hes2002]_. + +Jacobian +-------- + +To create a Jacobian in Hess model, specify ``'hess'`` model and provide a base divisor +of degree `g`, which is the genus of the function field:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: C.geometric_genus() + 1 + sage: B = C([0,1,0]).place() + sage: B.degree() + 1 + sage: J = C.jacobian(model='hess', base_div=B) + sage: J + Jacobian of Projective Plane Curve over Finite Field of size 29 + defined by x^3 - y^2*z + 5*z^3 (Hess model) + +Group of rational points +------------------------ + +The group of rational points of a Jacobian is created from the Jacobian. A +point of the Jacobian group is determined by a divisor (of degree zero) of the +form `D - B` where `D` is an effective divisor of degree `g` and `B` is the base +divisor. Hence a point of the Jacobian group is represented by `D`. + +:: + + sage: G = J.group() + sage: P1 = C([1,8,1]).place() + sage: P2 = C([2,10,1]).place() + sage: p1 = G(P1) + sage: p2 = G(P2) + sage: p1 + [Place (y + 21, z + 28)] + sage: p2 + [Place (y + 24, z + 14)] + sage: p1 + p2 + [Place (y + 8, z + 28)] + +AUTHORS: + +- Kwankyu Lee (2022-01-24): initial version + +""" + +# **************************************************************************** +# Copyright (C) 2022 Kwankyu Lee +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.misc.cachefunc import cached_method + +from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.richcmp import op_EQ, richcmp + +from sage.categories.map import Map +from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups +from sage.categories.homset import Hom + +from sage.arith.misc import integer_ceil +from sage.arith.functions import lcm + +from sage.rings.integer import Integer +from sage.matrix.constructor import matrix + +from sage.combinat.integer_vector_weighted import WeightedIntegerVectors + +from .place import FunctionFieldPlace +from .divisor import FunctionFieldDivisor + +from .jacobian_base import (Jacobian_base, + JacobianGroup_base, + JacobianGroup_finite_field_base, + JacobianPoint_base, + JacobianPoint_finite_field_base) + + +class JacobianPoint(JacobianPoint_base): + """ + Points of Jacobians represented by a pair of ideals. + + If a point of Jacobian is determined by `D`, then the divisor `D` is + represented by a pair of ideals in the finite maximal order and the + infinite maximal order of the function field. + + For efficiency reasons, the actual ideals stored are the inverted ideals + of the ideals representing the divisor `D`. + + INPUT: + + - ``parent`` -- Jacobian group + + - ``dS`` -- an ideal of the finite maximal order of a function field + + - ``ds`` -- an ideal of infinite maximal order of a function field + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl = C([1,8,1]).place() + sage: p = G.point(pl - b) + sage: dS, ds = p._data + sage: -(dS.divisor() + ds.divisor()) == pl + True + """ + def __init__(self, parent, dS, ds): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl = C([1,8,1]).place() + sage: p = G.point(pl - b) + sage: TestSuite(p).run(skip=['_test_category','_test_pickling']) + """ + super().__init__(parent) + self._data = (dS, ds) + + def _repr_(self): + """ + Return the string representation of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: G.zero() + [Place (1/y, 1/y*z)] + """ + dS, ds = self._data + divisor = (~dS).divisor() + (~ds).divisor() + return f'[{divisor}]' + + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^3 - x^2*(x^2 + x + 1)^2) + sage: f = x/(y + 1) + sage: d = f.divisor() + sage: {d: 1} + {Place (1/x, 1/x^4*y^2 + 1/x^2*y + 1) + + Place (1/x, 1/x^2*y + 1) + + 3*Place (x, (1/(x^3 + x^2 + x))*y^2) + - 6*Place (x + 1, y + 1): 1} + """ + return hash(self._data) + + def _richcmp_(self, other, op): + """ + Compare ``self`` with ``other`` with respect to operator ``op``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([2,10,1]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 == p1 + True + sage: p1 != p2 + True + sage: p1 > p1 + False + sage: p1 > p2 + False + sage: p1 < p2 + True + """ + if op is op_EQ: + J = self.parent() + idS, ids = self._data + jdS, jds = other._data + return J._normalize(idS / jdS, ids / jds) is not None + else: + return richcmp(self._data, other._data, op) + + def _add_(self, other): + """ + Return the sum of ``self`` and ``other``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([2,10,1]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + p2 + [Place (y + 8, z + 3)] + sage: p1 + p2 == p2 + p1 + True + """ + G = self.parent() + idS, ids = self._data + jdS, jds = other._data + bdS, bds = G._base_point + dS, ds = G._normalize(idS * jdS * bdS, ids * jds * bds) + return G.element_class(self.parent(), dS, ds) + + def _neg_(self): + """ + Return the negative of this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl = C([-1,2,1]).place() + sage: p = G.point(pl - b) + sage: -p + [Place (y + 27, z + 1)] + sage: -(-p) == p + True + """ + G = self.parent() + idS, ids = self._data + bdS2, bds2 = G._base_point_double + dS, ds = G._normalize(~(idS * bdS2), ~(ids * bds2)) + return G.element_class(self.parent(), dS, ds) + + def multiple(self, n): + """ + Return the ``n``-th multiple of this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl = C([-1,2,1]).place() + sage: p = G.point(pl - b) + sage: p.multiple(100) + [Place (1/y, 1/y*z + 8)] + """ + if n == 0: + return self.parent().zero() + + G = self.parent() + idS, ids = self._data + bdS, bds = G._base_point + bdS2, bds2 = G._base_point_double + idSbdS2 = idS * bdS2 + idsbds2 = ids * bds2 + + if n < 0: + bits = Integer(-n).digits(2) + else: + bits = Integer(n).digits(2) + bits.pop() + + dS = idS + ds = ids + for i in range(len(bits)): + b = bits.pop() + if b > 0: + dS, ds = G._normalize(dS * dS * idSbdS2 , ds * ds * idsbds2) + else: + dS, ds = G._normalize(dS * dS * bdS, ds * ds * bds) + if n < 0: + dS, ds = G._normalize(~(dS * bdS2), ~(ds * bds2)) + + return G.element_class(self.parent(), dS, ds) + + def addflip(self, other): + """ + Return the addflip of this and ``other`` point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([2,19,1]).place() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1.addflip(p2) + [Place (y + 8, z + 27)] + sage: _ == -(p1 + p2) + True + """ + return -(self + other) + + def defining_divisor(self): + """ + Return the effective divisor that defines this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl = C([-1,2,1]).place() + sage: p = G.point(pl - b) + sage: p.defining_divisor() == pl + True + """ + dS, ds = self._data + return (~dS).divisor() + (~ds).divisor() + + def order(self, bound=None): + """ + Return the order of this point. + + ALGORITHM: Shanks' Baby Step Giant Step + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: p = C([-1,2,1]).place() + sage: pt = G.point(p - b) + sage: pt.order() + 30 + """ + if bound is None: # naive + J = self.parent() + zero = J.zero() + + m = self + r = 1 + while m != zero: + m = m + self + r += 1 + return r + + # if bound is given, deploy Shanks' Baby Step Giant Step + + J = self.parent() + B = J.bound_on_order() + q = integer_ceil(B.sqrt()) + zero = J.zero() + + # baby steps + b = [zero] + g = self + for i in range(q - 1): + if g == zero: + return i + 1 + b.append(g) + g = g + self + + # giant steps + g0 = (-q)*(self) + g = g0 + for i in range(q - 1): + for r in range(q): + if g == b[r]: + return q * (i + 1) + r + g = g + g0 + + # order is neither smaller or nor larger than this + return q**2 + + def divisor(self): + """ + Return the divisor representing this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: pl = C([-1,2,1]).place() + sage: p = G.point(pl - b) + sage: G.point(p.divisor()) == p + True + """ + J = self.parent() + dS, ds = self._data + return (~dS).divisor() + (~ds).divisor() - J._base_div + + +class JacobianPoint_finite_field(JacobianPoint, JacobianPoint_finite_field_base): + """ + Points of Jacobians over finite fields + """ + pass + + +class JacobianGroupEmbedding(Map): + """ + Embeddings between Jacobian groups. + + INPUT: + + - ``base_group`` -- Jacobian group over a base field + + - ``extension_group`` -- Jacobian group over an extension field + + EXAMPLES:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: G3.coerce_map_from(G1) + Jacobian group embedding map: + From: Group of rational points of Jacobian + over Finite Field of size 17 (Hess model) + To: Group of rational points of Jacobian + over Finite Field in z3 of size 17^3 (Hess model) + """ + def __init__(self, base_group, extension_group): + """ + Initialize. + + TESTS:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: map = G3.coerce_map_from(G1) + sage: TestSuite(map).run(skip=['_test_category', '_test_pickling']) + """ + F = base_group._function_field + F_base = F.base_field() + K = F.constant_base_field() + + F_ext = extension_group._function_field + F_ext_base = F_ext.base_field() + K_ext = F_ext.constant_base_field() + + # construct embedding of F into F_ext + embedK = K_ext.coerce_map_from(K) + embedF_base = F_base.hom(F_ext_base.gen(), embedK) + if F.degree() > 1: + embedF = F.hom(F_ext.gen(), embedF_base) + else: + embedF = embedF_base + + self._embedF = embedF + self._O_ext = F_ext.maximal_order() + self._Oinf_ext = F_ext.maximal_order_infinite() + + Map.__init__(self, Hom(base_group, extension_group, CommutativeAdditiveGroups())) + + def _repr_type(self): + """ + Return string representation of ``self``. + + TESTS:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: G3.coerce_map_from(G1) # indirect doctest + Jacobian group embedding map: + From: Group of rational points of Jacobian + over Finite Field of size 17 (Hess model) + To: Group of rational points of Jacobian + over Finite Field in z3 of size 17^3 (Hess model) + """ + return 'Jacobian group embedding' + + def _call_(self, x): + """ + Conorm map from F to F_ext. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k, 2) + sage: C = Curve(y^5 - x^3 - 2*x - 1).projective_closure() + sage: J = C.jacobian(model='hess') + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: m = G3.coerce_map_from(G1) + sage: m(G1.zero()) == G3.zero() + True + """ + embedF = self._embedF + O_ext = self._O_ext + Oinf_ext = self._Oinf_ext + + idS,ids = x._data + dS = O_ext.ideal([embedF(g) for g in idS.gens()]) + ds = Oinf_ext.ideal([embedF(g) for g in ids.gens()]) + return self.codomain().element_class(self.codomain(), dS, ds) + + +class JacobianGroup(UniqueRepresentation, JacobianGroup_base): + """ + Groups of rational points of a Jacobian. + + INPUT: + + - ``parent`` -- a Jacobian + + - ``function_field`` -- a function field + + - ``base_div`` -- an effective divisor of the function field + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: J.group() + Group of rational points of Jacobian + over Finite Field of size 17 (Hess model) + """ + Element = JacobianPoint + _embedding_map_class = JacobianGroupEmbedding + + def __init__(self, parent, function_field, base_div): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: TestSuite(G).run(skip=['_test_elements', '_test_pickling']) + """ + super().__init__(parent, function_field, base_div) + + bdS, bds = self._get_dS_ds(-base_div) + try: + bdS._gens_two() # speed up multiplication with these ideals + bds._ideal._gens_two() # by storing vector forms of two generators + except AttributeError: + pass + self._base_point = (bdS, bds) + self._base_point_double = (bdS * bdS, bds * bds) + + self._base_place = None + + def _repr_(self): + """ + Return the string representation of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: J.group() + Group of rational points of Jacobian + over Finite Field of size 17 (Hess model) + """ + r = super()._repr_() + return r + ' (Hess model)' + + def _element_constructor_(self, x): + """ + Construct an element of ``self`` from ``x``. + + If ``x`` is an effective divisor, then it is assumed to of + degree `g`, the genus of the function field. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: G = C.jacobian(model='hess', base_div=b).group() + sage: G(0) + [Place (1/y, 1/y*z)] + """ + if x == 0: + return self.zero() + + if isinstance(x, FunctionFieldPlace): + if (self._base_place is not None + and x in self._function_field.place_set() + and x.degree() == 1): + x = x - self._base_place + else: + x = x.divisor() + + if (isinstance(x, FunctionFieldDivisor) + and x in self._function_field.divisor_group()): + if x.degree() == 0: + return self.point(x) + if x.is_effective(): + return self.element_class(self, *self._get_dS_ds(x)) + + raise ValueError(f"Cannot construct a point from {x}") + + def _get_dS_ds(self, divisor): + """ + Return (dS,ds) representation of the divisor. + + TESTS:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: pl = C([2,8,1]).place() + sage: dS, ds = G._get_dS_ds(2*pl) + sage: (~dS).divisor() + (~ds).divisor() == 2*pl + True + """ + F = self._function_field + O = F.maximal_order() + Oinf = F.maximal_order_infinite() + + I = O.ideal(1) + J = Oinf.ideal(1) + for p in divisor._data: + m = divisor._data[p] + if p.is_infinite_place(): + J *= p.prime_ideal() ** (-m) + else: + I *= p.prime_ideal() ** (-m) + + return I, J + + def _normalize(self, I, J): + """ + Return a pair of normalized ideals from `I` and `J`. + + INPUT: + + - ``I`` -- an ideal of the finite maximal order + + - ``J`` -- an ideal of the infinite maximal order + + The output represents an effective divisor linearly equivalent to the + divisor represented by the given ideals `I` and `J`. + + ALGORITHM: + + Computes a function `f` in the Riemann-Roch space of the divisor `D` + represented by the (inverted) ideals `I` and `J`. The output is the + pair of the (inverted) ideals representing the effective divisor `(f) + D`, + which is linearly equivalent to `D`. + + TESTS:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: pl = C([2,8,1]).place() + sage: p = G.point(pl - b) + sage: dS, ds = (p + p)._data # indirect doctest + sage: G.point((~dS).divisor() + (~ds).divisor() - b) == p + p + True + """ + F = self._function_field + n = F.degree() + + O = F.maximal_order() + Oinf = F.maximal_order_infinite() + + # Step 1: construct matrix M of rational functions in x such that + # M * B == C where B = [b1,b1,...,bn], C =[v1,v2,...,vn] + V,fr,to = F.free_module(map=True) + B = matrix([to(b) for b in J.gens_over_base()]) + C = matrix([to(v) for v in I.gens_over_base()]) + M = C * B.inverse() + + # Step 2: get the denominator d of M and set mat = d * M + den = lcm([e.denominator() for e in M.list()]) + R = den.parent() # polynomial ring + one = R.one() + mat = matrix(R, n, [e.numerator() for e in (den*M).list()]) + gens = list(I.gens_over_base()) + + # Step 3: transform mat to a weak Popov form, together with gens + + # initialise pivot_row and conflicts list + found = None + pivot_row = [[] for i in range(n)] + conflicts = [] + for i in range(n): + bestp = -1 + best = -1 + for c in range(n): + d = mat[i,c].degree() + if d >= best: + bestp = c + best = d + + if best <= den.degree(): + found = i + break + + if best >= 0: + pivot_row[bestp].append((i,best)) + if len(pivot_row[bestp]) > 1: + conflicts.append(bestp) + + if found is None: + # while there is a conflict, do a simple transformation + while conflicts: + c = conflicts.pop() + row = pivot_row[c] + i,ideg = row.pop() + j,jdeg = row.pop() + + if jdeg > ideg: + i,j = j,i + ideg,jdeg = jdeg,ideg + + coeff = - mat[i,c].lc() / mat[j,c].lc() + s = coeff * one.shift(ideg - jdeg) + + mat.add_multiple_of_row(i, j, s) + gens[i] += s * gens[j] + + row.append((j,jdeg)) + + bestp = -1 + best = -1 + for c in range(n): + d = mat[i,c].degree() + if d >= best: + bestp = c + best = d + + if best <= den.degree(): + found = i + break + + if best >= 0: + pivot_row[bestp].append((i,best)) + if len(pivot_row[bestp]) > 1: + conflicts.append(bestp) + else: + return None + + f = gens[found] + return (O.ideal(~f) * I, Oinf.ideal(~f) * J) + + def point(self, divisor): + """ + Return the point represented by the divisor of degree zero. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: p = C([-1,2,1]).place() + sage: G.point(p - b) + [Place (y + 2, z + 1)] + """ + c = divisor + self._base_div + f = c.basis_function_space()[0] + d = f.divisor() + c + dS, ds = self._get_dS_ds(d) + return self.element_class(self, dS, ds) + + @cached_method + def zero(self): + """ + Return the zero element of this group. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: G.zero() + [Place (1/y, 1/y*z)] + """ + bdS,bds = self._base_point + return self.element_class(self, ~bdS, ~bds) + + +class JacobianGroup_finite_field(JacobianGroup, JacobianGroup_finite_field_base): + """ + Jacobian groups of function fields over finite fields + + INPUT: + + - ``parent`` -- a Jacobian + + - ``function_field`` -- a function field + + - ``base_div`` -- an effective divisor of the function field + + EXAMPLES:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: G3.coerce_map_from(G1) + Jacobian group embedding map: + From: Group of rational points of Jacobian + over Finite Field of size 17 (Hess model) + To: Group of rational points of Jacobian + over Finite Field in z3 of size 17^3 (Hess model) + """ + Element = JacobianPoint_finite_field + + def __init__(self, parent, function_field, base_div): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: G = J.group() + sage: TestSuite(G).run(skip=['_test_elements','_test_pickling']) + """ + super().__init__(parent, function_field, base_div) + + F = self._function_field + K = F.constant_base_field() + + R = F.base_field() # base rational function field + x = R.gen() + y = F.gen() + + r = self._parent._function_field.constant_base_field().degree() + frob_K = K.frobenius_endomorphism(r) + frob_R = R.hom(x, base_morphism=frob_K) + frob_F = F.hom(y, base_morphism=frob_R) + + self._frobenius = frob_F + + def __iter__(self): + """ + Return generator of points of this group. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='hess') + sage: G = J.group() + sage: len([pt for pt in G]) + 11 + """ + g = self._parent._function_field.genus() + F = self._function_field + O = F.maximal_order() + Oinf = F.maximal_order_infinite() + + deg = 1 + support = [] + degrees = [] + multiples = [] + lst = [] + + places_infinite = F.places_infinite() + generators = [iter(places_infinite)] + num_of_infinite_places = len(places_infinite) + while True: + while True: + try: + new_pl = next(generators[-1]) + break + except StopIteration: + if deg > g: + return + generators.append(F._places_finite(deg)) + deg += 1 + multiples.append((g + 1)*[None]) + P = ~new_pl.prime_ideal() + dn = new_pl.degree() + I0 = O.ideal(1) + J0 = Oinf.ideal(1) + dr = 0 + for r in range(1, g // new_pl.degree() + 1): + if new_pl.is_infinite_place(): + J0 = J0 * P + else: + I0 = I0 * P + multiples[-1][r] = (I0, J0) + dr = dr + dn + for weights in WeightedIntegerVectors(g - dr, degrees): + I = I0 + J = J0 + for i in range(len(support)): + w = weights[i] + if w > 0: + dS, ds = multiples[i][w] + if i < num_of_infinite_places: + J *= ds # dS is the unit ideal + else: + I *= dS # ds is the unit ideal + pt = self.element_class(self, I, J) + if pt not in lst: + lst.append(pt) + yield pt + support.append(new_pl) + degrees.append(new_pl.degree()) + + def _frobenius_on(self, pt): + """ + Return the image of ``pt`` acted by the Frobenius automorphism. + + EXAMPLES:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='hess') + sage: G1 = J.group() + sage: G1.order() + 11 + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: pts1 = G1.get_points(11) + sage: pts3 = G3.get_points(12) + sage: pt = next(pt for pt in pts3 if pt not in pts1) + sage: pt.frobenius().frobenius().frobenius() == pt # indirect doctest + True + sage: pt.frobenius() == pt + False + """ + frob_F = self._frobenius + + F = self._function_field + O = F.maximal_order() + Oinf = F.maximal_order_infinite() + + idS,ids = pt._data + dS = O.ideal([frob_F(g) for g in idS.gens()]) + ds = Oinf.ideal([frob_F(g) for g in ids.gens()]) + return self.element_class(self, dS, ds) + + +class Jacobian(Jacobian_base, UniqueRepresentation): + """ + Jacobians of function fields. + + EXAMPLES:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: C.jacobian(model='hess', base_div=b) + Jacobian of Projective Plane Curve over Finite Field of size 17 + defined by x^3 - y^2*z + 5*z^3 (Hess model) + """ + def __init__(self, function_field, base_div, **kwds): + """ + Initialize. + + TESTS:: + + sage: k = GF(17) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: J = C.jacobian(model='hess', base_div=b) + sage: TestSuite(J).run(skip=['_test_elements','_test_pickling']) + """ + super().__init__(function_field, base_div, **kwds) + + if function_field.constant_base_field().is_finite(): + self._group_class = JacobianGroup_finite_field + else: + self._group_class = JacobianGroup + + def _repr_(self): + """ + Return the string representation of ``self``. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: C.jacobian(model='hess', base_div=b) + Jacobian of Projective Plane Curve over Finite Field of size 17 + defined by x^3 - y^2*z + 5*z^3 (Hess model) + """ + r = super()._repr_() + return r + ' (Hess model)' diff --git a/src/sage/rings/function_field/jacobian_khuri_makdisi.py b/src/sage/rings/function_field/jacobian_khuri_makdisi.py new file mode 100644 index 00000000000..eeb2ae12fd6 --- /dev/null +++ b/src/sage/rings/function_field/jacobian_khuri_makdisi.py @@ -0,0 +1,1029 @@ +r""" +Jacobians in Khuri-Makdisi model + +This module implements Jacobian arithmetic by Khuri-Makdisi's algorithms +[Khu2004]_ based on divisor representation by linear spaces. + +Jacobian +-------- + +There are three models for Jacobian arithmetic by Khuri-Makdisi's algorithms. +For each of the models, one should provide a base divisor satisfying certain +degree condition. The following lists the names of the three models and the +corresponding conditions on base divisors. Let `g` be the genus of the function +field. + +- ``km_large``: large model; requires an effective divisor of degree at least `2g + 1` + +- ``km_medium``: medium model; requires an effective divisor of degree at least `2g + 1` + +- ``km_small``: small model; requires an effective divisor of degree at least `g + 1` + +To create a Jacobian in this model, specify ``'km_[large|medium|small]'`` as ``model`` and +provide a base divisor satisfying the degree condition. + +EXAMPLES: + +We construct a function field (of a projective curve) over a finite field:: + + sage: P2. = ProjectiveSpace(GF(29), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: C.geometric_genus() + 1 + sage: H = C.function(y/x).divisor_of_poles() + sage: H.degree() + 3 + +Now we use `H` as base divisor for the large and medium models:: + + sage: J_large = C.jacobian(model='km_large', base_div=H) + sage: J_large + Jacobian of Projective Plane Curve over Finite Field of size 29 + defined by x^3 - y^2*z + 5*z^3 (Khuri-Makdisi large model) + sage: J_medium = C.jacobian(model='km_medium', base_div=H) + sage: J_medium + Jacobian of Projective Plane Curve over Finite Field of size 29 + defined by x^3 - y^2*z + 5*z^3 (Khuri-Makdisi medium model) + +and for the small model, we construct an effective divisor of degree 2:: + + sage: B = sum(H.support()[:2]) + sage: B.degree() + 2 + sage: J_small = C.jacobian(model='km_small', base_div=B) + sage: J_small + Jacobian of Projective Plane Curve over Finite Field of size 29 + defined by x^3 - y^2*z + 5*z^3 (Khuri-Makdisi small model) + +Group of rational points +------------------------ + +The group of rational points of a Jacobian is created from the Jacobian. A +point of the Jacobian group is represented by a divisor `D - B` where `D` is +an effective divisor of the same degree with the base divisor `B`. The +divisor `D` in turn is determined by a linear subspace of the Riemann-Roch +space associated with certain multiple of `B` (depending on the model). This +allows representing points of Jacobian as matrices once we fix a basis of the +Riemann-Roch space. + + +EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: H = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=H) + sage: G = J.group() + sage: D = C([0,1,0]).place() + sage: P1 = C([-1,2,1]).place() + sage: P2 = C([3,7,1]).place() + sage: p1 = G.point(P1 - D) + sage: p2 = G.point(P2 - D) + sage: p1 + Point of Jacobian determined by + [ 1 0 0 0 0 0 0 12 15] + [ 0 1 0 0 0 0 0 0 13] + [ 0 0 1 0 0 0 0 0 2] + [ 0 0 0 1 0 0 0 0 16] + [ 0 0 0 0 0 1 0 0 15] + [ 0 0 0 0 0 0 1 0 1] + sage: p2 + Point of Jacobian determined by + [ 1 0 0 0 0 0 0 12 5] + [ 0 1 0 0 0 0 0 0 2] + [ 0 0 1 0 0 0 0 0 13] + [ 0 0 0 1 0 0 0 0 8] + [ 0 0 0 0 0 1 0 0 10] + [ 0 0 0 0 0 0 1 0 14] + sage: p1 + p2 + Point of Jacobian determined by + [ 1 0 0 0 0 16 0 5 3] + [ 0 1 0 0 0 6 0 8 16] + [ 0 0 1 0 0 15 0 3 10] + [ 0 0 0 1 0 3 0 0 0] + [ 0 0 0 0 1 12 0 16 8] + [ 0 0 0 0 0 0 1 3 0] + +AUTHORS: + +- Kwankyu Lee (2022-01-24): initial version + +""" + +# **************************************************************************** +# Copyright (C) 2022 Kwankyu Lee +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.misc.cachefunc import cached_method + +from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.richcmp import op_EQ, richcmp + +from sage.categories.map import Map +from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups +from sage.categories.homset import Hom + +from sage.matrix.constructor import matrix + +from sage.combinat.integer_vector_weighted import WeightedIntegerVectors + +from .place import FunctionFieldPlace +from .divisor import FunctionFieldDivisor + +from .jacobian_base import (Jacobian_base, + JacobianGroup_base, + JacobianGroup_finite_field_base, + JacobianPoint_base, + JacobianPoint_finite_field_base) + + +class JacobianPoint(JacobianPoint_base): + """ + Points of a Jacobian group. + + INPUT: + + - ``parent`` -- Jacobian group + + - ``w`` -- matrix + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: pl = C([3,2,1]).place() + sage: G.point(pl - b) + Point of Jacobian determined by + [1 0 0 0 0 0 0 2 3] + [0 1 0 0 0 0 0 0 3] + [0 0 1 0 0 0 0 0 1] + [0 0 0 1 0 0 0 0 5] + [0 0 0 0 0 1 0 0 5] + [0 0 0 0 0 0 1 0 4] + + """ + def __init__(self, parent, w): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: pl = C([3,2,1]).place() + sage: p = G.point(pl - b) + sage: TestSuite(p).run(skip=['_test_category','_test_pickling']) + """ + super().__init__(parent) + w.set_immutable() + self._w = w + + def _repr_(self): + """ + Return the string representation of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: G.zero() + Point of Jacobian determined by + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 1 0] + """ + return f'Point of Jacobian determined by \n{self._w}' + + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: zero = G.zero() + sage: {zero: 1} + {Point of Jacobian determined by + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 1 0]: 1} + """ + return hash(self._w) + + def _richcmp_(self, other, op): + """ + Compare ``self`` with ``other`` with respect to operator ``op``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 == p1 + True + sage: p1 != p2 + True + sage: p1 > p1 + False + sage: p1 > p2 + True + sage: p1 < p2 + False + """ + if op is op_EQ: + km = self.parent()._km + return km.equal(self._w, other._w) + else: + return richcmp(self._w, other._w, op) + + def _add_(self, other): + """ + Return the sum of ``self`` and ``other``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + p2 + Point of Jacobian determined by + [1 0 0 0 0 0 3 1 1] + [0 1 0 0 0 0 3 0 2] + [0 0 1 0 0 0 0 3 0] + [0 0 0 1 0 0 0 0 3] + [0 0 0 0 1 0 4 0 3] + [0 0 0 0 0 1 6 5 2] + sage: p1 + p2 == p2 + p1 + True + """ + G = self.parent() + km = G._km + return G.element_class(self.parent(), km.add(self._w, other._w)) + + def _neg_(self): + """ + Return the negative of this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: b = F.get_place(1) + sage: p = C([-1,2,1]).place() + sage: pt = G.point(p - b) + sage: -pt + Point of Jacobian determined by + [1 0 0 0 0 0 1 6 0] + [0 1 0 0 0 0 2 6 3] + [0 0 1 0 0 0 4 1 1] + [0 0 0 1 0 0 1 4 1] + [0 0 0 0 1 0 5 2 6] + [0 0 0 0 0 1 3 1 3] + sage: -(-pt) == pt + True + """ + G = self.parent() + km = G._km + return G.element_class(self.parent(), km.negate(self._w)) + + def _rmul_(self, n): + """ + Return the ``n``-th multiple of this point. + + INPUT: + + - ``n`` -- an integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p = G.point(pl - b) + sage: 10*(10*p) == 100*p + True + """ + return self.multiple(n) + + def multiple(self, n): + """ + Return the ``n``-th multiple of this point. + + INPUT: + + - ``n`` -- an integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p = G.point(pl - b) + sage: p.multiple(100) + Point of Jacobian determined by + [1 0 0 0 0 2 0 1 1] + [0 1 0 0 0 5 0 1 6] + [0 0 1 0 0 2 0 6 3] + [0 0 0 1 0 1 0 0 0] + [0 0 0 0 1 5 0 1 4] + [0 0 0 0 0 0 1 1 0] + """ + G = self.parent() + km = G._km + return G.element_class(self.parent(), km.multiple(self._w, n)) + + def addflip(self, other): + """ + Return the addflip of this and ``other`` point. + + The addflip of two points is by definition the negative of the sum of + the points. This operation is faster than addition in Jacobian + arithmetic by Khuri-Makdisi algorithms. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1.addflip(p2) + Point of Jacobian determined by + [1 0 0 0 0 0 0 2 6] + [0 1 0 0 0 0 0 0 3] + [0 0 1 0 0 0 0 0 4] + [0 0 0 1 0 0 0 0 3] + [0 0 0 0 0 1 0 0 5] + [0 0 0 0 0 0 1 0 2] + sage: _ == -(p1 + p2) + True + """ + G = self.parent() + km = G._km + return G.element_class(self.parent(), km.addflip(self._w, other._w)) + + def defining_matrix(self): + """ + Return the matrix whose row span determines the effective divisor + representing this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: p = G.point(pl - b) + sage: p.defining_matrix() + [1 0 0 0 0 0 0 2 5] + [0 1 0 0 0 0 0 0 3] + [0 0 1 0 0 0 0 0 2] + [0 0 0 1 0 0 0 0 6] + [0 0 0 0 0 1 0 0 5] + [0 0 0 0 0 0 1 0 1] + """ + return self._w + + def divisor(self): + """ + Return the divisor representing this point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: b = F.get_place(1) + sage: p = C([-1,2,1]).place() + sage: pt = G.point(p - b) + sage: G.point(pt.divisor()) == pt + True + + ALGORITHM: Lemma 2.1 of [Khu2004]_. + """ + G = self.parent() + F = G._function_field + data = [G._from_L(f).divisor() for f in self._w.rows()] + supp = set() + for d in data: + supp.update(d.support()) + supp = list(supp) + d = F.divisor_group().zero() + for p in supp: + d += min(d.valuation(p) for d in data) * p.divisor() + return d + G._div_L - G._base_div + + +class JacobianPoint_finite_field(JacobianPoint, JacobianPoint_finite_field_base): + pass + + +class JacobianGroupEmbedding(Map): + """ + Embeddings between Jacobian groups. + + INPUT: + + - ``base_group`` -- Jacobian group over a base field + + - ``extension_group`` -- Jacobian group over an extension field + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: G3.coerce_map_from(G1) + Jacobian group embedding map: + From: Group of rational points of Jacobian + over Finite Field of size 7 (Khuri-Makdisi large model) + To: Group of rational points of Jacobian + over Finite Field in z3 of size 7^3 (Khuri-Makdisi large model) + """ + def __init__(self, base_group, extension_group): + """ + Initialize. + + TESTS:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: map = G3.coerce_map_from(G1) + sage: TestSuite(map).run(skip=['_test_category', '_test_pickling']) + """ + F_ext = extension_group._function_field + K_ext = F_ext.constant_base_field() + + self._K_ext = K_ext + + Map.__init__(self, Hom(base_group, extension_group, CommutativeAdditiveGroups())) + + def _repr_type(self): + """ + Return string representation of ``self``. + + TESTS:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: G3.coerce_map_from(G1) # indirect doctest + Jacobian group embedding map: + From: Group of rational points of Jacobian + over Finite Field of size 7 (Khuri-Makdisi large model) + To: Group of rational points of Jacobian + over Finite Field in z3 of size 7^3 (Khuri-Makdisi large model) + """ + return 'Jacobian group embedding' + + def _call_(self, x): + """ + Conorm map from F to F_ext. + + TESTS:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: m = G3.coerce_map_from(G1) + sage: m(G1.zero()) == G3.zero() + True + """ + w = (x._w).change_ring(self._K_ext) + + return self.codomain().element_class(self.codomain(), w) + + +class JacobianGroup(UniqueRepresentation, JacobianGroup_base): + """ + Groups of rational points of a Jacobian. + + INPUT: + + - ``parent`` -- a Jacobian + + - ``function_field`` -- a function field + + - ``base_div`` -- an effective divisor of the function field + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: J.group() + Group of rational points of Jacobian + over Finite Field of size 7 (Khuri-Makdisi large model) + """ + Element = JacobianPoint + _embedding_map_class = JacobianGroupEmbedding + + def __init__(self, parent, function_field, base_div): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + """ + super().__init__(parent, function_field, base_div) + + D0 = base_div + + self._V_cache = 10*[None] + + V_cache = self._V_cache + + def V(n): + if n in V_cache: + return V_cache[n] + + Vn, from_Vn, to_Vn = (n * D0).function_space() + V_cache[n] = (Vn, from_Vn, to_Vn) + + return Vn, from_Vn, to_Vn + + def mu(n, m, i, j): + Vn, from_Vn, to_Vn = V(n) + Vm, from_Vm, to_Vm = V(m) + Vnm, from_Vnm, to_Vnm = V(n + m) + return to_Vnm(from_Vn(Vn.gen(i)) * from_Vm(Vm.gen(j))) + + model = parent._model + + if model == 'large': + div_L = 3 * D0 + L, from_L, to_L = V(3) + from sage.rings.function_field.khuri_makdisi import KhuriMakdisi_large as KM + elif model == 'medium': + div_L = 2 * D0 + L, from_L, to_L = V(2) + from sage.rings.function_field.khuri_makdisi import KhuriMakdisi_medium as KM + elif model == 'small': + div_L = 3 * D0 + L, from_L, to_L = V(3) + from sage.rings.function_field.khuri_makdisi import KhuriMakdisi_small as KM + + self._div_L = div_L + self._L = L + self._from_L = from_L + self._to_L = to_L + + w0 = self.point(function_field.divisor_group().zero()).defining_matrix() + km = KM(lambda n: V(n)[0], mu, w0, D0.degree(), self._genus) + + self._km = km + self._w0 = w0 + + self._base_place = None + + def _repr_(self): + """ + Return the string representation of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: J.group() + Group of rational points of Jacobian + over Finite Field of size 7 (Khuri-Makdisi large model) + """ + r = super()._repr_() + return r + f' (Khuri-Makdisi {self._parent._model} model)' + + def _wd_from_divisor(self, x): + """ + Return the matrix representing the divisor ``x``. + + INPUT: + + - ``x`` -- an effective divisor + + TESTS: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_medium', base_div=h) + sage: G = J.group() + sage: P = C([-1,2,1]).place() + sage: G._wd_from_divisor(2*P) + [1 0 0 0 4 0] + [0 1 0 0 4 6] + [0 0 1 0 2 1] + [0 0 0 1 1 6] + """ + WD = (self._div_L - x).basis_function_space() + wd = matrix([self._to_L(f) for f in WD]) + wd.echelonize() + return wd + + def _element_constructor_(self, x): + """ + Construct an element of ``self`` from ``x``. + + If ``x`` is an effective divisor, then it is assumed to have the same + degree with the base divisor. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: G(0) + Point of Jacobian determined by + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 1 0] + sage: b = C([0,1,0]).place() + sage: J.set_base_place(b) + sage: p = C([-1,2,1]).place() + sage: G(p) + Point of Jacobian determined by + [1 0 0 0 0 0 0 2 5] + [0 1 0 0 0 0 0 0 3] + [0 0 1 0 0 0 0 0 2] + [0 0 0 1 0 0 0 0 6] + [0 0 0 0 0 1 0 0 5] + [0 0 0 0 0 0 1 0 1] + """ + if x == 0: + return self.zero() + + if isinstance(x, FunctionFieldPlace): + if (self._base_place is not None + and x in self._function_field.place_set() + and x.degree() == 1): + x = x - self._base_place + else: + x = x.divisor() + + if (isinstance(x, FunctionFieldDivisor) + and x in self._function_field.divisor_group()): + if x.degree() == 0: + return self.point(x) + if x.is_effective(): + wd = self._wd_from_divisor(x) + return self.element_class(self, wd) + + raise ValueError(f"Cannot construct a point from {x}") + + def point(self, divisor): + """ + Return the point represented by the divisor. + + INPUT: + + - ``divisor`` -- a divisor of degree zero + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: b = C([0,1,0]).place() + sage: p = C([-1,2,1]).place() + sage: G.point(p - b) + Point of Jacobian determined by + [1 0 0 0 0 0 0 2 5] + [0 1 0 0 0 0 0 0 3] + [0 0 1 0 0 0 0 0 2] + [0 0 0 1 0 0 0 0 6] + [0 0 0 0 0 1 0 0 5] + [0 0 0 0 0 0 1 0 1] + """ + if divisor.degree() != 0: + raise ValueError('divisor not of degree zero') + + c = divisor + self._base_div + f = c.basis_function_space()[0] + d = f.divisor() + c + + wd = self._wd_from_divisor(d) + return self.element_class(self, wd) + + @cached_method + def zero(self): + """ + Return the zero element of this group. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: G.zero() + Point of Jacobian determined by + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 1 0] + """ + return self.element_class(self, self._w0) + + +class JacobianGroup_finite_field(JacobianGroup, JacobianGroup_finite_field_base): + """ + Jacobian groups of function fields over finite fields. + + INPUT: + + - ``parent`` -- a Jacobian + + - ``function_field`` -- a function field + + - ``base_div`` -- an effective divisor of the function field + + EXAMPLES:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G1 = J.group() + sage: K = k.extension(2) + sage: G2 = J.group(K) + sage: G2.coerce_map_from(G1) + Jacobian group embedding map: + From: Group of rational points of Jacobian + over Finite Field of size 7 (Khuri-Makdisi large model) + To: Group of rational points of Jacobian + over Finite Field in z2 of size 7^2 (Khuri-Makdisi large model) + """ + Element = JacobianPoint_finite_field + + def __init__(self, parent, function_field, base_div): + """ + Initialize. + + TESTS:: + + sage: k = GF(7) + sage: P2. = ProjectiveSpace(k, 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: TestSuite(G).run(skip=['_test_elements', '_test_pickling']) + """ + super().__init__(parent, function_field, base_div) + + F = self._function_field + K = F.constant_base_field() + + r = self._parent._function_field.constant_base_field().degree() + frob_K = K.frobenius_endomorphism(r) + + self._frobenius_of_constant_field = frob_K + + def __iter__(self): + """ + Return generator of points of this group. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: b = C([0,0,1]).place() + sage: J = C.jacobian(model='km_large', base_div=3*b) + sage: G = J.group() + sage: len([pt for pt in G]) + 11 + """ + d0 = self._base_div.degree() + F = self._function_field + + zero_divisor = self._km.zero_divisor() + deg = 1 + support = [] + degrees = [] + multiples = [] + lst = [] + + places_infinite = F.places_infinite() + generators = [iter(places_infinite)] + while True: + while True: + try: + new_pl = next(generators[-1]) + break + except StopIteration: + if deg > d0: + return + generators.append(F._places_finite(deg)) + deg += 1 + multiples.append((d0 + 1)*[None]) + wn = self._wd_from_divisor(new_pl.divisor()) + dn = new_pl.degree() + wr = zero_divisor + dr = 0 + for r in range(1, d0 // dn + 1): + wr = self._km.add_divisor(wr, wn, dr, dn) + multiples[-1][r] = wr + dr += dn + for weights in WeightedIntegerVectors(d0 - dr, degrees): + d = dr + wD = wr + for i in range(len(support)): + w = weights[i] + if w > 0: + m = w * degrees[i] + wD = self._km.add_divisor(wD, multiples[i][w], d, m) + d += m + pt = self.element_class(self, wD) + if pt not in lst: + lst.append(pt) + yield pt + support.append(new_pl) + degrees.append(new_pl.degree()) + + def _frobenius_on(self, pt): + """ + Return the image of ``pt`` acted by the Frobenius automorphism. + + INPUT: + + - ``pt`` -- a point of ``self`` + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: b = C([0,0,1]).place() + sage: J = C.jacobian(model='km_large', base_div=3*b) + sage: G1 = J.group() + sage: K = k.extension(3) + sage: G3 = J.group(K) + sage: pt = G3.get_points(12)[-2] # expected to be a point rational over K + sage: pt.frobenius().frobenius().frobenius() == pt # indirect doctest + True + """ + w = pt._w.apply_morphism(self._frobenius_of_constant_field) + return self.element_class(self, w) + + +class Jacobian(UniqueRepresentation, Jacobian_base): + """ + Jacobians implemented by Khuri-Makdisi's algorithms. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: C.jacobian(model='km') + Jacobian of Projective Plane Curve over Finite Field of size 7 + defined by x^3 - y^2*z - 2*z^3 (Khuri-Makdisi large model) + """ + def __init__(self, function_field, base_div, model, **kwds): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='km_large') + sage: TestSuite(J).run(skip=['_test_elements', '_test_pickling']) + + :: + + sage: J = C.jacobian(model='km_unknown') + Traceback (most recent call last): + ... + ValueError: unknown model + """ + super().__init__(function_field, base_div, **kwds) + + if model not in ['large', 'medium', 'small']: + raise ValueError('unknown model') + + self._model = model + + if function_field.constant_base_field().is_finite(): + self._group_class = JacobianGroup_finite_field + else: + self._group_class = JacobianGroup + + def _repr_(self): + """ + Return the string representation of ``self``. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: C.jacobian(model='km_large') + Jacobian of Projective Plane Curve over Finite Field of size 7 + defined by x^3 - y^2*z - 2*z^3 (Khuri-Makdisi large model) + """ + r = super()._repr_() + return r + f' (Khuri-Makdisi {self._model} model)' diff --git a/src/sage/rings/function_field/khuri_makdisi.pyx b/src/sage/rings/function_field/khuri_makdisi.pyx new file mode 100644 index 00000000000..f0cac80a1f2 --- /dev/null +++ b/src/sage/rings/function_field/khuri_makdisi.pyx @@ -0,0 +1,893 @@ +r""" +Khuri-Makdisi algorithms for arithmetic in Jacobians + +This module implements Khuri-Makdisi's algorithms of [Khu2004]_. + +In the implementation, we use notations close to the ones used by +Khuri-Makdisi. We describe them below for readers of the code. + +Let `D_0` be the base divisor of the Jacobian in Khuri-Makdisi model. So `D_0` +is an effective divisor of appropriate degree `d_0` depending on the model. Let +`g` be the genus of the underlying function field. For large and medium models, +`d_0\ge 2g+1`. For small model `d_0\ge g+1`. A point of the Jacobian is a +divisor class containing a divisor `D - D_0` of degree `0` with an effective +divisor `D` of degree `d_0`. + +Let `V_n` denote the vector space `H^0(O(nD_0))` with a chosen +basis, and let `\mu_{n,m}` is a bilinear map from `V_n\times V_m\to V_{n+m}` +defined by `(f,g)\mapsto fg`. The map `\mu_{n,m}` can be represented by a +3-dimensional array as depicted below:: + + f + *------* + d /|e /| + *-|----* | + | *----|-* + |/ |/ + *------* + +where `d=\dim V_n`, `e=\dim V_m`, `f=\dim V_{n+m}`. In the implementation, we +instead use a matrix of size `d\times ef`. Each row of the matrix denotes a +matrix of size `e\times f`. + +A point of the Jacobian is represented by an effective divisor `D`. In +Khuri-Makdisi algorithms, the divisor `D` is represented by a subspace `W_D = +H^0(O(n_0D_0 - D))` of `V_{n_0}` with fixed `n_0` depending on the model. For +large and small models, `n_0=3` and `L = O(3D_0)`, and for medium model, +`n_0=2` and `L = O(2D_0)`. + +The subspace `W_D` is the row space of a matrix `w_D`. Thus in the +implementation, the matrix `w_D` represents a point of the Jacobian. The row +space of the matrix `w_L` is `V_{n_0}=H^0(O(n_0D_0))`. + +The function ``mu_image(w_D, w_E, mu_mat_n_m, expected_dim)`` computes the image +`\mu_{n,m}(W_D,W_E)` of the expected dimension. + +The function ``mu_preimage(w_E, w_F, mu_mat_n_m, expected_codim)`` computes the +preimage `W_D` such that `\mu_{n,m}(W_D,W_E)=W_F` of the expected codimension +`\dim V_n - \dim W_D`, which is a multiple of `d_0`. + +AUTHORS: + +- Kwankyu Lee (2022-01): initial version + +""" + +# **************************************************************************** +# Copyright (C) 2022 Kwankyu Lee +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.matrix.constructor import matrix +from sage.matrix.matrix cimport Matrix +from sage.modules.free_module_element cimport FreeModuleElement +from sage.rings.integer import Integer + + +cdef inline list listcat(list l): + flat_list = [] + for sublist in l: + flat_list.extend(sublist) + return flat_list + + +cdef class KhuriMakdisi_base(object): + cdef Matrix wL + cdef Matrix w0 + cdef int d0, g + + cdef Matrix mu_image(self, Matrix wd, Matrix we, Matrix mu_mat, int expected_dim=0): + """ + Lemma 2.2. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='km_large') + sage: G = J.group() + sage: b = C([0,0,1]).place() + sage: pl1 = C([1,2,1]).place() + sage: pl2 = C([3,1,1]).place() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: w1 = p1._w + sage: w2 = p2._w + sage: w1 + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 1 0 0 1 0 2] + [0 0 0 0 1 0 6 0 6] + [0 0 0 0 0 1 4 0 1] + [0 0 0 0 0 0 0 1 0] + sage: w2 + [0 1 0 0 0 0 0 2 2] + [0 0 1 0 0 0 0 4 6] + [0 0 0 1 0 0 0 5 6] + [0 0 0 0 1 0 0 3 1] + [0 0 0 0 0 1 0 3 5] + [0 0 0 0 0 0 1 6 3] + sage: (p1 + p2)._w # indirect doctest + [1 0 0 0 0 0 2 2 4] + [0 1 0 0 0 0 3 5 0] + [0 0 1 0 0 0 0 3 6] + [0 0 0 1 0 0 1 1 3] + [0 0 0 0 1 0 5 6 3] + [0 0 0 0 0 1 5 5 3] + """ + cdef Matrix mat + cdef FreeModuleElement v + cdef Py_ssize_t n, c, r + + n = we.ncols() + c = mu_mat.ncols() // n + mat = matrix(0, c) + for v in wd: + mat = mat.stack(we * matrix(n, v * mu_mat)) + mat.echelonize() + r = mat.rank() + mat = mat.matrix_from_rows(range(r)) + if expected_dim and r == expected_dim: + break + + assert not expected_dim or r == expected_dim + + return mat + + cdef Matrix mu_preimage(self, Matrix we, Matrix wde, Matrix mu_mat, int expected_codim=0): + """ + Lemma 2.3 (division). + + This computes + + {s: mu(s*E) subset F} = {s: s*M*E*F_perp^ == 0} + = {s: s*M*v*F_perp^ == 0 for v in E} + = {s: F_perp*(v*M^)*s == 0 for v in E} + + for E = we, F = wde, M^ = mu_mat_reversed + """ + cdef Matrix mat, perp, vmu + cdef FreeModuleElement v + cdef Py_ssize_t nd, ne, nde, r + + ne = we.ncols() + nde = wde.ncols() + nd = nde - ne + + perp = wde.right_kernel_matrix() + mat = matrix(0, mu_mat.nrows()) + for v in we: + vmu = matrix([v * matrix(ne, row) for row in mu_mat]) + mat = mat.stack(perp * vmu.transpose()) + mat.echelonize() + r = mat.rank() + mat = mat.matrix_from_rows(range(r)) + if expected_codim and r == expected_codim: + break + + assert not expected_codim or r == expected_codim + + return mat.right_kernel_matrix() + + cpdef Matrix negate(self, Matrix wd): + """ + Theorem 4.4 (negation), first method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p = G.point(pl - b) + sage: -p # indirect doctest + Point of Jacobian determined by + [ 1 0 0 0 0 0 15 11 2] + [ 0 1 0 0 0 0 16 0 12] + [ 0 0 1 0 0 0 0 16 0] + [ 0 0 0 1 0 0 0 0 16] + [ 0 0 0 0 1 0 12 0 16] + [ 0 0 0 0 0 1 15 16 2] + """ + return self.addflip(wd, self.w0) + + cpdef Matrix add(self, Matrix wd1, Matrix wd2): + """ + Theorem 4.5 (addition). + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p = G.point(pl - b) + sage: p + p # indirect doctest + Point of Jacobian determined by + [ 1 0 0 0 0 0 0 10 0] + [ 0 1 0 0 0 0 5 1 4] + [ 0 0 1 0 0 0 15 7 12] + [ 0 0 0 1 0 0 14 8 16] + [ 0 0 0 0 1 0 3 12 16] + [ 0 0 0 0 0 1 13 5 7] + """ + return self.negate(self.addflip(wd1, wd2)) + + cpdef Matrix subtract(self, Matrix wd1, Matrix wd2): + """ + Theorem 4.6 (subtraction), first method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p = G.point(pl - b) + sage: p - p # indirect doctest + Point of Jacobian determined by + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 1 0] + """ + return self.addflip(self.negate(wd1), wd2) + + cpdef Matrix multiple(self, Matrix wd, n): + """ + Compute multiple by additive square-and-multiply method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p = G.point(pl - b) + sage: 10*p + Point of Jacobian determined by + [ 1 0 0 0 0 0 5 2 2] + [ 0 1 0 0 0 0 13 6 11] + [ 0 0 1 0 0 0 1 11 4] + [ 0 0 0 1 0 0 1 13 7] + [ 0 0 0 0 1 0 12 16 2] + [ 0 0 0 0 0 1 6 9 10] + sage: (-10)*p + Point of Jacobian determined by + [ 1 0 0 0 0 13 0 10 6] + [ 0 1 0 0 0 5 0 4 16] + [ 0 0 1 0 0 2 0 0 4] + [ 0 0 0 1 0 9 0 6 9] + [ 0 0 0 0 1 6 0 0 9] + [ 0 0 0 0 0 0 1 9 5] + sage: 0*p + Point of Jacobian determined by + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 1 0] + """ + cdef Matrix w + cdef int sign, b + cdef list bits + + if n == 0: + return self.w0 + if n < 0: + bits = Integer(-n).digits(2) + else: + bits = Integer(n).digits(2) + bits.pop() + mwd = None + w = wd + sign = 1 + for i in range(len(bits)): + w = self.addflip(w, w) + sign = -sign + b = bits.pop() + if b > 0: + if sign < 0: + if mwd is None: + mwd = self.addflip(wd, self.w0) + w = self.addflip(w, mwd) + else: + w = self.addflip(w, wd) + sign = -sign + if sign < 0 and n > 0 or sign > 0 and n < 0: + w = self.addflip(w, self.w0) # negate + return w + + cpdef Matrix zero_divisor(self): + """ + Return the matrix `w_L` representing zero divisor. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl = C([-1,2,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: G._km.zero_divisor() + [1 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0] + [0 0 0 1 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 1 0 0] + [0 0 0 0 0 0 0 1 0] + [0 0 0 0 0 0 0 0 1] + """ + return self.wL + + +cdef class KhuriMakdisi_large(KhuriMakdisi_base): + r""" + Khuri-Makdisi's large model. + """ + cdef Matrix mu_mat33 + + def __init__(self, V, mu, w0, d0, g): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + Point of Jacobian determined by + [ 1 0 0 0 0 0 0 12 15] + [ 0 1 0 0 0 0 0 0 13] + [ 0 0 1 0 0 0 0 0 2] + [ 0 0 0 1 0 0 0 0 16] + [ 0 0 0 0 0 1 0 0 15] + [ 0 0 0 0 0 0 1 0 1] + sage: p2 + Point of Jacobian determined by + [ 1 0 0 0 0 0 0 12 5] + [ 0 1 0 0 0 0 0 0 2] + [ 0 0 1 0 0 0 0 0 13] + [ 0 0 0 1 0 0 0 0 8] + [ 0 0 0 0 0 1 0 0 10] + [ 0 0 0 0 0 0 1 0 14] + sage: p1 + p2 + Point of Jacobian determined by + [ 1 0 0 0 0 16 0 5 3] + [ 0 1 0 0 0 6 0 8 16] + [ 0 0 1 0 0 15 0 3 10] + [ 0 0 0 1 0 3 0 0 0] + [ 0 0 0 0 1 12 0 16 8] + [ 0 0 0 0 0 0 1 3 0] + sage: p1 - p2 + Point of Jacobian determined by + [ 1 0 0 0 0 0 13 9 5] + [ 0 1 0 0 0 0 2 5 8] + [ 0 0 1 0 0 0 6 7 5] + [ 0 0 0 1 0 0 11 3 16] + [ 0 0 0 0 1 0 9 7 10] + [ 0 0 0 0 0 1 4 10 5] + sage: p1.addflip(p2) == -(p1 + p2) + True + """ + self.wL = V(3).basis_matrix() + self.w0 = w0 + self.d0 = d0 + self.g = g + self.mu_mat33 = matrix(listcat([list(mu(3, 3, i, j)) for j in range(3*d0-g+1)]) for i in range(3*d0-g+1)) + + def equal(self, wd, we): + """ + Theorem 4.1, second method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: J = C.jacobian(model='km_large') + sage: b = C([0,1,0]).place() + sage: J.set_base_place(b) + sage: G = J.group() + sage: pl1 = C([3,2,1]).place() + sage: pl2 = C([5,5,1]).place() + sage: p1 = G(pl1) + sage: p2 = G(pl2) + sage: p1 + p2 == p2 + p1 # indirect doctest + True + sage: p1 - p2 == -(p2 - p1) + True + sage: zero = G.zero() + sage: p1 + zero == p1 + True + sage: p1 - p1 == zero + True + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix wf, w1, w2 + + wf = matrix(wd[0]) + w1 = self.mu_image(wf, we, self.mu_mat33, 2*d0 - g + 1) + w2 = self.mu_preimage(wd, w1, self.mu_mat33) + return w2.rank() > 0 + + cdef Matrix _add(self, Matrix wd, Matrix we): + """ + Theorem 3.6 (addition of divisors, first method). + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2 + + w1 = self.mu_image(wd, we, self.mu_mat33, 4*d0 - g + 1) + w2 = self.mu_preimage(self.wL, w1, self.mu_mat33, 2*d0) + return w2 + + cdef Matrix _flip(self, Matrix wd): + """ + Theorem 3.10 (flipping) + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2 + + # efficient than + # wf = matrix(wd[0]) + # w1 = self.mu_image(wf, self.wL, mu_mat, 3*d0 - g + 1) + w1 = matrix(3*d0 - g + 1, wd[0] * self.mu_mat33) + w2 = self.mu_preimage(wd, w1, self.mu_mat33, d0) + return w2 + + cpdef Matrix addflip(self, Matrix wd1, Matrix wd2): + """ + Theorem 4.3 (addflip) + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: F = C.function_field() + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1.addflip(p2) + Point of Jacobian determined by + [ 1 0 0 0 0 0 7 10 9] + [ 0 1 0 0 0 0 4 14 10] + [ 0 0 1 0 0 0 7 0 9] + [ 0 0 0 1 0 0 10 10 6] + [ 0 0 0 0 1 0 6 5 15] + [ 0 0 0 0 0 1 14 9 1] + """ + return self._flip(self._add(wd1, wd2)) + + cpdef Matrix add_divisor(self, Matrix wd1, Matrix wd2, int d1, int d2): + """ + Theorem 3.6 (addition of divisors, first method). + + We assume that `w_{D_1}`, `w_{D_2}` represent divisors of degree at most + `3d_0 - 2g - 1`. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='km_large') + sage: G = J.group() + sage: pts = G.get_points(G.order()) # indirect doctest + sage: len(pts) + 11 + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2 + + w1 = self.mu_image(wd1, wd2, self.mu_mat33, 6*d0 - d1 - d2 - g + 1) + w2 = self.mu_preimage(self.wL, w1, self.mu_mat33, d1 + d2) + return w2 + + +cdef class KhuriMakdisi_medium(KhuriMakdisi_base): + """ + Khuri-Makdisi's *medium* model + """ + cdef Matrix wV1, wV2, wV3, mu_mat22, mu_mat23, mu_mat31, mu_mat32 + + def __init__(self, V, mu, w0, d0, g): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: J = C.jacobian(model='km_medium', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + Point of Jacobian determined by + [ 1 0 0 0 16 12] + [ 0 1 0 0 15 0] + [ 0 0 1 0 1 0] + sage: p2 + Point of Jacobian determined by + [ 1 0 0 0 8 12] + [ 0 1 0 0 10 0] + [ 0 0 1 0 14 0] + sage: p1 + p2 + Point of Jacobian determined by + [ 1 0 0 6 3 16] + [ 0 1 0 15 16 10] + [ 0 0 1 3 0 0] + sage: p1 - p2 + Point of Jacobian determined by + [ 1 0 0 8 0 14] + [ 0 1 0 1 10 10] + [ 0 0 1 15 3 6] + sage: p1.addflip(p2) == -(p1 + p2) + True + """ + self.wL = V(2).basis_matrix() + self.w0 = w0 + self.d0 = d0 + self.g = g + self.wV1 = V(1).basis_matrix() + self.wV2 = V(2).basis_matrix() + self.wV3 = V(3).basis_matrix() + self.mu_mat22 = matrix(listcat([list(mu(2, 2, i, j)) for j in range(2*d0-g+1)]) for i in range(2*d0-g+1)) + self.mu_mat23 = matrix(listcat([list(mu(2, 3, i, j)) for j in range(3*d0-g+1)]) for i in range(2*d0-g+1)) + self.mu_mat31 = matrix(listcat([list(mu(3, 1, i, j)) for j in range(1*d0-g+1)]) for i in range(3*d0-g+1)) + self.mu_mat32 = matrix(listcat([list(mu(3, 2, i, j)) for j in range(2*d0-g+1)]) for i in range(3*d0-g+1)) + + def equal(self, wd, we): + """ + Theorem 4.1, second method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: J = C.jacobian(model='km_medium', base_div=h) + sage: G = J.group() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + p2 == p2 + p1 # indirect doctest + True + sage: p1 - p2 == -(p2 - p1) + True + sage: zero = G.zero() + sage: p1 + zero == p1 + True + sage: p1 - p1 == zero + True + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix wf, w1, w2 + + wf = matrix(wd[0]) + w1 = self.mu_image(wf, we, self.mu_mat22, d0 - g + 1) + w2 = self.mu_preimage(wd, w1, self.mu_mat22) + return w2.rank() > 0 + + cpdef Matrix addflip(self, Matrix wd1, Matrix wd2): + """ + Theorem 5.1 (addflip in medium model). + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: h = C.function(y/x).divisor_of_poles() + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: J = C.jacobian(model='km_medium', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: af = p1.addflip(p2) + sage: af + Point of Jacobian determined by + [ 1 0 0 6 3 16] + [ 0 1 0 0 7 9] + [ 0 0 1 14 2 3] + + We check the computation in other model:: + + sage: J = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: G.point(af.divisor()) == p1.addflip(p2) + True + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2, w3, w4 + + w1 = self.mu_image(wd1, wd2, self.mu_mat22, 2*d0 - g + 1) + w2 = self.mu_preimage(self.wV1, w1, self.mu_mat31, 2*d0) + # efficient than + # wf = matrix(w2[0]) + # w3 = self.mu_image(wf, self.wV2, self.mu_mat32, 2*d0 - g + 1) + w3 = matrix(2*d0 - g + 1, w2[0] * self.mu_mat32) + w4 = self.mu_preimage(w2, w3, self.mu_mat23, d0) + return w4 + + cpdef Matrix add_divisor(self, Matrix wd1, Matrix wd2, int d1, int d2): + """ + Theorem 3.6 (addition of divisors, first method). + + We assume that `w_{D_1}`, `w_{D_2}` represent divisors of degree at + most `4d_0 - 2g - 1`. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='km_medium') + sage: G = J.group() + sage: pts = G.get_points(G.order()) # indirect doctest + sage: len(pts) + 11 + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2 + + w1 = self.mu_image(wd1, wd2, self.mu_mat22, 4*d0 - d1 - d2 - g + 1) + w2 = self.mu_preimage(self.wL, w1, self.mu_mat22, d1 + d2) + return w2 + + +cdef class KhuriMakdisi_small(KhuriMakdisi_base): + """ + Khuri-Makdisi's *small* model + """ + cdef Matrix wV2, wV3, wV4, mu_mat22 + cdef Matrix mu_mat23, mu_mat24, mu_mat32, mu_mat33, mu_mat34, mu_mat42, mu_mat43 + + def __init__(self, V, mu, w0, d0, g): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: J = C.jacobian(model='km_small', base_div=2*b) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + Point of Jacobian determined by + [ 1 0 0 0 0 11] + [ 0 1 0 0 2 0] + [ 0 0 1 0 16 10] + [ 0 0 0 1 0 3] + sage: p2 + Point of Jacobian determined by + [1 0 0 0 0 3] + [0 1 0 0 7 0] + [0 0 1 0 3 5] + [0 0 0 1 0 2] + sage: p1 + p2 + Point of Jacobian determined by + [ 1 0 0 0 10 9] + [ 0 1 0 0 7 5] + [ 0 0 1 0 15 4] + [ 0 0 0 1 3 10] + sage: p1 - p2 + Point of Jacobian determined by + [ 1 0 0 0 10 9] + [ 0 1 0 0 9 8] + [ 0 0 1 0 15 4] + [ 0 0 0 1 15 11] + sage: p1.addflip(p2) == -(p1 + p2) + True + """ + self.wL = V(3).basis_matrix() + self.w0 = w0 + self.d0 = d0 + self.g = g + self.wV2 = V(2).basis_matrix() + self.wV3 = V(3).basis_matrix() + self.wV4 = V(4).basis_matrix() + self.mu_mat23 = matrix(listcat([list(mu(2, 3, i, j)) for j in range(3*d0-g+1)]) for i in range(2*d0-g+1)) + self.mu_mat24 = matrix(listcat([list(mu(2, 4, i, j)) for j in range(4*d0-g+1)]) for i in range(2*d0-g+1)) + self.mu_mat32 = matrix(listcat([list(mu(3, 2, i, j)) for j in range(2*d0-g+1)]) for i in range(3*d0-g+1)) + self.mu_mat33 = matrix(listcat([list(mu(3, 3, i, j)) for j in range(3*d0-g+1)]) for i in range(3*d0-g+1)) + self.mu_mat34 = matrix(listcat([list(mu(3, 4, i, j)) for j in range(4*d0-g+1)]) for i in range(3*d0-g+1)) + self.mu_mat42 = matrix(listcat([list(mu(4, 2, i, j)) for j in range(2*d0-g+1)]) for i in range(4*d0-g+1)) + self.mu_mat43 = matrix(listcat([list(mu(4, 3, i, j)) for j in range(3*d0-g+1)]) for i in range(4*d0-g+1)) + + def equal(self, wd, we): + """ + Theorem 4.1, second method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: J = C.jacobian(model='km_small', base_div=2*b) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: p1 + p2 == p2 + p1 # indirect doctest + True + sage: p1 - p2 == -(p2 - p1) + True + sage: zero = G.zero() + sage: p1 + zero == p1 + True + sage: p1 - p1 == zero + True + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix wf, w1, w2 + + wf = matrix(wd[0]) + w1 = self.mu_image(wf, we, self.mu_mat33, 2*d0 - g + 1) + w2 = self.mu_preimage(wd, w1, self.mu_mat33) + return w2.rank() > 0 + + cpdef Matrix addflip(self, Matrix wd1, Matrix wd2): + """ + Theorem 5.3 (addflip in small model), second method. + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(17), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: pl1 = C([-1,2,1]).place() + sage: pl2 = C([3,7,1]).place() + sage: J = C.jacobian(model='km_small', base_div=2*b) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: af = p1.addflip(p2) + sage: af + Point of Jacobian determined by + [ 1 0 0 0 10 9] + [ 0 1 0 0 10 12] + [ 0 0 1 0 15 4] + [ 0 0 0 1 14 7] + + We check the computation in other model:: + + sage: h = C.function(y/x).divisor_of_poles() + sage: Jl = C.jacobian(model='km_large', base_div=h) + sage: G = J.group() + sage: q1 = G.point(pl1 - b) + sage: q2 = G.point(pl2 - b) + sage: G.point(af.divisor()) == q1.addflip(p2) + True + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2, w3, w4, w5 + + w1 = self.mu_image(wd1, wd2, self.mu_mat33, 4*d0 - g + 1) + w2 = self.mu_preimage(self.wV3, w1, self.mu_mat33, 2*d0) + w3 = self.mu_preimage(self.wV2, w1, self.mu_mat42, 2*d0) + # efficient than + # wf = matrix(w2[0]) + # w4 = self.mu_image(wf, self.wV4, self.mu_mat34, 4*d0 - g + 1) + w4 = matrix(4*d0 - g + 1, w2[0] * self.mu_mat34) + w5 = self.mu_preimage(w3, w4, self.mu_mat34, d0) + return w5 + + cpdef Matrix negate(self, Matrix wd): + """ + Theorem 5.4 (negation in small model). + + TESTS:: + + sage: P2. = ProjectiveSpace(GF(7), 2) + sage: C = Curve(x^3 + 5*z^3 - y^2*z, P2) + sage: b = C([0,1,0]).place() + sage: pl1 = C([3,2,1]).place() + sage: pl2 = C([5,5,1]).place() + sage: J = C.jacobian(model='km_small', base_div=2*b) + sage: G = J.group() + sage: p1 = G.point(pl1 - b) + sage: p2 = G.point(pl2 - b) + sage: -(-p1) == p1 # indirect doctest + True + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2, w3, w4 + + w1 = self.mu_image(self.wV2, wd, self.mu_mat23, 4*d0 - g + 1) + w2 = self.mu_preimage(self.wV3, w1, self.mu_mat23, d0) + # efficient than + # wf = matrix(w2[0]) + # w3 = self.mu_image(wf, self.wV4, self.mu_mat24, 4*d0 - g + 1) + w3 = matrix(4*d0 - g + 1, w2[0] * self.mu_mat24) + w4 = self.mu_preimage(wd, w3, self.mu_mat33, d0) + return w4 + + cpdef Matrix add_divisor(self, Matrix wd1, Matrix wd2, int d1, int d2): + """ + Theorem 3.6 (addition of divisors, first method). + + We assume that `w_{D_1}`, `w_{D_2}` represent divisors of degree at most + `6d_0 - 2g - 1`. + + TESTS:: + + sage: k = GF(7) + sage: A. = AffineSpace(k,2) + sage: C = Curve(y^2 + x^3 + 2*x + 1).projective_closure() + sage: J = C.jacobian(model='km_small') + sage: G = J.group() + sage: pts = G.get_points(G.order()) # indirect doctest + sage: len(pts) + 11 + """ + cdef int d0 = self.d0 + cdef int g = self.g + cdef Matrix w1, w2 + + w1 = self.mu_image(wd1, wd2, self.mu_mat33, 6*d0 - d1 - d2 - g + 1) + w2 = self.mu_preimage(self.wL, w1, self.mu_mat33, d1 + d2) + return w2 diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 2c95365167b..00b0f0fb810 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2725,6 +2725,46 @@ def places_on(self, point): places.append(p) return places + def jacobian(self, model, base_div=None): + """ + Return the Jacobian of this curve. + + INPUT: + + - ``model`` -- model to use for arithmetic + + - ``base_div`` -- an effective divisor for the model + + The degree of the base divisor should satisfy certain degree condition + corresponding to the model used. The following table lists these + conditions. Let `g` be the geometric genus of the curve. + + - ``hess``: ideal-based arithmetic; requires base divisor of degree `g` + + - ``km_large``: Khuri-Makdisi's large model; requires base divisor of + degree at least `2g + 1` + + - ``km_medium``: Khuri-Makdisi's medium model; requires base divisor of + degree at least `2g + 1` + + - ``km_small``: Khuri-Makdisi's small model requires base divisor of + degree at least `g + 1` + + We assume the curve (or its function field) has a rational place. If a + base divisor is not given, one is chosen using a rational place. + + EXAMPLES:: + + sage: A. = AffineSpace(GF(5), 2) + sage: C = Curve(y^2*(x^3 - 1) - (x^3 - 2)).projective_closure() + sage: J = C.jacobian(model='hess'); J + Jacobian of Projective Plane Curve over Finite Field of size 5 defined by + 2*x0^5 - x0^2*x1^3 - x0^3*x2^2 + x1^3*x2^2 (Hess model) + sage: J.base_divisor().degree() == C.genus() + True + """ + return self.function_field().jacobian(model, base_div, curve=self) + class IntegralProjectiveCurve_finite_field(IntegralProjectiveCurve): """ diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 64a4d8cdc0d..1049da8f782 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -2338,6 +2338,62 @@ def ate_pairing(self, Q, n, k, t, q=None): ret = ret**e return ret + def point_of_jacobian_of_projective_curve(self): + r""" + Return the point in the Jacobian of the curve. + + The Jacobian is the one attached to the projective curve associated + with this elliptic curve. + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: k. = GF((5,2)) + sage: E = EllipticCurve(k,[1,0]); E + Elliptic Curve defined by y^2 = x^3 + x over Finite Field in a of size 5^2 + sage: E.order() + 32 + sage: P = E([a, 2*a + 4]) + sage: P + (a : 2*a + 4 : 1) + sage: P.order() + 8 + sage: p = P.point_of_jacobian_of_projective_curve() + sage: p + [Place (x + 4*a, y + 3*a + 1)] + sage: p.order() + 8 + sage: Q = 3*P + sage: q = Q.point_of_jacobian_of_projective_curve() + sage: q == 3*p + True + sage: G = p.parent() + sage: G.order() + 32 + sage: G + Group of rational points of Jacobian over Finite Field in a of size 5^2 (Hess model) + sage: J = G.parent(); J + Jacobian of Projective Plane Curve over Finite Field in a of size 5^2 + defined by x^2*y + y^3 - x*z^2 (Hess model) + sage: J.curve() == E.affine_patch(2).projective_closure() + True + """ + from sage.schemes.curves.constructor import Curve + C = self.curve() + A = C.ambient_space() # projective plane + x, y, z = self + + X = Curve(C.defining_ideal().gens(), A) + X = X.affine_patch(2).projective_closure() + F = X.function_field() + P = X(z,x,y).place() + + Pinf = F.places_infinite()[0] + assert Pinf.degree() == 1, "no rational point at infinity" + + J = X.jacobian(model='hess', base_div=F.genus()*Pinf) + G = J.group(self.base_ring()) + return G(P - P.degree()*Pinf) class EllipticCurvePoint_number_field(EllipticCurvePoint_field): """ diff --git a/src/sage/schemes/elliptic_curves/jacobian.py b/src/sage/schemes/elliptic_curves/jacobian.py index 16bdf2d11b4..9086d4e47ed 100644 --- a/src/sage/schemes/elliptic_curves/jacobian.py +++ b/src/sage/schemes/elliptic_curves/jacobian.py @@ -100,7 +100,7 @@ def Jacobian(X, **kwds): """ try: return X.jacobian(**kwds) - except AttributeError: + except (AttributeError, TypeError): pass morphism = kwds.pop('morphism', False) diff --git a/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py b/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py index daab2d2259e..298808e0c89 100644 --- a/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py +++ b/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py @@ -490,33 +490,103 @@ def scheme(self): r""" Return the scheme this morphism maps to; or, where this divisor lives. - .. warning:: + .. WARNING:: - Although a pointset is defined over a specific field, the - scheme returned may be over a different (usually smaller) - field. The example below demonstrates this: the pointset - is determined over a number field of absolute degree 2 but - the scheme returned is defined over the rationals. + Although a pointset is defined over a specific field, the + scheme returned may be over a different (usually smaller) + field. The example below demonstrates this: the pointset + is determined over a number field of absolute degree 2 but + the scheme returned is defined over the rationals. EXAMPLES:: + sage: # needs sage.rings.number_field sage: x = QQ['x'].gen() sage: f = x^5 + x sage: H = HyperellipticCurve(f) - sage: F. = NumberField(x^2 - 2, 'a') # needs sage.rings.number_field - sage: J = H.jacobian()(F); J # needs sage.rings.number_field + sage: F. = NumberField(x^2 - 2, 'a') + sage: J = H.jacobian()(F); J Set of rational points of Jacobian of Hyperelliptic Curve over Number Field in a with defining polynomial x^2 - 2 defined by y^2 = x^5 + x - - :: - - sage: P = J(H.lift_x(F(1))) # needs sage.rings.number_field - sage: P.scheme() # needs sage.rings.number_field + sage: P = J(H.lift_x(F(1))) + sage: P.scheme() Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x """ return self.codomain() + def point_of_jacobian_of_projective_curve(self): + r""" + Return the point in the Jacobian of the curve. + + The Jacobian is the one attached to the projective curve + corresponding to this hyperelliptic curve. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(11)) + sage: f = x^6 + x + 1 + sage: H = HyperellipticCurve(f) + sage: J = H.jacobian() + sage: D = J(H.lift_x(1)) + sage: D # divisor in Mumford representation + (x + 10, y + 6) + sage: jacobian_order = sum(H.frobenius_polynomial()) + sage: jacobian_order + 234 + sage: p = D.point_of_jacobian_of_projective_curve(); p + [Place (1/x0, 1/x0^3*x1 + 1) + + Place (x0 + 10, x1 + 6)] + sage: p # Jacobian point represented by an effective divisor + [Place (1/x0, 1/x0^3*x1 + 1) + + Place (x0 + 10, x1 + 6)] + sage: p.order() + 39 + sage: 234*p == 0 + True + sage: G = p.parent() + sage: G + Group of rational points of Jacobian over Finite Field of size 11 (Hess model) + sage: J = G.parent() + sage: J + Jacobian of Projective Plane Curve over Finite Field of size 11 + defined by x0^6 + x0^5*x1 + x1^6 - x0^4*x2^2 (Hess model) + sage: C = J.curve() + sage: C + Projective Plane Curve over Finite Field of size 11 + defined by x0^6 + x0^5*x1 + x1^6 - x0^4*x2^2 + sage: C.affine_patch(0) == H.affine_patch(2) + True + """ + from sage.schemes.curves.constructor import Curve + C = self.parent().curve() + P = C.ambient_space() # projective plane + x0, x1, x2 = P.gens() + + # X is the curve positioned in the ambient space + # such that x1 = x and x2 = y + X = Curve(C.defining_ideal().gens(), P) + X = X.affine_patch(2).projective_closure() + + u0, v0 = list(self) + u1 = u0.subs(x1).homogenize(x0) + v1 = (x2 - v0.subs(x1)).homogenize(x0) + u2 = u1/x0**u1.degree() + v2 = v1/x0**v1.degree() + u = X.function(u2) + v = X.function(v2) + + F = X.function_field() + O = F.maximal_order() + D = O.ideal([u,v]).divisor() + + Pinf = F.places_infinite()[0] + assert Pinf.degree() == 1, "no rational point at infinity" + + J = X.jacobian(model='hess', base_div=F.genus()*Pinf) + G = J.group(self.base_ring()) + return G(D - D.degree()*Pinf) + def __list__(self): r""" Return a list `(a(x), b(x))` of the polynomials giving the diff --git a/src/sage/schemes/jacobians/abstract_jacobian.py b/src/sage/schemes/jacobians/abstract_jacobian.py index d5e7c831515..fce6bdfc867 100644 --- a/src/sage/schemes/jacobians/abstract_jacobian.py +++ b/src/sage/schemes/jacobians/abstract_jacobian.py @@ -9,40 +9,23 @@ - William Stein (2005) """ -#***************************************************************************** + +# **************************************************************************** # Copyright (C) 2005 William Stein # -# Distributed under the terms of the GNU General Public License (GPL) -# as published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.categories.schemes import Jacobians from sage.categories.fields import Fields -_Fields = Fields() from sage.schemes.generic.scheme import Scheme, is_Scheme from sage.structure.richcmp import richcmp_method, richcmp - -def is_Jacobian(J): - """ - Return True if `J` is of type Jacobian_generic. - - EXAMPLES:: - - sage: from sage.schemes.jacobians.abstract_jacobian import Jacobian, is_Jacobian - sage: P2. = ProjectiveSpace(QQ, 2) - sage: C = Curve(x^3 + y^3 + z^3) - sage: J = Jacobian(C) - sage: is_Jacobian(J) - True - - :: - - sage: E = EllipticCurve('37a1') - sage: is_Jacobian(E) - False - """ - return isinstance(J, Jacobian_generic) +_Fields = Fields() def Jacobian(C): @@ -57,7 +40,7 @@ def Jacobian(C): """ try: return C.jacobian() - except AttributeError: + except (AttributeError, TypeError): return Jacobian_generic(C) @@ -76,7 +59,7 @@ class Jacobian_generic(Scheme): sage: J = Jacobian(C); J Jacobian of Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3 """ - def __init__(self, C): + def __init__(self, C, category=None): """ Initialize. @@ -92,12 +75,14 @@ def __init__(self, C): Note: this is an abstract parent, so we skip element tests:: - sage: TestSuite(J).run(skip =["_test_an_element",\ - "_test_elements",\ - "_test_elements_eq_reflexive",\ - "_test_elements_eq_symmetric",\ - "_test_elements_eq_transitive",\ - "_test_elements_neq",\ + sage: TestSuite(J).run(skip =["_test_an_element", \ + "_test_zero", \ + "_test_elements", \ + "_test_elements_eq_reflexive", \ + "_test_elements_eq_symmetric", \ + "_test_elements_eq_transitive", \ + "_test_additive_associativity", \ + "_test_elements_neq", \ "_test_some_elements"]) :: @@ -129,7 +114,7 @@ def __init__(self, C): if C.dimension() != 1: raise ValueError("C (=%s) must have dimension 1." % C) self.__curve = C - Scheme.__init__(self, C.base_scheme()) + Scheme.__init__(self, C.base_scheme(), category=Jacobians(C.base_ring()).or_subcategory(category)) def __richcmp__(self, J, op): """ @@ -153,7 +138,7 @@ def __richcmp__(self, J, op): sage: J1 != J2 True """ - if not is_Jacobian(J): + if not isinstance(J, Jacobian_generic): return NotImplemented return richcmp(self.curve(), J.curve(), op) @@ -247,8 +232,10 @@ def base_extend(self, R): sage: Jac = H.jacobian(); Jac Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^3 - 10*x + 9 - sage: F. = QQ.extension(x^2 + 1) # needs sage.rings.number_field - sage: Jac.base_extend(F) # needs sage.rings.number_field + + sage: # needs sage.rings.number_field + sage: F. = QQ.extension(x^2 + 1) + sage: Jac.base_extend(F) Jacobian of Hyperelliptic Curve over Number Field in a with defining polynomial x^2 + 1 defined by y^2 = x^3 - 10*x + 9 """ From 872061b10b256edc72940cd8d10b8446b6869771 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 2 Apr 2024 14:58:05 +0900 Subject: [PATCH 145/191] Do right things to define Jacobians category --- src/sage/categories/schemes.py | 22 +++++++++++++++++-- .../rings/function_field/jacobian_base.py | 20 ++++++++++++----- .../schemes/jacobians/abstract_jacobian.py | 2 ++ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index f2d0170fd2d..1de64a573cf 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -23,6 +23,7 @@ from sage.categories.rings import Rings from sage.categories.fields import Fields from sage.categories.homsets import HomsetsCategory +from sage.misc.abstract_method import abstract_method class Schemes(Category): @@ -299,7 +300,7 @@ def extra_super_categories(self): return [Rings()] -class Jacobians(AbelianVarieties): +class Jacobians(Schemes_over_base): """ The category of Jacobians attached to curves or function fields. """ @@ -317,7 +318,24 @@ def _repr_object_names(self): EXAMPLES:: sage: Jacobians(Spec(QQ)) # indirect doctest - Category of Jacobians over Rational Field + Category of Jacobians over Spectrum of Rational Field """ return "Jacobians over %s" % self.base_scheme() + class ParentMethods: + + @abstract_method + def base_curve(self): + """ + Return the curve to which this Jacobian is attached. + + EXAMPLES:: + + sage: # needs sage.rings.function_field + sage: K. = FunctionField(GF(2)) + sage: J = K.jacobian() + sage: J.base_curve() + Rational function field in x over Finite Field of size 2 + """ + + diff --git a/src/sage/rings/function_field/jacobian_base.py b/src/sage/rings/function_field/jacobian_base.py index 0fa7ba14c82..0f58eb5817f 100644 --- a/src/sage/rings/function_field/jacobian_base.py +++ b/src/sage/rings/function_field/jacobian_base.py @@ -616,11 +616,7 @@ def _repr_(self): sage: F.jacobian() Jacobian of Function field in y defined by y^2 + y + (x^2 + 1)/x (Hess model) """ - if self._curve is not None: - F = self._curve - else: - F = self._function_field - return f'Jacobian of {F}' + return f'Jacobian of {self.base_curve()}' def _an_element_(self): """ @@ -690,6 +686,20 @@ def curve(self): """ return self._curve + def base_curve(self): + """ + Return the base curve or the function field that abstractly defines a curve. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: F. = K.extension(Y^2 + Y + x + 1/x) + sage: J = F.jacobian() + sage: J.base_curve() + Function field in y defined by y^2 + y + (x^2 + 1)/x + """ + return self._function_field if self._curve is None else self._curve + def facade_for(self): """ Return the system of groups that this Jacobian is a facade for. diff --git a/src/sage/schemes/jacobians/abstract_jacobian.py b/src/sage/schemes/jacobians/abstract_jacobian.py index fce6bdfc867..a1b27708080 100644 --- a/src/sage/schemes/jacobians/abstract_jacobian.py +++ b/src/sage/schemes/jacobians/abstract_jacobian.py @@ -192,6 +192,8 @@ def curve(self): """ return self.__curve + base_curve = curve + def change_ring(self, R): r""" Return the Jacobian over the ring `R`. From 849c5f259e84be7f05c0cbed644f09882ad40862 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 2 Apr 2024 15:06:26 +0900 Subject: [PATCH 146/191] Add tests --- src/sage/categories/schemes.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index 1de64a573cf..3f50a729da8 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -303,6 +303,15 @@ def extra_super_categories(self): class Jacobians(Schemes_over_base): """ The category of Jacobians attached to curves or function fields. + + EXAMPLES:: + + sage: Jacobians(QQ) + Category of Jacobians over Rational Field + + TESTS:: + + sage: TestSuite(Jacobians(QQ)).run() """ def super_categories(self): """ @@ -337,5 +346,3 @@ def base_curve(self): sage: J.base_curve() Rational function field in x over Finite Field of size 2 """ - - From 8d76f0caed565945acef2428b6a8bb2e56350fac Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 2 Apr 2024 15:37:33 +0900 Subject: [PATCH 147/191] Fix formatting errors --- src/sage/categories/schemes.py | 10 +++++----- src/sage/schemes/curves/projective_curve.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index 3f50a729da8..626c537551c 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -340,9 +340,9 @@ def base_curve(self): EXAMPLES:: - sage: # needs sage.rings.function_field - sage: K. = FunctionField(GF(2)) - sage: J = K.jacobian() - sage: J.base_curve() - Rational function field in x over Finite Field of size 2 + sage: # needs sage.rings.function_field + sage: K. = FunctionField(GF(2)) + sage: J = K.jacobian() + sage: J.base_curve() + Rational function field in x over Finite Field of size 2 """ diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 00b0f0fb810..d8d2d4c8e67 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2758,8 +2758,8 @@ def jacobian(self, model, base_div=None): sage: A. = AffineSpace(GF(5), 2) sage: C = Curve(y^2*(x^3 - 1) - (x^3 - 2)).projective_closure() sage: J = C.jacobian(model='hess'); J - Jacobian of Projective Plane Curve over Finite Field of size 5 defined by - 2*x0^5 - x0^2*x1^3 - x0^3*x2^2 + x1^3*x2^2 (Hess model) + Jacobian of Projective Plane Curve over Finite Field of size 5 + defined by 2*x0^5 - x0^2*x1^3 - x0^3*x2^2 + x1^3*x2^2 (Hess model) sage: J.base_divisor().degree() == C.genus() True """ From 9b5ef791a817dbf78b49a609d60a24a64845123f Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 2 Apr 2024 17:01:52 +0900 Subject: [PATCH 148/191] Improve Schemes categories --- src/sage/categories/schemes.py | 68 ++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index 626c537551c..0c64079ff20 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -61,7 +61,6 @@ class Schemes(Category): sage: Schemes().Homsets().super_categories() [Category of homsets] """ - @staticmethod def __classcall_private__(cls, X=None): """ @@ -79,8 +78,7 @@ def __classcall_private__(cls, X=None): Category of schemes over Integer Ring """ if X is not None: - from sage.schemes.generic.scheme import is_Scheme - if not is_Scheme(X): + if X not in Schemes(): X = Schemes()(X) return Schemes_over_base(X) return super().__classcall__(cls) @@ -175,7 +173,6 @@ class Schemes_over_base(Category_over_base): sage: C = Schemes(ZZ) sage: TestSuite(C).run() """ - def base_scheme(self): """ EXAMPLES:: @@ -201,12 +198,11 @@ def _repr_object_names(self): sage: Schemes(Spec(ZZ)) # indirect doctest Category of schemes over Integer Ring """ - # To work around the name of the class (schemes_over_base) from sage.schemes.generic.scheme import is_AffineScheme - if is_AffineScheme(self.base_scheme()): - return "schemes over %s" % self.base_scheme().coordinate_ring() - else: - return "schemes over %s" % self.base_scheme() + base = self.base() + if is_AffineScheme(base): + base = base.coordinate_ring() + return f"schemes over {base}" class AbelianVarieties(Schemes_over_base): @@ -240,6 +236,18 @@ def __init__(self, base): raise ValueError('category of abelian varieties is only defined over fields') super().__init__(base) + def base_scheme(self): + """ + EXAMPLES:: + + sage: Schemes(Spec(ZZ)).base_scheme() + Spectrum of Integer Ring + """ + base = self.base() + if base not in Schemes(): + base = Schemes()(base) + return base + def super_categories(self): """ EXAMPLES:: @@ -257,7 +265,7 @@ def _repr_object_names(self): sage: AbelianVarieties(Spec(QQ)) # indirect doctest Category of abelian varieties over Rational Field """ - return "abelian varieties over %s" % self.base_scheme() + return "abelian varieties over %s" % self.base() class Homsets(HomsetsCategory): r""" @@ -313,8 +321,42 @@ class Jacobians(Schemes_over_base): sage: TestSuite(Jacobians(QQ)).run() """ + def __init__(self, base): + r""" + Constructor of this category. + + EXAMPLES:: + + sage: Jacobians(QQ) + Category of Jacobians over Rational Field + sage: Jacobians(Spec(QQ)) + Category of Jacobians over Rational Field + """ + from sage.schemes.generic.scheme import is_AffineScheme + if is_AffineScheme(base): + base = base.coordinate_ring() + if base not in Fields(): + raise ValueError('category of Jacobians is only defined over fields') + super().__init__(base) + + def base_scheme(self): + """ + Return the base scheme of this Jacobians category. + + EXAMPLES:: + + sage: Jacobians(QQ).base_scheme() + Spectrum of Rational Field + """ + base = self.base() + if base not in Schemes(): + base = Schemes()(base) + return base + def super_categories(self): """ + Return the super categories of this Jacobians category. + EXAMPLES:: sage: Jacobians(QQ).super_categories() @@ -324,12 +366,14 @@ def super_categories(self): def _repr_object_names(self): """ + Return the string representation of this category. + EXAMPLES:: sage: Jacobians(Spec(QQ)) # indirect doctest - Category of Jacobians over Spectrum of Rational Field + Category of Jacobians over Rational Field """ - return "Jacobians over %s" % self.base_scheme() + return "Jacobians over %s" % self.base() class ParentMethods: From 1de79032ea2ab141690e26bcdf1dfe6149362ceb Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 2 Apr 2024 18:36:07 +0900 Subject: [PATCH 149/191] Remove projective from point_of_jacobian_of_projective_curve method --- src/sage/schemes/elliptic_curves/ell_point.py | 6 +++--- src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 1049da8f782..5d83ca27d6d 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -2338,7 +2338,7 @@ def ate_pairing(self, Q, n, k, t, q=None): ret = ret**e return ret - def point_of_jacobian_of_projective_curve(self): + def point_of_jacobian_of_curve(self): r""" Return the point in the Jacobian of the curve. @@ -2358,13 +2358,13 @@ def point_of_jacobian_of_projective_curve(self): (a : 2*a + 4 : 1) sage: P.order() 8 - sage: p = P.point_of_jacobian_of_projective_curve() + sage: p = P.point_of_jacobian_of_curve() sage: p [Place (x + 4*a, y + 3*a + 1)] sage: p.order() 8 sage: Q = 3*P - sage: q = Q.point_of_jacobian_of_projective_curve() + sage: q = Q.point_of_jacobian_of_curve() sage: q == 3*p True sage: G = p.parent() diff --git a/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py b/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py index 298808e0c89..c9c580209c0 100644 --- a/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py +++ b/src/sage/schemes/hyperelliptic_curves/jacobian_morphism.py @@ -515,7 +515,7 @@ def scheme(self): """ return self.codomain() - def point_of_jacobian_of_projective_curve(self): + def point_of_jacobian_of_curve(self): r""" Return the point in the Jacobian of the curve. @@ -534,7 +534,7 @@ def point_of_jacobian_of_projective_curve(self): sage: jacobian_order = sum(H.frobenius_polynomial()) sage: jacobian_order 234 - sage: p = D.point_of_jacobian_of_projective_curve(); p + sage: p = D.point_of_jacobian_of_curve(); p [Place (1/x0, 1/x0^3*x1 + 1) + Place (x0 + 10, x1 + 6)] sage: p # Jacobian point represented by an effective divisor From 2f42cd94b9aaeed59774c9645648b7536c9ac053 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Wed, 3 Apr 2024 08:47:00 +0900 Subject: [PATCH 150/191] Fix copyright year --- src/sage/categories/schemes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index 0c64079ff20..cb1db7f8f3b 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -4,7 +4,7 @@ """ # **************************************************************************** -# Copyright (C) 2013 David Kohel +# Copyright (C) 2005 David Kohel # William Stein # 2008-2012 Nicolas M. Thiery # From 900fddcc2c5cb17263f3bf64a920c412205f0857 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Wed, 3 Apr 2024 11:04:17 +0900 Subject: [PATCH 151/191] Deprecate is_Jacobian before removing --- .../schemes/jacobians/abstract_jacobian.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/sage/schemes/jacobians/abstract_jacobian.py b/src/sage/schemes/jacobians/abstract_jacobian.py index a1b27708080..7f792df2835 100644 --- a/src/sage/schemes/jacobians/abstract_jacobian.py +++ b/src/sage/schemes/jacobians/abstract_jacobian.py @@ -28,6 +28,30 @@ _Fields = Fields() +def is_Jacobian(J): + """ + Return True if `J` is of type Jacobian_generic. + + EXAMPLES:: + + sage: from sage.schemes.jacobians.abstract_jacobian import Jacobian, is_Jacobian + sage: P2. = ProjectiveSpace(QQ, 2) + sage: C = Curve(x^3 + y^3 + z^3) + sage: J = Jacobian(C) + sage: is_Jacobian(J) + True + + :: + + sage: E = EllipticCurve('37a1') + sage: is_Jacobian(E) + False + """ + from sage.misc.superseded import deprecation + deprecation(35467, "Use Jacobian_generic directly") + return isinstance(J, Jacobian_generic) + + def Jacobian(C): """ EXAMPLES:: From d662b2094e040dba9d538774cad6de8fb510717a Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Wed, 3 Apr 2024 14:48:39 +0900 Subject: [PATCH 152/191] Fix deprecation warning in doctest --- src/sage/schemes/jacobians/abstract_jacobian.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/schemes/jacobians/abstract_jacobian.py b/src/sage/schemes/jacobians/abstract_jacobian.py index 7f792df2835..1a86025697e 100644 --- a/src/sage/schemes/jacobians/abstract_jacobian.py +++ b/src/sage/schemes/jacobians/abstract_jacobian.py @@ -39,6 +39,9 @@ def is_Jacobian(J): sage: C = Curve(x^3 + y^3 + z^3) sage: J = Jacobian(C) sage: is_Jacobian(J) + ... + DeprecationWarning: Use Jacobian_generic directly + See https://github.com/sagemath/sage/issues/35467 for details. True :: From 5f74854c259bcd7fb41000014d05386ee6157b3e Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 22 Jan 2024 13:25:44 +0000 Subject: [PATCH 153/191] Make sage-conf optional As noted in #37024 and in #36489, `sage-conf` is actually not needed on a few systems now. For this reason, we make the installation of it optional (as there are no optional install requires as far as I know, this means we remove it from `pyproject.toml` and `setup.cfg`). We also remove it from "install all dependencies via conda" as its not needed there. --- .devcontainer/onCreate-conda.sh | 3 +-- .github/workflows/ci-conda.yml | 8 ++------ .gitpod.yml | 3 +-- pkgs/sage-conf/README.rst | 2 +- src/doc/en/installation/conda.rst | 8 +++++++- src/pyproject.toml.m4 | 1 - src/setup.cfg.m4 | 1 - 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.devcontainer/onCreate-conda.sh b/.devcontainer/onCreate-conda.sh index 94b3abe9ff8..f0251185c62 100755 --- a/.devcontainer/onCreate-conda.sh +++ b/.devcontainer/onCreate-conda.sh @@ -8,6 +8,5 @@ conda init bash # Build sage conda run -n sage-dev ./bootstrap -conda run -n sage-dev ./configure --with-python=/opt/conda/envs/sage-dev/bin/python --prefix=/opt/conda/envs/sage-dev -conda run -n sage-dev pip install --no-build-isolation -v -v -e ./pkgs/sage-conf ./pkgs/sage-setup +conda run -n sage-dev pip install --no-build-isolation -v -v -e ./pkgs/sage-setup conda run -n sage-dev pip install --no-build-isolation -v -v -e ./src diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index a0f3c021643..b01b041a975 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -77,21 +77,17 @@ jobs: conda info conda list - - name: Configure + - name: Bootstrap shell: bash -l {0} continue-on-error: true run: | ./bootstrap - echo "::add-matcher::.github/workflows/configure-systempackage-problem-matcher.json" - ./configure --enable-build-as-root --with-python=$CONDA_PREFIX/bin/python --prefix=$CONDA_PREFIX --enable-system-site-packages $(for pkg in $(./sage -package list :standard: --has-file spkg-configure.m4 --has-file distros/conda.txt --exclude rpy2); do echo --with-system-$pkg=force; done) - echo "::remove-matcher owner=configure-system-package-warning::" - echo "::remove-matcher owner=configure-system-package-error::" - name: Build shell: bash -l {0} run: | # Use --no-deps and pip check below to verify that all necessary dependencies are installed via conda. - pip install --no-build-isolation --no-deps -v -v -e ./pkgs/sage-conf ./pkgs/sage-setup + pip install --no-build-isolation --no-deps -v -v -e ./pkgs/sage-setup pip install --no-build-isolation --no-deps --config-settings editable_mode=compat -v -v -e ./src env: SAGE_NUM_THREADS: 2 diff --git a/.gitpod.yml b/.gitpod.yml index 223e750bd63..a91131f4e7a 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -11,8 +11,7 @@ tasks: && conda config --append envs_dirs $(pwd) && conda activate $(pwd)/venv && ./bootstrap - && ./configure --enable-build-as-root --with-python=$CONDA_PREFIX/bin/python --prefix=$CONDA_PREFIX - && pip install --no-build-isolation -v -v -e ./pkgs/sage-conf ./pkgs/sage-setup + && pip install --no-build-isolation -v -v -e ./pkgs/sage-setup && pip install --no-build-isolation -v -v -e ./src # Activate conda environment, set up Trac remote # RestructuredText extension recommends python extension, although we have already installed it diff --git a/pkgs/sage-conf/README.rst b/pkgs/sage-conf/README.rst index 590e5ba1356..e86c483c089 100644 --- a/pkgs/sage-conf/README.rst +++ b/pkgs/sage-conf/README.rst @@ -87,7 +87,7 @@ 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 +may be used in an 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 diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 8e514f3a529..2191374cea2 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -138,9 +138,15 @@ Here we assume that you are using a git checkout. - Bootstrap the source tree and install the build prerequisites and the Sage library:: $ ./bootstrap - $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf_conda ./pkgs/sage-setup + $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-setup $ pip install --no-build-isolation --config-settings editable_mode=compat -v -v --editable ./src + If you encounter any errors, try to install the ``sage-conf`` package first:: + + $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf_conda + + and then run the last command again. + - Verify that Sage has been installed:: $ sage -c 'print(version())' diff --git a/src/pyproject.toml.m4 b/src/pyproject.toml.m4 index 7065ba1468c..084c5a45ead 100644 --- a/src/pyproject.toml.m4 +++ b/src/pyproject.toml.m4 @@ -6,7 +6,6 @@ requires = [ # Note that PEP517/518 have no notion of optional sage_spkg dependencies: # https://github.com/pypa/pip/issues/6144 esyscmd(`sage-get-system-packages install-requires-toml \ - sage_conf \ setuptools \ wheel \ sage_setup \ diff --git a/src/setup.cfg.m4 b/src/setup.cfg.m4 index e2a3330518d..c06001fd105 100644 --- a/src/setup.cfg.m4 +++ b/src/setup.cfg.m4 @@ -11,7 +11,6 @@ include(`setup_cfg_metadata.m4')dnl' [options] python_requires = >=3.9, <3.13 install_requires = - SPKG_INSTALL_REQUIRES_sage_conf SPKG_INSTALL_REQUIRES_six dnl From build/pkgs/sagelib/dependencies SPKG_INSTALL_REQUIRES_conway_polynomials From 5bcb9d47707ad9a373ba052fffe0b1c2af0302e2 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 11 Apr 2024 11:48:01 +0800 Subject: [PATCH 154/191] Remove outdated comment --- src/pyproject.toml.m4 | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pyproject.toml.m4 b/src/pyproject.toml.m4 index 084c5a45ead..7406c7ff359 100644 --- a/src/pyproject.toml.m4 +++ b/src/pyproject.toml.m4 @@ -2,9 +2,6 @@ # Minimum requirements for the build system to execute. requires = [ "sage_setup[autogen]", - # Some version of sage-conf is required. - # Note that PEP517/518 have no notion of optional sage_spkg dependencies: - # https://github.com/pypa/pip/issues/6144 esyscmd(`sage-get-system-packages install-requires-toml \ setuptools \ wheel \ From 0e7520c71adcb3ffcfdc36202dc3eab1b8467e50 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 11 Feb 2024 13:56:47 -0800 Subject: [PATCH 155/191] build/pkgs/python_build: Change to a normal standard package --- build/pkgs/python_build/checksums.ini | 5 +++++ .../python_build/{requirements.txt => install-requires.txt} | 0 build/pkgs/python_build/package-version.txt | 1 + build/pkgs/python_build/type | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/python_build/checksums.ini rename build/pkgs/python_build/{requirements.txt => install-requires.txt} (100%) create mode 100644 build/pkgs/python_build/package-version.txt diff --git a/build/pkgs/python_build/checksums.ini b/build/pkgs/python_build/checksums.ini new file mode 100644 index 00000000000..1316cf9cbe9 --- /dev/null +++ b/build/pkgs/python_build/checksums.ini @@ -0,0 +1,5 @@ +tarball=build-VERSION-py3-none-any.whl +sha1=14566af639ccc4387c8dd5b477fdb3ad9d98f92d +md5=505b77c45a8f2b92b8a2eca43c14a688 +cksum=205854257 +upstream_url=https://pypi.io/packages/py3/b/build/build-VERSION-py3-none-any.whl diff --git a/build/pkgs/python_build/requirements.txt b/build/pkgs/python_build/install-requires.txt similarity index 100% rename from build/pkgs/python_build/requirements.txt rename to build/pkgs/python_build/install-requires.txt diff --git a/build/pkgs/python_build/package-version.txt b/build/pkgs/python_build/package-version.txt new file mode 100644 index 00000000000..21e8796a09d --- /dev/null +++ b/build/pkgs/python_build/package-version.txt @@ -0,0 +1 @@ +1.0.3 diff --git a/build/pkgs/python_build/type b/build/pkgs/python_build/type index 134d9bc32d5..a6a7b9cd726 100644 --- a/build/pkgs/python_build/type +++ b/build/pkgs/python_build/type @@ -1 +1 @@ -optional +standard From b9c6d3303373934b64d631cf7bca73e86b84e8e0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 11 Feb 2024 14:37:06 -0800 Subject: [PATCH 156/191] build/pkgs/pyproject_hooks: New, python_build dependency --- build/pkgs/pyproject_hooks/SPKG.rst | 16 ++++++++++++++++ build/pkgs/pyproject_hooks/checksums.ini | 5 +++++ build/pkgs/pyproject_hooks/dependencies | 4 ++++ build/pkgs/pyproject_hooks/install-requires.txt | 1 + build/pkgs/pyproject_hooks/package-version.txt | 1 + build/pkgs/pyproject_hooks/type | 1 + 6 files changed, 28 insertions(+) create mode 100644 build/pkgs/pyproject_hooks/SPKG.rst create mode 100644 build/pkgs/pyproject_hooks/checksums.ini create mode 100644 build/pkgs/pyproject_hooks/dependencies create mode 100644 build/pkgs/pyproject_hooks/install-requires.txt create mode 100644 build/pkgs/pyproject_hooks/package-version.txt create mode 100644 build/pkgs/pyproject_hooks/type diff --git a/build/pkgs/pyproject_hooks/SPKG.rst b/build/pkgs/pyproject_hooks/SPKG.rst new file mode 100644 index 00000000000..31d8461a48d --- /dev/null +++ b/build/pkgs/pyproject_hooks/SPKG.rst @@ -0,0 +1,16 @@ +pyproject_hooks: Wrappers to call pyproject.toml-based build backend hooks. +=========================================================================== + +Description +----------- + +Wrappers to call pyproject.toml-based build backend hooks. + +License +------- + +Upstream Contact +---------------- + +https://pypi.org/project/pyproject_hooks/ + diff --git a/build/pkgs/pyproject_hooks/checksums.ini b/build/pkgs/pyproject_hooks/checksums.ini new file mode 100644 index 00000000000..f35e59aa59f --- /dev/null +++ b/build/pkgs/pyproject_hooks/checksums.ini @@ -0,0 +1,5 @@ +tarball=pyproject_hooks-VERSION-py3-none-any.whl +sha1=6c99163c52786fb97eac8b4e38cc13fa3af141a9 +md5=68020c2619c7a744dcee12b670c9f413 +cksum=3405759428 +upstream_url=https://pypi.io/packages/py3/p/pyproject_hooks/pyproject_hooks-VERSION-py3-none-any.whl diff --git a/build/pkgs/pyproject_hooks/dependencies b/build/pkgs/pyproject_hooks/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/pyproject_hooks/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/pyproject_hooks/install-requires.txt b/build/pkgs/pyproject_hooks/install-requires.txt new file mode 100644 index 00000000000..1f783738e6f --- /dev/null +++ b/build/pkgs/pyproject_hooks/install-requires.txt @@ -0,0 +1 @@ +pyproject_hooks diff --git a/build/pkgs/pyproject_hooks/package-version.txt b/build/pkgs/pyproject_hooks/package-version.txt new file mode 100644 index 00000000000..3eefcb9dd5b --- /dev/null +++ b/build/pkgs/pyproject_hooks/package-version.txt @@ -0,0 +1 @@ +1.0.0 diff --git a/build/pkgs/pyproject_hooks/type b/build/pkgs/pyproject_hooks/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/pyproject_hooks/type @@ -0,0 +1 @@ +standard From 36c1b026161a233957626fd99959e0af8ab31907 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Apr 2024 20:21:44 -0700 Subject: [PATCH 157/191] for a in build/pkgs/*; do (cd build/pkgs/zlib && if [ -r install-requires.txt ]; then git mv install-requires.txt version_requirements.txt; fi); done --- .../{install-requires.txt => version_requirements.txt} | 0 .../{install-requires.txt => version_requirements.txt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename build/pkgs/pyproject_hooks/{install-requires.txt => version_requirements.txt} (100%) rename build/pkgs/python_build/{install-requires.txt => version_requirements.txt} (100%) diff --git a/build/pkgs/pyproject_hooks/install-requires.txt b/build/pkgs/pyproject_hooks/version_requirements.txt similarity index 100% rename from build/pkgs/pyproject_hooks/install-requires.txt rename to build/pkgs/pyproject_hooks/version_requirements.txt diff --git a/build/pkgs/python_build/install-requires.txt b/build/pkgs/python_build/version_requirements.txt similarity index 100% rename from build/pkgs/python_build/install-requires.txt rename to build/pkgs/python_build/version_requirements.txt From c186c99b2c52bde4ed6481d3d10a4076a27fd42a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Apr 2024 20:22:06 -0700 Subject: [PATCH 158/191] build/pkgs/python_build: Update to 1.2.1 --- build/pkgs/python_build/checksums.ini | 6 +++--- build/pkgs/python_build/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/python_build/checksums.ini b/build/pkgs/python_build/checksums.ini index 1316cf9cbe9..df10f8d3196 100644 --- a/build/pkgs/python_build/checksums.ini +++ b/build/pkgs/python_build/checksums.ini @@ -1,5 +1,5 @@ tarball=build-VERSION-py3-none-any.whl -sha1=14566af639ccc4387c8dd5b477fdb3ad9d98f92d -md5=505b77c45a8f2b92b8a2eca43c14a688 -cksum=205854257 +sha1=950bf228726af5041adbe2bb04a7ca74e27bce60 +md5=6f34942a01c3307b42556ee7628f3d1d +cksum=4005002353 upstream_url=https://pypi.io/packages/py3/b/build/build-VERSION-py3-none-any.whl diff --git a/build/pkgs/python_build/package-version.txt b/build/pkgs/python_build/package-version.txt index 21e8796a09d..6085e946503 100644 --- a/build/pkgs/python_build/package-version.txt +++ b/build/pkgs/python_build/package-version.txt @@ -1 +1 @@ -1.0.3 +1.2.1 From 3d026342df5fed10cd91aa931c567d16bbfc2e63 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Apr 2024 20:28:16 -0700 Subject: [PATCH 159/191] build/pkgs/python_build/dependencies: Update --- build/pkgs/python_build/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/python_build/dependencies b/build/pkgs/python_build/dependencies index b72a6d1c776..af994ec1059 100644 --- a/build/pkgs/python_build/dependencies +++ b/build/pkgs/python_build/dependencies @@ -1,4 +1,4 @@ - pyparsing tomli packaging | $(PYTHON_TOOLCHAIN) $(PYTHON) +tomli packaging pyproject_hooks importlib_metadata | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. From 6683de7827bdc164b2c628e259f1305ca845c485 Mon Sep 17 00:00:00 2001 From: Nolord <33145668+Nolord@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:27:07 +0200 Subject: [PATCH 160/191] equivalent but more readable Co-authored-by: Travis Scrimshaw --- src/sage/combinat/set_partition_iterator.pyx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/set_partition_iterator.pyx b/src/sage/combinat/set_partition_iterator.pyx index 39eb7d0d645..33e4ad41958 100644 --- a/src/sage/combinat/set_partition_iterator.pyx +++ b/src/sage/combinat/set_partition_iterator.pyx @@ -129,6 +129,7 @@ def set_partition_iterator_blocks(base_set, Py_ssize_t k): cdef Py_ssize_t n = len(base) cdef list a = list(range(n)) # TODO: implement _set_partition_block_gen as an iterative algorithm - if n >= k: - for P in _set_partition_block_gen(n, k, a): - yield from_word( P, base) + if n < k: + return + for P in _set_partition_block_gen(n, k, a): + yield from_word( P, base) From 9db7f54cb1a10a7bcdbf97799448aab643e57bae Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Mon, 15 Apr 2024 10:50:31 +0200 Subject: [PATCH 161/191] Replaced comparison methods by `__richcmp__` Credit to @tscrim for the help on how to do this! --- .../algebras/quatalg/quaternion_algebra.py | 113 +++++------------- 1 file changed, 29 insertions(+), 84 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 91e4a326371..ebc9292688a 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -83,6 +83,8 @@ from sage.categories.algebras import Algebras from sage.categories.number_fields import NumberFields +from sage.structure.richcmp import richcmp_method + ######################################################## # Constructor ######################################################## @@ -1526,6 +1528,7 @@ def unpickle_QuaternionAlgebra_v0(*key): return QuaternionAlgebra(*key) +@richcmp_method class QuaternionOrder(Parent): """ An order in a quaternion algebra. @@ -1739,116 +1742,58 @@ def gen(self, n): """ return self.__basis[n] - def __eq__(self, other): + def __richcmp__(self, other, op): """ - Compare orders ``self`` and ``other``. + Compare this quaternion order to ``other``. EXAMPLES:: - sage: R = QuaternionAlgebra(-11,-1).maximal_order() + sage: R = QuaternionAlgebra(-1, -11).maximal_order() sage: R == R # indirect doctest True - sage: R == QuaternionAlgebra(-1,-1).maximal_order() - False sage: R == 5 False - sage: Q. = QuaternionAlgebra(-1,-19) + sage: R == QuaternionAlgebra(-1, -7).maximal_order() + False Orders can be equal even if they are defined by different bases (see :issue:`32245`):: + sage: Q. = QuaternionAlgebra(-1, -19) sage: Q.quaternion_order([1,-i,k,j+i*7]) == Q.quaternion_order([1,i,j,k]) True - """ - if not isinstance(other, QuaternionOrder): - return False - return (self.__quaternion_algebra == other.__quaternion_algebra and - self.unit_ideal() == other.unit_ideal()) - - def __ne__(self, other): - """ - Compare orders ``self`` and ``other``. - - Two orders are equal if they have the same - basis and are in the same quaternion algebra. - - EXAMPLES:: - - sage: R = QuaternionAlgebra(-11,-1).maximal_order() - sage: R != R # indirect doctest - False - sage: R != QuaternionAlgebra(-1,-1).maximal_order() - True - """ - return not self.__eq__(other) - - def __le__(self, other): - """ - Compare orders ``self`` and ``other``. - EXAMPLES:: + TESTS:: - sage: B. = QuaternionAlgebra(-1, -11) + sage: B = QuaternionAlgebra(-1, -11) + sage: i,j,k = B.gens() sage: O = B.quaternion_order([1,i,j,k]) - sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) - sage: O <= R + sage: O == O True - sage: R <= O - False - """ - if not isinstance(other, QuaternionOrder): - return False - return self.unit_ideal().__le__(other.unit_ideal()) - - def __lt__(self, other): - """ - Compare orders ``self`` and ``other``. - - EXAMPLES:: - - sage: B. = QuaternionAlgebra(-1, -11) - sage: O = B.quaternion_order([1,i,j,k]) sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) - sage: O < R + sage: O <= R # indirect doctest True - sage: R < O - False - """ - return self.__le__(other) and self.__ne__(other) - - def __ge__(self, other): - """ - Compare orders ``self`` and ``other``. - - EXAMPLES:: - - sage: B. = QuaternionAlgebra(-1, -11) - sage: O = B.quaternion_order([1,i,j,k]) - sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) sage: O >= R False - sage: R >= O + sage: O != R True - """ - if not isinstance(other, QuaternionOrder): - return False - return self.unit_ideal().__ge__(other.unit_ideal()) - - def __gt__(self, other): - """ - Compare orders ``self`` and ``other``. - - EXAMPLES:: - - sage: B. = QuaternionAlgebra(-1, -11) - sage: O = B.quaternion_order([1,i,j,k]) - sage: R = B.quaternion_order([1,i,(i+j)/2,(1+k)/2]) - sage: O > R + sage: O == R + False + sage: O != O False - sage: R > O + sage: O < O + False + sage: O < R + True + sage: O <= O + True + sage: R >= R True """ - return self.__ge__(other) and self.__ne__(other) + from sage.structure.richcmp import richcmp, op_NE + if not isinstance(other, QuaternionOrder): + return op == op_NE + return richcmp(self.unit_ideal(), other.unit_ideal(), op) def __hash__(self): """ From 14304926b22ea66bb4fd4427a64f8cc9cdd2c0e9 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Wed, 17 Apr 2024 13:09:08 +0200 Subject: [PATCH 162/191] fix doctest --- src/sage/combinat/sf/sfa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 56a32dea180..afa2e6653e7 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -6636,7 +6636,7 @@ def _apply_functor(self, R): sage: F(QQ) Traceback (most recent call last): ... - TypeError: not a constant polynomial + TypeError: t is not a constant polynomial """ from sage.combinat.sf.sf import SymmetricFunctions return self._basis(self._family(SymmetricFunctions(R), *self._args)) From b98072981ef1b182bc9e0a68b65062a6496b268a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 14:44:53 -0700 Subject: [PATCH 163/191] src/sage/modules/matrix_morphism.py: Deprecate is_MatrixMorphism --- src/sage/modules/matrix_morphism.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index ab194038d93..0fca483b977 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -20,8 +20,6 @@ [1 0 0] [0 1 0] [0 0 1] - sage: is_MatrixMorphism(m) - True sage: m.charpoly('x') # needs sage.libs.pari x^3 - 3*x^2 + 3*x - 1 sage: m.base_ring() @@ -66,10 +64,18 @@ def is_MatrixMorphism(x): sage: V = ZZ^2; phi = V.hom([3*V.0, 2*V.1]) sage: sage.modules.matrix_morphism.is_MatrixMorphism(phi) + doctest:warning... + DeprecationWarning: is_MatrixMorphism is deprecated; + use isinstance(..., MatrixMorphism_abstract) or categories instead + See https://github.com/sagemath/sage/issues/99999 for details. True sage: sage.modules.matrix_morphism.is_MatrixMorphism(3) False """ + from sage.misc.superseded import deprecation + deprecation(99999, + "is_MatrixMorphism is deprecated; " + "use isinstance(..., MatrixMorphism_abstract) or categories instead") return isinstance(x, MatrixMorphism_abstract) @@ -1367,7 +1373,7 @@ def is_equal_function(self, other): - Rob Beezer (2011-07-15) """ - if not is_MatrixMorphism(other): + if not isinstance(other, MatrixMorphism_abstract): msg = 'can only compare to a matrix morphism, not {0}' raise TypeError(msg.format(other)) if self.domain() != other.domain(): From 1d762946fd69334e902aed939459b8bebf9a9f07 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 15:15:40 -0700 Subject: [PATCH 164/191] MatrixMorphism_abstract.{charpoly,det,fcp,trace}: Move to category --- .../finite_dimensional_modules_with_basis.py | 82 +++++++++++++++++++ src/sage/modules/matrix_morphism.py | 69 ---------------- 2 files changed, 82 insertions(+), 69 deletions(-) diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 7cf24baa57d..35d19f54205 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -15,6 +15,8 @@ from sage.categories.fields import Fields from sage.categories.tensor import TensorProductsCategory from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute + class FiniteDimensionalModulesWithBasis(CategoryWithAxiom_over_base_ring): """ @@ -798,6 +800,86 @@ def image(self): return C.submodule(self.image_basis(), already_echelonized=True, category=self.category_for()) + @lazy_attribute + def characteristic_polynomial(self): + r""" + Return the characteristic polynomial of this endomorphism. + + :meth:`characteristic_polynomial` and :meth:`char_poly` are the same method. + + INPUT: + + - ``var`` -- variable + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.characteristic_polynomial() + x^2 - 3*x + 2 + sage: phi.charpoly() + x^2 - 3*x + 2 + sage: phi.matrix().charpoly() + x^2 - 3*x + 2 + sage: phi.charpoly('T') + T^2 - 3*T + 2 + """ + if not self.is_endomorphism(): + return NotImplemented + return self.matrix().charpoly + + charpoly = characteristic_polynomial + + @lazy_attribute + def det(self): + """ + Return the determinant of this endomorphism. + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.det() + 2 + """ + if not self.is_endomorphism(): + return NotImplemented + return self.matrix().determinant + + @lazy_attribute + def fcp(self): + """ + Return the factorization of the characteristic polynomial. + + INPUT: + + - ``var`` -- variable + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.fcp() # needs sage.libs.pari + (x - 2) * (x - 1) + sage: phi.fcp('T') # needs sage.libs.pari + (T - 2) * (T - 1) + """ + if not self.is_endomorphism(): + return NotImplemented + return self.matrix().fcp + + @lazy_attribute + def trace(self): + r""" + Return the trace of this endomorphism. + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.trace() + 3 + """ + if not self.is_endomorphism(): + return NotImplemented + return self.matrix().trace + class TensorProducts(TensorProductsCategory): def extra_super_categories(self): diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index 0fca483b977..5d67b34111b 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -806,35 +806,6 @@ def base_ring(self): """ return self.domain().base_ring() - def characteristic_polynomial(self, var='x'): - r""" - Return the characteristic polynomial of this endomorphism. - - ``characteristic_polynomial`` and ``char_poly`` are the same method. - - INPUT: - - - var -- variable - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0+V.1, 2*V.1]) - sage: phi.characteristic_polynomial() - x^2 - 3*x + 2 - sage: phi.charpoly() - x^2 - 3*x + 2 - sage: phi.matrix().charpoly() - x^2 - 3*x + 2 - sage: phi.charpoly('T') - T^2 - 3*T + 2 - """ - if not self.is_endomorphism(): - raise ArithmeticError("charpoly only defined for endomorphisms " - "(i.e., domain = range)") - return self.matrix().charpoly(var) - - charpoly = characteristic_polynomial - def decomposition(self, *args, **kwds): """ Return decomposition of this endomorphism, i.e., sequence of @@ -884,46 +855,6 @@ def decomposition(self, *args, **kwds): check=False) for V, _ in E], cr=True, check=False) - def trace(self): - r""" - Return the trace of this endomorphism. - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.trace() - 3 - """ - return self._matrix.trace() - - def det(self): - """ - Return the determinant of this endomorphism. - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.det() - 2 - """ - if not self.is_endomorphism(): - raise ArithmeticError("matrix morphism must be an endomorphism") - return self.matrix().determinant() - - def fcp(self, var='x'): - """ - Return the factorization of the characteristic polynomial. - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.fcp() # needs sage.libs.pari - (x - 2) * (x - 1) - sage: phi.fcp('T') # needs sage.libs.pari - (T - 2) * (T - 1) - """ - return self.charpoly(var).factor() - def kernel(self): """ Compute the kernel of this morphism. From a9d6761ec8e65e464f577e8f928769337ee77c80 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 15:35:43 -0700 Subject: [PATCH 165/191] FiniteDimensionalModulesWithBasis.MorphismMethods.{charpoly,det,fcp,trace}: Add CombinatorialFreeModule examples --- .../finite_dimensional_modules_with_basis.py | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 35d19f54205..82cc0fc36a5 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -839,6 +839,12 @@ def det(self): sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) sage: phi.det() 2 + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: phi.det() + 2 """ if not self.is_endomorphism(): return NotImplemented @@ -856,10 +862,16 @@ def fcp(self): EXAMPLES:: sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.fcp() # needs sage.libs.pari + sage: phi.fcp() # needs sage.libs.pari (x - 2) * (x - 1) - sage: phi.fcp('T') # needs sage.libs.pari + sage: phi.fcp('T') # needs sage.libs.pari (T - 2) * (T - 1) + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.fcp() # needs sage.libs.pari + (x - 2) * (x - 1) """ if not self.is_endomorphism(): return NotImplemented @@ -875,6 +887,12 @@ def trace(self): sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) sage: phi.trace() 3 + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.trace() + 3 """ if not self.is_endomorphism(): return NotImplemented From cb90891bd093c48e07c8483f6627be79727ee31f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 15:50:56 -0700 Subject: [PATCH 166/191] FiniteDimensionalModulesWithBasis.MorphismMethods: Define both det and determinant --- .../categories/finite_dimensional_modules_with_basis.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 82cc0fc36a5..89924be8308 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -830,13 +830,17 @@ def characteristic_polynomial(self): charpoly = characteristic_polynomial @lazy_attribute - def det(self): + def determinant(self): """ Return the determinant of this endomorphism. + :meth:`determinant` and :meth:`det` are the same method. + EXAMPLES:: sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.determinant() + 2 sage: phi.det() 2 @@ -850,6 +854,8 @@ def det(self): return NotImplemented return self.matrix().determinant + det = determinant + @lazy_attribute def fcp(self): """ From 4dcf44d0bbe9f8508870d34710437f29622d8fef Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 16:08:40 -0700 Subject: [PATCH 167/191] FiniteDimensionalModulesWithBasis.MorphismMethods: Add methods minpoly, minimal_polynomial --- .../finite_dimensional_modules_with_basis.py | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 89924be8308..988e8de9d36 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -805,7 +805,7 @@ def characteristic_polynomial(self): r""" Return the characteristic polynomial of this endomorphism. - :meth:`characteristic_polynomial` and :meth:`char_poly` are the same method. + :meth:`characteristic_polynomial` and :meth:`charpoly` are the same method. INPUT: @@ -822,6 +822,12 @@ def characteristic_polynomial(self): x^2 - 3*x + 2 sage: phi.charpoly('T') T^2 - 3*T + 2 + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.charpoly() + x^2 - 3*x + 2 """ if not self.is_endomorphism(): return NotImplemented @@ -847,7 +853,7 @@ def determinant(self): sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) sage: M = matrix(ZZ, [[1, 0], [1, 2]]) sage: psi = W.module_morphism(matrix=M, codomain=W) - sage: phi.det() + sage: psi.det() 2 """ if not self.is_endomorphism(): @@ -883,6 +889,37 @@ def fcp(self): return NotImplemented return self.matrix().fcp + @lazy_attribute + def minimal_polynomial(self): + r""" + Return the minimal polynomial of this endomorphism. + + :meth:`minimal_polynomial` and :meth:`minpoly` are the same method. + + INPUT: + + - ``var`` -- variable + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: k = GF(9, 'c') + sage: V = CombinatorialFreeModule(k, ['x', 'y', 'z', 'w']) + sage: A = matrix(k, 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) + sage: phi = V.module_morphism(matrix=A, codomain=V) + sage: factor(phi.minpoly()) + (x + 1) * (x + 2)^2 + sage: A.minpoly()(A) == 0 + True + sage: factor(phi.charpoly()) + (x + 1)^2 * (x + 2)^2 + """ + if not self.is_endomorphism(): + return NotImplemented + return self.matrix().minimal_polynomial + + minpoly = minimal_polynomial + @lazy_attribute def trace(self): r""" From 9c1e39315f7bfa7dc9082eb4862a099504930e69 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 8 Apr 2024 16:58:11 -0700 Subject: [PATCH 168/191] Remove FreeModuleMorphism.minpoly, move doctest to category method --- .../finite_dimensional_modules_with_basis.py | 26 +++++++++- src/sage/modules/free_module_morphism.py | 49 ------------------- 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 988e8de9d36..36716e336d3 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -898,9 +898,31 @@ def minimal_polynomial(self): INPUT: - - ``var`` -- variable + - ``var`` -- string (default: ``'x'``); a variable name - EXAMPLES:: + EXAMPLES: + + Compute the minimal polynomial, and check it. :: + + sage: V = GF(7)^3 + sage: H = V.Hom(V)([[0,1,2], [-1,0,3], [2,4,1]]); H + Vector space morphism represented by the matrix: + [0 1 2] + [6 0 3] + [2 4 1] + Domain: Vector space of dimension 3 over Finite Field of size 7 + Codomain: Vector space of dimension 3 over Finite Field of size 7 + sage: H.minpoly() # needs sage.libs.pari + x^3 + 6*x^2 + 6*x + 1 + sage: H.minimal_polynomial() # needs sage.libs.pari + x^3 + 6*x^2 + 6*x + 1 + sage: H^3 + (H^2)*6 + H*6 + 1 + Vector space morphism represented by the matrix: + [0 0 0] + [0 0 0] + [0 0 0] + Domain: Vector space of dimension 3 over Finite Field of size 7 + Codomain: Vector space of dimension 3 over Finite Field of size 7 sage: # needs sage.rings.finite_rings sage: k = GF(9, 'c') diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index 3fdd76bff6f..e7d5e8e1c5b 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -636,55 +636,6 @@ def eigenspaces(self, extend=True): return [(vec[0], Sequence(vec[1]).universe().subspace(vec[1])) for vec in ev] - def minimal_polynomial(self, var='x'): - r""" - Computes the minimal polynomial. - - ``minpoly()`` and ``minimal_polynomial()`` are the same method. - - INPUT: - - - ``var`` - string (default: 'x') a variable name - - OUTPUT: - - polynomial in var - the minimal polynomial of the endomorphism. - - EXAMPLES: - - Compute the minimal polynomial, and check it. :: - - sage: V = GF(7)^3 - sage: H = V.Hom(V)([[0,1,2], [-1,0,3], [2,4,1]]) - sage: H - Vector space morphism represented by the matrix: - [0 1 2] - [6 0 3] - [2 4 1] - Domain: Vector space of dimension 3 over Finite Field of size 7 - Codomain: Vector space of dimension 3 over Finite Field of size 7 - - sage: H.minpoly() # needs sage.libs.pari - x^3 + 6*x^2 + 6*x + 1 - - sage: H.minimal_polynomial() # needs sage.libs.pari - x^3 + 6*x^2 + 6*x + 1 - - sage: H^3 + (H^2)*6 + H*6 + 1 - Vector space morphism represented by the matrix: - [0 0 0] - [0 0 0] - [0 0 0] - Domain: Vector space of dimension 3 over Finite Field of size 7 - Codomain: Vector space of dimension 3 over Finite Field of size 7 - """ - if self.is_endomorphism(): - return self.matrix().minpoly(var) - else: - raise TypeError("not an endomorphism") - - minpoly = minimal_polynomial - class BaseIsomorphism1D(Morphism): """ From e9a9c060c209f449ba5bf4912624d77127694d34 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 18:53:48 -0700 Subject: [PATCH 169/191] MatrixMorphism_abstract, FreeModuleMorphism: Copy in methods from category --- src/sage/modules/free_module_morphism.py | 4 ++++ src/sage/modules/matrix_morphism.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index e7d5e8e1c5b..c1ad9221ae4 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -42,6 +42,7 @@ # be coercible into vector space of appropriate dimension. import sage.modules.free_module as free_module +from sage.categories.finite_dimensional_modules_with_basis import FiniteDimensionalModulesWithBasis from sage.categories.morphism import Morphism from sage.modules import free_module_homspace, matrix_morphism from sage.structure.richcmp import rich_to_bool, richcmp @@ -62,6 +63,9 @@ def is_FreeModuleMorphism(x): class FreeModuleMorphism(matrix_morphism.MatrixMorphism): + + minimal_polynomial = minpoly = FiniteDimensionalModulesWithBasis.MorphismMethods.minimal_polynomial + def __init__(self, parent, A, side="left"): """ INPUT: diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index 5d67b34111b..129bc02d578 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -52,6 +52,7 @@ import sage.categories.morphism import sage.categories.homset +from sage.categories.finite_dimensional_modules_with_basis import FiniteDimensionalModulesWithBasis from sage.structure.all import Sequence, parent from sage.structure.richcmp import richcmp, op_NE, op_EQ @@ -80,6 +81,17 @@ def is_MatrixMorphism(x): class MatrixMorphism_abstract(sage.categories.morphism.Morphism): + + # Copy in methods that delegate to self.matrix. + # This is needed because MatrixMorphism_abstract is subclassed + # for use with parents that are merely set up as additive abelian groups, + # but not as ZZ-modules; see sage.modular.abvar. + + characteristic_polynomial = charpoly = FiniteDimensionalModulesWithBasis.MorphismMethods.characteristic_polynomial + det = determinant = FiniteDimensionalModulesWithBasis.MorphismMethods.determinant + fcp = FiniteDimensionalModulesWithBasis.MorphismMethods.fcp + trace = FiniteDimensionalModulesWithBasis.MorphismMethods.trace + def __init__(self, parent, side='left'): """ INPUT: From a40402bfca9deed2994f698b02e35c4d1e631c5d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 19:18:01 -0700 Subject: [PATCH 170/191] src/sage/modular/abvar/morphism.py (HeckeOperator): Override method fcp to make it compatible with custom charpoly --- src/sage/modular/abvar/morphism.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/sage/modular/abvar/morphism.py b/src/sage/modular/abvar/morphism.py index b85cc670df9..e6b2339d44c 100644 --- a/src/sage/modular/abvar/morphism.py +++ b/src/sage/modular/abvar/morphism.py @@ -870,6 +870,20 @@ def charpoly(self, var='x'): """ return self.characteristic_polynomial(var) + def fcp(self, var='x'): + """ + Return the factorization of the characteristic polynomial. + + EXAMPLES:: + + sage: t2 = J0(33).hecke_operator(2) + sage: t2.charpoly() + x^3 + 3*x^2 - 4 + sage: t2.fcp() + (x - 1) * (x + 2)^2 + """ + return self.charpoly(var).factor() + def action_on_homology(self, R=ZZ): r""" Return the action of this Hecke operator on the homology From b1a0ad5dfc932e954497849801c6dadeede8d9ab Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 19:21:36 -0700 Subject: [PATCH 171/191] src/sage/modules/matrix_morphism.py: Fill in PR number in deprecation --- src/sage/modules/matrix_morphism.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index 129bc02d578..3e053d043fb 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -61,6 +61,8 @@ def is_MatrixMorphism(x): """ Return True if x is a Matrix morphism of free modules. + This function is deprecated. + EXAMPLES:: sage: V = ZZ^2; phi = V.hom([3*V.0, 2*V.1]) @@ -74,7 +76,7 @@ def is_MatrixMorphism(x): False """ from sage.misc.superseded import deprecation - deprecation(99999, + deprecation(37731, "is_MatrixMorphism is deprecated; " "use isinstance(..., MatrixMorphism_abstract) or categories instead") return isinstance(x, MatrixMorphism_abstract) From 49ed055056a9370a849562773128ee5bb23c6ac9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 2 Apr 2024 19:44:16 -0700 Subject: [PATCH 172/191] is_FreeModuleMorphism, is_VectorSpaceMorphism: Deprecate --- src/sage/geometry/fan_morphism.py | 5 ++--- src/sage/modules/free_module_morphism.py | 10 ++++++++++ src/sage/modules/matrix_morphism.py | 2 +- src/sage/modules/vector_space_homspace.py | 4 ++-- src/sage/modules/vector_space_morphism.py | 10 ++++++++++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/sage/geometry/fan_morphism.py b/src/sage/geometry/fan_morphism.py index fa1d82889d9..2602132e40b 100644 --- a/src/sage/geometry/fan_morphism.py +++ b/src/sage/geometry/fan_morphism.py @@ -89,8 +89,7 @@ from sage.misc.latex import latex from sage.misc.misc import walltime from sage.misc.misc_c import prod -from sage.modules.free_module_morphism import (FreeModuleMorphism, - is_FreeModuleMorphism) +from sage.modules.free_module_morphism import FreeModuleMorphism from sage.rings.infinity import Infinity from sage.rings.integer_ring import ZZ from sage.rings.infinity import is_Infinite @@ -277,7 +276,7 @@ def __init__(self, morphism, domain_fan, codomain, codomain_fan = codomain.lattice(), codomain else: codomain_fan = None - if is_FreeModuleMorphism(morphism): + if isinstance(morphism, FreeModuleMorphism): parent = morphism.parent() A = morphism.matrix() elif is_Matrix(morphism): diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index c1ad9221ae4..9f2c2648136 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -51,14 +51,24 @@ def is_FreeModuleMorphism(x): """ + This function is deprecated. + EXAMPLES:: sage: V = ZZ^2; f = V.hom([V.1, -2*V.0]) sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(f) + doctest:warning... + DeprecationWarning: is_FreeModuleMorphism is deprecated; + use isinstance(..., FreeModuleMorphism) or categories instead + See https://github.com/sagemath/sage/issues/37731 for details. True sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(0) False """ + from sage.misc.superseded import deprecation + deprecation(37731, + "is_FreeModuleMorphism is deprecated; " + "use isinstance(..., FreeModuleMorphism) or categories instead") return isinstance(x, FreeModuleMorphism) diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index 3e053d043fb..bbb4e75c35e 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -70,7 +70,7 @@ def is_MatrixMorphism(x): doctest:warning... DeprecationWarning: is_MatrixMorphism is deprecated; use isinstance(..., MatrixMorphism_abstract) or categories instead - See https://github.com/sagemath/sage/issues/99999 for details. + See https://github.com/sagemath/sage/issues/37731 for details. True sage: sage.modules.matrix_morphism.is_MatrixMorphism(3) False diff --git a/src/sage/modules/vector_space_homspace.py b/src/sage/modules/vector_space_homspace.py index 743163acb62..bee4ec941b6 100644 --- a/src/sage/modules/vector_space_homspace.py +++ b/src/sage/modules/vector_space_homspace.py @@ -369,14 +369,14 @@ def __call__(self, A, check=True, **kwds): Previously the above code resulted in a :class:`TypeError` because the dimensions of the matrix were incorrect. """ - from .vector_space_morphism import is_VectorSpaceMorphism, VectorSpaceMorphism + from .vector_space_morphism import VectorSpaceMorphism D = self.domain() C = self.codomain() side = kwds.get("side", "left") from sage.structure.element import is_Matrix if is_Matrix(A): pass - elif is_VectorSpaceMorphism(A): + elif isinstance(A, VectorSpaceMorphism): A = A.matrix() elif callable(A): try: diff --git a/src/sage/modules/vector_space_morphism.py b/src/sage/modules/vector_space_morphism.py index d605a4f4d30..4e43ce4d95e 100644 --- a/src/sage/modules/vector_space_morphism.py +++ b/src/sage/modules/vector_space_morphism.py @@ -785,6 +785,8 @@ def is_VectorSpaceMorphism(x) -> bool: r""" Returns ``True`` if ``x`` is a vector space morphism (a linear transformation). + This function is deprecated. + INPUT: ``x`` - anything @@ -798,10 +800,18 @@ def is_VectorSpaceMorphism(x) -> bool: sage: V = QQ^2; f = V.hom([V.1,-2*V.0]) sage: sage.modules.vector_space_morphism.is_VectorSpaceMorphism(f) + doctest:warning... + DeprecationWarning: is_VectorSpaceMorphism is deprecated; + use isinstance(..., VectorSpaceMorphism) or categories instead + See https://github.com/sagemath/sage/issues/37731 for details. True sage: sage.modules.vector_space_morphism.is_VectorSpaceMorphism('junk') False """ + from sage.misc.superseded import deprecation + deprecation(37731, + "is_VectorSpaceMorphism is deprecated; " + "use isinstance(..., VectorSpaceMorphism) or categories instead") return isinstance(x, VectorSpaceMorphism) From 5a827d86c29e870affe4225fdaabbb5b9d8e325a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 3 Apr 2024 22:24:59 -0700 Subject: [PATCH 173/191] Move methods to FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods --- .../finite_dimensional_modules_with_basis.py | 307 +++++++++--------- src/sage/modules/free_module_morphism.py | 2 +- src/sage/modules/matrix_morphism.py | 8 +- 3 files changed, 157 insertions(+), 160 deletions(-) diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 36716e336d3..0be84eccb84 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -11,8 +11,9 @@ # ***************************************************************************** import operator -from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring +from sage.categories.category_with_axiom import CategoryWithAxiom, CategoryWithAxiom_over_base_ring from sage.categories.fields import Fields +from sage.categories.homsets import HomsetsCategory from sage.categories.tensor import TensorProductsCategory from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute @@ -800,168 +801,164 @@ def image(self): return C.submodule(self.image_basis(), already_echelonized=True, category=self.category_for()) - @lazy_attribute - def characteristic_polynomial(self): - r""" - Return the characteristic polynomial of this endomorphism. - - :meth:`characteristic_polynomial` and :meth:`charpoly` are the same method. + class Homsets(HomsetsCategory): - INPUT: + class Endset(CategoryWithAxiom): - - ``var`` -- variable + class ElementMethods: - EXAMPLES:: + @lazy_attribute + def characteristic_polynomial(self): + r""" + Return the characteristic polynomial of this endomorphism. - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.characteristic_polynomial() - x^2 - 3*x + 2 - sage: phi.charpoly() - x^2 - 3*x + 2 - sage: phi.matrix().charpoly() - x^2 - 3*x + 2 - sage: phi.charpoly('T') - T^2 - 3*T + 2 - - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) - sage: M = matrix(ZZ, [[1, 0], [1, 2]]) - sage: psi = W.module_morphism(matrix=M, codomain=W) - sage: psi.charpoly() - x^2 - 3*x + 2 - """ - if not self.is_endomorphism(): - return NotImplemented - return self.matrix().charpoly + :meth:`characteristic_polynomial` and :meth:`charpoly` are the same method. - charpoly = characteristic_polynomial + INPUT: - @lazy_attribute - def determinant(self): - """ - Return the determinant of this endomorphism. - - :meth:`determinant` and :meth:`det` are the same method. - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.determinant() - 2 - sage: phi.det() - 2 - - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) - sage: M = matrix(ZZ, [[1, 0], [1, 2]]) - sage: psi = W.module_morphism(matrix=M, codomain=W) - sage: psi.det() - 2 - """ - if not self.is_endomorphism(): - return NotImplemented - return self.matrix().determinant + - ``var`` -- variable - det = determinant + EXAMPLES:: - @lazy_attribute - def fcp(self): - """ - Return the factorization of the characteristic polynomial. - - INPUT: - - - ``var`` -- variable - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.fcp() # needs sage.libs.pari - (x - 2) * (x - 1) - sage: phi.fcp('T') # needs sage.libs.pari - (T - 2) * (T - 1) - - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) - sage: M = matrix(ZZ, [[1, 0], [1, 2]]) - sage: psi = W.module_morphism(matrix=M, codomain=W) - sage: psi.fcp() # needs sage.libs.pari - (x - 2) * (x - 1) - """ - if not self.is_endomorphism(): - return NotImplemented - return self.matrix().fcp - - @lazy_attribute - def minimal_polynomial(self): - r""" - Return the minimal polynomial of this endomorphism. - - :meth:`minimal_polynomial` and :meth:`minpoly` are the same method. - - INPUT: - - - ``var`` -- string (default: ``'x'``); a variable name - - EXAMPLES: - - Compute the minimal polynomial, and check it. :: - - sage: V = GF(7)^3 - sage: H = V.Hom(V)([[0,1,2], [-1,0,3], [2,4,1]]); H - Vector space morphism represented by the matrix: - [0 1 2] - [6 0 3] - [2 4 1] - Domain: Vector space of dimension 3 over Finite Field of size 7 - Codomain: Vector space of dimension 3 over Finite Field of size 7 - sage: H.minpoly() # needs sage.libs.pari - x^3 + 6*x^2 + 6*x + 1 - sage: H.minimal_polynomial() # needs sage.libs.pari - x^3 + 6*x^2 + 6*x + 1 - sage: H^3 + (H^2)*6 + H*6 + 1 - Vector space morphism represented by the matrix: - [0 0 0] - [0 0 0] - [0 0 0] - Domain: Vector space of dimension 3 over Finite Field of size 7 - Codomain: Vector space of dimension 3 over Finite Field of size 7 - - sage: # needs sage.rings.finite_rings - sage: k = GF(9, 'c') - sage: V = CombinatorialFreeModule(k, ['x', 'y', 'z', 'w']) - sage: A = matrix(k, 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) - sage: phi = V.module_morphism(matrix=A, codomain=V) - sage: factor(phi.minpoly()) - (x + 1) * (x + 2)^2 - sage: A.minpoly()(A) == 0 - True - sage: factor(phi.charpoly()) - (x + 1)^2 * (x + 2)^2 - """ - if not self.is_endomorphism(): - return NotImplemented - return self.matrix().minimal_polynomial - - minpoly = minimal_polynomial - - @lazy_attribute - def trace(self): - r""" - Return the trace of this endomorphism. - - EXAMPLES:: - - sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) - sage: phi.trace() - 3 - - sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) - sage: M = matrix(ZZ, [[1, 0], [1, 2]]) - sage: psi = W.module_morphism(matrix=M, codomain=W) - sage: psi.trace() - 3 - """ - if not self.is_endomorphism(): - return NotImplemented - return self.matrix().trace + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.characteristic_polynomial() + x^2 - 3*x + 2 + sage: phi.charpoly() + x^2 - 3*x + 2 + sage: phi.matrix().charpoly() + x^2 - 3*x + 2 + sage: phi.charpoly('T') + T^2 - 3*T + 2 + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.charpoly() + x^2 - 3*x + 2 + """ + return self.matrix().charpoly + + charpoly = characteristic_polynomial + + @lazy_attribute + def determinant(self): + """ + Return the determinant of this endomorphism. + + :meth:`determinant` and :meth:`det` are the same method. + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.determinant() + 2 + sage: phi.det() + 2 + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.det() + 2 + """ + return self.matrix().determinant + + det = determinant + + @lazy_attribute + def fcp(self): + """ + Return the factorization of the characteristic polynomial. + + INPUT: + + - ``var`` -- variable + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.fcp() # needs sage.libs.pari + (x - 2) * (x - 1) + sage: phi.fcp('T') # needs sage.libs.pari + (T - 2) * (T - 1) + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.fcp() # needs sage.libs.pari + (x - 2) * (x - 1) + """ + return self.matrix().fcp + + @lazy_attribute + def minimal_polynomial(self): + r""" + Return the minimal polynomial of this endomorphism. + + :meth:`minimal_polynomial` and :meth:`minpoly` are the same method. + + INPUT: + + - ``var`` -- string (default: ``'x'``); a variable name + + EXAMPLES: + + Compute the minimal polynomial, and check it. :: + + sage: V = GF(7)^3 + sage: H = V.Hom(V)([[0,1,2], [-1,0,3], [2,4,1]]); H + Vector space morphism represented by the matrix: + [0 1 2] + [6 0 3] + [2 4 1] + Domain: Vector space of dimension 3 over Finite Field of size 7 + Codomain: Vector space of dimension 3 over Finite Field of size 7 + sage: H.minpoly() # needs sage.libs.pari + x^3 + 6*x^2 + 6*x + 1 + sage: H.minimal_polynomial() # needs sage.libs.pari + x^3 + 6*x^2 + 6*x + 1 + sage: H^3 + (H^2)*6 + H*6 + 1 + Vector space morphism represented by the matrix: + [0 0 0] + [0 0 0] + [0 0 0] + Domain: Vector space of dimension 3 over Finite Field of size 7 + Codomain: Vector space of dimension 3 over Finite Field of size 7 + + sage: # needs sage.rings.finite_rings + sage: k = GF(9, 'c') + sage: V = CombinatorialFreeModule(k, ['x', 'y', 'z', 'w']) + sage: A = matrix(k, 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) + sage: phi = V.module_morphism(matrix=A, codomain=V) + sage: factor(phi.minpoly()) + (x + 1) * (x + 2)^2 + sage: A.minpoly()(A) == 0 + True + sage: factor(phi.charpoly()) + (x + 1)^2 * (x + 2)^2 + """ + return self.matrix().minimal_polynomial + + minpoly = minimal_polynomial + + @lazy_attribute + def trace(self): + r""" + Return the trace of this endomorphism. + + EXAMPLES:: + + sage: V = ZZ^2; phi = V.hom([V.0 + V.1, 2*V.1]) + sage: phi.trace() + 3 + + sage: W = CombinatorialFreeModule(ZZ, ['x', 'y']) + sage: M = matrix(ZZ, [[1, 0], [1, 2]]) + sage: psi = W.module_morphism(matrix=M, codomain=W) + sage: psi.trace() + 3 + """ + return self.matrix().trace class TensorProducts(TensorProductsCategory): diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index 9f2c2648136..d53eeaf4176 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -74,7 +74,7 @@ def is_FreeModuleMorphism(x): class FreeModuleMorphism(matrix_morphism.MatrixMorphism): - minimal_polynomial = minpoly = FiniteDimensionalModulesWithBasis.MorphismMethods.minimal_polynomial + minimal_polynomial = minpoly = FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods.minimal_polynomial def __init__(self, parent, A, side="left"): """ diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index bbb4e75c35e..a77dc0f020d 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -89,10 +89,10 @@ class MatrixMorphism_abstract(sage.categories.morphism.Morphism): # for use with parents that are merely set up as additive abelian groups, # but not as ZZ-modules; see sage.modular.abvar. - characteristic_polynomial = charpoly = FiniteDimensionalModulesWithBasis.MorphismMethods.characteristic_polynomial - det = determinant = FiniteDimensionalModulesWithBasis.MorphismMethods.determinant - fcp = FiniteDimensionalModulesWithBasis.MorphismMethods.fcp - trace = FiniteDimensionalModulesWithBasis.MorphismMethods.trace + characteristic_polynomial = charpoly = FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods.characteristic_polynomial + det = determinant = FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods.determinant + fcp = FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods.fcp + trace = FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods.trace def __init__(self, parent, side='left'): """ From e965c0f55974db97dbfcad51641ddc0c771ed3bf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Apr 2024 16:09:19 -0700 Subject: [PATCH 174/191] FreeModuleMorphism: Revert 'Copy in methods from category' --- src/sage/modules/free_module_morphism.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index d53eeaf4176..486356e1605 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -42,7 +42,7 @@ # be coercible into vector space of appropriate dimension. import sage.modules.free_module as free_module -from sage.categories.finite_dimensional_modules_with_basis import FiniteDimensionalModulesWithBasis + from sage.categories.morphism import Morphism from sage.modules import free_module_homspace, matrix_morphism from sage.structure.richcmp import rich_to_bool, richcmp @@ -74,8 +74,6 @@ def is_FreeModuleMorphism(x): class FreeModuleMorphism(matrix_morphism.MatrixMorphism): - minimal_polynomial = minpoly = FiniteDimensionalModulesWithBasis.Homsets.Endset.ElementMethods.minimal_polynomial - def __init__(self, parent, A, side="left"): """ INPUT: From 84b0b238bdaa1959d24ac0ef4db49f505a79dddc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 7 Apr 2024 21:09:14 -0700 Subject: [PATCH 175/191] src/sage/categories/modules_with_basis.py: Update doctest output --- src/sage/categories/modules_with_basis.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 2a1fe2dd117..adac2edcd1b 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -116,9 +116,10 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring): Some more playing around with categories and higher order homsets:: sage: H.category() # needs sage.modules - Category of homsets of modules with basis over Rational Field + Category of homsets of finite dimensional modules with basis over Rational Field sage: Hom(H, H).category() # needs sage.modules - Category of endsets of homsets of modules with basis over Rational Field + Category of endsets of + homsets of finite dimensional modules with basis over Rational Field .. TODO:: ``End(X)`` is an algebra. From bf7beab6009c5760a9b77eb17eae8dae9bf5e144 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Mar 2024 13:53:03 -0700 Subject: [PATCH 176/191] build/pkgs/{gdb,gmp,libgd,python3,symmetrica}: Reduce xz to an order-only dependency --- build/pkgs/gdb/dependencies | 2 +- build/pkgs/gmp/dependencies | 2 +- build/pkgs/libgd/dependencies | 2 +- build/pkgs/python3/dependencies | 2 +- build/pkgs/symmetrica/dependencies | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/pkgs/gdb/dependencies b/build/pkgs/gdb/dependencies index cf6822bb92e..d6030116f99 100644 --- a/build/pkgs/gdb/dependencies +++ b/build/pkgs/gdb/dependencies @@ -1,4 +1,4 @@ -mpfr zlib ncurses xz | $(PYTHON) +mpfr zlib ncurses | $(PYTHON) xz ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gmp/dependencies b/build/pkgs/gmp/dependencies index ce98901e90d..9738ee88e94 100644 --- a/build/pkgs/gmp/dependencies +++ b/build/pkgs/gmp/dependencies @@ -1,3 +1,3 @@ -xz +| xz # xz is only needed to unpack the tarball when sage-bootstrap-python is Python < 3.3 diff --git a/build/pkgs/libgd/dependencies b/build/pkgs/libgd/dependencies index f2c5686fb06..66ad9984858 100644 --- a/build/pkgs/libgd/dependencies +++ b/build/pkgs/libgd/dependencies @@ -1,4 +1,4 @@ -libpng xz +libpng | xz # xz needed to unpack tarball when sage-bootstrap-python is Python < 3.3 ---------- diff --git a/build/pkgs/python3/dependencies b/build/pkgs/python3/dependencies index 9bdcf05edc4..c00db7fa1e0 100644 --- a/build/pkgs/python3/dependencies +++ b/build/pkgs/python3/dependencies @@ -1,4 +1,4 @@ -zlib readline sqlite libpng bzip2 liblzma xz libffi openssl +zlib readline sqlite libpng bzip2 liblzma libffi openssl | xz ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/symmetrica/dependencies b/build/pkgs/symmetrica/dependencies index 606ceeaec80..eb5b66f34f2 100644 --- a/build/pkgs/symmetrica/dependencies +++ b/build/pkgs/symmetrica/dependencies @@ -1,4 +1,4 @@ -xz +| xz xz is needed for unpacking the tarball when sage-bootstrap-python is ancient From bf39355647f5a76bea2c6bc4e6de0cf9f566bd05 Mon Sep 17 00:00:00 2001 From: Sebastian Spindler Date: Thu, 18 Apr 2024 10:57:54 +0200 Subject: [PATCH 177/191] Implemented reviewer feedback - Corrected order of additional arguments - Fixed spacing for PEP8 --- src/sage/algebras/quatalg/quaternion_algebra.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index ebc9292688a..4c9f9d7fb46 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -701,13 +701,13 @@ def maximal_order(self, take_shortcuts=True, order_basis=None): INPUT: - - ``order_basis`` -- (optional, default: ``None``) a basis of an - order of this quaternion algebra - - ``take_shortcuts`` -- (default: ``True``) if the discriminant is prime and the invariants of the algebra are of a nice form, use Proposition 5.2 of [Piz1980]_. + - ``order_basis`` -- (optional, default: ``None``) a basis of an + order of this quaternion algebra + OUTPUT: A maximal order in this quaternion algebra. @@ -814,7 +814,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None): # of such a form though) a, b = self.invariants() if (not order_basis and take_shortcuts and d_A.is_prime() - and a in ZZ and b in ZZ): + and a in ZZ and b in ZZ): a = ZZ(a) b = ZZ(b) i, j, k = self.gens() From d160c55c41893575bb60413227cfa8cca9ec41e6 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 27 Mar 2024 17:20:40 +0000 Subject: [PATCH 178/191] fix ascii_art of empty chain complex --- src/sage/homology/chain_complex.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index c01151ee7ed..c42e95ddd5f 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -444,10 +444,13 @@ def vector_art(d): for n in ordered: result_ordered += arrow_art(n) + vector_art(n) result = [result_ordered] + result - concatenated = result[0] - for r in result[1:]: - concatenated += AsciiArt([' ... ']) + r - return concatenated + try: + concatenated = result[0] + for r in result[1:]: + concatenated += AsciiArt([' ... ']) + r + return concatenated + except IndexError: + return [] def _unicode_art_(self): """ @@ -1803,10 +1806,13 @@ def module_art(n): for n in ordered: result_ordered += arrow_art(n) + module_art(n) result = [result_ordered] + result - concatenated = result[0] - for r in result[1:]: - concatenated += AsciiArt([' ... ']) + r - return concatenated + try: + concatenated = result[0] + for r in result[1:]: + concatenated += AsciiArt([' ... ']) + r + return concatenated + except IndexError: + return [] def _unicode_art_(self): """ From 7263b9b1614bcbca57f27ec11ad829270aaf10e5 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 27 Mar 2024 21:02:29 +0000 Subject: [PATCH 179/191] add tests, make sure unicode_art() is fixed too --- src/sage/homology/chain_complex.py | 43 ++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index c42e95ddd5f..655e5cc1356 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -418,6 +418,15 @@ def _ascii_art_(self): d_2 d_1 d_0 [1] d_-1 0 <---- [0] <---- [4] <---- [2] <----- 0 [5] [3] + + TESTS: + + check that :issue:`37678` is fixed:: + + sage: C = ChainComplex(base_ring=ZZ) + sage: ascii_art(C()) + [] + """ from sage.typeset.ascii_art import AsciiArt @@ -468,6 +477,8 @@ def _unicode_art_(self): ⎛1⎞ d_2 d_1 ⎛4⎞ d_0 ⎜2⎟ d_-1 0 <──── (0) <──── ⎝5⎠ <──── ⎝3⎠ <───── 0 + sage: unicode_art(C()) + [] """ from sage.typeset.unicode_art import UnicodeArt @@ -495,10 +506,13 @@ def vector_art(d): for n in ordered: result_ordered += arrow_art(n) + vector_art(n) result = [result_ordered] + result - concatenated = result[0] - for r in result[1:]: - concatenated += UnicodeArt([u' ... ']) + r - return concatenated + try: + concatenated = result[0] + for r in result[1:]: + concatenated += AsciiArt([' ... ']) + r + return concatenated + except IndexError: + return [] def is_cycle(self): """ @@ -1778,6 +1792,8 @@ def _ascii_art_(self): sage: ascii_art(D) [1] [1] [0] [1] 0 <-- C_7 <---- C_6 <-- 0 ... 0 <-- C_3 <---- C_2 <---- C_1 <---- C_0 <-- 0 + sage: ascii_art(ChainComplex(base_ring=ZZ)) + [] """ from sage.typeset.ascii_art import AsciiArt @@ -1834,6 +1850,14 @@ def _unicode_art_(self): sage: unicode_art(D) (1) (1) (0) (1) 0 <── C_7 <── C_6 <── 0 ... 0 <── C_3 <── C_2 <── C_1 <── C_0 <── 0 + + TESTS: + + check that :issue:`37678` is fixed:: + + sage: C = ChainComplex(base_ring=ZZ) + sage: unicode_art(C) + [] """ from sage.typeset.unicode_art import UnicodeArt @@ -1862,10 +1886,13 @@ def module_art(n): for n in ordered: result_ordered += arrow_art(n) + module_art(n) result = [result_ordered] + result - concatenated = result[0] - for r in result[1:]: - concatenated += UnicodeArt([u' ... ']) + r - return concatenated + try: + concatenated = result[0] + for r in result[1:]: + concatenated += AsciiArt([' ... ']) + r + return concatenated + except IndexError: + return [] def _latex_(self): """ From d192d0b693dc0acf49bdc981d6d34ce060e81328 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 28 Mar 2024 10:57:21 +0000 Subject: [PATCH 180/191] UnicodeArt, not AsciiArt (1) Co-authored-by: John H. Palmieri --- src/sage/homology/chain_complex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index 655e5cc1356..a9276905137 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -509,7 +509,7 @@ def vector_art(d): try: concatenated = result[0] for r in result[1:]: - concatenated += AsciiArt([' ... ']) + r + concatenated += UnicodeArt([' ... ']) + r return concatenated except IndexError: return [] From 96621faf2bcd04ac647a83cb646793ed7475d635 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 28 Mar 2024 10:57:42 +0000 Subject: [PATCH 181/191] UnicodeArt, not AsciiArt (2) Co-authored-by: John H. Palmieri --- src/sage/homology/chain_complex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index a9276905137..7c04b99712a 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -1889,7 +1889,7 @@ def module_art(n): try: concatenated = result[0] for r in result[1:]: - concatenated += AsciiArt([' ... ']) + r + concatenated += UnicodeArt([' ... ']) + r return concatenated except IndexError: return [] From a4a25a87901df322289456c2d72c9b67096b9bbd Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 28 Mar 2024 11:10:21 +0000 Subject: [PATCH 182/191] correct test outputs --- src/sage/homology/chain_complex.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index 7c04b99712a..e66f0bf9fc3 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -478,6 +478,10 @@ def _unicode_art_(self): d_2 d_1 ⎛4⎞ d_0 ⎜2⎟ d_-1 0 <──── (0) <──── ⎝5⎠ <──── ⎝3⎠ <───── 0 sage: unicode_art(C()) + ⎛0⎞ + d_2 d_1 ⎛0⎞ d_0 ⎜0⎟ d_-1 + 0 <──── (0) <──── ⎝0⎠ <──── ⎝0⎠ <───── 0 + sage: unicode_art(ChainComplex()) [] """ from sage.typeset.unicode_art import UnicodeArt From c083f7d619db877bbaa42f0824aad823c27bbbf5 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Fri, 19 Apr 2024 13:30:00 +0100 Subject: [PATCH 183/191] don't use try/except, and use 0, not [] --- src/sage/homology/chain_complex.py | 60 ++++++++++++++---------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index e66f0bf9fc3..43dfde91848 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -425,7 +425,7 @@ def _ascii_art_(self): sage: C = ChainComplex(base_ring=ZZ) sage: ascii_art(C()) - [] + 0 """ from sage.typeset.ascii_art import AsciiArt @@ -453,13 +453,12 @@ def vector_art(d): for n in ordered: result_ordered += arrow_art(n) + vector_art(n) result = [result_ordered] + result - try: - concatenated = result[0] - for r in result[1:]: - concatenated += AsciiArt([' ... ']) + r - return concatenated - except IndexError: - return [] + if len(result) == 0: + return AsciiArt(['0']) + concatenated = result[0] + for r in result[1:]: + concatenated += AsciiArt([' ... ']) + r + return concatenated def _unicode_art_(self): """ @@ -482,7 +481,7 @@ def _unicode_art_(self): d_2 d_1 ⎛0⎞ d_0 ⎜0⎟ d_-1 0 <──── (0) <──── ⎝0⎠ <──── ⎝0⎠ <───── 0 sage: unicode_art(ChainComplex()) - [] + 0 """ from sage.typeset.unicode_art import UnicodeArt @@ -510,13 +509,12 @@ def vector_art(d): for n in ordered: result_ordered += arrow_art(n) + vector_art(n) result = [result_ordered] + result - try: - concatenated = result[0] - for r in result[1:]: - concatenated += UnicodeArt([' ... ']) + r - return concatenated - except IndexError: - return [] + if len(result) == 0: + return UnicodeArt([u'0']) + concatenated = result[0] + for r in result[1:]: + concatenated += UnicodeArt([u' ... ']) + r + return concatenated def is_cycle(self): """ @@ -1797,7 +1795,7 @@ def _ascii_art_(self): [1] [1] [0] [1] 0 <-- C_7 <---- C_6 <-- 0 ... 0 <-- C_3 <---- C_2 <---- C_1 <---- C_0 <-- 0 sage: ascii_art(ChainComplex(base_ring=ZZ)) - [] + 0 """ from sage.typeset.ascii_art import AsciiArt @@ -1826,13 +1824,12 @@ def module_art(n): for n in ordered: result_ordered += arrow_art(n) + module_art(n) result = [result_ordered] + result - try: - concatenated = result[0] - for r in result[1:]: - concatenated += AsciiArt([' ... ']) + r - return concatenated - except IndexError: - return [] + if len(result) == 0: + return AsciiArt(['0']) + concatenated = result[0] + for r in result[1:]: + concatenated += AsciiArt([' ... ']) + r + return concatenated def _unicode_art_(self): """ @@ -1861,7 +1858,7 @@ def _unicode_art_(self): sage: C = ChainComplex(base_ring=ZZ) sage: unicode_art(C) - [] + 0 """ from sage.typeset.unicode_art import UnicodeArt @@ -1890,13 +1887,12 @@ def module_art(n): for n in ordered: result_ordered += arrow_art(n) + module_art(n) result = [result_ordered] + result - try: - concatenated = result[0] - for r in result[1:]: - concatenated += UnicodeArt([' ... ']) + r - return concatenated - except IndexError: - return [] + if len(result) == 0: + return UnicodeArt([u'0']) + concatenated = result[0] + for r in result[1:]: + concatenated += UnicodeArt([u' ... ']) + r + return concatenated def _latex_(self): """ From d4ff3a2f619cc2c49cd33c4dd2314b55781beca3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 12 Dec 2023 12:34:34 -0800 Subject: [PATCH 184/191] m4/pyproject_toml_metadata.m4: Allow Python 3.12 --- m4/pyproject_toml_metadata.m4 | 1 + 1 file changed, 1 insertion(+) diff --git a/m4/pyproject_toml_metadata.m4 b/m4/pyproject_toml_metadata.m4 index 139af7e43e4..0d9824b1f2e 100644 --- a/m4/pyproject_toml_metadata.m4 +++ b/m4/pyproject_toml_metadata.m4 @@ -13,6 +13,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: Mathematics", ] From 8fdedff46875cd1983e50317aa34e1fd3430e5c7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 19 Apr 2024 12:28:32 -0700 Subject: [PATCH 185/191] Add 'Programming Language :: Python :: 3.12' to Classifiers --- m4/setup_cfg_metadata.m4 | 1 + pkgs/sage-docbuild/pyproject.toml | 1 + pkgs/sage-setup/pyproject.toml | 1 + 3 files changed, 3 insertions(+) diff --git a/m4/setup_cfg_metadata.m4 b/m4/setup_cfg_metadata.m4 index 896ca37eb7f..fb202433fcd 100644 --- a/m4/setup_cfg_metadata.m4 +++ b/m4/setup_cfg_metadata.m4 @@ -16,5 +16,6 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Programming Language :: Python :: Implementation :: CPython Topic :: Scientific/Engineering :: Mathematics diff --git a/pkgs/sage-docbuild/pyproject.toml b/pkgs/sage-docbuild/pyproject.toml index 77840653af0..87e7c6521f8 100644 --- a/pkgs/sage-docbuild/pyproject.toml +++ b/pkgs/sage-docbuild/pyproject.toml @@ -18,6 +18,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: Mathematics", ] diff --git a/pkgs/sage-setup/pyproject.toml b/pkgs/sage-setup/pyproject.toml index 4a558643864..96b079cec62 100644 --- a/pkgs/sage-setup/pyproject.toml +++ b/pkgs/sage-setup/pyproject.toml @@ -18,6 +18,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: Mathematics", ] From 15aeb9a4db2eedecf7c3205e296ac90d63c94e87 Mon Sep 17 00:00:00 2001 From: Nolord <33145668+Nolord@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:38:46 +0200 Subject: [PATCH 186/191] Bell Polynomial - complete/ordinary variants - Documentation - Tests - Examples - Slightly better implementation Co-Authored-By: Travis Scrimshaw --- src/doc/en/reference/references/index.rst | 4 + src/sage/combinat/combinat.py | 166 ++++++++++++++++++---- 2 files changed, 146 insertions(+), 24 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index aa1aa130d32..a63d60aef75 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1801,6 +1801,10 @@ REFERENCES: .. [Com2019] Camille Combe, *Réalisation cubique du poset des intervalles de Tamari*, preprint :arxiv:`1904.00658` +.. [Com1974] Comtet Louis, *Identities and Expansions*. + In: Advanced Combinatorics. 1974. pp. 127-175 + :doi:`10.1007/978-94-010-2196-8_3` + .. [Con] Keith Conrad, *Groups of order 12*, http://www.math.uconn.edu/~kconrad/blurbs/grouptheory/group12.pdf, accessed 21 October 2009. diff --git a/src/sage/combinat/combinat.py b/src/sage/combinat/combinat.py index bd5e7102d66..38348c41c1d 100644 --- a/src/sage/combinat/combinat.py +++ b/src/sage/combinat/combinat.py @@ -2918,42 +2918,123 @@ def unshuffle_iterator(a, one=1) -> Iterator: (one if sign else - one)) -def bell_polynomial(n: Integer, k: Integer): +def bell_polynomial(n: Integer, k=None, ordinary=False): r""" - Return the Bell Polynomial + Return the (partial) (exponential/ordinary) bell Polynomial. + + The partial (exponential) *Bell polynomial* is defined by the formula .. MATH:: - B_{n,k}(x_0, x_1, \ldots, x_{n-k}) = - \sum_{\sum{j_i}=k, \sum{(i+1) j_i}=n} + B_{n,k}(x_0, x_1, \ldots, x_{n-k}) = + \sum_{\substack{j_0 + \ldots + j_{n-k} = k \\ 1 j_0 + \ldots + (n-k+1) j_{n-k} = n}} \frac{n!}{j_0!j_1!\cdots j_{n-k}!} \left(\frac{x_0}{(0+1)!}\right)^{j_0} \left(\frac{x_1}{(1+1)!}\right)^{j_1} \cdots \left(\frac{x_{n-k}}{(n-k+1)!}\right)^{j_{n-k}}. - INPUT: + The complete (exponential) Bell Polynomial is defined as - - ``n`` -- integer + .. MATH:: - - ``k`` -- integer + B_n(x_0, x_1, \ldots, x_{n-k}) = + \sum_{k=0}^n B_{n,k}(x_0, x_1, \ldots, x_{n-k}). - OUTPUT: + The ordinary variant of the partial Bell polynomial is defined by - - a polynomial in `n-k+1` variables over `\ZZ` + .. MATH:: - EXAMPLES:: + \hat B_{n,k}(x_0, x_1, \ldots, x_{n-k}) = + \sum_{\substack{j_0 + \ldots + j_{n-k} = k \\ 1 j_0 + \ldots + (n-k+1) j_{n-k} = n}} + \binom{k}{j_0, j_1, \ldots, j_{n-k}} + x_0^{j_0} x_1^{j_1} \cdots x_{n-k}^{j_{n-k}}, + + where we have used the multinomial coefficient. + The complete version has the same definition as its exponential counterpart. + + If we define `f(z) = \sum_{n=1}^\infty x_{n-1} z^n/n!` + then these are alternative definitions for exponential Bell polynomials + + .. MATH:: + + \begin{aligned} + \exp(f(z)) & = \sum_{n=0}^\infty B_n(x_0, \ldots, x_{n-1}) \frac{z^n}{n!}, \\ + \frac{f(z)^k}{k!} & = \sum_{n=k}^\infty B_{n, k}(x_0, \ldots, x_{n-k}) \frac{z^n}{n!}. + \end{aligned} + + Defining `g(z) = \sum_{n=1}^\infty x_{n-1} z^n`, + we have the analoguous alternative definitions + + .. MATH:: + + \begin{aligned} + \frac1{1-f(z)} & = \sum_{n=0}^\infty \hat B_n(x_0, \ldots, x_{n-1}) z^n, \\ + f(z)^k & = \sum_{n=k}^\infty \hat B_{n, k}(x_0, \ldots, x_{n-k}) z^n, + \end{aligned} + + (see reference). + + INPUT: + + - ``k`` -- (optional) if specified, returns the partial Bell + polynomial, otherwise returns the complete Bell polynomial + - ``ordinary`` -- (default: ``False``) if ``True``, returns the + (partial) ordinary Bell polynomial, otherwise returns + the (partial) exponential Bell polynomial - sage: bell_polynomial(6,2) # needs sage.combinat - 10*x2^2 + 15*x1*x3 + 6*x0*x4 - sage: bell_polynomial(6,3) # needs sage.combinat + EXAMPLES: + + The complete and partial Bell polynomials:: + + sage: # needs sage.combinat + sage: bell_polynomial(3) + x0^3 + 3*x0*x1 + x2 + sage: bell_polynomial(4) + x0^4 + 6*x0^2*x1 + 3*x1^2 + 4*x0*x2 + x3 + sage: bell_polynomial(6, 3) 15*x1^3 + 60*x0*x1*x2 + 15*x0^2*x3 + sage: bell_polynomial(6, 6) + x0^6 + + The ordinary variants are:: + + sage: # needs sage.combinat sage.arith + sage: bell_polynomial(3, ordinary=True) + x0^3 + 2*x0*x1 + x2 + sage: bell_polynomial(4, ordinary=True) + x0^4 + 3*x0^2*x1 + x1^2 + 2*x0*x2 + x3 + sage: bell_polynomial(6, 3, True) + x1^3 + 6*x0*x1*x2 + 3*x0^2*x3 + sage: bell_polynomial(6, 6, True) + x0^6 + + We verify the alternative definition of the different Bell polynomials + using the functions `f` and `g` given above:: + + sage: # needs sage.combinat sage.arith + sage: n = 6 # positive integer + sage: k = 4 # positive integer + sage: R. = InfinitePolynomialRing(QQ) + sage: PR = PolynomialRing(QQ, 'x', n) + sage: d = {x[i]: PR.gen(i) for i in range(n)} #substitution dictionnary + sage: L. = LazyPowerSeriesRing(R) + sage: f = L(lambda i: x[i-1]/factorial(i), valuation=1) + sage: all(exp(f)[i].subs(d) * factorial(i) == bell_polynomial(i) for i in range(n+1)) + True + sage: all((f^k/factorial(k))[i].subs(d) * factorial(i) == bell_polynomial(i, k) for i in range(k, n+k)) + True + sage: g = L(lambda i: x[i-1], valuation=1) + sage: all((1/(1-g))[i].subs(d) == bell_polynomial(i, ordinary=True) for i in range(n+1)) + True + sage: all((g^k)[i].subs(d) == bell_polynomial(i, k, True) for i in range(k, n+k)) + True TESTS: Check that :issue:`18338` is fixed:: - sage: bell_polynomial(0,0).parent() # needs sage.combinat - Multivariate Polynomial Ring in x over Integer Ring + sage: bell_polynomial(0, 0).parent() # needs sage.combinat + Univariate Polynomial Ring in x0 over Integer Ring sage: for n in (0..4): # needs sage.combinat ....: print([bell_polynomial(n,k).coefficients() for k in (0..n)]) @@ -2963,28 +3044,65 @@ def bell_polynomial(n: Integer, k: Integer): [[], [1], [3], [1]] [[], [1], [3, 4], [6], [1]] + Further checks for :issue:`37727`:: + + sage: # needs sage.combinat sage.arith + sage: bell_polynomial(0, 0) + 1 + sage: bell_polynomial(0, 0, True) + 1 + sage: bell_polynomial(1, 1) + x0 + sage: bell_polynomial(2, 2, True) + x0^2 + sage: bell_polynomial(5) + x0^5 + 10*x0^3*x1 + 15*x0*x1^2 + 10*x0^2*x2 + 10*x1*x2 + 5*x0*x3 + x4 + sage: sum(bell_polynomial(5, k) for k in range(6)) + x0^5 + 10*x0^3*x1 + 15*x0*x1^2 + 10*x0^2*x2 + 10*x1*x2 + 5*x0*x3 + x4 + sage: bell_polynomial(5, None, True) + x0^5 + 4*x0^3*x1 + 3*x0*x1^2 + 3*x0^2*x2 + 2*x1*x2 + 2*x0*x3 + x4 + sage: sum(bell_polynomial(5, k, True) for k in range(6)) + x0^5 + 4*x0^3*x1 + 3*x0*x1^2 + 3*x0^2*x2 + 2*x1*x2 + 2*x0*x3 + x4 + sage: bell_polynomial(0).parent() + Univariate Polynomial Ring in x0 over Integer Ring REFERENCES: - [Bel1927]_ + - [Com1974]_ AUTHORS: - Blair Sutton (2009-01-26) - Thierry Monteil (2015-09-29): the result must always be a polynomial. + - Kei Beauduin (2024-04-06): when univariate, + the polynomial is in variable ``x0``. extended to complete exponential, + partial ordinary and complete ordinary Bell polynomials. """ from sage.combinat.partition import Partitions - R = PolynomialRing(ZZ, 'x', n - k + 1) + from sage.arith.misc import multinomial + if k is None: + partitions = Partitions(n) + # We set k = 1 to use the correct ring + # It is not used in the computation otherwise + k = 1 + else: + partitions = Partitions(n, length=k) + if n <= k: + R = PolynomialRing(ZZ, 'x0') + else: + R = PolynomialRing(ZZ, 'x', n - k + 1) vars = R.gens() result = R.zero() - for p in Partitions(n, length=k): # type:ignore - factorial_product = 1 - power_factorial_product = 1 - for part, count in p.to_exp_dict().items(): - factorial_product *= factorial(count) - power_factorial_product *= factorial(part)**count - coefficient = factorial(n) // (factorial_product * power_factorial_product) - result += coefficient * prod([vars[i - 1] for i in p]) + for p in partitions: + if ordinary: + coefficient = multinomial(p.to_exp()) + else: + factorial_product = 1 + for part, count in p.to_exp_dict().items(): + factorial_product *= factorial(count) * factorial(part)**count + coefficient = factorial(n) // factorial_product + result += coefficient * prod(vars[i - 1] for i in p) return result From c4ca655fdb3746de4f55806b784d57fc24a07a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Tue, 16 Jan 2024 17:16:42 -0300 Subject: [PATCH 187/191] sagemath-standard: include sage_setup in sdist --- pkgs/sagemath-standard/sage_setup | 1 + src/MANIFEST.in | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 120000 pkgs/sagemath-standard/sage_setup diff --git a/pkgs/sagemath-standard/sage_setup b/pkgs/sagemath-standard/sage_setup new file mode 120000 index 00000000000..88b8133df49 --- /dev/null +++ b/pkgs/sagemath-standard/sage_setup @@ -0,0 +1 @@ +../../src/sage_setup \ No newline at end of file diff --git a/src/MANIFEST.in b/src/MANIFEST.in index 89d9d8e368e..a4613448097 100644 --- a/src/MANIFEST.in +++ b/src/MANIFEST.in @@ -3,10 +3,15 @@ include VERSION.txt recursive-include sage *.pxi *.pxd *.h *.hpp prune sage/ext/interpreters # In particular, __init__.py must not be present in the distribution; or sage_setup.autogen.interpreters.rebuild will not generate the code -prune sage_setup prune sage_docbuild prune doc +# include sage_setup +recursive-include sage_setup * +prune sage_setup/autogen/flint* +exclude sage_setup/autogen/flint* +exclude sage_setup/autogen/giacpy* + # # Most C and C++ files are generated by Cython and should not # be included in the sdist. From 4c3e451d593b1e75d3c9bd477bff09bc573e48e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Sat, 10 Feb 2024 16:15:28 -0300 Subject: [PATCH 188/191] sagemath-standard: remove sage_setup from build requirements --- src/pyproject.toml.m4 | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pyproject.toml.m4 b/src/pyproject.toml.m4 index 7406c7ff359..26de30ea108 100644 --- a/src/pyproject.toml.m4 +++ b/src/pyproject.toml.m4 @@ -1,11 +1,9 @@ [build-system] # Minimum requirements for the build system to execute. requires = [ - "sage_setup[autogen]", esyscmd(`sage-get-system-packages install-requires-toml \ setuptools \ wheel \ - sage_setup \ cypari \ cysignals \ cython \ From 0c8d74275bc814c4898af714a08b1946d4aee7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 12 Feb 2024 14:58:10 -0300 Subject: [PATCH 189/191] don't install sage-setup in conda --- .devcontainer/onCreate-conda.sh | 1 - .github/workflows/ci-conda.yml | 1 - .gitpod.yml | 1 - src/doc/en/installation/conda.rst | 1 - 4 files changed, 4 deletions(-) diff --git a/.devcontainer/onCreate-conda.sh b/.devcontainer/onCreate-conda.sh index f0251185c62..0904ebe7c16 100755 --- a/.devcontainer/onCreate-conda.sh +++ b/.devcontainer/onCreate-conda.sh @@ -8,5 +8,4 @@ conda init bash # Build sage conda run -n sage-dev ./bootstrap -conda run -n sage-dev pip install --no-build-isolation -v -v -e ./pkgs/sage-setup conda run -n sage-dev pip install --no-build-isolation -v -v -e ./src diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index b01b041a975..92408b50aea 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -87,7 +87,6 @@ jobs: shell: bash -l {0} run: | # Use --no-deps and pip check below to verify that all necessary dependencies are installed via conda. - pip install --no-build-isolation --no-deps -v -v -e ./pkgs/sage-setup pip install --no-build-isolation --no-deps --config-settings editable_mode=compat -v -v -e ./src env: SAGE_NUM_THREADS: 2 diff --git a/.gitpod.yml b/.gitpod.yml index a91131f4e7a..6d7c9ec93df 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -11,7 +11,6 @@ tasks: && conda config --append envs_dirs $(pwd) && conda activate $(pwd)/venv && ./bootstrap - && pip install --no-build-isolation -v -v -e ./pkgs/sage-setup && pip install --no-build-isolation -v -v -e ./src # Activate conda environment, set up Trac remote # RestructuredText extension recommends python extension, although we have already installed it diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 2191374cea2..49495d60ebf 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -138,7 +138,6 @@ Here we assume that you are using a git checkout. - Bootstrap the source tree and install the build prerequisites and the Sage library:: $ ./bootstrap - $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-setup $ pip install --no-build-isolation --config-settings editable_mode=compat -v -v --editable ./src If you encounter any errors, try to install the ``sage-conf`` package first:: From 1f28d78b3984bed171f3f34c52d374c74de0f527 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 23 Apr 2024 22:30:04 -0700 Subject: [PATCH 190/191] build/pkgs/pyscipopt/patches/792.patch: Remove --- build/pkgs/pyscipopt/patches/792.patch | 1217 ------------------------ 1 file changed, 1217 deletions(-) delete mode 100644 build/pkgs/pyscipopt/patches/792.patch diff --git a/build/pkgs/pyscipopt/patches/792.patch b/build/pkgs/pyscipopt/patches/792.patch deleted file mode 100644 index faff6076eb4..00000000000 --- a/build/pkgs/pyscipopt/patches/792.patch +++ /dev/null @@ -1,1217 +0,0 @@ -From 96acc6be39b6d153cfcfe7b14741956eaf7f5851 Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Sun, 18 Feb 2024 19:47:52 -0800 -Subject: [PATCH] src/pyscipopt: Add 'noexcept' to functions that use 'with - gil' - ---- - src/pyscipopt/benders.pxi | 30 ++++++++--------- - src/pyscipopt/benderscut.pxi | 14 ++++---- - src/pyscipopt/branchrule.pxi | 18 +++++----- - src/pyscipopt/conshdlr.pxi | 64 ++++++++++++++++++------------------ - src/pyscipopt/cutsel.pxi | 14 ++++---- - src/pyscipopt/event.pxi | 18 +++++----- - src/pyscipopt/heuristic.pxi | 14 ++++---- - src/pyscipopt/nodesel.pxi | 16 ++++----- - src/pyscipopt/presol.pxi | 14 ++++---- - src/pyscipopt/pricer.pxi | 16 ++++----- - src/pyscipopt/propagator.pxi | 22 ++++++------- - src/pyscipopt/reader.pxi | 8 ++--- - src/pyscipopt/relax.pxi | 14 ++++---- - src/pyscipopt/scip.pxd | 2 +- - src/pyscipopt/scip.pxi | 4 +-- - src/pyscipopt/sepa.pxi | 16 ++++----- - 16 files changed, 142 insertions(+), 142 deletions(-) - -diff --git a/src/pyscipopt/benders.pxi b/src/pyscipopt/benders.pxi -index 3e11db189..66a394d8d 100644 ---- a/src/pyscipopt/benders.pxi -+++ b/src/pyscipopt/benders.pxi -@@ -70,10 +70,10 @@ cdef Variable getPyVar(SCIP_VAR* var): - return vardata - - --cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_Bool threadsafe) with gil: -+cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_Bool threadsafe) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -81,56 +81,56 @@ cdef SCIP_RETCODE PyBendersFree (SCIP* scip, SCIP_BENDERS* benders) with gil: - Py_DECREF(PyBenders) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersInit (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersInit (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersExit (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersExit (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersInitpre (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersInitpre (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersinitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersExitpre (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersExitpre (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersexitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersInitsol (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersInitsol (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersExitsol (SCIP* scip, SCIP_BENDERS* benders) with gil: -+cdef SCIP_RETCODE PyBendersExitsol (SCIP* scip, SCIP_BENDERS* benders) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.bendersexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersCreatesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) with gil: -+cdef SCIP_RETCODE PyBendersCreatesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata - PyBenders.benderscreatesub(probnumber) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint, SCIP_Bool* infeasible, SCIP_Bool* auxviol, SCIP_Bool* skipsolve, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint, SCIP_Bool* infeasible, SCIP_Bool* auxviol, SCIP_Bool* skipsolve, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -146,7 +146,7 @@ cdef SCIP_RETCODE PyBendersPresubsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_ - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Bool onlyconvex, SCIP_Real* objective, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Bool onlyconvex, SCIP_Real* objective, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -159,7 +159,7 @@ cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SC - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Real* objective, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, int probnumber, SCIP_Real* objective, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -174,7 +174,7 @@ cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL - - cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, - SCIP_BENDERSENFOTYPE type, int* mergecands, int npriomergecands, int nmergecands, SCIP_Bool checkint, -- SCIP_Bool infeasible, SCIP_Bool* merged) with gil: -+ SCIP_Bool infeasible, SCIP_Bool* merged) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -190,7 +190,7 @@ cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SO - merged[0] = result_dict.get("merged", False) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) with gil: -+cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probnumber) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -@@ -198,7 +198,7 @@ cdef SCIP_RETCODE PyBendersFreesub (SCIP* scip, SCIP_BENDERS* benders, int probn - return SCIP_OKAY - - #TODO: Really need to ask about the passing and returning of variables --cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber) with gil: -+cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata - bendersdata = SCIPbendersGetData(benders) - PyBenders = bendersdata -diff --git a/src/pyscipopt/benderscut.pxi b/src/pyscipopt/benderscut.pxi -index 506a6f065..1ce561a06 100644 ---- a/src/pyscipopt/benderscut.pxi -+++ b/src/pyscipopt/benderscut.pxi -@@ -24,10 +24,10 @@ cdef class Benderscut: - print("python error in benderscutexec: this method needs to be implemented") - return {} - --cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata -@@ -35,35 +35,35 @@ cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut) wit - Py_DECREF(PyBenderscut) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) with gil: -+cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata - PyBenderscut.benderscutexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BENDERSCUTDATA* benderscutdata - benderscutdata = SCIPbenderscutGetData(benderscut) - PyBenderscut = benderscutdata -diff --git a/src/pyscipopt/branchrule.pxi b/src/pyscipopt/branchrule.pxi -index 251aa33b1..2d3411d2c 100644 ---- a/src/pyscipopt/branchrule.pxi -+++ b/src/pyscipopt/branchrule.pxi -@@ -39,10 +39,10 @@ cdef class Branchrule: - - - --cdef SCIP_RETCODE PyBranchruleCopy (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleCopy (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -@@ -50,35 +50,35 @@ cdef SCIP_RETCODE PyBranchruleFree (SCIP* scip, SCIP_BRANCHRULE* branchrule) wit - Py_DECREF(PyBranchrule) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleInit (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleInit (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExit (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleExit (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleInitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleInitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) with gil: -+cdef SCIP_RETCODE PyBranchruleExitsol (SCIP* scip, SCIP_BRANCHRULE* branchrule) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata - PyBranchrule.branchexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -@@ -86,7 +86,7 @@ cdef SCIP_RETCODE PyBranchruleExeclp (SCIP* scip, SCIP_BRANCHRULE* branchrule, S - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -@@ -94,7 +94,7 @@ cdef SCIP_RETCODE PyBranchruleExecext(SCIP* scip, SCIP_BRANCHRULE* branchrule, S - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyBranchruleExecps(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyBranchruleExecps(SCIP* scip, SCIP_BRANCHRULE* branchrule, SCIP_Bool allowaddcons, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_BRANCHRULEDATA* branchruledata - branchruledata = SCIPbranchruleGetData(branchrule) - PyBranchrule = branchruledata -diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi -index 80c60c17c..1299ad35c 100644 ---- a/src/pyscipopt/conshdlr.pxi -+++ b/src/pyscipopt/conshdlr.pxi -@@ -150,16 +150,16 @@ cdef Constraint getPyCons(SCIP_CONS* cons): - - - --cdef SCIP_RETCODE PyConshdlrCopy (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_Bool* valid) with gil: -+cdef SCIP_RETCODE PyConshdlrCopy (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_Bool* valid) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) with gil: -+cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consfree() - Py_DECREF(PyConshdlr) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -167,7 +167,7 @@ cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c - PyConshdlr.consinit(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -175,7 +175,7 @@ cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c - PyConshdlr.consexit(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -183,7 +183,7 @@ cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consinitpre(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -191,7 +191,7 @@ cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consexitpre(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -199,7 +199,7 @@ cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consinitsol(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) with gil: -+cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -207,7 +207,7 @@ cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consexitsol(constraints, restart) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_CONSDATA** consdata) with gil: -+cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_CONSDATA** consdata) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - assert consdata[0] == PyCons -@@ -216,7 +216,7 @@ cdef SCIP_RETCODE PyConsDelete (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - Py_DECREF(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* sourcecons, SCIP_CONS** targetcons) with gil: -+cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* sourcecons, SCIP_CONS** targetcons) noexcept with gil: - cdef Constraint PyTargetCons - PyConshdlr = getPyConshdlr(conshdlr) - PySourceCons = getPyCons(sourcecons) -@@ -235,7 +235,7 @@ cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* s - PySourceCons.isRemovable(), PySourceCons.isStickingAtNode())) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) with gil: -+cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -244,7 +244,7 @@ cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - infeasible[0] = result_dict.get("infeasible", infeasible[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -254,7 +254,7 @@ cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, -- SCIP_SOL* sol, SCIP_RESULT* result) with gil: -+ SCIP_SOL* sol, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -265,7 +265,7 @@ cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, -- SCIP_Bool solinfeasible, SCIP_RESULT* result) with gil: -+ SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -274,7 +274,7 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -285,7 +285,7 @@ cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* con - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, -- SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) with gil: -+ SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -295,7 +295,7 @@ cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_SOL* sol, SCIP_Bool checkintegrality, -- SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) with gil: -+ SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -306,7 +306,7 @@ cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsProp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, int nmarkedconss, -- SCIP_PROPTIMING proptiming, SCIP_RESULT* result) with gil: -+ SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -319,7 +319,7 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, - int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, - int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, -- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: -+ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -354,12 +354,12 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsResprop (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR* infervar, int inferinfo, -- SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) with gil: -+ SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consresprop() - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) with gil: -+cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - if cons == NULL: - PyConshdlr.conslock(None, locktype, nlockspos, nlocksneg) -@@ -368,31 +368,31 @@ cdef SCIP_RETCODE PyConsLock (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* co - PyConshdlr.conslock(PyCons, locktype, nlockspos, nlocksneg) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsActive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsActive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consactive(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDeactive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsDeactive (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consdeactive(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsEnable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsEnable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consenable(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) with gil: -+cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - PyConshdlr.consdisable(PyCons) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) with gil: -+cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] - for i in range(nconss): -@@ -400,7 +400,7 @@ cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - PyConshdlr.consdelvars(constraints) - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsPrint (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, FILE* file) with gil: -+cdef SCIP_RETCODE PyConsPrint (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, FILE* file) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - # TODO: pass file -@@ -411,7 +411,7 @@ cdef SCIP_RETCODE PyConsCopy (SCIP* scip, SCIP_CONS** cons, const char* name, SC - SCIP_CONS* sourcecons, SCIP_HASHMAP* varmap, SCIP_HASHMAP* consmap, SCIP_Bool initial, - SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, - SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, -- SCIP_Bool isglobal, SCIP_Bool* valid) with gil: -+ SCIP_Bool isglobal, SCIP_Bool* valid) noexcept with gil: - # TODO everything! - PyConshdlr = getPyConshdlr(sourceconshdlr) - PyConshdlr.conscopy() -@@ -421,14 +421,14 @@ cdef SCIP_RETCODE PyConsCopy (SCIP* scip, SCIP_CONS** cons, const char* name, SC - cdef SCIP_RETCODE PyConsParse (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cons, const char* name, const char* str, - SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, - SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, -- SCIP_Bool stickingatnode, SCIP_Bool* success) with gil: -+ SCIP_Bool stickingatnode, SCIP_Bool* success) noexcept with gil: - # TODO everything! - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consparse() - success[0] = False - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success) with gil: -+cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success) noexcept with gil: - # TODO - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) -@@ -436,7 +436,7 @@ cdef SCIP_RETCODE PyConsGetvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* - success[0] = False - return SCIP_OKAY - --cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success) with gil: -+cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) - PyCons = getPyCons(cons) - result_dict = PyConshdlr.consgetnvars(PyCons) -@@ -445,7 +445,7 @@ cdef SCIP_RETCODE PyConsGetnvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS - return SCIP_OKAY - - cdef SCIP_RETCODE PyConsGetdivebdchgs (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_DIVESET* diveset, SCIP_SOL* sol, -- SCIP_Bool* success, SCIP_Bool* infeasible) with gil: -+ SCIP_Bool* success, SCIP_Bool* infeasible) noexcept with gil: - # TODO - PyConshdlr = getPyConshdlr(conshdlr) - PyConshdlr.consgetdivebdchgs() -diff --git a/src/pyscipopt/cutsel.pxi b/src/pyscipopt/cutsel.pxi -index e953cb1e9..d259fb28e 100644 ---- a/src/pyscipopt/cutsel.pxi -+++ b/src/pyscipopt/cutsel.pxi -@@ -29,10 +29,10 @@ cdef class Cutsel: - return {} - - --cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata -@@ -40,7 +40,7 @@ cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: - Py_DECREF(PyCutsel) - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata -@@ -48,21 +48,21 @@ cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: - return SCIP_OKAY - - --cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata - PyCutsel.cutselexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata - PyCutsel.cutselinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: -+cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cutseldata = SCIPcutselGetData(cutsel) - PyCutsel = cutseldata -@@ -71,7 +71,7 @@ cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil: - - cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts, - SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts, -- int* nselectedcuts, SCIP_RESULT* result) with gil: -+ int* nselectedcuts, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata - cdef SCIP_ROW* scip_row - cutseldata = SCIPcutselGetData(cutsel) -diff --git a/src/pyscipopt/event.pxi b/src/pyscipopt/event.pxi -index 95c8bc1f4..914e882ed 100644 ---- a/src/pyscipopt/event.pxi -+++ b/src/pyscipopt/event.pxi -@@ -39,48 +39,48 @@ cdef class Eventhdlr: - - - # local helper functions for the interface --cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - cdef SCIP_EVENTHDLRDATA* eventhdlrdata - eventhdlrdata = SCIPeventhdlrGetData(eventhdlr) - return eventhdlrdata - --cdef SCIP_RETCODE PyEventCopy (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventCopy (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventcopy() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventFree (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventFree (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventfree() - Py_DECREF(PyEventhdlr) - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventInit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventInit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventExit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventExit (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventInitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventInitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventExitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) with gil: -+cdef SCIP_RETCODE PyEventExitsol (SCIP* scip, SCIP_EVENTHDLR* eventhdlr) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventDelete (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA** eventdata) with gil: -+cdef SCIP_RETCODE PyEventDelete (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA** eventdata) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEventhdlr.eventdelete() - return SCIP_OKAY - --cdef SCIP_RETCODE PyEventExec (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENT* event, SCIP_EVENTDATA* eventdata) with gil: -+cdef SCIP_RETCODE PyEventExec (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENT* event, SCIP_EVENTDATA* eventdata) noexcept with gil: - PyEventhdlr = getPyEventhdlr(eventhdlr) - PyEvent = Event() - PyEvent.event = event -diff --git a/src/pyscipopt/heuristic.pxi b/src/pyscipopt/heuristic.pxi -index 2980a1aee..930315630 100644 ---- a/src/pyscipopt/heuristic.pxi -+++ b/src/pyscipopt/heuristic.pxi -@@ -31,10 +31,10 @@ cdef class Heur: - - - --cdef SCIP_RETCODE PyHeurCopy (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurCopy (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata -@@ -42,35 +42,35 @@ cdef SCIP_RETCODE PyHeurFree (SCIP* scip, SCIP_HEUR* heur) with gil: - Py_DECREF(PyHeur) - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurInit (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurInit (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurExit (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurExit (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurInitsol (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurInitsol (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurExitsol (SCIP* scip, SCIP_HEUR* heur) with gil: -+cdef SCIP_RETCODE PyHeurExitsol (SCIP* scip, SCIP_HEUR* heur) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata - PyHeur.heurexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyHeurExec (SCIP* scip, SCIP_HEUR* heur, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyHeurExec (SCIP* scip, SCIP_HEUR* heur, SCIP_HEURTIMING heurtiming, SCIP_Bool nodeinfeasible, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_HEURDATA* heurdata - heurdata = SCIPheurGetData(heur) - PyHeur = heurdata -diff --git a/src/pyscipopt/nodesel.pxi b/src/pyscipopt/nodesel.pxi -index 4d795bc9d..a3e832f15 100644 ---- a/src/pyscipopt/nodesel.pxi -+++ b/src/pyscipopt/nodesel.pxi -@@ -42,10 +42,10 @@ cdef class Nodesel: - return 0 - - --cdef SCIP_RETCODE PyNodeselCopy (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselCopy (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -@@ -53,7 +53,7 @@ cdef SCIP_RETCODE PyNodeselFree (SCIP* scip, SCIP_NODESEL* nodesel) with gil: - Py_DECREF(PyNodesel) - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -@@ -61,28 +61,28 @@ cdef SCIP_RETCODE PyNodeselInit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: - return SCIP_OKAY - - --cdef SCIP_RETCODE PyNodeselExit (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselExit (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata - PyNodesel.nodeexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselInitsol (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselInitsol (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata - PyNodesel.nodeinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselExitsol (SCIP* scip, SCIP_NODESEL* nodesel) with gil: -+cdef SCIP_RETCODE PyNodeselExitsol (SCIP* scip, SCIP_NODESEL* nodesel) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata - PyNodesel.nodeexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE** selnode) with gil: -+cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE** selnode) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -@@ -91,7 +91,7 @@ cdef SCIP_RETCODE PyNodeselSelect (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* - selnode[0] = selected_node.scip_node - return SCIP_OKAY - --cdef int PyNodeselComp (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* node1, SCIP_NODE* node2) with gil: -+cdef int PyNodeselComp (SCIP* scip, SCIP_NODESEL* nodesel, SCIP_NODE* node1, SCIP_NODE* node2) noexcept with gil: - cdef SCIP_NODESELDATA* nodeseldata - nodeseldata = SCIPnodeselGetData(nodesel) - PyNodesel = nodeseldata -diff --git a/src/pyscipopt/presol.pxi b/src/pyscipopt/presol.pxi -index d2b9115a5..13bd9a623 100644 ---- a/src/pyscipopt/presol.pxi -+++ b/src/pyscipopt/presol.pxi -@@ -30,10 +30,10 @@ cdef class Presol: - - - --cdef SCIP_RETCODE PyPresolCopy (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolCopy (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -@@ -41,14 +41,14 @@ cdef SCIP_RETCODE PyPresolFree (SCIP* scip, SCIP_PRESOL* presol) with gil: - Py_DECREF(PyPresol) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolInit (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolInit (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata - PyPresol.presolinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -@@ -56,14 +56,14 @@ cdef SCIP_RETCODE PyPresolExit (SCIP* scip, SCIP_PRESOL* presol) with gil: - return SCIP_OKAY - - --cdef SCIP_RETCODE PyPresolInitpre (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolInitpre (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata - PyPresol.presolinitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPresolExitpre (SCIP* scip, SCIP_PRESOL* presol) with gil: -+cdef SCIP_RETCODE PyPresolExitpre (SCIP* scip, SCIP_PRESOL* presol) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -@@ -74,7 +74,7 @@ cdef SCIP_RETCODE PyPresolExec (SCIP* scip, SCIP_PRESOL* presol, int nrounds, SC - int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, - int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, - int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, -- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: -+ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PRESOLDATA* presoldata - presoldata = SCIPpresolGetData(presol) - PyPresol = presoldata -diff --git a/src/pyscipopt/pricer.pxi b/src/pyscipopt/pricer.pxi -index 1368572de..a218b254c 100644 ---- a/src/pyscipopt/pricer.pxi -+++ b/src/pyscipopt/pricer.pxi -@@ -33,10 +33,10 @@ cdef class Pricer: - - - --cdef SCIP_RETCODE PyPricerCopy (SCIP* scip, SCIP_PRICER* pricer, SCIP_Bool* valid) with gil: -+cdef SCIP_RETCODE PyPricerCopy (SCIP* scip, SCIP_PRICER* pricer, SCIP_Bool* valid) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata -@@ -44,35 +44,35 @@ cdef SCIP_RETCODE PyPricerFree (SCIP* scip, SCIP_PRICER* pricer) with gil: - Py_DECREF(PyPricer) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerInit (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerInit (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerExit (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerExit (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerInitsol (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerInitsol (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerExitsol (SCIP* scip, SCIP_PRICER* pricer) with gil: -+cdef SCIP_RETCODE PyPricerExitsol (SCIP* scip, SCIP_PRICER* pricer) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata - PyPricer.pricerexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* lowerbound, SCIP_Bool* stopearly, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* lowerbound, SCIP_Bool* stopearly, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata -@@ -82,7 +82,7 @@ cdef SCIP_RETCODE PyPricerRedcost (SCIP* scip, SCIP_PRICER* pricer, SCIP_Real* l - stopearly[0] = result_dict.get("stopearly", stopearly[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPricerFarkas (SCIP* scip, SCIP_PRICER* pricer, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyPricerFarkas (SCIP* scip, SCIP_PRICER* pricer, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PRICERDATA* pricerdata - pricerdata = SCIPpricerGetData(pricer) - PyPricer = pricerdata -diff --git a/src/pyscipopt/propagator.pxi b/src/pyscipopt/propagator.pxi -index d792577d9..4508efe78 100644 ---- a/src/pyscipopt/propagator.pxi -+++ b/src/pyscipopt/propagator.pxi -@@ -47,10 +47,10 @@ cdef class Prop: - - - --cdef SCIP_RETCODE PyPropCopy (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropCopy (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -58,42 +58,42 @@ cdef SCIP_RETCODE PyPropFree (SCIP* scip, SCIP_PROP* prop) with gil: - Py_DECREF(PyProp) - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropInit (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropInit (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExit (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropExit (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropInitpre (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropInitpre (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propinitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExitpre (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropExitpre (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propexitpre() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropInitsol (SCIP* scip, SCIP_PROP* prop) with gil: -+cdef SCIP_RETCODE PyPropInitsol (SCIP* scip, SCIP_PROP* prop) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata - PyProp.propinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExitsol (SCIP* scip, SCIP_PROP* prop, SCIP_Bool restart) with gil: -+cdef SCIP_RETCODE PyPropExitsol (SCIP* scip, SCIP_PROP* prop, SCIP_Bool restart) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -104,7 +104,7 @@ cdef SCIP_RETCODE PyPropPresol (SCIP* scip, SCIP_PROP* prop, int nrounds, SCIP_P - int nnewfixedvars, int nnewaggrvars, int nnewchgvartypes, int nnewchgbds, int nnewholes, - int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, - int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, -- int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) with gil: -+ int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -137,7 +137,7 @@ cdef SCIP_RETCODE PyPropPresol (SCIP* scip, SCIP_PROP* prop, int nrounds, SCIP_P - nchgsides[0] = result_dict["nchgsides"] - return SCIP_OKAY - --cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PROPDATA* propdata - propdata = SCIPpropGetData(prop) - PyProp = propdata -@@ -147,7 +147,7 @@ cdef SCIP_RETCODE PyPropExec (SCIP* scip, SCIP_PROP* prop, SCIP_PROPTIMING propt - return SCIP_OKAY - - cdef SCIP_RETCODE PyPropResProp (SCIP* scip, SCIP_PROP* prop, SCIP_VAR* infervar, int inferinfo, -- SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) with gil: -+ SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX* bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_PROPDATA* propdata - cdef SCIP_VAR* tmp - tmp = infervar -diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi -index df0b3a288..2c45585d6 100644 ---- a/src/pyscipopt/reader.pxi -+++ b/src/pyscipopt/reader.pxi -@@ -18,10 +18,10 @@ cdef class Reader: - return {} - - --cdef SCIP_RETCODE PyReaderCopy (SCIP* scip, SCIP_READER* reader) with gil: -+cdef SCIP_RETCODE PyReaderCopy (SCIP* scip, SCIP_READER* reader) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) with gil: -+cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) noexcept with gil: - cdef SCIP_READERDATA* readerdata - readerdata = SCIPreaderGetData(reader) - PyReader = readerdata -@@ -29,7 +29,7 @@ cdef SCIP_RETCODE PyReaderFree (SCIP* scip, SCIP_READER* reader) with gil: - Py_DECREF(PyReader) - return SCIP_OKAY - --cdef SCIP_RETCODE PyReaderRead (SCIP* scip, SCIP_READER* reader, const char* filename, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyReaderRead (SCIP* scip, SCIP_READER* reader, const char* filename, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_READERDATA* readerdata - readerdata = SCIPreaderGetData(reader) - PyReader = readerdata -@@ -44,7 +44,7 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, - SCIP_VAR** vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, - SCIP_VAR** fixedvars, int nfixedvars, int startnvars, - SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, -- SCIP_Bool genericnames, SCIP_RESULT* result) with gil: -+ SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_READERDATA* readerdata - readerdata = SCIPreaderGetData(reader) - cdef int fd = fileno(file) -diff --git a/src/pyscipopt/relax.pxi b/src/pyscipopt/relax.pxi -index 2b52c2643..81695e8bb 100644 ---- a/src/pyscipopt/relax.pxi -+++ b/src/pyscipopt/relax.pxi -@@ -30,10 +30,10 @@ cdef class Relax: - return{} - - --cdef SCIP_RETCODE PyRelaxCopy (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxCopy (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata -@@ -41,35 +41,35 @@ cdef SCIP_RETCODE PyRelaxFree (SCIP* scip, SCIP_RELAX* relax) with gil: - Py_DECREF(PyRelax) - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxInit (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxInit (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxinit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxExit (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxExit (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxInitsol (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxInitsol (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxinitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxExitsol (SCIP* scip, SCIP_RELAX* relax) with gil: -+cdef SCIP_RETCODE PyRelaxExitsol (SCIP* scip, SCIP_RELAX* relax) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata - PyRelax.relaxexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_RELAX* relax, SCIP_Real* lowerbound, SCIP_RESULT* result) with gil: -+cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_RELAX* relax, SCIP_Real* lowerbound, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_RELAXDATA* relaxdata - relaxdata = SCIPrelaxGetData(relax) - PyRelax = relaxdata -diff --git a/src/pyscipopt/scip.pxd b/src/pyscipopt/scip.pxd -index 12815dbc4..f35a42486 100644 ---- a/src/pyscipopt/scip.pxd -+++ b/src/pyscipopt/scip.pxd -@@ -501,7 +501,7 @@ cdef extern from "scip/scip.h": - ctypedef union SCIP_DOMCHG: - pass - -- ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) -+ ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept - ctypedef void (*errormessagecallback) (void *data, FILE *file, const char *msg) - ctypedef SCIP_RETCODE (*messagehdlrfree) (SCIP_MESSAGEHDLR *messagehdlr) - -diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi -index 0b2332d88..552197785 100644 ---- a/src/pyscipopt/scip.pxi -+++ b/src/pyscipopt/scip.pxi -@@ -975,10 +975,10 @@ cdef class Constraint: - and self.scip_cons == (other).scip_cons) - - --cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg): -+cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept: - sys.stdout.write(msg.decode('UTF-8')) - --cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg): -+cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg) noexcept: - sys.stderr.write(msg.decode('UTF-8')) - - # - remove create(), includeDefaultPlugins(), createProbBasic() methods -diff --git a/src/pyscipopt/sepa.pxi b/src/pyscipopt/sepa.pxi -index 271945db1..94355a7d2 100644 ---- a/src/pyscipopt/sepa.pxi -+++ b/src/pyscipopt/sepa.pxi -@@ -34,10 +34,10 @@ cdef class Sepa: - - - --cdef SCIP_RETCODE PySepaCopy (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaCopy (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata -@@ -45,35 +45,35 @@ cdef SCIP_RETCODE PySepaFree (SCIP* scip, SCIP_SEPA* sepa) with gil: - Py_DECREF(PySepa) - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaInit (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaInit (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepainit() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExit (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaExit (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepaexit() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaInitsol (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaInitsol (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepainitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExitsol (SCIP* scip, SCIP_SEPA* sepa) with gil: -+cdef SCIP_RETCODE PySepaExitsol (SCIP* scip, SCIP_SEPA* sepa) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata - PySepa.sepaexitsol() - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result, unsigned int allowlocal, int depth) with gil: -+cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result, unsigned int allowlocal, int depth) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - PySepa = sepadata -@@ -81,7 +81,7 @@ cdef SCIP_RETCODE PySepaExeclp (SCIP* scip, SCIP_SEPA* sepa, SCIP_RESULT* result - result[0] = result_dict.get("result", result[0]) - return SCIP_OKAY - --cdef SCIP_RETCODE PySepaExecsol (SCIP* scip, SCIP_SEPA* sepa, SCIP_SOL* sol, SCIP_RESULT* result, unsigned int allowlocal, int depth) with gil: -+cdef SCIP_RETCODE PySepaExecsol (SCIP* scip, SCIP_SEPA* sepa, SCIP_SOL* sol, SCIP_RESULT* result, unsigned int allowlocal, int depth) noexcept with gil: - cdef SCIP_SEPADATA* sepadata - sepadata = SCIPsepaGetData(sepa) - solution = Solution.create(scip, sol) From c4363fc97eb67fb08073ea37ef88d633e9feb160 Mon Sep 17 00:00:00 2001 From: Release Manager Date: Sat, 27 Apr 2024 17:37:12 +0200 Subject: [PATCH 191/191] Updated SageMath version to 10.4.beta4 --- CITATION.cff | 4 ++-- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sage_conf/version_requirements.txt | 2 +- build/pkgs/sage_docbuild/version_requirements.txt | 2 +- build/pkgs/sage_setup/version_requirements.txt | 2 +- build/pkgs/sage_sws2rst/version_requirements.txt | 2 +- build/pkgs/sagelib/version_requirements.txt | 2 +- build/pkgs/sagemath_bliss/version_requirements.txt | 2 +- build/pkgs/sagemath_categories/version_requirements.txt | 2 +- build/pkgs/sagemath_coxeter3/version_requirements.txt | 2 +- build/pkgs/sagemath_environment/version_requirements.txt | 2 +- build/pkgs/sagemath_mcqd/version_requirements.txt | 2 +- build/pkgs/sagemath_meataxe/version_requirements.txt | 2 +- build/pkgs/sagemath_objects/version_requirements.txt | 2 +- build/pkgs/sagemath_repl/version_requirements.txt | 2 +- build/pkgs/sagemath_sirocco/version_requirements.txt | 2 +- build/pkgs/sagemath_tdlib/version_requirements.txt | 2 +- pkgs/sage-conf/VERSION.txt | 2 +- pkgs/sage-conf_conda/VERSION.txt | 2 +- pkgs/sage-conf_pypi/VERSION.txt | 2 +- pkgs/sage-docbuild/VERSION.txt | 2 +- pkgs/sage-setup/VERSION.txt | 2 +- pkgs/sage-sws2rst/VERSION.txt | 2 +- pkgs/sagemath-bliss/VERSION.txt | 2 +- pkgs/sagemath-categories/VERSION.txt | 2 +- pkgs/sagemath-coxeter3/VERSION.txt | 2 +- pkgs/sagemath-environment/VERSION.txt | 2 +- pkgs/sagemath-mcqd/VERSION.txt | 2 +- pkgs/sagemath-meataxe/VERSION.txt | 2 +- pkgs/sagemath-objects/VERSION.txt | 2 +- pkgs/sagemath-repl/VERSION.txt | 2 +- pkgs/sagemath-sirocco/VERSION.txt | 2 +- pkgs/sagemath-tdlib/VERSION.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 38 files changed, 45 insertions(+), 45 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 78059fdc091..894be5d6a9e 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.4.beta3 +version: 10.4.beta4 doi: 10.5281/zenodo.593563 -date-released: 2024-04-12 +date-released: 2024-04-27 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index fa9d32fec7a..c62fa370476 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.4.beta3, Release Date: 2024-04-12 +SageMath version 10.4.beta4, Release Date: 2024-04-27 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 4c621a4ea47..5a209c1c1bc 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=f46d28f976fdd73aa93eff6810b28b3e7b165bf1 -md5=db30b8d7485d8c3b6f4f73a8282816be -cksum=726460493 +sha1=2d6779beb2e69f0f7bddc2edc44ad275442ffd29 +md5=789344e03a6b57ba1538c0c760449720 +cksum=3806733369 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 2310b785e39..6035b129425 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -3cffb4c1c8d29849cfeb9dc0332d7549800e044a +0a7b2513287af1124a358c2494b8bef4668a1882 diff --git a/build/pkgs/sage_conf/version_requirements.txt b/build/pkgs/sage_conf/version_requirements.txt index a9fc6b33c1e..1e512338617 100644 --- a/build/pkgs/sage_conf/version_requirements.txt +++ b/build/pkgs/sage_conf/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.4b3 +sage-conf ~= 10.4b4 diff --git a/build/pkgs/sage_docbuild/version_requirements.txt b/build/pkgs/sage_docbuild/version_requirements.txt index 6392017efee..005cc4306ac 100644 --- a/build/pkgs/sage_docbuild/version_requirements.txt +++ b/build/pkgs/sage_docbuild/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.4b3 +sage-docbuild ~= 10.4b4 diff --git a/build/pkgs/sage_setup/version_requirements.txt b/build/pkgs/sage_setup/version_requirements.txt index fa79fc9374b..fc721f1c1da 100644 --- a/build/pkgs/sage_setup/version_requirements.txt +++ b/build/pkgs/sage_setup/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.4b3 +sage-setup ~= 10.4b4 diff --git a/build/pkgs/sage_sws2rst/version_requirements.txt b/build/pkgs/sage_sws2rst/version_requirements.txt index 012366aac27..9ec4b186ac9 100644 --- a/build/pkgs/sage_sws2rst/version_requirements.txt +++ b/build/pkgs/sage_sws2rst/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.4b3 +sage-sws2rst ~= 10.4b4 diff --git a/build/pkgs/sagelib/version_requirements.txt b/build/pkgs/sagelib/version_requirements.txt index 958d7998ec8..9c1daa7372c 100644 --- a/build/pkgs/sagelib/version_requirements.txt +++ b/build/pkgs/sagelib/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.4b3 +sagemath-standard ~= 10.4b4 diff --git a/build/pkgs/sagemath_bliss/version_requirements.txt b/build/pkgs/sagemath_bliss/version_requirements.txt index f140cad57dd..ba9e1b2081d 100644 --- a/build/pkgs/sagemath_bliss/version_requirements.txt +++ b/build/pkgs/sagemath_bliss/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.4b3 +sagemath-bliss ~= 10.4b4 diff --git a/build/pkgs/sagemath_categories/version_requirements.txt b/build/pkgs/sagemath_categories/version_requirements.txt index 15b52d809bf..6155490b8ef 100644 --- a/build/pkgs/sagemath_categories/version_requirements.txt +++ b/build/pkgs/sagemath_categories/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.4b3 +sagemath-categories ~= 10.4b4 diff --git a/build/pkgs/sagemath_coxeter3/version_requirements.txt b/build/pkgs/sagemath_coxeter3/version_requirements.txt index db035aacdca..932bad03329 100644 --- a/build/pkgs/sagemath_coxeter3/version_requirements.txt +++ b/build/pkgs/sagemath_coxeter3/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.4b3 +sagemath-coxeter3 ~= 10.4b4 diff --git a/build/pkgs/sagemath_environment/version_requirements.txt b/build/pkgs/sagemath_environment/version_requirements.txt index 80fd875a7e4..475da537a2b 100644 --- a/build/pkgs/sagemath_environment/version_requirements.txt +++ b/build/pkgs/sagemath_environment/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.4b3 +sagemath-environment ~= 10.4b4 diff --git a/build/pkgs/sagemath_mcqd/version_requirements.txt b/build/pkgs/sagemath_mcqd/version_requirements.txt index 58a3e31ff65..0631db2f93a 100644 --- a/build/pkgs/sagemath_mcqd/version_requirements.txt +++ b/build/pkgs/sagemath_mcqd/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.4b3 +sagemath-mcqd ~= 10.4b4 diff --git a/build/pkgs/sagemath_meataxe/version_requirements.txt b/build/pkgs/sagemath_meataxe/version_requirements.txt index b46a8c93c1e..fa695fc4e4a 100644 --- a/build/pkgs/sagemath_meataxe/version_requirements.txt +++ b/build/pkgs/sagemath_meataxe/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.4b3 +sagemath-meataxe ~= 10.4b4 diff --git a/build/pkgs/sagemath_objects/version_requirements.txt b/build/pkgs/sagemath_objects/version_requirements.txt index 56948780fe6..38fc3c4dec3 100644 --- a/build/pkgs/sagemath_objects/version_requirements.txt +++ b/build/pkgs/sagemath_objects/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.4b3 +sagemath-objects ~= 10.4b4 diff --git a/build/pkgs/sagemath_repl/version_requirements.txt b/build/pkgs/sagemath_repl/version_requirements.txt index 230c8f95374..9b039bdd460 100644 --- a/build/pkgs/sagemath_repl/version_requirements.txt +++ b/build/pkgs/sagemath_repl/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.4b3 +sagemath-repl ~= 10.4b4 diff --git a/build/pkgs/sagemath_sirocco/version_requirements.txt b/build/pkgs/sagemath_sirocco/version_requirements.txt index d04d2ab48b0..09d50bb08f7 100644 --- a/build/pkgs/sagemath_sirocco/version_requirements.txt +++ b/build/pkgs/sagemath_sirocco/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.4b3 +sagemath-sirocco ~= 10.4b4 diff --git a/build/pkgs/sagemath_tdlib/version_requirements.txt b/build/pkgs/sagemath_tdlib/version_requirements.txt index 53da30e01ec..5f55b35c539 100644 --- a/build/pkgs/sagemath_tdlib/version_requirements.txt +++ b/build/pkgs/sagemath_tdlib/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.4b3 +sagemath-tdlib ~= 10.4b4 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/src/VERSION.txt b/src/VERSION.txt index af343da123a..957ecf95b0a 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.4.beta3 +10.4.beta4 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index ec030052a09..c2aa055eac9 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.4.beta3' -SAGE_RELEASE_DATE='2024-04-12' -SAGE_VERSION_BANNER='SageMath version 10.4.beta3, Release Date: 2024-04-12' +SAGE_VERSION='10.4.beta4' +SAGE_RELEASE_DATE='2024-04-27' +SAGE_VERSION_BANNER='SageMath version 10.4.beta4, Release Date: 2024-04-27' diff --git a/src/sage/version.py b/src/sage/version.py index c398930ba19..191a5474629 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.4.beta3' -date = '2024-04-12' -banner = 'SageMath version 10.4.beta3, Release Date: 2024-04-12' +version = '10.4.beta4' +date = '2024-04-27' +banner = 'SageMath version 10.4.beta4, Release Date: 2024-04-27'