diff --git a/.github/sync_labels.py b/.github/sync_labels.py index c920d21fca4..799b4985c5d 100755 --- a/.github/sync_labels.py +++ b/.github/sync_labels.py @@ -56,7 +56,7 @@ class ReviewDecision(Enum): """ changes_requested = 'CHANGES_REQUESTED' approved = 'APPROVED' - unclear = 'COMMENTED' + unclear = 'UNCLEAR' class Priority(Enum): r""" @@ -319,12 +319,15 @@ def get_review_decision(self): return None if self._review_decision is not None: + if self._review_decision == ReviewDecision.unclear: + return None return self._review_decision data = self.view('reviewDecision') if data: self._review_decision = ReviewDecision(data) else: + # To separate a not supplied value from not cached (see https://github.com/sagemath/sage/pull/36177#issuecomment-1704022893 ff) self._review_decision = ReviewDecision.unclear info('Review decision for %s: %s' % (self._issue, self._review_decision.value)) return self._review_decision @@ -349,9 +352,9 @@ def get_reviews(self, complete=False): self.get_commits() date = self._commit_date - no_rev = ReviewDecision.unclear.value + unproper_rev = RevState.commented.value new_revs = [rev for rev in self._reviews if rev['submittedAt'] > date] - proper_new_revs = [rev for rev in new_revs if rev['state'] != no_rev] + proper_new_revs = [rev for rev in new_revs if rev['state'] != unproper_rev] info('Proper reviews after %s for %s: %s' % (date, self._issue, proper_new_revs)) return proper_new_revs @@ -463,11 +466,6 @@ def approve_allowed(self): r""" Return if the actor has permission to approve this PR. """ - revs = self.get_reviews(complete=True) - if not any(rev['authorAssociation'] in ('MEMBER', 'OWNER') for rev in revs): - info('PR %s can\'t be approved because of missing member review' % (self._issue)) - return False - revs = self.get_reviews() revs = [rev for rev in revs if rev['author']['login'] != self._actor] ch_req = ReviewDecision.changes_requested diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ada020d8722..547ba7f90fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Update system packages id: prepare diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 2048d9c43ae..14d38feff96 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -8,6 +8,11 @@ on: - 'public/build/**-runci' pull_request: types: + # Defaults + - opened + - synchronize + - reopened + # When a CI label is added - labeled workflow_dispatch: # Allow to run manually @@ -21,13 +26,18 @@ jobs: test: name: Conda runs-on: ${{ matrix.os }} - - # Run on push, workflow dispatch and when certain labels are added + + # Run on push, workflow dispatch and when certain labels are added or are present if: | - github.event.action != 'labeled' || - github.event.label.name == 'c: packages: optional' || - github.event.label.name == 'c: packages: standard' || - github.event.label.name == 's: run conda ci' + github.event_name != 'pull_request' || + ((github.event.action != 'labeled' && + (contains(github.event.pull_request.labels.*.name, 'c: packages: standard') || + contains(github.event.pull_request.labels.*.name, 'c: packages: optional') || + contains(github.event.pull_request.labels.*.name, 's: run conda ci'))) || + (github.event.action == 'labeled' && + (github.event.label.name == 'c: packages: optional' || + github.event.label.name == 'c: packages: standard' || + github.event.label.name == 's: run conda ci'))) strategy: fail-fast: false @@ -39,7 +49,7 @@ jobs: conda-env: [environment] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check for Miniconda id: check_conda diff --git a/.github/workflows/ci-linux-incremental.yml b/.github/workflows/ci-linux-incremental.yml new file mode 100644 index 00000000000..c3de6545efb --- /dev/null +++ b/.github/workflows/ci-linux-incremental.yml @@ -0,0 +1,96 @@ +name: CI Linux incremental + +## This GitHub Actions workflow runs SAGE_ROOT/tox.ini with select environments, +## whenever a GitHub pull request is opened or synchronized in a repository +## where GitHub Actions are enabled. +## +## It builds and checks some sage spkgs as defined in TARGETS. +## +## A job succeeds if there is no error. +## +## The build is run with "make V=0", so the build logs of individual packages are suppressed. +## +## At the end, all package build logs that contain an error are printed out. +## +## After all jobs have finished (or are canceled) and a short delay, +## tar files of all logs are made available as "build artifacts". + +on: + pull_request: + types: + # Defaults + - opened + - synchronize + - reopened + # When a CI label is added + - labeled + workflow_dispatch: + +concurrency: + # Cancel previous runs of this workflow for the same branch + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + packages: write + +jobs: + + changed_files: + runs-on: ubuntu-latest + name: List changed packages + outputs: + uninstall_targets: ${{ steps.build-targets.outputs.uninstall_targets }} + build_targets: ${{ steps.build-targets.outputs.build_targets }} + steps: + - uses: actions/checkout@v4 + - name: Get all packages that have changed + id: changed-packages + uses: tj-actions/changed-files@v38 + with: + files_yaml: | + configures: + - 'build/pkgs/*/spkg-configure.m4' + pkgs: + - 'build/pkgs/**' + - 'pkgs/**' + - name: Determine targets to build + id: build-targets + run: | + echo "uninstall_targets=$(echo $(for a in '' ${{ steps.changed-packages.outputs.configures_all_changed_files }}; do echo $a | sed -E 's,build/pkgs/([_.a-z0-9]*)/spkg-configure[.]m4 *,\1-uninstall,'; done | sort -u))" >> $GITHUB_OUTPUT + echo "build_targets=$(echo $(for a in '' ${{ steps.changed-packages.outputs.pkgs_all_changed_files }}; do echo $a | sed -E 's,-,_,g;s,(build/)?pkgs/([-_.a-z0-9]*)/[^ ]* *,\2-ensure,;'; done | sort -u))" >> $GITHUB_OUTPUT + cat $GITHUB_OUTPUT + minimal: + needs: [changed_files] + if: | + github.event_name != 'pull_request' || + ((github.event.action != 'labeled' && + (contains(github.event.pull_request.labels.*.name, 'c: packages: standard') || + contains(github.event.pull_request.labels.*.name, 'c: packages: optional'))) || + (github.event.action == 'labeled' && + (github.event.label.name == 'c: packages: optional' || + github.event.label.name == 'c: packages: standard'))) + uses: ./.github/workflows/docker.yml + with: + # Build incrementally from published Docker image + incremental: true + free_disk_space: true + from_docker_repository: ghcr.io/sagemath/sage/ + from_docker_target: "with-targets" + from_docker_tag: "dev" + docker_targets: "with-targets" + targets: "${{needs.changed_files.outputs.uninstall_targets}} ${{needs.changed_files.outputs.build_targets}} build doc-html ptest" + tox_system_factors: >- + ["ubuntu-focal", + "ubuntu-jammy", + "ubuntu-mantic", + "debian-bullseye", + "debian-bookworm", + "fedora-30", + "fedora-38", + "gentoo-python3.11", + "debian-bullseye-i386"] + tox_packages_factors: >- + ["standard", + "minimal"] + docker_push_repository: ghcr.io/${{ github.repository }}/ diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index 5f049741eab..6f598521a37 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -63,6 +63,56 @@ jobs: ["standard"] docker_push_repository: ghcr.io/${{ github.repository }}/ + standard-sitepackages: + if: ${{ success() || failure() }} + needs: [standard-pre] + uses: ./.github/workflows/docker.yml + with: + # Build incrementally from previous stage (pre) + incremental: true + free_disk_space: true + from_docker_repository: ghcr.io/${{ github.repository }}/ + from_docker_target: "with-targets-pre" + docker_targets: "with-targets with-targets-optional" + # FIXME: duplicated from env.TARGETS + targets: build doc-html + targets_optional: ptest + tox_packages_factors: >- + ["standard-sitepackages"] + # Only test systems with a usable system python (>= 3.9) + tox_system_factors: >- + ["ubuntu-jammy", + "ubuntu-kinetic", + "ubuntu-lunar", + "ubuntu-mantic", + "debian-bullseye", + "debian-bookworm", + "debian-trixie", + "debian-sid", + "linuxmint-21", + "linuxmint-21.1", + "linuxmint-21.2", + "fedora-33", + "fedora-34", + "fedora-35", + "fedora-36", + "fedora-37", + "fedora-38", + "fedora-39", + "centos-stream-8-python3.9", + "centos-stream-9-python3.9", + "almalinux-8-python3.9", + "gentoo-python3.10", + "gentoo-python3.11", + "archlinux-latest", + "opensuse-15.4-gcc_11-python3.10", + "opensuse-15.5-gcc_11-python3.11", + "opensuse-tumbleweed-python3.10", + "opensuse-tumbleweed", + "debian-bullseye-i386"] + docker_push_repository: ghcr.io/${{ github.repository }}/ + max_parallel: 10 + minimal-pre: if: ${{ success() || failure() }} # It does not really "need" it. diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index c07c6968095..3f49b4f8d96 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -47,7 +47,7 @@ jobs: LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-tox-local-${{ matrix.tox_env }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_env }}--${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Select Xcode version run: | if [ ${{ matrix.xcode_version_factor }} != default ]; then sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version_factor }}.app; fi @@ -118,7 +118,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 500 - name: fetch tags @@ -160,7 +160,7 @@ jobs: TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }}-xcode_${{ matrix.xcode_version_factor }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: "!contains(matrix.tox_system_factor, 'nobootstrap')" - uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/ci-wsl.yml b/.github/workflows/ci-wsl.yml index e6d4d30cfc3..ae83e1d6a0f 100644 --- a/.github/workflows/ci-wsl.yml +++ b/.github/workflows/ci-wsl.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Configure git run: git config --global core.symlinks true - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Ubuntu 20.04 (in WSL) run: | (New-Object System.Net.WebClient).DownloadFile("https://aka.ms/wslubuntu2004", "Ubuntu.appx") diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index 0d57bd8440f..26c193dfb2b 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -73,14 +73,14 @@ jobs: choco install git python39 python39-pip --source cygwin - name: Check out SageMath - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ inputs.sage_repo }} ref: ${{ inputs.sage_ref }} fetch-depth: 2000 - name: Check out git-trac-command - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: sagemath/git-trac-command path: git-trac-command diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 96aae8fbc1a..3aaecc6a064 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install bootstrap prerequisites run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update @@ -51,7 +51,7 @@ jobs: env: CAN_DEPLOY: ${{ secrets.SAGEMATH_PYPI_API_TOKEN != '' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install bootstrap prerequisites run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update @@ -100,13 +100,13 @@ jobs: # CIBW_ARCHS: ${{ matrix.arch }} # https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python - CIBW_PROJECT_REQUIRES_PYTHON: ">=3.8" + CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9" # Environment during wheel build CIBW_ENVIRONMENT: "PATH=$(pwd)/local/bin:$PATH CPATH=$(pwd)/local/include:$CPATH LIBRARY_PATH=$(pwd)/local/lib:$LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/local/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal" # Use 'build', not 'pip wheel' CIBW_BUILD_FRONTEND: build steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 1fed6b453ce..6728b140c8b 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -19,7 +19,7 @@ jobs: container: ghcr.io/sagemath/sage/sage-docker-fedora-31-maximal-with-targets:dev steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Prepare run: | diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 3635980d15f..3c7cd9a7091 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -17,7 +17,7 @@ jobs: container: ghcr.io/sagemath/sage/sage-ubuntu-focal-standard-with-targets:dev steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Update system packages run: | @@ -82,6 +82,7 @@ jobs: # incremental docbuild may introduce broken links (inter-file references) though build succeeds run: | set -ex + export SAGE_USE_CDNS=yes mv /sage/local/share/doc/sage/html/en/.git /sage/.git-doc make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage mkdir -p /sage/local/share/doc/sage/html/en/ && mv /sage/.git-doc /sage/local/share/doc/sage/html/en/.git diff --git a/.github/workflows/doc-publish.yml b/.github/workflows/doc-publish.yml index e86727e73ef..14337131420 100644 --- a/.github/workflows/doc-publish.yml +++ b/.github/workflows/doc-publish.yml @@ -75,7 +75,7 @@ jobs: [Documentation preview for this PR](${{ steps.deploy-netlify.outputs.NETLIFY_URL }}) (built with commit ${{ steps.source-run-info.outputs.sourceHeadSha }}; [changes](${{ steps.deploy-netlify.outputs.NETLIFY_URL }}/CHANGES.html)) is ready! :tada: - name: Update deployment status PR check - uses: myrotvorets/set-commit-status-action@v1.1.7 + uses: myrotvorets/set-commit-status-action@v2.0.0 if: ${{ always() }} env: DEPLOY_SUCCESS: Successfully deployed preview. diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3c53c936237..1e773a1f8b9 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -18,26 +18,24 @@ on: default: >- ["ubuntu-trusty-toolchain-gcc_9", "ubuntu-xenial-toolchain-gcc_9", - "ubuntu-bionic-gcc_8-python3.8", + "ubuntu-bionic-gcc_8", "ubuntu-focal", "ubuntu-jammy", "ubuntu-kinetic", "ubuntu-lunar", "ubuntu-mantic", - "debian-buster", + "debian-buster-gcc_spkg", "debian-bullseye", "debian-bookworm", + "debian-trixie", "debian-sid", - "linuxmint-19-gcc_8-python3.8", - "linuxmint-19.3-gcc_8-python3.8", "linuxmint-20.1", "linuxmint-20.2", "linuxmint-20.3", "linuxmint-21", "linuxmint-21.1", "linuxmint-21.2", - "fedora-29-python3.8", - "fedora-30-python3.8", + "fedora-30", "fedora-31", "fedora-32", "fedora-33", @@ -59,9 +57,9 @@ on: "opensuse-15.4-gcc_11-python3.10", "opensuse-15.5-gcc_11-python3.11", "opensuse-tumbleweed-python3.10", + "opensuse-tumbleweed", "conda-forge", "ubuntu-bionic-gcc_8-i386", - "debian-buster-i386", "debian-bullseye-i386", ] tox_packages_factors: @@ -148,7 +146,7 @@ jobs: EXTRA_SAGE_PACKAGES: ${{ inputs.extra_sage_packages }} steps: - name: Check out SageMath - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ inputs.sage_repo }} ref: ${{ inputs.sage_ref }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 883749e2bf7..c63f371b268 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,11 +13,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install pycodestyle run: pip install tox pycodestyle - name: Lint using pycodestyle @@ -27,11 +27,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install relint run: pip install tox relint - name: Lint using relint @@ -41,11 +41,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install tox run: pip install tox - name: Lint using tox -e rst diff --git a/.github/workflows/push_to_docker_hub.yml b/.github/workflows/push_to_docker_hub.yml new file mode 100644 index 00000000000..eb36f3c979a --- /dev/null +++ b/.github/workflows/push_to_docker_hub.yml @@ -0,0 +1,126 @@ +name: Build Docker images and push to DockerHub + +on: + workflow_dispatch: + # Allow to run manually + branches: + - 'develop' + - 'docker_hub_gha' + push: + tags: + # Just create image on pushing a tag + - '*' + +jobs: + sagemath-dev: + name: Build Docker image on target make-build and push to DockerHub sagemath-dev + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set tag + # docker/metadata-action@v4 is not used since we need to distinguish + # between latest and develop tags + id: set_tag + run: | + git fetch --depth=1 origin +refs/tags/*:refs/tags/* + TAG_NAME=$(git tag --sort=v:refname | tail -1) + TAG="sagemath/sagemath-dev:$TAG_NAME" + TAG_LIST="$TAG, sagemath/sagemath-dev:develop" + TAG_LIST="$TAG" # don't tag develop until meaning of sagemath-dev is clear + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV + echo "TAG=$TAG" >> $GITHUB_ENV + echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV + + - name: Update Tag List + id: upd_tag_list + run: | + TAG_LIST="${{ env.TAG_LIST }}, sagemath/sagemath-dev:latest" + TAG_LIST="${{ env.TAG_LIST }}" # don't tag latest until meaning of sagemath-dev is clear + echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV + if: "!contains(env.TAG_NAME, 'beta') && !contains(env.TAG_NAME, 'rc')" + + - name: Check env + run: | + echo ${{ env.TAG_NAME }} + echo ${{ env.TAG }} + echo ${{ env.TAG_LIST }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push make-build + uses: docker/build-push-action@v4 + with: + context: . + file: docker/Dockerfile + target: make-build # see the corresponding header-note + push: true + tags: ${{ env.TAG_LIST }} + cache-from: type=gha + cache-to: type=gha,mode=max + + sagemath: + needs: sagemath-dev + name: Build Docker image on target sagemath and push to DockerHub sagemath + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set tag + # docker/metadata-action@v4 is not used since we need to distinguish + # between latest and develop tags + id: set_tag + run: | + git fetch --depth=1 origin +refs/tags/*:refs/tags/* + TAG_NAME=$(git tag --sort=v:refname | tail -1) + TAG="sagemath/sagemath:$TAG_NAME" + TAG_LIST="$TAG, sagemath/sagemath:develop" + BASE="sagemath/sagemath-dev:$TAG_NAME" + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV + echo "TAG=$TAG" >> $GITHUB_ENV + echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV + echo "BASE=$BASE" >> $GITHUB_ENV + + - name: Update Tag List + id: upd_tag_list + run: | + TAG_LIST="${{ env.TAG_LIST }}, sagemath/sagemath:latest" + echo "TAG_LIST=$TAG_LIST" >> $GITHUB_ENV + if: "!contains(env.TAG_NAME, 'beta') && !contains(env.TAG_NAME, 'rc')" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push sagemath + uses: docker/build-push-action@v4 + with: + context: . + file: docker/Dockerfile + build-args: | + MAKE_BUILD=${{ env.BASE }} + target: sagemath + push: true + tags: ${{ env.TAG_LIST }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.vscode/settings.json b/.vscode/settings.json index 77dcb2ce188..b3079a7c4ee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,7 +27,7 @@ "python.linting.enabled": true, // The following pycodestyle arguments are the same as the pycodestyle-minimal // tox environnment, see the file SAGE_ROOT/src/tox.ini - "python.linting.pycodestyleArgs": ["--select= E111,E21,E222,E227,E25,E271,E303,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605"], + "python.linting.pycodestyleArgs": ["--select= E111,E21,E222,E227,E25,E271,E303,E305,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605"], "cSpell.words": [ "furo", "Conda", diff --git a/.zenodo.json b/.zenodo.json deleted file mode 100644 index 0072019287e..00000000000 --- a/.zenodo.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "description": "Mirror of the Sage https://sagemath.org/ source tree", - "license": "other-open", - "title": "sagemath/sage: 10.1.beta2", - "version": "10.1.beta2", - "upload_type": "software", - "publication_date": "2023-06-03", - "creators": [ - { - "affiliation": "SageMath.org", - "name": "The SageMath Developers" - } - ], - "access_right": "open", - "related_identifiers": [ - { - "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/10.1.beta2", - "relation": "isSupplementTo" - }, - { - "scheme": "doi", - "identifier": "10.5281/zenodo.593563", - "relation": "isNewVersionOf" - } - ] -} diff --git a/CITATION.cff b/CITATION.cff index 5246de2c922..2ddeb664c30 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.1 +version: 10.2.beta3 doi: 10.5281/zenodo.593563 -date-released: 2023-08-20 +date-released: 2023-09-16 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/README.md b/README.md index 2e5419541af..aee0c3a0fbc 100644 --- a/README.md +++ b/README.md @@ -189,8 +189,8 @@ in the Installation Guide. 3. [Linux, WSL] Install the required minimal build prerequisites. - - Compilers: `gcc`, `gfortran`, `g++` (GCC 8.x to 12.x and recent - versions of Clang (LLVM) are supported). + - Compilers: `gcc`, `gfortran`, `g++` (GCC versions from 8.4.0 to 13.x + and recent versions of Clang (LLVM) are supported). See [build/pkgs/gcc/SPKG.rst](build/pkgs/gcc/SPKG.rst) and [build/pkgs/gfortran/SPKG.rst](build/pkgs/gfortran/SPKG.rst) for a discussion of suitable compilers. @@ -201,7 +201,7 @@ in the Installation Guide. more details. - Python 3.4 or later, or Python 2.7, a full installation including - `urllib`; but ideally version 3.8.x, 3.9.x, or 3.10.x, which + `urllib`; but ideally version 3.9.x, 3.10.x, or 3.11.x, which will avoid having to build Sage's own copy of Python 3. See [build/pkgs/python3/SPKG.rst](build/pkgs/python3/SPKG.rst) for more details. diff --git a/VERSION.txt b/VERSION.txt index 7175554482f..02a1ddafba2 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.1, Release Date: 2023-08-20 +SageMath version 10.2.beta3, Release Date: 2023-09-16 diff --git a/bootstrap b/bootstrap index 5156f369c38..aa5755cfc63 100755 --- a/bootstrap +++ b/bootstrap @@ -98,8 +98,8 @@ SAGE_SPKG_CONFIGURE_$(echo ${pkgname} | tr '[a-z]' '[A-Z]')" if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt"; then # A Python package SPKG_TREE_VAR=SAGE_VENV - echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(sage-get-system-packages install-requires ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions.m4 - echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(sage-get-system-packages install-requires-toml ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions_toml.m4 + echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(ENABLE_SYSTEM_SITE_PACKAGES=yes sage-get-system-packages install-requires ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions.m4 + echo "define(>>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(ENABLE_SYSTEM_SITE_PACKAGES=yes sage-get-system-packages install-requires-toml ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions_toml.m4 fi fi spkg_configures="$spkg_configures diff --git a/build/bin/sage-build-env-config.in b/build/bin/sage-build-env-config.in index b00fd2a3f99..7d6cd113bf9 100644 --- a/build/bin/sage-build-env-config.in +++ b/build/bin/sage-build-env-config.in @@ -53,9 +53,13 @@ export SAGE_PARI_CFG="@SAGE_PARI_CFG@" export SAGE_GLPK_PREFIX="@SAGE_GLPK_PREFIX@" export SAGE_FREETYPE_PREFIX="@SAGE_FREETYPE_PREFIX@" +export SAGE_PIP_INSTALL_FLAGS="@SAGE_PIP_INSTALL_FLAGS@" export SAGE_SUITESPARSE_PREFIX="@SAGE_SUITESPARSE_PREFIX@" export SAGE_CONFIGURE_FFLAS_FFPACK="@SAGE_CONFIGURE_FFLAS_FFPACK@" export CONFIGURED_SAGE_EDITABLE="@SAGE_EDITABLE@" export CONFIGURED_SAGE_WHEELS="@SAGE_WHEELS@" + +export ENABLE_SYSTEM_SITE_PACKAGES="@ENABLE_SYSTEM_SITE_PACKAGES@" +export PYTHON_MINOR="@PYTHON_MINOR@" diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers index 4eac9626ffa..67a2201d31f 100644 --- a/build/bin/sage-dist-helpers +++ b/build/bin/sage-dist-helpers @@ -325,7 +325,11 @@ sdh_store_wheel() { } sdh_store_and_pip_install_wheel() { - local pip_options="" + # The $SAGE_PIP_INSTALL_FLAGS variable is set by sage-build-env-config. + # We skip sanity checking its contents since you should either let sage + # decide what it contains, or really know what you are doing. + local pip_options="${SAGE_PIP_INSTALL_FLAGS}" + while [ $# -gt 0 ]; do case $1 in -*) pip_options="$pip_options $1" diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages index c51c36ceab9..c8b9314c3fe 100755 --- a/build/bin/sage-get-system-packages +++ b/build/bin/sage-get-system-packages @@ -1,4 +1,5 @@ #!/bin/sh + SYSTEM=$1 if [ -z "$SYSTEM" ]; then echo >&2 "usage: $0 {auto|debian|arch|conda|pip|...} SPKGS..." @@ -10,6 +11,7 @@ SPKGS="$*" if [ -z "$SAGE_ROOT" ]; then SAGE_ROOT=`pwd` fi + case "$SYSTEM" in install-requires) # Collect install-requires.txt (falling back to requirements.txt) and output it in the format @@ -44,6 +46,18 @@ case "$SYSTEM" in ;; esac for PKG_BASE in $SPKGS; do + + # Skip this package if it uses the SAGE_PYTHON_PACKAGE_CHECK + # macro and if --enable-system-site-packages was NOT passed + # to ./configure (or if ./configure has not yet been run). + SPKG_CONFIGURE="${SAGE_ROOT}/build/pkgs/${PKG_BASE}/spkg-configure.m4" + if [ -z "${ENABLE_SYSTEM_SITE_PACKAGES}" ]; then + if grep -q SAGE_PYTHON_PACKAGE_CHECK "${SPKG_CONFIGURE}" 2>/dev/null; + then + continue; + fi + fi + for NAME in $SYSTEM_PACKAGES_FILE_NAMES; do SYSTEM_PACKAGES_FILE="$SAGE_ROOT"/build/pkgs/$PKG_BASE/$NAME if [ -f $SYSTEM_PACKAGES_FILE ]; then diff --git a/build/bin/sage-spkg-info b/build/bin/sage-spkg-info index d02b3ac347f..e43e516dc5b 100755 --- a/build/bin/sage-spkg-info +++ b/build/bin/sage-spkg-info @@ -110,17 +110,19 @@ if [ -z "$system" ]; then echo "(none known)" else echo - if [ -f "$PKG_SCRIPTS"/spkg-configure.m4 ]; then - echo "If the system package is installed, ./configure will check whether it can be used." - else - echo "However, these system packages will not be used for building Sage" - if [ -f "$PKG_SCRIPTS"/install-requires.txt ]; then - echo "because using Python site-packages is not supported by the Sage distribution;" - echo "see https://github.com/sagemath/sage/issues/29023" + SPKG_CONFIGURE="${PKG_SCRIPTS}/spkg-configure.m4" + if [ -f "${SPKG_CONFIGURE}" ]; then + if grep -q SAGE_PYTHON_PACKAGE_CHECK "${SPKG_CONFIGURE}"; then + echo "If the system package is installed and if the (experimental) option" + echo "--enable-system-site-packages is passed to ./configure, then ./configure" + echo "will check if the system package can be used." else - echo "because spkg-configure.m4 has not been written for this package;" - echo "see https://github.com/sagemath/sage/issues/27330" + echo "If the system package is installed, ./configure will check if it can be used." fi + else + echo "However, these system packages will not be used for building Sage" + echo "because spkg-configure.m4 has not been written for this package;" + echo "see https://github.com/sagemath/sage/issues/27330" fi fi echo diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 14cbaf786eb..6980f6b6e4b 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -5,7 +5,7 @@ set -e SYSTEM="${1:-debian}" shopt -s extglob -SAGE_PACKAGE_LIST_ARGS="${2:- --has-file=spkg-configure.m4 :standard:}" +SAGE_PACKAGE_LIST_ARGS="${2:-:standard:}" WITH_SYSTEM_SPKG="${3:-yes}" IGNORE_MISSING_SYSTEM_PACKAGES="${4:-no}" EXTRA_SAGE_PACKAGES="${5:-_bootstrap}" @@ -15,17 +15,13 @@ SAGE_ROOT=. export PATH="$SAGE_ROOT"/build/bin:$PATH SYSTEM_PACKAGES=$EXTRA_SYSTEM_PACKAGES CONFIGURE_ARGS="--enable-option-checking " -for PKG_BASE in $(sage-package list --has-file=distros/$SYSTEM.txt $SAGE_PACKAGE_LIST_ARGS) $EXTRA_SAGE_PACKAGES; do - PKG_SCRIPTS="$SAGE_ROOT"/build/pkgs/$PKG_BASE - if [ -d $PKG_SCRIPTS ]; then - SYSTEM_PACKAGES_FILE=$PKG_SCRIPTS/distros/$SYSTEM.txt - PKG_SYSTEM_PACKAGES=$(echo $(${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE)) - if [ -n "PKG_SYSTEM_PACKAGES" ]; then - SYSTEM_PACKAGES+=" $PKG_SYSTEM_PACKAGES" - if [ -f $PKG_SCRIPTS/spkg-configure.m4 ]; then - CONFIGURE_ARGS+="--with-system-$PKG_BASE=${WITH_SYSTEM_SPKG} " - fi - fi +for SPKG in $(sage-package list --has-file=spkg-configure.m4 $SAGE_PACKAGE_LIST_ARGS) $EXTRA_SAGE_PACKAGES; do + SYSTEM_PACKAGE=$(sage-get-system-packages $SYSTEM $SPKG | sed 's/${PYTHON_MINOR}/'${PYTHON_MINOR}'/g') + if [ -n "${SYSTEM_PACKAGE}" ]; then + # SYSTEM_PACKAGE can be empty if, for example, the environment + # variable ENABLE_SYSTEM_SITE_PACKAGES is empty. + SYSTEM_PACKAGES+=" ${SYSTEM_PACKAGE}" + CONFIGURE_ARGS+="--with-system-${SPKG}=${WITH_SYSTEM_SPKG} " fi done echo "# Automatically generated by SAGE_ROOT/build/bin/write-dockerfile.sh" diff --git a/build/make/Makefile.in b/build/make/Makefile.in index b6858173362..cc004d08c3c 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -227,11 +227,13 @@ SAGE_I_TARGETS = sagelib doc python3_venv _clean-broken-gcc PYTHON_FOR_VENV = @PYTHON_FOR_VENV@ +PYTHON_MINOR = @PYTHON_MINOR@ +SAGE_VENV_FLAGS = @SAGE_VENV_FLAGS@ ifneq ($(PYTHON_FOR_VENV),) # Special rule for making the Python virtualenv from the system Python (Python # 3 only). $(PYTHON) is set in Makefile to python3_venv. -# Thus $(inst_python3_venv) will be the dependency of every Python package. +# Thus $(inst_python3_venv) will an (order-only) dependency of every Python package. # # TODO: If we reconfigure to build our own Python after having used the system # Python, files installed to create the virtualenv should be *removed*. That @@ -239,10 +241,15 @@ ifneq ($(PYTHON_FOR_VENV),) ifeq ($(PYTHON),python3) PYTHON = python3_venv endif -inst_python3_venv = $(SAGE_VENV)/pyvenv.cfg +inst_python3_venv = $(SAGE_VENV)/$(SPKG_INST_RELDIR)/python3_venv-3.$(PYTHON_MINOR)-$(subst /,-,$(PYTHON_FOR_VENV))$(findstring --system-site-packages,$(SAGE_VENV_FLAGS)) -$(inst_python3_venv): - $(PYTHON_FOR_VENV) $(SAGE_ROOT)/build/bin/sage-venv "$(SAGE_VENV)" +$(SAGE_VENV)/$(SPKG_INST_RELDIR): + mkdir -p "$@" + +$(inst_python3_venv): | $(SAGE_VENV)/$(SPKG_INST_RELDIR) + $(PYTHON_FOR_VENV) $(SAGE_ROOT)/build/bin/sage-venv $(SAGE_VENV_FLAGS) "$(SAGE_VENV)" + rm -f "$(SAGE_VENV)/$(SPKG_INST_RELDIR)"/python3_venv-* + touch "$@" endif # Build everything and start Sage. @@ -591,6 +598,8 @@ $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2): $(3) $(1): $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2) +$(1)-ensure: $(inst_$(1)) + $(1)-$(4)-no-deps: +@if [ -z '$$($(4))' ]; then \ echo "Error: The installation tree $(4) has been disabled" 2>&1; \ @@ -649,6 +658,8 @@ $(1)-build-deps: $(2) $(1): $(2) +$(MAKE_REC) $(1)-no-deps +$(1)-ensure: $(inst_$(1)) + $(1)-no-deps: $(AM_V_at)sage-logger -p 'sage --pip install -r "$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt"' '$$(SAGE_LOGS)/$(1).log' @@ -705,6 +716,8 @@ $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2): $(3) $(1): $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2) +$(1)-ensure: $(inst_$(1)) + $(1)-$(4)-no-deps: $(PLUS)@if [ -z '$$($(4))' ]; then \ echo "Error: The installation tree $(4) has been disabled" 2>&1; \ diff --git a/build/pkgs/_python3.8/distros/arch.txt b/build/pkgs/_python3.8/distros/arch.txt deleted file mode 100644 index 398ae3228b3..00000000000 --- a/build/pkgs/_python3.8/distros/arch.txt +++ /dev/null @@ -1 +0,0 @@ -python38 diff --git a/build/pkgs/_python3.8/distros/cygwin.txt b/build/pkgs/_python3.8/distros/cygwin.txt deleted file mode 100644 index 398ae3228b3..00000000000 --- a/build/pkgs/_python3.8/distros/cygwin.txt +++ /dev/null @@ -1 +0,0 @@ -python38 diff --git a/build/pkgs/_python3.8/distros/debian.txt b/build/pkgs/_python3.8/distros/debian.txt deleted file mode 100644 index bf46e908ff6..00000000000 --- a/build/pkgs/_python3.8/distros/debian.txt +++ /dev/null @@ -1,4 +0,0 @@ -python3.8 -python3.8-dev -python3.8-distutils -python3.8-venv diff --git a/build/pkgs/_python3.8/distros/fedora.txt b/build/pkgs/_python3.8/distros/fedora.txt deleted file mode 100644 index 1f9ac08ba8e..00000000000 --- a/build/pkgs/_python3.8/distros/fedora.txt +++ /dev/null @@ -1,2 +0,0 @@ -python38 -python38-devel diff --git a/build/pkgs/_python3.8/distros/freebsd.txt b/build/pkgs/_python3.8/distros/freebsd.txt deleted file mode 100644 index 398ae3228b3..00000000000 --- a/build/pkgs/_python3.8/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -python38 diff --git a/build/pkgs/_python3.8/distros/homebrew.txt b/build/pkgs/_python3.8/distros/homebrew.txt deleted file mode 100644 index ea9989e790c..00000000000 --- a/build/pkgs/_python3.8/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -python@3.8 diff --git a/build/pkgs/_python3.8/distros/macports.txt b/build/pkgs/_python3.8/distros/macports.txt deleted file mode 100644 index 398ae3228b3..00000000000 --- a/build/pkgs/_python3.8/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -python38 diff --git a/build/pkgs/_python3.8/distros/opensuse.txt b/build/pkgs/_python3.8/distros/opensuse.txt deleted file mode 100644 index 1f9ac08ba8e..00000000000 --- a/build/pkgs/_python3.8/distros/opensuse.txt +++ /dev/null @@ -1,2 +0,0 @@ -python38 -python38-devel diff --git a/build/pkgs/admcycles/dependencies b/build/pkgs/admcycles/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/admcycles/dependencies +++ b/build/pkgs/admcycles/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/alabaster/dependencies b/build/pkgs/alabaster/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/alabaster/dependencies +++ b/build/pkgs/alabaster/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/alabaster/distros/gentoo.txt b/build/pkgs/alabaster/distros/gentoo.txt new file mode 100644 index 00000000000..cffece61b27 --- /dev/null +++ b/build/pkgs/alabaster/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/alabaster diff --git a/build/pkgs/alabaster/distros/opensuse.txt b/build/pkgs/alabaster/distros/opensuse.txt index dcc39f9e849..debe990ce19 100644 --- a/build/pkgs/alabaster/distros/opensuse.txt +++ b/build/pkgs/alabaster/distros/opensuse.txt @@ -1 +1 @@ -python3-alabaster +python3${PYTHON_MINOR}-alabaster diff --git a/build/pkgs/alabaster/spkg-configure.m4 b/build/pkgs/alabaster/spkg-configure.m4 new file mode 100644 index 00000000000..4eca6e05a5f --- /dev/null +++ b/build/pkgs/alabaster/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([alabaster], [SAGE_PYTHON_PACKAGE_CHECK([alabaster])]) diff --git a/build/pkgs/appdirs/dependencies b/build/pkgs/appdirs/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/appdirs/dependencies +++ b/build/pkgs/appdirs/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/appnope/dependencies b/build/pkgs/appnope/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/appnope/dependencies +++ b/build/pkgs/appnope/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/argon2_cffi/dependencies b/build/pkgs/argon2_cffi/dependencies index d1b259926f8..920046ab33d 100644 --- a/build/pkgs/argon2_cffi/dependencies +++ b/build/pkgs/argon2_cffi/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) argon2_cffi_bindings | $(PYTHON_TOOLCHAIN) flit_core + argon2_cffi_bindings | $(PYTHON_TOOLCHAIN) flit_core $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/argon2_cffi/distros/gentoo.txt b/build/pkgs/argon2_cffi/distros/gentoo.txt new file mode 100644 index 00000000000..2f12ca869e4 --- /dev/null +++ b/build/pkgs/argon2_cffi/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/argon2-cffi diff --git a/build/pkgs/argon2_cffi/spkg-configure.m4 b/build/pkgs/argon2_cffi/spkg-configure.m4 new file mode 100644 index 00000000000..03ebc634492 --- /dev/null +++ b/build/pkgs/argon2_cffi/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([argon2_cffi], [SAGE_PYTHON_PACKAGE_CHECK([argon2_cffi])]) diff --git a/build/pkgs/argon2_cffi_bindings/dependencies b/build/pkgs/argon2_cffi_bindings/dependencies index 0d815c35f4b..4b9d24ccf44 100644 --- a/build/pkgs/argon2_cffi_bindings/dependencies +++ b/build/pkgs/argon2_cffi_bindings/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) cffi setuptools_scm + | $(PYTHON_TOOLCHAIN) cffi setuptools_scm $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/asttokens/dependencies b/build/pkgs/asttokens/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/asttokens/dependencies +++ b/build/pkgs/asttokens/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/asttokens/distros/gentoo.txt b/build/pkgs/asttokens/distros/gentoo.txt new file mode 100644 index 00000000000..4aae3fb6cb4 --- /dev/null +++ b/build/pkgs/asttokens/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/asttokens diff --git a/build/pkgs/asttokens/spkg-configure.m4 b/build/pkgs/asttokens/spkg-configure.m4 new file mode 100644 index 00000000000..2221fabfb2b --- /dev/null +++ b/build/pkgs/asttokens/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([asttokens], [SAGE_PYTHON_PACKAGE_CHECK([asttokens])]) diff --git a/build/pkgs/attrs/dependencies b/build/pkgs/attrs/dependencies index 4361e46ddaf..9be6b4aab7c 100644 --- a/build/pkgs/attrs/dependencies +++ b/build/pkgs/attrs/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) vcversioner | $(PYTHON_TOOLCHAIN) + vcversioner | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/attrs/distros/gentoo.txt b/build/pkgs/attrs/distros/gentoo.txt new file mode 100644 index 00000000000..3b906facd3a --- /dev/null +++ b/build/pkgs/attrs/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/attrs diff --git a/build/pkgs/attrs/spkg-configure.m4 b/build/pkgs/attrs/spkg-configure.m4 new file mode 100644 index 00000000000..ba6a9b71efa --- /dev/null +++ b/build/pkgs/attrs/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([attrs], [SAGE_PYTHON_PACKAGE_CHECK([attrs])]) diff --git a/build/pkgs/auditwheel_or_delocate/dependencies b/build/pkgs/auditwheel_or_delocate/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/auditwheel_or_delocate/dependencies +++ b/build/pkgs/auditwheel_or_delocate/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/awali/dependencies b/build/pkgs/awali/dependencies index b125e2ded92..09b60167a34 100644 --- a/build/pkgs/awali/dependencies +++ b/build/pkgs/awali/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cmake cython nbconvert ncurses + cmake cython nbconvert ncurses | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/babel/dependencies b/build/pkgs/babel/dependencies index 41462907c20..802e470da86 100644 --- a/build/pkgs/babel/dependencies +++ b/build/pkgs/babel/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) pytz + | $(PYTHON_TOOLCHAIN) pytz $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/babel/distros/arch.txt b/build/pkgs/babel/distros/arch.txt new file mode 100644 index 00000000000..f2d828ccc5c --- /dev/null +++ b/build/pkgs/babel/distros/arch.txt @@ -0,0 +1 @@ +python-babel diff --git a/build/pkgs/babel/distros/debian.txt b/build/pkgs/babel/distros/debian.txt new file mode 100644 index 00000000000..e623eb68a31 --- /dev/null +++ b/build/pkgs/babel/distros/debian.txt @@ -0,0 +1 @@ +python3-babel diff --git a/build/pkgs/babel/distros/fedora.txt b/build/pkgs/babel/distros/fedora.txt new file mode 100644 index 00000000000..98f65931c4c --- /dev/null +++ b/build/pkgs/babel/distros/fedora.txt @@ -0,0 +1 @@ +babel diff --git a/build/pkgs/babel/distros/gentoo.txt b/build/pkgs/babel/distros/gentoo.txt new file mode 100644 index 00000000000..2d2c34fb697 --- /dev/null +++ b/build/pkgs/babel/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/Babel diff --git a/build/pkgs/babel/distros/opensuse.txt b/build/pkgs/babel/distros/opensuse.txt index 70bb05b1327..6372e2e77da 100644 --- a/build/pkgs/babel/distros/opensuse.txt +++ b/build/pkgs/babel/distros/opensuse.txt @@ -1 +1 @@ -python3-Babel +python3${PYTHON_MINOR}-Babel diff --git a/build/pkgs/babel/install-requires.txt b/build/pkgs/babel/install-requires.txt index 1d0d6191bb9..b4db5e907f3 100644 --- a/build/pkgs/babel/install-requires.txt +++ b/build/pkgs/babel/install-requires.txt @@ -1 +1 @@ -babel >=2.6.0 +babel >=2.11.0 diff --git a/build/pkgs/babel/spkg-configure.m4 b/build/pkgs/babel/spkg-configure.m4 new file mode 100644 index 00000000000..d7b9a71c811 --- /dev/null +++ b/build/pkgs/babel/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([babel], [SAGE_PYTHON_PACKAGE_CHECK([babel])]) diff --git a/build/pkgs/backcall/dependencies b/build/pkgs/backcall/dependencies index 902a5feed13..4fedbe70cd1 100644 --- a/build/pkgs/backcall/dependencies +++ b/build/pkgs/backcall/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flit_core tomli + | $(PYTHON_TOOLCHAIN) flit_core tomli $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/backcall/distros/gentoo.txt b/build/pkgs/backcall/distros/gentoo.txt new file mode 100644 index 00000000000..266a222c558 --- /dev/null +++ b/build/pkgs/backcall/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/backcall diff --git a/build/pkgs/backcall/spkg-configure.m4 b/build/pkgs/backcall/spkg-configure.m4 new file mode 100644 index 00000000000..d6b11c49884 --- /dev/null +++ b/build/pkgs/backcall/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([backcall], [SAGE_PYTHON_PACKAGE_CHECK([backcall])]) diff --git a/build/pkgs/backports_zoneinfo/SPKG.rst b/build/pkgs/backports_zoneinfo/SPKG.rst deleted file mode 100644 index deaed349122..00000000000 --- a/build/pkgs/backports_zoneinfo/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -backports_zoneinfo: Backport of the standard library zoneinfo module -==================================================================== - -Description ------------ - -Backport of the standard library zoneinfo module for Python 3.8 - -License -------- - -Apache-2.0 - -Upstream Contact ----------------- - -https://pypi.org/project/backports.zoneinfo/ - diff --git a/build/pkgs/backports_zoneinfo/checksums.ini b/build/pkgs/backports_zoneinfo/checksums.ini deleted file mode 100644 index 1af2250d48c..00000000000 --- a/build/pkgs/backports_zoneinfo/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=backports.zoneinfo-VERSION.tar.gz -sha1=8015a85e499ceda8b526f907a2a60083f7004aa4 -md5=d51faaaed4a1d5158dcfcef90355e805 -cksum=2001250429 -upstream_url=https://pypi.io/packages/source/b/backports.zoneinfo/backports.zoneinfo-VERSION.tar.gz diff --git a/build/pkgs/backports_zoneinfo/distros/conda.txt b/build/pkgs/backports_zoneinfo/distros/conda.txt deleted file mode 100644 index 5a8be642f33..00000000000 --- a/build/pkgs/backports_zoneinfo/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -backports.zoneinfo diff --git a/build/pkgs/backports_zoneinfo/install-requires.txt b/build/pkgs/backports_zoneinfo/install-requires.txt deleted file mode 100644 index 5a8be642f33..00000000000 --- a/build/pkgs/backports_zoneinfo/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -backports.zoneinfo diff --git a/build/pkgs/backports_zoneinfo/package-version.txt b/build/pkgs/backports_zoneinfo/package-version.txt deleted file mode 100644 index 0c62199f16a..00000000000 --- a/build/pkgs/backports_zoneinfo/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.2.1 diff --git a/build/pkgs/backports_zoneinfo/spkg-install.in b/build/pkgs/backports_zoneinfo/spkg-install.in deleted file mode 100644 index 83aff6031e8..00000000000 --- a/build/pkgs/backports_zoneinfo/spkg-install.in +++ /dev/null @@ -1,6 +0,0 @@ -cd src -if python3 -c 'import sys; sys.exit(0 if sys.hexversion < 0x03090000 else 1)'; then - sdh_pip_install . -else - echo >&2 "Skipping install, not needed for Python >= 3.9" -fi diff --git a/build/pkgs/beautifulsoup4/dependencies b/build/pkgs/beautifulsoup4/dependencies index 01af7f65566..c9982dd1882 100644 --- a/build/pkgs/beautifulsoup4/dependencies +++ b/build/pkgs/beautifulsoup4/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) soupsieve | $(PYTHON_TOOLCHAIN) + soupsieve | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/beniget/dependencies b/build/pkgs/beniget/dependencies index d792a85db72..96da9efd5ac 100644 --- a/build/pkgs/beniget/dependencies +++ b/build/pkgs/beniget/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) gast | $(PYTHON_TOOLCHAIN) + gast | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/beniget/distros/gentoo.txt b/build/pkgs/beniget/distros/gentoo.txt new file mode 100644 index 00000000000..1a5972cd23f --- /dev/null +++ b/build/pkgs/beniget/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/beniget diff --git a/build/pkgs/beniget/spkg-configure.m4 b/build/pkgs/beniget/spkg-configure.m4 new file mode 100644 index 00000000000..8ae6101333e --- /dev/null +++ b/build/pkgs/beniget/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([beniget], [SAGE_PYTHON_PACKAGE_CHECK([beniget])]) diff --git a/build/pkgs/bleach/dependencies b/build/pkgs/bleach/dependencies index 4a74f9bfd68..c7ac2e8b3e7 100644 --- a/build/pkgs/bleach/dependencies +++ b/build/pkgs/bleach/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) packaging six webencodings | $(PYTHON_TOOLCHAIN) + packaging six webencodings | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/bleach/distros/arch.txt b/build/pkgs/bleach/distros/arch.txt new file mode 100644 index 00000000000..c5422ccff0c --- /dev/null +++ b/build/pkgs/bleach/distros/arch.txt @@ -0,0 +1 @@ +python-bleach diff --git a/build/pkgs/bleach/distros/debian.txt b/build/pkgs/bleach/distros/debian.txt new file mode 100644 index 00000000000..6d37c4c79f0 --- /dev/null +++ b/build/pkgs/bleach/distros/debian.txt @@ -0,0 +1 @@ +python3-bleach diff --git a/build/pkgs/bleach/distros/fedora.txt b/build/pkgs/bleach/distros/fedora.txt new file mode 100644 index 00000000000..c5422ccff0c --- /dev/null +++ b/build/pkgs/bleach/distros/fedora.txt @@ -0,0 +1 @@ +python-bleach diff --git a/build/pkgs/bleach/distros/gentoo.txt b/build/pkgs/bleach/distros/gentoo.txt new file mode 100644 index 00000000000..b4f9744eee9 --- /dev/null +++ b/build/pkgs/bleach/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/bleach diff --git a/build/pkgs/bleach/distros/opensuse.txt b/build/pkgs/bleach/distros/opensuse.txt new file mode 100644 index 00000000000..0e329f6dd62 --- /dev/null +++ b/build/pkgs/bleach/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-bleach diff --git a/build/pkgs/bleach/spkg-configure.m4 b/build/pkgs/bleach/spkg-configure.m4 new file mode 100644 index 00000000000..3c9bb26bb05 --- /dev/null +++ b/build/pkgs/bleach/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([bleach], [SAGE_PYTHON_PACKAGE_CHECK([bleach])]) diff --git a/build/pkgs/cachetools/SPKG.rst b/build/pkgs/cachetools/SPKG.rst new file mode 100644 index 00000000000..30035dfd3cd --- /dev/null +++ b/build/pkgs/cachetools/SPKG.rst @@ -0,0 +1,18 @@ +cachetools: Extensible memoizing collections and decorators +=========================================================== + +Description +----------- + +Extensible memoizing collections and decorators + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/cachetools/ + diff --git a/build/pkgs/cachetools/checksums.ini b/build/pkgs/cachetools/checksums.ini new file mode 100644 index 00000000000..0ffe70b3b2f --- /dev/null +++ b/build/pkgs/cachetools/checksums.ini @@ -0,0 +1,5 @@ +tarball=cachetools-VERSION-py3-none-any.whl +sha1=f7deaa4b10ae6d8955c83b0573e5b80f84e5d87a +md5=7375eb8031ea2c95b91d2406c29e9379 +cksum=3631496040 +upstream_url=https://pypi.io/packages/py3/c/cachetools/cachetools-VERSION-py3-none-any.whl diff --git a/build/pkgs/backports_zoneinfo/dependencies b/build/pkgs/cachetools/dependencies similarity index 66% rename from build/pkgs/backports_zoneinfo/dependencies rename to build/pkgs/cachetools/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/backports_zoneinfo/dependencies +++ b/build/pkgs/cachetools/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cachetools/install-requires.txt b/build/pkgs/cachetools/install-requires.txt new file mode 100644 index 00000000000..50d14084a9b --- /dev/null +++ b/build/pkgs/cachetools/install-requires.txt @@ -0,0 +1 @@ +cachetools diff --git a/build/pkgs/cachetools/package-version.txt b/build/pkgs/cachetools/package-version.txt new file mode 100644 index 00000000000..c7cb1311a64 --- /dev/null +++ b/build/pkgs/cachetools/package-version.txt @@ -0,0 +1 @@ +5.3.1 diff --git a/build/pkgs/cachetools/spkg-configure.m4 b/build/pkgs/cachetools/spkg-configure.m4 new file mode 100644 index 00000000000..1e6c1fb453a --- /dev/null +++ b/build/pkgs/cachetools/spkg-configure.m4 @@ -0,0 +1,7 @@ +SAGE_SPKG_CONFIGURE([cachetools], [ + sage_spkg_install_cachetools=yes + ], [dnl REQUIRED-CHECK + AC_REQUIRE([SAGE_SPKG_CONFIGURE_TOX]) + dnl cachetools is only needed when we cannot use system tox. + AS_VAR_SET([SPKG_REQUIRE], [$sage_spkg_install_tox]) + ]) diff --git a/build/pkgs/backports_zoneinfo/type b/build/pkgs/cachetools/type similarity index 100% rename from build/pkgs/backports_zoneinfo/type rename to build/pkgs/cachetools/type diff --git a/build/pkgs/certifi/dependencies b/build/pkgs/certifi/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/certifi/dependencies +++ b/build/pkgs/certifi/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/certifi/distros/arch.txt b/build/pkgs/certifi/distros/arch.txt new file mode 100644 index 00000000000..be421c8b4b2 --- /dev/null +++ b/build/pkgs/certifi/distros/arch.txt @@ -0,0 +1 @@ +python-certifi diff --git a/build/pkgs/certifi/distros/debian.txt b/build/pkgs/certifi/distros/debian.txt new file mode 100644 index 00000000000..f585a823bf3 --- /dev/null +++ b/build/pkgs/certifi/distros/debian.txt @@ -0,0 +1 @@ +python3-certifi diff --git a/build/pkgs/certifi/distros/fedora.txt b/build/pkgs/certifi/distros/fedora.txt new file mode 100644 index 00000000000..be421c8b4b2 --- /dev/null +++ b/build/pkgs/certifi/distros/fedora.txt @@ -0,0 +1 @@ +python-certifi diff --git a/build/pkgs/certifi/distros/gentoo.txt b/build/pkgs/certifi/distros/gentoo.txt new file mode 100644 index 00000000000..72e2e91c6ae --- /dev/null +++ b/build/pkgs/certifi/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/certifi diff --git a/build/pkgs/certifi/distros/opensuse.txt b/build/pkgs/certifi/distros/opensuse.txt index f585a823bf3..9f7a6b5c964 100644 --- a/build/pkgs/certifi/distros/opensuse.txt +++ b/build/pkgs/certifi/distros/opensuse.txt @@ -1 +1 @@ -python3-certifi +python3${PYTHON_MINOR}-certifi diff --git a/build/pkgs/certifi/spkg-configure.m4 b/build/pkgs/certifi/spkg-configure.m4 new file mode 100644 index 00000000000..ddd40613514 --- /dev/null +++ b/build/pkgs/certifi/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([certifi], [SAGE_PYTHON_PACKAGE_CHECK([certifi])]) diff --git a/build/pkgs/cffi/dependencies b/build/pkgs/cffi/dependencies index 9e4c266ad69..9af7c6ed3db 100644 --- a/build/pkgs/cffi/dependencies +++ b/build/pkgs/cffi/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) pycparser + | $(PYTHON_TOOLCHAIN) pycparser $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cffi/distros/gentoo.txt b/build/pkgs/cffi/distros/gentoo.txt new file mode 100644 index 00000000000..81eeb8108c7 --- /dev/null +++ b/build/pkgs/cffi/distros/gentoo.txt @@ -0,0 +1 @@ +virtual/python-cffi diff --git a/build/pkgs/cffi/distros/opensuse.txt b/build/pkgs/cffi/distros/opensuse.txt index 68ec4dda5ba..6bce4cd18b5 100644 --- a/build/pkgs/cffi/distros/opensuse.txt +++ b/build/pkgs/cffi/distros/opensuse.txt @@ -1 +1 @@ -python3-cffi +python3${PYTHON_MINOR}-cffi diff --git a/build/pkgs/cffi/spkg-configure.m4 b/build/pkgs/cffi/spkg-configure.m4 new file mode 100644 index 00000000000..dc81875927f --- /dev/null +++ b/build/pkgs/cffi/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([cffi], [SAGE_PYTHON_PACKAGE_CHECK([cffi])]) diff --git a/build/pkgs/chardet/SPKG.rst b/build/pkgs/chardet/SPKG.rst new file mode 100644 index 00000000000..6e5a717cca5 --- /dev/null +++ b/build/pkgs/chardet/SPKG.rst @@ -0,0 +1,18 @@ +chardet: Universal encoding detector for Python 3 +================================================= + +Description +----------- + +Universal encoding detector for Python 3 + +License +------- + +LGPL + +Upstream Contact +---------------- + +https://pypi.org/project/chardet/ + diff --git a/build/pkgs/chardet/checksums.ini b/build/pkgs/chardet/checksums.ini new file mode 100644 index 00000000000..9911b1d139e --- /dev/null +++ b/build/pkgs/chardet/checksums.ini @@ -0,0 +1,5 @@ +tarball=chardet-VERSION-py3-none-any.whl +sha1=2facc0387556aa8a2956ef682d49fc3eae56d30a +md5=b9eda7cd7d1582e269bd8eb7ffc4fcad +cksum=1563594607 +upstream_url=https://pypi.io/packages/py3/c/chardet/chardet-VERSION-py3-none-any.whl diff --git a/build/pkgs/toml/dependencies b/build/pkgs/chardet/dependencies similarity index 66% rename from build/pkgs/toml/dependencies rename to build/pkgs/chardet/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/toml/dependencies +++ b/build/pkgs/chardet/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/chardet/install-requires.txt b/build/pkgs/chardet/install-requires.txt new file mode 100644 index 00000000000..79236f25cda --- /dev/null +++ b/build/pkgs/chardet/install-requires.txt @@ -0,0 +1 @@ +chardet diff --git a/build/pkgs/chardet/package-version.txt b/build/pkgs/chardet/package-version.txt new file mode 100644 index 00000000000..91ff57278e3 --- /dev/null +++ b/build/pkgs/chardet/package-version.txt @@ -0,0 +1 @@ +5.2.0 diff --git a/build/pkgs/toml/spkg-configure.m4 b/build/pkgs/chardet/spkg-configure.m4 similarity index 50% rename from build/pkgs/toml/spkg-configure.m4 rename to build/pkgs/chardet/spkg-configure.m4 index 0dbc722cde5..2dba4eef338 100644 --- a/build/pkgs/toml/spkg-configure.m4 +++ b/build/pkgs/chardet/spkg-configure.m4 @@ -1,7 +1,7 @@ -SAGE_SPKG_CONFIGURE([toml], [ - sage_spkg_install_toml=yes +SAGE_SPKG_CONFIGURE([chardet], [ + sage_spkg_install_chardet=yes ], [dnl REQUIRED-CHECK AC_REQUIRE([SAGE_SPKG_CONFIGURE_TOX]) - dnl toml is only needed when we cannot use system tox. + dnl chardet is only needed when we cannot use system tox. AS_VAR_SET([SPKG_REQUIRE], [$sage_spkg_install_tox]) ]) diff --git a/build/pkgs/html5lib/type b/build/pkgs/chardet/type similarity index 100% rename from build/pkgs/html5lib/type rename to build/pkgs/chardet/type diff --git a/build/pkgs/charset_normalizer/dependencies b/build/pkgs/charset_normalizer/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/charset_normalizer/dependencies +++ b/build/pkgs/charset_normalizer/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/charset_normalizer/distros/gentoo.txt b/build/pkgs/charset_normalizer/distros/gentoo.txt new file mode 100644 index 00000000000..eefeb89e31e --- /dev/null +++ b/build/pkgs/charset_normalizer/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/charset_normalizer diff --git a/build/pkgs/charset_normalizer/spkg-configure.m4 b/build/pkgs/charset_normalizer/spkg-configure.m4 new file mode 100644 index 00000000000..18b18cf32b4 --- /dev/null +++ b/build/pkgs/charset_normalizer/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([charset_normalizer], [ + SAGE_PYTHON_PACKAGE_CHECK([charset_normalizer]) +]) diff --git a/build/pkgs/cmake/checksums.ini b/build/pkgs/cmake/checksums.ini index c89abdf4277..a145b30dfb4 100644 --- a/build/pkgs/cmake/checksums.ini +++ b/build/pkgs/cmake/checksums.ini @@ -1,5 +1,5 @@ tarball=cmake-VERSION.tar.gz -sha1=256d6a57a57fa6ceaacd6a2daf708baefd33850c -md5=226dd564164372f9f7d1e21e38e6e8c5 -cksum=2080281918 +sha1=3e9b980bfb16974f57ca02b5e2b403a2ef2d4eca +md5=7228f5fcc8a858fdeac27e29bda0c144 +cksum=2027526722 upstream_url=https://github.com/Kitware/CMake/releases/download/vVERSION/cmake-VERSION.tar.gz diff --git a/build/pkgs/cmake/package-version.txt b/build/pkgs/cmake/package-version.txt index 693bd59e3e6..a155471fc06 100644 --- a/build/pkgs/cmake/package-version.txt +++ b/build/pkgs/cmake/package-version.txt @@ -1 +1 @@ -3.24.3 +3.27.3 diff --git a/build/pkgs/colorama/SPKG.rst b/build/pkgs/colorama/SPKG.rst new file mode 100644 index 00000000000..3335092e4c7 --- /dev/null +++ b/build/pkgs/colorama/SPKG.rst @@ -0,0 +1,16 @@ +colorama: Cross-platform colored terminal text. +=============================================== + +Description +----------- + +Cross-platform colored terminal text. + +License +------- + +Upstream Contact +---------------- + +https://pypi.org/project/colorama/ + diff --git a/build/pkgs/colorama/checksums.ini b/build/pkgs/colorama/checksums.ini new file mode 100644 index 00000000000..e625d548a68 --- /dev/null +++ b/build/pkgs/colorama/checksums.ini @@ -0,0 +1,5 @@ +tarball=colorama-VERSION-py2.py3-none-any.whl +sha1=d6ab1608850fecfc0e1cf50bf93d743695c04027 +md5=3fc7a89530d68d7ea231ebe779c0db9c +cksum=3297334831 +upstream_url=https://pypi.io/packages/py2.py3/c/colorama/colorama-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/html5lib/dependencies b/build/pkgs/colorama/dependencies similarity index 59% rename from build/pkgs/html5lib/dependencies rename to build/pkgs/colorama/dependencies index 89200065387..47296a7bace 100644 --- a/build/pkgs/html5lib/dependencies +++ b/build/pkgs/colorama/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) webencodings | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/colorama/install-requires.txt b/build/pkgs/colorama/install-requires.txt new file mode 100644 index 00000000000..3fcfb51b2ad --- /dev/null +++ b/build/pkgs/colorama/install-requires.txt @@ -0,0 +1 @@ +colorama diff --git a/build/pkgs/colorama/package-version.txt b/build/pkgs/colorama/package-version.txt new file mode 100644 index 00000000000..ef52a648073 --- /dev/null +++ b/build/pkgs/colorama/package-version.txt @@ -0,0 +1 @@ +0.4.6 diff --git a/build/pkgs/colorama/spkg-configure.m4 b/build/pkgs/colorama/spkg-configure.m4 new file mode 100644 index 00000000000..65c88b05ec8 --- /dev/null +++ b/build/pkgs/colorama/spkg-configure.m4 @@ -0,0 +1,7 @@ +SAGE_SPKG_CONFIGURE([colorama], [ + sage_spkg_install_colorama=yes + ], [dnl REQUIRED-CHECK + AC_REQUIRE([SAGE_SPKG_CONFIGURE_TOX]) + dnl colorama is only needed when we cannot use system tox. + AS_VAR_SET([SPKG_REQUIRE], [$sage_spkg_install_tox]) + ]) diff --git a/build/pkgs/toml/type b/build/pkgs/colorama/type similarity index 100% rename from build/pkgs/toml/type rename to build/pkgs/colorama/type diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 6712dfd085c..0fb544d529f 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=15c6dc9764f4e9dfc526e7131483989b8ea72430 -md5=c46a0fd95ab6860f6d7185ca467b1df2 -cksum=427186534 +sha1=b2c2a31975aecc02df78e38082e915419c3354e6 +md5=2441f31fbe9e5a3ca1f6070fcee5e42c +cksum=4212643350 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 05d47f390a0..867f16b0119 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -aa220c4a1e34607d75d86b5abe022bd0c0358644 +f32860b2015ad42b5cb9c30a0af1351e597bf314 diff --git a/build/pkgs/contourpy/dependencies b/build/pkgs/contourpy/dependencies index 0740ab1d4a7..d12b50bf33c 100644 --- a/build/pkgs/contourpy/dependencies +++ b/build/pkgs/contourpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy | $(PYTHON_TOOLCHAIN) pybind11 + numpy | $(PYTHON_TOOLCHAIN) pybind11 $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/contourpy/distros/gentoo.txt b/build/pkgs/contourpy/distros/gentoo.txt new file mode 100644 index 00000000000..39774cf783f --- /dev/null +++ b/build/pkgs/contourpy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/contourpy diff --git a/build/pkgs/contourpy/spkg-configure.m4 b/build/pkgs/contourpy/spkg-configure.m4 new file mode 100644 index 00000000000..f26adf351de --- /dev/null +++ b/build/pkgs/contourpy/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([contourpy], [SAGE_PYTHON_PACKAGE_CHECK([contourpy])]) diff --git a/build/pkgs/conway_polynomials/dependencies b/build/pkgs/conway_polynomials/dependencies index 1700e743d59..6b134137610 100644 --- a/build/pkgs/conway_polynomials/dependencies +++ b/build/pkgs/conway_polynomials/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) +| $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cppy/dependencies b/build/pkgs/cppy/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/cppy/dependencies +++ b/build/pkgs/cppy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cppy/distros/gentoo.txt b/build/pkgs/cppy/distros/gentoo.txt new file mode 100644 index 00000000000..f66c6eff5ee --- /dev/null +++ b/build/pkgs/cppy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/cppy diff --git a/build/pkgs/cppy/install-requires.txt b/build/pkgs/cppy/install-requires.txt index 9d2b4aaeee0..42667a30148 100644 --- a/build/pkgs/cppy/install-requires.txt +++ b/build/pkgs/cppy/install-requires.txt @@ -1 +1 @@ -cppy +cppy >=1.2.0 diff --git a/build/pkgs/cppy/spkg-configure.m4 b/build/pkgs/cppy/spkg-configure.m4 new file mode 100644 index 00000000000..2c895d9b070 --- /dev/null +++ b/build/pkgs/cppy/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([cppy], [SAGE_PYTHON_PACKAGE_CHECK([cppy])]) diff --git a/build/pkgs/cryptominisat/dependencies b/build/pkgs/cryptominisat/dependencies index 15e88888b6d..e30473e40f6 100644 --- a/build/pkgs/cryptominisat/dependencies +++ b/build/pkgs/cryptominisat/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) m4ri zlib libpng | cmake boost_cropped + m4ri zlib libpng | cmake boost_cropped $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cvxopt/dependencies b/build/pkgs/cvxopt/dependencies index d47ae01f215..33055fe8bf4 100644 --- a/build/pkgs/cvxopt/dependencies +++ b/build/pkgs/cvxopt/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig + numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cvxopt/distros/arch.txt b/build/pkgs/cvxopt/distros/arch.txt new file mode 100644 index 00000000000..f15770f0506 --- /dev/null +++ b/build/pkgs/cvxopt/distros/arch.txt @@ -0,0 +1 @@ +python-cvxopt diff --git a/build/pkgs/cvxopt/distros/debian.txt b/build/pkgs/cvxopt/distros/debian.txt new file mode 100644 index 00000000000..2bb6ad1e834 --- /dev/null +++ b/build/pkgs/cvxopt/distros/debian.txt @@ -0,0 +1 @@ +python3-cvxopt diff --git a/build/pkgs/cvxopt/distros/fedora.txt b/build/pkgs/cvxopt/distros/fedora.txt new file mode 100644 index 00000000000..f15770f0506 --- /dev/null +++ b/build/pkgs/cvxopt/distros/fedora.txt @@ -0,0 +1 @@ +python-cvxopt diff --git a/build/pkgs/cvxopt/distros/gentoo.txt b/build/pkgs/cvxopt/distros/gentoo.txt new file mode 100644 index 00000000000..b3123912bbe --- /dev/null +++ b/build/pkgs/cvxopt/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/cvxopt diff --git a/build/pkgs/cvxopt/distros/opensuse.txt b/build/pkgs/cvxopt/distros/opensuse.txt new file mode 100644 index 00000000000..e254c198706 --- /dev/null +++ b/build/pkgs/cvxopt/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-cvxopt diff --git a/build/pkgs/cvxopt/spkg-configure.m4 b/build/pkgs/cvxopt/spkg-configure.m4 new file mode 100644 index 00000000000..c4aa6198edb --- /dev/null +++ b/build/pkgs/cvxopt/spkg-configure.m4 @@ -0,0 +1,5 @@ +SAGE_SPKG_CONFIGURE([cvxopt], [ + SAGE_SPKG_DEPCHECK([gsl glpk suitesparse], [ + SAGE_PYTHON_PACKAGE_CHECK([cvxopt]) + ]) +]) diff --git a/build/pkgs/cvxpy/dependencies b/build/pkgs/cvxpy/dependencies index 540b44ff0f2..42cfab890cc 100644 --- a/build/pkgs/cvxpy/dependencies +++ b/build/pkgs/cvxpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy scipy glpk cvxopt osqp_python ecos_python scs | $(PYTHON_TOOLCHAIN) + numpy scipy glpk cvxopt osqp_python ecos_python scs | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cycler/dependencies b/build/pkgs/cycler/dependencies index 730af09b339..8a158d645be 100644 --- a/build/pkgs/cycler/dependencies +++ b/build/pkgs/cycler/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) six | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cycler/distros/arch.txt b/build/pkgs/cycler/distros/arch.txt new file mode 100644 index 00000000000..5727259aca6 --- /dev/null +++ b/build/pkgs/cycler/distros/arch.txt @@ -0,0 +1 @@ +python-cycler diff --git a/build/pkgs/cycler/distros/debian.txt b/build/pkgs/cycler/distros/debian.txt new file mode 100644 index 00000000000..c77685dd417 --- /dev/null +++ b/build/pkgs/cycler/distros/debian.txt @@ -0,0 +1 @@ +python3-cycler diff --git a/build/pkgs/cycler/distros/fedora.txt b/build/pkgs/cycler/distros/fedora.txt new file mode 100644 index 00000000000..5727259aca6 --- /dev/null +++ b/build/pkgs/cycler/distros/fedora.txt @@ -0,0 +1 @@ +python-cycler diff --git a/build/pkgs/cycler/distros/freebsd.txt b/build/pkgs/cycler/distros/freebsd.txt new file mode 100644 index 00000000000..6da1dabb333 --- /dev/null +++ b/build/pkgs/cycler/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-cycler diff --git a/build/pkgs/cycler/distros/gentoo.txt b/build/pkgs/cycler/distros/gentoo.txt new file mode 100644 index 00000000000..4b215438e8f --- /dev/null +++ b/build/pkgs/cycler/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/cycler diff --git a/build/pkgs/cycler/distros/opensuse.txt b/build/pkgs/cycler/distros/opensuse.txt new file mode 100644 index 00000000000..6aab7454acb --- /dev/null +++ b/build/pkgs/cycler/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-Cycler diff --git a/build/pkgs/cycler/spkg-configure.m4 b/build/pkgs/cycler/spkg-configure.m4 new file mode 100644 index 00000000000..239571a0f10 --- /dev/null +++ b/build/pkgs/cycler/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([cycler], [SAGE_PYTHON_PACKAGE_CHECK([cycler])]) diff --git a/build/pkgs/cylp/dependencies b/build/pkgs/cylp/dependencies index 3c541129eb9..d2c6405119d 100644 --- a/build/pkgs/cylp/dependencies +++ b/build/pkgs/cylp/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy scipy cbc | $(PYTHON_TOOLCHAIN) cython + numpy scipy cbc | $(PYTHON_TOOLCHAIN) cython $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cypari/dependencies b/build/pkgs/cypari/dependencies index 72b5af7ad81..69dfe7e7d8a 100644 --- a/build/pkgs/cypari/dependencies +++ b/build/pkgs/cypari/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython pari cysignals | $(PYTHON_TOOLCHAIN) + cython pari cysignals | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cysignals/dependencies b/build/pkgs/cysignals/dependencies index d3225d480f1..cd45ae2076c 100644 --- a/build/pkgs/cysignals/dependencies +++ b/build/pkgs/cysignals/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython pari | $(PYTHON_TOOLCHAIN) + cython pari | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cython/checksums.ini b/build/pkgs/cython/checksums.ini index b06052c59aa..175914867ed 100644 --- a/build/pkgs/cython/checksums.ini +++ b/build/pkgs/cython/checksums.ini @@ -1,5 +1,5 @@ tarball=Cython-VERSION.tar.gz -sha1=015b737107304a5777f5c6552ffb12713684c924 -md5=91c36ea86c00adcc5c1c11cf48b733c0 -cksum=1793363471 +sha1=762987c737acfe7532cb3da38b450fb6e0cf1d7b +md5=a4d0f9fbc9c137f1a88937cd40e8c5ee +cksum=2260471737 upstream_url=https://pypi.io/packages/source/C/Cython/Cython-VERSION.tar.gz diff --git a/build/pkgs/cython/dependencies b/build/pkgs/cython/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/cython/dependencies +++ b/build/pkgs/cython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cython/distros/arch.txt b/build/pkgs/cython/distros/arch.txt new file mode 100644 index 00000000000..f6629e02456 --- /dev/null +++ b/build/pkgs/cython/distros/arch.txt @@ -0,0 +1 @@ +cython diff --git a/build/pkgs/cython/distros/debian.txt b/build/pkgs/cython/distros/debian.txt new file mode 100644 index 00000000000..f6629e02456 --- /dev/null +++ b/build/pkgs/cython/distros/debian.txt @@ -0,0 +1 @@ +cython diff --git a/build/pkgs/cython/distros/fedora.txt b/build/pkgs/cython/distros/fedora.txt new file mode 100644 index 00000000000..002d1b93c6f --- /dev/null +++ b/build/pkgs/cython/distros/fedora.txt @@ -0,0 +1 @@ +Cython diff --git a/build/pkgs/cython/distros/gentoo.txt b/build/pkgs/cython/distros/gentoo.txt new file mode 100644 index 00000000000..bb1512a15ba --- /dev/null +++ b/build/pkgs/cython/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/cython diff --git a/build/pkgs/cython/distros/opensuse.txt b/build/pkgs/cython/distros/opensuse.txt new file mode 100644 index 00000000000..09d8844feaf --- /dev/null +++ b/build/pkgs/cython/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-Cython diff --git a/build/pkgs/cython/package-version.txt b/build/pkgs/cython/package-version.txt index babe4be9be1..5232b0aaea8 100644 --- a/build/pkgs/cython/package-version.txt +++ b/build/pkgs/cython/package-version.txt @@ -1 +1 @@ -0.29.32.p2 +0.29.36 diff --git a/build/pkgs/cython/patches/trashcan.patch b/build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch similarity index 55% rename from build/pkgs/cython/patches/trashcan.patch rename to build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch index e1e88ebe465..0cd3f35df32 100644 --- a/build/pkgs/cython/patches/trashcan.patch +++ b/build/pkgs/cython/patches/0001-cython.trashcan-directive-to-enable-the-Python-trash.patch @@ -9,10 +9,10 @@ Date: Thu Feb 14 10:02:41 2019 +0100 @cython.trashcan directive to enable the Python trashcan for deallocations diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py -index d5742de..27fcad6 100644 +index 56845330d..3a3e8a956 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py -@@ -1426,6 +1426,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): +@@ -1443,6 +1443,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): is_final_type = scope.parent_type.is_final_type needs_gc = scope.needs_gc() @@ -20,7 +20,7 @@ index d5742de..27fcad6 100644 weakref_slot = scope.lookup_here("__weakref__") if not scope.is_closure_class_scope else None if weakref_slot not in scope.var_entries: -@@ -1464,6 +1465,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): +@@ -1481,6 +1482,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): # running this destructor. code.putln("PyObject_GC_UnTrack(o);") @@ -32,7 +32,7 @@ index d5742de..27fcad6 100644 # call the user's __dealloc__ self.generate_usr_dealloc_call(scope, code) -@@ -1537,6 +1543,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): +@@ -1554,6 +1560,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("(*Py_TYPE(o)->tp_free)(o);") if freelist_size: code.putln("}") @@ -44,18 +44,20 @@ index d5742de..27fcad6 100644 "}") diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py -index d859c19..19d96f1 100644 +index d03119fca..539629926 100644 --- a/Cython/Compiler/Options.py +++ b/Cython/Compiler/Options.py -@@ -313,6 +313,7 @@ directive_types = { +@@ -319,7 +319,8 @@ directive_types = { 'freelist': int, 'c_string_type': one_of('bytes', 'bytearray', 'str', 'unicode'), 'c_string_encoding': normalise_encoding_name, +- 'cpow': bool ++ 'cpow': bool, + 'trashcan': bool, } for key, val in _directive_defaults.items(): -@@ -355,6 +356,7 @@ directive_scopes = { # defaults to available everywhere +@@ -362,6 +363,7 @@ directive_scopes = { # defaults to available everywhere 'np_pythran': ('module',), 'fast_gil': ('module',), 'iterable_coroutine': ('module', 'function'), @@ -64,10 +66,10 @@ index d859c19..19d96f1 100644 diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py -index 3b572d6..f200c5f 100644 +index c309bd04b..9231130b5 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py -@@ -1136,6 +1136,7 @@ class PyObjectType(PyrexType): +@@ -1129,6 +1129,7 @@ class PyObjectType(PyrexType): is_extern = False is_subclassed = False is_gc_simple = False @@ -75,7 +77,7 @@ index 3b572d6..f200c5f 100644 def __str__(self): return "Python object" -@@ -1190,10 +1191,14 @@ class PyObjectType(PyrexType): +@@ -1183,10 +1184,14 @@ class PyObjectType(PyrexType): builtin_types_that_cannot_create_refcycles = set([ @@ -91,7 +93,7 @@ index 3b572d6..f200c5f 100644 class BuiltinObjectType(PyObjectType): # objstruct_cname string Name of PyObject struct -@@ -1218,6 +1223,7 @@ class BuiltinObjectType(PyObjectType): +@@ -1211,6 +1216,7 @@ class BuiltinObjectType(PyObjectType): self.typeptr_cname = "(&%s)" % cname self.objstruct_cname = objstruct_cname self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles @@ -100,10 +102,19 @@ index 3b572d6..f200c5f 100644 # Special case the type type, as many C API calls (and other # libraries) actually expect a PyTypeObject* for type arguments. diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py -index f7443cb..d44484d 100644 +index 7361a55ae..f0c311ba6 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py -@@ -2085,6 +2085,22 @@ class CClassScope(ClassScope): +@@ -2043,7 +2043,7 @@ class PyClassScope(ClassScope): + class CClassScope(ClassScope): + # Namespace of an extension type. + # +- # parent_type CClassType ++ # parent_type PyExtensionType + # #typeobj_cname string or None + # #objstruct_cname string + # method_table_cname string +@@ -2087,6 +2087,22 @@ class CClassScope(ClassScope): return not self.parent_type.is_gc_simple return False @@ -127,10 +138,10 @@ index f7443cb..d44484d 100644 """ Do we need to generate an implementation for the tp_clear slot? Can diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c -index 50d0e21..ca2adbe 100644 +index dc187ab49..f359165df 100644 --- a/Cython/Utility/ExtensionTypes.c +++ b/Cython/Utility/ExtensionTypes.c -@@ -74,6 +74,54 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { +@@ -119,6 +119,54 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { return r; } @@ -185,3 +196,160 @@ index 50d0e21..ca2adbe 100644 /////////////// CallNextTpDealloc.proto /////////////// static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc); +diff --git a/tests/run/trashcan.pyx b/tests/run/trashcan.pyx +new file mode 100644 +index 000000000..93a501ff8 +--- /dev/null ++++ b/tests/run/trashcan.pyx +@@ -0,0 +1,148 @@ ++# mode: run ++ ++cimport cython ++ ++ ++# Count number of times an object was deallocated twice. This should remain 0. ++cdef int double_deallocations = 0 ++def assert_no_double_deallocations(): ++ global double_deallocations ++ err = double_deallocations ++ double_deallocations = 0 ++ assert not err ++ ++ ++# Compute x = f(f(f(...(None)...))) nested n times and throw away the result. ++# The real test happens when exiting this function: then a big recursive ++# deallocation of x happens. We are testing two things in the tests below: ++# that Python does not crash and that no double deallocation happens. ++# See also https://github.com/python/cpython/pull/11841 ++def recursion_test(f, int n=2**20): ++ x = None ++ cdef int i ++ for i in range(n): ++ x = f(x) ++ ++ ++@cython.trashcan(True) ++cdef class Recurse: ++ """ ++ >>> recursion_test(Recurse) ++ >>> assert_no_double_deallocations() ++ """ ++ cdef public attr ++ cdef int deallocated ++ ++ def __init__(self, x): ++ self.attr = x ++ ++ def __dealloc__(self): ++ # Check that we're not being deallocated twice ++ global double_deallocations ++ double_deallocations += self.deallocated ++ self.deallocated = 1 ++ ++ ++cdef class RecurseSub(Recurse): ++ """ ++ >>> recursion_test(RecurseSub) ++ >>> assert_no_double_deallocations() ++ """ ++ cdef int subdeallocated ++ ++ def __dealloc__(self): ++ # Check that we're not being deallocated twice ++ global double_deallocations ++ double_deallocations += self.subdeallocated ++ self.subdeallocated = 1 ++ ++ ++@cython.freelist(4) ++@cython.trashcan(True) ++cdef class RecurseFreelist: ++ """ ++ >>> recursion_test(RecurseFreelist) ++ >>> recursion_test(RecurseFreelist, 1000) ++ >>> assert_no_double_deallocations() ++ """ ++ cdef public attr ++ cdef int deallocated ++ ++ def __init__(self, x): ++ self.attr = x ++ ++ def __dealloc__(self): ++ # Check that we're not being deallocated twice ++ global double_deallocations ++ double_deallocations += self.deallocated ++ self.deallocated = 1 ++ ++ ++# Subclass of list => uses trashcan by default ++# As long as https://github.com/python/cpython/pull/11841 is not fixed, ++# this does lead to double deallocations, so we skip that check. ++cdef class RecurseList(list): ++ """ ++ >>> RecurseList(42) ++ [42] ++ >>> recursion_test(RecurseList) ++ """ ++ def __init__(self, x): ++ super().__init__((x,)) ++ ++ ++# Some tests where the trashcan is NOT used. When the trashcan is not used ++# in a big recursive deallocation, the __dealloc__s of the base classs are ++# only run after the __dealloc__s of the subclasses. ++# We use this to detect trashcan usage. ++cdef int base_deallocated = 0 ++cdef int trashcan_used = 0 ++def assert_no_trashcan_used(): ++ global base_deallocated, trashcan_used ++ err = trashcan_used ++ trashcan_used = base_deallocated = 0 ++ assert not err ++ ++ ++cdef class Base: ++ def __dealloc__(self): ++ global base_deallocated ++ base_deallocated = 1 ++ ++ ++# Trashcan disabled by default ++cdef class Sub1(Base): ++ """ ++ >>> recursion_test(Sub1, 100) ++ >>> assert_no_trashcan_used() ++ """ ++ cdef public attr ++ ++ def __init__(self, x): ++ self.attr = x ++ ++ def __dealloc__(self): ++ global base_deallocated, trashcan_used ++ trashcan_used += base_deallocated ++ ++ ++@cython.trashcan(True) ++cdef class Middle(Base): ++ cdef public foo ++ ++ ++# Trashcan disabled explicitly ++@cython.trashcan(False) ++cdef class Sub2(Middle): ++ """ ++ >>> recursion_test(Sub2, 1000) ++ >>> assert_no_trashcan_used() ++ """ ++ cdef public attr ++ ++ def __init__(self, x): ++ self.attr = x ++ ++ def __dealloc__(self): ++ global base_deallocated, trashcan_used ++ trashcan_used += base_deallocated +-- +2.37.1 (Apple Git-137.1) + diff --git a/build/pkgs/cython/patches/4918.patch b/build/pkgs/cython/patches/0001-rebased-PR2946.patch similarity index 60% rename from build/pkgs/cython/patches/4918.patch rename to build/pkgs/cython/patches/0001-rebased-PR2946.patch index a9dbb0a4a0c..36764e7291e 100644 --- a/build/pkgs/cython/patches/4918.patch +++ b/build/pkgs/cython/patches/0001-rebased-PR2946.patch @@ -1,22 +1,21 @@ -From 0dade9353e06b052d0da5e512cdc2ce04061904a Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Sat, 23 Jul 2022 10:53:49 -0700 -Subject: [PATCH 1/3] Add PEP420 namespace support +From 0b69e95aa702fb9f52b285360d5c5ae5e7fbb745 Mon Sep 17 00:00:00 2001 +From: Dima Pasechnik +Date: Thu, 16 Mar 2023 22:35:09 +0000 +Subject: [PATCH] rebased PR2946 -Backport of https://github.com/cython/cython/pull/2946 to 0.29.x --- Cython/Compiler/Main.py | 44 +++++++++++++++---- - Cython/Utils.py | 26 ++++++++--- + Cython/Utils.py | 22 +++++++--- runtests.py | 1 + .../build/cythonize_pep420_namespace.srctree | 44 +++++++++++++++++++ - 4 files changed, 99 insertions(+), 16 deletions(-) + 4 files changed, 96 insertions(+), 15 deletions(-) create mode 100644 tests/build/cythonize_pep420_namespace.srctree diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py -index dc4add541e..2be7a06a1c 100644 +index 9c57452ba..1143ecf03 100644 --- a/Cython/Compiler/Main.py +++ b/Cython/Compiler/Main.py -@@ -801,32 +801,58 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False) +@@ -809,32 +809,58 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False) else: dirs = (Utils.find_root_package_dir(file_desc.filename),) + dirs @@ -85,14 +84,12 @@ index dc4add541e..2be7a06a1c 100644 diff --git a/Cython/Utils.py b/Cython/Utils.py -index d59d67d78b..305ebf8412 100644 +index 69563794c..77a48fbd7 100644 --- a/Cython/Utils.py +++ b/Cython/Utils.py -@@ -134,16 +134,21 @@ def find_root_package_dir(file_path): - else: +@@ -135,15 +135,19 @@ def find_root_package_dir(file_path): return dir -+ @cached_function -def check_package_dir(dir, package_names): +def check_package_dir(dir_path, package_names): @@ -110,19 +107,17 @@ index d59d67d78b..305ebf8412 100644 + namespace = False + return dir_path, namespace --@cached_function + @cached_function -def is_package_dir(dir_path): -+ +def contains_init(dir_path): for filename in ("__init__.py", "__init__.pyc", "__init__.pyx", -@@ -152,6 +157,13 @@ def is_package_dir(dir_path): +@@ -152,6 +156,12 @@ def is_package_dir(dir_path): if path_exists(path): return 1 + -+@cached_function +def is_package_dir(dir_path): + if contains_init(dir_path): + return 1 @@ -132,10 +127,10 @@ index d59d67d78b..305ebf8412 100644 def path_exists(path): # try on the filesystem first diff --git a/runtests.py b/runtests.py -index 91a0dd2570..7d04463846 100755 +index 91a0dd257..7d0446384 100755 --- a/runtests.py +++ b/runtests.py -@@ -415,6 +415,7 @@ def get_openmp_compiler_flags(language): +@@ -415,6 +415,7 @@ VER_DEP_MODULES = { 'run.special_methods_T561_py2' ]), (3,3) : (operator.lt, lambda x: x in ['build.package_compilation', @@ -145,7 +140,7 @@ index 91a0dd2570..7d04463846 100755 ]), diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree new file mode 100644 -index 0000000000..6a031e4170 +index 000000000..6a031e417 --- /dev/null +++ b/tests/build/cythonize_pep420_namespace.srctree @@ -0,0 +1,44 @@ @@ -193,95 +188,6 @@ index 0000000000..6a031e4170 + +a = A() +b = B() +-- +2.37.1 (Apple Git-137.1) -From fcd3e7bd1351a0964704f2921ae33b4b57250668 Mon Sep 17 00:00:00 2001 -From: Fedor Alekseev -Date: Mon, 9 Nov 2020 14:34:01 +0300 -Subject: [PATCH 2/3] Support namespace packages inside regular packages - ---- - Cython/Utils.py | 4 +--- - tests/build/cythonize_pep420_namespace.srctree | 17 ++++++++++++++++- - 2 files changed, 17 insertions(+), 4 deletions(-) - -diff --git a/Cython/Utils.py b/Cython/Utils.py -index 305ebf8412..f21d5cddba 100644 ---- a/Cython/Utils.py -+++ b/Cython/Utils.py -@@ -141,9 +141,7 @@ def check_package_dir(dir_path, package_names): - for dirname in package_names: - dir_path = os.path.join(dir_path, dirname) - has_init = contains_init(dir_path) -- if not namespace and not has_init: -- return None, False -- elif has_init: -+ if has_init: - namespace = False - return dir_path, namespace - -diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree -index 6a031e4170..04013a3004 100644 ---- a/tests/build/cythonize_pep420_namespace.srctree -+++ b/tests/build/cythonize_pep420_namespace.srctree -@@ -10,7 +10,8 @@ from distutils.core import setup, Extension - setup( - ext_modules=cythonize([ - Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), -- Extension("nsp.m2.b", ["nsp/m2/b.pyx"]) -+ Extension("nsp.m2.b", ["nsp/m2/b.pyx"]), -+ Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]) - ]), - ) - -@@ -31,14 +32,28 @@ cdef class A: - ######## nsp/m2/b.pyx ######## - - from nsp.m1.a cimport A -+from nsp.m3.c.d cimport D - - cdef class B(A): - pass - -+######## nsp/m3/__init__.py ######## -+ -+######## nsp/m3/c/d.pyx ######## -+ -+cdef class D: -+ pass -+ -+######## nsp/m3/c/d.pxd ######## -+ -+cdef class D: -+ pass -+ - ######## runner.py ######## - - from nsp.m1.a import A - from nsp.m2.b import B -+from nsp.m3.c.d import D - - a = A() - b = B() - -From 9d61b95a6a71a4c88a51ab8f30d5b3a8b93998b8 Mon Sep 17 00:00:00 2001 -From: scoder -Date: Sat, 14 Nov 2020 09:42:09 +0100 -Subject: [PATCH 3/3] Anticipate future changes. - ---- - tests/build/cythonize_pep420_namespace.srctree | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree -index 04013a3004..99649376a3 100644 ---- a/tests/build/cythonize_pep420_namespace.srctree -+++ b/tests/build/cythonize_pep420_namespace.srctree -@@ -11,7 +11,7 @@ setup( - ext_modules=cythonize([ - Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), - Extension("nsp.m2.b", ["nsp/m2/b.pyx"]), -- Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]) -+ Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]), - ]), - ) - diff --git a/build/pkgs/database_cubic_hecke/dependencies b/build/pkgs/database_cubic_hecke/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/database_cubic_hecke/dependencies +++ b/build/pkgs/database_cubic_hecke/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/database_knotinfo/dependencies b/build/pkgs/database_knotinfo/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/database_knotinfo/dependencies +++ b/build/pkgs/database_knotinfo/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/dateutil/dependencies b/build/pkgs/dateutil/dependencies index 7a972de985e..a90844872ae 100644 --- a/build/pkgs/dateutil/dependencies +++ b/build/pkgs/dateutil/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) six | $(PYTHON_TOOLCHAIN) + six | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/dateutil/distros/arch.txt b/build/pkgs/dateutil/distros/arch.txt new file mode 100644 index 00000000000..0f08daace31 --- /dev/null +++ b/build/pkgs/dateutil/distros/arch.txt @@ -0,0 +1 @@ +python-dateutil diff --git a/build/pkgs/dateutil/distros/debian.txt b/build/pkgs/dateutil/distros/debian.txt new file mode 100644 index 00000000000..2f46170765c --- /dev/null +++ b/build/pkgs/dateutil/distros/debian.txt @@ -0,0 +1 @@ +python3-dateutil diff --git a/build/pkgs/dateutil/distros/fedora.txt b/build/pkgs/dateutil/distros/fedora.txt new file mode 100644 index 00000000000..0f08daace31 --- /dev/null +++ b/build/pkgs/dateutil/distros/fedora.txt @@ -0,0 +1 @@ +python-dateutil diff --git a/build/pkgs/dateutil/distros/freebsd.txt b/build/pkgs/dateutil/distros/freebsd.txt new file mode 100644 index 00000000000..c336f5e0b1d --- /dev/null +++ b/build/pkgs/dateutil/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-dateutil diff --git a/build/pkgs/dateutil/distros/gentoo.txt b/build/pkgs/dateutil/distros/gentoo.txt new file mode 100644 index 00000000000..e129df768dc --- /dev/null +++ b/build/pkgs/dateutil/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/python-dateutil diff --git a/build/pkgs/dateutil/distros/opensuse.txt b/build/pkgs/dateutil/distros/opensuse.txt new file mode 100644 index 00000000000..ba37df671e5 --- /dev/null +++ b/build/pkgs/dateutil/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-python-dateutil diff --git a/build/pkgs/dateutil/install-requires.txt b/build/pkgs/dateutil/install-requires.txt index 0ae93da485e..face537605d 100644 --- a/build/pkgs/dateutil/install-requires.txt +++ b/build/pkgs/dateutil/install-requires.txt @@ -1 +1 @@ -dateutil >=2.8.1 +python-dateutil >=2.8.1 diff --git a/build/pkgs/dateutil/spkg-configure.m4 b/build/pkgs/dateutil/spkg-configure.m4 new file mode 100644 index 00000000000..fdcd1273975 --- /dev/null +++ b/build/pkgs/dateutil/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([dateutil], [SAGE_PYTHON_PACKAGE_CHECK([dateutil])]) diff --git a/build/pkgs/debugpy/dependencies b/build/pkgs/debugpy/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/debugpy/dependencies +++ b/build/pkgs/debugpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/debugpy/distros/gentoo.txt b/build/pkgs/debugpy/distros/gentoo.txt new file mode 100644 index 00000000000..8b797ce715f --- /dev/null +++ b/build/pkgs/debugpy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/debugpy diff --git a/build/pkgs/debugpy/spkg-configure.m4 b/build/pkgs/debugpy/spkg-configure.m4 new file mode 100644 index 00000000000..db605ff03c8 --- /dev/null +++ b/build/pkgs/debugpy/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([debugpy], [SAGE_PYTHON_PACKAGE_CHECK([debugpy])]) diff --git a/build/pkgs/decorator/dependencies b/build/pkgs/decorator/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/decorator/dependencies +++ b/build/pkgs/decorator/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/decorator/distros/arch.txt b/build/pkgs/decorator/distros/arch.txt new file mode 100644 index 00000000000..079560412f1 --- /dev/null +++ b/build/pkgs/decorator/distros/arch.txt @@ -0,0 +1 @@ +python-decorator diff --git a/build/pkgs/decorator/distros/debian.txt b/build/pkgs/decorator/distros/debian.txt new file mode 100644 index 00000000000..46c478e1513 --- /dev/null +++ b/build/pkgs/decorator/distros/debian.txt @@ -0,0 +1 @@ +python3-decorator diff --git a/build/pkgs/decorator/distros/fedora.txt b/build/pkgs/decorator/distros/fedora.txt new file mode 100644 index 00000000000..079560412f1 --- /dev/null +++ b/build/pkgs/decorator/distros/fedora.txt @@ -0,0 +1 @@ +python-decorator diff --git a/build/pkgs/decorator/distros/gentoo.txt b/build/pkgs/decorator/distros/gentoo.txt new file mode 100644 index 00000000000..fea5a67ac9e --- /dev/null +++ b/build/pkgs/decorator/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/decorator diff --git a/build/pkgs/decorator/distros/opensuse.txt b/build/pkgs/decorator/distros/opensuse.txt index 46c478e1513..4b9085da296 100644 --- a/build/pkgs/decorator/distros/opensuse.txt +++ b/build/pkgs/decorator/distros/opensuse.txt @@ -1 +1 @@ -python3-decorator +python3${PYTHON_MINOR}-decorator diff --git a/build/pkgs/decorator/spkg-configure.m4 b/build/pkgs/decorator/spkg-configure.m4 new file mode 100644 index 00000000000..e062778d6db --- /dev/null +++ b/build/pkgs/decorator/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([decorator], [SAGE_PYTHON_PACKAGE_CHECK([decorator])]) diff --git a/build/pkgs/defusedxml/dependencies b/build/pkgs/defusedxml/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/defusedxml/dependencies +++ b/build/pkgs/defusedxml/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/defusedxml/distros/gentoo.txt b/build/pkgs/defusedxml/distros/gentoo.txt new file mode 100644 index 00000000000..2804214449e --- /dev/null +++ b/build/pkgs/defusedxml/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/defusedxml diff --git a/build/pkgs/defusedxml/spkg-configure.m4 b/build/pkgs/defusedxml/spkg-configure.m4 new file mode 100644 index 00000000000..e02f34524ce --- /dev/null +++ b/build/pkgs/defusedxml/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([defusedxml], [SAGE_PYTHON_PACKAGE_CHECK([defusedxml])]) diff --git a/build/pkgs/deprecation/dependencies b/build/pkgs/deprecation/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/deprecation/dependencies +++ b/build/pkgs/deprecation/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/distlib/checksums.ini b/build/pkgs/distlib/checksums.ini index 1d749b2f9a7..be255ceca11 100644 --- a/build/pkgs/distlib/checksums.ini +++ b/build/pkgs/distlib/checksums.ini @@ -1,5 +1,5 @@ tarball=distlib-VERSION.tar.gz -sha1=3a86d49dc17320325004564d0dc86afa808624bc -md5=f60ba4e3f8e76c214d3d00b2227a16f7 -cksum=1543870863 +sha1=5c99f8bd1cc58c387a8d22afa632f81c6fec9993 +md5=44e4357e35bbd77fdf1b81e174e34f20 +cksum=3690000669 upstream_url=https://pypi.io/packages/source/d/distlib/distlib-VERSION.tar.gz diff --git a/build/pkgs/distlib/dependencies b/build/pkgs/distlib/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/distlib/dependencies +++ b/build/pkgs/distlib/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/distlib/package-version.txt b/build/pkgs/distlib/package-version.txt index 449d7e73a96..0f82685331e 100644 --- a/build/pkgs/distlib/package-version.txt +++ b/build/pkgs/distlib/package-version.txt @@ -1 +1 @@ -0.3.6 +0.3.7 diff --git a/build/pkgs/docutils/dependencies b/build/pkgs/docutils/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/docutils/dependencies +++ b/build/pkgs/docutils/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/docutils/distros/gentoo.txt b/build/pkgs/docutils/distros/gentoo.txt new file mode 100644 index 00000000000..fe4a4524cbb --- /dev/null +++ b/build/pkgs/docutils/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/docutils diff --git a/build/pkgs/docutils/distros/opensuse.txt b/build/pkgs/docutils/distros/opensuse.txt index a4bb792a5a4..a7fcdac14ef 100644 --- a/build/pkgs/docutils/distros/opensuse.txt +++ b/build/pkgs/docutils/distros/opensuse.txt @@ -1 +1 @@ -python3-docutils +python3${PYTHON_MINOR}-docutils diff --git a/build/pkgs/docutils/spkg-configure.m4 b/build/pkgs/docutils/spkg-configure.m4 new file mode 100644 index 00000000000..3584e4513c6 --- /dev/null +++ b/build/pkgs/docutils/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([docutils], [SAGE_PYTHON_PACKAGE_CHECK([docutils])]) diff --git a/build/pkgs/dot2tex/dependencies b/build/pkgs/dot2tex/dependencies index c1925d16b73..75d8c64edb5 100644 --- a/build/pkgs/dot2tex/dependencies +++ b/build/pkgs/dot2tex/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) pyparsing + | $(PYTHON_TOOLCHAIN) pyparsing $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ecos_python/dependencies b/build/pkgs/ecos_python/dependencies index ecd3af7675b..aaf3b261709 100644 --- a/build/pkgs/ecos_python/dependencies +++ b/build/pkgs/ecos_python/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy scipy | $(PYTHON_TOOLCHAIN) + numpy scipy | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/editables/checksums.ini b/build/pkgs/editables/checksums.ini index 6a0618183b7..52c7fa0b03b 100644 --- a/build/pkgs/editables/checksums.ini +++ b/build/pkgs/editables/checksums.ini @@ -1,5 +1,5 @@ tarball=editables-VERSION.tar.gz -sha1=a99e0ba3d75e4f439b9742e65cbff24e0b8ce80e -md5=e91709fbb0ef586cb7b785042068ab67 -cksum=2338248945 +sha1=90efed858e78bf6276d1a5959ec6692e11a6bce9 +md5=520de8c3a9dc5dfb2b365d104541c9de +cksum=3074203672 upstream_url=https://pypi.io/packages/source/e/editables/editables-VERSION.tar.gz diff --git a/build/pkgs/editables/dependencies b/build/pkgs/editables/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/editables/dependencies +++ b/build/pkgs/editables/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/editables/distros/gentoo.txt b/build/pkgs/editables/distros/gentoo.txt new file mode 100644 index 00000000000..a7759b55c3f --- /dev/null +++ b/build/pkgs/editables/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/editables diff --git a/build/pkgs/editables/package-version.txt b/build/pkgs/editables/package-version.txt index be586341736..2eb3c4fe4ee 100644 --- a/build/pkgs/editables/package-version.txt +++ b/build/pkgs/editables/package-version.txt @@ -1 +1 @@ -0.3 +0.5 diff --git a/build/pkgs/editables/spkg-configure.m4 b/build/pkgs/editables/spkg-configure.m4 new file mode 100644 index 00000000000..66a93c4165b --- /dev/null +++ b/build/pkgs/editables/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([editables], [SAGE_PYTHON_PACKAGE_CHECK([editables])]) diff --git a/build/pkgs/elliptic_curves/dependencies b/build/pkgs/elliptic_curves/dependencies index 6b134137610..3518086ab84 100644 --- a/build/pkgs/elliptic_curves/dependencies +++ b/build/pkgs/elliptic_curves/dependencies @@ -1,4 +1,4 @@ -| $(PYTHON) +| $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/entrypoints/dependencies b/build/pkgs/entrypoints/dependencies index 902a5feed13..4fedbe70cd1 100644 --- a/build/pkgs/entrypoints/dependencies +++ b/build/pkgs/entrypoints/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flit_core tomli + | $(PYTHON_TOOLCHAIN) flit_core tomli $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/entrypoints/distros/gentoo.txt b/build/pkgs/entrypoints/distros/gentoo.txt new file mode 100644 index 00000000000..684ddd036ee --- /dev/null +++ b/build/pkgs/entrypoints/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/entrypoints diff --git a/build/pkgs/entrypoints/spkg-configure.m4 b/build/pkgs/entrypoints/spkg-configure.m4 new file mode 100644 index 00000000000..caed658b69a --- /dev/null +++ b/build/pkgs/entrypoints/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([entrypoints], [SAGE_PYTHON_PACKAGE_CHECK([entrypoints])]) diff --git a/build/pkgs/executing/dependencies b/build/pkgs/executing/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/executing/dependencies +++ b/build/pkgs/executing/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/executing/distros/gentoo.txt b/build/pkgs/executing/distros/gentoo.txt new file mode 100644 index 00000000000..c2b60c085b9 --- /dev/null +++ b/build/pkgs/executing/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/executing diff --git a/build/pkgs/executing/spkg-configure.m4 b/build/pkgs/executing/spkg-configure.m4 new file mode 100644 index 00000000000..fdf2735ef0a --- /dev/null +++ b/build/pkgs/executing/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([executing], [SAGE_PYTHON_PACKAGE_CHECK([executing])]) diff --git a/build/pkgs/fastjsonschema/dependencies b/build/pkgs/fastjsonschema/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/fastjsonschema/dependencies +++ b/build/pkgs/fastjsonschema/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/filelock/checksums.ini b/build/pkgs/filelock/checksums.ini index 48a18055930..0d412bb2ca3 100644 --- a/build/pkgs/filelock/checksums.ini +++ b/build/pkgs/filelock/checksums.ini @@ -1,5 +1,5 @@ -tarball=filelock-VERSION.tar.gz -sha1=1de304add05b7e3e8874aa9f86202204f8042e30 -md5=9bd8d33d5d7dc95012981ccbfb2d2a0f -cksum=2335245752 -upstream_url=https://pypi.io/packages/source/f/filelock/filelock-VERSION.tar.gz +tarball=filelock-VERSION-py3-none-any.whl +sha1=74f5368865bf05ddc5b69949e4547ad25c078fc1 +md5=63b0f117cb65ef531ffafb566170661e +cksum=1046951951 +upstream_url=https://pypi.io/packages/py3/f/filelock/filelock-VERSION-py3-none-any.whl diff --git a/build/pkgs/filelock/dependencies b/build/pkgs/filelock/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/filelock/dependencies +++ b/build/pkgs/filelock/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/filelock/package-version.txt b/build/pkgs/filelock/package-version.txt index 19811903a7f..871f80a34be 100644 --- a/build/pkgs/filelock/package-version.txt +++ b/build/pkgs/filelock/package-version.txt @@ -1 +1 @@ -3.8.0 +3.12.3 diff --git a/build/pkgs/filelock/spkg-install.in b/build/pkgs/filelock/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/filelock/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/flit_core/dependencies b/build/pkgs/flit_core/dependencies index 93c460228b4..644ad35f773 100644 --- a/build/pkgs/flit_core/dependencies +++ b/build/pkgs/flit_core/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | pip + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/flit_core/distros/gentoo.txt b/build/pkgs/flit_core/distros/gentoo.txt new file mode 100644 index 00000000000..fe6bea92362 --- /dev/null +++ b/build/pkgs/flit_core/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/flit_core diff --git a/build/pkgs/flit_core/install-requires.txt b/build/pkgs/flit_core/install-requires.txt index 14ccfd92035..88b912bf11a 100644 --- a/build/pkgs/flit_core/install-requires.txt +++ b/build/pkgs/flit_core/install-requires.txt @@ -1 +1 @@ -flit-core +flit-core >= 3.7.1 diff --git a/build/pkgs/flit_core/spkg-configure.m4 b/build/pkgs/flit_core/spkg-configure.m4 new file mode 100644 index 00000000000..ee67557024f --- /dev/null +++ b/build/pkgs/flit_core/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([flit_core], [SAGE_PYTHON_PACKAGE_CHECK([flit_core])]) diff --git a/build/pkgs/fonttools/dependencies b/build/pkgs/fonttools/dependencies index 9c736669d9a..909380550a2 100644 --- a/build/pkgs/fonttools/dependencies +++ b/build/pkgs/fonttools/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) cython + | $(PYTHON_TOOLCHAIN) cython $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/fonttools/distros/gentoo.txt b/build/pkgs/fonttools/distros/gentoo.txt new file mode 100644 index 00000000000..172476e3166 --- /dev/null +++ b/build/pkgs/fonttools/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/fonttools diff --git a/build/pkgs/fonttools/spkg-configure.m4 b/build/pkgs/fonttools/spkg-configure.m4 new file mode 100644 index 00000000000..93c1477cc3c --- /dev/null +++ b/build/pkgs/fonttools/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([fonttools], [SAGE_PYTHON_PACKAGE_CHECK([fonttools])]) diff --git a/build/pkgs/fpylll/dependencies b/build/pkgs/fpylll/dependencies index 4b4fb1b44fb..4837249bcfa 100644 --- a/build/pkgs/fpylll/dependencies +++ b/build/pkgs/fpylll/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython cysignals numpy fplll + cython cysignals numpy fplll | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/furo/dependencies b/build/pkgs/furo/dependencies index fec067b2058..07434099dee 100644 --- a/build/pkgs/furo/dependencies +++ b/build/pkgs/furo/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) beautifulsoup4 sphinx pygments sphinx_basic_ng | $(PYTHON_TOOLCHAIN) + beautifulsoup4 sphinx pygments sphinx_basic_ng | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gambit/dependencies b/build/pkgs/gambit/dependencies index 1f00cbf5321..e026bfaacf9 100644 --- a/build/pkgs/gambit/dependencies +++ b/build/pkgs/gambit/dependencies @@ -1,4 +1,4 @@ -cython | $(PYTHON_TOOLCHAIN) +cython | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gap_jupyter/dependencies b/build/pkgs/gap_jupyter/dependencies index 41133c3ff0a..89f9b88dd92 100644 --- a/build/pkgs/gap_jupyter/dependencies +++ b/build/pkgs/gap_jupyter/dependencies @@ -1 +1 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython gap + | $(PYTHON_TOOLCHAIN) ipython gap $(PYTHON) diff --git a/build/pkgs/gast/checksums.ini b/build/pkgs/gast/checksums.ini index 1aa653229f2..57bc0736a13 100644 --- a/build/pkgs/gast/checksums.ini +++ b/build/pkgs/gast/checksums.ini @@ -1,5 +1,5 @@ tarball=gast-VERSION.tar.gz -sha1=a84811eedebc5bca94b4eae978aab5f2c805b106 -md5=fdff900805e03e9dd76d377eb4cbaed7 -cksum=387443419 +sha1=6c113cf8d33cc654d33210335103485ab41d3dbb +md5=907c689e3fdbc7a48cc010e665195baa +cksum=218846575 upstream_url=https://pypi.io/packages/source/g/gast/gast-VERSION.tar.gz diff --git a/build/pkgs/gast/dependencies b/build/pkgs/gast/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/gast/dependencies +++ b/build/pkgs/gast/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gast/distros/gentoo.txt b/build/pkgs/gast/distros/gentoo.txt new file mode 100644 index 00000000000..3be5e7e785c --- /dev/null +++ b/build/pkgs/gast/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/gast diff --git a/build/pkgs/gast/package-version.txt b/build/pkgs/gast/package-version.txt index be14282b7ff..7d8568351b4 100644 --- a/build/pkgs/gast/package-version.txt +++ b/build/pkgs/gast/package-version.txt @@ -1 +1 @@ -0.5.3 +0.5.4 diff --git a/build/pkgs/gast/spkg-configure.m4 b/build/pkgs/gast/spkg-configure.m4 new file mode 100644 index 00000000000..26ec59feaee --- /dev/null +++ b/build/pkgs/gast/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([gast], [SAGE_PYTHON_PACKAGE_CHECK([gast])]) diff --git a/build/pkgs/gc/SPKG.rst b/build/pkgs/gc/SPKG.rst index ece6b70d3e6..ee778eb5fcd 100644 --- a/build/pkgs/gc/SPKG.rst +++ b/build/pkgs/gc/SPKG.rst @@ -6,25 +6,24 @@ Description The Boehm-Demers-Weiser conservative garbage collector. + License ------- -- Permissive BSD + GPL 2.0+ +- MIT-style (https://github.com/ivmai/bdwgc/blob/master/LICENSE) Upstream Contact ---------------- -Webpage: http://www.hboehm.info/gc/ +- Ivan Maidanski + +Webpage: +- https://github.com/ivmai/bdwgc/ +- https://www.hboehm.info/gc/ -Email List: bdwgc@lists.opendylan.org Special Update/Build Instructions --------------------------------- None. - -Patches -~~~~~~~ - -- cygwin64.patch: let libgc build on Cygwin64. diff --git a/build/pkgs/gc/checksums.ini b/build/pkgs/gc/checksums.ini index 628ecde3d37..828d7e35d93 100644 --- a/build/pkgs/gc/checksums.ini +++ b/build/pkgs/gc/checksums.ini @@ -1,5 +1,5 @@ tarball=gc-VERSION.tar.gz -sha1=4b8b24534f469b64ff4bc2332a9bdf8bef8bf1d4 -md5=67a5093e2f9f381bd550aa891d00b54b -cksum=121524068 +sha1=41c88cbc4bc9bf76e1a95a1500ea5b0360bc4f55 +md5=8901a6ed29ac35842420054772ea3441 +cksum=4201205407 upstream_url=https://github.com/ivmai/bdwgc/releases/download/vVERSION/gc-VERSION.tar.gz diff --git a/build/pkgs/gc/package-version.txt b/build/pkgs/gc/package-version.txt index 50c496d20c6..11cb5b746c0 100644 --- a/build/pkgs/gc/package-version.txt +++ b/build/pkgs/gc/package-version.txt @@ -1 +1 @@ -8.0.4 +8.2.4 diff --git a/build/pkgs/gc/spkg-install.in b/build/pkgs/gc/spkg-install.in index 4acf5cf8b19..f42295bb279 100644 --- a/build/pkgs/gc/spkg-install.in +++ b/build/pkgs/gc/spkg-install.in @@ -4,9 +4,7 @@ GC_CONFIGURE="--enable-large-config" if [ "$UNAME" = "CYGWIN" ]; then # See https://github.com/sagemath/sage/issues/22694 - GC_CONFIGURE="$GC_CONFIGURE --enable-threads=posix --enable-handle-fork --enable-shared --disable-static" - # Force use of mmap on Cygwin https://github.com/sagemath/sage/issues/23973 - export CFLAGS="$CFLAGS -DUSE_MMAP -DUSE_MUNMAP" + GC_CONFIGURE="$GC_CONFIGURE --enable-threads=posix --enable-handle-fork" fi sdh_configure $GC_CONFIGURE diff --git a/build/pkgs/gcc/SPKG.rst b/build/pkgs/gcc/SPKG.rst index 75feee2d6d8..1f90eb0bf67 100644 --- a/build/pkgs/gcc/SPKG.rst +++ b/build/pkgs/gcc/SPKG.rst @@ -6,7 +6,7 @@ Description This package represents the required C and C++ compilers. -- GCC (GNU Compiler Collection) versions 8.x to 12.x are supported. +- GCC (GNU Compiler Collection) versions 8.x (>= 8.4.0) to 13.x are supported. - Clang (LLVM) is also supported. @@ -25,7 +25,7 @@ need to run:: Vendor and versions of the C and C++ compilers should match. Users of older Linux distributions (in particular, ``ubuntu-xenial`` -or older, ``debian-stretch`` or older, ``linuxmint-18`` or older) +or older, ``debian-buster`` or older, ``linuxmint-18`` or older) should upgrade their systems before attempting to install Sage from source. Users of ``ubuntu-bionic``, ``linuxmint-19.x``, and ``opensuse-15.x`` can install a versioned ``gcc`` system package diff --git a/build/pkgs/gcc/spkg-configure.m4 b/build/pkgs/gcc/spkg-configure.m4 index 34953c32302..e1b44ec1c9d 100644 --- a/build/pkgs/gcc/spkg-configure.m4 +++ b/build/pkgs/gcc/spkg-configure.m4 @@ -161,8 +161,8 @@ SAGE_SPKG_CONFIGURE_BASE([gcc], [ # Add the .0 because Debian/Ubuntu gives version numbers like # 4.6 instead of 4.6.4 (Trac #18885) AS_CASE(["$GXX_VERSION.0"], - [[[0-7]].*], [ - # Install our own GCC if the system-provided one is older than gcc 8 + [[[0-7]].*|8.[[0-3]].*], [ + # Install our own GCC if the system-provided one is older than gcc 8.4 SAGE_SHOULD_INSTALL_GCC([you have $CXX version $GXX_VERSION, which is quite old]) ], [1[[4-9]].*], [ diff --git a/build/pkgs/gdb/dependencies b/build/pkgs/gdb/dependencies index bdf81f77180..cf6822bb92e 100644 --- a/build/pkgs/gdb/dependencies +++ b/build/pkgs/gdb/dependencies @@ -1,4 +1,4 @@ -mpfr zlib ncurses $(PYTHON) xz +mpfr zlib ncurses xz | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gitpython/dependencies b/build/pkgs/gitpython/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/gitpython/dependencies +++ b/build/pkgs/gitpython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gmpy2/dependencies b/build/pkgs/gmpy2/dependencies index 98c6065dc87..b1f92b9241d 100644 --- a/build/pkgs/gmpy2/dependencies +++ b/build/pkgs/gmpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(MP_LIBRARY) mpfr mpc | $(PYTHON_TOOLCHAIN) + $(MP_LIBRARY) mpfr mpc | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/gmpy2/distros/arch.txt b/build/pkgs/gmpy2/distros/arch.txt new file mode 100644 index 00000000000..d4464a5ce2c --- /dev/null +++ b/build/pkgs/gmpy2/distros/arch.txt @@ -0,0 +1 @@ +python-gmpy2 diff --git a/build/pkgs/gmpy2/distros/debian.txt b/build/pkgs/gmpy2/distros/debian.txt new file mode 100644 index 00000000000..afdd6281722 --- /dev/null +++ b/build/pkgs/gmpy2/distros/debian.txt @@ -0,0 +1 @@ +python3-gmpy2 diff --git a/build/pkgs/gmpy2/distros/fedora.txt b/build/pkgs/gmpy2/distros/fedora.txt new file mode 100644 index 00000000000..d4464a5ce2c --- /dev/null +++ b/build/pkgs/gmpy2/distros/fedora.txt @@ -0,0 +1 @@ +python-gmpy2 diff --git a/build/pkgs/gmpy2/distros/freebsd.txt b/build/pkgs/gmpy2/distros/freebsd.txt new file mode 100644 index 00000000000..0d9d2c435a6 --- /dev/null +++ b/build/pkgs/gmpy2/distros/freebsd.txt @@ -0,0 +1 @@ +math/py-gmpy2 diff --git a/build/pkgs/gmpy2/distros/gentoo.txt b/build/pkgs/gmpy2/distros/gentoo.txt new file mode 100644 index 00000000000..519f9d8729a --- /dev/null +++ b/build/pkgs/gmpy2/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/gmpy diff --git a/build/pkgs/gmpy2/distros/opensuse.txt b/build/pkgs/gmpy2/distros/opensuse.txt new file mode 100644 index 00000000000..36d52b88ba6 --- /dev/null +++ b/build/pkgs/gmpy2/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-gmpy2 diff --git a/build/pkgs/gmpy2/spkg-configure.m4 b/build/pkgs/gmpy2/spkg-configure.m4 new file mode 100644 index 00000000000..2d0390f7db3 --- /dev/null +++ b/build/pkgs/gmpy2/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([gmpy2], [SAGE_PYTHON_PACKAGE_CHECK([gmpy2])]) diff --git a/build/pkgs/hatch_fancy_pypi_readme/dependencies b/build/pkgs/hatch_fancy_pypi_readme/dependencies index 8cd44d06682..cfb7c484697 100644 --- a/build/pkgs/hatch_fancy_pypi_readme/dependencies +++ b/build/pkgs/hatch_fancy_pypi_readme/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) hatchling + | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/hatch_nodejs_version/dependencies b/build/pkgs/hatch_nodejs_version/dependencies index e9293f104ca..85e8893f785 100644 --- a/build/pkgs/hatch_nodejs_version/dependencies +++ b/build/pkgs/hatch_nodejs_version/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) hatchling | $(PYTHON_TOOLCHAIN) + hatchling | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/hatch_vcs/dependencies b/build/pkgs/hatch_vcs/dependencies index 8cd44d06682..cfb7c484697 100644 --- a/build/pkgs/hatch_vcs/dependencies +++ b/build/pkgs/hatch_vcs/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) hatchling + | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/hatchling/dependencies b/build/pkgs/hatchling/dependencies index 84b5ea48ccc..4c10ae56e2e 100644 --- a/build/pkgs/hatchling/dependencies +++ b/build/pkgs/hatchling/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pathspec tomli editables pluggy packaging | $(PYTHON_TOOLCHAIN) + pathspec tomli editables pluggy packaging | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/hatchling/distros/gentoo.txt b/build/pkgs/hatchling/distros/gentoo.txt new file mode 100644 index 00000000000..24842db3e5a --- /dev/null +++ b/build/pkgs/hatchling/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/hatchling diff --git a/build/pkgs/hatchling/spkg-configure.m4 b/build/pkgs/hatchling/spkg-configure.m4 new file mode 100644 index 00000000000..d03747f230b --- /dev/null +++ b/build/pkgs/hatchling/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([hatchling], [SAGE_PYTHON_PACKAGE_CHECK([hatchling])]) diff --git a/build/pkgs/html5lib/SPKG.rst b/build/pkgs/html5lib/SPKG.rst deleted file mode 100644 index c0abaca59f3..00000000000 --- a/build/pkgs/html5lib/SPKG.rst +++ /dev/null @@ -1,19 +0,0 @@ -html5lib: An HTML parser -======================== - -Description ------------ - -HTML parser based on the WHATWG HTML specification. - -License -------- - -MIT License - - -Upstream Contact ----------------- - -Home Page: https://github.com/html5lib/html5lib-python/issues - diff --git a/build/pkgs/html5lib/checksums.ini b/build/pkgs/html5lib/checksums.ini deleted file mode 100644 index 13cb3b0d87f..00000000000 --- a/build/pkgs/html5lib/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=html5lib-VERSION.tar.gz -sha1=6d1348b6356b62305e4a410df9dfd02143d841a1 -md5=6748742e2ec4cb99287a6bc82bcfe2b0 -cksum=3263889571 -upstream_url=https://pypi.io/packages/source/h/html5lib/html5lib-VERSION.tar.gz diff --git a/build/pkgs/html5lib/distros/conda.txt b/build/pkgs/html5lib/distros/conda.txt deleted file mode 100644 index 6bcef8ab7d4..00000000000 --- a/build/pkgs/html5lib/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -html5lib diff --git a/build/pkgs/html5lib/distros/macports.txt b/build/pkgs/html5lib/distros/macports.txt deleted file mode 100644 index b11ce6f9dad..00000000000 --- a/build/pkgs/html5lib/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -py-html5lib diff --git a/build/pkgs/html5lib/distros/repology.txt b/build/pkgs/html5lib/distros/repology.txt deleted file mode 100644 index 52080964da2..00000000000 --- a/build/pkgs/html5lib/distros/repology.txt +++ /dev/null @@ -1,2 +0,0 @@ -html5lib -python:html5lib diff --git a/build/pkgs/html5lib/distros/void.txt b/build/pkgs/html5lib/distros/void.txt deleted file mode 100644 index 6d7b8dfb001..00000000000 --- a/build/pkgs/html5lib/distros/void.txt +++ /dev/null @@ -1 +0,0 @@ -python3-html5lib diff --git a/build/pkgs/html5lib/install-requires.txt b/build/pkgs/html5lib/install-requires.txt deleted file mode 100644 index f71f129272c..00000000000 --- a/build/pkgs/html5lib/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -html5lib >=1.0.1 diff --git a/build/pkgs/html5lib/package-version.txt b/build/pkgs/html5lib/package-version.txt deleted file mode 100644 index 9459d4ba2a0..00000000000 --- a/build/pkgs/html5lib/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.1 diff --git a/build/pkgs/html5lib/spkg-install.in b/build/pkgs/html5lib/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/html5lib/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/idna/dependencies b/build/pkgs/idna/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/idna/dependencies +++ b/build/pkgs/idna/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/idna/distros/arch.txt b/build/pkgs/idna/distros/arch.txt new file mode 100644 index 00000000000..a73e70cade0 --- /dev/null +++ b/build/pkgs/idna/distros/arch.txt @@ -0,0 +1 @@ +python-idna diff --git a/build/pkgs/idna/distros/debian.txt b/build/pkgs/idna/distros/debian.txt new file mode 100644 index 00000000000..de48e70887b --- /dev/null +++ b/build/pkgs/idna/distros/debian.txt @@ -0,0 +1 @@ +python3-idna diff --git a/build/pkgs/idna/distros/fedora.txt b/build/pkgs/idna/distros/fedora.txt new file mode 100644 index 00000000000..a73e70cade0 --- /dev/null +++ b/build/pkgs/idna/distros/fedora.txt @@ -0,0 +1 @@ +python-idna diff --git a/build/pkgs/idna/distros/gentoo.txt b/build/pkgs/idna/distros/gentoo.txt new file mode 100644 index 00000000000..68ef51c453e --- /dev/null +++ b/build/pkgs/idna/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/idna diff --git a/build/pkgs/idna/distros/opensuse.txt b/build/pkgs/idna/distros/opensuse.txt new file mode 100644 index 00000000000..ea8400fa563 --- /dev/null +++ b/build/pkgs/idna/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-idna diff --git a/build/pkgs/idna/spkg-configure.m4 b/build/pkgs/idna/spkg-configure.m4 new file mode 100644 index 00000000000..9d363f212e6 --- /dev/null +++ b/build/pkgs/idna/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([idna], [SAGE_PYTHON_PACKAGE_CHECK([idna])]) diff --git a/build/pkgs/imagesize/dependencies b/build/pkgs/imagesize/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/imagesize/dependencies +++ b/build/pkgs/imagesize/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/imagesize/distros/gentoo.txt b/build/pkgs/imagesize/distros/gentoo.txt new file mode 100644 index 00000000000..54350ba2642 --- /dev/null +++ b/build/pkgs/imagesize/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/imagesize diff --git a/build/pkgs/imagesize/spkg-configure.m4 b/build/pkgs/imagesize/spkg-configure.m4 new file mode 100644 index 00000000000..20210eff2f0 --- /dev/null +++ b/build/pkgs/imagesize/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([imagesize], [SAGE_PYTHON_PACKAGE_CHECK([imagesize])]) diff --git a/build/pkgs/importlib_metadata/dependencies b/build/pkgs/importlib_metadata/dependencies index 77aa2a42f93..3c8d3aeb24e 100644 --- a/build/pkgs/importlib_metadata/dependencies +++ b/build/pkgs/importlib_metadata/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) zipp typing_extensions | $(PYTHON_TOOLCHAIN) tomli + zipp typing_extensions | $(PYTHON_TOOLCHAIN) tomli $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/importlib_metadata/distros/arch.txt b/build/pkgs/importlib_metadata/distros/arch.txt new file mode 100644 index 00000000000..b3c206287ec --- /dev/null +++ b/build/pkgs/importlib_metadata/distros/arch.txt @@ -0,0 +1 @@ +python-importlib-metadata diff --git a/build/pkgs/importlib_metadata/distros/debian.txt b/build/pkgs/importlib_metadata/distros/debian.txt new file mode 100644 index 00000000000..c005bf38793 --- /dev/null +++ b/build/pkgs/importlib_metadata/distros/debian.txt @@ -0,0 +1 @@ +python3-importlib-metadata diff --git a/build/pkgs/importlib_metadata/distros/fedora.txt b/build/pkgs/importlib_metadata/distros/fedora.txt new file mode 100644 index 00000000000..b3c206287ec --- /dev/null +++ b/build/pkgs/importlib_metadata/distros/fedora.txt @@ -0,0 +1 @@ +python-importlib-metadata diff --git a/build/pkgs/importlib_metadata/distros/freebsd.txt b/build/pkgs/importlib_metadata/distros/freebsd.txt new file mode 100644 index 00000000000..23518da7cff --- /dev/null +++ b/build/pkgs/importlib_metadata/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-importlib-metadata diff --git a/build/pkgs/importlib_metadata/distros/gentoo.txt b/build/pkgs/importlib_metadata/distros/gentoo.txt new file mode 100644 index 00000000000..4f927864c2b --- /dev/null +++ b/build/pkgs/importlib_metadata/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/importlib_metadata diff --git a/build/pkgs/importlib_metadata/distros/opensuse.txt b/build/pkgs/importlib_metadata/distros/opensuse.txt new file mode 100644 index 00000000000..7a665131cd4 --- /dev/null +++ b/build/pkgs/importlib_metadata/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-importlib-metadata diff --git a/build/pkgs/importlib_metadata/spkg-configure.m4 b/build/pkgs/importlib_metadata/spkg-configure.m4 new file mode 100644 index 00000000000..0554e522252 --- /dev/null +++ b/build/pkgs/importlib_metadata/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([importlib_metadata], [ + SAGE_PYTHON_PACKAGE_CHECK([importlib_metadata]) +]) diff --git a/build/pkgs/importlib_resources/dependencies b/build/pkgs/importlib_resources/dependencies index 58927ab6f75..655283898b7 100644 --- a/build/pkgs/importlib_resources/dependencies +++ b/build/pkgs/importlib_resources/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) zipp | $(PYTHON_TOOLCHAIN) + zipp | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/importlib_resources/distros/gentoo.txt b/build/pkgs/importlib_resources/distros/gentoo.txt new file mode 100644 index 00000000000..d5e1f2cf6a8 --- /dev/null +++ b/build/pkgs/importlib_resources/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/importlib_resources diff --git a/build/pkgs/importlib_resources/spkg-configure.m4 b/build/pkgs/importlib_resources/spkg-configure.m4 new file mode 100644 index 00000000000..50df55b4643 --- /dev/null +++ b/build/pkgs/importlib_resources/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([importlib_resources], [ + SAGE_PYTHON_PACKAGE_CHECK([importlib_resources]) +]) diff --git a/build/pkgs/ipykernel/dependencies b/build/pkgs/ipykernel/dependencies index 792c3e70634..7e153a0cb46 100644 --- a/build/pkgs/ipykernel/dependencies +++ b/build/pkgs/ipykernel/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) ipython_genutils importlib_metadata matplotlib_inline ipython jupyter_client tornado appnope traitlets executing | $(PYTHON_TOOLCHAIN) + ipython_genutils importlib_metadata matplotlib_inline ipython jupyter_client tornado appnope traitlets executing | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipykernel/distros/arch.txt b/build/pkgs/ipykernel/distros/arch.txt new file mode 100644 index 00000000000..286458797f7 --- /dev/null +++ b/build/pkgs/ipykernel/distros/arch.txt @@ -0,0 +1 @@ +python-ipykernel diff --git a/build/pkgs/ipykernel/distros/debian.txt b/build/pkgs/ipykernel/distros/debian.txt new file mode 100644 index 00000000000..d919f6f3190 --- /dev/null +++ b/build/pkgs/ipykernel/distros/debian.txt @@ -0,0 +1 @@ +ipykernel diff --git a/build/pkgs/ipykernel/distros/fedora.txt b/build/pkgs/ipykernel/distros/fedora.txt new file mode 100644 index 00000000000..286458797f7 --- /dev/null +++ b/build/pkgs/ipykernel/distros/fedora.txt @@ -0,0 +1 @@ +python-ipykernel diff --git a/build/pkgs/ipykernel/distros/freebsd.txt b/build/pkgs/ipykernel/distros/freebsd.txt new file mode 100644 index 00000000000..92235f132be --- /dev/null +++ b/build/pkgs/ipykernel/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-ipykernel diff --git a/build/pkgs/ipykernel/distros/gentoo.txt b/build/pkgs/ipykernel/distros/gentoo.txt new file mode 100644 index 00000000000..88aab61ef39 --- /dev/null +++ b/build/pkgs/ipykernel/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/ipykernel diff --git a/build/pkgs/ipykernel/distros/opensuse.txt b/build/pkgs/ipykernel/distros/opensuse.txt new file mode 100644 index 00000000000..1485db27e0d --- /dev/null +++ b/build/pkgs/ipykernel/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-ipykernel diff --git a/build/pkgs/ipykernel/spkg-configure.m4 b/build/pkgs/ipykernel/spkg-configure.m4 new file mode 100644 index 00000000000..94ecc2dcc4e --- /dev/null +++ b/build/pkgs/ipykernel/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([ipykernel], [SAGE_PYTHON_PACKAGE_CHECK([ipykernel])]) diff --git a/build/pkgs/ipympl/dependencies b/build/pkgs/ipympl/dependencies index 05d47407b15..90b85bcfdbc 100644 --- a/build/pkgs/ipympl/dependencies +++ b/build/pkgs/ipympl/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) ipywidgets matplotlib ipykernel | $(PYTHON_TOOLCHAIN) jupyter_packaging + ipywidgets matplotlib ipykernel | $(PYTHON_TOOLCHAIN) jupyter_packaging $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipython/dependencies b/build/pkgs/ipython/dependencies index 38dad7b80ee..6e3be0a2a95 100644 --- a/build/pkgs/ipython/dependencies +++ b/build/pkgs/ipython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jinja2 tornado pyzmq pickleshare simplegeneric traitlets decorator wcwidth prompt_toolkit pygments pexpect appnope backcall jedi stack_data | $(PYTHON_TOOLCHAIN) +tornado pyzmq pickleshare simplegeneric traitlets decorator wcwidth prompt_toolkit pygments pexpect appnope backcall jedi stack_data | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipython/distros/arch.txt b/build/pkgs/ipython/distros/arch.txt new file mode 100644 index 00000000000..49a7ffe2a95 --- /dev/null +++ b/build/pkgs/ipython/distros/arch.txt @@ -0,0 +1 @@ +ipython diff --git a/build/pkgs/ipython/distros/debian.txt b/build/pkgs/ipython/distros/debian.txt new file mode 100644 index 00000000000..c32c6b449cf --- /dev/null +++ b/build/pkgs/ipython/distros/debian.txt @@ -0,0 +1 @@ +python3-ipython diff --git a/build/pkgs/ipython/distros/fedora.txt b/build/pkgs/ipython/distros/fedora.txt new file mode 100644 index 00000000000..49a7ffe2a95 --- /dev/null +++ b/build/pkgs/ipython/distros/fedora.txt @@ -0,0 +1 @@ +ipython diff --git a/build/pkgs/ipython/distros/freebsd.txt b/build/pkgs/ipython/distros/freebsd.txt new file mode 100644 index 00000000000..3252ee7fbc1 --- /dev/null +++ b/build/pkgs/ipython/distros/freebsd.txt @@ -0,0 +1 @@ +devel/ipython diff --git a/build/pkgs/ipython/distros/gentoo.txt b/build/pkgs/ipython/distros/gentoo.txt new file mode 100644 index 00000000000..8b76f186ff8 --- /dev/null +++ b/build/pkgs/ipython/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/ipython diff --git a/build/pkgs/ipython/distros/opensuse.txt b/build/pkgs/ipython/distros/opensuse.txt index c32c6b449cf..32aac30ae1e 100644 --- a/build/pkgs/ipython/distros/opensuse.txt +++ b/build/pkgs/ipython/distros/opensuse.txt @@ -1 +1 @@ -python3-ipython +python3${PYTHON_MINOR}-ipython diff --git a/build/pkgs/ipython/install-requires.txt b/build/pkgs/ipython/install-requires.txt index a52df49c421..03d4a4f3413 100644 --- a/build/pkgs/ipython/install-requires.txt +++ b/build/pkgs/ipython/install-requires.txt @@ -1 +1,2 @@ -ipython >=7.13.0 +ipython >=7.13.0, <8.9.0 +# ipython >= 8.9.0 requires prompt_toolkit too new for Sage diff --git a/build/pkgs/ipython/spkg-configure.m4 b/build/pkgs/ipython/spkg-configure.m4 new file mode 100644 index 00000000000..02ab89f5193 --- /dev/null +++ b/build/pkgs/ipython/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([ipython], [SAGE_PYTHON_PACKAGE_CHECK([ipython])]) diff --git a/build/pkgs/ipython_genutils/dependencies b/build/pkgs/ipython_genutils/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/ipython_genutils/dependencies +++ b/build/pkgs/ipython_genutils/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipython_genutils/distros/gentoo.txt b/build/pkgs/ipython_genutils/distros/gentoo.txt new file mode 100644 index 00000000000..01bc49d4e1a --- /dev/null +++ b/build/pkgs/ipython_genutils/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/ipython_genutils diff --git a/build/pkgs/ipython_genutils/spkg-configure.m4 b/build/pkgs/ipython_genutils/spkg-configure.m4 new file mode 100644 index 00000000000..b0ba86ac7a3 --- /dev/null +++ b/build/pkgs/ipython_genutils/spkg-configure.m4 @@ -0,0 +1,4 @@ +SAGE_SPKG_CONFIGURE( + [ipython_genutils], + [SAGE_PYTHON_PACKAGE_CHECK([ipython_genutils])] +) diff --git a/build/pkgs/ipywidgets/dependencies b/build/pkgs/ipywidgets/dependencies index 64f5151c754..bcb4e030b7d 100644 --- a/build/pkgs/ipywidgets/dependencies +++ b/build/pkgs/ipywidgets/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) widgetsnbextension jupyterlab_widgets | $(PYTHON_TOOLCHAIN) ipykernel ipython traitlets + widgetsnbextension jupyterlab_widgets | $(PYTHON_TOOLCHAIN) ipykernel ipython traitlets $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipywidgets/distros/gentoo.txt b/build/pkgs/ipywidgets/distros/gentoo.txt new file mode 100644 index 00000000000..7c76967c65b --- /dev/null +++ b/build/pkgs/ipywidgets/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/ipywidgets diff --git a/build/pkgs/ipywidgets/spkg-configure.m4 b/build/pkgs/ipywidgets/spkg-configure.m4 new file mode 100644 index 00000000000..51ca9be74db --- /dev/null +++ b/build/pkgs/ipywidgets/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([ipywidgets], [SAGE_PYTHON_PACKAGE_CHECK([ipywidgets])]) diff --git a/build/pkgs/jedi/dependencies b/build/pkgs/jedi/dependencies index 60b5f820a37..0e2212bd149 100644 --- a/build/pkgs/jedi/dependencies +++ b/build/pkgs/jedi/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) parso | $(PYTHON_TOOLCHAIN) + parso | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jedi/distros/gentoo.txt b/build/pkgs/jedi/distros/gentoo.txt new file mode 100644 index 00000000000..6c85a46cfcb --- /dev/null +++ b/build/pkgs/jedi/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/jedi diff --git a/build/pkgs/jedi/spkg-configure.m4 b/build/pkgs/jedi/spkg-configure.m4 new file mode 100644 index 00000000000..a37dbcc92db --- /dev/null +++ b/build/pkgs/jedi/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([jedi], [SAGE_PYTHON_PACKAGE_CHECK([jedi])]) diff --git a/build/pkgs/jinja2/dependencies b/build/pkgs/jinja2/dependencies index 6947978ec42..151ae9767d1 100644 --- a/build/pkgs/jinja2/dependencies +++ b/build/pkgs/jinja2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) markupsafe docutils | $(PYTHON_TOOLCHAIN) + markupsafe docutils | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jinja2/distros/debian.txt b/build/pkgs/jinja2/distros/debian.txt new file mode 100644 index 00000000000..f2db865ab36 --- /dev/null +++ b/build/pkgs/jinja2/distros/debian.txt @@ -0,0 +1 @@ +python3-jinja2 diff --git a/build/pkgs/jinja2/distros/fedora.txt b/build/pkgs/jinja2/distros/fedora.txt new file mode 100644 index 00000000000..f5f3caf99cc --- /dev/null +++ b/build/pkgs/jinja2/distros/fedora.txt @@ -0,0 +1 @@ +python-jinja2 diff --git a/build/pkgs/jinja2/distros/gentoo.txt b/build/pkgs/jinja2/distros/gentoo.txt new file mode 100644 index 00000000000..15a27aecd44 --- /dev/null +++ b/build/pkgs/jinja2/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/jinja diff --git a/build/pkgs/jinja2/distros/opensuse.txt b/build/pkgs/jinja2/distros/opensuse.txt index 5d90a223f55..8ad585a7ef3 100644 --- a/build/pkgs/jinja2/distros/opensuse.txt +++ b/build/pkgs/jinja2/distros/opensuse.txt @@ -1 +1 @@ -python3-Jinja2 +python3${PYTHON_MINOR}-jinja2 diff --git a/build/pkgs/jinja2/install-requires.txt b/build/pkgs/jinja2/install-requires.txt index 99d8e6ecd6e..829d4c266d3 100644 --- a/build/pkgs/jinja2/install-requires.txt +++ b/build/pkgs/jinja2/install-requires.txt @@ -1 +1,2 @@ -jinja2 >=2.11.2 +jinja2 >=3.0 +# for sphinx diff --git a/build/pkgs/jinja2/spkg-configure.m4 b/build/pkgs/jinja2/spkg-configure.m4 new file mode 100644 index 00000000000..0970d1c8bea --- /dev/null +++ b/build/pkgs/jinja2/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([jinja2], [SAGE_PYTHON_PACKAGE_CHECK([jinja2])]) diff --git a/build/pkgs/jsonschema/dependencies b/build/pkgs/jsonschema/dependencies index 51698156cf0..d0211604157 100644 --- a/build/pkgs/jsonschema/dependencies +++ b/build/pkgs/jsonschema/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) vcversioner attrs importlib_metadata pyrsistent | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs hatch_fancy_pypi_readme + vcversioner attrs importlib_metadata pyrsistent | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs hatch_fancy_pypi_readme $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jsonschema/distros/arch.txt b/build/pkgs/jsonschema/distros/arch.txt new file mode 100644 index 00000000000..8943c30f9ed --- /dev/null +++ b/build/pkgs/jsonschema/distros/arch.txt @@ -0,0 +1 @@ +python-jsonschema diff --git a/build/pkgs/jsonschema/distros/debian.txt b/build/pkgs/jsonschema/distros/debian.txt new file mode 100644 index 00000000000..047e6cc5d1d --- /dev/null +++ b/build/pkgs/jsonschema/distros/debian.txt @@ -0,0 +1 @@ +python3-jsonschema diff --git a/build/pkgs/jsonschema/distros/fedora.txt b/build/pkgs/jsonschema/distros/fedora.txt new file mode 100644 index 00000000000..8943c30f9ed --- /dev/null +++ b/build/pkgs/jsonschema/distros/fedora.txt @@ -0,0 +1 @@ +python-jsonschema diff --git a/build/pkgs/jsonschema/distros/gentoo.txt b/build/pkgs/jsonschema/distros/gentoo.txt new file mode 100644 index 00000000000..d708e4c9990 --- /dev/null +++ b/build/pkgs/jsonschema/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/jsonschema diff --git a/build/pkgs/jsonschema/distros/opensuse.txt b/build/pkgs/jsonschema/distros/opensuse.txt index 047e6cc5d1d..2a587a55946 100644 --- a/build/pkgs/jsonschema/distros/opensuse.txt +++ b/build/pkgs/jsonschema/distros/opensuse.txt @@ -1 +1 @@ -python3-jsonschema +python3${PYTHON_MINOR}-jsonschema diff --git a/build/pkgs/jsonschema/spkg-configure.m4 b/build/pkgs/jsonschema/spkg-configure.m4 new file mode 100644 index 00000000000..b9e5e216a3b --- /dev/null +++ b/build/pkgs/jsonschema/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([jsonschema], [SAGE_PYTHON_PACKAGE_CHECK([jsonschema])]) diff --git a/build/pkgs/jupymake/dependencies b/build/pkgs/jupymake/dependencies index c8ed956ad6a..aa714006aae 100644 --- a/build/pkgs/jupymake/dependencies +++ b/build/pkgs/jupymake/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) polymake | $(PYTHON_TOOLCHAIN) + polymake | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_client/dependencies b/build/pkgs/jupyter_client/dependencies index 29d5d3b6bf3..dcc8c256fad 100644 --- a/build/pkgs/jupyter_client/dependencies +++ b/build/pkgs/jupyter_client/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jupyter_core | $(PYTHON_TOOLCHAIN) pyzmq dateutil nest_asyncio tornado traitlets entrypoints hatchling + jupyter_core | $(PYTHON_TOOLCHAIN) pyzmq dateutil nest_asyncio tornado traitlets entrypoints hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_client/distros/gentoo.txt b/build/pkgs/jupyter_client/distros/gentoo.txt new file mode 100644 index 00000000000..4f1de883ca1 --- /dev/null +++ b/build/pkgs/jupyter_client/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/jupyter_client diff --git a/build/pkgs/jupyter_client/distros/opensuse.txt b/build/pkgs/jupyter_client/distros/opensuse.txt index 0159b2d7b90..a1e21956a79 100644 --- a/build/pkgs/jupyter_client/distros/opensuse.txt +++ b/build/pkgs/jupyter_client/distros/opensuse.txt @@ -1 +1 @@ -python3-jupyter-client +python3${PYTHON_MINOR}-jupyter-client diff --git a/build/pkgs/jupyter_client/spkg-configure.m4 b/build/pkgs/jupyter_client/spkg-configure.m4 new file mode 100644 index 00000000000..fbd34982c14 --- /dev/null +++ b/build/pkgs/jupyter_client/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_client], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_client]) +]) diff --git a/build/pkgs/jupyter_core/checksums.ini b/build/pkgs/jupyter_core/checksums.ini index 5a49b040b98..3e45d122068 100644 --- a/build/pkgs/jupyter_core/checksums.ini +++ b/build/pkgs/jupyter_core/checksums.ini @@ -1,5 +1,5 @@ tarball=jupyter_core-VERSION.tar.gz -sha1=6e48f90477c11ad41b9404732a2bdcb485f4e630 -md5=84d207d4c48513a2b87ff2ed508beb98 -cksum=2072829465 +sha1=2a0a14c4c1624826100d59169636bb588465deb9 +md5=7586526dd4ca9d1bc820a4a5429df48b +cksum=1776144013 upstream_url=https://pypi.io/packages/source/j/jupyter_core/jupyter_core-VERSION.tar.gz diff --git a/build/pkgs/jupyter_core/dependencies b/build/pkgs/jupyter_core/dependencies index 6aeda10f20d..a312196cbed 100644 --- a/build/pkgs/jupyter_core/dependencies +++ b/build/pkgs/jupyter_core/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) traitlets + traitlets | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_core/distros/gentoo.txt b/build/pkgs/jupyter_core/distros/gentoo.txt new file mode 100644 index 00000000000..f168c5ad7ad --- /dev/null +++ b/build/pkgs/jupyter_core/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/jupyter_core diff --git a/build/pkgs/jupyter_core/distros/opensuse.txt b/build/pkgs/jupyter_core/distros/opensuse.txt index 2f316f2ee07..2c677674477 100644 --- a/build/pkgs/jupyter_core/distros/opensuse.txt +++ b/build/pkgs/jupyter_core/distros/opensuse.txt @@ -1 +1 @@ -python3-jupyter-core +python3${PYTHON_MINOR}-jupyter-core diff --git a/build/pkgs/jupyter_core/package-version.txt b/build/pkgs/jupyter_core/package-version.txt index 4f89fb96069..815588ef140 100644 --- a/build/pkgs/jupyter_core/package-version.txt +++ b/build/pkgs/jupyter_core/package-version.txt @@ -1 +1 @@ -4.11.2 +4.12.0 diff --git a/build/pkgs/jupyter_core/spkg-configure.m4 b/build/pkgs/jupyter_core/spkg-configure.m4 new file mode 100644 index 00000000000..67df9c38b5b --- /dev/null +++ b/build/pkgs/jupyter_core/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyter_core], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyter_core]) +]) diff --git a/build/pkgs/jupyter_jsmol/SPKG.rst b/build/pkgs/jupyter_jsmol/SPKG.rst index e318a86c7b1..64458e86b2d 100644 --- a/build/pkgs/jupyter_jsmol/SPKG.rst +++ b/build/pkgs/jupyter_jsmol/SPKG.rst @@ -9,7 +9,7 @@ JSmol viewer widget for Jupyter License ------- -BSD +MIT Upstream Contact ---------------- diff --git a/build/pkgs/jupyter_jsmol/checksums.ini b/build/pkgs/jupyter_jsmol/checksums.ini index 0ac16d6e78c..9ac2c41a8e4 100644 --- a/build/pkgs/jupyter_jsmol/checksums.ini +++ b/build/pkgs/jupyter_jsmol/checksums.ini @@ -1,5 +1,5 @@ -tarball=jupyter_jsmol-VERSION.tar.gz -sha1=6ba59de9d1df15b2a09a57f6bdf10f48f13af9ac -md5=90e9490414e7fbecc6013b4b051b06d7 -cksum=917919116 -upstream_url=https://pypi.io/packages/source/j/jupyter-jsmol/jupyter_jsmol-VERSION.tar.gz +tarball=jupyter_jsmol-VERSION-py2.py3-none-any.whl +sha1=b00f1ca76aaa906c7c0a43e36baf608183f3d552 +md5=dd786877513296a36a08518ad64ace47 +cksum=2135042898 +upstream_url=https://pypi.io/packages/py2.py3/j/jupyter_jsmol/jupyter_jsmol-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/jupyter_jsmol/dependencies b/build/pkgs/jupyter_jsmol/dependencies index a6d87526311..2c7683a6111 100644 --- a/build/pkgs/jupyter_jsmol/dependencies +++ b/build/pkgs/jupyter_jsmol/dependencies @@ -1,4 +1,4 @@ -ipywidgets jupyter_packaging $(PYTHON) | $(PYTHON_TOOLCHAIN) +ipywidgets | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_jsmol/install-requires.txt b/build/pkgs/jupyter_jsmol/install-requires.txt index 2df501ec9a8..9465bfb8e0c 100644 --- a/build/pkgs/jupyter_jsmol/install-requires.txt +++ b/build/pkgs/jupyter_jsmol/install-requires.txt @@ -1 +1 @@ -jupyter-jsmol >=2022.1.0 +jupyter-jsmol diff --git a/build/pkgs/jupyter_jsmol/spkg-install.in b/build/pkgs/jupyter_jsmol/spkg-install.in deleted file mode 100644 index 72d65dde8d5..00000000000 --- a/build/pkgs/jupyter_jsmol/spkg-install.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src -# Use --no-build-isolation because we have a different version of jupyter_packaging -eval sdh_pip_install --no-build-isolation --config-settings "--global-option=--skip-npm" . diff --git a/build/pkgs/jupyter_packaging/dependencies b/build/pkgs/jupyter_packaging/dependencies index 838afe13edf..11e420a0a7b 100644 --- a/build/pkgs/jupyter_packaging/dependencies +++ b/build/pkgs/jupyter_packaging/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) packaging deprecation tomlkit | $(PYTHON_TOOLCHAIN) hatchling + packaging deprecation tomlkit | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_sphinx/dependencies b/build/pkgs/jupyter_sphinx/dependencies index 785929f6ea8..37476f7a572 100644 --- a/build/pkgs/jupyter_sphinx/dependencies +++ b/build/pkgs/jupyter_sphinx/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) sphinx ipywidgets ipython nbconvert nbformat | $(PYTHON_TOOLCHAIN) + sphinx ipywidgets ipython nbconvert nbformat | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab/dependencies b/build/pkgs/jupyterlab/dependencies index 98ad2e94050..059006650e1 100644 --- a/build/pkgs/jupyterlab/dependencies +++ b/build/pkgs/jupyterlab/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) vcversioner jupyter_core jupyter_client jinja2 tornado ipython packaging terminado traitlets nbconvert send2trash nbformat prometheus_client ipython_genutils argon2_cffi pyzmq idna requests jsonschema babel notebook | $(PYTHON_TOOLCHAIN) + vcversioner jupyter_core jupyter_client jinja2 tornado ipython packaging terminado traitlets nbconvert send2trash nbformat prometheus_client ipython_genutils argon2_cffi pyzmq idna requests jsonschema babel notebook | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab_pygments/dependencies b/build/pkgs/jupyterlab_pygments/dependencies index a59532cdda1..fd3f15b7aa3 100644 --- a/build/pkgs/jupyterlab_pygments/dependencies +++ b/build/pkgs/jupyterlab_pygments/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pygments | $(PYTHON_TOOLCHAIN) + pygments | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab_pygments/distros/gentoo.txt b/build/pkgs/jupyterlab_pygments/distros/gentoo.txt new file mode 100644 index 00000000000..c57b4f13403 --- /dev/null +++ b/build/pkgs/jupyterlab_pygments/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/jupyterlab_pygments diff --git a/build/pkgs/jupyterlab_pygments/spkg-configure.m4 b/build/pkgs/jupyterlab_pygments/spkg-configure.m4 new file mode 100644 index 00000000000..e46e21f461e --- /dev/null +++ b/build/pkgs/jupyterlab_pygments/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([jupyterlab_pygments], [ + SAGE_PYTHON_PACKAGE_CHECK([jupyterlab_pygments]) +]) diff --git a/build/pkgs/jupyterlab_widgets/dependencies b/build/pkgs/jupyterlab_widgets/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/jupyterlab_widgets/dependencies +++ b/build/pkgs/jupyterlab_widgets/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab_widgets/distros/arch.txt b/build/pkgs/jupyterlab_widgets/distros/arch.txt new file mode 100644 index 00000000000..0800dc09838 --- /dev/null +++ b/build/pkgs/jupyterlab_widgets/distros/arch.txt @@ -0,0 +1 @@ +jupyterlab-widgets diff --git a/build/pkgs/jupyterlab_widgets/distros/freebsd.txt b/build/pkgs/jupyterlab_widgets/distros/freebsd.txt new file mode 100644 index 00000000000..6fc98fe86a0 --- /dev/null +++ b/build/pkgs/jupyterlab_widgets/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-jupyterlab-widgets diff --git a/build/pkgs/jupyterlab_widgets/distros/opensuse.txt b/build/pkgs/jupyterlab_widgets/distros/opensuse.txt new file mode 100644 index 00000000000..04706eee600 --- /dev/null +++ b/build/pkgs/jupyterlab_widgets/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-jupyterlab-widgets diff --git a/build/pkgs/kissat/checksums.ini b/build/pkgs/kissat/checksums.ini index 66b187bb599..85929110253 100644 --- a/build/pkgs/kissat/checksums.ini +++ b/build/pkgs/kissat/checksums.ini @@ -1,5 +1,5 @@ tarball=kissat-rel-VERSION.tar.gz -sha1=abfd971d5f560ed76281ed3ed7b75e20cb445618 -md5=6ef4b2efcc60c95a32581bfe59720154 -cksum=1532123399 +sha1=49972324939761306ee50cfa3df93cd3cd530256 +md5=1d0fa246c5451e3592910f2c9a5f3476 +cksum=2570717921 upstream_url=https://github.com/arminbiere/kissat/archive/refs/tags/rel-VERSION.tar.gz diff --git a/build/pkgs/kissat/package-version.txt b/build/pkgs/kissat/package-version.txt index 4a36342fcab..fd2a01863fd 100644 --- a/build/pkgs/kissat/package-version.txt +++ b/build/pkgs/kissat/package-version.txt @@ -1 +1 @@ -3.0.0 +3.1.0 diff --git a/build/pkgs/kiwisolver/dependencies b/build/pkgs/kiwisolver/dependencies index 5df13094620..1ba038a9b7a 100644 --- a/build/pkgs/kiwisolver/dependencies +++ b/build/pkgs/kiwisolver/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cppy | $(PYTHON_TOOLCHAIN) + cppy | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/kiwisolver/distros/gentoo.txt b/build/pkgs/kiwisolver/distros/gentoo.txt new file mode 100644 index 00000000000..7b30c9540ec --- /dev/null +++ b/build/pkgs/kiwisolver/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/kiwisolver diff --git a/build/pkgs/kiwisolver/spkg-configure.m4 b/build/pkgs/kiwisolver/spkg-configure.m4 new file mode 100644 index 00000000000..4e7ac97b57d --- /dev/null +++ b/build/pkgs/kiwisolver/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([kiwisolver], [SAGE_PYTHON_PACKAGE_CHECK([kiwisolver])]) diff --git a/build/pkgs/libatomic_ops/SPKG.rst b/build/pkgs/libatomic_ops/SPKG.rst index 5d376f67e91..daa139b9d1b 100644 --- a/build/pkgs/libatomic_ops/SPKG.rst +++ b/build/pkgs/libatomic_ops/SPKG.rst @@ -4,19 +4,21 @@ libatomic_ops: Access hardware-provided atomic memory update operations Description ----------- -A part of the Boehm-Demers-Weiser conservative garbage collector. +This package provides semi-portable access to hardware-provided +atomic memory update operations on a number of architectures. + License ------- -- Permissive BSD + GPL 2.0+ +- MIT + GPL 2.0+ Upstream Contact ---------------- -- Webpage: http://www.hboehm.info/gc/ -- Email List: bdwgc@lists.opendylan.org +https://github.com/ivmai/libatomic_ops/ + Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/libatomic_ops/checksums.ini b/build/pkgs/libatomic_ops/checksums.ini index 35390b81443..92ac5be4cd5 100644 --- a/build/pkgs/libatomic_ops/checksums.ini +++ b/build/pkgs/libatomic_ops/checksums.ini @@ -1,5 +1,5 @@ tarball=libatomic_ops-VERSION.tar.gz -sha1=ad1c9cd6cc22e042a784e34baa360874083e5f60 -md5=90a78a84d9c28ce11f331c25289bfbd0 -cksum=1553525211 +sha1=69223bbec025a0d57977feb861479f78a5e6c8d7 +md5=a7e51e8041c3e60c298c037b2789c3fa +cksum=596151076 upstream_url=https://github.com/ivmai/libatomic_ops/releases/download/vVERSION/libatomic_ops-VERSION.tar.gz diff --git a/build/pkgs/libatomic_ops/package-version.txt b/build/pkgs/libatomic_ops/package-version.txt index dd812d3580c..09a6d30847d 100644 --- a/build/pkgs/libatomic_ops/package-version.txt +++ b/build/pkgs/libatomic_ops/package-version.txt @@ -1 +1 @@ -7.6.10 +7.8.0 diff --git a/build/pkgs/libbraiding/package-version.txt b/build/pkgs/libbraiding/package-version.txt index 9459d4ba2a0..5625e59da88 100644 --- a/build/pkgs/libbraiding/package-version.txt +++ b/build/pkgs/libbraiding/package-version.txt @@ -1 +1 @@ -1.1 +1.2 diff --git a/build/pkgs/lrcalc_python/dependencies b/build/pkgs/lrcalc_python/dependencies index 27c96045586..d7e0cec0534 100644 --- a/build/pkgs/lrcalc_python/dependencies +++ b/build/pkgs/lrcalc_python/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) lrcalc | $(PYTHON_TOOLCHAIN) cython + lrcalc | $(PYTHON_TOOLCHAIN) cython $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/markupsafe/dependencies b/build/pkgs/markupsafe/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/markupsafe/dependencies +++ b/build/pkgs/markupsafe/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/markupsafe/distros/gentoo.txt b/build/pkgs/markupsafe/distros/gentoo.txt new file mode 100644 index 00000000000..9654e3531b6 --- /dev/null +++ b/build/pkgs/markupsafe/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/markupsafe diff --git a/build/pkgs/markupsafe/distros/opensuse.txt b/build/pkgs/markupsafe/distros/opensuse.txt index 483c7ee1e18..8c103c6b5e5 100644 --- a/build/pkgs/markupsafe/distros/opensuse.txt +++ b/build/pkgs/markupsafe/distros/opensuse.txt @@ -1 +1 @@ -python3-MarkupSafe +python3${PYTHON_MINOR}-MarkupSafe diff --git a/build/pkgs/markupsafe/install-requires.txt b/build/pkgs/markupsafe/install-requires.txt index 331f488e6a0..7d44bce10e1 100644 --- a/build/pkgs/markupsafe/install-requires.txt +++ b/build/pkgs/markupsafe/install-requires.txt @@ -1 +1 @@ -markupsafe >=1.1.0 +markupsafe >=2.0 diff --git a/build/pkgs/markupsafe/spkg-configure.m4 b/build/pkgs/markupsafe/spkg-configure.m4 new file mode 100644 index 00000000000..79eb8dba6f1 --- /dev/null +++ b/build/pkgs/markupsafe/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([markupsafe], [SAGE_PYTHON_PACKAGE_CHECK([markupsafe])]) diff --git a/build/pkgs/mathics/dependencies b/build/pkgs/mathics/dependencies index ac723a5ac26..11d5626d8c7 100644 --- a/build/pkgs/mathics/dependencies +++ b/build/pkgs/mathics/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) pint palettable mathics_scanner + | $(PYTHON_TOOLCHAIN) pint palettable mathics_scanner $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/mathics_scanner/dependencies b/build/pkgs/mathics_scanner/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/mathics_scanner/dependencies +++ b/build/pkgs/mathics_scanner/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/mathjax/distros/gentoo.txt b/build/pkgs/mathjax/distros/gentoo.txt new file mode 100644 index 00000000000..a347f8c2348 --- /dev/null +++ b/build/pkgs/mathjax/distros/gentoo.txt @@ -0,0 +1 @@ +">=dev-libs/mathjax-3" diff --git a/build/pkgs/mathjax/spkg-configure.m4 b/build/pkgs/mathjax/spkg-configure.m4 new file mode 100644 index 00000000000..70fb46a2067 --- /dev/null +++ b/build/pkgs/mathjax/spkg-configure.m4 @@ -0,0 +1,26 @@ +SAGE_SPKG_CONFIGURE([mathjax], [ + # Arch: /usr/share/mathjax + # Gentoo: /usr/share/mathjax + # Void: /usr/share/mathjax + AC_MSG_CHECKING([for MathJax-3.x]) + m4_foreach([mathjax_dir], [/usr/share/mathjax], [ + # tex-chtml.hs is used in src/sage_docbuild/conf.py + # and was not present in MathJax-2.x + AS_IF([test -f "mathjax_dir/tex-chtml.js"], [ + SAGE_MATHJAX_DIR="mathjax_dir" + AC_MSG_RESULT([mathjax_dir]) + ]) + ]) + AS_IF([test -z "${SAGE_MATHJAX_DIR}"], [ + AC_MSG_RESULT([no]) + sage_spkg_install_mathjax=yes + ]) +],[],[],[ + # post-check + AS_IF([test x$sage_spkg_install_mathjax = xyes], [ + # Our spkg-src script adds an extra "mathjax" + SAGE_MATHJAX_DIR='${prefix}'/share/mathjax/mathjax + ]) + + AC_SUBST(SAGE_MATHJAX_DIR, "${SAGE_MATHJAX_DIR}") +]) diff --git a/build/pkgs/matplotlib/dependencies b/build/pkgs/matplotlib/dependencies index cfcf3edda7e..f2968081f9c 100644 --- a/build/pkgs/matplotlib/dependencies +++ b/build/pkgs/matplotlib/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy freetype pillow dateutil pyparsing tornado six cycler qhull fonttools contourpy | $(PYTHON_TOOLCHAIN) kiwisolver certifi setuptools_scm_git_archive + numpy freetype pillow dateutil pyparsing tornado cycler qhull fonttools contourpy | $(PYTHON_TOOLCHAIN) kiwisolver certifi setuptools_scm_git_archive $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/matplotlib/distros/arch.txt b/build/pkgs/matplotlib/distros/arch.txt new file mode 100644 index 00000000000..f6d856e585c --- /dev/null +++ b/build/pkgs/matplotlib/distros/arch.txt @@ -0,0 +1 @@ +python-matplotlib diff --git a/build/pkgs/matplotlib/distros/debian.txt b/build/pkgs/matplotlib/distros/debian.txt new file mode 100644 index 00000000000..13743297213 --- /dev/null +++ b/build/pkgs/matplotlib/distros/debian.txt @@ -0,0 +1 @@ +python3-matplotlib diff --git a/build/pkgs/matplotlib/distros/fedora.txt b/build/pkgs/matplotlib/distros/fedora.txt new file mode 100644 index 00000000000..f6d856e585c --- /dev/null +++ b/build/pkgs/matplotlib/distros/fedora.txt @@ -0,0 +1 @@ +python-matplotlib diff --git a/build/pkgs/matplotlib/distros/gentoo.txt b/build/pkgs/matplotlib/distros/gentoo.txt new file mode 100644 index 00000000000..bcfefb5fcc4 --- /dev/null +++ b/build/pkgs/matplotlib/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/matplotlib diff --git a/build/pkgs/matplotlib/distros/opensuse.txt b/build/pkgs/matplotlib/distros/opensuse.txt index 13743297213..40f1130ec6f 100644 --- a/build/pkgs/matplotlib/distros/opensuse.txt +++ b/build/pkgs/matplotlib/distros/opensuse.txt @@ -1 +1 @@ -python3-matplotlib +python3${PYTHON_MINOR}-matplotlib diff --git a/build/pkgs/matplotlib/spkg-configure.m4 b/build/pkgs/matplotlib/spkg-configure.m4 new file mode 100644 index 00000000000..39c2d2901d0 --- /dev/null +++ b/build/pkgs/matplotlib/spkg-configure.m4 @@ -0,0 +1,5 @@ +SAGE_SPKG_CONFIGURE([matplotlib], [ + SAGE_SPKG_DEPCHECK([bzip2 freetype libpng qhull], [ + SAGE_PYTHON_PACKAGE_CHECK([matplotlib]) + ]) +]) diff --git a/build/pkgs/matplotlib_inline/dependencies b/build/pkgs/matplotlib_inline/dependencies index 1da34eeae60..a1a8daa948c 100644 --- a/build/pkgs/matplotlib_inline/dependencies +++ b/build/pkgs/matplotlib_inline/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) traitlets | $(PYTHON_TOOLCHAIN) + traitlets | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/matplotlib_inline/distros/gentoo.txt b/build/pkgs/matplotlib_inline/distros/gentoo.txt new file mode 100644 index 00000000000..6a5859ca074 --- /dev/null +++ b/build/pkgs/matplotlib_inline/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/matplotlib-inline diff --git a/build/pkgs/matplotlib_inline/spkg-configure.m4 b/build/pkgs/matplotlib_inline/spkg-configure.m4 new file mode 100644 index 00000000000..e59658ff159 --- /dev/null +++ b/build/pkgs/matplotlib_inline/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([matplotlib_inline], [ + SAGE_PYTHON_PACKAGE_CHECK([matplotlib_inline]) +]) diff --git a/build/pkgs/memory_allocator/dependencies b/build/pkgs/memory_allocator/dependencies index 296a2bebad3..1db13c07e43 100644 --- a/build/pkgs/memory_allocator/dependencies +++ b/build/pkgs/memory_allocator/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython | $(PYTHON_TOOLCHAIN) + cython | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/meson/checksums.ini b/build/pkgs/meson/checksums.ini index d3dbb277dba..ef8b1ec0b21 100644 --- a/build/pkgs/meson/checksums.ini +++ b/build/pkgs/meson/checksums.ini @@ -1,5 +1,5 @@ tarball=meson-VERSION.tar.gz -sha1=a2d102eb6a37307c9b67283e9764ed57cf286223 -md5=843ba549bb2a199d9e04092116a7e749 -cksum=2108460988 +sha1=087da0ecbc065bb40361ba683b55c20cb42a948a +md5=e3cc846536189aacd7d01858a45ca9af +cksum=4011973902 upstream_url=https://pypi.io/packages/source/m/meson/meson-VERSION.tar.gz diff --git a/build/pkgs/meson/dependencies b/build/pkgs/meson/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/meson/dependencies +++ b/build/pkgs/meson/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/meson/package-version.txt b/build/pkgs/meson/package-version.txt index 7dea76edb3d..6085e946503 100644 --- a/build/pkgs/meson/package-version.txt +++ b/build/pkgs/meson/package-version.txt @@ -1 +1 @@ -1.0.1 +1.2.1 diff --git a/build/pkgs/meson/spkg-configure.m4 b/build/pkgs/meson/spkg-configure.m4 index efe863664f7..dbc575650fc 100644 --- a/build/pkgs/meson/spkg-configure.m4 +++ b/build/pkgs/meson/spkg-configure.m4 @@ -1,10 +1,11 @@ SAGE_SPKG_CONFIGURE( [meson], [ - AC_CACHE_CHECK([for meson >= 0.64], [ac_cv_path_MESON], [ + dnl scipy 1.11.2 needs meson >= 1.1.0 + AC_CACHE_CHECK([for meson >= 1.1.0], [ac_cv_path_MESON], [ AC_PATH_PROGS_FEATURE_CHECK([MESON], [meson], [ meson_version=`$ac_path_MESON --version 2>&1` AS_IF([test -n "$meson_version"], [ - AX_COMPARE_VERSION([$meson_version], [ge], [0.64], [ + AX_COMPARE_VERSION([$meson_version], [ge], [1.1.0], [ ac_cv_path_MESON="$ac_path_MESON" ac_path_MESON_found=: ]) diff --git a/build/pkgs/meson_python/checksums.ini b/build/pkgs/meson_python/checksums.ini index 0e1c77874b7..da59c9577aa 100644 --- a/build/pkgs/meson_python/checksums.ini +++ b/build/pkgs/meson_python/checksums.ini @@ -1,5 +1,5 @@ tarball=meson_python-VERSION.tar.gz -sha1=bdaf002dc1ef314c32e2be76f3b2872f1282c4cc -md5=39be4f0b7f036e1d5db4a76fdb031355 -cksum=2636510839 +sha1=e52e84fcd84ea7dd8c11f464390786686a1be8e6 +md5=0db4483e30df43dbd465254be9c7db8a +cksum=1452585711 upstream_url=https://pypi.io/packages/source/m/meson_python/meson_python-VERSION.tar.gz diff --git a/build/pkgs/meson_python/dependencies b/build/pkgs/meson_python/dependencies index 160adbf36c9..01b5cb597b0 100644 --- a/build/pkgs/meson_python/dependencies +++ b/build/pkgs/meson_python/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) meson pyproject_metadata tomli ninja_build patchelf | $(PYTHON_TOOLCHAIN) + meson pyproject_metadata tomli ninja_build patchelf | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/meson_python/distros/gentoo.txt b/build/pkgs/meson_python/distros/gentoo.txt new file mode 100644 index 00000000000..0dec932b5b3 --- /dev/null +++ b/build/pkgs/meson_python/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/meson-python diff --git a/build/pkgs/meson_python/package-version.txt b/build/pkgs/meson_python/package-version.txt index 34a83616bb5..9beb74d490b 100644 --- a/build/pkgs/meson_python/package-version.txt +++ b/build/pkgs/meson_python/package-version.txt @@ -1 +1 @@ -0.12.1 +0.13.2 diff --git a/build/pkgs/meson_python/patches/ARCHFLAGS_empty.patch b/build/pkgs/meson_python/patches/ARCHFLAGS_empty.patch deleted file mode 100644 index 8857629f080..00000000000 --- a/build/pkgs/meson_python/patches/ARCHFLAGS_empty.patch +++ /dev/null @@ -1,21 +0,0 @@ -commit caa435144b1b4fa40c51558f15fd8dae2c0b5868 -Author: Matthias Koeppe -Date: Sat Mar 11 10:16:56 2023 -0800 - - BUG: handle ARCHFLAGS set to the empty string - -diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py -index e312059..d798f4c 100644 ---- a/mesonpy/__init__.py -+++ b/mesonpy/__init__.py -@@ -686,8 +686,8 @@ class Project(): - - # setuptools-like ARCHFLAGS environment variable support - if sysconfig.get_platform().startswith('macosx-'): -- archflags = self._env.get('ARCHFLAGS') -- if archflags is not None: -+ archflags = self._env.get('ARCHFLAGS', '').strip() -+ if archflags: - arch, *other = filter(None, (x.strip() for x in archflags.split('-arch'))) - if other: - raise ConfigError(f'Multi-architecture builds are not supported but $ARCHFLAGS={archflags!r}') diff --git a/build/pkgs/meson_python/spkg-configure.m4 b/build/pkgs/meson_python/spkg-configure.m4 new file mode 100644 index 00000000000..267e6ad801c --- /dev/null +++ b/build/pkgs/meson_python/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([meson_python], [ + SAGE_PYTHON_PACKAGE_CHECK([meson-python]) +]) diff --git a/build/pkgs/mistune/dependencies b/build/pkgs/mistune/dependencies index 296a2bebad3..1db13c07e43 100644 --- a/build/pkgs/mistune/dependencies +++ b/build/pkgs/mistune/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython | $(PYTHON_TOOLCHAIN) + cython | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/mistune/distros/gentoo.txt b/build/pkgs/mistune/distros/gentoo.txt new file mode 100644 index 00000000000..56f0a4ebced --- /dev/null +++ b/build/pkgs/mistune/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/mistune diff --git a/build/pkgs/mistune/spkg-configure.m4 b/build/pkgs/mistune/spkg-configure.m4 new file mode 100644 index 00000000000..972f33d086b --- /dev/null +++ b/build/pkgs/mistune/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([mistune], [SAGE_PYTHON_PACKAGE_CHECK([mistune])]) diff --git a/build/pkgs/mpmath/dependencies b/build/pkgs/mpmath/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/mpmath/dependencies +++ b/build/pkgs/mpmath/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/mpmath/distros/arch.txt b/build/pkgs/mpmath/distros/arch.txt new file mode 100644 index 00000000000..a7dc8d568f3 --- /dev/null +++ b/build/pkgs/mpmath/distros/arch.txt @@ -0,0 +1 @@ +python-mpmath diff --git a/build/pkgs/mpmath/distros/debian.txt b/build/pkgs/mpmath/distros/debian.txt new file mode 100644 index 00000000000..fbc82a97e07 --- /dev/null +++ b/build/pkgs/mpmath/distros/debian.txt @@ -0,0 +1 @@ +python3-mpmath diff --git a/build/pkgs/mpmath/distros/fedora.txt b/build/pkgs/mpmath/distros/fedora.txt new file mode 100644 index 00000000000..a7dc8d568f3 --- /dev/null +++ b/build/pkgs/mpmath/distros/fedora.txt @@ -0,0 +1 @@ +python-mpmath diff --git a/build/pkgs/mpmath/distros/gentoo.txt b/build/pkgs/mpmath/distros/gentoo.txt new file mode 100644 index 00000000000..946c62d9e1a --- /dev/null +++ b/build/pkgs/mpmath/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/mpmath diff --git a/build/pkgs/mpmath/distros/opensuse.txt b/build/pkgs/mpmath/distros/opensuse.txt new file mode 100644 index 00000000000..8b65d97862d --- /dev/null +++ b/build/pkgs/mpmath/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-mpmath diff --git a/build/pkgs/mpmath/spkg-configure.m4 b/build/pkgs/mpmath/spkg-configure.m4 new file mode 100644 index 00000000000..f43c8388264 --- /dev/null +++ b/build/pkgs/mpmath/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([mpmath], [SAGE_PYTHON_PACKAGE_CHECK([mpmath])]) diff --git a/build/pkgs/msolve/checksums.ini b/build/pkgs/msolve/checksums.ini index a2ef7368790..ae12f77abc9 100644 --- a/build/pkgs/msolve/checksums.ini +++ b/build/pkgs/msolve/checksums.ini @@ -1,5 +1,5 @@ tarball=msolve-VERSION.tar.gz -sha1=db99898afd03c2491d7d2190b89cea9ff0c41313 -md5=4ff5909d27f164aad9f7bdff633c037d -cksum=507678049 +sha1=bfd1d4f2e5dc0eb321592b3add6665a9d3eadf8c +md5=33a16c21ea8dea9e796d40f1dfd52fa9 +cksum=117017965 upstream_url=https://github.com/algebraic-solving/msolve/releases/download/vVERSION/msolve-VERSION.tar.gz diff --git a/build/pkgs/msolve/package-version.txt b/build/pkgs/msolve/package-version.txt index 76914ddc02f..8f0916f768f 100644 --- a/build/pkgs/msolve/package-version.txt +++ b/build/pkgs/msolve/package-version.txt @@ -1 +1 @@ -0.4.9 +0.5.0 diff --git a/build/pkgs/nbclient/dependencies b/build/pkgs/nbclient/dependencies index e21070fd3af..acec3fadace 100644 --- a/build/pkgs/nbclient/dependencies +++ b/build/pkgs/nbclient/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jupyter_client nbformat | $(PYTHON_TOOLCHAIN) + jupyter_client nbformat | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/nbclient/distros/gentoo.txt b/build/pkgs/nbclient/distros/gentoo.txt new file mode 100644 index 00000000000..06ff18d206a --- /dev/null +++ b/build/pkgs/nbclient/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/nbclient diff --git a/build/pkgs/nbclient/spkg-configure.m4 b/build/pkgs/nbclient/spkg-configure.m4 new file mode 100644 index 00000000000..14178b793d2 --- /dev/null +++ b/build/pkgs/nbclient/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([nbclient], [SAGE_PYTHON_PACKAGE_CHECK([nbclient])]) diff --git a/build/pkgs/nbconvert/dependencies b/build/pkgs/nbconvert/dependencies index b423493e603..4a7730e8e9f 100644 --- a/build/pkgs/nbconvert/dependencies +++ b/build/pkgs/nbconvert/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) mistune jinja2 pygments traitlets jupyter_core nbformat entrypoints bleach pandocfilters defusedxml jupyter_client jupyterlab_pygments nbclient beautifulsoup4 markupsafe | $(PYTHON_TOOLCHAIN) +mistune jinja2 pygments traitlets jupyter_core nbformat entrypoints bleach pandocfilters defusedxml jupyter_client jupyterlab_pygments nbclient beautifulsoup4 markupsafe tinycss2 | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/nbconvert/distros/gentoo.txt b/build/pkgs/nbconvert/distros/gentoo.txt new file mode 100644 index 00000000000..6c45a107368 --- /dev/null +++ b/build/pkgs/nbconvert/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/nbconvert diff --git a/build/pkgs/nbconvert/spkg-configure.m4 b/build/pkgs/nbconvert/spkg-configure.m4 new file mode 100644 index 00000000000..9b5dee3b8b5 --- /dev/null +++ b/build/pkgs/nbconvert/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([nbconvert], [SAGE_PYTHON_PACKAGE_CHECK([nbconvert])]) diff --git a/build/pkgs/nbformat/dependencies b/build/pkgs/nbformat/dependencies index 6c8921f1382..a6f9cc5f425 100644 --- a/build/pkgs/nbformat/dependencies +++ b/build/pkgs/nbformat/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jsonschema fastjsonschema jupyter_core traitlets | $(PYTHON_TOOLCHAIN) hatchling hatch_nodejs_version + jsonschema fastjsonschema jupyter_core traitlets | $(PYTHON_TOOLCHAIN) hatchling hatch_nodejs_version $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/nbformat/distros/gentoo.txt b/build/pkgs/nbformat/distros/gentoo.txt new file mode 100644 index 00000000000..006b1f2fc6d --- /dev/null +++ b/build/pkgs/nbformat/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/nbformat diff --git a/build/pkgs/nbformat/spkg-configure.m4 b/build/pkgs/nbformat/spkg-configure.m4 new file mode 100644 index 00000000000..5a7f8c4ccec --- /dev/null +++ b/build/pkgs/nbformat/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([nbformat], [SAGE_PYTHON_PACKAGE_CHECK([nbformat])]) diff --git a/build/pkgs/nest_asyncio/dependencies b/build/pkgs/nest_asyncio/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/nest_asyncio/dependencies +++ b/build/pkgs/nest_asyncio/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/nest_asyncio/distros/gentoo.txt b/build/pkgs/nest_asyncio/distros/gentoo.txt new file mode 100644 index 00000000000..ab742d2b0bd --- /dev/null +++ b/build/pkgs/nest_asyncio/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/nest_asyncio diff --git a/build/pkgs/nest_asyncio/spkg-configure.m4 b/build/pkgs/nest_asyncio/spkg-configure.m4 new file mode 100644 index 00000000000..4d815276dfb --- /dev/null +++ b/build/pkgs/nest_asyncio/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([nest_asyncio], [SAGE_PYTHON_PACKAGE_CHECK([nest_asyncio])]) diff --git a/build/pkgs/networkx/dependencies b/build/pkgs/networkx/dependencies index 8eb6920e25d..fdba548c01a 100644 --- a/build/pkgs/networkx/dependencies +++ b/build/pkgs/networkx/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) decorator | $(PYTHON_TOOLCHAIN) scipy + decorator | $(PYTHON_TOOLCHAIN) scipy $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/networkx/distros/arch.txt b/build/pkgs/networkx/distros/arch.txt new file mode 100644 index 00000000000..293f943529a --- /dev/null +++ b/build/pkgs/networkx/distros/arch.txt @@ -0,0 +1 @@ +python-networkx diff --git a/build/pkgs/networkx/distros/debian.txt b/build/pkgs/networkx/distros/debian.txt new file mode 100644 index 00000000000..67790667af2 --- /dev/null +++ b/build/pkgs/networkx/distros/debian.txt @@ -0,0 +1 @@ +python3-networkx diff --git a/build/pkgs/networkx/distros/fedora.txt b/build/pkgs/networkx/distros/fedora.txt new file mode 100644 index 00000000000..293f943529a --- /dev/null +++ b/build/pkgs/networkx/distros/fedora.txt @@ -0,0 +1 @@ +python-networkx diff --git a/build/pkgs/networkx/distros/gentoo.txt b/build/pkgs/networkx/distros/gentoo.txt new file mode 100644 index 00000000000..dd97742cff8 --- /dev/null +++ b/build/pkgs/networkx/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/networkx diff --git a/build/pkgs/networkx/distros/opensuse.txt b/build/pkgs/networkx/distros/opensuse.txt index 67790667af2..7c421f08d48 100644 --- a/build/pkgs/networkx/distros/opensuse.txt +++ b/build/pkgs/networkx/distros/opensuse.txt @@ -1 +1 @@ -python3-networkx +python3${PYTHON_MINOR}-networkx diff --git a/build/pkgs/networkx/spkg-configure.m4 b/build/pkgs/networkx/spkg-configure.m4 new file mode 100644 index 00000000000..926671e166e --- /dev/null +++ b/build/pkgs/networkx/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([networkx], [SAGE_PYTHON_PACKAGE_CHECK([networkx])]) diff --git a/build/pkgs/nibabel/distros/opensuse.txt b/build/pkgs/nibabel/distros/opensuse.txt index 19df029d93f..1a7f1fd31f7 100644 --- a/build/pkgs/nibabel/distros/opensuse.txt +++ b/build/pkgs/nibabel/distros/opensuse.txt @@ -1 +1 @@ -python3-nibabel +python3${PYTHON_MINOR}-nibabel diff --git a/build/pkgs/ninja_build/checksums.ini b/build/pkgs/ninja_build/checksums.ini index d3914da794a..43ddbfd6334 100644 --- a/build/pkgs/ninja_build/checksums.ini +++ b/build/pkgs/ninja_build/checksums.ini @@ -1,5 +1,5 @@ tarball=ninja_build-VERSION.tar.gz -sha1=f8c9279bdd4efc63b1a6be3b8c5a5031699af9ac -md5=7d1a1a2f5cdc06795b3054df5c17d5ef -cksum=3142198237 +sha1=938723cdfc7a6f7c8f84c83b9a2cecdf1e5e1ad3 +md5=32151c08211d7ca3c1d832064f6939b0 +cksum=4040304461 upstream_url=https://github.com/ninja-build/ninja/archive/refs/tags/vVERSION.tar.gz diff --git a/build/pkgs/ninja_build/dependencies b/build/pkgs/ninja_build/dependencies index 6b134137610..3518086ab84 100644 --- a/build/pkgs/ninja_build/dependencies +++ b/build/pkgs/ninja_build/dependencies @@ -1,4 +1,4 @@ -| $(PYTHON) +| $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ninja_build/package-version.txt b/build/pkgs/ninja_build/package-version.txt index 1cac385c6cb..720c7384c61 100644 --- a/build/pkgs/ninja_build/package-version.txt +++ b/build/pkgs/ninja_build/package-version.txt @@ -1 +1 @@ -1.11.0 +1.11.1 diff --git a/build/pkgs/nodeenv/dependencies b/build/pkgs/nodeenv/dependencies index 16df46f57ee..04eff0c842c 100644 --- a/build/pkgs/nodeenv/dependencies +++ b/build/pkgs/nodeenv/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) certifi + | $(PYTHON_TOOLCHAIN) certifi $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/normaliz/checksums.ini b/build/pkgs/normaliz/checksums.ini index 803bf8e282f..fd5561cad24 100644 --- a/build/pkgs/normaliz/checksums.ini +++ b/build/pkgs/normaliz/checksums.ini @@ -1,5 +1,5 @@ tarball=normaliz-VERSION.tar.gz -sha1=16fcf28e862f8d7c971c9fa682cbacb24fcf8ce1 -md5=0d8a2e841193bb4b2422aac7744ece0b -cksum=2885510960 -upstream_url=https://github.com/Normaliz/Normaliz/releases/download/VERSION/normaliz-VERSION.tar.gz +sha1=d3c4e554c6a5ccf4fd04147e7744a63e3def1766 +md5=1c7a7833ad180ef4e0e4f124ed398973 +cksum=3124231015 +upstream_url=https://github.com/Normaliz/Normaliz/releases/download/vVERSION/normaliz-VERSION.tar.gz diff --git a/build/pkgs/normaliz/package-version.txt b/build/pkgs/normaliz/package-version.txt index 30291cba223..f870be23bad 100644 --- a/build/pkgs/normaliz/package-version.txt +++ b/build/pkgs/normaliz/package-version.txt @@ -1 +1 @@ -3.10.0 +3.10.1 diff --git a/build/pkgs/normaliz/patches/411.patch b/build/pkgs/normaliz/patches/411.patch new file mode 100644 index 00000000000..d9e52bd78bf --- /dev/null +++ b/build/pkgs/normaliz/patches/411.patch @@ -0,0 +1,21 @@ +commit ecdb62c90a3767b440800dcf2c49589e890a53b1 +Author: Matthias Koeppe +Date: Tue Aug 8 17:03:32 2023 -0700 + + full_cone.cpp: Remove debug output + +diff --git a/source/libnormaliz/full_cone.cpp b/source/libnormaliz/full_cone.cpp +index 0fd906b3..cb2cce2b 100644 +--- a/source/libnormaliz/full_cone.cpp ++++ b/source/libnormaliz/full_cone.cpp +@@ -3447,8 +3447,8 @@ void Full_Cone::build_cone_dynamic() { + // if they aren't in a hyperplane anyway + if(IntHullNorm.size() > 0){ + #pragma omp parallel for +- for(size_t i = 0; i< OriGens.nr_of_rows(); ++i){ +- cout << "i " << i << " -- " << OriGensFloat[i]; ++ for (size_t i = 0; i< OriGens.nr_of_rows(); ++i){ ++ // cout << "i " << i << " -- " << OriGensFloat[i]; + nmz_float norm = v_scalar_product(OriGensFloat[i], IntHullNormFloat); + v_scalar_division(OriGensFloat[i], norm); + } diff --git a/build/pkgs/notebook/dependencies b/build/pkgs/notebook/dependencies index 9f5cb330ae2..9e6cbf4b36d 100644 --- a/build/pkgs/notebook/dependencies +++ b/build/pkgs/notebook/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado send2trash prometheus_client argon2_cffi + | $(PYTHON_TOOLCHAIN) ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado send2trash prometheus_client argon2_cffi $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/notebook/distros/gentoo.txt b/build/pkgs/notebook/distros/gentoo.txt new file mode 100644 index 00000000000..6475d72541e --- /dev/null +++ b/build/pkgs/notebook/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/notebook diff --git a/build/pkgs/notebook/spkg-configure.m4 b/build/pkgs/notebook/spkg-configure.m4 new file mode 100644 index 00000000000..a17ba95eac6 --- /dev/null +++ b/build/pkgs/notebook/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([notebook], [SAGE_PYTHON_PACKAGE_CHECK([notebook])]) diff --git a/build/pkgs/notedown/dependencies b/build/pkgs/notedown/dependencies index ea77eefc7f4..3dcb5b1900f 100644 --- a/build/pkgs/notedown/dependencies +++ b/build/pkgs/notedown/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(PYTHON_TOOLCHAIN) | pip nbformat nbconvert six pandoc_attributes + $(PYTHON_TOOLCHAIN) | pip nbformat nbconvert six pandoc_attributes $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/numpy/dependencies b/build/pkgs/numpy/dependencies index d3c0f0055e4..63faafe335a 100644 --- a/build/pkgs/numpy/dependencies +++ b/build/pkgs/numpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(BLAS) gfortran | $(PYTHON_TOOLCHAIN) pkgconfig cython + $(BLAS) gfortran | $(PYTHON_TOOLCHAIN) pkgconfig cython $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/numpy/distros/arch.txt b/build/pkgs/numpy/distros/arch.txt new file mode 100644 index 00000000000..c8722b9f663 --- /dev/null +++ b/build/pkgs/numpy/distros/arch.txt @@ -0,0 +1 @@ +python-numpy diff --git a/build/pkgs/numpy/distros/debian.txt b/build/pkgs/numpy/distros/debian.txt new file mode 100644 index 00000000000..79d5c5a1429 --- /dev/null +++ b/build/pkgs/numpy/distros/debian.txt @@ -0,0 +1 @@ +python3-numpy diff --git a/build/pkgs/numpy/distros/fedora.txt b/build/pkgs/numpy/distros/fedora.txt new file mode 100644 index 00000000000..c8722b9f663 --- /dev/null +++ b/build/pkgs/numpy/distros/fedora.txt @@ -0,0 +1 @@ +python-numpy diff --git a/build/pkgs/numpy/distros/gentoo.txt b/build/pkgs/numpy/distros/gentoo.txt new file mode 100644 index 00000000000..d2179d43851 --- /dev/null +++ b/build/pkgs/numpy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/numpy diff --git a/build/pkgs/numpy/distros/opensuse.txt b/build/pkgs/numpy/distros/opensuse.txt new file mode 100644 index 00000000000..2e278515236 --- /dev/null +++ b/build/pkgs/numpy/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-numpy diff --git a/build/pkgs/numpy/spkg-configure.m4 b/build/pkgs/numpy/spkg-configure.m4 new file mode 100644 index 00000000000..16f9a90fad2 --- /dev/null +++ b/build/pkgs/numpy/spkg-configure.m4 @@ -0,0 +1,5 @@ +SAGE_SPKG_CONFIGURE([numpy], [ + SAGE_SPKG_DEPCHECK([openblas], [ + SAGE_PYTHON_PACKAGE_CHECK([numpy]) + ]) +]) diff --git a/build/pkgs/ore_algebra/dependencies b/build/pkgs/ore_algebra/dependencies index 05ba0d8954b..126e8ceee06 100644 --- a/build/pkgs/ore_algebra/dependencies +++ b/build/pkgs/ore_algebra/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) $(SAGERUNTIME) + | $(PYTHON_TOOLCHAIN) $(SAGERUNTIME) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/osqp_python/dependencies b/build/pkgs/osqp_python/dependencies index 4f344bba626..6cc50626d1d 100644 --- a/build/pkgs/osqp_python/dependencies +++ b/build/pkgs/osqp_python/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) qdldl_python numpy scipy | $(PYTHON_TOOLCHAIN) cmake + qdldl_python numpy scipy | $(PYTHON_TOOLCHAIN) cmake $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/p_group_cohomology/dependencies b/build/pkgs/p_group_cohomology/dependencies index a9d113183c5..57ea7e0dd94 100644 --- a/build/pkgs/p_group_cohomology/dependencies +++ b/build/pkgs/p_group_cohomology/dependencies @@ -1 +1 @@ -$(PYTHON) cython cysignals singular meataxe modular_resolution $(SAGE_SRC)/sage/matrix/matrix_gfpn_dense.pxd $(SAGE_SRC)/sage/structure/element.pxd $(SAGE_SRC)/sage/matrix/matrix_gfpn_dense.pxd $(SAGE_SRC)/sage/matrix/matrix0.pxd $(SAGE_SRC)/sage/libs/meataxe.pxd $(SAGE_SRC)/sage/rings/morphism.pxd | $(PYTHON_TOOLCHAIN) matplotlib gap xz $(SAGERUNTIME) ipywidgets + cython cysignals singular meataxe modular_resolution $(SAGE_SRC)/sage/matrix/matrix_gfpn_dense.pxd $(SAGE_SRC)/sage/structure/element.pxd $(SAGE_SRC)/sage/matrix/matrix_gfpn_dense.pxd $(SAGE_SRC)/sage/matrix/matrix0.pxd $(SAGE_SRC)/sage/libs/meataxe.pxd $(SAGE_SRC)/sage/rings/morphism.pxd | $(PYTHON_TOOLCHAIN) matplotlib gap xz $(SAGERUNTIME) ipywidgets $(PYTHON) diff --git a/build/pkgs/packaging/checksums.ini b/build/pkgs/packaging/checksums.ini index c8c315c78c8..83ab122e324 100644 --- a/build/pkgs/packaging/checksums.ini +++ b/build/pkgs/packaging/checksums.ini @@ -1,5 +1,5 @@ tarball=packaging-VERSION.tar.gz -sha1=b8caff3bec760723db6af4092c68075e22bdb769 -md5=e713c1939f294fd729af4a7be40dd141 -cksum=2539089468 +sha1=1245c28c10ae6cb80164f081daece224b6fa89bc +md5=f7d5c39c6f92cc2dfa1293ba8f6c097c +cksum=11867377 upstream_url=https://pypi.io/packages/source/p/packaging/packaging-VERSION.tar.gz diff --git a/build/pkgs/packaging/dependencies b/build/pkgs/packaging/dependencies index 2323f9df04a..17220ffcc37 100644 --- a/build/pkgs/packaging/dependencies +++ b/build/pkgs/packaging/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | setuptools pip wheel pyparsing setuptools_wheel + | setuptools pip wheel pyparsing setuptools_wheel $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/packaging/distros/arch.txt b/build/pkgs/packaging/distros/arch.txt new file mode 100644 index 00000000000..02ad855da9a --- /dev/null +++ b/build/pkgs/packaging/distros/arch.txt @@ -0,0 +1 @@ +python-packaging diff --git a/build/pkgs/packaging/distros/debian.txt b/build/pkgs/packaging/distros/debian.txt new file mode 100644 index 00000000000..8f1c0ffc29f --- /dev/null +++ b/build/pkgs/packaging/distros/debian.txt @@ -0,0 +1 @@ +python3-packaging diff --git a/build/pkgs/packaging/distros/fedora.txt b/build/pkgs/packaging/distros/fedora.txt new file mode 100644 index 00000000000..02ad855da9a --- /dev/null +++ b/build/pkgs/packaging/distros/fedora.txt @@ -0,0 +1 @@ +python-packaging diff --git a/build/pkgs/packaging/distros/gentoo.txt b/build/pkgs/packaging/distros/gentoo.txt new file mode 100644 index 00000000000..e5309ed2b25 --- /dev/null +++ b/build/pkgs/packaging/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/packaging diff --git a/build/pkgs/packaging/distros/opensuse.txt b/build/pkgs/packaging/distros/opensuse.txt new file mode 100644 index 00000000000..bec5186f923 --- /dev/null +++ b/build/pkgs/packaging/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-packaging diff --git a/build/pkgs/packaging/install-requires.txt b/build/pkgs/packaging/install-requires.txt index cb98c369e84..637d00eff2f 100644 --- a/build/pkgs/packaging/install-requires.txt +++ b/build/pkgs/packaging/install-requires.txt @@ -1,2 +1,3 @@ -packaging >=18.0 +packaging >=21.0 # Trac #30975: packaging 20.5 is known to work but we have to silence "DeprecationWarning: Creating a LegacyVersion" +# Sphinx needs >= 21 diff --git a/build/pkgs/packaging/package-version.txt b/build/pkgs/packaging/package-version.txt index 8e5954eb6f3..a12b18e4372 100644 --- a/build/pkgs/packaging/package-version.txt +++ b/build/pkgs/packaging/package-version.txt @@ -1 +1 @@ -21.3 +23.1 diff --git a/build/pkgs/packaging/spkg-configure.m4 b/build/pkgs/packaging/spkg-configure.m4 new file mode 100644 index 00000000000..398f9e13cd3 --- /dev/null +++ b/build/pkgs/packaging/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([packaging], [SAGE_PYTHON_PACKAGE_CHECK([packaging])]) diff --git a/build/pkgs/palettable/dependencies b/build/pkgs/palettable/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/palettable/dependencies +++ b/build/pkgs/palettable/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pandoc_attributes/dependencies b/build/pkgs/pandoc_attributes/dependencies index 64f88253c78..cc9d4970706 100644 --- a/build/pkgs/pandoc_attributes/dependencies +++ b/build/pkgs/pandoc_attributes/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(PYTHON_TOOLCHAIN) | pip pandocfilters + $(PYTHON_TOOLCHAIN) | pip pandocfilters $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pandocfilters/dependencies b/build/pkgs/pandocfilters/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pandocfilters/dependencies +++ b/build/pkgs/pandocfilters/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pandocfilters/distros/arch.txt b/build/pkgs/pandocfilters/distros/arch.txt new file mode 100644 index 00000000000..e7a86d0373c --- /dev/null +++ b/build/pkgs/pandocfilters/distros/arch.txt @@ -0,0 +1 @@ +python-pandocfilters diff --git a/build/pkgs/pandocfilters/distros/debian.txt b/build/pkgs/pandocfilters/distros/debian.txt new file mode 100644 index 00000000000..d0d4c24e15e --- /dev/null +++ b/build/pkgs/pandocfilters/distros/debian.txt @@ -0,0 +1 @@ +python3-pandocfilters diff --git a/build/pkgs/pandocfilters/distros/fedora.txt b/build/pkgs/pandocfilters/distros/fedora.txt new file mode 100644 index 00000000000..e7a86d0373c --- /dev/null +++ b/build/pkgs/pandocfilters/distros/fedora.txt @@ -0,0 +1 @@ +python-pandocfilters diff --git a/build/pkgs/pandocfilters/distros/gentoo.txt b/build/pkgs/pandocfilters/distros/gentoo.txt new file mode 100644 index 00000000000..a726fda2817 --- /dev/null +++ b/build/pkgs/pandocfilters/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pandocfilters diff --git a/build/pkgs/pandocfilters/distros/opensuse.txt b/build/pkgs/pandocfilters/distros/opensuse.txt new file mode 100644 index 00000000000..843b3c1b32b --- /dev/null +++ b/build/pkgs/pandocfilters/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-pandocfilters diff --git a/build/pkgs/pandocfilters/spkg-configure.m4 b/build/pkgs/pandocfilters/spkg-configure.m4 new file mode 100644 index 00000000000..3e9537f818c --- /dev/null +++ b/build/pkgs/pandocfilters/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([pandocfilters], [ + SAGE_PYTHON_PACKAGE_CHECK([pandocfilters]) +]) diff --git a/build/pkgs/pari_jupyter/dependencies b/build/pkgs/pari_jupyter/dependencies index 44eaa153cc2..f7f0020c13b 100644 --- a/build/pkgs/pari_jupyter/dependencies +++ b/build/pkgs/pari_jupyter/dependencies @@ -1 +1 @@ -$(PYTHON) pari | $(PYTHON_TOOLCHAIN) cython notebook jupyter_core + pari | $(PYTHON_TOOLCHAIN) cython notebook jupyter_core $(PYTHON) diff --git a/build/pkgs/parso/dependencies b/build/pkgs/parso/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/parso/dependencies +++ b/build/pkgs/parso/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/parso/distros/gentoo.txt b/build/pkgs/parso/distros/gentoo.txt new file mode 100644 index 00000000000..f9ce4c7f2f2 --- /dev/null +++ b/build/pkgs/parso/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/parso diff --git a/build/pkgs/parso/spkg-configure.m4 b/build/pkgs/parso/spkg-configure.m4 new file mode 100644 index 00000000000..1ca6f1b909d --- /dev/null +++ b/build/pkgs/parso/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([parso], [SAGE_PYTHON_PACKAGE_CHECK([parso])]) diff --git a/build/pkgs/pathspec/dependencies b/build/pkgs/pathspec/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pathspec/dependencies +++ b/build/pkgs/pathspec/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pathspec/distros/gentoo.txt b/build/pkgs/pathspec/distros/gentoo.txt new file mode 100644 index 00000000000..6f8fd9dc4cd --- /dev/null +++ b/build/pkgs/pathspec/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pathspec diff --git a/build/pkgs/pathspec/spkg-configure.m4 b/build/pkgs/pathspec/spkg-configure.m4 new file mode 100644 index 00000000000..086fd9830e9 --- /dev/null +++ b/build/pkgs/pathspec/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pathspec], [SAGE_PYTHON_PACKAGE_CHECK([pathspec])]) diff --git a/build/pkgs/pexpect/dependencies b/build/pkgs/pexpect/dependencies index 4a942502496..d3f8eced66f 100644 --- a/build/pkgs/pexpect/dependencies +++ b/build/pkgs/pexpect/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) ptyprocess | $(PYTHON_TOOLCHAIN) + ptyprocess | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pexpect/distros/arch.txt b/build/pkgs/pexpect/distros/arch.txt new file mode 100644 index 00000000000..74d08141569 --- /dev/null +++ b/build/pkgs/pexpect/distros/arch.txt @@ -0,0 +1 @@ +python-pexpect diff --git a/build/pkgs/pexpect/distros/fedora.txt b/build/pkgs/pexpect/distros/fedora.txt new file mode 100644 index 00000000000..74d08141569 --- /dev/null +++ b/build/pkgs/pexpect/distros/fedora.txt @@ -0,0 +1 @@ +python-pexpect diff --git a/build/pkgs/pexpect/distros/freebsd.txt b/build/pkgs/pexpect/distros/freebsd.txt new file mode 100644 index 00000000000..767fd38a2fa --- /dev/null +++ b/build/pkgs/pexpect/distros/freebsd.txt @@ -0,0 +1 @@ +misc/py-pexpect diff --git a/build/pkgs/pexpect/distros/gentoo.txt b/build/pkgs/pexpect/distros/gentoo.txt new file mode 100644 index 00000000000..30c4b60d014 --- /dev/null +++ b/build/pkgs/pexpect/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pexpect diff --git a/build/pkgs/pexpect/distros/opensuse.txt b/build/pkgs/pexpect/distros/opensuse.txt index 8d745ee4a07..f8cc97d1599 100644 --- a/build/pkgs/pexpect/distros/opensuse.txt +++ b/build/pkgs/pexpect/distros/opensuse.txt @@ -1 +1 @@ -python3-pexpect +python3${PYTHON_MINOR}-pexpect diff --git a/build/pkgs/pexpect/spkg-configure.m4 b/build/pkgs/pexpect/spkg-configure.m4 new file mode 100644 index 00000000000..6520856fbb5 --- /dev/null +++ b/build/pkgs/pexpect/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pexpect], [SAGE_PYTHON_PACKAGE_CHECK([pexpect])]) diff --git a/build/pkgs/phitigra/dependencies b/build/pkgs/phitigra/dependencies index 7aeb0c77c74..61dca76d6bc 100644 --- a/build/pkgs/phitigra/dependencies +++ b/build/pkgs/phitigra/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) ipywidgets pillow numpy | $(PYTHON_TOOLCHAIN) + ipywidgets pillow numpy | $(PYTHON_TOOLCHAIN) $(PYTHON) These dependencies include the install-requires of ipycanvas. ---------- diff --git a/build/pkgs/pickleshare/dependencies b/build/pkgs/pickleshare/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pickleshare/dependencies +++ b/build/pkgs/pickleshare/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pickleshare/distros/arch.txt b/build/pkgs/pickleshare/distros/arch.txt new file mode 100644 index 00000000000..6d991a27d41 --- /dev/null +++ b/build/pkgs/pickleshare/distros/arch.txt @@ -0,0 +1 @@ +python-pickleshare diff --git a/build/pkgs/pickleshare/distros/debian.txt b/build/pkgs/pickleshare/distros/debian.txt new file mode 100644 index 00000000000..a00907d167b --- /dev/null +++ b/build/pkgs/pickleshare/distros/debian.txt @@ -0,0 +1 @@ +python3-pickleshare diff --git a/build/pkgs/pickleshare/distros/fedora.txt b/build/pkgs/pickleshare/distros/fedora.txt new file mode 100644 index 00000000000..6d991a27d41 --- /dev/null +++ b/build/pkgs/pickleshare/distros/fedora.txt @@ -0,0 +1 @@ +python-pickleshare diff --git a/build/pkgs/pickleshare/distros/gentoo.txt b/build/pkgs/pickleshare/distros/gentoo.txt new file mode 100644 index 00000000000..14fad0fa428 --- /dev/null +++ b/build/pkgs/pickleshare/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pickleshare diff --git a/build/pkgs/pickleshare/distros/opensuse.txt b/build/pkgs/pickleshare/distros/opensuse.txt index a00907d167b..260701493fc 100644 --- a/build/pkgs/pickleshare/distros/opensuse.txt +++ b/build/pkgs/pickleshare/distros/opensuse.txt @@ -1 +1 @@ -python3-pickleshare +python3${PYTHON_MINOR}-pickleshare diff --git a/build/pkgs/pickleshare/spkg-configure.m4 b/build/pkgs/pickleshare/spkg-configure.m4 new file mode 100644 index 00000000000..80e9b7ccba9 --- /dev/null +++ b/build/pkgs/pickleshare/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pickleshare], [SAGE_PYTHON_PACKAGE_CHECK([pickleshare])]) diff --git a/build/pkgs/pillow/dependencies b/build/pkgs/pillow/dependencies index 2ece64e58e8..f2500281136 100644 --- a/build/pkgs/pillow/dependencies +++ b/build/pkgs/pillow/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) zlib freetype | $(PYTHON_TOOLCHAIN) pkgconf + zlib freetype | $(PYTHON_TOOLCHAIN) pkgconf $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pillow/distros/arch.txt b/build/pkgs/pillow/distros/arch.txt new file mode 100644 index 00000000000..86dbb1d13b8 --- /dev/null +++ b/build/pkgs/pillow/distros/arch.txt @@ -0,0 +1 @@ +python-pillow diff --git a/build/pkgs/pillow/distros/debian.txt b/build/pkgs/pillow/distros/debian.txt new file mode 100644 index 00000000000..3319fcd7e0f --- /dev/null +++ b/build/pkgs/pillow/distros/debian.txt @@ -0,0 +1 @@ +python3-pillow diff --git a/build/pkgs/pillow/distros/fedora.txt b/build/pkgs/pillow/distros/fedora.txt new file mode 100644 index 00000000000..86dbb1d13b8 --- /dev/null +++ b/build/pkgs/pillow/distros/fedora.txt @@ -0,0 +1 @@ +python-pillow diff --git a/build/pkgs/pillow/distros/gentoo.txt b/build/pkgs/pillow/distros/gentoo.txt new file mode 100644 index 00000000000..12436496ed4 --- /dev/null +++ b/build/pkgs/pillow/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pillow diff --git a/build/pkgs/pillow/distros/opensuse.txt b/build/pkgs/pillow/distros/opensuse.txt index 88283bea6d9..8261b108af6 100644 --- a/build/pkgs/pillow/distros/opensuse.txt +++ b/build/pkgs/pillow/distros/opensuse.txt @@ -1 +1 @@ -python3-Pillow +python3${PYTHON_MINOR}-Pillow diff --git a/build/pkgs/pillow/spkg-configure.m4 b/build/pkgs/pillow/spkg-configure.m4 new file mode 100644 index 00000000000..f2e68e230ac --- /dev/null +++ b/build/pkgs/pillow/spkg-configure.m4 @@ -0,0 +1,5 @@ +SAGE_SPKG_CONFIGURE([pillow], [ + SAGE_SPKG_DEPCHECK([bzip2 freetype libpng zlib], [ + SAGE_PYTHON_PACKAGE_CHECK([pillow]) + ]) +]) diff --git a/build/pkgs/pint/dependencies b/build/pkgs/pint/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pint/dependencies +++ b/build/pkgs/pint/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pip/dependencies b/build/pkgs/pip/dependencies index 618d627629a..dac3579f7e3 100644 --- a/build/pkgs/pip/dependencies +++ b/build/pkgs/pip/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) setuptools wheel + setuptools wheel | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pip/distros/debian.txt b/build/pkgs/pip/distros/debian.txt new file mode 100644 index 00000000000..39bd9fc5097 --- /dev/null +++ b/build/pkgs/pip/distros/debian.txt @@ -0,0 +1 @@ +python3-pip diff --git a/build/pkgs/pip/distros/fedora.txt b/build/pkgs/pip/distros/fedora.txt new file mode 100644 index 00000000000..311c1b821ca --- /dev/null +++ b/build/pkgs/pip/distros/fedora.txt @@ -0,0 +1 @@ +python-pip diff --git a/build/pkgs/pip/distros/freebsd.txt b/build/pkgs/pip/distros/freebsd.txt new file mode 100644 index 00000000000..7b125c1bfa4 --- /dev/null +++ b/build/pkgs/pip/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-pip diff --git a/build/pkgs/pip/distros/gentoo.txt b/build/pkgs/pip/distros/gentoo.txt new file mode 100644 index 00000000000..793fb731829 --- /dev/null +++ b/build/pkgs/pip/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pip diff --git a/build/pkgs/pip/distros/opensuse.txt b/build/pkgs/pip/distros/opensuse.txt index 39bd9fc5097..eb4aa7ea9f1 100644 --- a/build/pkgs/pip/distros/opensuse.txt +++ b/build/pkgs/pip/distros/opensuse.txt @@ -1 +1 @@ -python3-pip +python3${PYTHON_MINOR}-pip diff --git a/build/pkgs/pip/install-requires.txt b/build/pkgs/pip/install-requires.txt index 7af2e246633..5e76a10f694 100644 --- a/build/pkgs/pip/install-requires.txt +++ b/build/pkgs/pip/install-requires.txt @@ -1,2 +1,3 @@ -pip >=21.3 +pip >=22.1 # for use of the "in-tree-build" feature, default since 21.3, by the Sage distribution +# for use of --config-settings, 22.1 diff --git a/build/pkgs/pip/spkg-configure.m4 b/build/pkgs/pip/spkg-configure.m4 new file mode 100644 index 00000000000..c7a55621f48 --- /dev/null +++ b/build/pkgs/pip/spkg-configure.m4 @@ -0,0 +1,12 @@ +SAGE_SPKG_CONFIGURE([pip], [ + dnl always run this macro because it changes the default value of + dnl the --with-system- option. + SAGE_PYTHON_PACKAGE_CHECK([pip]) + + dnl if we might not install the spkg, make sure that "pip" is in + dnl the user's PATH, too. + AS_IF([test "x$sage_spkg_install_pip" != "xyes"], [ + AC_CHECK_PROG(HAVE_PIP, pip, yes, no) + AS_IF([test "x$HAVE_PIP" = "xno"], [sage_spkg_install_pip=yes]) + ]) +]) diff --git a/build/pkgs/pkgconfig/dependencies b/build/pkgs/pkgconfig/dependencies index 6dfe046e55e..b52668ccb01 100644 --- a/build/pkgs/pkgconfig/dependencies +++ b/build/pkgs/pkgconfig/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) pkgconf poetry_core + | $(PYTHON_TOOLCHAIN) pkgconf poetry_core $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pkgconfig/distros/arch.txt b/build/pkgs/pkgconfig/distros/arch.txt new file mode 100644 index 00000000000..38a18b3565f --- /dev/null +++ b/build/pkgs/pkgconfig/distros/arch.txt @@ -0,0 +1 @@ +python-pkgconfig diff --git a/build/pkgs/pkgconfig/distros/debian.txt b/build/pkgs/pkgconfig/distros/debian.txt new file mode 100644 index 00000000000..38e5106dd74 --- /dev/null +++ b/build/pkgs/pkgconfig/distros/debian.txt @@ -0,0 +1 @@ +python3-pkgconfig diff --git a/build/pkgs/pkgconfig/distros/fedora.txt b/build/pkgs/pkgconfig/distros/fedora.txt new file mode 100644 index 00000000000..38a18b3565f --- /dev/null +++ b/build/pkgs/pkgconfig/distros/fedora.txt @@ -0,0 +1 @@ +python-pkgconfig diff --git a/build/pkgs/pkgconfig/distros/freebsd.txt b/build/pkgs/pkgconfig/distros/freebsd.txt new file mode 100644 index 00000000000..d26a4e96787 --- /dev/null +++ b/build/pkgs/pkgconfig/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-pkgconfig diff --git a/build/pkgs/pkgconfig/distros/gentoo.txt b/build/pkgs/pkgconfig/distros/gentoo.txt new file mode 100644 index 00000000000..32e86187155 --- /dev/null +++ b/build/pkgs/pkgconfig/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pkgconfig diff --git a/build/pkgs/pkgconfig/spkg-configure.m4 b/build/pkgs/pkgconfig/spkg-configure.m4 new file mode 100644 index 00000000000..67082934525 --- /dev/null +++ b/build/pkgs/pkgconfig/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pkgconfig], [SAGE_PYTHON_PACKAGE_CHECK([pkgconfig])]) diff --git a/build/pkgs/platformdirs/checksums.ini b/build/pkgs/platformdirs/checksums.ini index 604aa7f6c99..288483e8fc2 100644 --- a/build/pkgs/platformdirs/checksums.ini +++ b/build/pkgs/platformdirs/checksums.ini @@ -1,5 +1,5 @@ tarball=platformdirs-VERSION.tar.gz -sha1=082974f7d3ea03adfa147f4ab5be76079c2a116f -md5=f449b7f3767577fa2a57465a4523e92e -cksum=2966639810 +sha1=c4e0f8486e67a97affbc1b6b267a1f196c4177fa +md5=1c1c8c05e9bc370b78e0a95103523b75 +cksum=4231977838 upstream_url=https://pypi.io/packages/source/p/platformdirs/platformdirs-VERSION.tar.gz diff --git a/build/pkgs/platformdirs/dependencies b/build/pkgs/platformdirs/dependencies index 5b4aec583a4..952ebfb66cd 100644 --- a/build/pkgs/platformdirs/dependencies +++ b/build/pkgs/platformdirs/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) setuptools_scm | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs + setuptools_scm | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/platformdirs/distros/gentoo.txt b/build/pkgs/platformdirs/distros/gentoo.txt new file mode 100644 index 00000000000..e25e3dd9e9d --- /dev/null +++ b/build/pkgs/platformdirs/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/platformdirs diff --git a/build/pkgs/platformdirs/package-version.txt b/build/pkgs/platformdirs/package-version.txt index fe16b348d97..30291cba223 100644 --- a/build/pkgs/platformdirs/package-version.txt +++ b/build/pkgs/platformdirs/package-version.txt @@ -1 +1 @@ -2.5.4 +3.10.0 diff --git a/build/pkgs/platformdirs/spkg-configure.m4 b/build/pkgs/platformdirs/spkg-configure.m4 new file mode 100644 index 00000000000..a01f0dd4912 --- /dev/null +++ b/build/pkgs/platformdirs/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([platformdirs], [SAGE_PYTHON_PACKAGE_CHECK([platformdirs])]) diff --git a/build/pkgs/pluggy/checksums.ini b/build/pkgs/pluggy/checksums.ini index 087f36ad1a6..02c89db5e83 100644 --- a/build/pkgs/pluggy/checksums.ini +++ b/build/pkgs/pluggy/checksums.ini @@ -1,5 +1,5 @@ -tarball=pluggy-VERSION.tar.gz -sha1=0486bc511fc3415bb84252339b63b9d9e6d0734a -md5=daa6fddfb6cd364f3c82e52098911e4b -cksum=996010694 -upstream_url=https://pypi.io/packages/source/p/pluggy/pluggy-VERSION.tar.gz +tarball=pluggy-VERSION-py3-none-any.whl +sha1=25492905db99a151fc86368f0cca518a5ee5a832 +md5=9d0a58f023a0642eebae7c19f2729b72 +cksum=273236458 +upstream_url=https://pypi.io/packages/py3/p/pluggy/pluggy-VERSION-py3-none-any.whl diff --git a/build/pkgs/pluggy/dependencies b/build/pkgs/pluggy/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pluggy/dependencies +++ b/build/pkgs/pluggy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pluggy/distros/arch.txt b/build/pkgs/pluggy/distros/arch.txt new file mode 100644 index 00000000000..c869e54c551 --- /dev/null +++ b/build/pkgs/pluggy/distros/arch.txt @@ -0,0 +1 @@ +python-pluggy diff --git a/build/pkgs/pluggy/distros/debian.txt b/build/pkgs/pluggy/distros/debian.txt new file mode 100644 index 00000000000..43a3acf0462 --- /dev/null +++ b/build/pkgs/pluggy/distros/debian.txt @@ -0,0 +1 @@ +python3-pluggy diff --git a/build/pkgs/pluggy/distros/fedora.txt b/build/pkgs/pluggy/distros/fedora.txt new file mode 100644 index 00000000000..c869e54c551 --- /dev/null +++ b/build/pkgs/pluggy/distros/fedora.txt @@ -0,0 +1 @@ +python-pluggy diff --git a/build/pkgs/pluggy/distros/gentoo.txt b/build/pkgs/pluggy/distros/gentoo.txt new file mode 100644 index 00000000000..7b338764374 --- /dev/null +++ b/build/pkgs/pluggy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pluggy diff --git a/build/pkgs/pluggy/distros/opensuse.txt b/build/pkgs/pluggy/distros/opensuse.txt new file mode 100644 index 00000000000..42720b43944 --- /dev/null +++ b/build/pkgs/pluggy/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-pluggy diff --git a/build/pkgs/pluggy/package-version.txt b/build/pkgs/pluggy/package-version.txt index 3eefcb9dd5b..f0bb29e7638 100644 --- a/build/pkgs/pluggy/package-version.txt +++ b/build/pkgs/pluggy/package-version.txt @@ -1 +1 @@ -1.0.0 +1.3.0 diff --git a/build/pkgs/pluggy/spkg-configure.m4 b/build/pkgs/pluggy/spkg-configure.m4 new file mode 100644 index 00000000000..11b1fce4f94 --- /dev/null +++ b/build/pkgs/pluggy/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pluggy], [SAGE_PYTHON_PACKAGE_CHECK([pluggy])]) diff --git a/build/pkgs/pluggy/spkg-install.in b/build/pkgs/pluggy/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/pluggy/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/ply/dependencies b/build/pkgs/ply/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/ply/dependencies +++ b/build/pkgs/ply/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ply/distros/gentoo.txt b/build/pkgs/ply/distros/gentoo.txt new file mode 100644 index 00000000000..c8b16309b09 --- /dev/null +++ b/build/pkgs/ply/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/ply diff --git a/build/pkgs/ply/spkg-configure.m4 b/build/pkgs/ply/spkg-configure.m4 new file mode 100644 index 00000000000..ffb0030d013 --- /dev/null +++ b/build/pkgs/ply/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([ply], [SAGE_PYTHON_PACKAGE_CHECK([ply])]) diff --git a/build/pkgs/poetry_core/dependencies b/build/pkgs/poetry_core/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/poetry_core/dependencies +++ b/build/pkgs/poetry_core/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pplpy/dependencies b/build/pkgs/pplpy/dependencies index 84d4fbab430..f61061ddefe 100644 --- a/build/pkgs/pplpy/dependencies +++ b/build/pkgs/pplpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(MP_LIBRARY) gmpy2 cysignals mpfr mpc ppl | $(PYTHON_TOOLCHAIN) sphinx + $(MP_LIBRARY) gmpy2 cysignals mpfr mpc ppl | $(PYTHON_TOOLCHAIN) sphinx $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pplpy/distros/arch.txt b/build/pkgs/pplpy/distros/arch.txt new file mode 100644 index 00000000000..579bdb042f6 --- /dev/null +++ b/build/pkgs/pplpy/distros/arch.txt @@ -0,0 +1 @@ +python-pplpy diff --git a/build/pkgs/pplpy/distros/fedora.txt b/build/pkgs/pplpy/distros/fedora.txt new file mode 100644 index 00000000000..579bdb042f6 --- /dev/null +++ b/build/pkgs/pplpy/distros/fedora.txt @@ -0,0 +1 @@ +python-pplpy diff --git a/build/pkgs/pplpy/distros/freebsd.txt b/build/pkgs/pplpy/distros/freebsd.txt new file mode 100644 index 00000000000..2006f870646 --- /dev/null +++ b/build/pkgs/pplpy/distros/freebsd.txt @@ -0,0 +1 @@ +math/py-pplpy diff --git a/build/pkgs/pplpy/distros/void.txt b/build/pkgs/pplpy/distros/void.txt new file mode 100644 index 00000000000..f39eaff76ae --- /dev/null +++ b/build/pkgs/pplpy/distros/void.txt @@ -0,0 +1 @@ +python3-pplpy diff --git a/build/pkgs/primecountpy/dependencies b/build/pkgs/primecountpy/dependencies index c141a1d7c2f..ce1374b2a0e 100644 --- a/build/pkgs/primecountpy/dependencies +++ b/build/pkgs/primecountpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) primecount cysignals | $(PYTHON_TOOLCHAIN) cython + primecount cysignals | $(PYTHON_TOOLCHAIN) cython $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/prometheus_client/dependencies b/build/pkgs/prometheus_client/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/prometheus_client/dependencies +++ b/build/pkgs/prometheus_client/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/prometheus_client/distros/gentoo.txt b/build/pkgs/prometheus_client/distros/gentoo.txt new file mode 100644 index 00000000000..aa2889c913e --- /dev/null +++ b/build/pkgs/prometheus_client/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/prometheus_client diff --git a/build/pkgs/prometheus_client/distros/opensuse.txt b/build/pkgs/prometheus_client/distros/opensuse.txt index 4d7723ec37e..c061661b6e6 100644 --- a/build/pkgs/prometheus_client/distros/opensuse.txt +++ b/build/pkgs/prometheus_client/distros/opensuse.txt @@ -1 +1 @@ -python3-prometheus_client +python3${PYTHON_MINOR}-prometheus_client diff --git a/build/pkgs/prometheus_client/spkg-configure.m4 b/build/pkgs/prometheus_client/spkg-configure.m4 new file mode 100644 index 00000000000..b4945889131 --- /dev/null +++ b/build/pkgs/prometheus_client/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([prometheus_client], [ + SAGE_PYTHON_PACKAGE_CHECK([prometheus_client]) +]) diff --git a/build/pkgs/prompt_toolkit/dependencies b/build/pkgs/prompt_toolkit/dependencies index 57465daf937..2bdb6af86bc 100644 --- a/build/pkgs/prompt_toolkit/dependencies +++ b/build/pkgs/prompt_toolkit/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) six wcwidth | $(PYTHON_TOOLCHAIN) + six wcwidth | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/prompt_toolkit/distros/arch.txt b/build/pkgs/prompt_toolkit/distros/arch.txt new file mode 100644 index 00000000000..89b0ac83a9b --- /dev/null +++ b/build/pkgs/prompt_toolkit/distros/arch.txt @@ -0,0 +1 @@ +python-importlib_resources diff --git a/build/pkgs/prompt_toolkit/distros/debian.txt b/build/pkgs/prompt_toolkit/distros/debian.txt new file mode 100644 index 00000000000..2b0146fc669 --- /dev/null +++ b/build/pkgs/prompt_toolkit/distros/debian.txt @@ -0,0 +1 @@ +importlib-resources diff --git a/build/pkgs/prompt_toolkit/distros/fedora.txt b/build/pkgs/prompt_toolkit/distros/fedora.txt new file mode 100644 index 00000000000..967f8570d4f --- /dev/null +++ b/build/pkgs/prompt_toolkit/distros/fedora.txt @@ -0,0 +1 @@ +python-prompt-toolkit diff --git a/build/pkgs/prompt_toolkit/distros/freebsd.txt b/build/pkgs/prompt_toolkit/distros/freebsd.txt new file mode 100644 index 00000000000..a2f0c05129b --- /dev/null +++ b/build/pkgs/prompt_toolkit/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-importlib-resources diff --git a/build/pkgs/prompt_toolkit/distros/gentoo.txt b/build/pkgs/prompt_toolkit/distros/gentoo.txt new file mode 100644 index 00000000000..6902484e74c --- /dev/null +++ b/build/pkgs/prompt_toolkit/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/prompt_toolkit diff --git a/build/pkgs/prompt_toolkit/distros/opensuse.txt b/build/pkgs/prompt_toolkit/distros/opensuse.txt index 424253f1340..3c48b809bc1 100644 --- a/build/pkgs/prompt_toolkit/distros/opensuse.txt +++ b/build/pkgs/prompt_toolkit/distros/opensuse.txt @@ -1 +1 @@ -python3-prompt_toolkit +python3${PYTHON_MINOR}-importlib_resources diff --git a/build/pkgs/prompt_toolkit/spkg-configure.m4 b/build/pkgs/prompt_toolkit/spkg-configure.m4 new file mode 100644 index 00000000000..fd8c1a67015 --- /dev/null +++ b/build/pkgs/prompt_toolkit/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([prompt_toolkit], [ + SAGE_PYTHON_PACKAGE_CHECK([prompt_toolkit]) +]) diff --git a/build/pkgs/ptyprocess/dependencies b/build/pkgs/ptyprocess/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/ptyprocess/dependencies +++ b/build/pkgs/ptyprocess/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ptyprocess/distros/arch.txt b/build/pkgs/ptyprocess/distros/arch.txt new file mode 100644 index 00000000000..911a22468fc --- /dev/null +++ b/build/pkgs/ptyprocess/distros/arch.txt @@ -0,0 +1 @@ +python-ptyprocess diff --git a/build/pkgs/ptyprocess/distros/fedora.txt b/build/pkgs/ptyprocess/distros/fedora.txt new file mode 100644 index 00000000000..911a22468fc --- /dev/null +++ b/build/pkgs/ptyprocess/distros/fedora.txt @@ -0,0 +1 @@ +python-ptyprocess diff --git a/build/pkgs/ptyprocess/distros/freebsd.txt b/build/pkgs/ptyprocess/distros/freebsd.txt new file mode 100644 index 00000000000..bc587f2e5fc --- /dev/null +++ b/build/pkgs/ptyprocess/distros/freebsd.txt @@ -0,0 +1 @@ +sysutils/py-ptyprocess diff --git a/build/pkgs/ptyprocess/distros/gentoo.txt b/build/pkgs/ptyprocess/distros/gentoo.txt new file mode 100644 index 00000000000..571a851d976 --- /dev/null +++ b/build/pkgs/ptyprocess/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/ptyprocess diff --git a/build/pkgs/ptyprocess/distros/opensuse.txt b/build/pkgs/ptyprocess/distros/opensuse.txt index ad4f6db1ca7..846495a86e8 100644 --- a/build/pkgs/ptyprocess/distros/opensuse.txt +++ b/build/pkgs/ptyprocess/distros/opensuse.txt @@ -1 +1 @@ -python3-ptyprocess +python3${PYTHON_MINOR}-ptyprocess diff --git a/build/pkgs/ptyprocess/spkg-configure.m4 b/build/pkgs/ptyprocess/spkg-configure.m4 new file mode 100644 index 00000000000..bfacbaed935 --- /dev/null +++ b/build/pkgs/ptyprocess/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([ptyprocess], [SAGE_PYTHON_PACKAGE_CHECK([ptyprocess])]) diff --git a/build/pkgs/pure_eval/dependencies b/build/pkgs/pure_eval/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pure_eval/dependencies +++ b/build/pkgs/pure_eval/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pure_eval/distros/gentoo.txt b/build/pkgs/pure_eval/distros/gentoo.txt new file mode 100644 index 00000000000..9905067ea96 --- /dev/null +++ b/build/pkgs/pure_eval/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pure_eval diff --git a/build/pkgs/pure_eval/spkg-configure.m4 b/build/pkgs/pure_eval/spkg-configure.m4 new file mode 100644 index 00000000000..5b6ef2d4a6b --- /dev/null +++ b/build/pkgs/pure_eval/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pure_eval], [SAGE_PYTHON_PACKAGE_CHECK([pure_eval])]) diff --git a/build/pkgs/py/dependencies b/build/pkgs/py/dependencies index 14a312e5dee..995ddecb8f4 100644 --- a/build/pkgs/py/dependencies +++ b/build/pkgs/py/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) setuptools_scm + | $(PYTHON_TOOLCHAIN) setuptools_scm $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/py/distros/arch.txt b/build/pkgs/py/distros/arch.txt new file mode 100644 index 00000000000..b348d395fbd --- /dev/null +++ b/build/pkgs/py/distros/arch.txt @@ -0,0 +1 @@ +python-py diff --git a/build/pkgs/py/distros/debian.txt b/build/pkgs/py/distros/debian.txt new file mode 100644 index 00000000000..81fefe60903 --- /dev/null +++ b/build/pkgs/py/distros/debian.txt @@ -0,0 +1 @@ +python3-py diff --git a/build/pkgs/py/distros/fedora.txt b/build/pkgs/py/distros/fedora.txt new file mode 100644 index 00000000000..b348d395fbd --- /dev/null +++ b/build/pkgs/py/distros/fedora.txt @@ -0,0 +1 @@ +python-py diff --git a/build/pkgs/py/distros/opensuse.txt b/build/pkgs/py/distros/opensuse.txt new file mode 100644 index 00000000000..c03de61a449 --- /dev/null +++ b/build/pkgs/py/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-py diff --git a/build/pkgs/py/spkg-configure.m4 b/build/pkgs/py/spkg-configure.m4 new file mode 100644 index 00000000000..ded70343090 --- /dev/null +++ b/build/pkgs/py/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([py], [SAGE_PYTHON_PACKAGE_CHECK([py])]) diff --git a/build/pkgs/pybind11/checksums.ini b/build/pkgs/pybind11/checksums.ini index 1cc6d36c174..c8b9c661568 100644 --- a/build/pkgs/pybind11/checksums.ini +++ b/build/pkgs/pybind11/checksums.ini @@ -1,5 +1,5 @@ tarball=pybind11-VERSION.tar.gz -sha1=d0e6e22c2ce36fad4bb60dbac4d6d498ceb464df -md5=0b181dbb44c3cc632e724cef5081cae1 -cksum=4287838207 +sha1=3c75333a9056f0be18eb612803cd46a2bb0c87fc +md5=67c58224e41c442e47fa84e7789c2c39 +cksum=419587142 upstream_url=https://pypi.io/packages/source/p/pybind11/pybind11-VERSION.tar.gz diff --git a/build/pkgs/pybind11/dependencies b/build/pkgs/pybind11/dependencies index da2b0925acd..ca33204bd52 100644 --- a/build/pkgs/pybind11/dependencies +++ b/build/pkgs/pybind11/dependencies @@ -1 +1 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) diff --git a/build/pkgs/pybind11/distros/gentoo.txt b/build/pkgs/pybind11/distros/gentoo.txt new file mode 100644 index 00000000000..0c500b3c84d --- /dev/null +++ b/build/pkgs/pybind11/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pybind11 diff --git a/build/pkgs/pybind11/install-requires.txt b/build/pkgs/pybind11/install-requires.txt index 7f37917011f..6c44c4bd07e 100644 --- a/build/pkgs/pybind11/install-requires.txt +++ b/build/pkgs/pybind11/install-requires.txt @@ -1 +1 @@ -pybind11 >=2.5.0 +pybind11 >=2.6 diff --git a/build/pkgs/pybind11/package-version.txt b/build/pkgs/pybind11/package-version.txt index 8bbb6e406a7..6ceb272eecd 100644 --- a/build/pkgs/pybind11/package-version.txt +++ b/build/pkgs/pybind11/package-version.txt @@ -1 +1 @@ -2.10.1 +2.11.1 diff --git a/build/pkgs/pybind11/spkg-configure.m4 b/build/pkgs/pybind11/spkg-configure.m4 new file mode 100644 index 00000000000..cce1cf5cff8 --- /dev/null +++ b/build/pkgs/pybind11/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pybind11], [SAGE_PYTHON_PACKAGE_CHECK([pybind11])]) diff --git a/build/pkgs/pybtex/distros/opensuse.txt b/build/pkgs/pybtex/distros/opensuse.txt index bdd39a48fde..e482a1bfea0 100644 --- a/build/pkgs/pybtex/distros/opensuse.txt +++ b/build/pkgs/pybtex/distros/opensuse.txt @@ -1 +1 @@ -python3-pybtex +python3${PYTHON_MINOR}-pybtex diff --git a/build/pkgs/pycosat/dependencies b/build/pkgs/pycosat/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pycosat/dependencies +++ b/build/pkgs/pycosat/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pycosat/distros/alpine.txt b/build/pkgs/pycosat/distros/alpine.txt new file mode 100644 index 00000000000..7eb034d6713 --- /dev/null +++ b/build/pkgs/pycosat/distros/alpine.txt @@ -0,0 +1 @@ +py3-pycosat diff --git a/build/pkgs/pycosat/distros/arch.txt b/build/pkgs/pycosat/distros/arch.txt new file mode 100644 index 00000000000..dab3122ef4c --- /dev/null +++ b/build/pkgs/pycosat/distros/arch.txt @@ -0,0 +1 @@ +python-pycosat diff --git a/build/pkgs/pycosat/distros/fedora.txt b/build/pkgs/pycosat/distros/fedora.txt new file mode 100644 index 00000000000..dab3122ef4c --- /dev/null +++ b/build/pkgs/pycosat/distros/fedora.txt @@ -0,0 +1 @@ +python-pycosat diff --git a/build/pkgs/pycosat/distros/freebsd.txt b/build/pkgs/pycosat/distros/freebsd.txt new file mode 100644 index 00000000000..35e4e7730cc --- /dev/null +++ b/build/pkgs/pycosat/distros/freebsd.txt @@ -0,0 +1 @@ +math/py-pycosat diff --git a/build/pkgs/pycparser/dependencies b/build/pkgs/pycparser/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pycparser/dependencies +++ b/build/pkgs/pycparser/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pycparser/distros/gentoo.txt b/build/pkgs/pycparser/distros/gentoo.txt new file mode 100644 index 00000000000..5e87307c4b9 --- /dev/null +++ b/build/pkgs/pycparser/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pycparser diff --git a/build/pkgs/pycparser/distros/opensuse.txt b/build/pkgs/pycparser/distros/opensuse.txt index 0ba4f8b19f5..503e7c176d1 100644 --- a/build/pkgs/pycparser/distros/opensuse.txt +++ b/build/pkgs/pycparser/distros/opensuse.txt @@ -1 +1 @@ -python3-pycparser +python3${PYTHON_MINOR}-pycparser diff --git a/build/pkgs/pycparser/spkg-configure.m4 b/build/pkgs/pycparser/spkg-configure.m4 new file mode 100644 index 00000000000..4b9b90079a9 --- /dev/null +++ b/build/pkgs/pycparser/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pycparser], [SAGE_PYTHON_PACKAGE_CHECK([pycparser])]) diff --git a/build/pkgs/pycryptosat/dependencies b/build/pkgs/pycryptosat/dependencies index b897ff72eae..c51735427aa 100644 --- a/build/pkgs/pycryptosat/dependencies +++ b/build/pkgs/pycryptosat/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) m4ri zlib libpng cryptominisat | cmake boost_cropped $(PYTHON_TOOLCHAIN) + m4ri zlib libpng cryptominisat | cmake boost_cropped $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pycygwin/dependencies b/build/pkgs/pycygwin/dependencies index 296a2bebad3..1db13c07e43 100644 --- a/build/pkgs/pycygwin/dependencies +++ b/build/pkgs/pycygwin/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython | $(PYTHON_TOOLCHAIN) + cython | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pygments/dependencies b/build/pkgs/pygments/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pygments/dependencies +++ b/build/pkgs/pygments/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pygments/distros/arch.txt b/build/pkgs/pygments/distros/arch.txt new file mode 100644 index 00000000000..f3e72a89c38 --- /dev/null +++ b/build/pkgs/pygments/distros/arch.txt @@ -0,0 +1 @@ +python-pygments diff --git a/build/pkgs/pygments/distros/debian.txt b/build/pkgs/pygments/distros/debian.txt new file mode 100644 index 00000000000..3ab37929b2c --- /dev/null +++ b/build/pkgs/pygments/distros/debian.txt @@ -0,0 +1 @@ +python3-pygments diff --git a/build/pkgs/pygments/distros/fedora.txt b/build/pkgs/pygments/distros/fedora.txt new file mode 100644 index 00000000000..f3e72a89c38 --- /dev/null +++ b/build/pkgs/pygments/distros/fedora.txt @@ -0,0 +1 @@ +python-pygments diff --git a/build/pkgs/pygments/distros/gentoo.txt b/build/pkgs/pygments/distros/gentoo.txt new file mode 100644 index 00000000000..a584f321e71 --- /dev/null +++ b/build/pkgs/pygments/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pygments diff --git a/build/pkgs/pygments/distros/opensuse.txt b/build/pkgs/pygments/distros/opensuse.txt index 9ff5740e79c..ef63366ff27 100644 --- a/build/pkgs/pygments/distros/opensuse.txt +++ b/build/pkgs/pygments/distros/opensuse.txt @@ -1 +1 @@ -python3-Pygments +python3${PYTHON_MINOR}-pygments diff --git a/build/pkgs/pygments/install-requires.txt b/build/pkgs/pygments/install-requires.txt index 0d0dc97d523..337e5bbad8b 100644 --- a/build/pkgs/pygments/install-requires.txt +++ b/build/pkgs/pygments/install-requires.txt @@ -1 +1 @@ -pygments >=2.3.1 +pygments >=2.12 diff --git a/build/pkgs/pygments/spkg-configure.m4 b/build/pkgs/pygments/spkg-configure.m4 new file mode 100644 index 00000000000..99f29e3c9b3 --- /dev/null +++ b/build/pkgs/pygments/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pygments], [SAGE_PYTHON_PACKAGE_CHECK([pygments])]) diff --git a/build/pkgs/pygraphviz/dependencies b/build/pkgs/pygraphviz/dependencies index 232dc205925..a723707e09c 100644 --- a/build/pkgs/pygraphviz/dependencies +++ b/build/pkgs/pygraphviz/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) libgraphviz | $(PYTHON_TOOLCHAIN) + libgraphviz | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pynormaliz/dependencies b/build/pkgs/pynormaliz/dependencies index 76200c19d23..1fca858579e 100644 --- a/build/pkgs/pynormaliz/dependencies +++ b/build/pkgs/pynormaliz/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) normaliz | $(PYTHON_TOOLCHAIN) + normaliz | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyparsing/dependencies b/build/pkgs/pyparsing/dependencies index 2471ffdf59d..22915b3da68 100644 --- a/build/pkgs/pyparsing/dependencies +++ b/build/pkgs/pyparsing/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | pip wheel flit_core tomli + | pip wheel flit_core tomli $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyparsing/distros/arch.txt b/build/pkgs/pyparsing/distros/arch.txt new file mode 100644 index 00000000000..428820c215f --- /dev/null +++ b/build/pkgs/pyparsing/distros/arch.txt @@ -0,0 +1 @@ +python-pyparsing diff --git a/build/pkgs/pyparsing/distros/freebsd.txt b/build/pkgs/pyparsing/distros/freebsd.txt new file mode 100644 index 00000000000..39fdc921fd0 --- /dev/null +++ b/build/pkgs/pyparsing/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-pyparsing diff --git a/build/pkgs/pyparsing/distros/gentoo.txt b/build/pkgs/pyparsing/distros/gentoo.txt new file mode 100644 index 00000000000..ef0419f9cbc --- /dev/null +++ b/build/pkgs/pyparsing/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pyparsing diff --git a/build/pkgs/pyparsing/distros/opensuse.txt b/build/pkgs/pyparsing/distros/opensuse.txt index 492a7ce0a69..2a91a003cf9 100644 --- a/build/pkgs/pyparsing/distros/opensuse.txt +++ b/build/pkgs/pyparsing/distros/opensuse.txt @@ -1 +1 @@ -python3-pyparsing +python3${PYTHON_MINOR}-pyparsing diff --git a/build/pkgs/pyparsing/spkg-configure.m4 b/build/pkgs/pyparsing/spkg-configure.m4 new file mode 100644 index 00000000000..d2b4c0055e4 --- /dev/null +++ b/build/pkgs/pyparsing/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pyparsing], [SAGE_PYTHON_PACKAGE_CHECK([pyparsing])]) diff --git a/build/pkgs/pyppeteer/dependencies b/build/pkgs/pyppeteer/dependencies index 1c2d4afb8d4..7d9ec36f9c7 100644 --- a/build/pkgs/pyppeteer/dependencies +++ b/build/pkgs/pyppeteer/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) appdirs importlib_metadata urllib3 certifi | $(PYTHON_TOOLCHAIN) + appdirs importlib_metadata urllib3 certifi | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyproject_api/SPKG.rst b/build/pkgs/pyproject_api/SPKG.rst new file mode 100644 index 00000000000..521b15e35d6 --- /dev/null +++ b/build/pkgs/pyproject_api/SPKG.rst @@ -0,0 +1,16 @@ +pyproject_api: API to interact with the python pyproject.toml based projects +============================================================================ + +Description +----------- + +API to interact with the python pyproject.toml based projects + +License +------- + +Upstream Contact +---------------- + +https://pypi.org/project/pyproject-api/ + diff --git a/build/pkgs/pyproject_api/checksums.ini b/build/pkgs/pyproject_api/checksums.ini new file mode 100644 index 00000000000..9fc8e383a7c --- /dev/null +++ b/build/pkgs/pyproject_api/checksums.ini @@ -0,0 +1,5 @@ +tarball=pyproject_api-VERSION-py3-none-any.whl +sha1=5ea24c784a68fd0ef0228c332dc078ce64387eb8 +md5=8941280ffec3eb79a8cd6e380774980f +cksum=913049079 +upstream_url=https://pypi.io/packages/py3/p/pyproject_api/pyproject_api-VERSION-py3-none-any.whl diff --git a/build/pkgs/pyproject_api/dependencies b/build/pkgs/pyproject_api/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/pyproject_api/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/pyproject_api/install-requires.txt b/build/pkgs/pyproject_api/install-requires.txt new file mode 100644 index 00000000000..3f2ab4cb2a0 --- /dev/null +++ b/build/pkgs/pyproject_api/install-requires.txt @@ -0,0 +1 @@ +pyproject-api diff --git a/build/pkgs/pyproject_api/package-version.txt b/build/pkgs/pyproject_api/package-version.txt new file mode 100644 index 00000000000..9c6d6293b1a --- /dev/null +++ b/build/pkgs/pyproject_api/package-version.txt @@ -0,0 +1 @@ +1.6.1 diff --git a/build/pkgs/pyproject_api/type b/build/pkgs/pyproject_api/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/pyproject_api/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/pyproject_metadata/checksums.ini b/build/pkgs/pyproject_metadata/checksums.ini index 4fcc0ec49c2..6fb14a63679 100644 --- a/build/pkgs/pyproject_metadata/checksums.ini +++ b/build/pkgs/pyproject_metadata/checksums.ini @@ -1,5 +1,5 @@ tarball=pyproject-metadata-VERSION.tar.gz -sha1=c2b7679b1e56a341aa00c186c0d1a6bbd7bd5c2c -md5=e13b11cb723da96f8397addddca963cc -cksum=2246727402 +sha1=41fba5c33917d77b9364fadb76e590e86789634d +md5=ca5e9527cff96153a976e14530b53746 +cksum=2053869519 upstream_url=https://pypi.io/packages/source/p/pyproject_metadata/pyproject-metadata-VERSION.tar.gz diff --git a/build/pkgs/pyproject_metadata/dependencies b/build/pkgs/pyproject_metadata/dependencies index 6d5368db738..3df264eee42 100644 --- a/build/pkgs/pyproject_metadata/dependencies +++ b/build/pkgs/pyproject_metadata/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) packaging pyparsing | $(PYTHON_TOOLCHAIN) + packaging pyparsing | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyproject_metadata/distros/gentoo.txt b/build/pkgs/pyproject_metadata/distros/gentoo.txt new file mode 100644 index 00000000000..f4acf389e43 --- /dev/null +++ b/build/pkgs/pyproject_metadata/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pyproject-metadata diff --git a/build/pkgs/pyproject_metadata/package-version.txt b/build/pkgs/pyproject_metadata/package-version.txt index ee6cdce3c29..39e898a4f95 100644 --- a/build/pkgs/pyproject_metadata/package-version.txt +++ b/build/pkgs/pyproject_metadata/package-version.txt @@ -1 +1 @@ -0.6.1 +0.7.1 diff --git a/build/pkgs/pyproject_metadata/spkg-configure.m4 b/build/pkgs/pyproject_metadata/spkg-configure.m4 new file mode 100644 index 00000000000..1e61f2eada6 --- /dev/null +++ b/build/pkgs/pyproject_metadata/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([pyproject_metadata], [ + SAGE_PYTHON_PACKAGE_CHECK([pyproject_metadata]) +]) diff --git a/build/pkgs/pyrsistent/dependencies b/build/pkgs/pyrsistent/dependencies index 4361e46ddaf..9be6b4aab7c 100644 --- a/build/pkgs/pyrsistent/dependencies +++ b/build/pkgs/pyrsistent/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) vcversioner | $(PYTHON_TOOLCHAIN) + vcversioner | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyrsistent/distros/gentoo.txt b/build/pkgs/pyrsistent/distros/gentoo.txt new file mode 100644 index 00000000000..83439cebfe4 --- /dev/null +++ b/build/pkgs/pyrsistent/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pyrsistent diff --git a/build/pkgs/pyrsistent/spkg-configure.m4 b/build/pkgs/pyrsistent/spkg-configure.m4 new file mode 100644 index 00000000000..f7ca75dbac5 --- /dev/null +++ b/build/pkgs/pyrsistent/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pyrsistent], [SAGE_PYTHON_PACKAGE_CHECK([pyrsistent])]) diff --git a/build/pkgs/pyscipopt/dependencies b/build/pkgs/pyscipopt/dependencies index 66f72c29e1a..3c4a108db0f 100644 --- a/build/pkgs/pyscipopt/dependencies +++ b/build/pkgs/pyscipopt/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) scip | $(PYTHON_TOOLCHAIN) cython + scip | $(PYTHON_TOOLCHAIN) cython $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pysingular/dependencies b/build/pkgs/pysingular/dependencies index bd58b826630..075bad15831 100644 --- a/build/pkgs/pysingular/dependencies +++ b/build/pkgs/pysingular/dependencies @@ -1 +1 @@ -$(PYTHON) singular | $(PYTHON_TOOLCHAIN) + singular | $(PYTHON_TOOLCHAIN) $(PYTHON) diff --git a/build/pkgs/pytest/dependencies b/build/pkgs/pytest/dependencies index 7e5a90a20bd..af3334a7daf 100644 --- a/build/pkgs/pytest/dependencies +++ b/build/pkgs/pytest/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pluggy packaging attrs py pyparsing importlib_metadata tomli | $(PYTHON_TOOLCHAIN) + pluggy packaging attrs py pyparsing importlib_metadata tomli | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pytest_mock/dependencies b/build/pkgs/pytest_mock/dependencies index 37ea60eb442..720c11ec214 100644 --- a/build/pkgs/pytest_mock/dependencies +++ b/build/pkgs/pytest_mock/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pytest packaging attrs pluggy tomli py pyparsing | $(PYTHON_TOOLCHAIN) + pytest packaging attrs pluggy tomli py pyparsing | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pytest_xdist/dependencies b/build/pkgs/pytest_xdist/dependencies index aa8c608f663..19d8b032667 100644 --- a/build/pkgs/pytest_xdist/dependencies +++ b/build/pkgs/pytest_xdist/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pytest | $(PYTHON_TOOLCHAIN) + pytest | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/python3/SPKG.rst b/build/pkgs/python3/SPKG.rst index 94a163de1f3..73c9f958f26 100644 --- a/build/pkgs/python3/SPKG.rst +++ b/build/pkgs/python3/SPKG.rst @@ -8,7 +8,7 @@ By default, Sage will try to use system's ``python3`` to set up a virtual environment, a.k.a. `venv `_ rather than building a Python 3 installation from scratch. -Sage will accept versions 3.8.x to 3.10.x. +Sage will accept versions 3.9.x to 3.10.x. You can also use ``--with-python=/path/to/python3_binary`` to tell Sage to use ``/path/to/python3_binary`` to set up the venv. Note that setting up the venv requires diff --git a/build/pkgs/python3/distros/opensuse.txt b/build/pkgs/python3/distros/opensuse.txt index 07358a92e89..760ddd76f2c 100644 --- a/build/pkgs/python3/distros/opensuse.txt +++ b/build/pkgs/python3/distros/opensuse.txt @@ -1 +1 @@ -python3-devel +python3${PYTHON_MINOR}-devel diff --git a/build/pkgs/python3/spkg-configure.m4 b/build/pkgs/python3/spkg-configure.m4 index 3efe191ff2c..d57aa416e3a 100644 --- a/build/pkgs/python3/spkg-configure.m4 +++ b/build/pkgs/python3/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([python3], [ - m4_pushdef([MIN_VERSION], [3.8.0]) - m4_pushdef([MIN_NONDEPRECATED_VERSION], [3.8.0]) + m4_pushdef([MIN_VERSION], [3.9.0]) + m4_pushdef([MIN_NONDEPRECATED_VERSION], [3.9.0]) m4_pushdef([LT_STABLE_VERSION], [3.12.0]) m4_pushdef([LT_VERSION], [3.12.0]) AC_ARG_WITH([python], @@ -130,17 +130,17 @@ To build Sage with a different system python, use ./configure --with-python=/pat ]) AC_SUBST([PYTHON_FOR_VENV]) + AS_IF([test -n "$PYTHON_FOR_VENV"], + [PYTHON_VERSION=$("$PYTHON_FOR_VENV" -c "import sysconfig; print(sysconfig.get_python_version())")], + [PYTHON_VERSION=$(echo $(cat build/pkgs/python3/package-version.txt))]) + AC_SUBST([PYTHON_MINOR], [$(echo $PYTHON_VERSION | cut -d. -f2)]) + export PYTHON_MINOR # for sage-get-system-packages + AS_VAR_IF([SAGE_VENV], [auto], [SAGE_VENV=$SAGE_VENV_AUTO]) AS_CASE([$SAGE_VENV], [no], [SAGE_VENV='${SAGE_LOCAL}'],dnl Quoted so that it is resolved at build time by shell/Makefile - [yes], [AS_IF([test -n "$PYTHON_FOR_VENV"], [ - PYTHON_VERSION=$("$PYTHON_FOR_VENV" -c "import sysconfig; print(sysconfig.get_python_version())") - ], [ - PYTHON_VERSION=$(echo $(cat build/pkgs/python3/package-version.txt)) - ]) - SAGE_VENV='${SAGE_LOCAL}'/var/lib/sage/venv-python$PYTHON_VERSION] + [yes], [SAGE_VENV='${SAGE_LOCAL}'/var/lib/sage/venv-python$PYTHON_VERSION] ) - dnl These temporary directories are created by the check above dnl and need to be cleaned up to prevent the "rm -f conftest*" dnl (that a bunch of other checks do) from emitting warnings about diff --git a/build/pkgs/python_build/dependencies b/build/pkgs/python_build/dependencies index 769e08a8c26..b72a6d1c776 100644 --- a/build/pkgs/python_build/dependencies +++ b/build/pkgs/python_build/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pyparsing tomli packaging | $(PYTHON_TOOLCHAIN) + pyparsing tomli packaging | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/python_igraph/dependencies b/build/pkgs/python_igraph/dependencies index 67ed15160f4..dde58706323 100644 --- a/build/pkgs/python_igraph/dependencies +++ b/build/pkgs/python_igraph/dependencies @@ -1,4 +1,4 @@ -igraph texttable $(PYTHON) | $(PYTHON_TOOLCHAIN) +igraph texttable | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/python_igraph/distros/arch.txt b/build/pkgs/python_igraph/distros/arch.txt new file mode 100644 index 00000000000..03f8142066f --- /dev/null +++ b/build/pkgs/python_igraph/distros/arch.txt @@ -0,0 +1 @@ +python-igraph diff --git a/build/pkgs/python_igraph/distros/debian.txt b/build/pkgs/python_igraph/distros/debian.txt new file mode 100644 index 00000000000..218ba998007 --- /dev/null +++ b/build/pkgs/python_igraph/distros/debian.txt @@ -0,0 +1 @@ +python3-igraph diff --git a/build/pkgs/python_igraph/distros/fedora.txt b/build/pkgs/python_igraph/distros/fedora.txt new file mode 100644 index 00000000000..03f8142066f --- /dev/null +++ b/build/pkgs/python_igraph/distros/fedora.txt @@ -0,0 +1 @@ +python-igraph diff --git a/build/pkgs/python_igraph/distros/freebsd.txt b/build/pkgs/python_igraph/distros/freebsd.txt new file mode 100644 index 00000000000..d86a516f3ed --- /dev/null +++ b/build/pkgs/python_igraph/distros/freebsd.txt @@ -0,0 +1 @@ +math/py-igraph diff --git a/build/pkgs/pythran/checksums.ini b/build/pkgs/pythran/checksums.ini index cb4704c4bc4..dc9beccf6b6 100644 --- a/build/pkgs/pythran/checksums.ini +++ b/build/pkgs/pythran/checksums.ini @@ -1,5 +1,5 @@ tarball=pythran-VERSION.tar.gz -sha1=71bc7c868cf011d184a013211f4195d8f9c606a2 -md5=168c31e8d108f26440b663b44cd99379 -cksum=2086161839 +sha1=dd675e9ccc93379b529687328ca558d5617eb1c6 +md5=3090288af50566af75cb058d1878aaad +cksum=3968085663 upstream_url=https://pypi.io/packages/source/p/pythran/pythran-VERSION.tar.gz diff --git a/build/pkgs/pythran/dependencies b/build/pkgs/pythran/dependencies index 8a64589c0bc..3845adb7a2c 100644 --- a/build/pkgs/pythran/dependencies +++ b/build/pkgs/pythran/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) beniget gast ply numpy | $(PYTHON_TOOLCHAIN) + beniget gast ply numpy | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pythran/distros/gentoo.txt b/build/pkgs/pythran/distros/gentoo.txt new file mode 100644 index 00000000000..1bb7cdcd4eb --- /dev/null +++ b/build/pkgs/pythran/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pythran diff --git a/build/pkgs/pythran/install-requires.txt b/build/pkgs/pythran/install-requires.txt index 86d056b339f..f365e5f4971 100644 --- a/build/pkgs/pythran/install-requires.txt +++ b/build/pkgs/pythran/install-requires.txt @@ -1 +1 @@ -pythran +pythran >=0.12.1 diff --git a/build/pkgs/pythran/package-version.txt b/build/pkgs/pythran/package-version.txt index 34a83616bb5..c317a91891f 100644 --- a/build/pkgs/pythran/package-version.txt +++ b/build/pkgs/pythran/package-version.txt @@ -1 +1 @@ -0.12.1 +0.13.1 diff --git a/build/pkgs/pythran/spkg-configure.m4 b/build/pkgs/pythran/spkg-configure.m4 new file mode 100644 index 00000000000..592e95bcb3d --- /dev/null +++ b/build/pkgs/pythran/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pythran], [SAGE_PYTHON_PACKAGE_CHECK([pythran])]) diff --git a/build/pkgs/pytz/dependencies b/build/pkgs/pytz/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/pytz/dependencies +++ b/build/pkgs/pytz/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pytz/distros/arch.txt b/build/pkgs/pytz/distros/arch.txt new file mode 100644 index 00000000000..2cccc9e61ec --- /dev/null +++ b/build/pkgs/pytz/distros/arch.txt @@ -0,0 +1 @@ +python-pytz diff --git a/build/pkgs/pytz/distros/debian.txt b/build/pkgs/pytz/distros/debian.txt new file mode 100644 index 00000000000..db209080161 --- /dev/null +++ b/build/pkgs/pytz/distros/debian.txt @@ -0,0 +1 @@ +python3-tz diff --git a/build/pkgs/pytz/distros/fedora.txt b/build/pkgs/pytz/distros/fedora.txt new file mode 100644 index 00000000000..2cccc9e61ec --- /dev/null +++ b/build/pkgs/pytz/distros/fedora.txt @@ -0,0 +1 @@ +python-pytz diff --git a/build/pkgs/pytz/distros/gentoo.txt b/build/pkgs/pytz/distros/gentoo.txt new file mode 100644 index 00000000000..902a18bf73e --- /dev/null +++ b/build/pkgs/pytz/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pytz diff --git a/build/pkgs/pytz/distros/opensuse.txt b/build/pkgs/pytz/distros/opensuse.txt index 1b20e1dbb77..232b99a6d04 100644 --- a/build/pkgs/pytz/distros/opensuse.txt +++ b/build/pkgs/pytz/distros/opensuse.txt @@ -1 +1 @@ -python3-pytz +python3${PYTHON_MINOR}-pytz diff --git a/build/pkgs/pytz/spkg-configure.m4 b/build/pkgs/pytz/spkg-configure.m4 new file mode 100644 index 00000000000..366521be957 --- /dev/null +++ b/build/pkgs/pytz/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([pytz], [SAGE_PYTHON_PACKAGE_CHECK([pytz])]) diff --git a/build/pkgs/pytz_deprecation_shim/dependencies b/build/pkgs/pytz_deprecation_shim/dependencies index 232fe6c0554..2ea28ad2718 100644 --- a/build/pkgs/pytz_deprecation_shim/dependencies +++ b/build/pkgs/pytz_deprecation_shim/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) tzdata | $(PYTHON_TOOLCHAIN) + tzdata | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyx/distros/opensuse.txt b/build/pkgs/pyx/distros/opensuse.txt index 03265558e86..f7dd2365b82 100644 --- a/build/pkgs/pyx/distros/opensuse.txt +++ b/build/pkgs/pyx/distros/opensuse.txt @@ -1 +1 @@ -python3-PyX +python3${PYTHON_MINOR}-PyX diff --git a/build/pkgs/pyzmq/dependencies b/build/pkgs/pyzmq/dependencies index c72b3d23340..5031d872d13 100644 --- a/build/pkgs/pyzmq/dependencies +++ b/build/pkgs/pyzmq/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython zeromq | $(PYTHON_TOOLCHAIN) + cython zeromq | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyzmq/distros/arch.txt b/build/pkgs/pyzmq/distros/arch.txt new file mode 100644 index 00000000000..23f64d1f1a3 --- /dev/null +++ b/build/pkgs/pyzmq/distros/arch.txt @@ -0,0 +1 @@ +python-pyzmq diff --git a/build/pkgs/pyzmq/distros/fedora.txt b/build/pkgs/pyzmq/distros/fedora.txt new file mode 100644 index 00000000000..23f64d1f1a3 --- /dev/null +++ b/build/pkgs/pyzmq/distros/fedora.txt @@ -0,0 +1 @@ +python-pyzmq diff --git a/build/pkgs/pyzmq/distros/gentoo.txt b/build/pkgs/pyzmq/distros/gentoo.txt new file mode 100644 index 00000000000..77c24295bd0 --- /dev/null +++ b/build/pkgs/pyzmq/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/pyzmq diff --git a/build/pkgs/pyzmq/distros/opensuse.txt b/build/pkgs/pyzmq/distros/opensuse.txt index 265a272130e..fe243347c49 100644 --- a/build/pkgs/pyzmq/distros/opensuse.txt +++ b/build/pkgs/pyzmq/distros/opensuse.txt @@ -1 +1 @@ -python3-pyzmq +python3${PYTHON_MINOR}-pyzmq diff --git a/build/pkgs/pyzmq/spkg-configure.m4 b/build/pkgs/pyzmq/spkg-configure.m4 new file mode 100644 index 00000000000..ae2b126efb1 --- /dev/null +++ b/build/pkgs/pyzmq/spkg-configure.m4 @@ -0,0 +1,5 @@ +SAGE_SPKG_CONFIGURE([pyzmq], [ + SAGE_SPKG_DEPCHECK([zeromq], [ + SAGE_PYTHON_PACKAGE_CHECK([pyzmq]) + ]) +]) diff --git a/build/pkgs/qdldl_python/dependencies b/build/pkgs/qdldl_python/dependencies index 48c2586b9f4..757104fcba0 100644 --- a/build/pkgs/qdldl_python/dependencies +++ b/build/pkgs/qdldl_python/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pybind11 numpy scipy | $(PYTHON_TOOLCHAIN) cmake + pybind11 numpy scipy | $(PYTHON_TOOLCHAIN) cmake $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/requests/dependencies b/build/pkgs/requests/dependencies index b896dbc3cac..668fe014f12 100644 --- a/build/pkgs/requests/dependencies +++ b/build/pkgs/requests/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) idna urllib3 certifi charset_normalizer + | $(PYTHON_TOOLCHAIN) idna urllib3 certifi charset_normalizer $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/requests/distros/arch.txt b/build/pkgs/requests/distros/arch.txt new file mode 100644 index 00000000000..93a7bc19b60 --- /dev/null +++ b/build/pkgs/requests/distros/arch.txt @@ -0,0 +1 @@ +python-requests diff --git a/build/pkgs/requests/distros/debian.txt b/build/pkgs/requests/distros/debian.txt new file mode 100644 index 00000000000..43147b2be74 --- /dev/null +++ b/build/pkgs/requests/distros/debian.txt @@ -0,0 +1 @@ +python3-requests diff --git a/build/pkgs/requests/distros/fedora.txt b/build/pkgs/requests/distros/fedora.txt new file mode 100644 index 00000000000..93a7bc19b60 --- /dev/null +++ b/build/pkgs/requests/distros/fedora.txt @@ -0,0 +1 @@ +python-requests diff --git a/build/pkgs/requests/distros/gentoo.txt b/build/pkgs/requests/distros/gentoo.txt new file mode 100644 index 00000000000..d3dc9415e3d --- /dev/null +++ b/build/pkgs/requests/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/requests diff --git a/build/pkgs/requests/distros/opensuse.txt b/build/pkgs/requests/distros/opensuse.txt index 43147b2be74..c1581ad8a95 100644 --- a/build/pkgs/requests/distros/opensuse.txt +++ b/build/pkgs/requests/distros/opensuse.txt @@ -1 +1 @@ -python3-requests +python3${PYTHON_MINOR}-requests diff --git a/build/pkgs/requests/spkg-configure.m4 b/build/pkgs/requests/spkg-configure.m4 new file mode 100644 index 00000000000..f50a66cdee3 --- /dev/null +++ b/build/pkgs/requests/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([requests], [SAGE_PYTHON_PACKAGE_CHECK([requests])]) diff --git a/build/pkgs/retrolab/dependencies b/build/pkgs/retrolab/dependencies index 531f28310be..58027d3558c 100644 --- a/build/pkgs/retrolab/dependencies +++ b/build/pkgs/retrolab/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jupyterlab | $(PYTHON_TOOLCHAIN) + jupyterlab | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index b8937d88769..b88615716d4 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r cffi tzlocal pytz jinja2 | $(PYTHON_TOOLCHAIN) pycparser + r cffi tzlocal pytz jinja2 | $(PYTHON_TOOLCHAIN) pycparser $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/rpy2/distros/arch.txt b/build/pkgs/rpy2/distros/arch.txt new file mode 100644 index 00000000000..9748535a285 --- /dev/null +++ b/build/pkgs/rpy2/distros/arch.txt @@ -0,0 +1 @@ +python-rpy2 diff --git a/build/pkgs/rpy2/distros/debian.txt b/build/pkgs/rpy2/distros/debian.txt new file mode 100644 index 00000000000..8f389862688 --- /dev/null +++ b/build/pkgs/rpy2/distros/debian.txt @@ -0,0 +1 @@ +rpy2 diff --git a/build/pkgs/rpy2/distros/freebsd.txt b/build/pkgs/rpy2/distros/freebsd.txt new file mode 100644 index 00000000000..21caa8b9edd --- /dev/null +++ b/build/pkgs/rpy2/distros/freebsd.txt @@ -0,0 +1 @@ +math/py-rpy2 diff --git a/build/pkgs/rpy2/distros/macports.txt b/build/pkgs/rpy2/distros/macports.txt new file mode 100644 index 00000000000..71f03850a9b --- /dev/null +++ b/build/pkgs/rpy2/distros/macports.txt @@ -0,0 +1 @@ +py-rpy2 diff --git a/build/pkgs/rpy2/distros/opensuse.txt b/build/pkgs/rpy2/distros/opensuse.txt new file mode 100644 index 00000000000..5b9c1542845 --- /dev/null +++ b/build/pkgs/rpy2/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-rpy2 diff --git a/build/pkgs/rpy2/spkg-configure.m4 b/build/pkgs/rpy2/spkg-configure.m4 index c9831c6b60a..0cb3784ea9c 100644 --- a/build/pkgs/rpy2/spkg-configure.m4 +++ b/build/pkgs/rpy2/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([rpy2], [ - sage_spkg_install_rpy2=yes - ], [dnl REQUIRED-CHECK + SAGE_PYTHON_PACKAGE_CHECK([rpy2]) +], [dnl REQUIRED-CHECK AC_REQUIRE([SAGE_SPKG_CONFIGURE_R]) dnl rpy2 is only needed when there is a usable system R AS_VAR_IF([sage_spkg_install_r], [yes], [dnl diff --git a/build/pkgs/rst2ipynb/dependencies b/build/pkgs/rst2ipynb/dependencies index 7fcda2181e1..d828daf957d 100644 --- a/build/pkgs/rst2ipynb/dependencies +++ b/build/pkgs/rst2ipynb/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pandoc | $(PYTHON_TOOLCHAIN) notedown + pandoc | $(PYTHON_TOOLCHAIN) notedown $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sage_conf/dependencies b/build/pkgs/sage_conf/dependencies index 0479fd1d280..f2bd00aaf0d 100644 --- a/build/pkgs/sage_conf/dependencies +++ b/build/pkgs/sage_conf/dependencies @@ -1 +1 @@ -$(PYTHON) $(SAGE_ROOT)/pkgs/sage-conf/_sage_conf/_conf.py $(SAGE_ROOT)/pkgs/sage-conf/setup.cfg $(SAGE_ROOT)/pkgs/sage-conf/bin/sage-env-config | $(PYTHON_TOOLCHAIN) + $(SAGE_ROOT)/pkgs/sage-conf/_sage_conf/_conf.py $(SAGE_ROOT)/pkgs/sage-conf/setup.cfg $(SAGE_ROOT)/pkgs/sage-conf/bin/sage-env-config | $(PYTHON_TOOLCHAIN) $(PYTHON) diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index c92aca850f4..a7983695b38 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.1 +sage-conf ~= 10.2b3 diff --git a/build/pkgs/sage_docbuild/dependencies b/build/pkgs/sage_docbuild/dependencies index 376ad09772a..c21e4b287e3 100644 --- a/build/pkgs/sage_docbuild/dependencies +++ b/build/pkgs/sage_docbuild/dependencies @@ -1 +1 @@ -$(PYTHON) sphinx $(SAGE_ROOT)/pkgs/sage-docbuild/sage_docbuild/*.py $(SAGE_ROOT)/pkgs/sage-docbuild/sage_docbuild/ext/*.py | $(PYTHON_TOOLCHAIN) sagelib + sphinx $(SAGE_ROOT)/pkgs/sage-docbuild/sage_docbuild/*.py $(SAGE_ROOT)/pkgs/sage-docbuild/sage_docbuild/ext/*.py | $(PYTHON_TOOLCHAIN) sagelib $(PYTHON) diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index e7a51281874..59771e40936 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.1 +sage-docbuild ~= 10.2b3 diff --git a/build/pkgs/sage_flatsurf/dependencies b/build/pkgs/sage_flatsurf/dependencies index 4c62fdd4fef..c706908baa7 100644 --- a/build/pkgs/sage_flatsurf/dependencies +++ b/build/pkgs/sage_flatsurf/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) surface_dynamics $(SAGERUNTIME) + | $(PYTHON_TOOLCHAIN) surface_dynamics $(SAGERUNTIME) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sage_numerical_backends_coin/dependencies b/build/pkgs/sage_numerical_backends_coin/dependencies index 4cbde1164f2..0448728cea5 100644 --- a/build/pkgs/sage_numerical_backends_coin/dependencies +++ b/build/pkgs/sage_numerical_backends_coin/dependencies @@ -1,4 +1,4 @@ -cbc cysignals $(SAGE_SRC)/sage/numerical/backends/generic_backend.pxd $(SAGE_SRC)/sage/cpython/string.pxd $(SAGE_SRC)/sage/cpython/string_impl.h | $(SAGERUNTIME) $(PYTHON_TOOLCHAIN) cython ipywidgets +cbc cysignals $(SAGE_SRC)/sage/numerical/backends/generic_backend.pxd $(SAGE_SRC)/sage/cpython/string.pxd $(SAGE_SRC)/sage/cpython/string_impl.h | $(SAGERUNTIME) $(PYTHON_TOOLCHAIN) cython ipywidgets $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sage_numerical_backends_cplex/dependencies b/build/pkgs/sage_numerical_backends_cplex/dependencies index 0b35afa3540..840bdcabd34 100644 --- a/build/pkgs/sage_numerical_backends_cplex/dependencies +++ b/build/pkgs/sage_numerical_backends_cplex/dependencies @@ -1,4 +1,4 @@ -cysignals $(SAGE_SRC)/sage/numerical/backends/generic_backend.pxd $(SAGE_SRC)/sage/cpython/string.pxd $(SAGE_SRC)/sage/cpython/string_impl.h | $(SAGERUNTIME) $(PYTHON_TOOLCHAIN) cython ipywidgets +cysignals $(SAGE_SRC)/sage/numerical/backends/generic_backend.pxd $(SAGE_SRC)/sage/cpython/string.pxd $(SAGE_SRC)/sage/cpython/string_impl.h | $(SAGERUNTIME) $(PYTHON_TOOLCHAIN) cython ipywidgets $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sage_numerical_backends_gurobi/dependencies b/build/pkgs/sage_numerical_backends_gurobi/dependencies index 0b35afa3540..840bdcabd34 100644 --- a/build/pkgs/sage_numerical_backends_gurobi/dependencies +++ b/build/pkgs/sage_numerical_backends_gurobi/dependencies @@ -1,4 +1,4 @@ -cysignals $(SAGE_SRC)/sage/numerical/backends/generic_backend.pxd $(SAGE_SRC)/sage/cpython/string.pxd $(SAGE_SRC)/sage/cpython/string_impl.h | $(SAGERUNTIME) $(PYTHON_TOOLCHAIN) cython ipywidgets +cysignals $(SAGE_SRC)/sage/numerical/backends/generic_backend.pxd $(SAGE_SRC)/sage/cpython/string.pxd $(SAGE_SRC)/sage/cpython/string_impl.h | $(SAGERUNTIME) $(PYTHON_TOOLCHAIN) cython ipywidgets $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sage_setup/dependencies b/build/pkgs/sage_setup/dependencies index 8c2e218f49a..cae3faf9049 100644 --- a/build/pkgs/sage_setup/dependencies +++ b/build/pkgs/sage_setup/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cython pkgconfig jinja2 $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/*.py $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/autogen/interpreters/specs/*.py $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/command/*.py | $(PYTHON_TOOLCHAIN) + cython pkgconfig jinja2 $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/*.py $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/autogen/interpreters/specs/*.py $(SAGE_ROOT)/pkgs/sage-setup/sage_setup/command/*.py | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 19d640c75eb..5454a3500d0 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.1 +sage-setup ~= 10.2b3 diff --git a/build/pkgs/sage_sws2rst/dependencies b/build/pkgs/sage_sws2rst/dependencies index 5ca5e27df75..f32c4fc594d 100644 --- a/build/pkgs/sage_sws2rst/dependencies +++ b/build/pkgs/sage_sws2rst/dependencies @@ -1 +1 @@ -$(PYTHON) beautifulsoup4 $(SAGE_ROOT)/pkgs/sage-sws2rst/*.py | $(PYTHON_TOOLCHAIN) + beautifulsoup4 $(SAGE_ROOT)/pkgs/sage-sws2rst/*.py | $(PYTHON_TOOLCHAIN) $(PYTHON) diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 03bedff32a5..640e3ae7d65 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.1 +sage-sws2rst ~= 10.2b3 diff --git a/build/pkgs/sagelib/dependencies b/build/pkgs/sagelib/dependencies index 9b8c062d3c3..5dc2efe1d31 100644 --- a/build/pkgs/sagelib/dependencies +++ b/build/pkgs/sagelib/dependencies @@ -1,4 +1,4 @@ -FORCE $(SCRIPTS) arb boost_cropped $(BLAS) brial cliquer cypari cysignals cython ecl eclib ecm flint libgd gap giac givaro glpk gmpy2 gsl iml importlib_metadata importlib_resources jinja2 jupyter_core lcalc lrcalc_python libbraiding libhomfly libpng linbox m4ri m4rie memory_allocator mpc mpfi mpfr $(MP_LIBRARY) ntl numpy pari pip pkgconfig planarity ppl pplpy primesieve primecount primecountpy pycygwin $(PYTHON) requests rw sage_conf singular symmetrica typing_extensions $(PCFILES) | $(PYTHON_TOOLCHAIN) sage_setup +FORCE $(SCRIPTS) arb boost_cropped $(BLAS) brial cliquer cypari cysignals cython ecl eclib ecm flint libgd gap giac givaro glpk gmpy2 gsl iml importlib_metadata importlib_resources jupyter_core lcalc lrcalc_python libbraiding libhomfly libpng linbox m4ri m4rie memory_allocator mpc mpfi mpfr $(MP_LIBRARY) ntl numpy pari pip pkgconfig planarity ppl pplpy primesieve primecount primecountpy pycygwin $(PYTHON) requests rw sage_conf singular symmetrica typing_extensions $(PCFILES) | $(PYTHON_TOOLCHAIN) sage_setup $(PYTHON) pythran ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index cf9a3720e26..175584ae516 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.1 +sagemath-standard ~= 10.2b3 diff --git a/build/pkgs/sagemath_bliss/dependencies b/build/pkgs/sagemath_bliss/dependencies index 279e79ace91..a7915e316b9 100644 --- a/build/pkgs/sagemath_bliss/dependencies +++ b/build/pkgs/sagemath_bliss/dependencies @@ -1 +1 @@ -$(PYTHON) bliss cysignals | $(PYTHON_TOOLCHAIN) sage_setup sage_conf sagemath_environment cython pkgconfig + bliss cysignals | $(PYTHON_TOOLCHAIN) sage_setup sage_conf sagemath_environment cython pkgconfig $(PYTHON) diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index 37dc85dfa86..5b942c5726b 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.1 +sagemath-bliss ~= 10.2b3 diff --git a/build/pkgs/sagemath_categories/dependencies b/build/pkgs/sagemath_categories/dependencies index d8b6bdbd4a7..9fa43a64aae 100644 --- a/build/pkgs/sagemath_categories/dependencies +++ b/build/pkgs/sagemath_categories/dependencies @@ -1 +1 @@ -$(PYTHON) sagemath_objects | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build + sagemath_objects | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build $(PYTHON) diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index f9c9912c022..32f0f5efe49 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.1 +sagemath-categories ~= 10.2b3 diff --git a/build/pkgs/sagemath_coxeter3/dependencies b/build/pkgs/sagemath_coxeter3/dependencies index 615392ca427..ada45656089 100644 --- a/build/pkgs/sagemath_coxeter3/dependencies +++ b/build/pkgs/sagemath_coxeter3/dependencies @@ -1 +1 @@ -$(PYTHON) coxeter3 | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig + coxeter3 | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig $(PYTHON) diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index 29b48b35f85..ba8508ec050 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.1 +sagemath-coxeter3 ~= 10.2b3 diff --git a/build/pkgs/sagemath_environment/dependencies b/build/pkgs/sagemath_environment/dependencies index 605611e7a21..0f36ec317e6 100644 --- a/build/pkgs/sagemath_environment/dependencies +++ b/build/pkgs/sagemath_environment/dependencies @@ -1 +1 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) python_build + | $(PYTHON_TOOLCHAIN) python_build $(PYTHON) diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index f582bef1437..8d32b0ed13f 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.1 +sagemath-environment ~= 10.2b3 diff --git a/build/pkgs/sagemath_mcqd/dependencies b/build/pkgs/sagemath_mcqd/dependencies index e383df7dafa..9896fdaccfc 100644 --- a/build/pkgs/sagemath_mcqd/dependencies +++ b/build/pkgs/sagemath_mcqd/dependencies @@ -1 +1 @@ -$(PYTHON) mcqd memory_allocator cysignals | $(PYTHON_TOOLCHAIN) sage_setup cython pkgconfig + mcqd memory_allocator cysignals | $(PYTHON_TOOLCHAIN) sage_setup cython pkgconfig $(PYTHON) diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index d0c9adf2723..2d692f1c2e5 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.1 +sagemath-mcqd ~= 10.2b3 diff --git a/build/pkgs/sagemath_meataxe/dependencies b/build/pkgs/sagemath_meataxe/dependencies index f100932802a..c333fcc61db 100644 --- a/build/pkgs/sagemath_meataxe/dependencies +++ b/build/pkgs/sagemath_meataxe/dependencies @@ -1 +1 @@ -$(PYTHON) meataxe | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig + meataxe | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig $(PYTHON) diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index 42a5c6179d2..0d0cc7f10ca 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.1 +sagemath-meataxe ~= 10.2b3 diff --git a/build/pkgs/sagemath_objects/dependencies b/build/pkgs/sagemath_objects/dependencies index 807b8b17215..ffc14bb6ba6 100644 --- a/build/pkgs/sagemath_objects/dependencies +++ b/build/pkgs/sagemath_objects/dependencies @@ -1,3 +1,3 @@ -FORCE $(PYTHON) cysignals gmpy2 | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build +FORCE cysignals gmpy2 | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build $(PYTHON) # FORCE: Always run the spkg-install script diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index 1ab7b2045b1..dd91ce540e3 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.1 +sagemath-objects ~= 10.2b3 diff --git a/build/pkgs/sagemath_repl/dependencies b/build/pkgs/sagemath_repl/dependencies index ebc253dac5b..7d7ba20c5dd 100644 --- a/build/pkgs/sagemath_repl/dependencies +++ b/build/pkgs/sagemath_repl/dependencies @@ -1 +1 @@ -$(PYTHON) sagemath_objects sagemath_environment ipython ipywidgets | $(PYTHON_TOOLCHAIN) python_build + sagemath_objects sagemath_environment ipython ipywidgets | $(PYTHON_TOOLCHAIN) python_build $(PYTHON) diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index c8d676d3564..d63353e2cd4 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.1 +sagemath-repl ~= 10.2b3 diff --git a/build/pkgs/sagemath_sirocco/dependencies b/build/pkgs/sagemath_sirocco/dependencies index b923f34d7eb..4f47049ec4b 100644 --- a/build/pkgs/sagemath_sirocco/dependencies +++ b/build/pkgs/sagemath_sirocco/dependencies @@ -1 +1 @@ -$(PYTHON) sirocco cypari cysignals mpfr | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig + sirocco cypari cysignals mpfr | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig $(PYTHON) diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 410e38cd2f7..29e7be858c1 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.1 +sagemath-sirocco ~= 10.2b3 diff --git a/build/pkgs/sagemath_tdlib/dependencies b/build/pkgs/sagemath_tdlib/dependencies index 5c7ecd31f2f..b22ab6c52a7 100644 --- a/build/pkgs/sagemath_tdlib/dependencies +++ b/build/pkgs/sagemath_tdlib/dependencies @@ -1 +1 @@ -$(PYTHON) tdlib cysignals | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig + tdlib cysignals | $(PYTHON_TOOLCHAIN) sage_setup sagemath_environment cython pkgconfig $(PYTHON) diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index 93a6d0e5e7d..14eabe771da 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.1 +sagemath-tdlib ~= 10.2b3 diff --git a/build/pkgs/sagenb_export/dependencies b/build/pkgs/sagenb_export/dependencies index 26033350f88..f9a2f2adbb9 100644 --- a/build/pkgs/sagenb_export/dependencies +++ b/build/pkgs/sagenb_export/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) notebook nbconvert ipython six | $(PYTHON_TOOLCHAIN) + notebook nbconvert ipython six | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sagetex/dependencies b/build/pkgs/sagetex/dependencies index 6090d5dc3ac..af9b5f370fb 100644 --- a/build/pkgs/sagetex/dependencies +++ b/build/pkgs/sagetex/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) maxima scipy matplotlib pillow tachyon pyparsing + maxima scipy matplotlib pillow tachyon pyparsing | $(PYTHON) To build SageTeX, you just need Python and pyparsing, but to test (SAGE_CHECK=yes) SageTeX, you actually need to run Sage, produce plots,... diff --git a/build/pkgs/scipy/checksums.ini b/build/pkgs/scipy/checksums.ini index e56c56745e3..7015206d1e7 100644 --- a/build/pkgs/scipy/checksums.ini +++ b/build/pkgs/scipy/checksums.ini @@ -1,5 +1,5 @@ tarball=scipy-VERSION.tar.gz -sha1=ff83163396a70276c0441b541befc485b471b27b -md5=de3db61d840456634ba37f2b5816e049 -cksum=3826133895 +sha1=856f8ac8498751b72d678ef64b88e436d04a957d +md5=27baf613b6cf3f9600a05161f132151c +cksum=1656738318 upstream_url=https://pypi.io/packages/source/s/scipy/scipy-VERSION.tar.gz diff --git a/build/pkgs/scipy/dependencies b/build/pkgs/scipy/dependencies index 5d42789eb10..82fa8e0c0d7 100644 --- a/build/pkgs/scipy/dependencies +++ b/build/pkgs/scipy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(BLAS) gfortran numpy pybind11 cython pythran | $(PYTHON_TOOLCHAIN) meson_python + $(BLAS) gfortran numpy pybind11 cython pythran | $(PYTHON_TOOLCHAIN) meson_python $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/scipy/distros/arch.txt b/build/pkgs/scipy/distros/arch.txt new file mode 100644 index 00000000000..7ff2882c1bf --- /dev/null +++ b/build/pkgs/scipy/distros/arch.txt @@ -0,0 +1 @@ +python-scipy diff --git a/build/pkgs/scipy/distros/debian.txt b/build/pkgs/scipy/distros/debian.txt new file mode 100644 index 00000000000..12b366666d6 --- /dev/null +++ b/build/pkgs/scipy/distros/debian.txt @@ -0,0 +1 @@ +python3-scipy diff --git a/build/pkgs/scipy/distros/fedora.txt b/build/pkgs/scipy/distros/fedora.txt new file mode 100644 index 00000000000..7ff2882c1bf --- /dev/null +++ b/build/pkgs/scipy/distros/fedora.txt @@ -0,0 +1 @@ +python-scipy diff --git a/build/pkgs/scipy/distros/gentoo.txt b/build/pkgs/scipy/distros/gentoo.txt new file mode 100644 index 00000000000..11dabd2830f --- /dev/null +++ b/build/pkgs/scipy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/scipy diff --git a/build/pkgs/scipy/distros/opensuse.txt b/build/pkgs/scipy/distros/opensuse.txt index 12b366666d6..d2bc2a30a85 100644 --- a/build/pkgs/scipy/distros/opensuse.txt +++ b/build/pkgs/scipy/distros/opensuse.txt @@ -1 +1 @@ -python3-scipy +python3${PYTHON_MINOR}-scipy diff --git a/build/pkgs/scipy/install-requires.txt b/build/pkgs/scipy/install-requires.txt index 16d57fdb9b0..dd975a870e3 100644 --- a/build/pkgs/scipy/install-requires.txt +++ b/build/pkgs/scipy/install-requires.txt @@ -4,4 +4,4 @@ # deprecations cannot be introduced in micro releases. # SciPy devs wait "at least 6 months", "in practice two (minor) releases" # from deprecation to removal of a feature. -scipy >=1.5, <1.11 +scipy >=1.5, <1.12 diff --git a/build/pkgs/scipy/package-version.txt b/build/pkgs/scipy/package-version.txt index 4dae2985b58..ca7176690dd 100644 --- a/build/pkgs/scipy/package-version.txt +++ b/build/pkgs/scipy/package-version.txt @@ -1 +1 @@ -1.10.1 +1.11.2 diff --git a/build/pkgs/scipy/spkg-configure.m4 b/build/pkgs/scipy/spkg-configure.m4 new file mode 100644 index 00000000000..0b7294a02e8 --- /dev/null +++ b/build/pkgs/scipy/spkg-configure.m4 @@ -0,0 +1,5 @@ +SAGE_SPKG_CONFIGURE([scipy], [ + SAGE_SPKG_DEPCHECK([openblas], [ + SAGE_PYTHON_PACKAGE_CHECK([scipy]) + ]) +]) diff --git a/build/pkgs/scs/dependencies b/build/pkgs/scs/dependencies index 56c3c7a111c..a736df74ec5 100644 --- a/build/pkgs/scs/dependencies +++ b/build/pkgs/scs/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy | $(PYTHON_TOOLCHAIN) cmake + numpy | $(PYTHON_TOOLCHAIN) cmake $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/send2trash/dependencies b/build/pkgs/send2trash/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/send2trash/dependencies +++ b/build/pkgs/send2trash/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/send2trash/distros/gentoo.txt b/build/pkgs/send2trash/distros/gentoo.txt new file mode 100644 index 00000000000..a89b1798476 --- /dev/null +++ b/build/pkgs/send2trash/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/send2trash diff --git a/build/pkgs/send2trash/distros/opensuse.txt b/build/pkgs/send2trash/distros/opensuse.txt index 404e2bd3580..8d3c81fa23c 100644 --- a/build/pkgs/send2trash/distros/opensuse.txt +++ b/build/pkgs/send2trash/distros/opensuse.txt @@ -1 +1 @@ -python3-Send2Trash +python3${PYTHON_MINOR}-Send2Trash diff --git a/build/pkgs/send2trash/spkg-configure.m4 b/build/pkgs/send2trash/spkg-configure.m4 new file mode 100644 index 00000000000..3bbb727e430 --- /dev/null +++ b/build/pkgs/send2trash/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([send2trash], [SAGE_PYTHON_PACKAGE_CHECK([send2trash])]) diff --git a/build/pkgs/setuptools/dependencies b/build/pkgs/setuptools/dependencies index 1700e743d59..d45a397db36 100644 --- a/build/pkgs/setuptools/dependencies +++ b/build/pkgs/setuptools/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) + | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools/distros/arch.txt b/build/pkgs/setuptools/distros/arch.txt new file mode 100644 index 00000000000..e1ad17860cd --- /dev/null +++ b/build/pkgs/setuptools/distros/arch.txt @@ -0,0 +1 @@ +python-setuptools diff --git a/build/pkgs/setuptools/distros/debian.txt b/build/pkgs/setuptools/distros/debian.txt new file mode 100644 index 00000000000..1c0901c0374 --- /dev/null +++ b/build/pkgs/setuptools/distros/debian.txt @@ -0,0 +1 @@ +python3-setuptools diff --git a/build/pkgs/setuptools/distros/fedora.txt b/build/pkgs/setuptools/distros/fedora.txt new file mode 100644 index 00000000000..e1ad17860cd --- /dev/null +++ b/build/pkgs/setuptools/distros/fedora.txt @@ -0,0 +1 @@ +python-setuptools diff --git a/build/pkgs/setuptools/distros/gentoo.txt b/build/pkgs/setuptools/distros/gentoo.txt new file mode 100644 index 00000000000..3a4fa34a57f --- /dev/null +++ b/build/pkgs/setuptools/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/setuptools diff --git a/build/pkgs/setuptools/distros/opensuse.txt b/build/pkgs/setuptools/distros/opensuse.txt index 1c0901c0374..b2d8de78f80 100644 --- a/build/pkgs/setuptools/distros/opensuse.txt +++ b/build/pkgs/setuptools/distros/opensuse.txt @@ -1 +1 @@ -python3-setuptools +python3${PYTHON_MINOR}-setuptools diff --git a/build/pkgs/setuptools/install-requires.txt b/build/pkgs/setuptools/install-requires.txt index 0810ca37277..e0cf7c9b5dc 100644 --- a/build/pkgs/setuptools/install-requires.txt +++ b/build/pkgs/setuptools/install-requires.txt @@ -1 +1 @@ -setuptools >=49.6.0 +setuptools >=49.6.0, <64 diff --git a/build/pkgs/setuptools/spkg-configure.m4 b/build/pkgs/setuptools/spkg-configure.m4 new file mode 100644 index 00000000000..a2ad8119063 --- /dev/null +++ b/build/pkgs/setuptools/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([setuptools], [SAGE_PYTHON_PACKAGE_CHECK([setuptools])]) diff --git a/build/pkgs/setuptools_scm/dependencies b/build/pkgs/setuptools_scm/dependencies index f3662a5c829..7dd3b6e8f6e 100644 --- a/build/pkgs/setuptools_scm/dependencies +++ b/build/pkgs/setuptools_scm/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) typing_extensions | setuptools pip wheel tomli packaging + typing_extensions | setuptools pip wheel tomli packaging $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools_scm/distros/arch.txt b/build/pkgs/setuptools_scm/distros/arch.txt new file mode 100644 index 00000000000..2b97444decf --- /dev/null +++ b/build/pkgs/setuptools_scm/distros/arch.txt @@ -0,0 +1 @@ +python-setuptools-scm diff --git a/build/pkgs/setuptools_scm/distros/debian.txt b/build/pkgs/setuptools_scm/distros/debian.txt new file mode 100644 index 00000000000..bcfdd6ebcdd --- /dev/null +++ b/build/pkgs/setuptools_scm/distros/debian.txt @@ -0,0 +1 @@ +setuptools-scm diff --git a/build/pkgs/setuptools_scm/distros/fedora.txt b/build/pkgs/setuptools_scm/distros/fedora.txt new file mode 100644 index 00000000000..720fd2897be --- /dev/null +++ b/build/pkgs/setuptools_scm/distros/fedora.txt @@ -0,0 +1 @@ +python-setuptools_scm diff --git a/build/pkgs/setuptools_scm/distros/freebsd.txt b/build/pkgs/setuptools_scm/distros/freebsd.txt new file mode 100644 index 00000000000..ba714681e0a --- /dev/null +++ b/build/pkgs/setuptools_scm/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-setuptools_scm diff --git a/build/pkgs/setuptools_scm/distros/gentoo.txt b/build/pkgs/setuptools_scm/distros/gentoo.txt new file mode 100644 index 00000000000..46efc2bdeb4 --- /dev/null +++ b/build/pkgs/setuptools_scm/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/setuptools-scm diff --git a/build/pkgs/setuptools_scm/distros/opensuse.txt b/build/pkgs/setuptools_scm/distros/opensuse.txt index 2aa5ca12cba..cacb303c566 100644 --- a/build/pkgs/setuptools_scm/distros/opensuse.txt +++ b/build/pkgs/setuptools_scm/distros/opensuse.txt @@ -1 +1 @@ -python3-setuptools_scm +python3${PYTHON_MINOR}-setuptools_scm diff --git a/build/pkgs/setuptools_scm/install-requires.txt b/build/pkgs/setuptools_scm/install-requires.txt index ee00ef62d52..34188327a0f 100644 --- a/build/pkgs/setuptools_scm/install-requires.txt +++ b/build/pkgs/setuptools_scm/install-requires.txt @@ -1 +1,2 @@ -setuptools_scm >=4.1.2 +# matplotlib-3.6.2 needs >= 7 +setuptools_scm >=7 diff --git a/build/pkgs/setuptools_scm/spkg-configure.m4 b/build/pkgs/setuptools_scm/spkg-configure.m4 new file mode 100644 index 00000000000..437148c2a8f --- /dev/null +++ b/build/pkgs/setuptools_scm/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([setuptools_scm], [ + SAGE_PYTHON_PACKAGE_CHECK([setuptools_scm]) +]) diff --git a/build/pkgs/setuptools_scm_git_archive/dependencies b/build/pkgs/setuptools_scm_git_archive/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/setuptools_scm_git_archive/dependencies +++ b/build/pkgs/setuptools_scm_git_archive/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools_wheel/dependencies b/build/pkgs/setuptools_wheel/dependencies index 618d627629a..dac3579f7e3 100644 --- a/build/pkgs/setuptools_wheel/dependencies +++ b/build/pkgs/setuptools_wheel/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) setuptools wheel + setuptools wheel | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools_wheel/install-requires.txt b/build/pkgs/setuptools_wheel/install-requires.txt index d1dc532ceab..d3767a68c8f 100644 --- a/build/pkgs/setuptools_wheel/install-requires.txt +++ b/build/pkgs/setuptools_wheel/install-requires.txt @@ -1 +1 @@ -# We use this file to mark the package as a Python package +setuptools >= 65.6 diff --git a/build/pkgs/simplegeneric/dependencies b/build/pkgs/simplegeneric/dependencies index 703d0ec7ba3..1169eb4105f 100644 --- a/build/pkgs/simplegeneric/dependencies +++ b/build/pkgs/simplegeneric/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) # simplegeneric does not strictly require setuptools, but it does try # to use setuptools if it is available. However, there is a problem diff --git a/build/pkgs/simplegeneric/distros/gentoo.txt b/build/pkgs/simplegeneric/distros/gentoo.txt new file mode 100644 index 00000000000..a86e90d96ec --- /dev/null +++ b/build/pkgs/simplegeneric/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/simplegeneric diff --git a/build/pkgs/simplegeneric/distros/opensuse.txt b/build/pkgs/simplegeneric/distros/opensuse.txt index d788a7233a7..ddc1661a230 100644 --- a/build/pkgs/simplegeneric/distros/opensuse.txt +++ b/build/pkgs/simplegeneric/distros/opensuse.txt @@ -1 +1 @@ -python3-simplegeneric +python3${PYTHON_MINOR}-simplegeneric diff --git a/build/pkgs/simplegeneric/spkg-configure.m4 b/build/pkgs/simplegeneric/spkg-configure.m4 new file mode 100644 index 00000000000..13715ab5f2b --- /dev/null +++ b/build/pkgs/simplegeneric/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([simplegeneric], [SAGE_PYTHON_PACKAGE_CHECK([simplegeneric])]) diff --git a/build/pkgs/singular/checksums.ini b/build/pkgs/singular/checksums.ini index 313463d2fea..1101fc55700 100644 --- a/build/pkgs/singular/checksums.ini +++ b/build/pkgs/singular/checksums.ini @@ -1,5 +1,5 @@ tarball=singular-VERSION.tar.gz -sha1=28bb3ee97ef48d04dfa96de182fd93eebe08426c -md5=fc0a4f5720dadba45a52ee94324ce00c -cksum=1573851737 -upstream_url=ftp://jim.mathematik.uni-kl.de/pub/Math/Singular/SOURCES/4-3-1/singular-VERSION.tar.gz +sha1=df1997f412580f2073295aba569bb955ad227317 +md5=50349213e206a18cdaa1bc410dde7ea4 +cksum=376854707 +upstream_url=ftp://jim.mathematik.uni-kl.de/pub/Math/Singular/SOURCES/4-3-2/singular-VERSION.tar.gz diff --git a/build/pkgs/singular/package-version.txt b/build/pkgs/singular/package-version.txt index 66e2bede53a..9f1bf008217 100644 --- a/build/pkgs/singular/package-version.txt +++ b/build/pkgs/singular/package-version.txt @@ -1 +1 @@ -4.3.1p3 +4.3.2p7 diff --git a/build/pkgs/singular/spkg-configure.m4 b/build/pkgs/singular/spkg-configure.m4 index 6a85631f624..d0310c459fb 100644 --- a/build/pkgs/singular/spkg-configure.m4 +++ b/build/pkgs/singular/spkg-configure.m4 @@ -6,14 +6,28 @@ SAGE_SPKG_CONFIGURE([singular], [ AS_IF([test -z "${SINGULAR_BIN}"], [sage_spkg_install_singular=yes], [ dnl Use pkg-config to ensure that Singular is new enough. PKG_CHECK_MODULES([SINGULAR], [Singular >= 4.2.1], [ - AC_MSG_CHECKING([that Singular's help is working]) - AS_IF([test x`printf "system(\"--browser\", \"builtin\"); \n help;" | Singular 2>&1 | grep "error occurred"` = x], [ - AC_MSG_RESULT(yes) - ], [ - AC_MSG_RESULT(no) - sage_spkg_install_singular=yes - ] - )], [ + AC_MSG_CHECKING([whether Singular is built with FLINT]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #include + #if !defined(HAVE_FLINT) + # error "Need Singular compiled with FLINT" + #endif + ], []) + ], [ + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([that Singular's help is working]) + AS_IF([test x`printf "system(\"--browser\", \"builtin\"); \n help;" | Singular 2>&1 | grep "error occurred"` = x], [ + AC_MSG_RESULT(yes) + ], [ + AC_MSG_RESULT(no) + sage_spkg_install_singular=yes + ]) + ], [ + AC_MSG_RESULT([no]) + sage_spkg_install_singular=yes + ]) + ], [ dnl pkg-config version check failed sage_spkg_install_singular=yes ]) diff --git a/build/pkgs/singular_jupyter/dependencies b/build/pkgs/singular_jupyter/dependencies index 14dc06f7076..dc15abb82c7 100644 --- a/build/pkgs/singular_jupyter/dependencies +++ b/build/pkgs/singular_jupyter/dependencies @@ -1 +1 @@ -$(PYTHON) jupyter_client | $(PYTHON_TOOLCHAIN) pysingular ipython ipywidgets + jupyter_client | $(PYTHON_TOOLCHAIN) pysingular ipython ipywidgets $(PYTHON) diff --git a/build/pkgs/six/dependencies b/build/pkgs/six/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/six/dependencies +++ b/build/pkgs/six/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/six/distros/arch.txt b/build/pkgs/six/distros/arch.txt new file mode 100644 index 00000000000..787c5308ea4 --- /dev/null +++ b/build/pkgs/six/distros/arch.txt @@ -0,0 +1 @@ +python-six diff --git a/build/pkgs/six/distros/debian.txt b/build/pkgs/six/distros/debian.txt new file mode 100644 index 00000000000..68ff8595d0b --- /dev/null +++ b/build/pkgs/six/distros/debian.txt @@ -0,0 +1 @@ +python3-six diff --git a/build/pkgs/six/distros/fedora.txt b/build/pkgs/six/distros/fedora.txt new file mode 100644 index 00000000000..787c5308ea4 --- /dev/null +++ b/build/pkgs/six/distros/fedora.txt @@ -0,0 +1 @@ +python-six diff --git a/build/pkgs/six/distros/gentoo.txt b/build/pkgs/six/distros/gentoo.txt new file mode 100644 index 00000000000..f73f648ff75 --- /dev/null +++ b/build/pkgs/six/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/six diff --git a/build/pkgs/six/distros/opensuse.txt b/build/pkgs/six/distros/opensuse.txt index 68ff8595d0b..127cfc6a26a 100644 --- a/build/pkgs/six/distros/opensuse.txt +++ b/build/pkgs/six/distros/opensuse.txt @@ -1 +1 @@ -python3-six +python3${PYTHON_MINOR}-six diff --git a/build/pkgs/six/spkg-configure.m4 b/build/pkgs/six/spkg-configure.m4 new file mode 100644 index 00000000000..a382b81a3dd --- /dev/null +++ b/build/pkgs/six/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([six], [SAGE_PYTHON_PACKAGE_CHECK([six])]) diff --git a/build/pkgs/slabbe/dependencies b/build/pkgs/slabbe/dependencies index 05ba0d8954b..126e8ceee06 100644 --- a/build/pkgs/slabbe/dependencies +++ b/build/pkgs/slabbe/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) $(SAGERUNTIME) + | $(PYTHON_TOOLCHAIN) $(SAGERUNTIME) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/snappy/dependencies b/build/pkgs/snappy/dependencies index db96ccc42e0..ceaf757887e 100644 --- a/build/pkgs/snappy/dependencies +++ b/build/pkgs/snappy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) decorator ipython cypari | $(PYTHON_TOOLCHAIN) sagelib + decorator ipython cypari | $(PYTHON_TOOLCHAIN) sagelib $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/snowballstemmer/dependencies b/build/pkgs/snowballstemmer/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/snowballstemmer/dependencies +++ b/build/pkgs/snowballstemmer/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/snowballstemmer/distros/gentoo.txt b/build/pkgs/snowballstemmer/distros/gentoo.txt new file mode 100644 index 00000000000..63fd8513221 --- /dev/null +++ b/build/pkgs/snowballstemmer/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/snowballstemmer diff --git a/build/pkgs/snowballstemmer/distros/opensuse.txt b/build/pkgs/snowballstemmer/distros/opensuse.txt index 09b2636df60..a21cc876a24 100644 --- a/build/pkgs/snowballstemmer/distros/opensuse.txt +++ b/build/pkgs/snowballstemmer/distros/opensuse.txt @@ -1 +1 @@ -python3-snowballstemmer +python3${PYTHON_MINOR}-snowballstemmer diff --git a/build/pkgs/snowballstemmer/spkg-configure.m4 b/build/pkgs/snowballstemmer/spkg-configure.m4 new file mode 100644 index 00000000000..6aa08825d39 --- /dev/null +++ b/build/pkgs/snowballstemmer/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([snowballstemmer], [ + SAGE_PYTHON_PACKAGE_CHECK([snowballstemmer]) +]) diff --git a/build/pkgs/soupsieve/dependencies b/build/pkgs/soupsieve/dependencies index 8cd44d06682..cfb7c484697 100644 --- a/build/pkgs/soupsieve/dependencies +++ b/build/pkgs/soupsieve/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) hatchling + | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinx/dependencies b/build/pkgs/sphinx/dependencies index 75c668d9c23..9b7505c9aec 100644 --- a/build/pkgs/sphinx/dependencies +++ b/build/pkgs/sphinx/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) docutils jinja2 pygments snowballstemmer imagesize babel alabaster requests sphinxcontrib_websupport sphinxcontrib_applehelp sphinxcontrib_devhelp sphinxcontrib_htmlhelp sphinxcontrib_jsmath sphinxcontrib_qthelp sphinxcontrib_serializinghtml packaging importlib_metadata + | $(PYTHON_TOOLCHAIN) docutils jinja2 pygments snowballstemmer imagesize babel alabaster requests sphinxcontrib_websupport sphinxcontrib_applehelp sphinxcontrib_devhelp sphinxcontrib_htmlhelp sphinxcontrib_jsmath sphinxcontrib_qthelp sphinxcontrib_serializinghtml packaging importlib_metadata $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinx/distros/arch.txt b/build/pkgs/sphinx/distros/arch.txt new file mode 100644 index 00000000000..db9f745da4c --- /dev/null +++ b/build/pkgs/sphinx/distros/arch.txt @@ -0,0 +1 @@ +python-sphinx diff --git a/build/pkgs/sphinx/distros/debian.txt b/build/pkgs/sphinx/distros/debian.txt new file mode 100644 index 00000000000..6966869c705 --- /dev/null +++ b/build/pkgs/sphinx/distros/debian.txt @@ -0,0 +1 @@ +sphinx diff --git a/build/pkgs/sphinx/distros/fedora.txt b/build/pkgs/sphinx/distros/fedora.txt new file mode 100644 index 00000000000..db9f745da4c --- /dev/null +++ b/build/pkgs/sphinx/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinx diff --git a/build/pkgs/sphinx/distros/freebsd.txt b/build/pkgs/sphinx/distros/freebsd.txt new file mode 100644 index 00000000000..f7f30dba25f --- /dev/null +++ b/build/pkgs/sphinx/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinx diff --git a/build/pkgs/sphinx/distros/opensuse.txt b/build/pkgs/sphinx/distros/opensuse.txt index bc54d0bd553..0aa0566b066 100644 --- a/build/pkgs/sphinx/distros/opensuse.txt +++ b/build/pkgs/sphinx/distros/opensuse.txt @@ -1 +1 @@ -python3-Sphinx +python3${PYTHON_MINOR}-Sphinx diff --git a/build/pkgs/sphinx_basic_ng/dependencies b/build/pkgs/sphinx_basic_ng/dependencies index 175a793ecbc..ac849c62bf6 100644 --- a/build/pkgs/sphinx_basic_ng/dependencies +++ b/build/pkgs/sphinx_basic_ng/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) sphinx | $(PYTHON_TOOLCHAIN) + sphinx | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinx_copybutton/dependencies b/build/pkgs/sphinx_copybutton/dependencies index 175a793ecbc..ac849c62bf6 100644 --- a/build/pkgs/sphinx_copybutton/dependencies +++ b/build/pkgs/sphinx_copybutton/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) sphinx | $(PYTHON_TOOLCHAIN) + sphinx | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_applehelp/dependencies b/build/pkgs/sphinxcontrib_applehelp/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/sphinxcontrib_applehelp/dependencies +++ b/build/pkgs/sphinxcontrib_applehelp/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_applehelp/distros/arch.txt b/build/pkgs/sphinxcontrib_applehelp/distros/arch.txt new file mode 100644 index 00000000000..3754baa21f5 --- /dev/null +++ b/build/pkgs/sphinxcontrib_applehelp/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-applehelp diff --git a/build/pkgs/sphinxcontrib_applehelp/distros/fedora.txt b/build/pkgs/sphinxcontrib_applehelp/distros/fedora.txt new file mode 100644 index 00000000000..3754baa21f5 --- /dev/null +++ b/build/pkgs/sphinxcontrib_applehelp/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-applehelp diff --git a/build/pkgs/sphinxcontrib_applehelp/distros/freebsd.txt b/build/pkgs/sphinxcontrib_applehelp/distros/freebsd.txt new file mode 100644 index 00000000000..73fbc3bf7ad --- /dev/null +++ b/build/pkgs/sphinxcontrib_applehelp/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-applehelp diff --git a/build/pkgs/sphinxcontrib_applehelp/distros/gentoo.txt b/build/pkgs/sphinxcontrib_applehelp/distros/gentoo.txt new file mode 100644 index 00000000000..66ac8da7340 --- /dev/null +++ b/build/pkgs/sphinxcontrib_applehelp/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-applehelp diff --git a/build/pkgs/sphinxcontrib_applehelp/distros/opensuse.txt b/build/pkgs/sphinxcontrib_applehelp/distros/opensuse.txt index adedbd455f8..9d71e79f307 100644 --- a/build/pkgs/sphinxcontrib_applehelp/distros/opensuse.txt +++ b/build/pkgs/sphinxcontrib_applehelp/distros/opensuse.txt @@ -1 +1 @@ -python3-sphinxcontrib-applehelp +python3${PYTHON_MINOR}-sphinxcontrib-applehelp diff --git a/build/pkgs/sphinxcontrib_applehelp/spkg-configure.m4 b/build/pkgs/sphinxcontrib_applehelp/spkg-configure.m4 new file mode 100644 index 00000000000..e834aed8fd8 --- /dev/null +++ b/build/pkgs/sphinxcontrib_applehelp/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_applehelp], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_applehelp]) +]) diff --git a/build/pkgs/sphinxcontrib_devhelp/dependencies b/build/pkgs/sphinxcontrib_devhelp/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/sphinxcontrib_devhelp/dependencies +++ b/build/pkgs/sphinxcontrib_devhelp/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_devhelp/distros/arch.txt b/build/pkgs/sphinxcontrib_devhelp/distros/arch.txt new file mode 100644 index 00000000000..0b1b3e44a6b --- /dev/null +++ b/build/pkgs/sphinxcontrib_devhelp/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-devhelp diff --git a/build/pkgs/sphinxcontrib_devhelp/distros/fedora.txt b/build/pkgs/sphinxcontrib_devhelp/distros/fedora.txt new file mode 100644 index 00000000000..0b1b3e44a6b --- /dev/null +++ b/build/pkgs/sphinxcontrib_devhelp/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-devhelp diff --git a/build/pkgs/sphinxcontrib_devhelp/distros/freebsd.txt b/build/pkgs/sphinxcontrib_devhelp/distros/freebsd.txt new file mode 100644 index 00000000000..86982bcbd27 --- /dev/null +++ b/build/pkgs/sphinxcontrib_devhelp/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-devhelp diff --git a/build/pkgs/sphinxcontrib_devhelp/distros/gentoo.txt b/build/pkgs/sphinxcontrib_devhelp/distros/gentoo.txt new file mode 100644 index 00000000000..9b5c899a706 --- /dev/null +++ b/build/pkgs/sphinxcontrib_devhelp/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-devhelp diff --git a/build/pkgs/sphinxcontrib_devhelp/distros/opensuse.txt b/build/pkgs/sphinxcontrib_devhelp/distros/opensuse.txt new file mode 100644 index 00000000000..95012c2425d --- /dev/null +++ b/build/pkgs/sphinxcontrib_devhelp/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-sphinxcontrib-devhelp diff --git a/build/pkgs/sphinxcontrib_devhelp/spkg-configure.m4 b/build/pkgs/sphinxcontrib_devhelp/spkg-configure.m4 new file mode 100644 index 00000000000..8728136e92e --- /dev/null +++ b/build/pkgs/sphinxcontrib_devhelp/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_devhelp], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_devhelp]) +]) diff --git a/build/pkgs/sphinxcontrib_htmlhelp/dependencies b/build/pkgs/sphinxcontrib_htmlhelp/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/sphinxcontrib_htmlhelp/dependencies +++ b/build/pkgs/sphinxcontrib_htmlhelp/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_htmlhelp/distros/arch.txt b/build/pkgs/sphinxcontrib_htmlhelp/distros/arch.txt new file mode 100644 index 00000000000..81390fd522f --- /dev/null +++ b/build/pkgs/sphinxcontrib_htmlhelp/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-htmlhelp diff --git a/build/pkgs/sphinxcontrib_htmlhelp/distros/fedora.txt b/build/pkgs/sphinxcontrib_htmlhelp/distros/fedora.txt new file mode 100644 index 00000000000..81390fd522f --- /dev/null +++ b/build/pkgs/sphinxcontrib_htmlhelp/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-htmlhelp diff --git a/build/pkgs/sphinxcontrib_htmlhelp/distros/freebsd.txt b/build/pkgs/sphinxcontrib_htmlhelp/distros/freebsd.txt new file mode 100644 index 00000000000..9b97c55996b --- /dev/null +++ b/build/pkgs/sphinxcontrib_htmlhelp/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-htmlhelp diff --git a/build/pkgs/sphinxcontrib_htmlhelp/distros/gentoo.txt b/build/pkgs/sphinxcontrib_htmlhelp/distros/gentoo.txt new file mode 100644 index 00000000000..e080bacf8ba --- /dev/null +++ b/build/pkgs/sphinxcontrib_htmlhelp/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-htmlhelp diff --git a/build/pkgs/sphinxcontrib_htmlhelp/distros/opensuse.txt b/build/pkgs/sphinxcontrib_htmlhelp/distros/opensuse.txt new file mode 100644 index 00000000000..5859fe855bb --- /dev/null +++ b/build/pkgs/sphinxcontrib_htmlhelp/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-sphinxcontrib-htmlhelp diff --git a/build/pkgs/sphinxcontrib_htmlhelp/spkg-configure.m4 b/build/pkgs/sphinxcontrib_htmlhelp/spkg-configure.m4 new file mode 100644 index 00000000000..c77b003dc37 --- /dev/null +++ b/build/pkgs/sphinxcontrib_htmlhelp/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_htmlhelp], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_htmlhelp]) +]) diff --git a/build/pkgs/sphinxcontrib_jsmath/dependencies b/build/pkgs/sphinxcontrib_jsmath/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/sphinxcontrib_jsmath/dependencies +++ b/build/pkgs/sphinxcontrib_jsmath/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_jsmath/distros/arch.txt b/build/pkgs/sphinxcontrib_jsmath/distros/arch.txt new file mode 100644 index 00000000000..2b4927832ac --- /dev/null +++ b/build/pkgs/sphinxcontrib_jsmath/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-jsmath diff --git a/build/pkgs/sphinxcontrib_jsmath/distros/fedora.txt b/build/pkgs/sphinxcontrib_jsmath/distros/fedora.txt new file mode 100644 index 00000000000..2b4927832ac --- /dev/null +++ b/build/pkgs/sphinxcontrib_jsmath/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-jsmath diff --git a/build/pkgs/sphinxcontrib_jsmath/distros/freebsd.txt b/build/pkgs/sphinxcontrib_jsmath/distros/freebsd.txt new file mode 100644 index 00000000000..78aa428cb13 --- /dev/null +++ b/build/pkgs/sphinxcontrib_jsmath/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-jsmath diff --git a/build/pkgs/sphinxcontrib_jsmath/distros/gentoo.txt b/build/pkgs/sphinxcontrib_jsmath/distros/gentoo.txt new file mode 100644 index 00000000000..041a4710e66 --- /dev/null +++ b/build/pkgs/sphinxcontrib_jsmath/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-jsmath diff --git a/build/pkgs/sphinxcontrib_jsmath/distros/opensuse.txt b/build/pkgs/sphinxcontrib_jsmath/distros/opensuse.txt new file mode 100644 index 00000000000..dbe478264db --- /dev/null +++ b/build/pkgs/sphinxcontrib_jsmath/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-sphinxcontrib-jsmath diff --git a/build/pkgs/sphinxcontrib_jsmath/spkg-configure.m4 b/build/pkgs/sphinxcontrib_jsmath/spkg-configure.m4 new file mode 100644 index 00000000000..e46bde2bd9d --- /dev/null +++ b/build/pkgs/sphinxcontrib_jsmath/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_jsmath], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_jsmath]) +]) diff --git a/build/pkgs/sphinxcontrib_qthelp/dependencies b/build/pkgs/sphinxcontrib_qthelp/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/sphinxcontrib_qthelp/dependencies +++ b/build/pkgs/sphinxcontrib_qthelp/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_qthelp/distros/arch.txt b/build/pkgs/sphinxcontrib_qthelp/distros/arch.txt new file mode 100644 index 00000000000..2c11924a5df --- /dev/null +++ b/build/pkgs/sphinxcontrib_qthelp/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-qthelp diff --git a/build/pkgs/sphinxcontrib_qthelp/distros/fedora.txt b/build/pkgs/sphinxcontrib_qthelp/distros/fedora.txt new file mode 100644 index 00000000000..2c11924a5df --- /dev/null +++ b/build/pkgs/sphinxcontrib_qthelp/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-qthelp diff --git a/build/pkgs/sphinxcontrib_qthelp/distros/freebsd.txt b/build/pkgs/sphinxcontrib_qthelp/distros/freebsd.txt new file mode 100644 index 00000000000..77ff8756694 --- /dev/null +++ b/build/pkgs/sphinxcontrib_qthelp/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-qthelp diff --git a/build/pkgs/sphinxcontrib_qthelp/distros/gentoo.txt b/build/pkgs/sphinxcontrib_qthelp/distros/gentoo.txt new file mode 100644 index 00000000000..7210099b087 --- /dev/null +++ b/build/pkgs/sphinxcontrib_qthelp/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-qthelp diff --git a/build/pkgs/sphinxcontrib_qthelp/distros/opensuse.txt b/build/pkgs/sphinxcontrib_qthelp/distros/opensuse.txt new file mode 100644 index 00000000000..9462502bae5 --- /dev/null +++ b/build/pkgs/sphinxcontrib_qthelp/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-sphinxcontrib-qthelp diff --git a/build/pkgs/sphinxcontrib_qthelp/spkg-configure.m4 b/build/pkgs/sphinxcontrib_qthelp/spkg-configure.m4 new file mode 100644 index 00000000000..81ea5e1269f --- /dev/null +++ b/build/pkgs/sphinxcontrib_qthelp/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_qthelp], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_qthelp]) +]) diff --git a/build/pkgs/sphinxcontrib_serializinghtml/dependencies b/build/pkgs/sphinxcontrib_serializinghtml/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/sphinxcontrib_serializinghtml/dependencies +++ b/build/pkgs/sphinxcontrib_serializinghtml/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_serializinghtml/distros/arch.txt b/build/pkgs/sphinxcontrib_serializinghtml/distros/arch.txt new file mode 100644 index 00000000000..46d22be403f --- /dev/null +++ b/build/pkgs/sphinxcontrib_serializinghtml/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-serializinghtml diff --git a/build/pkgs/sphinxcontrib_serializinghtml/distros/fedora.txt b/build/pkgs/sphinxcontrib_serializinghtml/distros/fedora.txt new file mode 100644 index 00000000000..46d22be403f --- /dev/null +++ b/build/pkgs/sphinxcontrib_serializinghtml/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-serializinghtml diff --git a/build/pkgs/sphinxcontrib_serializinghtml/distros/freebsd.txt b/build/pkgs/sphinxcontrib_serializinghtml/distros/freebsd.txt new file mode 100644 index 00000000000..de7f59bad6e --- /dev/null +++ b/build/pkgs/sphinxcontrib_serializinghtml/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-serializinghtml diff --git a/build/pkgs/sphinxcontrib_serializinghtml/distros/gentoo.txt b/build/pkgs/sphinxcontrib_serializinghtml/distros/gentoo.txt new file mode 100644 index 00000000000..38bca8f1dcb --- /dev/null +++ b/build/pkgs/sphinxcontrib_serializinghtml/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sphinxcontrib-serializinghtml diff --git a/build/pkgs/sphinxcontrib_serializinghtml/distros/opensuse.txt b/build/pkgs/sphinxcontrib_serializinghtml/distros/opensuse.txt index 1a8ea8424a7..7a647e3e36a 100644 --- a/build/pkgs/sphinxcontrib_serializinghtml/distros/opensuse.txt +++ b/build/pkgs/sphinxcontrib_serializinghtml/distros/opensuse.txt @@ -1 +1 @@ -python3-sphinxcontrib-serializinghtml +python3${PYTHON_MINOR}-sphinxcontrib-serializinghtml diff --git a/build/pkgs/sphinxcontrib_serializinghtml/install-requires.txt b/build/pkgs/sphinxcontrib_serializinghtml/install-requires.txt index 98fc0654928..584fc77c6b2 100644 --- a/build/pkgs/sphinxcontrib_serializinghtml/install-requires.txt +++ b/build/pkgs/sphinxcontrib_serializinghtml/install-requires.txt @@ -1 +1 @@ -sphinxcontrib_serializinghtml >=1.1.4 +sphinxcontrib_serializinghtml >=1.1.5 diff --git a/build/pkgs/sphinxcontrib_serializinghtml/spkg-configure.m4 b/build/pkgs/sphinxcontrib_serializinghtml/spkg-configure.m4 new file mode 100644 index 00000000000..be8e62555ac --- /dev/null +++ b/build/pkgs/sphinxcontrib_serializinghtml/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([sphinxcontrib_serializinghtml], [ + SAGE_PYTHON_PACKAGE_CHECK([sphinxcontrib_serializinghtml]) +]) diff --git a/build/pkgs/sphinxcontrib_websupport/dependencies b/build/pkgs/sphinxcontrib_websupport/dependencies index dabbd0f750d..52be4a5ba53 100644 --- a/build/pkgs/sphinxcontrib_websupport/dependencies +++ b/build/pkgs/sphinxcontrib_websupport/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) sphinxcontrib_serializinghtml | $(PYTHON_TOOLCHAIN) + sphinxcontrib_serializinghtml | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sphinxcontrib_websupport/distros/arch.txt b/build/pkgs/sphinxcontrib_websupport/distros/arch.txt new file mode 100644 index 00000000000..a9a5a1a1727 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/distros/arch.txt @@ -0,0 +1 @@ +python-sphinxcontrib-websupport diff --git a/build/pkgs/sphinxcontrib_websupport/distros/fedora.txt b/build/pkgs/sphinxcontrib_websupport/distros/fedora.txt new file mode 100644 index 00000000000..a9a5a1a1727 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/distros/fedora.txt @@ -0,0 +1 @@ +python-sphinxcontrib-websupport diff --git a/build/pkgs/sphinxcontrib_websupport/distros/freebsd.txt b/build/pkgs/sphinxcontrib_websupport/distros/freebsd.txt new file mode 100644 index 00000000000..b8911943237 --- /dev/null +++ b/build/pkgs/sphinxcontrib_websupport/distros/freebsd.txt @@ -0,0 +1 @@ +textproc/py-sphinxcontrib-websupport diff --git a/build/pkgs/sphinxcontrib_websupport/distros/opensuse.txt b/build/pkgs/sphinxcontrib_websupport/distros/opensuse.txt index 2c8e8e8d34d..d01c76bd534 100644 --- a/build/pkgs/sphinxcontrib_websupport/distros/opensuse.txt +++ b/build/pkgs/sphinxcontrib_websupport/distros/opensuse.txt @@ -1 +1 @@ -python3-sphinxcontrib-websupport +python3${PYTHON_MINOR}-sphinxcontrib-websupport diff --git a/build/pkgs/sqlalchemy/distros/opensuse.txt b/build/pkgs/sqlalchemy/distros/opensuse.txt index 023e06b7468..0a1757fd5b3 100644 --- a/build/pkgs/sqlalchemy/distros/opensuse.txt +++ b/build/pkgs/sqlalchemy/distros/opensuse.txt @@ -1 +1 @@ -python3-SQLAlchemy +python3${PYTHON_MINOR}-SQLAlchemy diff --git a/build/pkgs/stack_data/dependencies b/build/pkgs/stack_data/dependencies index cf6aae43990..52b3edda4b5 100644 --- a/build/pkgs/stack_data/dependencies +++ b/build/pkgs/stack_data/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) executing asttokens pure_eval | $(PYTHON_TOOLCHAIN) + executing asttokens pure_eval | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/stack_data/distros/gentoo.txt b/build/pkgs/stack_data/distros/gentoo.txt new file mode 100644 index 00000000000..6f94c8c7fdc --- /dev/null +++ b/build/pkgs/stack_data/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/stack_data diff --git a/build/pkgs/stack_data/spkg-configure.m4 b/build/pkgs/stack_data/spkg-configure.m4 new file mode 100644 index 00000000000..6c1dd4cee59 --- /dev/null +++ b/build/pkgs/stack_data/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([stack_data], [ + SAGE_PYTHON_PACKAGE_CHECK([stack_data]) +]) diff --git a/build/pkgs/surface_dynamics/dependencies b/build/pkgs/surface_dynamics/dependencies index 936121d388d..d8bc8524dbb 100644 --- a/build/pkgs/surface_dynamics/dependencies +++ b/build/pkgs/surface_dynamics/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) cysignals pplpy $(SAGE_SRC)/sage/rings/integer.pxd $(SAGE_SRC)/sage/ext/stdsage.pxd | $(PYTHON_TOOLCHAIN) $(SAGERUNTIME) + cysignals pplpy $(SAGE_SRC)/sage/rings/integer.pxd $(SAGE_SRC)/sage/ext/stdsage.pxd | $(PYTHON_TOOLCHAIN) $(SAGERUNTIME) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/symengine_py/dependencies b/build/pkgs/symengine_py/dependencies index 0b94df79ab9..c48bcedf69c 100644 --- a/build/pkgs/symengine_py/dependencies +++ b/build/pkgs/symengine_py/dependencies @@ -1,4 +1,4 @@ -symengine $(PYTHON) | cmake cython $(PYTHON_TOOLCHAIN) +symengine | cmake cython $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sympy/dependencies b/build/pkgs/sympy/dependencies index 24e1585f16e..6480ac46289 100644 --- a/build/pkgs/sympy/dependencies +++ b/build/pkgs/sympy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) mpmath | $(PYTHON_TOOLCHAIN) + mpmath | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sympy/distros/arch.txt b/build/pkgs/sympy/distros/arch.txt new file mode 100644 index 00000000000..126c88afd85 --- /dev/null +++ b/build/pkgs/sympy/distros/arch.txt @@ -0,0 +1 @@ +python-sympy diff --git a/build/pkgs/sympy/distros/debian.txt b/build/pkgs/sympy/distros/debian.txt new file mode 100644 index 00000000000..db423c87ba7 --- /dev/null +++ b/build/pkgs/sympy/distros/debian.txt @@ -0,0 +1 @@ +python3-sympy diff --git a/build/pkgs/sympy/distros/fedora.txt b/build/pkgs/sympy/distros/fedora.txt new file mode 100644 index 00000000000..126c88afd85 --- /dev/null +++ b/build/pkgs/sympy/distros/fedora.txt @@ -0,0 +1 @@ +python-sympy diff --git a/build/pkgs/sympy/distros/gentoo.txt b/build/pkgs/sympy/distros/gentoo.txt new file mode 100644 index 00000000000..b5a5034c731 --- /dev/null +++ b/build/pkgs/sympy/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/sympy diff --git a/build/pkgs/sympy/distros/opensuse.txt b/build/pkgs/sympy/distros/opensuse.txt new file mode 100644 index 00000000000..bea17da35b4 --- /dev/null +++ b/build/pkgs/sympy/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-sympy diff --git a/build/pkgs/sympy/spkg-configure.m4 b/build/pkgs/sympy/spkg-configure.m4 new file mode 100644 index 00000000000..fa0f1f54311 --- /dev/null +++ b/build/pkgs/sympy/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([sympy], [SAGE_PYTHON_PACKAGE_CHECK([sympy])]) diff --git a/build/pkgs/terminado/dependencies b/build/pkgs/terminado/dependencies index 54ec1c7c229..2138b7ccbe8 100644 --- a/build/pkgs/terminado/dependencies +++ b/build/pkgs/terminado/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) ptyprocess tornado | $(PYTHON_TOOLCHAIN) hatchling + ptyprocess tornado | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/terminado/distros/gentoo.txt b/build/pkgs/terminado/distros/gentoo.txt new file mode 100644 index 00000000000..1df16f18abb --- /dev/null +++ b/build/pkgs/terminado/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/terminado diff --git a/build/pkgs/terminado/spkg-configure.m4 b/build/pkgs/terminado/spkg-configure.m4 new file mode 100644 index 00000000000..5defc2ff877 --- /dev/null +++ b/build/pkgs/terminado/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([terminado], [SAGE_PYTHON_PACKAGE_CHECK([terminado])]) diff --git a/build/pkgs/texttable/dependencies b/build/pkgs/texttable/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/texttable/dependencies +++ b/build/pkgs/texttable/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/texttable/distros/arch.txt b/build/pkgs/texttable/distros/arch.txt new file mode 100644 index 00000000000..8d1ccec8c7d --- /dev/null +++ b/build/pkgs/texttable/distros/arch.txt @@ -0,0 +1 @@ +python-texttable diff --git a/build/pkgs/texttable/distros/debian.txt b/build/pkgs/texttable/distros/debian.txt new file mode 100644 index 00000000000..8f8e7e29d7a --- /dev/null +++ b/build/pkgs/texttable/distros/debian.txt @@ -0,0 +1 @@ +python3-texttable diff --git a/build/pkgs/texttable/distros/fedora.txt b/build/pkgs/texttable/distros/fedora.txt new file mode 100644 index 00000000000..8d1ccec8c7d --- /dev/null +++ b/build/pkgs/texttable/distros/fedora.txt @@ -0,0 +1 @@ +python-texttable diff --git a/build/pkgs/texttable/distros/gentoo.txt b/build/pkgs/texttable/distros/gentoo.txt new file mode 100644 index 00000000000..b33a7a75d50 --- /dev/null +++ b/build/pkgs/texttable/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/texttable diff --git a/build/pkgs/texttable/distros/opensuse.txt b/build/pkgs/texttable/distros/opensuse.txt new file mode 100644 index 00000000000..d4959328e94 --- /dev/null +++ b/build/pkgs/texttable/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-texttable diff --git a/build/pkgs/texttable/spkg-configure.m4 b/build/pkgs/texttable/spkg-configure.m4 new file mode 100644 index 00000000000..42a3de105b5 --- /dev/null +++ b/build/pkgs/texttable/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([texttable], [SAGE_PYTHON_PACKAGE_CHECK([texttable])]) diff --git a/build/pkgs/tinycss2/dependencies b/build/pkgs/tinycss2/dependencies index 89200065387..7ebee8487db 100644 --- a/build/pkgs/tinycss2/dependencies +++ b/build/pkgs/tinycss2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) webencodings | $(PYTHON_TOOLCHAIN) + webencodings | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/toml/SPKG.rst b/build/pkgs/toml/SPKG.rst deleted file mode 100644 index e1b53b8f79e..00000000000 --- a/build/pkgs/toml/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -toml: Python Library for Tom's Obvious, Minimal Language -======================================================== - -Description ------------ - -Python Library for Tom's Obvious, Minimal Language - -License -------- - -MIT - -Upstream Contact ----------------- - -https://pypi.org/project/toml/ - diff --git a/build/pkgs/toml/checksums.ini b/build/pkgs/toml/checksums.ini deleted file mode 100644 index 27467959676..00000000000 --- a/build/pkgs/toml/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=toml-VERSION.tar.gz -sha1=00137fc72f31100edd1c03670081b03053b6c836 -md5=59bce5d8d67e858735ec3f399ec90253 -cksum=3015531877 -upstream_url=https://pypi.io/packages/source/t/toml/toml-VERSION.tar.gz diff --git a/build/pkgs/toml/distros/arch.txt b/build/pkgs/toml/distros/arch.txt new file mode 100644 index 00000000000..821ee775ac7 --- /dev/null +++ b/build/pkgs/toml/distros/arch.txt @@ -0,0 +1 @@ +python-toml diff --git a/build/pkgs/toml/distros/conda.txt b/build/pkgs/toml/distros/conda.txt deleted file mode 100644 index bd79a658fe7..00000000000 --- a/build/pkgs/toml/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -toml diff --git a/build/pkgs/toml/distros/void.txt b/build/pkgs/toml/distros/debian.txt similarity index 100% rename from build/pkgs/toml/distros/void.txt rename to build/pkgs/toml/distros/debian.txt diff --git a/build/pkgs/toml/distros/fedora.txt b/build/pkgs/toml/distros/fedora.txt new file mode 100644 index 00000000000..821ee775ac7 --- /dev/null +++ b/build/pkgs/toml/distros/fedora.txt @@ -0,0 +1 @@ +python-toml diff --git a/build/pkgs/toml/distros/gentoo.txt b/build/pkgs/toml/distros/gentoo.txt new file mode 100644 index 00000000000..64fcea3559f --- /dev/null +++ b/build/pkgs/toml/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/toml diff --git a/build/pkgs/toml/distros/opensuse.txt b/build/pkgs/toml/distros/opensuse.txt new file mode 100644 index 00000000000..fbc340aee15 --- /dev/null +++ b/build/pkgs/toml/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-toml diff --git a/build/pkgs/toml/install-requires.txt b/build/pkgs/toml/install-requires.txt deleted file mode 100644 index bd79a658fe7..00000000000 --- a/build/pkgs/toml/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -toml diff --git a/build/pkgs/toml/package-version.txt b/build/pkgs/toml/package-version.txt deleted file mode 100644 index 5eef0f10e8c..00000000000 --- a/build/pkgs/toml/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.10.2 diff --git a/build/pkgs/toml/spkg-install.in b/build/pkgs/toml/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/toml/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/tomli/dependencies b/build/pkgs/tomli/dependencies index 7cd1e28759d..992761d1f11 100644 --- a/build/pkgs/tomli/dependencies +++ b/build/pkgs/tomli/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | pip flit_core + | pip flit_core $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tomli/distros/gentoo.txt b/build/pkgs/tomli/distros/gentoo.txt new file mode 100644 index 00000000000..0458e252a4d --- /dev/null +++ b/build/pkgs/tomli/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/tomli diff --git a/build/pkgs/tomli/spkg-configure.m4 b/build/pkgs/tomli/spkg-configure.m4 new file mode 100644 index 00000000000..95a8b8b84c2 --- /dev/null +++ b/build/pkgs/tomli/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([tomli], [SAGE_PYTHON_PACKAGE_CHECK([tomli])]) diff --git a/build/pkgs/tomlkit/dependencies b/build/pkgs/tomlkit/dependencies index 3eb5a92ef22..e67b4c08948 100644 --- a/build/pkgs/tomlkit/dependencies +++ b/build/pkgs/tomlkit/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) poetry_core + | $(PYTHON_TOOLCHAIN) poetry_core $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tomlkit/distros/gentoo.txt b/build/pkgs/tomlkit/distros/gentoo.txt new file mode 100644 index 00000000000..afe59d9bfe2 --- /dev/null +++ b/build/pkgs/tomlkit/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/tomlkit diff --git a/build/pkgs/tomlkit/spkg-configure.m4 b/build/pkgs/tomlkit/spkg-configure.m4 new file mode 100644 index 00000000000..6da571e5370 --- /dev/null +++ b/build/pkgs/tomlkit/spkg-configure.m4 @@ -0,0 +1,2 @@ +SAGE_SPKG_CONFIGURE([tomlkit], [SAGE_PYTHON_PACKAGE_CHECK([tomlkit])]) + diff --git a/build/pkgs/tornado/dependencies b/build/pkgs/tornado/dependencies index 212c6234efb..0d4701f9d71 100644 --- a/build/pkgs/tornado/dependencies +++ b/build/pkgs/tornado/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) certifi | $(PYTHON_TOOLCHAIN) + certifi | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tornado/distros/gentoo.txt b/build/pkgs/tornado/distros/gentoo.txt new file mode 100644 index 00000000000..6ae4b9fc443 --- /dev/null +++ b/build/pkgs/tornado/distros/gentoo.txt @@ -0,0 +1 @@ +www-servers/tornado diff --git a/build/pkgs/tornado/distros/opensuse.txt b/build/pkgs/tornado/distros/opensuse.txt index 426685be95b..1f37b341221 100644 --- a/build/pkgs/tornado/distros/opensuse.txt +++ b/build/pkgs/tornado/distros/opensuse.txt @@ -1 +1 @@ -python3-tornado +python3${PYTHON_MINOR}-tornado diff --git a/build/pkgs/tornado/spkg-configure.m4 b/build/pkgs/tornado/spkg-configure.m4 new file mode 100644 index 00000000000..1ee5bc9f544 --- /dev/null +++ b/build/pkgs/tornado/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([tornado], [SAGE_PYTHON_PACKAGE_CHECK([tornado])]) diff --git a/build/pkgs/tox/checksums.ini b/build/pkgs/tox/checksums.ini index 19a159a8e4a..caf44efe123 100644 --- a/build/pkgs/tox/checksums.ini +++ b/build/pkgs/tox/checksums.ini @@ -1,5 +1,5 @@ -tarball=tox-VERSION.tar.gz -sha1=4a17b94eea345a2fb1a76106fb4d01ac9aca3569 -md5=ed4a11d13cd6a206b516c84750109602 -cksum=3144404727 -upstream_url=https://pypi.io/packages/source/t/tox/tox-VERSION.tar.gz +tarball=tox-VERSION-py3-none-any.whl +sha1=d3312285c4988d3307d3b000a8a18cfcb16aea29 +md5=127a9d3fae61a0967f14ab6d59fd118f +cksum=4147794288 +upstream_url=https://pypi.io/packages/py3/t/tox/tox-VERSION-py3-none-any.whl diff --git a/build/pkgs/tox/dependencies b/build/pkgs/tox/dependencies index 5a00a282b7d..ebec555b1e0 100644 --- a/build/pkgs/tox/dependencies +++ b/build/pkgs/tox/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) packaging six filelock pluggy py toml virtualenv importlib_metadata | $(PYTHON_TOOLCHAIN) +cachetools chardet colorama filelock packaging platformdirs pluggy pyproject_api tomli virtualenv | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tox/install-requires.txt b/build/pkgs/tox/install-requires.txt index ffbf4099ae8..41bd756ea6b 100644 --- a/build/pkgs/tox/install-requires.txt +++ b/build/pkgs/tox/install-requires.txt @@ -1 +1,2 @@ -tox >= 3.21.4 +# see spkg-configure.m4 +tox >= 4.2.7 diff --git a/build/pkgs/tox/package-version.txt b/build/pkgs/tox/package-version.txt index 8c53120442c..d782fca8f64 100644 --- a/build/pkgs/tox/package-version.txt +++ b/build/pkgs/tox/package-version.txt @@ -1 +1 @@ -3.27.0 +4.11.1 diff --git a/build/pkgs/tox/spkg-configure.m4 b/build/pkgs/tox/spkg-configure.m4 index 5a260439cdd..ab69f673b5a 100644 --- a/build/pkgs/tox/spkg-configure.m4 +++ b/build/pkgs/tox/spkg-configure.m4 @@ -1,28 +1,18 @@ SAGE_SPKG_CONFIGURE([tox], [ - dnl Use non-ancient tox with full support for PEP 517. - m4_pushdef([TOX3_MIN_VERSION], [3.21.4]) dnl Early 4.0.x versions have bugs regarding complex factor conditions - m4_pushdef([TOX4_MIN_VERSION], [4.0.15]) - AC_CACHE_CHECK([for tox 3 >= ]TOX3_MIN_VERSION[ or tox 4 >= ]TOX4_MIN_VERSION, [ac_cv_path_TOX], [ + dnl [pkgenv] added in 4.2 - https://tox.wiki/en/latest/upgrading.html#packaging-configuration-and-inheritance + dnl 4.2.7 for repaired numerical factors + m4_pushdef([TOX4_MIN_VERSION], [4.2.7]) + AC_CACHE_CHECK([for tox >= ]TOX4_MIN_VERSION, [ac_cv_path_TOX], [ AC_PATH_PROGS_FEATURE_CHECK([TOX], [tox], [ tox_version=$($ac_path_TOX --version 2> /dev/null | tail -n 1) - AS_IF([test -n "$tox_version"], [ - AX_COMPARE_VERSION([$tox_version], [lt], [4], [ - AX_COMPARE_VERSION([$tox_version], [ge], TOX3_MIN_VERSION, [ - ac_cv_path_TOX="$ac_path_TOX" - ac_path_TOX_found=: - ]) - ], [ - AX_COMPARE_VERSION([$tox_version], [ge], TOX4_MIN_VERSION, [ - ac_cv_path_TOX="$ac_path_TOX" - ac_path_TOX_found=: - ]) - ]) + AX_COMPARE_VERSION([$tox_version], [ge], TOX4_MIN_VERSION, [ + ac_cv_path_TOX="$ac_path_TOX" + ac_path_TOX_found=: ]) ]) ]) AS_IF([test -z "$ac_cv_path_TOX"], [sage_spkg_install_tox=yes]) m4_popdef([TOX4_MIN_VERSION]) - m4_popdef([TOX3_MIN_VERSION]) ]) diff --git a/build/pkgs/tox/spkg-install.in b/build/pkgs/tox/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/tox/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/traitlets/dependencies b/build/pkgs/traitlets/dependencies index df88de8f64c..6b7d279c5ab 100644 --- a/build/pkgs/traitlets/dependencies +++ b/build/pkgs/traitlets/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython_genutils decorator six hatchling + | $(PYTHON_TOOLCHAIN) ipython_genutils decorator hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/traitlets/distros/gentoo.txt b/build/pkgs/traitlets/distros/gentoo.txt new file mode 100644 index 00000000000..46bfaab6fef --- /dev/null +++ b/build/pkgs/traitlets/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/traitlets diff --git a/build/pkgs/traitlets/distros/opensuse.txt b/build/pkgs/traitlets/distros/opensuse.txt index 93cb8375e46..f0cc6730e1f 100644 --- a/build/pkgs/traitlets/distros/opensuse.txt +++ b/build/pkgs/traitlets/distros/opensuse.txt @@ -1 +1 @@ -python3-traitlets +python3${PYTHON_MINOR}-traitlets diff --git a/build/pkgs/traitlets/spkg-configure.m4 b/build/pkgs/traitlets/spkg-configure.m4 new file mode 100644 index 00000000000..df2382b8f01 --- /dev/null +++ b/build/pkgs/traitlets/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([traitlets], [SAGE_PYTHON_PACKAGE_CHECK([traitlets])]) diff --git a/build/pkgs/typing_extensions/dependencies b/build/pkgs/typing_extensions/dependencies index f8bd1ee040d..e0e94942dba 100644 --- a/build/pkgs/typing_extensions/dependencies +++ b/build/pkgs/typing_extensions/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | flit_core + | flit_core $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/typing_extensions/distros/arch.txt b/build/pkgs/typing_extensions/distros/arch.txt new file mode 100644 index 00000000000..92ad68dabc4 --- /dev/null +++ b/build/pkgs/typing_extensions/distros/arch.txt @@ -0,0 +1 @@ +python-typing_extensions diff --git a/build/pkgs/typing_extensions/distros/debian.txt b/build/pkgs/typing_extensions/distros/debian.txt new file mode 100644 index 00000000000..424ebf1a645 --- /dev/null +++ b/build/pkgs/typing_extensions/distros/debian.txt @@ -0,0 +1 @@ +python3-typing-extensions diff --git a/build/pkgs/typing_extensions/distros/fedora.txt b/build/pkgs/typing_extensions/distros/fedora.txt new file mode 100644 index 00000000000..8c13a4539ac --- /dev/null +++ b/build/pkgs/typing_extensions/distros/fedora.txt @@ -0,0 +1 @@ +python-typing-extensions diff --git a/build/pkgs/typing_extensions/distros/freebsd.txt b/build/pkgs/typing_extensions/distros/freebsd.txt new file mode 100644 index 00000000000..b4424d384df --- /dev/null +++ b/build/pkgs/typing_extensions/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-typing-extensions diff --git a/build/pkgs/typing_extensions/distros/gentoo.txt b/build/pkgs/typing_extensions/distros/gentoo.txt new file mode 100644 index 00000000000..20b3d1de123 --- /dev/null +++ b/build/pkgs/typing_extensions/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/typing-extensions diff --git a/build/pkgs/typing_extensions/distros/opensuse.txt b/build/pkgs/typing_extensions/distros/opensuse.txt new file mode 100644 index 00000000000..62a10cbbc72 --- /dev/null +++ b/build/pkgs/typing_extensions/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-typing_extensions diff --git a/build/pkgs/typing_extensions/spkg-configure.m4 b/build/pkgs/typing_extensions/spkg-configure.m4 new file mode 100644 index 00000000000..cbb75fec955 --- /dev/null +++ b/build/pkgs/typing_extensions/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([typing_extensions],[ + SAGE_PYTHON_PACKAGE_CHECK([typing_extensions]) +]) diff --git a/build/pkgs/tzdata/dependencies b/build/pkgs/tzdata/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/tzdata/dependencies +++ b/build/pkgs/tzdata/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tzlocal/dependencies b/build/pkgs/tzlocal/dependencies index da4c8ca99cf..4e161b299ab 100644 --- a/build/pkgs/tzlocal/dependencies +++ b/build/pkgs/tzlocal/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) backports_zoneinfo pytz_deprecation_shim | $(PYTHON_TOOLCHAIN) + pytz_deprecation_shim | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tzlocal/distros/arch.txt b/build/pkgs/tzlocal/distros/arch.txt new file mode 100644 index 00000000000..1de39af60b2 --- /dev/null +++ b/build/pkgs/tzlocal/distros/arch.txt @@ -0,0 +1 @@ +python-tzlocal diff --git a/build/pkgs/tzlocal/distros/debian.txt b/build/pkgs/tzlocal/distros/debian.txt new file mode 100644 index 00000000000..95d2d705c05 --- /dev/null +++ b/build/pkgs/tzlocal/distros/debian.txt @@ -0,0 +1 @@ +python3-tzlocal diff --git a/build/pkgs/tzlocal/distros/fedora.txt b/build/pkgs/tzlocal/distros/fedora.txt new file mode 100644 index 00000000000..1de39af60b2 --- /dev/null +++ b/build/pkgs/tzlocal/distros/fedora.txt @@ -0,0 +1 @@ +python-tzlocal diff --git a/build/pkgs/tzlocal/distros/freebsd.txt b/build/pkgs/tzlocal/distros/freebsd.txt new file mode 100644 index 00000000000..c42ec397d1c --- /dev/null +++ b/build/pkgs/tzlocal/distros/freebsd.txt @@ -0,0 +1 @@ +devel/py-tzlocal diff --git a/build/pkgs/tzlocal/distros/gentoo.txt b/build/pkgs/tzlocal/distros/gentoo.txt new file mode 100644 index 00000000000..2018442dcc4 --- /dev/null +++ b/build/pkgs/tzlocal/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/tzlocal diff --git a/build/pkgs/tzlocal/distros/opensuse.txt b/build/pkgs/tzlocal/distros/opensuse.txt index 95d2d705c05..2e4de5e9e49 100644 --- a/build/pkgs/tzlocal/distros/opensuse.txt +++ b/build/pkgs/tzlocal/distros/opensuse.txt @@ -1 +1 @@ -python3-tzlocal +python3${PYTHON_MINOR}-tzlocal diff --git a/build/pkgs/tzlocal/spkg-configure.m4 b/build/pkgs/tzlocal/spkg-configure.m4 new file mode 100644 index 00000000000..e020b2823f9 --- /dev/null +++ b/build/pkgs/tzlocal/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([tzlocal], [SAGE_PYTHON_PACKAGE_CHECK([tzlocal])]) diff --git a/build/pkgs/urllib3/dependencies b/build/pkgs/urllib3/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/urllib3/dependencies +++ b/build/pkgs/urllib3/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/urllib3/distros/arch.txt b/build/pkgs/urllib3/distros/arch.txt new file mode 100644 index 00000000000..af6e58664fb --- /dev/null +++ b/build/pkgs/urllib3/distros/arch.txt @@ -0,0 +1 @@ +python-urllib3 diff --git a/build/pkgs/urllib3/distros/debian.txt b/build/pkgs/urllib3/distros/debian.txt new file mode 100644 index 00000000000..918569f9677 --- /dev/null +++ b/build/pkgs/urllib3/distros/debian.txt @@ -0,0 +1 @@ +python3-urllib3 diff --git a/build/pkgs/urllib3/distros/fedora.txt b/build/pkgs/urllib3/distros/fedora.txt new file mode 100644 index 00000000000..af6e58664fb --- /dev/null +++ b/build/pkgs/urllib3/distros/fedora.txt @@ -0,0 +1 @@ +python-urllib3 diff --git a/build/pkgs/urllib3/distros/freebsd.txt b/build/pkgs/urllib3/distros/freebsd.txt new file mode 100644 index 00000000000..751c1d25c41 --- /dev/null +++ b/build/pkgs/urllib3/distros/freebsd.txt @@ -0,0 +1 @@ +net/py-urllib3 diff --git a/build/pkgs/urllib3/distros/gentoo.txt b/build/pkgs/urllib3/distros/gentoo.txt new file mode 100644 index 00000000000..172a5357dba --- /dev/null +++ b/build/pkgs/urllib3/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/urllib3 diff --git a/build/pkgs/urllib3/distros/opensuse.txt b/build/pkgs/urllib3/distros/opensuse.txt new file mode 100644 index 00000000000..7466e3c2bdd --- /dev/null +++ b/build/pkgs/urllib3/distros/opensuse.txt @@ -0,0 +1 @@ +python3${PYTHON_MINOR}-urllib3 diff --git a/build/pkgs/urllib3/spkg-configure.m4 b/build/pkgs/urllib3/spkg-configure.m4 new file mode 100644 index 00000000000..d7ef3e1661c --- /dev/null +++ b/build/pkgs/urllib3/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([urllib3], [SAGE_PYTHON_PACKAGE_CHECK([urllib3])]) diff --git a/build/pkgs/vcversioner/dependencies b/build/pkgs/vcversioner/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/vcversioner/dependencies +++ b/build/pkgs/vcversioner/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/vcversioner/distros/opensuse.txt b/build/pkgs/vcversioner/distros/opensuse.txt index 3a9b9818aa4..a9b307f8509 100644 --- a/build/pkgs/vcversioner/distros/opensuse.txt +++ b/build/pkgs/vcversioner/distros/opensuse.txt @@ -1 +1 @@ -python3-vcversioner +python3${PYTHON_MINOR}-vcversioner diff --git a/build/pkgs/virtualenv/checksums.ini b/build/pkgs/virtualenv/checksums.ini index e324ed781ee..b7def1fa7e0 100644 --- a/build/pkgs/virtualenv/checksums.ini +++ b/build/pkgs/virtualenv/checksums.ini @@ -1,5 +1,5 @@ -tarball=virtualenv-VERSION.tar.gz -sha1=8371dccb9866b40c3fdc5c0aa9c8f034cc0b174b -md5=b2d60f3c431f370b5fed5169b94f4798 -cksum=3124829245 -upstream_url=https://pypi.io/packages/source/v/virtualenv/virtualenv-VERSION.tar.gz +tarball=virtualenv-VERSION-py3-none-any.whl +sha1=a17fc6409d29b7e7b1427f37496bfc0fa399f9bf +md5=6374ee91c1ed02956a334aa01d9414ed +cksum=31593789 +upstream_url=https://pypi.io/packages/py3/v/virtualenv/virtualenv-VERSION-py3-none-any.whl diff --git a/build/pkgs/virtualenv/dependencies b/build/pkgs/virtualenv/dependencies index a8b8def7051..b0e964bba0c 100644 --- a/build/pkgs/virtualenv/dependencies +++ b/build/pkgs/virtualenv/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) appdirs distlib filelock six importlib_metadata importlib_resources platformdirs | $(PYTHON_TOOLCHAIN) +distlib filelock platformdirs | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/virtualenv/package-version.txt b/build/pkgs/virtualenv/package-version.txt index d1df974a56b..b744a5a46cb 100644 --- a/build/pkgs/virtualenv/package-version.txt +++ b/build/pkgs/virtualenv/package-version.txt @@ -1 +1 @@ -20.16.6 +20.24.4 diff --git a/build/pkgs/virtualenv/spkg-install.in b/build/pkgs/virtualenv/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/virtualenv/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/wcwidth/dependencies b/build/pkgs/wcwidth/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/wcwidth/dependencies +++ b/build/pkgs/wcwidth/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/wcwidth/distros/gentoo.txt b/build/pkgs/wcwidth/distros/gentoo.txt new file mode 100644 index 00000000000..edeb80b62a1 --- /dev/null +++ b/build/pkgs/wcwidth/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/wcwidth diff --git a/build/pkgs/wcwidth/distros/opensuse.txt b/build/pkgs/wcwidth/distros/opensuse.txt index 2974220c878..8fea03a6c67 100644 --- a/build/pkgs/wcwidth/distros/opensuse.txt +++ b/build/pkgs/wcwidth/distros/opensuse.txt @@ -1 +1 @@ -python3-wcwidth +python3${PYTHON_MINOR}-wcwidth diff --git a/build/pkgs/wcwidth/spkg-configure.m4 b/build/pkgs/wcwidth/spkg-configure.m4 new file mode 100644 index 00000000000..5bde15af224 --- /dev/null +++ b/build/pkgs/wcwidth/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([wcwidth], [SAGE_PYTHON_PACKAGE_CHECK([wcwidth])]) diff --git a/build/pkgs/webencodings/dependencies b/build/pkgs/webencodings/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/webencodings/dependencies +++ b/build/pkgs/webencodings/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/webencodings/distros/arch.txt b/build/pkgs/webencodings/distros/arch.txt new file mode 100644 index 00000000000..12ddba901a4 --- /dev/null +++ b/build/pkgs/webencodings/distros/arch.txt @@ -0,0 +1 @@ +python-webencodings diff --git a/build/pkgs/webencodings/distros/debian.txt b/build/pkgs/webencodings/distros/debian.txt new file mode 100644 index 00000000000..ac30c2f3307 --- /dev/null +++ b/build/pkgs/webencodings/distros/debian.txt @@ -0,0 +1 @@ +python3-webencodings diff --git a/build/pkgs/webencodings/distros/fedora.txt b/build/pkgs/webencodings/distros/fedora.txt new file mode 100644 index 00000000000..12ddba901a4 --- /dev/null +++ b/build/pkgs/webencodings/distros/fedora.txt @@ -0,0 +1 @@ +python-webencodings diff --git a/build/pkgs/webencodings/distros/gentoo.txt b/build/pkgs/webencodings/distros/gentoo.txt new file mode 100644 index 00000000000..7539b0fdcde --- /dev/null +++ b/build/pkgs/webencodings/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/webencodings diff --git a/build/pkgs/webencodings/distros/opensuse.txt b/build/pkgs/webencodings/distros/opensuse.txt index ac30c2f3307..b8d9c4d299c 100644 --- a/build/pkgs/webencodings/distros/opensuse.txt +++ b/build/pkgs/webencodings/distros/opensuse.txt @@ -1 +1 @@ -python3-webencodings +python3${PYTHON_MINOR}-webencodings diff --git a/build/pkgs/webencodings/spkg-configure.m4 b/build/pkgs/webencodings/spkg-configure.m4 new file mode 100644 index 00000000000..1b9a5c431f3 --- /dev/null +++ b/build/pkgs/webencodings/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([webencodings], [ + SAGE_PYTHON_PACKAGE_CHECK([webencodings]) +]) diff --git a/build/pkgs/wheel/dependencies b/build/pkgs/wheel/dependencies index 98d3e59447b..a8e327be793 100644 --- a/build/pkgs/wheel/dependencies +++ b/build/pkgs/wheel/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) setuptools + setuptools | $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/wheel/distros/arch.txt b/build/pkgs/wheel/distros/arch.txt new file mode 100644 index 00000000000..ae4cbb9f52f --- /dev/null +++ b/build/pkgs/wheel/distros/arch.txt @@ -0,0 +1 @@ +python-wheel diff --git a/build/pkgs/wheel/distros/debian.txt b/build/pkgs/wheel/distros/debian.txt new file mode 100644 index 00000000000..3c066725a1d --- /dev/null +++ b/build/pkgs/wheel/distros/debian.txt @@ -0,0 +1 @@ +python3-wheel diff --git a/build/pkgs/wheel/distros/fedora.txt b/build/pkgs/wheel/distros/fedora.txt new file mode 100644 index 00000000000..ae4cbb9f52f --- /dev/null +++ b/build/pkgs/wheel/distros/fedora.txt @@ -0,0 +1 @@ +python-wheel diff --git a/build/pkgs/wheel/distros/gentoo.txt b/build/pkgs/wheel/distros/gentoo.txt new file mode 100644 index 00000000000..ec571d59d93 --- /dev/null +++ b/build/pkgs/wheel/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/wheel diff --git a/build/pkgs/wheel/distros/opensuse.txt b/build/pkgs/wheel/distros/opensuse.txt index 3c066725a1d..3df335c1375 100644 --- a/build/pkgs/wheel/distros/opensuse.txt +++ b/build/pkgs/wheel/distros/opensuse.txt @@ -1 +1 @@ -python3-wheel +python3${PYTHON_MINOR}-wheel diff --git a/build/pkgs/wheel/spkg-configure.m4 b/build/pkgs/wheel/spkg-configure.m4 new file mode 100644 index 00000000000..7897ea96cc6 --- /dev/null +++ b/build/pkgs/wheel/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([wheel], [SAGE_PYTHON_PACKAGE_CHECK([wheel])]) diff --git a/build/pkgs/widgetsnbextension/dependencies b/build/pkgs/widgetsnbextension/dependencies index f7ff1dca568..301cefdea49 100644 --- a/build/pkgs/widgetsnbextension/dependencies +++ b/build/pkgs/widgetsnbextension/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jupyter_packaging | $(PYTHON_TOOLCHAIN) jupyter_core + jupyter_packaging | $(PYTHON_TOOLCHAIN) jupyter_core $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/widgetsnbextension/spkg-configure.m4 b/build/pkgs/widgetsnbextension/spkg-configure.m4 new file mode 100644 index 00000000000..bf82dafe209 --- /dev/null +++ b/build/pkgs/widgetsnbextension/spkg-configure.m4 @@ -0,0 +1,3 @@ +SAGE_SPKG_CONFIGURE([widgetsnbextension], [ + SAGE_PYTHON_PACKAGE_CHECK([widgetsnbextension]) +]) diff --git a/build/pkgs/zipp/dependencies b/build/pkgs/zipp/dependencies index 4361e46ddaf..9be6b4aab7c 100644 --- a/build/pkgs/zipp/dependencies +++ b/build/pkgs/zipp/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) vcversioner | $(PYTHON_TOOLCHAIN) + vcversioner | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/zipp/distros/gentoo.txt b/build/pkgs/zipp/distros/gentoo.txt new file mode 100644 index 00000000000..7f59450c2b7 --- /dev/null +++ b/build/pkgs/zipp/distros/gentoo.txt @@ -0,0 +1 @@ +dev-python/zipp diff --git a/build/pkgs/zipp/spkg-configure.m4 b/build/pkgs/zipp/spkg-configure.m4 new file mode 100644 index 00000000000..0fe3a9cd224 --- /dev/null +++ b/build/pkgs/zipp/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([zipp], [SAGE_PYTHON_PACKAGE_CHECK([zipp])]) diff --git a/build/sage_bootstrap/creator.py b/build/sage_bootstrap/creator.py index f7a6ab203dc..c52090e5fa3 100644 --- a/build/sage_bootstrap/creator.py +++ b/build/sage_bootstrap/creator.py @@ -94,7 +94,7 @@ def set_python_data_and_scripts(self, pypi_package_name=None, source='normal'): if pypi_package_name is None: pypi_package_name = self.package_name with open(os.path.join(self.path, 'dependencies'), 'w+') as f: - f.write('$(PYTHON) | $(PYTHON_TOOLCHAIN)\n\n') + f.write(' | $(PYTHON_TOOLCHAIN) $(PYTHON)\n\n') f.write('----------\nAll lines of this file are ignored except the first.\n') if source == 'normal': with open(os.path.join(self.path, 'spkg-install.in'), 'w+') as f: diff --git a/configure.ac b/configure.ac index 4a255967fc6..532da2165e8 100644 --- a/configure.ac +++ b/configure.ac @@ -445,6 +445,40 @@ AC_ARG_ENABLE([download-from-upstream-url], [disallow downloading packages from their upstream URL if they cannot be found on the Sage mirrors])], [], [AS_VAR_SET([enable_download_from_upstream_url], [yes])]) +AC_ARG_ENABLE( + [system-site-packages], [AS_HELP_STRING( + [--enable-system-site-packages], + [allow the use of python packages from the system (experimental; default: no)] + )], [ + AS_IF([test "x$enable_system_site_packages" = "xyes"], [ + dnl When installing python SPKGs in the presence of system-site + dnl packages, we need to --ignore-installed so that a patched SPKG + dnl can be installed in the presence of an unpatched system package + dnl that appears (to pip) to be identical. The --no-deps flag is + dnl then needed because --ignore-installed will make any installed + dnl dependencies invisible to pip, who does not appreciate that. + SAGE_PIP_INSTALL_FLAGS="${SAGE_PIP_INSTALL_FLAGS} --no-deps --ignore-installed" + + SAGE_VENV_FLAGS="${SAGE_VENV_FLAGS} --system-site-packages" + + dnl We want to raise an error if the user asked for "system site + dnl packages" but the system python will not be used. Technically + dnl that causes no problems (SAGE_PYTHON_PACKAGE_CHECK always fails, + dnl so SPKGs are used for all python packages), but it may be confusing + dnl to end users who expect the flag to actually give them access to + dnl their system python packages and who may not be paying close + dnl attention to their ./configure output. + with_system_python3="force" + + dnl This is substituted in to build/bin/sage-build-env-config.in for use + dnl by build/bin/sage-get-system-packages + ENABLE_SYSTEM_SITE_PACKAGES=yes + ]) +]) +AC_SUBST([ENABLE_SYSTEM_SITE_PACKAGES]) +AC_SUBST([SAGE_PIP_INSTALL_FLAGS]) +AC_SUBST([SAGE_VENV_FLAGS]) + SAGE_SPKG_OPTIONS="" AS_IF([test "x$enable_experimental_packages" = "xyes"], [ AS_VAR_APPEND([SAGE_SPKG_OPTIONS], [" -y"]) @@ -473,7 +507,7 @@ AC_ARG_ENABLE([cvxopt], AC_ARG_ENABLE([notebook], AS_HELP_STRING([--disable-notebook], [disable build of the Jupyter notebook and related packages]), [ - for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi; do + for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi webencodings tinycss2; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done ]) @@ -487,7 +521,7 @@ AS_IF([test "$SAGE_ENABLE_notebook" = no -a "$SAGE_ENABLE_sagelib" = no], [ AC_ARG_ENABLE([r], AS_HELP_STRING([--disable-r], [disable build of the R package and related packages]), [ - for pkg in r rpy2 r_jupyter; do + for pkg in r rpy2 r_jupyter tzlocal; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done ]) @@ -496,7 +530,7 @@ AC_ARG_ENABLE([doc], AS_HELP_STRING([--disable-doc], [disable build of the Sage documentation and packages depending on it]), [ dnl Disable packages needed for docbuilding - for pkg in sage_docbuild alabaster babel snowballstemmer imagesize sphinx sphinxcontrib_devhelp sphinxcontrib_jsmath sphinxcontrib_serializinghtml sphinxcontrib_applehelp sphinxcontrib_htmlhelp sphinxcontrib_qthelp sphinxcontrib_websupport jupyter_sphinx furo sphinx_copybutton; do + for pkg in sage_docbuild alabaster babel snowballstemmer imagesize sphinx sphinxcontrib_devhelp sphinxcontrib_jsmath sphinxcontrib_serializinghtml sphinxcontrib_applehelp sphinxcontrib_htmlhelp sphinxcontrib_qthelp sphinxcontrib_websupport jupyter_sphinx furo sphinx_copybutton mathjax; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done AS_VAR_IF([enableval], [no], [dnl Disable the docbuild by disabling the install tree for documentation diff --git a/docker/Dockerfile b/docker/Dockerfile index 9d56b10b9c5..6b0ecab4795 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -70,11 +70,12 @@ ARG ARTIFACT_BASE=source-clean +ARG MAKE_BUILD=make-build ################################################################################ # Image containing the run-time dependencies for Sage # ################################################################################ -FROM ubuntu:jammy as run-time-dependencies +FROM ubuntu:latest as run-time-dependencies LABEL maintainer="Erik M. Bray , Julian Rüth " # Set sane defaults for common environment variables. ENV LC_ALL C.UTF-8 @@ -122,7 +123,7 @@ ARG SAGE_ROOT=/home/sage/sage RUN mkdir -p "$SAGE_ROOT" WORKDIR $SAGE_ROOT RUN git init -RUN git remote add trac https://gitlab.com/sagemath/dev/tracmirror.git +RUN git remote add upstream https://github.com/sagemath/sage.git ################################################################################ # Image with the build context added, i.e., the directory from which `docker # @@ -155,10 +156,10 @@ WORKDIR $SAGE_ROOT # We create a list of all files present in the artifact-base (with a timestamp # of now) so we can find out later which files were added/changed/removed. RUN find . \( -type f -or -type l \) > $HOME/artifact-base.manifest -RUN git fetch "$HOME/sage-context" HEAD \ +RUN git fetch --update-shallow "$HOME/sage-context" HEAD \ && if [ -e docker/.commit ]; then \ git reset `cat docker/.commit` \ - || ( echo "Could not find commit `cat docker/.commit` in your local Git history. Please merge in the latest built develop branch to fix this: git fetch trac && git merge `cat docker/.commit`." && exit 1 ) \ + || ( echo "Could not find commit `cat docker/.commit` in your local Git history. Please merge in the latest built develop branch to fix this: git fetch upstream && git merge `cat docker/.commit`." && exit 1 ) \ else \ echo "You are building from $ARTIFACT_BASE which has no docker/.commit file. That's a bug unless you are building from source-clean or something similar." \ && git reset FETCH_HEAD \ @@ -203,7 +204,7 @@ RUN make build ################################################################################ # Image with a full build of sage and its documentation. # ################################################################################ -FROM make-build as make-all +FROM $MAKE_BUILD as make-all # The docbuild needs quite some RAM (as of May 2018). It sometimes calls # os.fork() to spawn an external program which then exceeds easily the # overcommit limit of the system (no RAM is actually used, but this limit is diff --git a/m4/sage_python_package_check.m4 b/m4/sage_python_package_check.m4 new file mode 100644 index 00000000000..e0713512ea0 --- /dev/null +++ b/m4/sage_python_package_check.m4 @@ -0,0 +1,118 @@ +# +# SYNOPSIS +# +# SAGE_PYTHON_PACKAGE_CHECK(package) +# +# DESCRIPTION +# +# Determine if the system copy of a python package can be used by sage. +# +# This macro uses setuptools.version's pkg_resources to check that the +# "install-requires.txt" file for the named package is satisfied, and +# it can typically fail in four ways: +# +# 1. If --enable-system-site-packages was not passed to ./configure, +# +# 2. If we are not using the system python (no $PYTHON_FOR_VENV), +# +# 3. If we are unable to create a venv with the system python, +# +# 4. If setuptools is not available to the system python, +# +# 5. If the contents of install-requires.txt are not met (wrong +# version, no version, etc.) by the system python. +# +# In any of those cases, we set sage_spkg_install_$package to "yes" +# so that the corresponding SPKG is installed. Otherwise, we do +# nothing, since the default value of sage_spkg_install_$package +# is "no" (to use the system copy). +# +# The SAGE_SPKG_CONFIGURE_PYTHON3() macro is AC_REQUIRE'd to ensure +# that $PYTHON_FOR_VENV is available, if it is going to be available. +# The check is run inside a new venv, and with the PYTHONUSERBASE +# variable poisoned in the same manner as sage-env poisons it, to +# ensure that the ./configure- and run-time views of the system +# are as similar as possible. +# +# To avoid suggesting these system packages to users who have not +# set --enable-system-site-packages, this macro also changes the +# default for --with-system-foo from "yes" to "no" in that case. +# + +AC_DEFUN([SAGE_PYTHON_PACKAGE_CHECK], [ + AC_MSG_CHECKING([if --enable-system-site-packages was used]) + AS_IF([test "${enable_system_site_packages}" = "yes"], [ + AC_MSG_RESULT(yes) + AC_REQUIRE([SAGE_SPKG_CONFIGURE_PYTHON3]) + + dnl We run this check inside a python venv, because that's ultimately + dnl how the system $PYTHON_FOR_VENV will be used. + AC_MSG_CHECKING([if we can create a python venv in config.venv]) + + dnl Use --clear because ./configure typically clobbers its output files. + AS_IF(["${PYTHON_FOR_VENV}" build/bin/sage-venv dnl + --system-site-packages dnl + --clear dnl + config.venv dnl + 2>&AS_MESSAGE_LOG_FD], [ + AC_MSG_RESULT(yes) + dnl strip all comments from install-requires.txt; this should leave + dnl only a single line containing the version specification for this + dnl package. + SAGE_PKG_VERSPEC=$(sed '/^#/d' "./build/pkgs/$1/install-requires.txt") + AC_MSG_CHECKING([for python package $1 ("${SAGE_PKG_VERSPEC}")]) + + dnl To prevent user-site (pip install --user) packages from being + dnl detected as "system" packages, we poison PYTHONUSERBASE. The + dnl sage-env script also does this at runtime; we mimic that + dnl implementation to ensure that the behaviors at ./configure and + dnl runtime are identical. Beware that (as in sage-env) the poisoning + dnl is skipped if PYTHONUSERBASE is non-empty. In particular, if the + dnl user points PYTHONUSERBASE to any path (even the default), then + dnl his local pip packages will be detected. + PYTHONUSERBASE_SAVED="${PYTHONUSERBASE}" + AS_IF([test -z "${PYTHONUSERBASE}"], [ + PYTHONUSERBASE="${HOME}/.sage/local" + ]) + + AS_IF( + [PYTHONUSERBASE="${PYTHONUSERBASE}" config.venv/bin/python3 -c dnl + "import pkg_resources; dnl + pkg_resources.require('${SAGE_PKG_VERSPEC}'.splitlines())" dnl + 2>&AS_MESSAGE_LOG_FD], + [AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no); sage_spkg_install_$1=yes] + ) + + PYTHONUSERBASE="${PYTHONUSERBASE_SAVED}" + ], [ + dnl failed to create a venv for some reason + AC_MSG_RESULT(no) + sage_spkg_install_$1=yes + ]) + + dnl Clean up config.venv, but only if we could have created it. + dnl (The --clear flag to pyvenv will not clobber a plain file.) + AS_IF([test -d config.venv], [rm -rf config.venv]) + ], [ + dnl System site packages are disabled. + AC_MSG_RESULT(no; skipping check) + sage_spkg_install_$1=yes + + dnl We have to retroactively hack the --with-system-foo={no,yes,force} + dnl mechanism here because it wasn't designed with the ability to + dnl disable arbitrary chunks of system packages in mind. The easy cases + dnl are "no" and "force" which require no action; "no" means we won't + dnl suggest the package anyway, and "force" will raise an error when + dnl the system-package check fails. + dnl + dnl The default of "yes" is more troubling because it is the default. To + dnl avoid prompting users to install packages that won't be used, we want + dnl to ignore "yes" when reporting the "hint: install these packages..." + dnl at the end of ./configure. To accomplish that, we change "yes" to + dnl "no" here, essentially changing the default for packages using this + dnl macro when --enable-system-site-packages is disabled. Packages with + dnl "no" are not suggested to the user. + AS_IF([test "${sage_use_system_$1}" = "yes"],[sage_use_system_$1=no]) + ]) +]) diff --git a/m4/sage_spkg_configure.m4 b/m4/sage_spkg_configure.m4 index a0eeaa53a74..1f07d7cd294 100644 --- a/m4/sage_spkg_configure.m4 +++ b/m4/sage_spkg_configure.m4 @@ -58,6 +58,31 @@ dnl indicate why m4_pushdef([SPKG_USE_SYSTEM], [sage_use_system_]SPKG_NAME) # BEGIN SAGE_SPKG_CONFIGURE_]m4_toupper($1)[ +dnl Hide the output from Python (system site package) checks +dnl when --enable-system-site-packages was not given. This +dnl doesn't affect the test results but it minimizes the noise +dnl in the ./configure output. The config.log however retains +dnl everything. +dnl +dnl Open descriptor 9 as a copy of AS_MESSAGE_FD, so that it +dnl can later be used to restore AS_MESSAGE_FD. Afterwards, +dnl send AS_MESSAGE_FD to /dev/null. We'll restore it if this +dnl isn't a python package or if --enable-system-site-packages +dnl was given (or at the end of this macro, if nothing else). +exec 9<&AS_MESSAGE_FD +exec AS_MESSAGE_FD>/dev/null + +AS_IF([test "${enable_system_site_packages}" = "yes"], [ + dnl Python package checks are enabled, so restore AS_MESSAGE_FD + exec AS_MESSAGE_FD<&9 +]) + +SPKG_CONFIGURE="${SAGE_ROOT}/build/pkgs/$1/spkg-configure.m4" +AS_IF([! grep -q [SAGE_PYTHON_PACKAGE_CHECK] "${SPKG_CONFIGURE}"],[ + dnl Not a python package, so restore AS_MESSAGE_FD + exec AS_MESSAGE_FD<&9 +]) + echo "-----------------------------------------------------------------------------" >& AS_MESSAGE_FD echo "Checking whether SageMath should install SPKG $1..." >& AS_MESSAGE_FD AS_BOX([Checking whether SageMath should install SPKG $1...]) >& AS_MESSAGE_LOG_FD @@ -140,6 +165,13 @@ AS_VAR_IF(SPKG_INSTALL, [no], [ dnl Run POST $5 +dnl Restore the message file descriptor that we clobbered earlier +dnl for the sake of hiding site package check noise. It's possible +dnl that we've already done this above, but it doesn't hurt to do +dnl it again, and we want everything "back to normal" at the end +dnl of this macro. +exec AS_MESSAGE_FD<&9 + # END SAGE_SPKG_CONFIGURE_]m4_toupper($1)[ m4_popdef([SPKG_USE_SYSTEM]) m4_popdef([SPKG_REQUIRE]) diff --git a/m4/setup_cfg_metadata.m4 b/m4/setup_cfg_metadata.m4 index ca042345499..896ca37eb7f 100644 --- a/m4/setup_cfg_metadata.m4 +++ b/m4/setup_cfg_metadata.m4 @@ -13,7 +13,6 @@ classifiers = Operating System :: POSIX Operating System :: MacOS :: MacOS X Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sage-conf/_sage_conf/_conf.py.in b/pkgs/sage-conf/_sage_conf/_conf.py.in index f2e197b45ed..87b27ca05cb 100644 --- a/pkgs/sage-conf/_sage_conf/_conf.py.in +++ b/pkgs/sage-conf/_sage_conf/_conf.py.in @@ -50,7 +50,7 @@ SAGE_ARCHFLAGS = "@SAGE_ARCHFLAGS@" SAGE_PKG_CONFIG_PATH = "@SAGE_PKG_CONFIG_PATH@".replace('$SAGE_LOCAL', SAGE_LOCAL) # Used in sage.repl.ipython_kernel.install -MATHJAX_DIR = SAGE_LOCAL + "/share/mathjax" +MATHJAX_DIR = "@SAGE_MATHJAX_DIR@".replace('${prefix}', SAGE_LOCAL) THREEJS_DIR = SAGE_LOCAL + "/share/threejs-sage" # OpenMP flags, if available. diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sage-docbuild/setup.cfg b/pkgs/sage-docbuild/setup.cfg index 337548c6ff3..596f9b4506e 100644 --- a/pkgs/sage-docbuild/setup.cfg +++ b/pkgs/sage-docbuild/setup.cfg @@ -17,7 +17,6 @@ classifiers = Operating System :: POSIX Operating System :: MacOS :: MacOS X Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sage-setup/setup.cfg b/pkgs/sage-setup/setup.cfg index 5d7f440e7c6..2355ef6b301 100644 --- a/pkgs/sage-setup/setup.cfg +++ b/pkgs/sage-setup/setup.cfg @@ -32,7 +32,7 @@ packages = sage_setup.autogen.interpreters.specs sage_setup.command -python_requires = >=3.8, <3.12 +python_requires = >=3.9, <3.12 install_requires = pkgconfig diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-bliss/pyproject.toml.m4 b/pkgs/sagemath-bliss/pyproject.toml.m4 index 439482ad26b..1cbcdf7e162 100644 --- a/pkgs/sagemath-bliss/pyproject.toml.m4 +++ b/pkgs/sagemath-bliss/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_sage_conf SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-categories/pyproject.toml.m4 b/pkgs/sagemath-categories/pyproject.toml.m4 index 6ce29ddcb71..cf4c97f1fd1 100644 --- a/pkgs/sagemath-categories/pyproject.toml.m4 +++ b/pkgs/sagemath-categories/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment diff --git a/pkgs/sagemath-categories/setup.cfg.m4 b/pkgs/sagemath-categories/setup.cfg.m4 index 2539a8aafb5..f5eb7c72968 100644 --- a/pkgs/sagemath-categories/setup.cfg.m4 +++ b/pkgs/sagemath-categories/setup.cfg.m4 @@ -8,7 +8,7 @@ long_description_content_type = text/x-rst include(`setup_cfg_metadata.m4')dnl' [options] -python_requires = >=3.8, <3.12 +python_requires = >=3.9, <3.12 install_requires = SPKG_INSTALL_REQUIRES_sagemath_objects diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-coxeter3/pyproject.toml.m4 b/pkgs/sagemath-coxeter3/pyproject.toml.m4 index e5b939e414d..a7d65382b21 100644 --- a/pkgs/sagemath-coxeter3/pyproject.toml.m4 +++ b/pkgs/sagemath-coxeter3/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-environment/pyproject.toml.m4 b/pkgs/sagemath-environment/pyproject.toml.m4 index 7f62a86cd69..fb2db955ed5 100644 --- a/pkgs/sagemath-environment/pyproject.toml.m4 +++ b/pkgs/sagemath-environment/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_wheel ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-environment/setup.cfg.m4 b/pkgs/sagemath-environment/setup.cfg.m4 index 1ede94ee283..9e5bb31eeb7 100644 --- a/pkgs/sagemath-environment/setup.cfg.m4 +++ b/pkgs/sagemath-environment/setup.cfg.m4 @@ -8,7 +8,7 @@ long_description_content_type = text/x-rst include(`setup_cfg_metadata.m4')dnl' [options] -python_requires = >=3.8, <3.12 +python_requires = >=3.9, <3.12 install_requires = py_modules = diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-mcqd/pyproject.toml.m4 b/pkgs/sagemath-mcqd/pyproject.toml.m4 index d28ff179a00..7e651119193 100644 --- a/pkgs/sagemath-mcqd/pyproject.toml.m4 +++ b/pkgs/sagemath-mcqd/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-meataxe/pyproject.toml.m4 b/pkgs/sagemath-meataxe/pyproject.toml.m4 index e5b939e414d..a7d65382b21 100644 --- a/pkgs/sagemath-meataxe/pyproject.toml.m4 +++ b/pkgs/sagemath-meataxe/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-objects/pyproject.toml.m4 b/pkgs/sagemath-objects/pyproject.toml.m4 index 0c5558f3412..d8fda57a8f8 100644 --- a/pkgs/sagemath-objects/pyproject.toml.m4 +++ b/pkgs/sagemath-objects/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment diff --git a/pkgs/sagemath-objects/setup.cfg.m4 b/pkgs/sagemath-objects/setup.cfg.m4 index 94ec7f63024..894c07b5bbf 100644 --- a/pkgs/sagemath-objects/setup.cfg.m4 +++ b/pkgs/sagemath-objects/setup.cfg.m4 @@ -9,7 +9,7 @@ include(`setup_cfg_metadata.m4')dnl' [options] include(`sage_spkg_versions.m4')dnl' -python_requires = >=3.8, <3.12 +python_requires = >=3.9, <3.12 install_requires = SPKG_INSTALL_REQUIRES_gmpy2 SPKG_INSTALL_REQUIRES_cysignals diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-repl/pyproject.toml.m4 b/pkgs/sagemath-repl/pyproject.toml.m4 index 7f62a86cd69..fb2db955ed5 100644 --- a/pkgs/sagemath-repl/pyproject.toml.m4 +++ b/pkgs/sagemath-repl/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_wheel ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-repl/setup.cfg.m4 b/pkgs/sagemath-repl/setup.cfg.m4 index 8c7e11777b8..f71d7bf6c2a 100644 --- a/pkgs/sagemath-repl/setup.cfg.m4 +++ b/pkgs/sagemath-repl/setup.cfg.m4 @@ -8,7 +8,7 @@ long_description_content_type = text/x-rst include(`setup_cfg_metadata.m4')dnl' [options] -python_requires = >=3.8, <3.12 +python_requires = >=3.9, <3.12 install_requires = SPKG_INSTALL_REQUIRES_sagemath_objects SPKG_INSTALL_REQUIRES_sagemath_environment diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-sirocco/pyproject.toml.m4 b/pkgs/sagemath-sirocco/pyproject.toml.m4 index 1b000bd5c3b..99894dd5e5e 100644 --- a/pkgs/sagemath-sirocco/pyproject.toml.m4 +++ b/pkgs/sagemath-sirocco/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/pkgs/sagemath-tdlib/pyproject.toml.m4 b/pkgs/sagemath-tdlib/pyproject.toml.m4 index e5b939e414d..a7d65382b21 100644 --- a/pkgs/sagemath-tdlib/pyproject.toml.m4 +++ b/pkgs/sagemath-tdlib/pyproject.toml.m4 @@ -2,7 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools + SPKG_INSTALL_REQUIRES_setuptools_wheel SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython diff --git a/pyrightconfig.json b/pyrightconfig.json index 2bcc9ea2a10..643c56360c9 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -7,7 +7,7 @@ "root": "src" } ], - "pythonVersion": "3.8", + "pythonVersion": "3.9", "exclude": ["venv"], "venvPath": "./venv/", "venv": "./", diff --git a/src/VERSION.txt b/src/VERSION.txt index ae425d69819..3a63d34271d 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta3 diff --git a/src/bin/sage-env b/src/bin/sage-env index 13b54fa7e92..2a63be5b7c0 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -635,3 +635,11 @@ if [ -n "$SAGE_LOCAL" ]; then fi fi + + +# Newer versions of debugpy come with a bundled pydevd that complains +# about >=python-3.11's core modules being frozen (and therefore not +# breakpoint-able). This workaround simply hides the warning to keep +# our doctests predictable (which was the status quo with earlier +# versions of debugpy). +export PYDEVD_DISABLE_FILE_VALIDATION=1 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index a823b80cca4..33c372fe352 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.1' -SAGE_RELEASE_DATE='2023-08-20' -SAGE_VERSION_BANNER='SageMath version 10.1, Release Date: 2023-08-20' +SAGE_VERSION='10.2.beta3' +SAGE_RELEASE_DATE='2023-09-16' +SAGE_VERSION_BANNER='SageMath version 10.2.beta3, Release Date: 2023-09-16' diff --git a/src/doc/en/developer/coding_basics.rst b/src/doc/en/developer/coding_basics.rst index 091cb47283b..4821dabfd68 100644 --- a/src/doc/en/developer/coding_basics.rst +++ b/src/doc/en/developer/coding_basics.rst @@ -945,7 +945,7 @@ written. for both examples. - **Preparsing:** As in Sage's console, `4/3` returns `4/3` and not - `1.3333333333333333` as in Python 3.8. Testing occurs with full Sage + `1.3333333333333333` as in Python. Testing occurs with full Sage preparsing of input within the standard Sage shell environment, as described in :ref:`section-preparsing`. diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index 615433aa7d0..d96106ecc98 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -16,18 +16,18 @@ that Sage supports. The information regarding the supported versions can be found in the files ``build/pkgs/python3/spkg-configure.m4`` and ``src/setup.cfg.m4``. -As of Sage 9.7, Python 3.8 is the oldest supported version. Hence, -all language and library features that are available in Python 3.8 can -be used; but features introduced in Python 3.9 cannot be used. If a +Python 3.9 is the oldest supported version. Hence, +all language and library features that are available in Python 3.9 can +be used; but features introduced in Python 3.10 cannot be used. If a feature is deprecated in a newer supported version, it must be ensured that deprecation warnings issued by Python do not lead to failures in doctests. -Some key language and library features have been backported to Python 3.8 +Some key language and library features have been backported to older Python versions using one of two mechanisms: - ``from __future__ import annotations`` (see Python reference for - `__future__ `_) + `__future__ `_) modernizes type annotations according to `PEP 563 `_ (Postponed evaluation of annotations). All Sage library code that uses type annotations diff --git a/src/doc/en/developer/github.rst b/src/doc/en/developer/github.rst index 07ede71057e..79db6ccc3d1 100644 --- a/src/doc/en/developer/github.rst +++ b/src/doc/en/developer/github.rst @@ -73,6 +73,18 @@ and check:: which will show the default repo along with its readme, which is quite long. +``gh`` extensions +----------------- + +``gh`` is extendable; e.g. a useful extension to ``gh`` allows testing of +Sage's GitHub Actions locally, using Docker. It is called ``act`` and can be +installed by running:: + + [alice@localhost sage]$ gh extension install https://github.com/nektos/gh-act + +Append ``--force`` flag to the command above to force an upgrade of the extension. +More details on configuring and using ``gh act`` are in :ref:`chapter-portability_testing`. + Linking Git to your GitHub account ================================== diff --git a/src/doc/en/developer/portability_testing.rst b/src/doc/en/developer/portability_testing.rst index f401b5e4853..b95bb7b5ab7 100644 --- a/src/doc/en/developer/portability_testing.rst +++ b/src/doc/en/developer/portability_testing.rst @@ -1152,6 +1152,58 @@ are available: ptest`` has not been run yet. +Testing GitHub Actions locally +============================== + +`act `_ is a tool, written in Go, and using Docker, +to run GitHub Actions locally; in particular, it speeds up developing Actions. +We recommend using ``gh extension`` facility to install ``act``. :: + + [alice@localhost sage]$ gh extension install https://github.com/nektos/gh-act + +Extra steps needed for configuration of Docker to run Actions locally can be found on +`act's GitHub `_ + +Here we give a very short sampling of ``act``'s capabilities. If you installed standalone +``act``, it should be invoked as ``act``, not as ``gh act``. +After the set up, one can e.g. list all the available linting actions:: + + [alice@localhost sage]$ gh act -l | grep lint + 0 lint-pycodestyle Code style check with pycodestyle Lint lint.yml push,pull_request + 0 lint-relint Code style check with relint Lint lint.yml push,pull_request + 0 lint-rst Validate docstring markup as RST Lint lint.yml push,pull_request + [alice@localhost sage]$ + +run a particular action ``lint-rst`` :: + + [alice@localhost sage]$ gh act -j lint-rst + ... + +and so on. + +By default, ``act`` pulls all the data needed from the next, but it can also cache it, +speeding up repeated runs quite a lot. The following repeats running of ``lint-rst`` using cached data:: + + [alice@localhost sage]$ gh act -p false -r -j lint-rst + [Lint/Validate docstring markup as RST] Start image=catthehacker/ubuntu:act-latest + ... + | rst: commands[0] /home/alice/work/software/sage/src> flake8 --select=RST + | rst: OK (472.60=setup[0.09]+cmd[472.51] seconds) + | congratulations :) (474.10 seconds) + ... + [Lint/Validate docstring markup as RST] Success - Main Lint using tox -e rst + [Lint/Validate docstring markup as RST] Run Post Set up Python + [Lint/Validate docstring markup as RST] docker exec cmd=[node /var/run/act/actions/actions-setup-python@v4/dist/cache-save/index.js] user= workdir= + [Lint/Validate docstring markup as RST] Success - Post Set up Python + [Lint/Validate docstring markup as RST] Job succeeded + +Here ``-p false`` means using already pulled Docker images, and ``-r`` means do not remove Docker images +after a successful run which used them. This, and many more details, can be found by running ``gh act -h``, as well +as reading ``act``'s documentation. + +.. This sectuion is a stub. + More Sage-specfic details for using ``act`` should be added. PRs welcome! + Using our pre-built Docker images for development in VS Code ============================================================ diff --git a/src/doc/en/reference/curves/index.rst b/src/doc/en/reference/curves/index.rst index b95ab97f839..2bc0d098cba 100644 --- a/src/doc/en/reference/curves/index.rst +++ b/src/doc/en/reference/curves/index.rst @@ -10,6 +10,7 @@ Curves sage/schemes/curves/projective_curve sage/schemes/curves/point sage/schemes/curves/closed_point + sage/schemes/curves/zariski_vankampen sage/schemes/jacobians/abstract_jacobian diff --git a/src/doc/en/reference/dynamics/index.rst b/src/doc/en/reference/dynamics/index.rst index 83cb7782f3a..e91f343c899 100644 --- a/src/doc/en/reference/dynamics/index.rst +++ b/src/doc/en/reference/dynamics/index.rst @@ -29,6 +29,7 @@ Arithmetic Dynamical Systems sage/dynamics/arithmetic_dynamics/product_projective_ds sage/dynamics/arithmetic_dynamics/wehlerK3 sage/dynamics/arithmetic_dynamics/berkovich_ds + sage/dynamics/arithmetic_dynamics/dynamical_semigroup .. SEEALSO:: diff --git a/src/doc/en/reference/groups/index.rst b/src/doc/en/reference/groups/index.rst index 46764ef45e1..97a7c126698 100644 --- a/src/doc/en/reference/groups/index.rst +++ b/src/doc/en/reference/groups/index.rst @@ -18,6 +18,7 @@ Groups sage/groups/braid sage/groups/cubic_braid sage/groups/indexed_free_group + sage/groups/artin sage/groups/raag sage/groups/cactus_group sage/groups/group_exp diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 475a34f5dea..e09f339513f 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -351,6 +351,10 @@ REFERENCES: *Characteristic polynomials of subspace arrangements and finite fields*. Advances in Mathematics, 122(2):193-233, 1996. +.. [Ath2000] \C. A. Athanasiadis, + *Deformations of Coxeter hyperplane arrangements and their characteristic polynomials*. + Adv. Stud. Pure Math., 27, 2000. + .. [Av2000] \D. Avis, *A revised implementation of the reverse search vertex enumeration algorithm.* Polytopes-combinatorics and computation. Birkhauser Basel, 2000. @@ -807,6 +811,10 @@ REFERENCES: Stein. strassen_window_multiply_c. strassen.pyx, Sage 3.0, 2008. http://www.sagemath.org +.. [BHS2023] Jose Bastidas, Christophe Hohlweg, and Franco Saliola. + *The primitive Eulerian polynomial*. + Preprint, (2023) :arxiv:`2306.15556`. + .. [BrHu2019] Petter Brändén, June Huh. *Lorentzian polynomials*. Ann. Math. (2) 192, No. 3, 821-891 (2020). :arxiv:`1902.03719`, :doi:`10.4007/annals.2020.192.3.4`. @@ -1100,6 +1108,9 @@ REFERENCES: complexes and combinatorics of simplicial manifolds," *Uspekhi Mat. Nauk* 55 (2000), 171--172. +.. [BP2014] \V. M. Bukhshtaber and T. E. Panov. "Toric Topology", + 2014. :arxiv:`1210.2368` + .. [BP2015] \P. Butera and M. Pernici "Sums of permanental minors using Grassmann algebra", International Journal of Graph Theory and its Applications, 1 (2015), @@ -2661,6 +2672,9 @@ REFERENCES: TR-737-05, (2005). ftp://ftp.cs.princeton.edu/reports/2005/737.pdf +.. [Gek1988] \E.-U. Gekeler, On the coefficients of Drinfel'd modular + forms. Invent. Math. 93 (1988), no. 3, 667-700 + .. [Gek1991] \E.-U. Gekeler. On finite Drinfeld modules. Journal of algebra, 1(141):187–203, 1991. @@ -2777,6 +2791,10 @@ REFERENCES: .. [GL1996] \G. Golub and C. van Loan. *Matrix Computations*. 3rd edition, Johns Hopkins Univ. Press, 1996. +.. [GL2019] \J. Grbić and A. Linton. + "Lowest-degree triple Massey products in moment-angle complexes", + 2019. :arxiv:`1908.02222v2` + .. [GrLe1996] \J. Graham and G.I. Lehrer *Cellular algebras*. Invent. Math. 123 (1996), 1–34. :mathscinet:`MR1376244` @@ -4581,6 +4599,9 @@ REFERENCES: .. [Mil1974] \J. W. Milnor and J. D. Stasheff, *Characteristic Classes*, University Press, Princeton and Tokyo, 1974. +.. [Mil2006] \J. W. Milnor, *On Lattes maps*, + Dynamics on the Riemann sphere, Eur. Math. Soc., 9–43 + .. [Mil1978] \S. Milne, *A q-analog of restricted growth functions, Dobinsky’s equality and Charlier polynomials*. Trans. Amer. Math. Soc., 245 (1978), diff --git a/src/doc/en/reference/topology/index.rst b/src/doc/en/reference/topology/index.rst index 1442b327ed2..955e6827722 100644 --- a/src/doc/en/reference/topology/index.rst +++ b/src/doc/en/reference/topology/index.rst @@ -23,5 +23,6 @@ other types of cell complexes. sage/topology/simplicial_set_morphism sage/topology/cell_complex sage/topology/filtered_simplicial_complex + sage/topology/moment_angle_complex .. include:: ../footer.txt diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 4efe68a2617..de2349a9a3f 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -106,7 +106,6 @@ This base class provides a lot more methods than a general parent:: sage: [p for p in dir(Field) if p not in dir(Parent)] ['__fraction_field', - '__ideal_monoid', '__iter__', '__len__', '__rxor__', @@ -119,6 +118,7 @@ This base class provides a lot more methods than a general parent:: '_default_category', '_gens', '_ideal_class_', + '_ideal_monoid', '_latex_names', '_list', '_one_element', diff --git a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst index 51aec989810..553a946c4d8 100644 --- a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst +++ b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst @@ -298,7 +298,7 @@ http://docs.python.org/library/ for a complete list. :: sage: el bla sage: el.__dict__ - {'__custom_name': 'bla', 'value': 42} + {'_SageObject__custom_name': 'bla', 'value': 42} Lots of Sage objects are not Python objects but compiled Cython objects. Python sees them as builtin objects and you do not have diff --git a/src/pyproject.toml.m4 b/src/pyproject.toml.m4 index 56f1b2b03ab..f707b6f890e 100644 --- a/src/pyproject.toml.m4 +++ b/src/pyproject.toml.m4 @@ -6,7 +6,7 @@ requires = [ # https://github.com/pypa/pip/issues/6144 esyscmd(`sage-get-system-packages install-requires-toml \ sage_conf \ - setuptools \ + setuptools_wheel \ wheel \ sage_setup \ cypari \ diff --git a/src/sage/algebras/affine_nil_temperley_lieb.py b/src/sage/algebras/affine_nil_temperley_lieb.py index f7901ae314d..720c5f481cd 100644 --- a/src/sage/algebras/affine_nil_temperley_lieb.py +++ b/src/sage/algebras/affine_nil_temperley_lieb.py @@ -119,7 +119,7 @@ def _repr_(self): sage: A = AffineNilTemperleyLiebTypeA(3); A The affine nilTemperley Lieb algebra A3 over the ring Integer Ring """ - return "The affine nilTemperley Lieb algebra A%s over the ring %s"%(self._n, self._base_ring) + return "The affine nilTemperley Lieb algebra A%s over the ring %s" % (self._n, self._base_ring) def weyl_group(self): """ @@ -234,7 +234,7 @@ def has_no_braid_relation(self, w, i): return False s = w.parent().simple_reflections() wi = w*s[i] - adjacent = [(i-1)%w.parent().n, (i+1)%w.parent().n] + adjacent = [(i-1) % w.parent().n, (i+1) % w.parent().n] for j in adjacent: if j in w.descents(): if j in wi.descents(): @@ -258,6 +258,6 @@ def _repr_term(self, t, short_display=True): if len(redword) == 0: return "1" elif short_display: - return "*".join("%s%d"%(self._prefix, i) for i in redword) + return "*".join("%s%d" % (self._prefix, i) for i in redword) else: - return "*".join("%s[%d]"%(self._prefix, i) for i in redword) + return "*".join("%s[%d]" % (self._prefix, i) for i in redword) diff --git a/src/sage/algebras/cellular_basis.py b/src/sage/algebras/cellular_basis.py index 42ce84307d5..873bd899b3e 100644 --- a/src/sage/algebras/cellular_basis.py +++ b/src/sage/algebras/cellular_basis.py @@ -233,7 +233,7 @@ def _latex_term(self, x): sm = latex(m) if sm.find('\\text{\\textt') != -1: sm = str(m) - return "C^{%s}_{%s}"%(sla, sm) + return "C^{%s}_{%s}" % (sla, sm) def cellular_basis_of(self): """ diff --git a/src/sage/algebras/down_up_algebra.py b/src/sage/algebras/down_up_algebra.py index c5fe5361282..3ee1bcea25f 100644 --- a/src/sage/algebras/down_up_algebra.py +++ b/src/sage/algebras/down_up_algebra.py @@ -237,7 +237,7 @@ def _latex_(self): sage: latex(DU) \mathcal{DU}(a,b,g) """ - return "\\mathcal{DU}(%s,%s,%s)"%(self._alpha, self._beta, self._gamma) + return "\\mathcal{DU}(%s,%s,%s)" % (self._alpha, self._beta, self._gamma) def _repr_term(self, m): r""" diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py index 9c8090c8929..af2b5e7dd3c 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py @@ -740,7 +740,7 @@ def maximal_ideal(self): - :class:`~sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_ideal.FiniteDimensionalAlgebraIdeal`; the unique maximal ideal of ``self``. If ``self`` is not a local - algebra, a ``ValueError`` is raised. + algebra, a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py index e3f456c263e..22f12ce6bb5 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py @@ -29,7 +29,7 @@ class FiniteDimensionalAlgebraMorphism(RingHomomorphism_im_gens): - ``f`` -- matrix of the underlying `k`-linear map - ``unitary`` -- boolean (default: ``True``); if ``True`` and ``check`` - is also ``True``, raise a ``ValueError`` unless ``A`` and ``B`` are + is also ``True``, raise a :class:`ValueError` unless ``A`` and ``B`` are unitary and ``f`` respects unit elements - ``check`` -- boolean (default: ``True``); check whether the given diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index 52e7471d1bf..460b623b877 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -331,6 +331,7 @@ def create_object(self, version, key): return FreeAlgebra_letterplace(key[1], degrees=key[0]) return FreeAlgebra_generic(key[0], len(key[1]), key[1]) + FreeAlgebra = FreeAlgebraFactory('FreeAlgebra') @@ -597,7 +598,7 @@ def exp_to_monomial(T): out = [] for i in range(len(T)): if T[i]: - out.append((i%ngens,T[i])) + out.append((i % ngens,T[i])) return M(out) return self.element_class(self, {exp_to_monomial(T):c for T,c in x.letterplace_polynomial().dict().items()}) # ok, not a free algebra element (or should not be viewed as one). diff --git a/src/sage/algebras/free_algebra_quotient.py b/src/sage/algebras/free_algebra_quotient.py index 86e0cbfff32..81c7f5ad91e 100644 --- a/src/sage/algebras/free_algebra_quotient.py +++ b/src/sage/algebras/free_algebra_quotient.py @@ -211,7 +211,7 @@ def gen(self, i): sage: H.gen(2) k - An IndexError is raised if an invalid generator is requested:: + An :class:`IndexError` is raised if an invalid generator is requested:: sage: H.gen(3) Traceback (most recent call last): diff --git a/src/sage/algebras/fusion_rings/f_matrix.py b/src/sage/algebras/fusion_rings/f_matrix.py index e178b567a3e..fe39ebf72b4 100644 --- a/src/sage/algebras/fusion_rings/f_matrix.py +++ b/src/sage/algebras/fusion_rings/f_matrix.py @@ -280,7 +280,7 @@ def __init__(self, fusion_ring, fusion_label="f", var_prefix='fx', inject_variab n_vars = self.findcases() self._poly_ring = PolynomialRing(self._FR.field(), n_vars, var_prefix) if inject_variables: - print("creating variables %s%s..%s%s"%(var_prefix, 1, var_prefix, n_vars)) + print("creating variables %s%s..%s%s" % (var_prefix, 1, var_prefix, n_vars)) self._poly_ring.inject_variables(get_main_globals()) self._idx_to_sextuple, self._fvars = self.findcases(output=True) @@ -309,7 +309,7 @@ def _repr_(self): sage: FusionRing("B2", 1).get_fmatrix() F-Matrix factory for The Fusion Ring of Type B2 and level 1 with Integer Ring coefficients """ - return "F-Matrix factory for %s"%self._FR + return "F-Matrix factory for %s" % self._FR def clear_equations(self): r""" @@ -1229,11 +1229,6 @@ def start_worker_pool(self, processes=None): :meth:`shutdown_worker_pool` to close the pool and properly dispose of shared memory resources. - .. NOTE:: - - Python 3.8+ is required, since the ``multiprocessing.shared_memory`` - module must be imported. - INPUT: - ``processes`` -- an integer indicating the number of workers @@ -1605,7 +1600,7 @@ def _triangular_elim(self, eqns=None, verbose=True): n = self.pool._processes chunks = [[] for i in range(n)] for i, eq_tup in enumerate(eqns): - chunks[i%n].append(eq_tup) + chunks[i % n].append(eq_tup) eqns = chunks else: eqns = [eqns] @@ -1685,7 +1680,7 @@ def equations_graph(self, eqns=None): s = [v for v in eq.variables()] for x in s: for y in s: - if y!=x: + if y != x: G.add_edge(x, y) return G diff --git a/src/sage/algebras/fusion_rings/fusion_double.py b/src/sage/algebras/fusion_rings/fusion_double.py index 07c0f55bc97..520ea96ef13 100644 --- a/src/sage/algebras/fusion_rings/fusion_double.py +++ b/src/sage/algebras/fusion_rings/fusion_double.py @@ -198,7 +198,7 @@ def _repr_(self): The Fusion Ring of the Drinfeld Double of Symmetric group of order 3! as a permutation group """ - return "The Fusion Ring of the Drinfeld Double of %s"%self._G + return "The Fusion Ring of the Drinfeld Double of %s" % self._G def inject_variables(self): """ diff --git a/src/sage/algebras/fusion_rings/fusion_ring.py b/src/sage/algebras/fusion_rings/fusion_ring.py index 0e450281c1f..02da0032802 100644 --- a/src/sage/algebras/fusion_rings/fusion_ring.py +++ b/src/sage/algebras/fusion_rings/fusion_ring.py @@ -53,7 +53,7 @@ class FusionRing(WeylCharacterRing): The cyclotomic order is an integer `N` such that all computations will return elements of the cyclotomic field of `N`-th roots of unity. Normally you will never need to change this but consider changing it - if :meth:`root_of_unity` raises a ``ValueError``. + if :meth:`root_of_unity` raises a :class:`ValueError`. This algebra has a basis (sometimes called *primary fields* but here called *simple objects*) indexed by the weights of level `\leq k`. @@ -1180,7 +1180,7 @@ def _get_trees(fr, top_row, root): comp_basis = list() for top in product((a*a).monomials(), repeat=n_strands//2): # If the n_strands is odd, we must extend the top row by a fusing anyon - top_row = list(top)+[a]*(n_strands%2) + top_row = list(top)+[a]*(n_strands % 2) comp_basis.extend(tuple([*top, *levels]) for levels in _get_trees(self, top_row, b)) return comp_basis @@ -1289,7 +1289,7 @@ def get_braid_generators(self, we don't run the solver again. - ``use_mp`` -- (default: ``True``) a boolean indicating whether to use multiprocessing to speed up the computation; this is - highly recommended. Python 3.8+ is required. + highly recommended. - ``verbose`` -- (default: ``True``) boolean indicating whether to be verbose with the computation diff --git a/src/sage/algebras/fusion_rings/shm_managers.pyx b/src/sage/algebras/fusion_rings/shm_managers.pyx index 84cd66e2be8..bbb364e91dd 100644 --- a/src/sage/algebras/fusion_rings/shm_managers.pyx +++ b/src/sage/algebras/fusion_rings/shm_managers.pyx @@ -55,8 +55,7 @@ cdef class KSHandler: - ``n_slots`` -- the total number of F-symbols - ``field`` -- F-matrix's base cyclotomic field - ``use_mp`` -- a boolean indicating whether to construct a shared - memory block to back ``self``. Requires Python 3.8+, since we - must import the ``multiprocessing.shared_memory`` module. + memory block to back ``self``. - ``init_data`` -- a dictionary or :class:`KSHandler` object containing known squares for initialization, e.g., from a solver checkpoint - ``name`` -- the name of a shared memory object (used by child processes @@ -391,9 +390,6 @@ cdef class FvarsHandler: ``name`` attribute. Children processes use the ``name`` attribute, accessed via ``self.shm.name`` to attach to the shared memory block. - Multiprocessing requires Python 3.8+, since we must import the - ``multiprocessing.shared_memory`` module. - INPUT: - ``n_slots`` -- number of generators of the underlying polynomial ring @@ -422,7 +418,7 @@ cdef class FvarsHandler: .. NOTE:: - If you ever encounter an ``OverflowError`` when running the + If you ever encounter an :class:`OverflowError` when running the :meth:`FMatrix.find_orthogonal_solution` solver, consider increasing the parameter ``n_bytes``. diff --git a/src/sage/algebras/group_algebra.py b/src/sage/algebras/group_algebra.py index c639106b239..e16b0c08a21 100644 --- a/src/sage/algebras/group_algebra.py +++ b/src/sage/algebras/group_algebra.py @@ -223,5 +223,6 @@ def _coerce_map_from_(self, S): return SetMorphism(S.Hom(self, category=self.category() | S.category()), lambda x: self.sum_of_terms( (hom_G(g), hom_K(c)) for g,c in x )) + from sage.misc.persist import register_unpickle_override register_unpickle_override('sage.algebras.group_algebras', 'GroupAlgebra', GroupAlgebra_class) diff --git a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py index 5f21e1049b0..cf1c7a04c39 100644 --- a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py +++ b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py @@ -366,7 +366,7 @@ def _latex_(self): sage: latex(H) \mathcal{H}_{5,2}(q) """ - return "\\mathcal{H}_{%s,%s}(%s)"%(self._r, self._n, self._q) + return "\\mathcal{H}_{%s,%s}(%s)" % (self._r, self._n, self._q) def hecke_parameter(self): r""" @@ -479,7 +479,7 @@ def _repr_(self): Ariki-Koike algebra of rank 5 and order 2 with q=q and u=(u0, u1, u2, u3, u4) ... in the LT-basis """ - return "%s in the %s-basis"%(self.realization_of(), self._realization_name()) + return "%s in the %s-basis" % (self.realization_of(), self._realization_name()) def hecke_parameter(self): r""" @@ -602,8 +602,8 @@ def _repr_term(self, m): sage: LT._repr_term( ((1, 0, 2), Permutation([3,2,1])) ) 'L1*L3^2*T[2,1,2]' """ - gen_str = lambda e: '' if e == 1 else '^%s'%e - lhs = '*'.join('L%s'%(j+1) + gen_str(i) + gen_str = lambda e: '' if e == 1 else '^%s' % e + lhs = '*'.join('L%s' % (j+1) + gen_str(i) for j,i in enumerate(m[0]) if i > 0) redword = m[1].reduced_word() if not redword: @@ -625,15 +625,15 @@ def _latex_term(self, m): sage: LT._latex_term( ((1, 0, 2), Permutation([3,2,1])) ) 'L_{1} L_{3}^{2} T_{2} T_{1} T_{2}' """ - gen_str = lambda e: '' if e == 1 else '^{%s}'%e - lhs = ' '.join('L_{%s}'%(j+1) + gen_str(i) + gen_str = lambda e: '' if e == 1 else '^{%s}' % e + lhs = ' '.join('L_{%s}' % (j+1) + gen_str(i) for j,i in enumerate(m[0]) if i > 0) redword = m[1].reduced_word() if not redword: if not lhs: return '1' return lhs - return lhs + ' ' + ' '.join("T_{%d}"%i for i in redword) + return lhs + ' ' + ' '.join("T_{%d}" % i for i in redword) def _from_T_basis(self, t): r""" @@ -698,10 +698,10 @@ def algebra_generators(self): for i in range(self._n): r = list(self._zero_tuple) # Make a copy r[i] = 1 - d['L%s'%(i+1)] = self.monomial( (tuple(r), self._one_perm) ) + d['L%s' % (i+1)] = self.monomial( (tuple(r), self._one_perm) ) G = self._Pn.group_generators() for i in range(1, self._n): - d['T%s'%i] = self.monomial( (self._zero_tuple, G[i]) ) + d['T%s' % i] = self.monomial( (self._zero_tuple, G[i]) ) return Family(sorted(d), lambda i: d[i]) def T(self, i=None): @@ -725,10 +725,10 @@ def T(self, i=None): """ G = self.algebra_generators() if i is None: - return [G['L1']] + [G['T%s'%j] for j in range(1, self._n)] + return [G['L1']] + [G['T%s' % j] for j in range(1, self._n)] if i == 0: return G['L1'] - return G['T%s'%i] + return G['T%s' % i] def L(self, i=None): r""" @@ -759,10 +759,10 @@ def L(self, i=None): if i is None: if self._r == 1: return [self._Li_power(j, 1) for j in range(1, self._n+1)] - return [G['L%s'%j] for j in range(1, self._n+1)] + return [G['L%s' % j] for j in range(1, self._n+1)] if self._r == 1: return self._Li_power(i, 1) - return G['L%s'%i] + return G['L%s' % i] @cached_method def product_on_basis(self, m1, m2): @@ -1179,7 +1179,7 @@ def __init__(self, algebra): sage: TestSuite(T).run() # long time """ _Basis.__init__(self, algebra, prefix='T') - self._assign_names(['T%s'%i for i in range(self._n)]) + self._assign_names(['T%s' % i for i in range(self._n)]) def _repr_term(self, t): r""" @@ -1200,7 +1200,7 @@ def _repr_term(self, t): if len(redword) == 0: return "1" return (self._print_options['prefix'] - + '[%s]'%','.join('%d'%i for i in redword)) + + '[%s]' % ','.join('%d' % i for i in redword)) def _latex_term(self, t): r""" @@ -1220,7 +1220,7 @@ def _latex_term(self, t): redword += t[1].reduced_word() if len(redword) == 0: return "1" - return ''.join("%s_{%d}"%(self._print_options['prefix'], i) + return ''.join("%s_{%d}" % (self._print_options['prefix'], i) for i in redword) def _from_LT_basis(self, m): diff --git a/src/sage/algebras/letterplace/free_algebra_letterplace.pxd b/src/sage/algebras/letterplace/free_algebra_letterplace.pxd index d1d162c3b40..47a7275aba0 100644 --- a/src/sage/algebras/letterplace/free_algebra_letterplace.pxd +++ b/src/sage/algebras/letterplace/free_algebra_letterplace.pxd @@ -20,16 +20,15 @@ cdef class FreeAlgebra_letterplace_libsingular(): cdef ring* _lp_ring cdef MPolynomialRing_libsingular _commutative_ring cdef MPolynomialRing_libsingular _lp_ring_internal - cdef object __ngens + cdef object _ngens cdef class FreeAlgebra_letterplace(Algebra): cdef MPolynomialRing_libsingular _commutative_ring cdef MPolynomialRing_libsingular _current_ring cdef int _degbound - cdef int __ngens + cdef int _ngens cdef int _nb_slackvars cdef object __monoid - cdef public object __custom_name cdef str exponents_to_string(self, E) cdef str exponents_to_latex(self, E) cdef tuple _degrees diff --git a/src/sage/algebras/letterplace/free_algebra_letterplace.pyx b/src/sage/algebras/letterplace/free_algebra_letterplace.pyx index e9c70c9de29..53f0dfdea6d 100644 --- a/src/sage/algebras/letterplace/free_algebra_letterplace.pyx +++ b/src/sage/algebras/letterplace/free_algebra_letterplace.pyx @@ -255,7 +255,7 @@ cdef class FreeAlgebra_letterplace(Algebra): """ if not isinstance(R, MPolynomialRing_libsingular): raise TypeError("a letterplace algebra must be provided by a polynomial ring of type %s" % MPolynomialRing_libsingular) - self.__ngens = R.ngens() + self._ngens = R.ngens() if degrees is None: varnames = R.variable_names() self._nb_slackvars = 0 @@ -269,12 +269,12 @@ cdef class FreeAlgebra_letterplace(Algebra): self._current_ring = make_letterplace_ring(R, 1) self._degbound = 1 if degrees is None: - self._degrees = tuple([int(1)] * self.__ngens) + self._degrees = tuple([int(1)] * self._ngens) else: if (not isinstance(degrees, (tuple, list))) \ - or len(degrees) != self.__ngens - self._nb_slackvars \ + or len(degrees) != self._ngens - self._nb_slackvars \ or any(i <= 0 for i in degrees): - raise TypeError("the generator degrees must be given by a list or tuple of %d positive integers" % (self.__ngens - 1)) + raise TypeError("the generator degrees must be given by a list or tuple of %d positive integers" % (self._ngens - 1)) self._degrees = tuple([int(i) for i in degrees]) self.set_degbound(max(self._degrees)) self._populate_coercion_lists_(coerce_list=[base_ring]) @@ -305,7 +305,7 @@ cdef class FreeAlgebra_letterplace(Algebra): sage: F.ngens() 3 """ - return self.__ngens - self._nb_slackvars + return self._ngens - self._nb_slackvars def gen(self, i): """ @@ -327,17 +327,17 @@ cdef class FreeAlgebra_letterplace(Algebra): sage: F.gen(2) c """ - if i >= self.__ngens - self._nb_slackvars: - raise ValueError("this free algebra only has %d generators" % (self.__ngens - self._nb_slackvars)) + if i >= self._ngens - self._nb_slackvars: + raise ValueError("this free algebra only has %d generators" % (self._ngens - self._nb_slackvars)) if self._gens is not None: return self._gens[i] deg = self._degrees[i] # self.set_degbound(deg) p = self._current_ring.gen(i) cdef int n - cdef int j = self.__ngens - 1 + cdef int j = self._ngens - 1 for n in range(1, deg): - j += self.__ngens + j += self._ngens p *= self._current_ring.gen(j) return FreeAlgebraElement_letterplace(self, p) @@ -413,7 +413,7 @@ cdef class FreeAlgebra_letterplace(Algebra): sage: FreeAlgebra(QQ, implementation='letterplace', names=['x']).is_commutative() True """ - return self.__ngens - self._nb_slackvars <= 1 + return self._ngens - self._nb_slackvars <= 1 def is_field(self, proof=True): """ @@ -430,7 +430,7 @@ cdef class FreeAlgebra_letterplace(Algebra): sage: F.is_field() False """ - return (not (self.__ngens - self._nb_slackvars)) and self._base.is_field(proof=proof) + return (not (self._ngens - self._nb_slackvars)) and self._base.is_field(proof=proof) def _repr_(self): """ @@ -446,7 +446,7 @@ cdef class FreeAlgebra_letterplace(Algebra): sage: F Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field """ - return "Free Associative Unital Algebra on %d generators %s over %s" % (self.__ngens - self._nb_slackvars, self.gens(), self._base) + return "Free Associative Unital Algebra on %d generators %s over %s" % (self._ngens - self._nb_slackvars, self.gens(), self._base) def _latex_(self): r""" @@ -586,7 +586,7 @@ cdef class FreeAlgebra_letterplace(Algebra): generated free abelian monoid. In principle, this is correct, but it is not implemented, yet.> """ - cdef int ngens = self.__ngens + cdef int ngens = self._ngens cdef int nblocks = len(E) // ngens cdef int i, j, base, exp, var_ind cdef list out = [] @@ -618,7 +618,7 @@ cdef class FreeAlgebra_letterplace(Algebra): sage: latex(-(a*b*(z+1)-c)^2) # indirect doctest \left(2 z + 1\right) a b a b + \left(z + 1\right) a b c + \left(z + 1\right) c a b - c c """ - cdef int ngens = self.__ngens + cdef int ngens = self._ngens cdef int nblocks = len(E) // ngens cdef int i, j, base, exp, var_ind cdef list out = [] @@ -678,7 +678,7 @@ cdef class FreeAlgebra_letterplace(Algebra): cdef list out = [] C = self.current_ring() cdef FreeAlgebraElement_letterplace x - ngens = self.__ngens + ngens = self._ngens cdef list G = [C(x._poly) for x in g] from sage.groups.perm_gps.permgroup_named import CyclicPermutationGroup CG = CyclicPermutationGroup(C.ngens()) @@ -811,7 +811,7 @@ cdef class FreeAlgebra_letterplace(Algebra): l = len(e) break cdef dict out = {} - self.set_degbound(l // self.__ngens) + self.set_degbound(l // self._ngens) cdef Py_ssize_t n = self._current_ring.ngens() for e, c in D.iteritems(): out[tuple(e) + (0,) * (n - l)] = c @@ -896,7 +896,7 @@ cdef class FreeAlgebra_letterplace_libsingular(): self._commutative_ring = commutative_ring def __init__(self, commutative_ring, degbound): - self.__ngens = commutative_ring.ngens() * degbound + self._ngens = commutative_ring.ngens() * degbound def __dealloc__(self): r""" diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index 26e0153a309..a2bb531abe0 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -345,7 +345,7 @@ def set_row(mat, row, val): def build_assoc(row): ret = {} for i, v in row.dict().items(): - ret[i//m, i%m] = v + ret[i//m, i % m] = v return self._assoc(ret) while added: @@ -1124,7 +1124,7 @@ def __init__(self, R, cartan_type): dim = self._classical.dimension() from sage.sets.finite_enumerated_set import FiniteEnumeratedSet index_set = FiniteEnumeratedSet(range(dim)) - names = tuple(['CR%s'%s for s in range(dim)]) + names = tuple(['CR%s' % s for s in range(dim)]) category = LieAlgebras(R).FiniteDimensional().WithBasis() FinitelyGeneratedLieAlgebra.__init__(self, R, names=names, index_set=index_set, diff --git a/src/sage/algebras/lie_algebras/examples.py b/src/sage/algebras/lie_algebras/examples.py index 89ad4362e5e..2c6c23297f9 100644 --- a/src/sage/algebras/lie_algebras/examples.py +++ b/src/sage/algebras/lie_algebras/examples.py @@ -309,6 +309,7 @@ def regular_vector_fields(R): from sage.algebras.lie_algebras.virasoro import LieAlgebraRegularVectorFields return LieAlgebraRegularVectorFields(R) + witt = regular_vector_fields def pwitt(R, p): diff --git a/src/sage/algebras/lie_algebras/free_lie_algebra.py b/src/sage/algebras/lie_algebras/free_lie_algebra.py index 207f8d63a8c..60d49a174b6 100644 --- a/src/sage/algebras/lie_algebras/free_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/free_lie_algebra.py @@ -713,7 +713,7 @@ def _rewrite_bracket(self, l, r): sage: Lyn([x, [y, [z, x]]]) # indirect doctest [x, [[x, z], y]] """ - assert l < r, "Order mismatch %s > %s"%(l, r) + assert l < r, "Order mismatch %s > %s" % (l, r) if self._is_basis_element(l, r): # Compute the grade of the new element diff --git a/src/sage/algebras/lie_algebras/heisenberg.py b/src/sage/algebras/lie_algebras/heisenberg.py index 629fb0a8306..d2f336f642c 100644 --- a/src/sage/algebras/lie_algebras/heisenberg.py +++ b/src/sage/algebras/lie_algebras/heisenberg.py @@ -58,7 +58,7 @@ def p(self, i): sage: L.p(2) p2 """ - return self.element_class(self, {'p%i'%i: self.base_ring().one()}) + return self.element_class(self, {'p%i' % i: self.base_ring().one()}) def q(self, i): """ @@ -70,7 +70,7 @@ def q(self, i): sage: L.q(2) q2 """ - return self.element_class(self, {'q%i'%i: self.base_ring().one()}) + return self.element_class(self, {'q%i' % i: self.base_ring().one()}) def z(self): """ @@ -122,6 +122,23 @@ def _repr_term(self, m): """ return m + def _ascii_art_term(self, m): + r""" + Return a string representation of the term indexed by ``m``. + + EXAMPLES:: + + sage: H = lie_algebras.Heisenberg(QQ, 3) + sage: H._ascii_art_term('p1') + p1 + sage: H._ascii_art_term('z') + z + sage: ascii_art(sum(i * b for i, b in enumerate(H.basis()))) + p2 + 2*p3 + 3*q1 + 4*q2 + 5*q3 + 6*z + """ + from sage.typeset.ascii_art import ascii_art + return ascii_art(m) + def _latex_term(self, m): r""" Return a string representation of the term indexed by ``m``. @@ -138,7 +155,7 @@ def _latex_term(self, m): """ if len(m) == 1: return m - return "%s_{%s}"%(m[0], m[1:]) # else it is of length at least 2 + return "%s_{%s}" % (m[0], m[1:]) # else it is of length at least 2 def _unicode_art_term(self, m): r""" @@ -261,12 +278,12 @@ def lie_algebra_generators(self): """ if self._n == 0: return Family(['z'], lambda i: self.z()) - k = ['p%s'%i for i in range(1, self._n+1)] - k += ['q%s'%i for i in range(1, self._n+1)] + k = ['p%s' % i for i in range(1, self._n+1)] + k += ['q%s' % i for i in range(1, self._n+1)] d = {} for i in range(1, self._n+1): - d['p%s'%i] = self.p(i) - d['q%s'%i] = self.q(i) + d['p%s' % i] = self.p(i) + d['q%s' % i] = self.q(i) return Family(k, lambda i: d[i]) @cached_method @@ -282,8 +299,8 @@ def basis(self): """ d = {} for i in range(1, self._n+1): - d['p%s'%i] = self.p(i) - d['q%s'%i] = self.q(i) + d['p%s' % i] = self.p(i) + d['q%s' % i] = self.q(i) d['z'] = self.z() return Family(self._indices, lambda i: d[i]) @@ -385,8 +402,8 @@ def __init__(self, R, n): sage: TestSuite(L).run() """ HeisenbergAlgebra_fd.__init__(self, n) - names = tuple(['p%s'%i for i in range(1,n+1)] - + ['q%s'%i for i in range(1,n+1)] + names = tuple(['p%s' % i for i in range(1,n+1)] + + ['q%s' % i for i in range(1,n+1)] + ['z']) LieAlgebraWithGenerators.__init__(self, R, names=names, index_set=names, category=LieAlgebras(R).Nilpotent().FiniteDimensional().WithBasis()) @@ -687,8 +704,8 @@ def __init__(self, R, n): p = tuple(MS({(0,i): one}) for i in range(1, n+1)) q = tuple(MS({(i,n+1): one}) for i in range(1, n+1)) z = (MS({(0,n+1): one}),) - names = tuple('p%s'%i for i in range(1,n+1)) - names = names + tuple('q%s'%i for i in range(1,n+1)) + ('z',) + names = tuple('p%s' % i for i in range(1,n+1)) + names = names + tuple('q%s' % i for i in range(1,n+1)) + ('z',) cat = LieAlgebras(R).Nilpotent().FiniteDimensional().WithBasis() LieAlgebraFromAssociative.__init__(self, MS, p + q + z, names=names, index_set=names, category=cat) @@ -716,7 +733,7 @@ def p(self, i): [0 0 0] [0 0 0] """ - return self._gens['p%s'%i] + return self._gens['p%s' % i] def q(self, i): r""" @@ -730,7 +747,7 @@ def q(self, i): [0 0 1] [0 0 0] """ - return self._gens['q%s'%i] + return self._gens['q%s' % i] def z(self): """ diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 5a9d5956557..2db27f5f60d 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -590,7 +590,7 @@ def _Hom_(self, Y, category=None, **options): The sole purpose of this method is to construct the homset as a :class:`~sage.algebras.lie_algebras.verma_module.VermaModuleHomset`. If ``category`` is specified and is not a subcategory of - ``self.category()``, a ``TypeError`` is raised instead. + ``self.category()``, a :class:`TypeError` is raised instead. This method is not meant to be called directly. Please use :func:`sage.categories.homset.Hom` instead. diff --git a/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py index 31b542cd373..8cc6533b781 100644 --- a/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py @@ -111,7 +111,7 @@ def __init__(self, R, ngens=None, gram_matrix=None, names=None, latex_names = None if (names is None) and (index_set is None): - if ngens==1: + if ngens == 1: names = 'psi' else: names = 'psi_' diff --git a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py index 5c14016eab2..1007488e165 100644 --- a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py @@ -328,10 +328,10 @@ def __classcall_private__(cls, R=None, arg0=None, index_set=None, 'string_quotes', 'sorting_key', 'graded', 'super'] for key in kwds: if key not in known_keywords: - raise ValueError("got an unexpected keyword argument '%s'"%key) + raise ValueError("got an unexpected keyword argument '%s'" % key) if isinstance(arg0,dict) and arg0: - graded=kwds.pop("graded", False) + graded = kwds.pop("graded", False) if weights is not None or graded: from .graded_lie_conformal_algebra import \ GradedLieConformalAlgebra diff --git a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py index a4669506314..7581daf0ddb 100644 --- a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +++ b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py @@ -152,15 +152,15 @@ def _standardize_s_coeff(s_coeff, index_set, ce, parity=None): #e.g. v = { 0: { (L,2):3, (G,3):1}, 1:{(L,1),2} } v = s_coeff[mypair] key = tuple(mypair) - vals={} + vals = {} for l in v.keys(): lth_product = {k:y for k,y in v[l].items() if y} if lth_product: - vals[l]=lth_product + vals[l] = lth_product myvals = tuple((k, tuple(v.items())) for k, v in vals.items() if v) - if key in sc.keys() and sorted(sc[key]) != sorted(myvals): + if key in sc and sorted(sc[key]) != sorted(myvals): raise ValueError("two distinct values given for one " "and the same bracket, skew-symmetry" "is not satisfied?") @@ -175,25 +175,25 @@ def _standardize_s_coeff(s_coeff, index_set, ce, parity=None): else: parsgn = 1 maxpole = max(v.keys()) - vals={} + vals = {} for k in range(maxpole+1): kth_product = {} for j in range(maxpole+1-k): if k+j in v.keys(): for i in v[k+j]: if (i[0] not in ce) or ( - i[0] in ce and i[1] + j == 0): - kth_product[(i[0],i[1]+j)] = \ - kth_product.get((i[0], i[1]+j), 0) - kth_product[(i[0],i[1]+j)] += parsgn*\ - v[k+j][i]*(-1)**(k+j+1)*binomial(i[1]+j,j) - kth_product = {k:v for k,v in kth_product.items() if v} + i[0] in ce and i[1] + j == 0): + kth_product[(i[0], i[1] + j)] = \ + kth_product.get((i[0], i[1] + j), 0) + kth_product[(i[0], i[1] + j)] += parsgn *\ + v[k+j][i]*(-1)**(k+j+1)*binomial(i[1]+j,j) + kth_product = {k: v for k, v in kth_product.items() if v} if kth_product: - vals[k]=kth_product + vals[k] = kth_product myvals = tuple((k, tuple(v.items())) for k, v in vals.items() if v) - if key in sc.keys() and sorted(sc[key]) != sorted(myvals): + if key in sc and sorted(sc[key]) != sorted(myvals): raise ValueError("two distinct values given for one " "and the same bracket. " "Skew-symmetry is not satisfied?") @@ -214,7 +214,7 @@ def __init__(self, R, s_coeff, index_set=None, central_elements=None, """ names, index_set = standardize_names_index_set(names,index_set) if central_elements is None: - central_elements= tuple() + central_elements = tuple() if names is not None and names != tuple(index_set): names2 = names + tuple(central_elements) @@ -266,14 +266,14 @@ def __init__(self, R, s_coeff, index_set=None, central_elements=None, category = default_category.or_subcategory(category) if element_class is None: - element_class=LCAStructureCoefficientsElement + element_class = LCAStructureCoefficientsElement FinitelyFreelyGeneratedLCA.__init__( self, R, index_set=index_set, central_elements=central_elements, category=category, element_class=element_class, prefix=prefix, names=names, latex_names=latex_names, **kwds) - s_coeff=dict(s_coeff) + s_coeff = dict(s_coeff) self._s_coeff = Family({k: tuple((j, sum(c*self.monomial(i) for i,c in v )) for j,v in s_coeff[k]) for k in s_coeff}) self._parity = dict(zip(self.gens(),parity+(0,)*len(central_elements))) diff --git a/src/sage/algebras/nil_coxeter_algebra.py b/src/sage/algebras/nil_coxeter_algebra.py index 5d255b9786d..862fdc3b97e 100644 --- a/src/sage/algebras/nil_coxeter_algebra.py +++ b/src/sage/algebras/nil_coxeter_algebra.py @@ -110,16 +110,18 @@ def homogeneous_generator_noncommutative_variables(self, r): 0 sage: U.homogeneous_generator_noncommutative_variables(0) 1 - """ - assert (len(self._cartan_type) == 2 and self._cartan_type[0] in ['A','B']) or (len(self._cartan_type) == 3 and self._cartan_type[2] == 1), "Analogue of symmetric functions in noncommutative variables is not defined in type %s"%(self._cartan_type) + ct = self._cartan_type + msg = f"Analogue of symmetric functions in noncommutative variables is not defined in type {ct}" + assert (len(ct) == 2 and ct[0] in ['A', 'B']) or (len(ct) == 3 and ct[2] == 1), msg if r >= self._n: return self.zero() return self.sum_of_monomials(w for w in self._W.pieri_factors() if w.length() == r) - def homogeneous_noncommutative_variables(self,la): + def homogeneous_noncommutative_variables(self, la): r""" Give the homogeneous function indexed by `la`, viewed inside the Nil-Coxeter algebra. + This is only defined in finite type `A`, `B` and affine types `A^{(1)}`, `B^{(1)}`, `C^{(1)}`, `D^{(1)}`. INPUT: @@ -182,9 +184,9 @@ def k_schur_noncommutative_variables(self, la): """ - assert self._cartan_type[0] == 'A' and len(self._cartan_type) == 3 and self._cartan_type[2] == 1, "%s is not affine type A."%(self._W) - assert la in Partitions(), "%s is not a partition."%(la) - assert (len(la) == 0 or la[0] < self._W.n), "%s is not a %s-bounded partition."%(la, self._W.n-1) + assert self._cartan_type[0] == 'A' and len(self._cartan_type) == 3 and self._cartan_type[2] == 1, "%s is not affine type A." % (self._W) + assert la in Partitions(), "%s is not a partition." % (la) + assert (len(la) == 0 or la[0] < self._W.n), "%s is not a %s-bounded partition." % (la, self._W.n-1) Sym = SymmetricFunctions(self._base_ring) h = Sym.homogeneous() ks = Sym.kschur(self._n-1,1) diff --git a/src/sage/algebras/orlik_solomon.py b/src/sage/algebras/orlik_solomon.py index 52dae24fee3..920056787c6 100644 --- a/src/sage/algebras/orlik_solomon.py +++ b/src/sage/algebras/orlik_solomon.py @@ -502,7 +502,7 @@ def as_gca(self): for j in indices: if j != i: mon *= A.gen(j) - rel += sign *mon + rel += sign * mon sign = -sign rels.append(rel) I = A.ideal(rels) diff --git a/src/sage/algebras/quantum_clifford.py b/src/sage/algebras/quantum_clifford.py index 5079283e8ec..2b85615cf20 100644 --- a/src/sage/algebras/quantum_clifford.py +++ b/src/sage/algebras/quantum_clifford.py @@ -288,14 +288,14 @@ def algebra_generators(self): for i in range(self._n): r = list(zero) # Make a copy r[i] = 1 - d['psi%s'%i] = self.monomial( (self._psi(r), one) ) + d['psi%s' % i] = self.monomial((self._psi(r), one)) r[i] = -1 - d['psid%s'%i] = self.monomial( (self._psi(r), one) ) + d['psid%s' % i] = self.monomial((self._psi(r), one)) zero = self._psi(zero) for i in range(self._n): temp = list(zero) # Make a copy temp[i] = 1 - d['w%s'%i] = self.monomial( (zero, tuple(temp)) ) + d['w%s' % i] = self.monomial((zero, tuple(temp))) return Family(sorted(d), lambda i: d[i]) @cached_method @@ -397,10 +397,10 @@ def _repr_term(self, m): 5 """ p, v = m - rp = '*'.join('psi%s'%i if p[i] > 0 else 'psid%s'%i + rp = '*'.join('psi%s' % i if p[i] > 0 else 'psid%s' % i for i in range(self._n) if p[i] != 0) - gen_str = lambda e: '' if e == 1 else '^%s'%e - rv = '*'.join('w%s'%i + gen_str(v[i]) for i in range(self._n) if v[i] != 0) + gen_str = lambda e: '' if e == 1 else '^%s' % e + rv = '*'.join('w%s' % i + gen_str(v[i]) for i in range(self._n) if v[i] != 0) if rp: if rv: return rp + '*' + rv @@ -429,10 +429,10 @@ def _latex_term(self, m): 5 """ p, v = m - rp = ''.join('\\psi_{%s}'%i if p[i] > 0 else '\\psi^{\\dagger}_{%s}'%i + rp = ''.join('\\psi_{%s}' % i if p[i] > 0 else '\\psi^{\\dagger}_{%s}' % i for i in range(self._n) if p[i] != 0) - gen_str = lambda e: '' if e == 1 else '^{%s}'%e - rv = ''.join('\\omega_{%s}'%i + gen_str(v[i]) + gen_str = lambda e: '' if e == 1 else '^{%s}' % e + rv = ''.join('\\omega_{%s}' % i + gen_str(v[i]) for i in range(self._n) if v[i] != 0) if not rp and not rv: return '1' @@ -700,15 +700,15 @@ def _repr_term(self, m): def ppr(i): val = p[i] if val == -1: - return 'psid%s'%i + return 'psid%s' % i elif val == 1: - return 'psi%s'%i + return 'psi%s' % i elif val == 2: - return 'psi%s*psid%s'%(i,i) + return 'psi%s*psid%s' % (i,i) rp = '*'.join(ppr(i) for i in range(self._n) if p[i] != 0) - gen_str = lambda e: '' if e == 1 else '^%s'%e - rv = '*'.join('w%s'%i + gen_str(v[i]) for i in range(self._n) if v[i] != 0) + gen_str = lambda e: '' if e == 1 else '^%s' % e + rv = '*'.join('w%s' % i + gen_str(v[i]) for i in range(self._n) if v[i] != 0) if rp: if rv: return rp + '*' + rv @@ -741,15 +741,15 @@ def _latex_term(self, m): def ppr(i): val = p[i] if val == -1: - return '\\psi^{\\dagger}_{%s}'%i + return '\\psi^{\\dagger}_{%s}' % i elif val == 1: - return '\\psi_{%s}'%i + return '\\psi_{%s}' % i elif val == 2: return '\\psi_{%s}\\psi^{\\dagger}_{%s}' % (i, i) rp = ''.join(ppr(i) for i in range(self._n) if p[i] != 0) - gen_str = lambda e: '' if e == 1 else '^{%s}'%e - rv = ''.join('\\omega_{%s}'%i + gen_str(v[i]) + gen_str = lambda e: '' if e == 1 else '^{%s}' % e + rv = ''.join('\\omega_{%s}' % i + gen_str(v[i]) for i in range(self._n) if v[i] != 0) if not rp and not rv: return '1' @@ -875,7 +875,7 @@ def key(X): return (self._psi(p), tuple(e)) q = self._q - ret = {key(X): (-1)**len(X) * sign * q**(q_power+k*(len(pairings)%2)) + ret = {key(X): (-1)**len(X) * sign * q**(q_power+k*(len(pairings) % 2)) for X in powerset(pairings)} return self._from_dict(ret) diff --git a/src/sage/algebras/quantum_groups/quantum_group_gap.py b/src/sage/algebras/quantum_groups/quantum_group_gap.py index 5e991dd80bc..8925c047916 100644 --- a/src/sage/algebras/quantum_groups/quantum_group_gap.py +++ b/src/sage/algebras/quantum_groups/quantum_group_gap.py @@ -1579,7 +1579,7 @@ def _latex_(self): sage: T = tensor([V,V]) sage: S = T.highest_weight_decomposition()[0] sage: latex(S) - \begin{tikzpicture} + \begin{tikzpicture}... ... \end{tikzpicture} """ diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 04f8f2a0d84..1b6001209a0 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -1793,6 +1793,42 @@ def unit_ideal(self): else: raise NotImplementedError("ideal only implemented for quaternion algebras over QQ") + def basis_matrix(self): + r""" + Return the basis matrix of this quaternion order, for the + specific basis returned by :meth:`basis()`. + + OUTPUT: matrix over `\QQ` + + EXAMPLES:: + + sage: O = QuaternionAlgebra(-11,-1).maximal_order() + sage: O.basis() + (1/2 + 1/2*i, 1/2*j - 1/2*k, i, -k) + sage: O.basis_matrix() + [ 1/2 1/2 0 0] + [ 0 0 1/2 -1/2] + [ 0 1 0 0] + [ 0 0 0 -1] + + Note that the returned matrix is *not* necessarily the same as + the basis matrix of the :meth:`unit_ideal()`:: + + sage: Q. = QuaternionAlgebra(-1,-11) + sage: O = Q.quaternion_order([j,i,-1,k]) + sage: O.basis_matrix() + [ 0 0 1 0] + [ 0 1 0 0] + [-1 0 0 0] + [ 0 0 0 1] + sage: O.unit_ideal().basis_matrix() + [1 0 0 0] + [0 1 0 0] + [0 0 1 0] + [0 0 0 1] + """ + return matrix(QQ, map(list, self.__basis)) + def __mul__(self, other): """ Every order equals its own unit ideal. Overload ideal multiplication @@ -2792,8 +2828,8 @@ def cyclic_right_subideals(self, p, alpha=None): .. NOTE:: Currently, `p` must satisfy a bunch of conditions, or a - ``NotImplementedError`` is raised. In particular, `p` must be - odd and unramified in the quaternion algebra, must be + :class:`NotImplementedError` is raised. In particular, `p` must + be odd and unramified in the quaternion algebra, must be coprime to the index of the right order in the maximal order, and also coprime to the normal of self. (The Brandt modules code has a more general algorithm in some cases.) diff --git a/src/sage/algebras/quatalg/quaternion_algebra_element.pyx b/src/sage/algebras/quatalg/quaternion_algebra_element.pyx index f6e87440fe9..723c284989e 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra_element.pyx +++ b/src/sage/algebras/quatalg/quaternion_algebra_element.pyx @@ -34,7 +34,6 @@ Check that :trac:`20829` is fixed:: from sage.structure.element cimport AlgebraElement, Element from sage.structure.richcmp cimport rich_to_bool, rich_to_bool_sgn, richcmp_item -from sage.algebras.quatalg.quaternion_algebra_element cimport QuaternionAlgebraElement_abstract from sage.rings.rational cimport Rational from sage.rings.integer cimport Integer from sage.rings.number_field.number_field_element cimport NumberFieldElement @@ -1700,15 +1699,15 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra x, y, z, w = v cdef NumberFieldElement a = (parent._base(parent._a)) cdef NumberFieldElement b = (parent._base(parent._b)) - fmpz_poly_set_ZZX(self.x, (x).__numerator) - fmpz_poly_set_ZZX(self.y, (y).__numerator) - fmpz_poly_set_ZZX(self.z, (z).__numerator) - fmpz_poly_set_ZZX(self.w, (w).__numerator) + fmpz_poly_set_ZZX(self.x, (x)._numerator) + fmpz_poly_set_ZZX(self.y, (y)._numerator) + fmpz_poly_set_ZZX(self.z, (z)._numerator) + fmpz_poly_set_ZZX(self.w, (w)._numerator) - ZZ_to_mpz(T1, &(x).__denominator) - ZZ_to_mpz(T2, &(y).__denominator) - ZZ_to_mpz(t3, &(z).__denominator) - ZZ_to_mpz(t4, &(w).__denominator) + ZZ_to_mpz(T1, &(x)._denominator) + ZZ_to_mpz(T2, &(y)._denominator) + ZZ_to_mpz(t3, &(z)._denominator) + ZZ_to_mpz(t4, &(w)._denominator) mpz_lcm(self.d, T1, T2) mpz_lcm(self.d, self.d, t3) @@ -1724,10 +1723,10 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra fmpz_poly_scalar_mul_mpz(self.z, self.z, t3) fmpz_poly_scalar_mul_mpz(self.w, self.w, t4) - fmpz_poly_set_ZZX(self.a, a.__numerator) # we will assume that the denominator of a and b are 1 - fmpz_poly_set_ZZX(self.b, b.__numerator) + fmpz_poly_set_ZZX(self.a, a._numerator) # we will assume that the denominator of a and b are 1 + fmpz_poly_set_ZZX(self.b, b._numerator) - fmpz_poly_set_ZZX(self.modulus, (x).__fld_numerator.x) # and same for the modulus + fmpz_poly_set_ZZX(self.modulus, (x)._fld_numerator.x) # and same for the modulus def __getitem__(self, int i): """ @@ -1756,17 +1755,17 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra cdef NumberFieldElement item = el._new() if i == 0: - fmpz_poly_get_ZZX(item.__numerator, self.x) + fmpz_poly_get_ZZX(item._numerator, self.x) elif i == 1: - fmpz_poly_get_ZZX(item.__numerator, self.y) + fmpz_poly_get_ZZX(item._numerator, self.y) elif i == 2: - fmpz_poly_get_ZZX(item.__numerator, self.z) + fmpz_poly_get_ZZX(item._numerator, self.z) elif i == 3: - fmpz_poly_get_ZZX(item.__numerator, self.w) + fmpz_poly_get_ZZX(item._numerator, self.w) else: raise IndexError("quaternion element index out of range") - mpz_to_ZZ(&item.__denominator, self.d) + mpz_to_ZZ(&item._denominator, self.d) return item diff --git a/src/sage/algebras/splitting_algebra.py b/src/sage/algebras/splitting_algebra.py index 08a4992d48a..3b0dfce4586 100644 --- a/src/sage/algebras/splitting_algebra.py +++ b/src/sage/algebras/splitting_algebra.py @@ -332,10 +332,10 @@ def __init__(self, monic_polynomial, names='X', iterate=True, warning=True): try: cf0_inv = ~(cf[0]) cf0_inv = self(cf0_inv) - verbose("invertible coefficient: %s found" %(cf0_inv)) + verbose("invertible coefficient: %s found" % (cf0_inv)) break except NotImplementedError: - verbose("constant coefficient: %s not invertibe" %(cf0)) + verbose("constant coefficient: %s not invertibe" % (cf0)) # ------------------------------------------------------------------ # assuming that cf splits into linear factors over self diff --git a/src/sage/algebras/steenrod/steenrod_algebra_bases.py b/src/sage/algebras/steenrod/steenrod_algebra_bases.py index f028e6d5df5..c289b284fe1 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_bases.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_bases.py @@ -834,12 +834,12 @@ def degree_dictionary(n, basis): """ dict = {} if basis.find('wood') >= 0: - k=0 - m=0 + k = 0 + m = 0 deg = 2**m * (2**(k+1) - 1) while deg <= n: dict[deg] = (m,k) - if m>0: + if m > 0: m = m - 1 k = k + 1 else: @@ -847,8 +847,8 @@ def degree_dictionary(n, basis): k = 0 deg = 2**m * (2**(k+1) - 1) elif basis.find('wall') >= 0 or basis.find('arnon') >= 0: - k=0 - m=0 + k = 0 + m = 0 deg = 2**k * (2**(m-k+1) - 1) while deg <= n: dict[deg] = (m,k) @@ -859,8 +859,8 @@ def degree_dictionary(n, basis): k = k - 1 deg = 2**k * (2**(m-k+1) - 1) elif basis.find('pst') >= 0 or basis.find('comm') >= 0: - s=0 - t=1 + s = 0 + t = 1 deg = 2**s * (2**t - 1) while deg <= n: if basis.find('pst') >= 0: @@ -1128,7 +1128,7 @@ def steenrod_basis_error_check(dim, p, **kwds): for i in range(dim): if i % 5 == 0: - verbose("up to dimension %s"%i) + verbose("up to dimension %s" % i) milnor_dim = len(steenrod_algebra_basis.f(i,'milnor',p=p,generic=generic)) for B in bases: if milnor_dim != len(steenrod_algebra_basis.f(i,B,p,generic=generic)): @@ -1147,7 +1147,7 @@ def steenrod_basis_error_check(dim, p, **kwds): for i in range(dim): if i % 5 == 0: - verbose("up to dimension %s"%i) + verbose("up to dimension %s" % i) for pro in profiles: milnor_dim = len(steenrod_algebra_basis.f(i,'milnor',p=p,profile=pro,generic=generic)) for B in bases: diff --git a/src/sage/algebras/steenrod/steenrod_algebra_misc.py b/src/sage/algebras/steenrod/steenrod_algebra_misc.py index d8fedad70b8..91ab657a84f 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_misc.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_misc.py @@ -177,7 +177,7 @@ def get_basis_name(basis, p, generic=None): if basis.find('long') >= 0: result = result + '_long' else: - gencase = " for the generic Steenrod algebra" if p==2 and generic else "" + gencase = " for the generic Steenrod algebra" if p == 2 and generic else "" raise ValueError("%s is not a recognized basis%s at the prime %s" % (basis, gencase, p)) return result diff --git a/src/sage/algebras/yokonuma_hecke_algebra.py b/src/sage/algebras/yokonuma_hecke_algebra.py index 700395a2d84..df474b8d4f7 100644 --- a/src/sage/algebras/yokonuma_hecke_algebra.py +++ b/src/sage/algebras/yokonuma_hecke_algebra.py @@ -183,7 +183,7 @@ def _latex_(self): sage: latex(Y) \mathcal{Y}_{5,2}(q) """ - return "\\mathcal{Y}_{%s,%s}(%s)"%(self._d, self._n, self._q) + return "\\mathcal{Y}_{%s,%s}(%s)" % (self._d, self._n, self._q) def _repr_term(self, m): """ @@ -195,8 +195,8 @@ def _repr_term(self, m): sage: Y._repr_term( ((1, 0, 2), Permutation([3,2,1])) ) 't1*t3^2*g[2,1,2]' """ - gen_str = lambda e: '' if e == 1 else '^%s'%e - lhs = '*'.join('t%s'%(j+1) + gen_str(i) for j,i in enumerate(m[0]) if i > 0) + gen_str = lambda e: '' if e == 1 else '^%s' % e + lhs = '*'.join('t%s' % (j+1) + gen_str(i) for j,i in enumerate(m[0]) if i > 0) redword = m[1].reduced_word() if not redword: if not lhs: @@ -217,14 +217,14 @@ def _latex_term(self, m): sage: Y._latex_term( ((1, 0, 2), Permutation([3,2,1])) ) 't_{1} t_{3}^2 g_{2} g_{1} g_{2}' """ - gen_str = lambda e: '' if e == 1 else '^%s'%e - lhs = ' '.join('t_{%s}'%(j+1) + gen_str(i) for j,i in enumerate(m[0]) if i > 0) + gen_str = lambda e: '' if e == 1 else '^%s' % e + lhs = ' '.join('t_{%s}' % (j+1) + gen_str(i) for j,i in enumerate(m[0]) if i > 0) redword = m[1].reduced_word() if not redword: if not lhs: return '1' return lhs - return lhs + ' ' + ' '.join("g_{%d}"%i for i in redword) + return lhs + ' ' + ' '.join("g_{%d}" % i for i in redword) @cached_method def algebra_generators(self): @@ -243,10 +243,10 @@ def algebra_generators(self): for i in range(self._n): r = list(zero) # Make a copy r[i] = 1 - d['t%s'%(i+1)] = self.monomial( (tuple(r), one) ) + d['t%s' % (i+1)] = self.monomial( (tuple(r), one) ) G = self._Pn.group_generators() for i in range(1, self._n): - d['g%s'%i] = self.monomial( (tuple(zero), G[i]) ) + d['g%s' % i] = self.monomial( (tuple(zero), G[i]) ) return Family(sorted(d), lambda i: d[i]) @cached_method @@ -323,8 +323,8 @@ def g(self, i=None): """ G = self.algebra_generators() if i is None: - return [G['g%s'%i] for i in range(1, self._n)] - return G['g%s'%i] + return [G['g%s' % i] for i in range(1, self._n)] + return G['g%s' % i] def t(self, i=None): """ @@ -345,8 +345,8 @@ def t(self, i=None): """ G = self.algebra_generators() if i is None: - return [G['t%s'%i] for i in range(1, self._n+1)] - return G['t%s'%i] + return [G['t%s' % i] for i in range(1, self._n+1)] + return G['t%s' % i] def product_on_basis(self, m1, m2): """ @@ -488,7 +488,7 @@ def __invert__(self): if not self: raise ZeroDivisionError if len(self) != 1: - raise NotImplementedError("inverse only implemented for basis elements (monomials in the generators)"%self) + raise NotImplementedError("inverse only implemented for basis elements (monomials in the generators)" % self) H = self.parent() t,w = self.support_of_term() c = ~self.coefficients()[0] diff --git a/src/sage/arith/functions.pyx b/src/sage/arith/functions.pyx index 0f2c07d247a..db49367b7f4 100644 --- a/src/sage/arith/functions.pyx +++ b/src/sage/arith/functions.pyx @@ -72,25 +72,25 @@ def lcm(a, b=None): Make sure we try `\QQ` and not merely `\ZZ` (:trac:`13014`):: - sage: bool(lcm(2/5, 3/7) == lcm(SR(2/5), SR(3/7))) # optional - sage.symbolic + sage: bool(lcm(2/5, 3/7) == lcm(SR(2/5), SR(3/7))) # needs sage.symbolic True Make sure that the lcm of Expressions stays symbolic:: sage: parent(lcm(2, 4)) Integer Ring - sage: parent(lcm(SR(2), 4)) # optional - sage.symbolic + sage: parent(lcm(SR(2), 4)) # needs sage.symbolic Symbolic Ring - sage: parent(lcm(2, SR(4))) # optional - sage.symbolic + sage: parent(lcm(2, SR(4))) # needs sage.symbolic Symbolic Ring - sage: parent(lcm(SR(2), SR(4))) # optional - sage.symbolic + sage: parent(lcm(SR(2), SR(4))) # needs sage.symbolic Symbolic Ring Verify that objects without lcm methods but which can't be coerced to `\ZZ` or `\QQ` raise an error:: - sage: F. = FreeMonoid(2) # optional - sage.groups - sage: lcm(x,y) # optional - sage.groups + sage: F. = FreeMonoid(2) # needs sage.groups + sage: lcm(x,y) # needs sage.groups Traceback (most recent call last): ... TypeError: unable to find lcm of x and y diff --git a/src/sage/arith/long.pxd b/src/sage/arith/long.pxd index eda9d8c1f48..0031a0ae337 100644 --- a/src/sage/arith/long.pxd +++ b/src/sage/arith/long.pxd @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.misc.cython +# sage.doctest: needs sage.misc.cython r""" Fast conversion of Python objects to C long """ @@ -17,8 +17,6 @@ Fast conversion of Python objects to C long from libc.limits cimport LONG_MIN, LONG_MAX from cpython.object cimport Py_SIZE -from cpython.int cimport PyInt_AS_LONG -from cpython.long cimport PyLong_AsLong from cpython.number cimport PyNumber_Index, PyIndex_Check from cpython.longintrepr cimport py_long, PyLong_SHIFT, digit @@ -30,8 +28,9 @@ cdef inline long pyobject_to_long(x) except? LONG_MIN: r""" Given a Python object ``x`` cast it quickly to a C long. - A ``TypeError`` is raised if the input cannot be converted to an integer or - an ``OverflowError`` is raised if it does not fit into a C long. + A :class:`TypeError` is raised if the input cannot be converted to + an integer or + an :class:`OverflowError` is raised if it does not fit into a C long. TESTS: @@ -83,7 +82,7 @@ cdef enum: cdef inline bint integer_check_long(x, long* value, int* err) except -1: """ Return whether ``x`` is some integer type. This is true for the - Python types ``int`` and ``long``, for Sage Integers and for types + Python type ``int``, for Sage Integers and for types implementing ``__index__``. If possible, compute the value of this integer as C long and store @@ -104,7 +103,7 @@ cdef inline bint integer_check_long(x, long* value, int* err) except -1: - ``ERR_TYPE``: ``x`` is not an integer type of any kind. - - ``ERR_INDEX``: ``x`` implements ``__index__`` but a ``TypeError`` + - ``ERR_INDEX``: ``x`` implements ``__index__`` but a :class:`TypeError` was raised calling ``__index__()``. - Other exceptions in ``__index__`` are simply propagated. This is diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 5ba4c1e5e70..33810425307 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -25,10 +25,10 @@ from sage.structure.element import parent from sage.structure.coerce import py_scalar_to_element -from sage.rings.rational_field import QQ -from sage.rings.integer_ring import ZZ from sage.rings.integer import Integer, GCD_list +from sage.rings.integer_ring import ZZ from sage.rings.rational import Rational +from sage.rings.rational_field import QQ from sage.rings.abc import RealField, ComplexField from sage.rings.fast_arith import arith_int, arith_llong, prime_range @@ -58,7 +58,7 @@ def algdep(z, degree, known_bits=None, use_bits=None, known_digits=None, is not found, then ``None`` will be returned. If ``proof=True`` then the result is returned only if it can be proved correct (i.e. the only possible minimal polynomial satisfying the height bound, or no - such polynomial exists). Otherwise a ``ValueError`` is raised + such polynomial exists). Otherwise a :class:`ValueError` is raised indicating that higher precision is required. ALGORITHM: Uses LLL for real/complex inputs, PARI C-library @@ -81,109 +81,111 @@ def algdep(z, degree, known_bits=None, use_bits=None, known_digits=None, EXAMPLES:: - sage: algdep(1.888888888888888, 1) # optional - sage.libs.pari + sage: algdep(1.888888888888888, 1) # needs sage.libs.pari 9*x - 17 - sage: algdep(0.12121212121212, 1) # optional - sage.libs.pari + sage: algdep(0.12121212121212, 1) # needs sage.libs.pari 33*x - 4 - sage: algdep(sqrt(2), 2) # optional - sage.libs.pari sage.symbolic + sage: algdep(sqrt(2), 2) # needs sage.libs.pari sage.symbolic x^2 - 2 This example involves a complex number:: - sage: z = (1/2) * (1 + RDF(sqrt(3)) * CC.0); z # optional - sage.symbolic + sage: z = (1/2) * (1 + RDF(sqrt(3)) * CC.0); z # needs sage.symbolic 0.500000000000000 + 0.866025403784439*I - sage: algdep(z, 6) # optional - sage.symbolic + sage: algdep(z, 6) # needs sage.symbolic x^2 - x + 1 This example involves a `p`-adic number:: - sage: K = Qp(3, print_mode='series') # optional - sage.rings.padics - sage: a = K(7/19); a # optional - sage.rings.padics + sage: K = Qp(3, print_mode='series') # needs sage.rings.padics + sage: a = K(7/19); a # needs sage.rings.padics 1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12 + 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20) - sage: algdep(a, 1) # optional - sage.rings.padics + sage: algdep(a, 1) # needs sage.rings.padics 19*x - 7 These examples show the importance of proper precision control. We compute a 200-bit approximation to `sqrt(2)` which is wrong in the 33'rd bit:: + sage: # needs sage.libs.pari sage.rings.real_mpfr sage: z = sqrt(RealField(200)(2)) + (1/2)^33 - sage: p = algdep(z, 4); p # optional - sage.libs.pari + sage: p = algdep(z, 4); p 227004321085*x^4 - 216947902586*x^3 - 99411220986*x^2 + 82234881648*x - 211871195088 - sage: factor(p) # optional - sage.libs.pari + sage: factor(p) 227004321085*x^4 - 216947902586*x^3 - 99411220986*x^2 + 82234881648*x - 211871195088 - sage: algdep(z, 4, known_bits=32) # optional - sage.libs.pari + sage: algdep(z, 4, known_bits=32) x^2 - 2 - sage: algdep(z, 4, known_digits=10) # optional - sage.libs.pari + sage: algdep(z, 4, known_digits=10) x^2 - 2 - sage: algdep(z, 4, use_bits=25) # optional - sage.libs.pari + sage: algdep(z, 4, use_bits=25) x^2 - 2 - sage: algdep(z, 4, use_digits=8) # optional - sage.libs.pari + sage: algdep(z, 4, use_digits=8) x^2 - 2 Using the ``height_bound`` and ``proof`` parameters, we can see that `pi` is not the root of an integer polynomial of degree at most 5 and coefficients bounded above by 10:: - sage: algdep(pi.n(), 5, height_bound=10, proof=True) is None # optional - sage.libs.pari sage.symbolic + sage: algdep(pi.n(), 5, height_bound=10, proof=True) is None # needs sage.libs.pari sage.symbolic True For stronger results, we need more precision:: - sage: algdep(pi.n(), 5, height_bound=100, proof=True) is None # optional - sage.libs.pari sage.symbolic + sage: # needs sage.libs.pari sage.symbolic + sage: algdep(pi.n(), 5, height_bound=100, proof=True) is None Traceback (most recent call last): ... ValueError: insufficient precision for non-existence proof - sage: algdep(pi.n(200), 5, height_bound=100, proof=True) is None # optional - sage.libs.pari sage.symbolic + sage: algdep(pi.n(200), 5, height_bound=100, proof=True) is None True - - sage: algdep(pi.n(), 10, height_bound=10, proof=True) is None # optional - sage.libs.pari sage.symbolic + sage: algdep(pi.n(), 10, height_bound=10, proof=True) is None Traceback (most recent call last): ... ValueError: insufficient precision for non-existence proof - sage: algdep(pi.n(200), 10, height_bound=10, proof=True) is None # optional - sage.libs.pari sage.symbolic + sage: algdep(pi.n(200), 10, height_bound=10, proof=True) is None True We can also use ``proof=True`` to get positive results:: - sage: a = sqrt(2) + sqrt(3) + sqrt(5) # optional - sage.libs.pari sage.symbolic - sage: algdep(a.n(), 8, height_bound=1000, proof=True) # optional - sage.libs.pari sage.symbolic + sage: # needs sage.libs.pari sage.symbolic + sage: a = sqrt(2) + sqrt(3) + sqrt(5) + sage: algdep(a.n(), 8, height_bound=1000, proof=True) Traceback (most recent call last): ... ValueError: insufficient precision for uniqueness proof - sage: f = algdep(a.n(1000), 8, height_bound=1000, proof=True); f # optional - sage.libs.pari sage.symbolic + sage: f = algdep(a.n(1000), 8, height_bound=1000, proof=True); f x^8 - 40*x^6 + 352*x^4 - 960*x^2 + 576 - sage: f(a).expand() # optional - sage.libs.pari sage.symbolic + sage: f(a).expand() 0 TESTS:: - sage: algdep(complex("1+2j"), 4) # optional - sage.libs.pari + sage: algdep(complex("1+2j"), 4) # needs sage.libs.pari sage.rings.complex_double x^2 - 2*x + 5 We get an irreducible polynomial even if PARI returns a reducible one:: - sage: z = CDF(1, RR(3).sqrt())/2 - sage: pari(z).algdep(5) # optional - sage.libs.pari + sage: z = CDF(1, RR(3).sqrt())/2 # needs sage.rings.complex_double + sage: pari(z).algdep(5) # needs sage.libs.pari sage.rings.complex_double sage.symbolic x^5 + x^2 - sage: algdep(z, 5) # optional - sage.libs.pari + sage: algdep(z, 5) # needs sage.libs.pari sage.rings.complex_double sage.symbolic x^2 - x + 1 Check that cases where a constant polynomial might look better get handled correctly:: - sage: z = CC(-1)**(1/3) - sage: algdep(z, 1) # optional - sage.libs.pari + sage: z = CC(-1)**(1/3) # needs sage.rings.real_mpfr + sage: algdep(z, 1) # needs sage.libs.pari sage.symbolic x Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8, float64 # optional - numpy - sage: algdep(float64(1.888888888888888), int8(1)) # optional - numpy sage.libs.pari + sage: from numpy import int8, float64 # needs numpy + sage: algdep(float64(1.888888888888888), int8(1)) # needs numpy sage.libs.pari 9*x - 17 sage: from gmpy2 import mpz, mpfr - sage: algdep(mpfr(1.888888888888888), mpz(1)) # optional - sage.libs.pari + sage: algdep(mpfr(1.888888888888888), mpz(1)) # needs sage.libs.pari 9*x - 17 """ if proof and not height_bound: @@ -302,54 +304,54 @@ def bernoulli(n, algorithm='default', num_threads=1): EXAMPLES:: - sage: bernoulli(12) # optional - sage.libs.flint + sage: bernoulli(12) # needs sage.libs.flint -691/2730 - sage: bernoulli(50) # optional - sage.libs.flint + sage: bernoulli(50) # needs sage.libs.flint 495057205241079648212477525/66 We demonstrate each of the alternative algorithms:: - sage: bernoulli(12, algorithm='arb') # optional - sage.libs.flint + sage: bernoulli(12, algorithm='arb') # needs sage.libs.flint -691/2730 - sage: bernoulli(12, algorithm='flint') # optional - sage.libs.flint + sage: bernoulli(12, algorithm='flint') # needs sage.libs.flint -691/2730 - sage: bernoulli(12, algorithm='gap') # optional - sage.libs.gap + sage: bernoulli(12, algorithm='gap') # needs sage.libs.gap -691/2730 - sage: bernoulli(12, algorithm='gp') # optional - sage.libs.pari + sage: bernoulli(12, algorithm='gp') # needs sage.libs.pari -691/2730 sage: bernoulli(12, algorithm='magma') # optional - magma -691/2730 - sage: bernoulli(12, algorithm='pari') # optional - sage.libs.pari + sage: bernoulli(12, algorithm='pari') # needs sage.libs.pari -691/2730 - sage: bernoulli(12, algorithm='bernmm') # optional - sage.libs.ntl + sage: bernoulli(12, algorithm='bernmm') # needs sage.libs.ntl -691/2730 - sage: bernoulli(12, algorithm='bernmm', num_threads=4) # optional - sage.libs.ntl + sage: bernoulli(12, algorithm='bernmm', num_threads=4) # needs sage.libs.ntl -691/2730 TESTS:: - sage: algs = [] - sage: algs += ['arb'] # optional - sage.libs.flint - sage: algs += ['gap'] # optional - sage.libs.gap - sage: algs += ['gp', 'pari'] # optional - sage.libs.pari - sage: algs += ['bernmm'] # optional - sage.libs.ntl - sage: algs += ['flint'] # optional - sage.libs.flint + sage: algs = [] # The imports below are so that "sage -fixdoctests --probe" does not remove + sage: import sage.libs.arb; algs += ['arb'] # needs sage.libs.flint + sage: import sage.libs.gap; algs += ['gap'] # needs sage.libs.gap + sage: import sage.libs.pari; algs += ['gp', 'pari'] # needs sage.libs.pari + sage: import sage.libs.ntl; algs += ['bernmm'] # needs sage.libs.ntl + sage: import sage.libs.flint; algs += ['flint'] # needs sage.libs.flint sage: test_list = [ZZ.random_element(2, 2255) for _ in range(500)] sage: vals = [[bernoulli(i, algorithm=j) for j in algs] for i in test_list] # long time (up to 21s on sage.math, 2011) sage: all(len(set(x)) == 1 for x in vals) # long time (depends on previous line) True sage: algs = [] - sage: algs += ['gp', 'pari'] # optional - sage.libs.pari - sage: algs += ['bernmm'] # optional - sage.libs.ntl + sage: import sage.libs.pari; algs += ['gp', 'pari'] # needs sage.libs.pari + sage: import sage.libs.ntl; algs += ['bernmm'] # needs sage.libs.ntl sage: test_list = [ZZ.random_element(2256, 5000) for _ in range(500)] sage: vals = [[bernoulli(i, algorithm=j) for j in algs] for i in test_list] # long time (up to 30s on sage.math, 2011) sage: all(len(set(x))==1 for x in vals) # long time (depends on previous line) True - sage: from numpy import int8 # optional - numpy - sage: bernoulli(int8(12)) # optional - numpy sage.libs.flint + sage: from numpy import int8 # needs numpy + sage: bernoulli(int8(12)) # needs numpy sage.libs.flint -691/2730 sage: from gmpy2 import mpz - sage: bernoulli(mpz(12)) # optional - sage.libs.flint + sage: bernoulli(mpz(12)) # needs sage.libs.flint -691/2730 AUTHOR: @@ -439,8 +441,8 @@ def factorial(n, algorithm='gmp'): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: factorial(int8(4)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: factorial(int8(4)) # needs numpy 24 sage: from gmpy2 import mpz sage: factorial(mpz(4)) @@ -525,7 +527,7 @@ def is_prime(n): sage: a = 2**2048 + 981 sage: is_prime(a) # not tested - takes ~ 1min sage: proof.arithmetic(False) - sage: is_prime(a) # instantaneous! # optional - sage.libs.pari + sage: is_prime(a) # instantaneous! # needs sage.libs.pari True sage: proof.arithmetic(True) @@ -550,8 +552,8 @@ def is_prime(n): (cf. :trac:`32340`) and we should not warn:: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 + 1) # optional - sage.rings.number_field - sage: is_prime(1 + i) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 + 1) # needs sage.rings.number_field + sage: is_prime(1 + i) # needs sage.rings.number_field True """ try: @@ -562,8 +564,8 @@ def is_prime(n): R = n.parent() if R.is_field(): # number fields redefine .is_prime(), see #32340 - from sage.rings.number_field.number_field import NumberField_generic - if not isinstance(R, NumberField_generic): + from sage.rings.number_field.number_field_base import NumberField + if R is QQ or not isinstance(R, NumberField): import warnings s = f'Testing primality in {R}, which is a field, ' \ 'hence the result will always be False. ' @@ -592,19 +594,20 @@ def is_pseudoprime(n): EXAMPLES:: - sage: is_pseudoprime(389) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: is_pseudoprime(389) True - sage: is_pseudoprime(2000) # optional - sage.libs.pari + sage: is_pseudoprime(2000) False - sage: is_pseudoprime(2) # optional - sage.libs.pari + sage: is_pseudoprime(2) True - sage: is_pseudoprime(-1) # optional - sage.libs.pari + sage: is_pseudoprime(-1) False sage: factor(-6) -1 * 2 * 3 - sage: is_pseudoprime(1) # optional - sage.libs.pari + sage: is_pseudoprime(1) False - sage: is_pseudoprime(-2) # optional - sage.libs.pari + sage: is_pseudoprime(-2) False """ return ZZ(n).is_pseudoprime() @@ -627,51 +630,54 @@ def is_prime_power(n, get_data=False): EXAMPLES:: - sage: is_prime_power(389) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: is_prime_power(389) True - sage: is_prime_power(2000) # optional - sage.libs.pari + sage: is_prime_power(2000) False - sage: is_prime_power(2) # optional - sage.libs.pari + sage: is_prime_power(2) True - sage: is_prime_power(1024) # optional - sage.libs.pari + sage: is_prime_power(1024) True - sage: is_prime_power(1024, get_data=True) # optional - sage.libs.pari + sage: is_prime_power(1024, get_data=True) (2, 10) The same results can be obtained with:: - sage: 389.is_prime_power() # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: 389.is_prime_power() True - sage: 2000.is_prime_power() # optional - sage.libs.pari + sage: 2000.is_prime_power() False - sage: 2.is_prime_power() # optional - sage.libs.pari + sage: 2.is_prime_power() True - sage: 1024.is_prime_power() # optional - sage.libs.pari + sage: 1024.is_prime_power() True - sage: 1024.is_prime_power(get_data=True) # optional - sage.libs.pari + sage: 1024.is_prime_power(get_data=True) (2, 10) TESTS:: - sage: is_prime_power(-1) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: is_prime_power(-1) False - sage: is_prime_power(1) # optional - sage.libs.pari + sage: is_prime_power(1) False - sage: is_prime_power(QQ(997^100)) # optional - sage.libs.pari + sage: is_prime_power(QQ(997^100)) True - sage: is_prime_power(1/2197) # optional - sage.libs.pari + sage: is_prime_power(1/2197) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer - sage: is_prime_power("foo") # optional - sage.libs.pari + sage: is_prime_power("foo") Traceback (most recent call last): ... TypeError: unable to convert 'foo' to an integer sage: from gmpy2 import mpz - sage: is_prime_power(mpz(389)) # optional - sage.libs.pari + sage: is_prime_power(mpz(389)) True - sage: from numpy import int16 # optional - numpy - sage: is_prime_power(int16(389)) # optional - numpy sage.libs.pari + sage: from numpy import int16 # needs numpy + sage: is_prime_power(int16(389)) # needs numpy True """ return ZZ(n).is_prime_power(get_data=get_data) @@ -694,39 +700,41 @@ def is_pseudoprime_power(n, get_data=False): EXAMPLES:: - sage: is_pseudoprime_power(389) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: is_pseudoprime_power(389) True - sage: is_pseudoprime_power(2000) # optional - sage.libs.pari + sage: is_pseudoprime_power(2000) False - sage: is_pseudoprime_power(2) # optional - sage.libs.pari + sage: is_pseudoprime_power(2) True - sage: is_pseudoprime_power(1024) # optional - sage.libs.pari + sage: is_pseudoprime_power(1024) True - sage: is_pseudoprime_power(-1) # optional - sage.libs.pari + sage: is_pseudoprime_power(-1) False - sage: is_pseudoprime_power(1) # optional - sage.libs.pari + sage: is_pseudoprime_power(1) False - sage: is_pseudoprime_power(997^100) # optional - sage.libs.pari + sage: is_pseudoprime_power(997^100) True Use of the get_data keyword:: - sage: is_pseudoprime_power(3^1024, get_data=True) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: is_pseudoprime_power(3^1024, get_data=True) (3, 1024) - sage: is_pseudoprime_power(2^256, get_data=True) # optional - sage.libs.pari + sage: is_pseudoprime_power(2^256, get_data=True) (2, 256) - sage: is_pseudoprime_power(31, get_data=True) # optional - sage.libs.pari + sage: is_pseudoprime_power(31, get_data=True) (31, 1) - sage: is_pseudoprime_power(15, get_data=True) # optional - sage.libs.pari + sage: is_pseudoprime_power(15, get_data=True) (15, 0) Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: is_pseudoprime_power(int16(1024)) # optional - numpy sage.libs.pari + sage: from numpy import int16 # needs numpy + sage: is_pseudoprime_power(int16(1024)) # needs numpy sage.libs.pari True sage: from gmpy2 import mpz - sage: is_pseudoprime_power(mpz(1024)) # optional - sage.libs.pari + sage: is_pseudoprime_power(mpz(1024)) True """ return ZZ(n).is_prime_power(proof=False, get_data=get_data) @@ -790,8 +798,8 @@ def valuation(m, *args, **kwds): Traceback (most recent call last): ... ValueError: You can only compute the valuation with respect to a integer larger than 1. - sage: from numpy import int16 # optional - numpy - sage: valuation(int16(512), int16(2)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: valuation(int16(512), int16(2)) # needs numpy 9 sage: from gmpy2 import mpz sage: valuation(mpz(512), mpz(2)) @@ -828,49 +836,50 @@ def prime_powers(start, stop=None): EXAMPLES:: - sage: prime_powers(20) # optional - sage.libs.pari + sage: prime_powers(20) # needs sage.libs.pari [2, 3, 4, 5, 7, 8, 9, 11, 13, 16, 17, 19] - sage: len(prime_powers(1000)) # optional - sage.libs.pari + sage: len(prime_powers(1000)) # needs sage.libs.pari 193 - sage: len(prime_range(1000)) # optional - sage.libs.pari + sage: len(prime_range(1000)) # needs sage.libs.pari 168 - sage: a = [z for z in range(95, 1234) if is_prime_power(z)] # optional - sage.libs.pari - sage: b = prime_powers(95, 1234) # optional - sage.libs.pari - sage: len(b) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: a = [z for z in range(95, 1234) if is_prime_power(z)] + sage: b = prime_powers(95, 1234) + sage: len(b) 194 - sage: len(a) # optional - sage.libs.pari + sage: len(a) 194 - sage: a[:10] # optional - sage.libs.pari + sage: a[:10] [97, 101, 103, 107, 109, 113, 121, 125, 127, 128] - sage: b[:10] # optional - sage.libs.pari + sage: b[:10] [97, 101, 103, 107, 109, 113, 121, 125, 127, 128] - sage: a == b # optional - sage.libs.pari + sage: a == b True - sage: prime_powers(100) == [i for i in range(100) if is_prime_power(i)] # optional - sage.libs.pari + sage: prime_powers(100) == [i for i in range(100) if is_prime_power(i)] # needs sage.libs.pari True - sage: prime_powers(10, 7) # optional - sage.libs.pari + sage: prime_powers(10, 7) [] - sage: prime_powers(-5) # optional - sage.libs.pari + sage: prime_powers(-5) [] - sage: prime_powers(-1, 3) # optional - sage.libs.pari + sage: prime_powers(-1, 3) # needs sage.libs.pari [2] TESTS: Check that output are always Sage integers (:trac:`922`):: - sage: v = prime_powers(10) # optional - sage.libs.pari - sage: type(v[0]) # optional - sage.libs.pari + sage: v = prime_powers(10) # needs sage.libs.pari + sage: type(v[0]) # needs sage.libs.pari - sage: prime_powers(0, 1) # optional - sage.libs.pari + sage: prime_powers(0, 1) [] - sage: prime_powers(2) # optional - sage.libs.pari + sage: prime_powers(2) [] - sage: prime_powers(3) # optional - sage.libs.pari + sage: prime_powers(3) # needs sage.libs.pari [2] sage: prime_powers("foo") @@ -885,18 +894,18 @@ def prime_powers(start, stop=None): Check that long input are accepted (:trac:`17852`):: - sage: prime_powers(6l) # optional - sage.libs.pari + sage: prime_powers(6l) # needs sage.libs.pari [2, 3, 4, 5] - sage: prime_powers(6l, 10l) # optional - sage.libs.pari + sage: prime_powers(6l, 10l) # needs sage.libs.pari [7, 8, 9] Check numpy and gmpy2 support:: - sage: from numpy import int8 # optional - numpy - sage: prime_powers(int8(20)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: prime_powers(int8(20)) # needs numpy sage.libs.pari [2, 3, 4, 5, 7, 8, 9, 11, 13, 16, 17, 19] sage: from gmpy2 import mpz - sage: prime_powers(mpz(20)) # optional - sage.libs.pari + sage: prime_powers(mpz(20)) # needs sage.libs.pari [2, 3, 4, 5, 7, 8, 9, 11, 13, 16, 17, 19] """ start = ZZ(start) @@ -938,11 +947,11 @@ def primes_first_n(n, leave_pari=False): EXAMPLES:: - sage: primes_first_n(10) # optional - sage.libs.pari + sage: primes_first_n(10) # needs sage.libs.pari [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - sage: len(primes_first_n(1000)) # optional - sage.libs.pari + sage: len(primes_first_n(1000)) # needs sage.libs.pari 1000 - sage: primes_first_n(0) # optional - sage.libs.pari + sage: primes_first_n(0) [] """ if n < 0: @@ -980,13 +989,13 @@ def eratosthenes(n): [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47] sage: len(eratosthenes(100)) 25 - sage: eratosthenes(213) == prime_range(213) # optional - sage.libs.pari + sage: eratosthenes(213) == prime_range(213) # needs sage.libs.pari True TESTS:: - sage: from numpy import int8 # optional - numpy - sage: eratosthenes(int8(3)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: eratosthenes(int8(3)) # needs numpy [2, 3] sage: from gmpy2 import mpz sage: eratosthenes(mpz(3)) @@ -1052,41 +1061,43 @@ def primes(start=2, stop=None, proof=None): EXAMPLES:: - sage: for p in primes(5, 10): # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: for p in primes(5, 10): ....: print(p) 5 7 - sage: list(primes(13)) # optional - sage.libs.pari + sage: list(primes(13)) [2, 3, 5, 7, 11] - sage: list(primes(10000000000, 10000000100)) # optional - sage.libs.pari + sage: list(primes(10000000000, 10000000100)) [10000000019, 10000000033, 10000000061, 10000000069, 10000000097] - sage: max(primes(10^100, 10^100+10^4, proof=False)) # optional - sage.libs.pari + sage: max(primes(10^100, 10^100+10^4, proof=False)) 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009631 - sage: next(p for p in primes(10^20, infinity) if is_prime(2*p+1)) # optional - sage.libs.pari + sage: next(p for p in primes(10^20, infinity) if is_prime(2*p+1)) 100000000000000001243 TESTS:: - sage: for a in range(-10, 50): # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: for a in range(-10, 50): ....: for b in range(-10, 50): ....: assert list(primes(a,b)) == list(filter(is_prime, range(a,b))) - sage: sum(primes(-10, 9973, proof=False)) == sum(filter(is_prime, range(-10, 9973))) # optional - sage.libs.pari + sage: sum(primes(-10, 9973, proof=False)) == sum(filter(is_prime, range(-10, 9973))) True - sage: for p in primes(10, infinity): # optional - sage.libs.pari + sage: for p in primes(10, infinity): ....: if p > 20: break ....: print(p) 11 13 17 19 - sage: next(p for p in primes(10,oo)) # checks alternate infinity notation # optional - sage.libs.pari + sage: next(p for p in primes(10,oo)) # checks alternate infinity notation 11 - sage: from numpy import int8 # optional - numpy - sage: list(primes(int8(13))) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: list(primes(int8(13))) # needs numpy [2, 3, 5, 7, 11] sage: from gmpy2 import mpz - sage: list(primes(mpz(13))) # optional - sage.libs.pari + sage: list(primes(mpz(13))) [2, 3, 5, 7, 11] """ from sage.rings.infinity import infinity @@ -1126,40 +1137,41 @@ def next_prime_power(n): EXAMPLES:: - sage: next_prime_power(1) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: next_prime_power(1) 2 - sage: next_prime_power(2) # optional - sage.libs.pari + sage: next_prime_power(2) 3 - sage: next_prime_power(10) # optional - sage.libs.pari + sage: next_prime_power(10) 11 - sage: next_prime_power(7) # optional - sage.libs.pari + sage: next_prime_power(7) 8 - sage: next_prime_power(99) # optional - sage.libs.pari + sage: next_prime_power(99) 101 The same results can be obtained with:: - sage: 1.next_prime_power() # optional - sage.libs.pari + sage: 1.next_prime_power() 2 - sage: 2.next_prime_power() # optional - sage.libs.pari + sage: 2.next_prime_power() 3 - sage: 10.next_prime_power() # optional - sage.libs.pari + sage: 10.next_prime_power() 11 Note that `2` is the smallest prime power:: - sage: next_prime_power(-10) # optional - sage.libs.pari + sage: next_prime_power(-10) 2 - sage: next_prime_power(0) # optional - sage.libs.pari + sage: next_prime_power(0) 2 TESTS:: - sage: from numpy import int8 # optional - numpy - sage: next_prime_power(int8(10)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: next_prime_power(int8(10)) # needs numpy sage.libs.pari 11 sage: from gmpy2 import mpz - sage: next_prime_power(mpz(10)) # optional - sage.libs.pari + sage: next_prime_power(mpz(10)) 11 """ return ZZ(n).next_prime_power() @@ -1177,22 +1189,23 @@ def next_probable_prime(n): EXAMPLES:: - sage: next_probable_prime(-100) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: next_probable_prime(-100) 2 - sage: next_probable_prime(19) # optional - sage.libs.pari + sage: next_probable_prime(19) 23 - sage: next_probable_prime(int(999999999)) # optional - sage.libs.pari + sage: next_probable_prime(int(999999999)) 1000000007 - sage: next_probable_prime(2^768) # optional - sage.libs.pari + sage: next_probable_prime(2^768) 1552518092300708935148979488462502555256886017116696611139052038026050952686376886330878408828646477950487730697131073206171580044114814391444287275041181139204454976020849905550265285631598444825262999193716468750892846853816058039 TESTS:: - sage: from numpy import int8 # optional - numpy - sage: next_probable_prime(int8(19)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: next_probable_prime(int8(19)) # needs numpy sage.libs.pari 23 sage: from gmpy2 import mpz - sage: next_probable_prime(mpz(19)) # optional - sage.libs.pari + sage: next_probable_prime(mpz(19)) # needs sage.libs.pari 23 """ return ZZ(n).next_probable_prime() @@ -1216,33 +1229,34 @@ def next_prime(n, proof=None): EXAMPLES:: - sage: next_prime(-100) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: next_prime(-100) 2 - sage: next_prime(1) # optional - sage.libs.pari + sage: next_prime(1) 2 - sage: next_prime(2) # optional - sage.libs.pari + sage: next_prime(2) 3 - sage: next_prime(3) # optional - sage.libs.pari + sage: next_prime(3) 5 - sage: next_prime(4) # optional - sage.libs.pari + sage: next_prime(4) 5 Notice that the next_prime(5) is not 5 but 7. :: - sage: next_prime(5) # optional - sage.libs.pari + sage: next_prime(5) # needs sage.libs.pari 7 - sage: next_prime(2004) # optional - sage.libs.pari + sage: next_prime(2004) # needs sage.libs.pari 2011 TESTS:: - sage: from numpy import int8 # optional - numpy - sage: next_prime(int8(3)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: next_prime(int8(3)) # needs numpy sage.libs.pari 5 sage: from gmpy2 import mpz - sage: next_probable_prime(mpz(3)) # optional - sage.libs.pari + sage: next_probable_prime(mpz(3)) # needs sage.libs.pari 5 """ return ZZ(n).next_prime(proof) @@ -1255,38 +1269,39 @@ def previous_prime(n): EXAMPLES:: - sage: previous_prime(10) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: previous_prime(10) 7 - sage: previous_prime(7) # optional - sage.libs.pari + sage: previous_prime(7) 5 - sage: previous_prime(8) # optional - sage.libs.pari + sage: previous_prime(8) 7 - sage: previous_prime(7) # optional - sage.libs.pari + sage: previous_prime(7) 5 - sage: previous_prime(5) # optional - sage.libs.pari + sage: previous_prime(5) 3 - sage: previous_prime(3) # optional - sage.libs.pari + sage: previous_prime(3) 2 - sage: previous_prime(2) # optional - sage.libs.pari + sage: previous_prime(2) Traceback (most recent call last): ... ValueError: no previous prime - sage: previous_prime(1) # optional - sage.libs.pari + sage: previous_prime(1) Traceback (most recent call last): ... ValueError: no previous prime - sage: previous_prime(-20) # optional - sage.libs.pari + sage: previous_prime(-20) Traceback (most recent call last): ... ValueError: no previous prime TESTS:: - sage: from numpy import int8 # optional - numpy - sage: previous_prime(int8(7)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: previous_prime(int8(7)) # needs numpy sage.libs.pari 5 sage: from gmpy2 import mpz - sage: previous_prime(mpz(7)) # optional - sage.libs.pari + sage: previous_prime(mpz(7)) 5 """ n = ZZ(n) - 1 @@ -1321,52 +1336,54 @@ def previous_prime_power(n): EXAMPLES:: - sage: previous_prime_power(3) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: previous_prime_power(3) 2 - sage: previous_prime_power(10) # optional - sage.libs.pari + sage: previous_prime_power(10) 9 - sage: previous_prime_power(7) # optional - sage.libs.pari + sage: previous_prime_power(7) 5 - sage: previous_prime_power(127) # optional - sage.libs.pari + sage: previous_prime_power(127) 125 The same results can be obtained with:: - sage: 3.previous_prime_power() # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: 3.previous_prime_power() 2 - sage: 10.previous_prime_power() # optional - sage.libs.pari + sage: 10.previous_prime_power() 9 - sage: 7.previous_prime_power() # optional - sage.libs.pari + sage: 7.previous_prime_power() 5 - sage: 127.previous_prime_power() # optional - sage.libs.pari + sage: 127.previous_prime_power() 125 Input less than or equal to `2` raises errors:: - sage: previous_prime_power(2) # optional - sage.libs.pari + sage: previous_prime_power(2) Traceback (most recent call last): ... ValueError: no prime power less than 2 - sage: previous_prime_power(-10) # optional - sage.libs.pari + sage: previous_prime_power(-10) Traceback (most recent call last): ... ValueError: no prime power less than 2 :: - sage: n = previous_prime_power(2^16 - 1) # optional - sage.libs.pari - sage: while is_prime(n): # optional - sage.libs.pari + sage: n = previous_prime_power(2^16 - 1) # needs sage.libs.pari + sage: while is_prime(n): # needs sage.libs.pari ....: n = previous_prime_power(n) - sage: factor(n) # optional - sage.libs.pari + sage: factor(n) # needs sage.libs.pari 251^2 TESTS:: - sage: from numpy import int8 # optional - numpy - sage: previous_prime_power(int8(10)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: previous_prime_power(int8(10)) # needs numpy sage.libs.pari 9 sage: from gmpy2 import mpz - sage: previous_prime_power(mpz(10)) # optional - sage.libs.pari + sage: previous_prime_power(mpz(10)) # needs sage.libs.pari 9 """ return ZZ(n).previous_prime_power() @@ -1394,42 +1411,44 @@ def random_prime(n, proof=None, lbound=2): EXAMPLES:: - sage: p = random_prime(100000) # optional - sage.libs.pari - sage: p.is_prime() # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: p = random_prime(100000) + sage: p.is_prime() True - sage: p <= 100000 # optional - sage.libs.pari + sage: p <= 100000 True - sage: random_prime(2) # optional - sage.libs.pari + sage: random_prime(2) 2 Here we generate a random prime between 100 and 200:: - sage: p = random_prime(200, lbound=100) # optional - sage.libs.pari - sage: p.is_prime() # optional - sage.libs.pari + sage: p = random_prime(200, lbound=100) + sage: p.is_prime() True - sage: 100 <= p <= 200 # optional - sage.libs.pari + sage: 100 <= p <= 200 True If all we care about is finding a pseudo prime, then we can pass in ``proof=False`` :: - sage: p = random_prime(200, proof=False, lbound=100) # optional - sage.libs.pari - sage: p.is_pseudoprime() # optional - sage.libs.pari + sage: p = random_prime(200, proof=False, lbound=100) # needs sage.libs.pari + sage: p.is_pseudoprime() # needs sage.libs.pari True - sage: 100 <= p <= 200 # optional - sage.libs.pari + sage: 100 <= p <= 200 True TESTS:: - sage: type(random_prime(2)) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: type(random_prime(2)) - sage: type(random_prime(100)) # optional - sage.libs.pari + sage: type(random_prime(100)) - sage: random_prime(1, lbound=-2) #caused Sage hang #10112 # optional - sage.libs.pari + sage: random_prime(1, lbound=-2) # caused Sage hang #10112 Traceback (most recent call last): ... ValueError: n must be greater than or equal to 2 - sage: random_prime(126, lbound=114) # optional - sage.libs.pari + sage: random_prime(126, lbound=114) Traceback (most recent call last): ... ValueError: there are no primes between 114 and 126 (inclusive) @@ -1521,13 +1540,14 @@ def divisors(n): This function works whenever one has unique factorization:: - sage: K. = QuadraticField(7) # optional - sage.rings.number_field - sage: divisors(K.ideal(7)) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(7) + sage: divisors(K.ideal(7)) [Fractional ideal (1), Fractional ideal (a), Fractional ideal (7)] - sage: divisors(K.ideal(3)) # optional - sage.rings.number_field + sage: divisors(K.ideal(3)) [Fractional ideal (1), Fractional ideal (3), Fractional ideal (a - 2), Fractional ideal (a + 2)] - sage: divisors(K.ideal(35)) # optional - sage.rings.number_field + sage: divisors(K.ideal(35)) [Fractional ideal (1), Fractional ideal (5), Fractional ideal (a), Fractional ideal (7), Fractional ideal (5*a), Fractional ideal (35)] @@ -1535,8 +1555,8 @@ def divisors(n): sage: divisors(int(300)) [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 25, 30, 50, 60, 75, 100, 150, 300] - sage: import numpy # optional - numpy - sage: divisors(numpy.int8(100)) # optional - numpy + sage: import numpy # needs numpy + sage: divisors(numpy.int8(100)) # needs numpy [1, 2, 4, 5, 10, 20, 25, 50, 100] sage: import gmpy2 sage: divisors(gmpy2.mpz(100)) @@ -1598,13 +1618,13 @@ class Sigma: :: - sage: P = plot(sigma, 1, 100) # optional - sage.plot + sage: P = plot(sigma, 1, 100) # needs sage.plot This method also works with k-th powers. :: - sage: P = plot(sigma, 1, 100, k=2) # optional - sage.plot + sage: P = plot(sigma, 1, 100, k=2) # needs sage.plot AUTHORS: @@ -1616,21 +1636,24 @@ class Sigma: sage: sigma(100,4) 106811523 - sage: sigma(factorial(100), 3).mod(144169) # optional - sage.libs.pari + + sage: # needs sage.libs.pari + sage: sigma(factorial(100), 3).mod(144169) 3672 - sage: sigma(factorial(150), 12).mod(691) # optional - sage.libs.pari + sage: sigma(factorial(150), 12).mod(691) 176 - sage: RR(sigma(factorial(133),20)) # optional - sage.libs.pari + sage: RR(sigma(factorial(133),20)) # needs sage.rings.real_mpfr 2.80414775675747e4523 - sage: sigma(factorial(100),0) # optional - sage.libs.pari + sage: sigma(factorial(100),0) 39001250856960000 - sage: sigma(factorial(41),1) # optional - sage.libs.pari + sage: sigma(factorial(41),1) 229199532273029988767733858700732906511758707916800 - sage: from numpy import int8 # optional - numpy - sage: sigma(int8(100), int8(4)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: sigma(int8(100), int8(4)) # needs numpy 106811523 + sage: from gmpy2 import mpz - sage: sigma(mpz(100), mpz(4)) # optional - sage.libs.pari + sage: sigma(mpz(100), mpz(4)) 106811523 """ def __repr__(self): @@ -1654,9 +1677,9 @@ def __call__(self, n, k=1): sage: from sage.arith.misc import Sigma sage: q = Sigma() - sage: q(10) # optional - sage.libs.pari + sage: q(10) 18 - sage: q(10,2) # optional - sage.libs.pari + sage: q(10,2) 130 """ n = ZZ(n) @@ -1698,8 +1721,8 @@ def plot(self, xmin=1, xmax=50, k=1, pointsize=30, rgbcolor=(0,0,1), join=True, EXAMPLES:: sage: from sage.arith.misc import Sigma - sage: p = Sigma().plot() # optional - sage.libs.pari sage.plot - sage: p.ymax() # optional - sage.libs.pari sage.plot + sage: p = Sigma().plot() # needs sage.libs.pari sage.plot + sage: p.ymax() # needs sage.libs.pari sage.plot 124.0 """ v = [(n, sigma(n, k)) for n in range(xmin, xmax + 1)] @@ -1778,44 +1801,44 @@ def gcd(a, b=None, **kwargs): The following shows that indeed coercion takes place before computing the gcd. This behaviour was introduced in :trac:`10771`:: - sage: R.=QQ[] - sage: S.=ZZ[] + sage: R. = QQ[] + sage: S. = ZZ[] sage: p = S.random_element(degree=(0,10)) sage: q = R.random_element(degree=(0,10)) - sage: parent(gcd(1/p,q)) + sage: parent(gcd(1/p, q)) Fraction Field of Univariate Polynomial Ring in x over Rational Field - sage: parent(gcd([1/p,q])) + sage: parent(gcd([1/p, q])) Fraction Field of Univariate Polynomial Ring in x over Rational Field Make sure we try QQ and not merely ZZ (:trac:`13014`):: - sage: bool(gcd(2/5, 3/7) == gcd(SR(2/5), SR(3/7))) # optional - sage.symbolic + sage: bool(gcd(2/5, 3/7) == gcd(SR(2/5), SR(3/7))) # needs sage.symbolic True Make sure that the gcd of Expressions stays symbolic:: sage: parent(gcd(2, 4)) Integer Ring - sage: parent(gcd(SR(2), 4)) # optional - sage.symbolic + sage: parent(gcd(SR(2), 4)) # needs sage.symbolic Symbolic Ring - sage: parent(gcd(2, SR(4))) # optional - sage.symbolic + sage: parent(gcd(2, SR(4))) # needs sage.symbolic Symbolic Ring - sage: parent(gcd(SR(2), SR(4))) # optional - sage.symbolic + sage: parent(gcd(SR(2), SR(4))) # needs sage.symbolic Symbolic Ring Verify that objects without gcd methods but which cannot be coerced to ZZ or QQ raise an error:: - sage: F. = FreeMonoid(2) # optional - sage.groups - sage: gcd(a, b) # optional - sage.groups + sage: F. = FreeMonoid(2) # needs sage.groups + sage: gcd(a, b) # needs sage.groups Traceback (most recent call last): ... TypeError: unable to call gcd with a Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: GCD(int8(97), int8(100)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: GCD(int8(97), int8(100)) # needs numpy 1 sage: from gmpy2 import mpq, mpz sage: GCD(mpq(2/3), mpq(4/5)) @@ -1914,8 +1937,8 @@ def xlcm(m, n): TESTS:: - sage: from numpy import int16 # optional - numpy - sage: xlcm(int16(120), int16(36)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: xlcm(int16(120), int16(36)) # needs numpy (360, 40, 9) sage: from gmpy2 import mpz sage: xlcm(mpz(120), mpz(36)) @@ -1980,15 +2003,16 @@ def xgcd(a, b): sage: xgcd(x^3 - 1, x^2 - 1) (x - 1, 1, -x) - sage: K. = NumberField(x^2 - 3) # optional - sage.rings.number_field - sage: g.xgcd(g + 2) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3) # needs sage.rings.number_field + sage: g.xgcd(g + 2) # needs sage.rings.number_field (1, 1/3*g, 0) - sage: R. = K[] # optional - sage.rings.number_field - sage: S. = R.fraction_field()[] # optional - sage.rings.number_field - sage: xgcd(y^2, a*y + b) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R. = K[] + sage: S. = R.fraction_field()[] + sage: xgcd(y^2, a*y + b) (1, a^2/b^2, ((-a)/b^2)*y + 1/b) - sage: xgcd((b+g)*y^2, (a+g)*y + b) # optional - sage.rings.number_field + sage: xgcd((b+g)*y^2, (a+g)*y + b) (1, (a^2 + (2*g)*a + 3)/(b^3 + g*b^2), ((-a + (-g))/b^2)*y + 1/b) Here is an example of a xgcd for two polynomials over the integers, where the linear @@ -1999,15 +2023,15 @@ def xgcd(a, b): x sage: xgcd(2*x*(x-1), x^2) (2*x, -1, 2) - sage: (2*(x-1)).resultant(x) + sage: (2*(x-1)).resultant(x) # needs sage.libs.pari 2 Tests with numpy and gmpy2 types:: - sage: from numpy import int8 # optional - numpy - sage: xgcd(4, int8(8)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: xgcd(4, int8(8)) # needs numpy (4, 1, 0) - sage: xgcd(int8(4), int8(8)) # optional - numpy + sage: xgcd(int8(4), int8(8)) # needs numpy (4, 1, 0) sage: from gmpy2 import mpz sage: xgcd(mpz(4), mpz(8)) @@ -2019,10 +2043,11 @@ def xgcd(a, b): We check that :trac:`3330` has been fixed:: - sage: R. = NumberField(x^2 - 3, 'g').extension(x^2 - 7, 'h')[] # optional - sage.rings.number_field - sage: h = R.base_ring().gen() # optional - sage.rings.number_field - sage: S. = R.fraction_field()[] # optional - sage.rings.number_field - sage: xgcd(y^2, a*h*y + b) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R. = NumberField(x^2 - 3, 'g').extension(x^2 - 7, 'h')[] + sage: h = R.base_ring().gen() + sage: S. = R.fraction_field()[] + sage: xgcd(y^2, a*h*y + b) (1, 7*a^2/b^2, (((-h)*a)/b^2)*y + 1/b) """ try: @@ -2146,8 +2171,8 @@ def inverse_mod(a, m): Tests with numpy and mpz numbers:: - sage: from numpy import int8 # optional - numpy - sage: inverse_mod(int8(5), int8(14)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: inverse_mod(int8(5), int8(14)) # needs numpy 3 sage: from gmpy2 import mpz sage: inverse_mod(mpz(5), mpz(14)) @@ -2255,8 +2280,8 @@ def power_mod(a, n, m): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int32 # optional - numpy - sage: power_mod(int32(2), int32(390), int32(391)) # optional - numpy + sage: from numpy import int32 # needs numpy + sage: power_mod(int32(2), int32(390), int32(391)) # needs numpy 285 sage: from gmpy2 import mpz sage: power_mod(mpz(2), mpz(390), mpz(391)) @@ -2378,8 +2403,8 @@ def rational_reconstruction(a, m, algorithm='fast'): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int32 # optional - numpy - sage: rational_reconstruction(int32(3), int32(292393)) # optional - numpy + sage: from numpy import int32 # needs numpy + sage: rational_reconstruction(int32(3), int32(292393)) # needs numpy 3 sage: from gmpy2 import mpz sage: rational_reconstruction(mpz(3), mpz(292393)) @@ -2418,8 +2443,8 @@ def mqrr_rational_reconstruction(u, m, T): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: mqrr_rational_reconstruction(int16(21), int16(3100), int16(13)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: mqrr_rational_reconstruction(int16(21), int16(3100), int16(13)) # needs numpy (21, 1) sage: from gmpy2 import mpz sage: mqrr_rational_reconstruction(mpz(21), mpz(3100), mpz(13)) @@ -2486,8 +2511,8 @@ def trial_division(n, bound=None): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: trial_division(int8(91)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: trial_division(int8(91)) # needs numpy 7 sage: from gmpy2 import mpz sage: trial_division(mpz(91)) @@ -2518,10 +2543,10 @@ def factor(n, proof=None, int_=False, algorithm='pari', verbose=0, **kwds): EXAMPLES:: - sage: f(n) = n^2 # optional - sage.symbolic - sage: is_prime(f(3)) # optional - sage.symbolic + sage: f(n) = n^2 # needs sage.symbolic + sage: is_prime(f(3)) # needs sage.symbolic False - sage: factor(f(3)) # optional - sage.symbolic + sage: factor(f(3)) # needs sage.symbolic 9 INPUT: @@ -2582,17 +2607,17 @@ def factor(n, proof=None, int_=False, algorithm='pari', verbose=0, **kwds): -1 sage: f.value() -20 - sage: factor(-next_prime(10^2) * next_prime(10^7)) # optional - sage.libs.pari + sage: factor(-next_prime(10^2) * next_prime(10^7)) # needs sage.libs.pari -1 * 101 * 10000019 :: - sage: factor(293292629867846432923017396246429, algorithm='flint') # optional - sage.libs.flint + sage: factor(293292629867846432923017396246429, algorithm='flint') # needs sage.libs.flint 3 * 4852301647696687 * 20148007492971089 :: - sage: factor(-500, algorithm='kash') # optional - kash + sage: factor(-500, algorithm='kash') -1 * 2^2 * 5^3 :: @@ -2610,7 +2635,7 @@ def factor(n, proof=None, int_=False, algorithm='pari', verbose=0, **kwds): 1 sage: factor(-1) -1 - sage: factor(2^(2^7) + 1) # optional - sage.libs.pari + sage: factor(2^(2^7) + 1) # needs sage.libs.pari 59649589127497217 * 5704689200685129054721 Sage calls PARI's :pari:`factor`, which has ``proof=False`` by default. @@ -2620,42 +2645,43 @@ def factor(n, proof=None, int_=False, algorithm='pari', verbose=0, **kwds): :: - sage: factor(3^89 - 1, proof=False) # optional - sage.libs.pari + sage: factor(3^89 - 1, proof=False) # needs sage.libs.pari 2 * 179 * 1611479891519807 * 5042939439565996049162197 :: - sage: factor(2^197 + 1) # long time (2s) # optional - sage.libs.pari + sage: factor(2^197 + 1) # long time (2s) # needs sage.libs.pari 3 * 197002597249 * 1348959352853811313 * 251951573867253012259144010843 Any object which has a factor method can be factored like this:: - sage: K. = QuadraticField(-1) # optional - sage.rings.number_field - sage: factor(122 - 454*i) # optional - sage.rings.number_field + sage: K. = QuadraticField(-1) # needs sage.rings.number_field + sage: factor(122 - 454*i) # needs sage.rings.number_field (-i) * (-i - 2)^3 * (i + 1)^3 * (-2*i + 3) * (i + 4) To access the data in a factorization:: - sage: f = factor(420); f # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: f = factor(420); f 2^2 * 3 * 5 * 7 - sage: [x for x in f] # optional - sage.libs.pari + sage: [x for x in f] [(2, 2), (3, 1), (5, 1), (7, 1)] - sage: [p for p,e in f] # optional - sage.libs.pari + sage: [p for p,e in f] [2, 3, 5, 7] - sage: [e for p,e in f] # optional - sage.libs.pari + sage: [e for p,e in f] [2, 1, 1, 1] - sage: [p^e for p,e in f] # optional - sage.libs.pari + sage: [p^e for p,e in f] [4, 3, 5, 7] We can factor Python, numpy and gmpy2 numbers:: sage: factor(math.pi) 3.141592653589793 - sage: import numpy # optional - numpy - sage: factor(numpy.int8(30)) # optional - numpy sage.libs.pari + sage: import numpy # needs numpy + sage: factor(numpy.int8(30)) # needs numpy sage.libs.pari 2 * 3 * 5 sage: import gmpy2 - sage: factor(gmpy2.mpz(30)) # optional - sage.libs.pari + sage: factor(gmpy2.mpz(30)) 2 * 3 * 5 TESTS:: @@ -2707,14 +2733,14 @@ def radical(n, *args, **kwds): Traceback (most recent call last): ... ArithmeticError: radical of 0 is not defined - sage: K. = QuadraticField(-1) # optional - sage.rings.number_field - sage: radical(K(2)) # optional - sage.rings.number_field + sage: K. = QuadraticField(-1) # needs sage.rings.number_field + sage: radical(K(2)) # needs sage.rings.number_field i + 1 Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: radical(int8(50)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: radical(int8(50)) # needs numpy 10 sage: from gmpy2 import mpz sage: radical(mpz(50)) @@ -2767,13 +2793,13 @@ def prime_divisors(n): For polynomials we get all irreducible factors:: sage: R. = PolynomialRing(QQ) - sage: prime_divisors(x^12 - 1) # optional - sage.libs.pari + sage: prime_divisors(x^12 - 1) # needs sage.libs.pari [x - 1, x + 1, x^2 - x + 1, x^2 + 1, x^2 + x + 1, x^4 - x^2 + 1] Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: prime_divisors(int8(-100)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: prime_divisors(int8(-100)) # needs numpy [2, 5] sage: from gmpy2 import mpz sage: prime_divisors(mpz(-100)) @@ -2805,8 +2831,8 @@ def odd_part(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: odd_part(int8(5)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: odd_part(int8(5)) # needs numpy 5 sage: from gmpy2 import mpz sage: odd_part(mpz(5)) @@ -2849,8 +2875,8 @@ def prime_to_m_part(n, m): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: prime_to_m_part(int16(240), int16(2)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: prime_to_m_part(int16(240), int16(2)) # needs numpy 15 sage: from gmpy2 import mpz sage: prime_to_m_part(mpz(240), mpz(2)) @@ -2890,9 +2916,9 @@ def is_square(n, root=False): True sage: is_square(-2.2) False - sage: is_square(CDF(-2.2)) + sage: is_square(CDF(-2.2)) # needs sage.rings.complex_double True - sage: is_square((x-1)^2) # optional - sage.symbolic + sage: is_square((x-1)^2) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: is_square() not implemented for @@ -2905,8 +2931,8 @@ def is_square(n, root=False): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: is_square(int8(4)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: is_square(int8(4)) # needs numpy True sage: from gmpy2 import mpz sage: is_square(mpz(4)) @@ -2915,7 +2941,7 @@ def is_square(n, root=False): Tests with Polynomial:: sage: R. = LaurentPolynomialRing(QQ, 'v') - sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - sage.combinat sage.modules + sage: H = IwahoriHeckeAlgebra('A3', v**2) # needs sage.combinat sage.modules sage: R. = QQ[] sage: p = a*b + c*d*a*d*a + 5 sage: is_square(p**2) @@ -2944,47 +2970,49 @@ def is_squarefree(n): EXAMPLES:: - sage: is_squarefree(100) # optional - sage.libs.pari + sage: is_squarefree(100) # needs sage.libs.pari False - sage: is_squarefree(101) # optional - sage.libs.pari + sage: is_squarefree(101) # needs sage.libs.pari True sage: R = ZZ['x'] sage: x = R.gen() - sage: is_squarefree((x^2+x+1) * (x-2)) # optional - sage.libs.pari + sage: is_squarefree((x^2+x+1) * (x-2)) # needs sage.libs.pari True - sage: is_squarefree((x-1)**2 * (x-3)) # optional - sage.libs.pari + sage: is_squarefree((x-1)**2 * (x-3)) # needs sage.libs.pari False - sage: O = ZZ[sqrt(-1)] # optional - sage.rings.number_field sage.symbolic - sage: I = O.gen(1) # optional - sage.rings.number_field sage.symbolic - sage: is_squarefree(I + 1) # optional - sage.rings.number_field sage.symbolic + sage: # needs sage.rings.number_field sage.symbolic + sage: O = ZZ[sqrt(-1)] + sage: I = O.gen(1) + sage: is_squarefree(I + 1) True - sage: is_squarefree(O(2)) # optional - sage.rings.number_field sage.symbolic + sage: is_squarefree(O(2)) False - sage: O(2).factor() # optional - sage.rings.number_field sage.symbolic + sage: O(2).factor() (-I) * (I + 1)^2 This method fails on domains which are not Unique Factorization Domains:: - sage: O = ZZ[sqrt(-5)] # optional - sage.rings.number_field sage.symbolic - sage: a = O.gen(1) # optional - sage.rings.number_field sage.symbolic - sage: is_squarefree(a - 3) # optional - sage.rings.number_field sage.symbolic + sage: O = ZZ[sqrt(-5)] # needs sage.rings.number_field sage.symbolic + sage: a = O.gen(1) # needs sage.rings.number_field sage.symbolic + sage: is_squarefree(a - 3) # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... ArithmeticError: non-principal ideal in factorization Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: is_squarefree(int8(100)) # optional - numpy sage.libs.pari + sage: # needs sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: is_squarefree(int8(100)) # needs numpy False - sage: is_squarefree(int8(101)) # optional - numpy sage.libs.pari + sage: is_squarefree(int8(101)) # needs numpy True sage: from gmpy2 import mpz - sage: is_squarefree(mpz(100)) # optional - sage.libs.pari + sage: is_squarefree(mpz(100)) False - sage: is_squarefree(mpz(101)) # optional - sage.libs.pari + sage: is_squarefree(mpz(101)) True """ e = py_scalar_to_element(n) @@ -3021,11 +3049,11 @@ class Euler_Phi: 1 sage: euler_phi(2) 1 - sage: euler_phi(3) # optional - sage.libs.pari + sage: euler_phi(3) # needs sage.libs.pari 2 - sage: euler_phi(12) # optional - sage.libs.pari + sage: euler_phi(12) # needs sage.libs.pari 4 - sage: euler_phi(37) # optional - sage.libs.pari + sage: euler_phi(37) # needs sage.libs.pari 36 Notice that euler_phi is defined to be 0 on negative numbers and @@ -3044,7 +3072,7 @@ class Euler_Phi: :: - sage: euler_phi(21) # optional - sage.libs.pari + sage: euler_phi(21) # needs sage.libs.pari 12 sage: [i for i in range(21) if gcd(21,i) == 1] [1, 2, 4, 5, 8, 10, 11, 13, 16, 17, 19, 20] @@ -3054,22 +3082,22 @@ class Euler_Phi: :: - sage: len([i for i in range(21) if gcd(21,i) == 1]) == euler_phi(21) # optional - sage.libs.pari + sage: len([i for i in range(21) if gcd(21,i) == 1]) == euler_phi(21) # needs sage.libs.pari True The phi function also has a special plotting method. :: - sage: P = plot(euler_phi, -3, 71) # optional - sage.libs.pari sage.plot + sage: P = plot(euler_phi, -3, 71) # needs sage.libs.pari sage.plot Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: euler_phi(int8(37)) # optional - numpy sage.libs.pari sage.plot + sage: from numpy import int8 # needs numpy + sage: euler_phi(int8(37)) # needs numpy sage.libs.pari 36 sage: from gmpy2 import mpz - sage: euler_phi(mpz(37)) # optional - sage.libs.pari sage.plot + sage: euler_phi(mpz(37)) # needs sage.libs.pari 36 AUTHORS: @@ -3097,9 +3125,9 @@ def __call__(self, n): EXAMPLES:: sage: from sage.arith.misc import Euler_Phi - sage: Euler_Phi()(10) # optional - sage.libs.pari + sage: Euler_Phi()(10) # needs sage.libs.pari 4 - sage: Euler_Phi()(720) # optional - sage.libs.pari + sage: Euler_Phi()(720) # needs sage.libs.pari 192 """ if n <= 0: @@ -3133,8 +3161,8 @@ def plot(self, xmin=1, xmax=50, pointsize=30, rgbcolor=(0, 0, 1), EXAMPLES:: sage: from sage.arith.misc import Euler_Phi - sage: p = Euler_Phi().plot() # optional - sage.plot - sage: p.ymax() # optional - sage.plot + sage: p = Euler_Phi().plot() # needs sage.libs.pari sage.plot + sage: p.ymax() # needs sage.libs.pari sage.plot 46.0 """ v = [(n, euler_phi(n)) for n in range(xmin, xmax + 1)] @@ -3190,7 +3218,7 @@ def carmichael_lambda(n): The Carmichael function of the first ten primes:: - sage: list(map(carmichael_lambda, primes_first_n(10))) # optional - sage.libs.pari + sage: list(map(carmichael_lambda, primes_first_n(10))) # needs sage.libs.pari [1, 2, 4, 6, 10, 12, 16, 18, 22, 28] Cases where the Carmichael function is equivalent to the Euler phi @@ -3198,19 +3226,19 @@ def carmichael_lambda(n): sage: carmichael_lambda(2) == euler_phi(2) True - sage: carmichael_lambda(4) == euler_phi(4) # optional - sage.libs.pari + sage: carmichael_lambda(4) == euler_phi(4) # needs sage.libs.pari True - sage: p = random_prime(1000, lbound=3, proof=True) # optional - sage.libs.pari + sage: p = random_prime(1000, lbound=3, proof=True) # needs sage.libs.pari sage: k = randint(1, 1000) - sage: carmichael_lambda(p^k) == euler_phi(p^k) # optional - sage.libs.pari + sage: carmichael_lambda(p^k) == euler_phi(p^k) # needs sage.libs.pari True A case where `\lambda(n) \neq \varphi(n)`:: sage: k = randint(3, 1000) - sage: carmichael_lambda(2^k) == 2^(k - 2) # optional - sage.libs.pari + sage: carmichael_lambda(2^k) == 2^(k - 2) # needs sage.libs.pari True - sage: carmichael_lambda(2^k) == 2^(k - 2) == euler_phi(2^k) # optional - sage.libs.pari + sage: carmichael_lambda(2^k) == 2^(k - 2) == euler_phi(2^k) # needs sage.libs.pari False Verifying the current implementation of the Carmichael function using @@ -3220,7 +3248,7 @@ def carmichael_lambda(n): sage: from sage.arith.misc import carmichael_lambda sage: n = randint(1, 500) - sage: c = carmichael_lambda(n) # optional - sage.libs.pari + sage: c = carmichael_lambda(n) sage: def coprime(n): ....: return [i for i in range(n) if gcd(i, n) == 1] sage: def znpower(n, k): @@ -3235,7 +3263,7 @@ def carmichael_lambda(n): ....: T = [L[i] == ones[i] for i in range(len(L))] ....: if all(T): ....: return k - sage: c == my_carmichael(n) # optional - sage.libs.pari + sage: c == my_carmichael(n) True Carmichael's theorem states that `a^{\lambda(n)} \equiv 1 \pmod{n}` @@ -3244,12 +3272,12 @@ def carmichael_lambda(n): sage: from sage.arith.misc import carmichael_lambda sage: n = randint(2, 1000) - sage: c = carmichael_lambda(n) # optional - sage.libs.pari + sage: c = carmichael_lambda(n) sage: ZnZ = IntegerModRing(n) sage: M = ZnZ.list_of_elements_of_multiplicative_group() sage: ones = [1] * len(M) - sage: P = [power_mod(a, c, n) for a in M] # optional - sage.libs.pari - sage: P == ones # optional - sage.libs.pari + sage: P = [power_mod(a, c, n) for a in M] + sage: P == ones True TESTS: @@ -3269,7 +3297,7 @@ def carmichael_lambda(n): Bug reported in :trac:`8283`:: sage: from sage.arith.misc import carmichael_lambda - sage: type(carmichael_lambda(16)) # optional - sage.libs.pari + sage: type(carmichael_lambda(16)) REFERENCES: @@ -3350,38 +3378,40 @@ def crt(a, b, m=None, n=None): Note that this also works for polynomial rings:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^3 - 7) # optional - sage.rings.number_field - sage: R. = K[] # optional - sage.rings.number_field - sage: f = y^2 + 3 # optional - sage.rings.number_field - sage: g = y^3 - 5 # optional - sage.rings.number_field - sage: CRT(1, 3, f, g) # optional - sage.rings.number_field + sage: K. = NumberField(x^3 - 7) + sage: R. = K[] + sage: f = y^2 + 3 + sage: g = y^3 - 5 + sage: CRT(1, 3, f, g) -3/26*y^4 + 5/26*y^3 + 15/26*y + 53/26 - sage: CRT(1, a, f, g) # optional - sage.rings.number_field + sage: CRT(1, a, f, g) (-3/52*a + 3/52)*y^4 + (5/52*a - 5/52)*y^3 + (15/52*a - 15/52)*y + 27/52*a + 25/52 You can also do this for any number of moduli:: - sage: K. = NumberField(x^3 - 7) # optional - sage.rings.number_field - sage: R. = K[] # optional - sage.rings.number_field - sage: CRT([], []) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^3 - 7) + sage: R. = K[] + sage: CRT([], []) 0 - sage: CRT([a], [x]) # optional - sage.rings.number_field + sage: CRT([a], [x]) a - sage: f = x^2 + 3 # optional - sage.rings.number_field - sage: g = x^3 - 5 # optional - sage.rings.number_field - sage: h = x^5 + x^2 - 9 # optional - sage.rings.number_field - sage: k = CRT([1, a, 3], [f, g, h]); k # optional - sage.rings.number_field + sage: f = x^2 + 3 + sage: g = x^3 - 5 + sage: h = x^5 + x^2 - 9 + sage: k = CRT([1, a, 3], [f, g, h]); k (127/26988*a - 5807/386828)*x^9 + (45/8996*a - 33677/1160484)*x^8 + (2/173*a - 6/173)*x^7 + (133/6747*a - 5373/96707)*x^6 + (-6/2249*a + 18584/290121)*x^5 + (-277/8996*a + 38847/386828)*x^4 + (-135/4498*a + 42673/193414)*x^3 + (-1005/8996*a + 470245/1160484)*x^2 + (-1215/8996*a + 141165/386828)*x + 621/8996*a + 836445/386828 - sage: k.mod(f) # optional - sage.rings.number_field + sage: k.mod(f) 1 - sage: k.mod(g) # optional - sage.rings.number_field + sage: k.mod(g) a - sage: k.mod(h) # optional - sage.rings.number_field + sage: k.mod(h) 3 If the moduli are not coprime, a solution may not exist:: @@ -3408,13 +3438,13 @@ def crt(a, b, m=None, n=None): crt also work with numpy and gmpy2 numbers:: - sage: import numpy # optional - numpy - sage: crt(numpy.int8(2), numpy.int8(3), numpy.int8(7), numpy.int8(11)) # optional - numpy + sage: import numpy # needs numpy + sage: crt(numpy.int8(2), numpy.int8(3), numpy.int8(7), numpy.int8(11)) # needs numpy 58 sage: from gmpy2 import mpz sage: crt(mpz(2), mpz(3), mpz(7), mpz(11)) 58 - sage: crt(mpz(2), 3, mpz(7), numpy.int8(11)) # optional - numpy + sage: crt(mpz(2), 3, mpz(7), numpy.int8(11)) # needs numpy 58 """ if isinstance(a, list): @@ -3501,8 +3531,8 @@ def CRT_list(values, moduli): sage: CRT([32r,2r,2r],[60r,90r,150r]) 452 - sage: from numpy import int8 # optional - numpy - sage: CRT_list([int8(2), int8(3), int8(2)], [int8(3), int8(5), int8(7)]) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: CRT_list([int8(2), int8(3), int8(2)], [int8(3), int8(5), int8(7)]) # needs numpy 23 sage: from gmpy2 import mpz sage: CRT_list([mpz(2),mpz(3),mpz(2)], [mpz(3),mpz(5),mpz(7)]) @@ -3606,7 +3636,7 @@ def CRT_vectors(X, moduli): sage: CRT_vectors([[3,5,7],[3,5,11]], [2,3]) [3, 5, 5] - sage: CRT_vectors([vector(ZZ, [2,3,1]), Sequence([1,7,8], ZZ)], [8,9]) # optional - sage.modules + sage: CRT_vectors([vector(ZZ, [2,3,1]), Sequence([1,7,8], ZZ)], [8,9]) # needs sage.modules [10, 43, 17] """ # First find the CRT basis: @@ -3652,7 +3682,7 @@ def binomial(x, m, **kwds): 10 sage: binomial(2, 0) 1 - sage: binomial(1/2, 0) # optional - sage.libs.pari + sage: binomial(1/2, 0) # needs sage.libs.pari 1 sage: binomial(3, -1) 0 @@ -3662,13 +3692,13 @@ def binomial(x, m, **kwds): -6 sage: binomial(-5, -2) 0 - sage: binomial(RealField()('2.5'), 2) + sage: binomial(RealField()('2.5'), 2) # needs sage.rings.real_mpfr 1.87500000000000 - sage: n = var('n'); binomial(n, 2) # optional - sage.symbolic + sage: n = var('n'); binomial(n, 2) # needs sage.symbolic 1/2*(n - 1)*n - sage: n = var('n'); binomial(n, n) # optional - sage.symbolic + sage: n = var('n'); binomial(n, n) # needs sage.symbolic 1 - sage: n = var('n'); binomial(n, n - 1) # optional - sage.symbolic + sage: n = var('n'); binomial(n, n - 1) # needs sage.symbolic n sage: binomial(2^100, 2^100) 1 @@ -3684,8 +3714,8 @@ def binomial(x, m, **kwds): 'pari' (faster for large values):: sage: a = binomial(100, 45, algorithm='gmp') - sage: b = binomial(100, 45, algorithm='pari') - sage: a == b + sage: b = binomial(100, 45, algorithm='pari') # needs sage.libs.pari + sage: a == b # needs sage.libs.pari True TESTS: @@ -3697,13 +3727,13 @@ def binomial(x, m, **kwds): We test conversion of arguments to Integers -- see :trac:`6870`:: - sage: binomial(1/2, 1/1) + sage: binomial(1/2, 1/1) # needs sage.libs.pari 1/2 sage: binomial(10^20 + 1/1, 10^20) 100000000000000000001 - sage: binomial(SR(10**7), 10**7) # optional - sage.symbolic + sage: binomial(SR(10**7), 10**7) # needs sage.symbolic 1 - sage: binomial(3/2, SR(1/1)) # optional - sage.symbolic + sage: binomial(3/2, SR(1/1)) # needs sage.symbolic 3/2 Some floating point cases -- see :trac:`7562`, :trac:`9633`, and @@ -3756,8 +3786,8 @@ def binomial(x, m, **kwds): sage: binomial(y,3).parent() Multivariate Polynomial Ring in x, y over Ring of integers modulo 7 - sage: n = var('n') # optional - sage.symbolic - sage: binomial(n,2) # optional - sage.symbolic + sage: n = var('n') # needs sage.symbolic + sage: binomial(n,2) # needs sage.symbolic 1/2*(n - 1)*n Invalid inputs:: @@ -3768,8 +3798,8 @@ def binomial(x, m, **kwds): ... TypeError: either m or x-m must be an integer - sage: k, i = var('k,i') # optional - sage.symbolic - sage: binomial(k,i) # optional - sage.symbolic + sage: k, i = var('k,i') # needs sage.symbolic + sage: binomial(k,i) # needs sage.symbolic Traceback (most recent call last): ... TypeError: either m or x-m must be an integer @@ -3806,15 +3836,15 @@ def binomial(x, m, **kwds): :func:`~sage.functions.other.binomial` from the module :mod:`sage.functions.other`:: - sage: from sage.functions.other import binomial # optional - sage.symbolic - sage: binomial(k, i) # optional - sage.symbolic + sage: from sage.functions.other import binomial + sage: binomial(k, i) # needs sage.symbolic binomial(k, i) binomial support numpy and gmpy2 parameters:: sage: from sage.arith.misc import binomial - sage: import numpy # optional - numpy - sage: binomial(numpy.int32(20), numpy.int32(10)) # optional - numpy + sage: import numpy # needs numpy + sage: binomial(numpy.int32(20), numpy.int32(10)) # needs numpy 184756 sage: import gmpy2 sage: binomial(gmpy2.mpz(20), gmpy2.mpz(10)) @@ -3895,17 +3925,17 @@ def multinomial(*ks): 618970023101454657175683075 sage: multinomial([2^30, 2, 1]) 618970023101454657175683075 - sage: multinomial(Composition([1, 3])) # optional - sage.combinat + sage: multinomial(Composition([1, 3])) 4 - sage: multinomial(Partition([4, 2])) # optional - sage.combinat + sage: multinomial(Partition([4, 2])) # needs sage.combinat 15 TESTS: Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: multinomial(int8(3), int8(2)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: multinomial(int8(3), int8(2)) # needs numpy 10 sage: from gmpy2 import mpz sage: multinomial(mpz(3), mpz(2)) @@ -3961,8 +3991,8 @@ def binomial_coefficients(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: sorted(binomial_coefficients(int8(3)).items()) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: sorted(binomial_coefficients(int8(3)).items()) # needs numpy [((0, 3), 1), ((1, 2), 3), ((2, 1), 3), ((3, 0), 1)] sage: from gmpy2 import mpz sage: sorted(binomial_coefficients(mpz(3)).items()) @@ -4038,8 +4068,8 @@ def multinomial_coefficients(m, n): {(): 1} sage: multinomial_coefficients(0, 3) {} - sage: from numpy import int8 # optional - numpy - sage: sorted(multinomial_coefficients(int8(2), int8(5)).items()) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: sorted(multinomial_coefficients(int8(2), int8(5)).items()) # needs numpy [((0, 5), 1), ((1, 4), 5), ((2, 3), 10), ((3, 2), 10), ((4, 1), 5), ((5, 0), 1)] sage: from gmpy2 import mpz sage: sorted(multinomial_coefficients(mpz(2), mpz(5)).items()) @@ -4127,8 +4157,8 @@ def kronecker_symbol(x,y): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: kronecker_symbol(int8(13),int8(21)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: kronecker_symbol(int8(13),int8(21)) # needs numpy -1 sage: from gmpy2 import mpz sage: kronecker_symbol(mpz(13),mpz(21)) @@ -4179,8 +4209,8 @@ def legendre_symbol(x, p): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: legendre_symbol(int8(2), int8(3)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: legendre_symbol(int8(2), int8(3)) # needs numpy -1 sage: from gmpy2 import mpz sage: legendre_symbol(mpz(2),mpz(3)) @@ -4235,8 +4265,8 @@ def jacobi_symbol(a, b): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: jacobi_symbol(int16(10), int16(777)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: jacobi_symbol(int16(10), int16(777)) # needs numpy -1 sage: from gmpy2 import mpz sage: jacobi_symbol(mpz(10),mpz(777)) @@ -4252,7 +4282,7 @@ def primitive_root(n, check=True): """ Return a positive integer that generates the multiplicative group of integers modulo `n`, if one exists; otherwise, raise a - ``ValueError``. + :class:`ValueError`. A primitive root exists if `n=4` or `n=p^k` or `n=2p^k`, where `p` is an odd prime and `k` is a nonnegative number. @@ -4271,15 +4301,16 @@ def primitive_root(n, check=True): EXAMPLES:: - sage: primitive_root(23) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: primitive_root(23) 5 - sage: primitive_root(-46) # optional - sage.libs.pari + sage: primitive_root(-46) 5 - sage: primitive_root(25) # optional - sage.libs.pari + sage: primitive_root(25) 2 - sage: print([primitive_root(p) for p in primes(100)]) # optional - sage.libs.pari + sage: print([primitive_root(p) for p in primes(100)]) [1, 2, 2, 3, 2, 2, 3, 2, 5, 2, 3, 2, 6, 3, 5, 2, 2, 2, 2, 7, 5, 3, 2, 3, 5] - sage: primitive_root(8) # optional - sage.libs.pari + sage: primitive_root(8) Traceback (most recent call last): ... ValueError: no primitive root @@ -4295,57 +4326,59 @@ def primitive_root(n, check=True): :: sage: n = 10^50 + 151 # a prime - sage: primitive_root(n) # optional - sage.libs.pari + sage: primitive_root(n) # needs sage.libs.pari 11 - sage: primitive_root(n, check=False) # optional - sage.libs.pari + sage: primitive_root(n, check=False) # needs sage.libs.pari 11 TESTS: Various special cases:: - sage: primitive_root(-1) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: primitive_root(-1) 0 - sage: primitive_root(0) # optional - sage.libs.pari + sage: primitive_root(0) Traceback (most recent call last): ... ValueError: no primitive root - sage: primitive_root(1) # optional - sage.libs.pari + sage: primitive_root(1) 0 - sage: primitive_root(2) # optional - sage.libs.pari + sage: primitive_root(2) 1 - sage: primitive_root(3) # optional - sage.libs.pari + sage: primitive_root(3) 2 - sage: primitive_root(4) # optional - sage.libs.pari + sage: primitive_root(4) 3 We test that various numbers without primitive roots give an error - see :trac:`10836`:: - sage: primitive_root(15) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: primitive_root(15) Traceback (most recent call last): ... ValueError: no primitive root - sage: primitive_root(16) # optional - sage.libs.pari + sage: primitive_root(16) Traceback (most recent call last): ... ValueError: no primitive root - sage: primitive_root(1729) # optional - sage.libs.pari + sage: primitive_root(1729) Traceback (most recent call last): ... ValueError: no primitive root - sage: primitive_root(4*7^8) # optional - sage.libs.pari + sage: primitive_root(4*7^8) Traceback (most recent call last): ... ValueError: no primitive root Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: primitive_root(int8(-46)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: primitive_root(int8(-46)) # needs numpy sage.libs.pari 5 sage: from gmpy2 import mpz - sage: primitive_root(mpz(-46)) # optional - sage.libs.pari + sage: primitive_root(mpz(-46)) # needs sage.libs.pari 5 """ from sage.libs.pari.all import pari @@ -4381,29 +4414,29 @@ def nth_prime(n): EXAMPLES:: - sage: nth_prime(3) # optional - sage.libs.pari + sage: nth_prime(3) # needs sage.libs.pari 5 - sage: nth_prime(10) # optional - sage.libs.pari + sage: nth_prime(10) # needs sage.libs.pari 29 - sage: nth_prime(10^7) # optional - sage.libs.pari + sage: nth_prime(10^7) # needs sage.libs.pari 179424673 :: - sage: nth_prime(0) # optional - sage.libs.pari + sage: nth_prime(0) Traceback (most recent call last): ... ValueError: nth prime meaningless for non-positive n (=0) TESTS:: - sage: all(prime_pi(nth_prime(j)) == j for j in range(1, 1000, 10)) # optional - sage.libs.pari + sage: all(prime_pi(nth_prime(j)) == j for j in range(1, 1000, 10)) # needs sage.libs.pari sage.symbolic True - sage: from numpy import int8 # optional - numpy - sage: nth_prime(int8(10)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: nth_prime(int8(10)) # needs numpy sage.libs.pari 29 sage: from gmpy2 import mpz - sage: nth_prime(mpz(10)) # optional - sage.libs.pari + sage: nth_prime(mpz(10)) # needs sage.libs.pari 29 """ if n <= 0: @@ -4434,8 +4467,8 @@ def quadratic_residues(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: quadratic_residues(int8(11)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: quadratic_residues(int8(11)) # needs numpy [0, 1, 3, 4, 5, 9] sage: from gmpy2 import mpz sage: quadratic_residues(mpz(11)) @@ -4469,39 +4502,40 @@ class Moebius: EXAMPLES:: - sage: moebius(-5) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: moebius(-5) -1 - sage: moebius(9) # optional - sage.libs.pari + sage: moebius(9) 0 - sage: moebius(12) # optional - sage.libs.pari + sage: moebius(12) 0 - sage: moebius(-35) # optional - sage.libs.pari + sage: moebius(-35) 1 - sage: moebius(-1) # optional - sage.libs.pari + sage: moebius(-1) 1 - sage: moebius(7) # optional - sage.libs.pari + sage: moebius(7) -1 :: - sage: moebius(0) # potentially nonstandard! # optional - sage.libs.pari + sage: moebius(0) # potentially nonstandard! 0 The moebius function even makes sense for non-integer inputs. :: - sage: x = GF(7)['x'].0 # optional - sage.libs.pari - sage: moebius(x + 2) # optional - sage.libs.pari + sage: x = GF(7)['x'].0 + sage: moebius(x + 2) # needs sage.libs.pari -1 Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: moebius(int8(-5)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: moebius(int8(-5)) # needs numpy sage.libs.pari -1 sage: from gmpy2 import mpz - sage: moebius(mpz(-5)) # optional - sage.libs.pari + sage: moebius(mpz(-5)) # needs sage.libs.pari -1 """ def __call__(self, n): @@ -4509,7 +4543,7 @@ def __call__(self, n): EXAMPLES:: sage: from sage.arith.misc import Moebius - sage: Moebius().__call__(7) # optional - sage.libs.pari + sage: Moebius().__call__(7) # needs sage.libs.pari -1 """ n = py_scalar_to_element(n) @@ -4567,8 +4601,8 @@ def plot(self, xmin=0, xmax=50, pointsize=30, rgbcolor=(0,0,1), join=True, EXAMPLES:: sage: from sage.arith.misc import Moebius - sage: p = Moebius().plot() # optional - sage.plot - sage: p.ymax() # optional - sage.plot + sage: p = Moebius().plot() # needs sage.libs.pari sage.plot + sage: p.ymax() # needs sage.libs.pari sage.plot 1.0 """ values = self.range(xmin, xmax + 1) @@ -4590,12 +4624,13 @@ def range(self, start, stop=None, step=None): EXAMPLES:: - sage: v = moebius.range(-10, 10); v # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: v = moebius.range(-10, 10); v [1, 0, 0, -1, 1, -1, 0, -1, -1, 1, 0, 1, -1, -1, 0, -1, 1, -1, 0, 0] - sage: v == [moebius(n) for n in range(-10, 10)] # optional - sage.libs.pari + sage: v == [moebius(n) for n in range(-10, 10)] True - sage: v = moebius.range(-1000, 2000, 4) # optional - sage.libs.pari - sage: v == [moebius(n) for n in range(-1000, 2000, 4)] # optional - sage.libs.pari + sage: v = moebius.range(-1000, 2000, 4) + sage: v == [moebius(n) for n in range(-1000, 2000, 4)] True """ if stop is None: @@ -4660,7 +4695,7 @@ def continuant(v, n=None): sage: p/q 517656/190435 sage: F = continued_fraction([2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10]) - sage: F.convergent(14) # optional - sage.libs.pari + sage: F.convergent(14) 517656/190435 sage: x = PolynomialRing(RationalField(), 'x', 5).gens() sage: continuant(x) @@ -4689,8 +4724,8 @@ def continuant(v, n=None): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: continuant([int8(1), int8(2), int8(3)]) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: continuant([int8(1), int8(2), int8(3)]) # needs numpy 10 sage: from gmpy2 import mpz sage: continuant([mpz(1), mpz(2), mpz(3)]) @@ -4727,18 +4762,18 @@ def number_of_divisors(n): EXAMPLES:: - sage: number_of_divisors(100) # optional - sage.libs.pari + sage: number_of_divisors(100) # needs sage.libs.pari 9 - sage: number_of_divisors(-720) # optional - sage.libs.pari + sage: number_of_divisors(-720) # needs sage.libs.pari 30 Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: number_of_divisors(int8(100)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: number_of_divisors(int8(100)) # needs numpy sage.libs.pari 9 sage: from gmpy2 import mpz - sage: number_of_divisors(mpz(100)) # optional - sage.libs.pari + sage: number_of_divisors(mpz(100)) # needs sage.libs.pari 9 """ m = ZZ(n) @@ -4776,33 +4811,34 @@ def hilbert_symbol(a, b, p, algorithm="pari"): EXAMPLES:: - sage: hilbert_symbol(-1, -1, -1, algorithm='all') # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: hilbert_symbol(-1, -1, -1, algorithm='all') -1 - sage: hilbert_symbol(2, 3, 5, algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(2, 3, 5, algorithm='all') 1 - sage: hilbert_symbol(4, 3, 5, algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(4, 3, 5, algorithm='all') 1 - sage: hilbert_symbol(0, 3, 5, algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(0, 3, 5, algorithm='all') 0 - sage: hilbert_symbol(-1, -1, 2, algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(-1, -1, 2, algorithm='all') -1 - sage: hilbert_symbol(1, -1, 2, algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(1, -1, 2, algorithm='all') 1 - sage: hilbert_symbol(3, -1, 2, algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(3, -1, 2, algorithm='all') -1 - sage: hilbert_symbol(QQ(-1)/QQ(4), -1, 2) == -1 # optional - sage.libs.pari + sage: hilbert_symbol(QQ(-1)/QQ(4), -1, 2) == -1 # needs sage.libs.pari True - sage: hilbert_symbol(QQ(-1)/QQ(4), -1, 3) == 1 # optional - sage.libs.pari + sage: hilbert_symbol(QQ(-1)/QQ(4), -1, 3) == 1 # needs sage.libs.pari True Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: hilbert_symbol(int8(2), int8(3), int8(5), algorithm='all') # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: hilbert_symbol(int8(2), int8(3), int8(5), algorithm='all') # needs numpy sage.libs.pari 1 sage: from gmpy2 import mpz - sage: hilbert_symbol(mpz(2), mpz(3), mpz(5), algorithm='all') # optional - sage.libs.pari + sage: hilbert_symbol(mpz(2), mpz(3), mpz(5), algorithm='all') # needs sage.libs.pari 1 AUTHORS: @@ -4881,22 +4917,23 @@ def hilbert_conductor(a, b): EXAMPLES:: - sage: hilbert_conductor(-1, -1) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: hilbert_conductor(-1, -1) 2 - sage: hilbert_conductor(-1, -11) # optional - sage.libs.pari + sage: hilbert_conductor(-1, -11) 11 - sage: hilbert_conductor(-2, -5) # optional - sage.libs.pari + sage: hilbert_conductor(-2, -5) 5 - sage: hilbert_conductor(-3, -17) # optional - sage.libs.pari + sage: hilbert_conductor(-3, -17) 17 Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: hilbert_conductor(int8(-3), int8(-17)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: hilbert_conductor(int8(-3), int8(-17)) # needs numpy sage.libs.pari 17 sage: from gmpy2 import mpz - sage: hilbert_conductor(mpz(-3), mpz(-17)) # optional - sage.libs.pari + sage: hilbert_conductor(mpz(-3), mpz(-17)) # needs sage.libs.pari 17 AUTHOR: @@ -4924,19 +4961,20 @@ def hilbert_conductor_inverse(d): EXAMPLES:: - sage: hilbert_conductor_inverse(2) # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: hilbert_conductor_inverse(2) (-1, -1) - sage: hilbert_conductor_inverse(3) # optional - sage.libs.pari + sage: hilbert_conductor_inverse(3) (-1, -3) - sage: hilbert_conductor_inverse(6) # optional - sage.libs.pari + sage: hilbert_conductor_inverse(6) (-1, 3) - sage: hilbert_conductor_inverse(30) # optional - sage.libs.pari + sage: hilbert_conductor_inverse(30) (-3, -10) - sage: hilbert_conductor_inverse(4) # optional - sage.libs.pari + sage: hilbert_conductor_inverse(4) Traceback (most recent call last): ... ValueError: d needs to be squarefree - sage: hilbert_conductor_inverse(-1) # optional - sage.libs.pari + sage: hilbert_conductor_inverse(-1) Traceback (most recent call last): ... ValueError: d needs to be positive @@ -4947,18 +4985,18 @@ def hilbert_conductor_inverse(d): TESTS:: - sage: for i in range(100): # optional - sage.libs.pari + sage: for i in range(100): # needs sage.libs.pari ....: d = ZZ.random_element(2**32).squarefree_part() ....: if hilbert_conductor(*hilbert_conductor_inverse(d)) != d: ....: print("hilbert_conductor_inverse failed for d = {}".format(d)) Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: hilbert_conductor_inverse(int8(30)) # optional - numpy sage.libs.pari + sage: from numpy import int8 # needs numpy + sage: hilbert_conductor_inverse(int8(30)) # needs numpy sage.libs.pari (-3, -10) sage: from gmpy2 import mpz - sage: hilbert_conductor_inverse(mpz(30)) # optional - sage.libs.pari + sage: hilbert_conductor_inverse(mpz(30)) # needs sage.libs.pari (-3, -10) """ Z = ZZ @@ -5034,26 +5072,28 @@ def falling_factorial(x, a): sage: falling_factorial(10, 3) 720 - sage: falling_factorial(10, RR('3.0')) # optional - sage.symbolic - 720.000000000000 - sage: falling_factorial(10, RR('3.3')) # optional - sage.symbolic - 1310.11633396601 sage: falling_factorial(10, 10) 3628800 sage: factorial(10) 3628800 - sage: a = falling_factorial(1 + I, I); a # optional - sage.symbolic + + sage: # needs sage.symbolic + sage: falling_factorial(10, RR('3.0')) + 720.000000000000 + sage: falling_factorial(10, RR('3.3')) + 1310.11633396601 + sage: a = falling_factorial(1 + I, I); a gamma(I + 2) - sage: CC(a) # optional - sage.symbolic + sage: CC(a) 0.652965496420167 + 0.343065839816545*I sage: falling_factorial(1 + I, 4) 4*I + 2 sage: falling_factorial(I, 4) -10 - sage: M = MatrixSpace(ZZ, 4, 4) - sage: A = M([1,0,1,0, 1,0,1,0, 1,0,10,10, 1,0,1,1]) - sage: falling_factorial(A, 2) # A(A - I) + sage: M = MatrixSpace(ZZ, 4, 4) # needs sage.modules + sage: A = M([1,0,1,0, 1,0,1,0, 1,0,10,10, 1,0,1,1]) # needs sage.modules + sage: falling_factorial(A, 2) # A(A - I) # needs sage.modules [ 1 0 10 10] [ 1 0 10 10] [ 20 0 101 100] @@ -5067,13 +5107,13 @@ def falling_factorial(x, a): Check that :trac:`14858` is fixed:: - sage: falling_factorial(-4, SR(2)) # optional - sage.symbolic + sage: falling_factorial(-4, SR(2)) # needs sage.symbolic 20 Check that :trac:`16770` is fixed:: - sage: d = var('d') # optional - sage.symbolic - sage: parent(falling_factorial(d, 0)) # optional - sage.symbolic + sage: d = var('d') # needs sage.symbolic + sage: parent(falling_factorial(d, 0)) # needs sage.symbolic Symbolic Ring Check that :trac:`20075` is fixed:: @@ -5083,8 +5123,8 @@ def falling_factorial(x, a): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: falling_factorial(int8(10), int8(3)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: falling_factorial(int8(10), int8(3)) # needs numpy 720 sage: from gmpy2 import mpz sage: falling_factorial(mpz(10), mpz(3)) @@ -5137,17 +5177,15 @@ def rising_factorial(x, a): sage: rising_factorial(10,3) 1320 - sage: rising_factorial(10,RR('3.0')) + sage: # needs sage.symbolic + sage: rising_factorial(10, RR('3.0')) 1320.00000000000 - - sage: rising_factorial(10,RR('3.3')) + sage: rising_factorial(10, RR('3.3')) 2826.38895824964 - sage: a = rising_factorial(1+I, I); a gamma(2*I + 1)/gamma(I + 1) sage: CC(a) 0.266816390637832 + 0.122783354006372*I - sage: a = rising_factorial(I, 4); a -10 @@ -5159,15 +5197,15 @@ def rising_factorial(x, a): Check that :trac:`14858` is fixed:: - sage: bool(rising_factorial(-4, 2) == # optional - sage.symbolic + sage: bool(rising_factorial(-4, 2) == # needs sage.symbolic ....: rising_factorial(-4, SR(2)) == ....: rising_factorial(SR(-4), SR(2))) True Check that :trac:`16770` is fixed:: - sage: d = var('d') # optional - sage.symbolic - sage: parent(rising_factorial(d, 0)) # optional - sage.symbolic + sage: d = var('d') # needs sage.symbolic + sage: parent(rising_factorial(d, 0)) # needs sage.symbolic Symbolic Ring Check that :trac:`20075` is fixed:: @@ -5177,8 +5215,8 @@ def rising_factorial(x, a): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: rising_factorial(int8(10), int8(3)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: rising_factorial(int8(10), int8(3)) # needs numpy 1320 sage: from gmpy2 import mpz sage: rising_factorial(mpz(10), mpz(3)) @@ -5207,15 +5245,15 @@ def integer_ceil(x): sage: integer_ceil(5.4) 6 - sage: integer_ceil(x) # optional - sage.symbolic + sage: integer_ceil(x) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: computation of ceil of x not implemented Tests with numpy and gmpy2 numbers:: - sage: from numpy import float32 # optional - numpy - sage: integer_ceil(float32(5.4)) # optional - numpy + sage: from numpy import float32 # needs numpy + sage: integer_ceil(float32(5.4)) # needs numpy 6 sage: from gmpy2 import mpfr sage: integer_ceil(mpfr(5.4)) @@ -5253,15 +5291,15 @@ def integer_floor(x): sage: integer_floor(RDF(-5/2)) -3 - sage: integer_floor(x) # optional - sage.symbolic + sage: integer_floor(x) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: computation of floor of x not implemented Tests with numpy and gmpy2 numbers:: - sage: from numpy import float32 # optional - numpy - sage: integer_floor(float32(5.4)) # optional - numpy + sage: from numpy import float32 # needs numpy + sage: integer_floor(float32(5.4)) # needs numpy 5 sage: from gmpy2 import mpfr sage: integer_floor(mpfr(5.4)) @@ -5298,7 +5336,7 @@ def integer_trunc(i): def two_squares(n): """ Write the integer `n` as a sum of two integer squares if possible; - otherwise raise a ``ValueError``. + otherwise raise a :class:`ValueError`. INPUT: @@ -5317,11 +5355,11 @@ def two_squares(n): ValueError: 21 is not a sum of 2 squares sage: two_squares(21^2) (0, 21) - sage: a, b = two_squares(100000000000000000129); a, b # optional - sage.libs.pari + sage: a, b = two_squares(100000000000000000129); a, b # needs sage.libs.pari (4418521500, 8970878873) - sage: a^2 + b^2 # optional - sage.libs.pari + sage: a^2 + b^2 # needs sage.libs.pari 100000000000000000129 - sage: two_squares(2^222 + 1) # optional - sage.libs.pari + sage: two_squares(2^222 + 1) # needs sage.libs.pari (253801659504708621991421712450521, 2583712713213354898490304645018692) sage: two_squares(0) (0, 0) @@ -5332,7 +5370,7 @@ def two_squares(n): TESTS:: - sage: for _ in range(100): # optional - sage.libs.pari + sage: for _ in range(100): # needs sage.libs.pari ....: a = ZZ.random_element(2**16, 2**20) ....: b = ZZ.random_element(2**16, 2**20) ....: n = a**2 + b**2 @@ -5341,8 +5379,8 @@ def two_squares(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: two_squares(int16(389)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: two_squares(int16(389)) # needs numpy (10, 17) sage: from gmpy2 import mpz sage: two_squares(mpz(389)) @@ -5420,7 +5458,7 @@ def two_squares(n): def three_squares(n): """ Write the integer `n` as a sum of three integer squares if possible; - otherwise raise a ``ValueError``. + otherwise raise a :class:`ValueError`. INPUT: @@ -5439,11 +5477,12 @@ def three_squares(n): (3, 24, 49) sage: three_squares(7^100) (0, 0, 1798465042647412146620280340569649349251249) - sage: three_squares(11^111 - 1) # optional - sage.libs.pari - (616274160655975340150706442680, 901582938385735143295060746161, 6270382387635744140394001363065311967964099981788593947233) - sage: three_squares(7 * 2^41) # optional - sage.libs.pari + sage: three_squares(11^111 - 1) # needs sage.libs.pari + (616274160655975340150706442680, 901582938385735143295060746161, + 6270382387635744140394001363065311967964099981788593947233) + sage: three_squares(7 * 2^41) # needs sage.libs.pari (1048576, 2097152, 3145728) - sage: three_squares(7 * 2^42) # optional - sage.libs.pari + sage: three_squares(7 * 2^42) Traceback (most recent call last): ... ValueError: 30786325577728 is not a sum of 3 squares @@ -5456,7 +5495,7 @@ def three_squares(n): TESTS:: - sage: for _ in range(100): # optional - sage.libs.pari + sage: for _ in range(100): # needs sage.libs.pari ....: a = ZZ.random_element(2**16, 2**20) ....: b = ZZ.random_element(2**16, 2**20) ....: c = ZZ.random_element(2**16, 2**20) @@ -5466,8 +5505,8 @@ def three_squares(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: three_squares(int16(389)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: three_squares(int16(389)) # needs numpy (1, 8, 18) sage: from gmpy2 import mpz sage: three_squares(mpz(389)) @@ -5583,23 +5622,24 @@ def four_squares(n): (0, 0, 3, 11) sage: four_squares(1101011011004) (90, 102, 1220, 1049290) - sage: four_squares(10^100 - 1) # optional - sage.libs.pari - (155024616290, 2612183768627, 14142135623730950488016887, 99999999999999999999999999999999999999999999999999) - sage: for i in range(2^129, 2^129+10000): # long time # optional - sage.libs.pari + sage: four_squares(10^100 - 1) # needs sage.libs.pari + (155024616290, 2612183768627, 14142135623730950488016887, + 99999999999999999999999999999999999999999999999999) + sage: for i in range(2^129, 2^129 + 10000): # long time # needs sage.libs.pari ....: S = four_squares(i) ....: assert sum(x^2 for x in S) == i TESTS:: - sage: for _ in range(100): # optional - sage.libs.pari + sage: for _ in range(100): ....: n = ZZ.random_element(2**32, 2**34) ....: aa, bb, cc, dd = four_squares(n) ....: assert aa**2 + bb**2 + cc**2 + dd**2 == n Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: four_squares(int16(389)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: four_squares(int16(389)) # needs numpy (0, 1, 8, 18) sage: from gmpy2 import mpz sage: four_squares(mpz(389)) @@ -5639,7 +5679,7 @@ def four_squares(n): def sum_of_k_squares(k, n): """ Write the integer `n` as a sum of `k` integer squares if possible; - otherwise raise a ``ValueError``. + otherwise raise a :class:`ValueError`. INPUT: @@ -5660,8 +5700,12 @@ def sum_of_k_squares(k, n): (1, 2, 5, 98) sage: sum_of_k_squares(5, 9634) (0, 1, 2, 5, 98) - sage: sum_of_k_squares(6, 11^1111 - 1) # optional - sage.libs.pari - (19215400822645944253860920437586326284, 37204645194585992174252915693267578306, 3473654819477394665857484221256136567800161086815834297092488779216863122, 5860191799617673633547572610351797996721850737768032876360978911074629287841061578270832330322236796556721252602860754789786937515870682024273948, 20457423294558182494001919812379023992538802203730791019728543439765347851316366537094696896669915675685581905102118246887673397020172285247862426612188418787649371716686651256443143210952163970564228423098202682066311189439731080552623884051737264415984619097656479060977602722566383385989, 311628095411678159849237738619458396497534696043580912225334269371611836910345930320700816649653412141574887113710604828156159177769285115652741014638785285820578943010943846225597311231847997461959204894255074229895666356909071243390280307709880906261008237873840245959883405303580405277298513108957483306488193844321589356441983980532251051786704380984788999660195252373574924026139168936921591652831237741973242604363696352878914129671292072201700073286987126265965322808664802662993006926302359371379531571194266134916767573373504566621665949840469229781956838744551367172353) + sage: sum_of_k_squares(6, 11^1111 - 1) # needs sage.libs.pari + (19215400822645944253860920437586326284, 37204645194585992174252915693267578306, + 3473654819477394665857484221256136567800161086815834297092488779216863122, + 5860191799617673633547572610351797996721850737768032876360978911074629287841061578270832330322236796556721252602860754789786937515870682024273948, + 20457423294558182494001919812379023992538802203730791019728543439765347851316366537094696896669915675685581905102118246887673397020172285247862426612188418787649371716686651256443143210952163970564228423098202682066311189439731080552623884051737264415984619097656479060977602722566383385989, + 311628095411678159849237738619458396497534696043580912225334269371611836910345930320700816649653412141574887113710604828156159177769285115652741014638785285820578943010943846225597311231847997461959204894255074229895666356909071243390280307709880906261008237873840245959883405303580405277298513108957483306488193844321589356441983980532251051786704380984788999660195252373574924026139168936921591652831237741973242604363696352878914129671292072201700073286987126265965322808664802662993006926302359371379531571194266134916767573373504566621665949840469229781956838744551367172353) sage: sum_of_k_squares(7, 0) (0, 0, 0, 0, 0, 0, 0) sage: sum_of_k_squares(30,999999) @@ -5693,8 +5737,8 @@ def sum_of_k_squares(k, n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int16 # optional - numpy - sage: sum_of_k_squares(int16(2), int16(9634)) # optional - numpy + sage: from numpy import int16 # needs numpy + sage: sum_of_k_squares(int16(2), int16(9634)) # needs numpy (15, 97) sage: from gmpy2 import mpz sage: sum_of_k_squares(mpz(2), mpz(9634)) @@ -5765,8 +5809,8 @@ def subfactorial(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: subfactorial(int8(8)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: subfactorial(int8(8)) # needs numpy 14833 sage: from gmpy2 import mpz sage: subfactorial(mpz(8)) @@ -5806,10 +5850,10 @@ def is_power_of_two(n): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: is_power_of_two(int8(16)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: is_power_of_two(int8(16)) # needs numpy True - sage: is_power_of_two(int8(24)) # optional - numpy + sage: is_power_of_two(int8(24)) # needs numpy False sage: from gmpy2 import mpz sage: is_power_of_two(mpz(16)) @@ -5826,7 +5870,7 @@ def differences(lis, n=1): EXAMPLES:: - sage: differences(prime_range(50)) # optional - sage.libs.pari + sage: differences(prime_range(50)) # needs sage.libs.pari [1, 2, 2, 4, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4] sage: differences([i^2 for i in range(1,11)]) [3, 5, 7, 9, 11, 13, 15, 17, 19] @@ -5834,13 +5878,13 @@ def differences(lis, n=1): [10, 22, 40, 64, 94, 130, 172, 220, 274, 334, 400, 472, 550, 634, 724, 820, 922, 1030, 1144] sage: differences([i^3 - i^2 for i in range(1,21)], 2) [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 100, 106, 112] - sage: differences([p - i^2 for i, p in enumerate(prime_range(50))], 3) # optional - sage.libs.pari + sage: differences([p - i^2 for i, p in enumerate(prime_range(50))], 3) # needs sage.libs.pari [-1, 2, -4, 4, -4, 4, 0, -6, 8, -6, 0, 4] Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: differences([int8(1), int8(4), int8(6), int8(19)]) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: differences([int8(1), int8(4), int8(6), int8(19)]) # needs numpy [3, 2, 13] sage: from gmpy2 import mpz sage: differences([mpz(1), mpz(4), mpz(6), mpz(19)]) @@ -5873,15 +5917,15 @@ def _key_complex_for_display(a): sage: import sage.arith.misc sage: key_c = sage.arith.misc._key_complex_for_display - sage: key_c(CC(5)) + sage: key_c(CC(5)) # needs sage.rings.real_mpfr (0, 5.00000000000000) - sage: key_c(CC(5, 5)) + sage: key_c(CC(5, 5)) # needs sage.rings.real_mpfr (1, 5.00000000, 5.00000000000000) - sage: CIF200 = ComplexIntervalField(200) - sage: key_c(CIF200(5)) + sage: CIF200 = ComplexIntervalField(200) # needs sage.rings.complex_interval_field + sage: key_c(CIF200(5)) # needs sage.rings.complex_interval_field (0, 5) - sage: key_c(CIF200(5, 5)) + sage: key_c(CIF200(5, 5)) # needs sage.rings.complex_interval_field (1, 5.00000000, 5) """ ar = a.real() @@ -5920,6 +5964,7 @@ def sort_complex_numbers_for_display(nums): EXAMPLES:: + sage: # needs sage.rings.complex_double sage: import sage.arith.misc sage: sort_c = sort_complex_numbers_for_display sage: nums = [CDF(i) for i in range(3)] @@ -5939,7 +5984,6 @@ def sort_complex_numbers_for_display(nums): sage: assert first_non_real >= 3 sage: for i in range(first_non_real - 1): ....: assert nums[i].real() <= nums[i + 1].real() - sage: def truncate(n): ....: if n.real() < 1e-10: ....: return 0 @@ -5985,8 +6029,8 @@ def fundamental_discriminant(D): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: fundamental_discriminant(int8(102)) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: fundamental_discriminant(int8(102)) # needs numpy 408 sage: from gmpy2 import mpz sage: fundamental_discriminant(mpz(102)) @@ -6043,8 +6087,8 @@ def squarefree_divisors(x): Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: list(squarefree_divisors(int8(12))) # optional - numpy + sage: from numpy import int8 # needs numpy + sage: list(squarefree_divisors(int8(12))) # needs numpy [1, 2, 3, 6] sage: from gmpy2 import mpz sage: list(squarefree_divisors(mpz(12))) @@ -6096,7 +6140,7 @@ def dedekind_sum(p, q, algorithm='default'): Several small values:: - sage: for q in range(10): print([dedekind_sum(p,q) for p in range(q+1)]) # optional - sage.libs.flint + sage: for q in range(10): print([dedekind_sum(p,q) for p in range(q+1)]) # needs sage.libs.flint [0] [0, 0] [0, 0, 0] @@ -6110,44 +6154,44 @@ def dedekind_sum(p, q, algorithm='default'): Check relations for restricted arguments:: - sage: q = 23; dedekind_sum(1, q); (q-1)*(q-2)/(12*q) # optional - sage.libs.flint + sage: q = 23; dedekind_sum(1, q); (q-1)*(q-2)/(12*q) # needs sage.libs.flint 77/46 77/46 sage: p, q = 100, 723 # must be coprime - sage: dedekind_sum(p, q) + dedekind_sum(q, p) # optional - sage.libs.flint + sage: dedekind_sum(p, q) + dedekind_sum(q, p) # needs sage.libs.flint 31583/86760 - sage: -1/4 + (p/q + q/p + 1/(p*q))/12 # optional - sage.libs.flint + sage: -1/4 + (p/q + q/p + 1/(p*q))/12 31583/86760 We check that evaluation works with large input:: - sage: dedekind_sum(3^54 - 1, 2^93 + 1) # optional - sage.libs.flint + sage: dedekind_sum(3^54 - 1, 2^93 + 1) # needs sage.libs.flint 459340694971839990630374299870/29710560942849126597578981379 - sage: dedekind_sum(3^54 - 1, 2^93 + 1, algorithm='pari') # optional - sage.libs.pari + sage: dedekind_sum(3^54 - 1, 2^93 + 1, algorithm='pari') # needs sage.libs.pari 459340694971839990630374299870/29710560942849126597578981379 We check consistency of the results:: - sage: dedekind_sum(5, 7, algorithm='default') # optional - sage.libs.flint + sage: dedekind_sum(5, 7, algorithm='default') # needs sage.libs.flint -1/14 - sage: dedekind_sum(5, 7, algorithm='flint') # optional - sage.libs.flint + sage: dedekind_sum(5, 7, algorithm='flint') # needs sage.libs.flint -1/14 - sage: dedekind_sum(5, 7, algorithm='pari') # optional - sage.libs.pari + sage: dedekind_sum(5, 7, algorithm='pari') # needs sage.libs.pari -1/14 - sage: dedekind_sum(6, 8, algorithm='default') # optional - sage.libs.flint + sage: dedekind_sum(6, 8, algorithm='default') # needs sage.libs.flint -1/8 - sage: dedekind_sum(6, 8, algorithm='flint') # optional - sage.libs.flint + sage: dedekind_sum(6, 8, algorithm='flint') # needs sage.libs.flint -1/8 - sage: dedekind_sum(6, 8, algorithm='pari') # optional - sage.libs.pari + sage: dedekind_sum(6, 8, algorithm='pari') # needs sage.libs.pari -1/8 Tests with numpy and gmpy2 numbers:: - sage: from numpy import int8 # optional - numpy - sage: dedekind_sum(int8(5), int8(7), algorithm='default') # optional - numpy sage.libs.flint + sage: from numpy import int8 # needs numpy + sage: dedekind_sum(int8(5), int8(7), algorithm='default') # needs numpy sage.libs.flint -1/14 sage: from gmpy2 import mpz - sage: dedekind_sum(mpz(5), mpz(7), algorithm='default') # optional - sage.libs.flint + sage: dedekind_sum(mpz(5), mpz(7), algorithm='default') # needs sage.libs.flint -1/14 REFERENCES: @@ -6205,46 +6249,50 @@ def gauss_sum(char_value, finite_field): EXAMPLES:: + sage: # needs sage.libs.pari sage.rings.number_field sage: from sage.arith.misc import gauss_sum - sage: F = GF(5); q = 5 # optional - sage.libs.pari - sage: zq = UniversalCyclotomicField().zeta(q - 1) # optional - sage.libs.pari - sage: L = [gauss_sum(zq**i, F) for i in range(5)]; L # optional - sage.libs.pari + sage: F = GF(5); q = 5 + sage: zq = UniversalCyclotomicField().zeta(q - 1) + sage: L = [gauss_sum(zq**i, F) for i in range(5)]; L [-1, E(20)^4 + E(20)^13 - E(20)^16 - E(20)^17, E(5) - E(5)^2 - E(5)^3 + E(5)^4, E(20)^4 - E(20)^13 - E(20)^16 + E(20)^17, -1] - sage: [g*g.conjugate() for g in L] # optional - sage.libs.pari + sage: [g*g.conjugate() for g in L] [1, 5, 5, 5, 1] - sage: F = GF(11**2); q = 11**2 # optional - sage.libs.pari - sage: zq = UniversalCyclotomicField().zeta(q - 1) # optional - sage.libs.pari - sage: g = gauss_sum(zq**4, F) # optional - sage.libs.pari - sage: g*g.conjugate() # optional - sage.libs.pari + sage: # needs sage.libs.pari sage.rings.number_field + sage: F = GF(11**2); q = 11**2 + sage: zq = UniversalCyclotomicField().zeta(q - 1) + sage: g = gauss_sum(zq**4, F) + sage: g*g.conjugate() 121 TESTS:: - sage: F = GF(11); q = 11 # optional - sage.libs.pari sage.rings.number_field - sage: zq = UniversalCyclotomicField().zeta(q - 1) # optional - sage.libs.pari sage.rings.number_field - sage: gauss_sum(zq**2, F).n(60) # optional - sage.libs.pari sage.rings.number_field + sage: # needs sage.libs.pari sage.rings.number_field + sage: F = GF(11); q = 11 + sage: zq = UniversalCyclotomicField().zeta(q - 1) + sage: gauss_sum(zq**2, F).n(60) 2.6361055643248352 + 2.0126965627574471*I - sage: zq = QQbar.zeta(q - 1) # optional - sage.libs.pari sage.rings.number_field - sage: gauss_sum(zq**2, F) # optional - sage.libs.pari sage.rings.number_field + sage: zq = QQbar.zeta(q - 1) # needs sage.libs.pari sage.rings.number_field + sage: gauss_sum(zq**2, F) # needs sage.libs.pari sage.rings.number_field 2.636105564324836? + 2.012696562757447?*I - sage: zq = ComplexField(60).zeta(q - 1) # optional - sage.libs.pari sage.rings.number_field - sage: gauss_sum(zq**2, F) # optional - sage.libs.pari sage.rings.number_field + sage: zq = ComplexField(60).zeta(q - 1) # needs sage.libs.pari sage.rings.number_field + sage: gauss_sum(zq**2, F) # needs sage.libs.pari sage.rings.number_field 2.6361055643248352 + 2.0126965627574471*I - sage: F = GF(7); q = 7 # optional - sage.libs.pari sage.rings.number_field - sage: zq = QQbar.zeta(q - 1) # optional - sage.libs.pari sage.rings.number_field - sage: D = DirichletGroup(7, QQbar) # optional - sage.libs.pari sage.rings.number_field - sage: all(D[i].gauss_sum() == gauss_sum(zq**i, F) for i in range(6)) # optional - sage.libs.pari sage.rings.number_field + sage: # needs sage.libs.pari sage.rings.number_field + sage: F = GF(7); q = 7 + sage: zq = QQbar.zeta(q - 1) + sage: D = DirichletGroup(7, QQbar) + sage: all(D[i].gauss_sum() == gauss_sum(zq**i, F) for i in range(6)) True - sage: gauss_sum(1, QQ) + sage: gauss_sum(1, QQ) # needs sage.libs.pari sage.rings.number_field Traceback (most recent call last): ... ValueError: second input must be a finite field diff --git a/src/sage/arith/multi_modular.pyx b/src/sage/arith/multi_modular.pyx index 83f9df2a7c7..a656742bd50 100644 --- a/src/sage/arith/multi_modular.pyx +++ b/src/sage/arith/multi_modular.pyx @@ -186,7 +186,7 @@ cdef class MultiModularBasis_base(): cdef mod_int _new_random_prime(self, set known_primes) except 1: """ Choose a new random prime for inclusion in the list of moduli, - or raise a ``RuntimeError`` if there are no more primes. + or raise a :class:`RuntimeError` if there are no more primes. INPUT: diff --git a/src/sage/arith/numerical_approx.pxd b/src/sage/arith/numerical_approx.pxd index b12750f3dc3..85f92eca336 100644 --- a/src/sage/arith/numerical_approx.pxd +++ b/src/sage/arith/numerical_approx.pxd @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.rings.real_mpfr + cpdef inline long digits_to_bits(d) except -1: """ EXAMPLES:: diff --git a/src/sage/arith/numerical_approx.pyx b/src/sage/arith/numerical_approx.pyx index 37a78833e61..6698a0ec317 100644 --- a/src/sage/arith/numerical_approx.pyx +++ b/src/sage/arith/numerical_approx.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.real_mpfr r""" Generic numerical approximation function """ @@ -28,7 +29,7 @@ def numerical_approx_generic(x, prec): EXAMPLES:: sage: from sage.arith.numerical_approx import numerical_approx_generic - sage: numerical_approx_generic(pi, 20) + sage: numerical_approx_generic(pi, 20) # needs sage.symbolic 3.1416 sage: numerical_approx_generic(int(42), 20) 42.000 diff --git a/src/sage/arith/rational_reconstruction.pyx b/src/sage/arith/rational_reconstruction.pyx index 8342f672cc2..4a669f977cb 100644 --- a/src/sage/arith/rational_reconstruction.pyx +++ b/src/sage/arith/rational_reconstruction.pyx @@ -34,8 +34,8 @@ cdef int mpq_rational_reconstruction(mpq_t answer, mpz_t a, mpz_t m) except -1: such that the numerator and denominator of the result is bounded by sqrt(m/2). - If `m` is zero, raise ``ZeroDivisionError``. If the rational - reconstruction does not exist, raise ``ValueError``. + If `m` is zero, raise :class`ZeroDivisionError`. If the rational + reconstruction does not exist, raise :class:`ValueError`. We assume that ``mpq_init`` has been called on ``answer``. diff --git a/src/sage/arith/srange.pyx b/src/sage/arith/srange.pyx index c21a43c0ee1..156e548a11a 100644 --- a/src/sage/arith/srange.pyx +++ b/src/sage/arith/srange.pyx @@ -244,8 +244,8 @@ def srange(*args, **kwds): [1.00000000000000] sage: srange(1.0, 1.0) [] - sage: V = VectorSpace(QQ, 2) - sage: srange(V([0,0]), V([5,5]), step=V([2,2])) + sage: V = VectorSpace(QQ, 2) # needs sage.modules + sage: srange(V([0,0]), V([5,5]), step=V([2,2])) # needs sage.modules [(0, 0), (2, 2), (4, 4)] Including the endpoint:: diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 34abf305f70..37807450ac0 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -429,7 +429,7 @@ from sage.misc.parser import Parser, LookupNameMaker from sage.structure.element import Expression from sage.symbolic.ring import var, SR -from sage.symbolic.expression import symbol_table +from sage.symbolic.symbols import symbol_table from sage.symbolic.function import Function from sage.symbolic.function_factory import function_factory from sage.symbolic.integration.integral import (indefinite_integral, diff --git a/src/sage/calculus/interpolation.pyx b/src/sage/calculus/interpolation.pyx index 21b82388461..83bc83d1797 100644 --- a/src/sage/calculus/interpolation.pyx +++ b/src/sage/calculus/interpolation.pyx @@ -135,7 +135,7 @@ cdef class Spline: if i < len(self.v): self.v[i] = xy else: - for j from len(self.v) <= j <= i: + for j in range(len(self.v), i + 1): self.v.append((0, 0)) self.v[i] = xy self.stop_interp() @@ -262,7 +262,7 @@ cdef class Spline: raise MemoryError cdef int i - for i from 0 <= i < n: + for i in range(n): self.x[i] = v[i][0] self.y[i] = v[i][1] diff --git a/src/sage/calculus/ode.pyx b/src/sage/calculus/ode.pyx index a7fbb87dffb..f1004b9b438 100644 --- a/src/sage/calculus/ode.pyx +++ b/src/sage/calculus/ode.pyx @@ -64,20 +64,20 @@ cdef int c_jac(double t,double *y,double *dfdy,double *dfdt,void *params): cdef int param_n cdef PyFunctionWrapper wrapper wrapper = params - y_n=wrapper.y_n - y_list=[] - for i from 0<=i params - y_n= wrapper.y_n - y_list=[] - for i from 0<=i sig_malloc(sizeof(double)*(dim)) - if y==NULL: + y = sig_malloc(sizeof(double)*(dim)) + if y == NULL: raise MemoryError("error allocating memory") - result=[] - v=[0]*dim + result = [] + v = [0]*dim cdef gsl_odeiv_step_type * T - for i from 0 <=i< dim: #copy initial conditions into C array - y[i]=self.y_0[i] + for i in range(dim): # copy initial conditions into C array + y[i] = self.y_0[i] if self.algorithm == "rkf45": T=gsl_odeiv_step_rkf45 @@ -502,9 +502,9 @@ class ode_solver(): if not self.scale_abs: c = gsl_odeiv_control_standard_new(self.error_abs,self.error_rel,self.a,self.a_dydt) elif hasattr(self.scale_abs,'__len__'): - if len(self.scale_abs)==dim: + if len(self.scale_abs) == dim: scale_abs_array = sig_malloc(dim*sizeof(double)) - for i from 0 <=i y[j] result.append( (t,copy.copy(v)) ) t = t_end @@ -579,9 +579,9 @@ class ode_solver(): else: n = len(self.t_span) - result.append((self.t_span[0],self.y_0)) - t=self.t_span[0] - for i from 0 0: v.append(point([(i, x)], hue=(1, 1, 1), **args)) diff --git a/src/sage/calculus/transforms/fft.pyx b/src/sage/calculus/transforms/fft.pyx index 168698957c4..363fa65a836 100644 --- a/src/sage/calculus/transforms/fft.pyx +++ b/src/sage/calculus/transforms/fft.pyx @@ -10,15 +10,15 @@ AUTHORS: - L.F. Tabera Alonso (2013-3): Documentation """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 William Stein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from cysignals.memory cimport sig_malloc, sig_free @@ -257,7 +257,7 @@ cdef class FastFourierTransform_complex(FastFourierTransform_base): I = I.n() s = 1/(3*pi) # so arg gets scaled between -1/3 and 1/3. - for i from xmin <= i < xmax: + for i in range(xmin, xmax): z = self.data[2*i] + I*self.data[2*i+1] mag = z.abs() arg = z.arg()*s diff --git a/src/sage/calculus/var.pyx b/src/sage/calculus/var.pyx index 070728253d6..84f7a16a91f 100644 --- a/src/sage/calculus/var.pyx +++ b/src/sage/calculus/var.pyx @@ -36,7 +36,7 @@ def var(*args, **kwds): If a single symbolic variable was created, the variable itself. Otherwise, a tuple of symbolic variables. The variable names are checked to be valid Python identifiers and a - ``ValueError`` is raised otherwise. + :class:`ValueError` is raised otherwise. EXAMPLES: diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 4637e239dce..b3244f766d4 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -333,28 +333,30 @@ cdef class InverseAction(Action): EXAMPLES:: - sage: V = QQ^3 # optional - sage.modules - sage: v = V((1, 2, 3)) # optional - sage.modules + sage: V = QQ^3 # needs sage.modules + sage: v = V((1, 2, 3)) # needs sage.modules sage: cm = get_coercion_model() - sage: a = cm.get_action(V, QQ, operator.mul) # optional - sage.modules - sage: a # optional - sage.modules + sage: # needs sage.modules + sage: a = cm.get_action(V, QQ, operator.mul) + sage: a Right scalar multiplication by Rational Field on Vector space of dimension 3 over Rational Field - sage: ~a # optional - sage.modules + sage: ~a Right inverse action by Rational Field on Vector space of dimension 3 over Rational Field - sage: (~a)(v, 1/3) # optional - sage.modules + sage: (~a)(v, 1/3) (3, 6, 9) - sage: b = cm.get_action(QQ, V, operator.mul) # optional - sage.modules - sage: b # optional - sage.modules + sage: # needs sage.modules + sage: b = cm.get_action(QQ, V, operator.mul) + sage: b Left scalar multiplication by Rational Field on Vector space of dimension 3 over Rational Field - sage: ~b # optional - sage.modules + sage: ~b Left inverse action by Rational Field on Vector space of dimension 3 over Rational Field - sage: (~b)(1/3, v) # optional - sage.modules + sage: (~b)(1/3, v) (3, 6, 9) sage: c = cm.get_action(ZZ, list, operator.mul) @@ -398,11 +400,12 @@ cdef class InverseAction(Action): Check that this action can be pickled (:trac:`29031`):: - sage: V = QQ^3 # optional - sage.modules - sage: v = V((1, 2, 3)) # optional - sage.modules - sage: cm = get_coercion_model() # optional - sage.modules - sage: a = cm.get_action(V, QQ, operator.mul) # optional - sage.modules - sage: loads(dumps(~a)) is not None # optional - sage.modules + sage: # needs sage.modules + sage: V = QQ^3 + sage: v = V((1, 2, 3)) + sage: cm = get_coercion_model() + sage: a = cm.get_action(V, QQ, operator.mul) + sage: loads(dumps(~a)) is not None True """ return (type(self), (self._action,)) @@ -432,16 +435,17 @@ cdef class PrecomposedAction(Action): We demonstrate that an example discussed on :trac:`14711` did not become a problem:: - sage: E = ModularSymbols(11).2 # optional - sage.modular - sage: s = E.modular_symbol_rep() # optional - sage.modular - sage: del E,s # optional - sage.modular - sage: import gc # optional - sage.modular - sage: _ = gc.collect() # optional - sage.modular - sage: E = ModularSymbols(11).2 # optional - sage.modular - sage: v = E.manin_symbol_rep() # optional - sage.modular - sage: c,x = v[0] # optional - sage.modular - sage: y = x.modular_symbol_rep() # optional - sage.modular - sage: coercion_model.get_action(QQ, parent(y), op=operator.mul) # optional - sage.modular + sage: # needs sage.modular + sage: E = ModularSymbols(11).2 + sage: s = E.modular_symbol_rep() + sage: del E,s + sage: import gc + sage: _ = gc.collect() + sage: E = ModularSymbols(11).2 + sage: v = E.manin_symbol_rep() + sage: c,x = v[0] + sage: y = x.modular_symbol_rep() + sage: coercion_model.get_action(QQ, parent(y), op=operator.mul) Left scalar multiplication by Rational Field on Abelian Group of all Formal Finite Sums over Rational Field with precomposition on right by Coercion map: @@ -483,12 +487,13 @@ cdef class PrecomposedAction(Action): Check that this action can be pickled (:trac:`29031`):: - sage: E = ModularSymbols(11).2 # optional - sage.modular - sage: v = E.manin_symbol_rep() # optional - sage.modular - sage: c,x = v[0] # optional - sage.modular - sage: y = x.modular_symbol_rep() # optional - sage.modular - sage: act = coercion_model.get_action(QQ, parent(y), op=operator.mul) # optional - sage.modular - sage: loads(dumps(act)) is not None # optional - sage.modular + sage: # needs sage.modular + sage: E = ModularSymbols(11).2 + sage: v = E.manin_symbol_rep() + sage: c,x = v[0] + sage: y = x.modular_symbol_rep() + sage: act = coercion_model.get_action(QQ, parent(y), op=operator.mul) + sage: loads(dumps(act)) is not None True """ return (type(self), (self._action, self.G_precomposition, self.S_precomposition)) diff --git a/src/sage/categories/additive_magmas.py b/src/sage/categories/additive_magmas.py index 3f688577aff..b39441fe84d 100644 --- a/src/sage/categories/additive_magmas.py +++ b/src/sage/categories/additive_magmas.py @@ -283,7 +283,7 @@ def addition_table(self, names='letters', elements=None): elements as lowercase ASCII letters. :: sage: R = IntegerModRing(5) - sage: R.addition_table() # optional - sage.modules + sage: R.addition_table() # needs sage.modules + a b c d e +---------- a| a b c d e @@ -298,7 +298,7 @@ def addition_table(self, names='letters', elements=None): ``digits`` will include leading zeros as padding. :: sage: R = IntegerModRing(11) - sage: P = R.addition_table(names='elements'); P # optional - sage.modules + sage: P = R.addition_table(names='elements'); P # needs sage.modules + 0 1 2 3 4 5 6 7 8 9 10 +--------------------------------- 0| 0 1 2 3 4 5 6 7 8 9 10 @@ -313,7 +313,7 @@ def addition_table(self, names='letters', elements=None): 9| 9 10 0 1 2 3 4 5 6 7 8 10| 10 0 1 2 3 4 5 6 7 8 9 - sage: T = R.addition_table(names='digits'); T # optional - sage.modules + sage: T = R.addition_table(names='digits'); T # needs sage.modules + 00 01 02 03 04 05 06 07 08 09 10 +--------------------------------- 00| 00 01 02 03 04 05 06 07 08 09 10 @@ -333,7 +333,7 @@ def addition_table(self, names='letters', elements=None): sage: S = IntegerModRing(7) sage: elts = [0, 3, 6, 2, 5, 1, 4] - sage: S.addition_table(elements=elts) # optional - sage.modules + sage: S.addition_table(elements=elts) # needs sage.modules + a b c d e f g +-------------- a| a b c d e f g @@ -354,7 +354,7 @@ def addition_table(self, names='letters', elements=None): sage: T = IntegerModRing(12) sage: elts = [0, 3, 6, 9] - sage: T.addition_table(names='elements', elements=elts) # optional - sage.modules + sage: T.addition_table(names='elements', elements=elts) # needs sage.modules + 0 3 6 9 +-------- 0| 0 3 6 9 @@ -367,16 +367,17 @@ def addition_table(self, names='letters', elements=None): :class:`~sage.matrix.operation_table.OperationTable` for more comprehensive documentation. :: + sage: # needs sage.modules sage: R = IntegerModRing(3) - sage: T = R.addition_table() # optional - sage.modules - sage: T.column_keys() # optional - sage.modules + sage: T = R.addition_table() + sage: T.column_keys() (0, 1, 2) - sage: sorted(T.translation().items()) # optional - sage.modules + sage: sorted(T.translation().items()) [('a', 0), ('b', 1), ('c', 2)] - sage: T.change_names(['x', 'y', 'z']) # optional - sage.modules - sage: sorted(T.translation().items()) # optional - sage.modules + sage: T.change_names(['x', 'y', 'z']) + sage: sorted(T.translation().items()) [('x', 0), ('y', 1), ('z', 2)] - sage: T # optional - sage.modules + sage: T + x y z +------ x| x y z @@ -473,16 +474,17 @@ def _add_(self, right): r""" EXAMPLES:: - sage: G5 = GF(5); G8 = GF(4, 'x'); GG = G5.cartesian_product(G8) # optional - sage.rings.finite_rings - sage: e = GG((G5(1), G8.primitive_element())); e # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: G5 = GF(5); G8 = GF(4, 'x'); GG = G5.cartesian_product(G8) + sage: e = GG((G5(1), G8.primitive_element())); e (1, x) - sage: e + e # optional - sage.rings.finite_rings + sage: e + e (2, 0) - sage: e = groups.misc.AdditiveCyclic(8) # optional - sage.rings.finite_rings - sage: x = e.cartesian_product(e)((e(1), e(2))) # optional - sage.rings.finite_rings - sage: x # optional - sage.rings.finite_rings + sage: e = groups.misc.AdditiveCyclic(8) # needs sage.groups + sage: x = e.cartesian_product(e)((e(1), e(2))) + sage: x (1, 2) - sage: 4 * x # optional - sage.rings.finite_rings + sage: 4 * x (4, 0) """ return self.parent()._cartesian_product_of_elements( @@ -521,8 +523,8 @@ def algebra_generators(self): sage: S = CommutativeAdditiveSemigroups().example(); S An example of a commutative semigroup: the free commutative semigroup generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(QQ) # optional - sage.modules - sage: A.algebra_generators() # optional - sage.modules + sage: A = S.algebra(QQ) # needs sage.modules + sage: A.algebra_generators() # needs sage.modules Family (B[a], B[b], B[c], B[d]) .. TODO:: @@ -547,9 +549,9 @@ def product_on_basis(self, g1, g2): sage: S = CommutativeAdditiveSemigroups().example(); S An example of a commutative semigroup: the free commutative semigroup generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(QQ) # optional - sage.modules - sage: a, b, c, d = A.algebra_generators() # optional - sage.modules - sage: a * d * b # optional - sage.modules + sage: A = S.algebra(QQ) # needs sage.modules + sage: a, b, c, d = A.algebra_generators() # needs sage.modules + sage: a * d * b # needs sage.modules B[a + b + d] .. TODO:: @@ -724,10 +726,11 @@ def is_empty(self): EXAMPLES:: - sage: A = AdditiveAbelianGroup([3, 3]) # optional - sage.groups - sage: A in AdditiveMagmas() # optional - sage.groups + sage: # needs sage.modules + sage: A = AdditiveAbelianGroup([3, 3]) + sage: A in AdditiveMagmas() True - sage: A.is_empty() # optional - sage.groups + sage: A.is_empty() False sage: B = CommutativeAdditiveMonoids().example() @@ -739,7 +742,7 @@ def is_empty(self): We check that the method ``is_empty`` is inherited from this category in both examples above:: - sage: A.is_empty.__module__ # optional - sage.groups + sage: A.is_empty.__module__ # needs sage.modules 'sage.categories.additive_magmas' sage: B.is_empty.__module__ 'sage.categories.additive_magmas' @@ -807,17 +810,17 @@ def _sub_(left, right): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a', 'b']) # optional - sage.modules - sage: a, b = F.basis() # optional - sage.modules - sage: a - b # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a', 'b']) # needs sage.modules + sage: a, b = F.basis() # needs sage.modules + sage: a - b # needs sage.modules B['a'] - B['b'] TESTS: Check that :trac:`18275` is fixed:: - sage: C = GF(5).cartesian_product(GF(5)) # optional - sage.rings.finite_rings - sage: C.one() - C.one() # optional - sage.rings.finite_rings + sage: C = GF(5).cartesian_product(GF(5)) + sage: C.one() - C.one() (0, 0) """ return left + (-right) @@ -833,21 +836,22 @@ def __neg__(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a', 'b']) # optional - sage.modules - sage: a, b = F.basis() # optional - sage.modules - sage: -b # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a', 'b']) # needs sage.modules + sage: a, b = F.basis() # needs sage.modules + sage: -b # needs sage.modules -B['b'] TESTS:: - sage: F = CombinatorialFreeModule(ZZ, ['a', 'b']) # optional - sage.modules - sage: a, b = F.gens() # optional - sage.modules - sage: FF = cartesian_product((F, F)) # optional - sage.modules - sage: x = cartesian_product([a, 2*a-3*b]); x # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(ZZ, ['a', 'b']) + sage: a, b = F.gens() + sage: FF = cartesian_product((F, F)) + sage: x = cartesian_product([a, 2*a-3*b]); x B[(0, 'a')] + 2*B[(1, 'a')] - 3*B[(1, 'b')] - sage: x.parent() is FF # optional - sage.modules + sage: x.parent() is FF True - sage: -x # optional - sage.modules + sage: -x -B[(0, 'a')] - 2*B[(1, 'a')] + 3*B[(1, 'b')] """ return self._neg_() @@ -917,15 +921,15 @@ def _neg_(self): EXAMPLES:: - sage: x = cartesian_product((GF(7)(2), 17)); x # optional - sage.rings.finite_rings + sage: x = cartesian_product((GF(7)(2), 17)); x (2, 17) - sage: -x # optional - sage.rings.finite_rings + sage: -x (5, -17) TESTS:: sage: C = AdditiveMagmas().AdditiveUnital().AdditiveInverse().CartesianProducts() - sage: x.parent() in C # optional - sage.rings.finite_rings + sage: x.parent() in C True """ return self.parent()._cartesian_product_of_elements( @@ -954,7 +958,7 @@ def zero(self): EXAMPLES:: - sage: GF(8, 'x').cartesian_product(GF(5)).zero() # optional - sage.rings.finite_rings + sage: GF(8, 'x').cartesian_product(GF(5)).zero() # needs sage.rings.finite_rings (0, 0) """ return self._cartesian_product_of_elements( @@ -989,15 +993,16 @@ def one_basis(self): EXAMPLES:: + sage: # needs sage.modules sage: S = CommutativeAdditiveMonoids().example(); S An example of a commutative monoid: the free commutative monoid generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(ZZ) # optional - sage.modules - sage: A.one_basis() # optional - sage.modules + sage: A = S.algebra(ZZ) + sage: A.one_basis() 0 - sage: A.one() # optional - sage.modules + sage: A.one() B[0] - sage: A(3) # optional - sage.modules + sage: A(3) 3*B[0] """ return self.basis().keys().zero() @@ -1016,17 +1021,17 @@ def zero(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.zero.__module__ # optional - sage.combinat + sage: A.zero.__module__ # needs sage.modules 'sage.categories.additive_magmas' - sage: A.zero() # optional - sage.combinat + sage: A.zero() # needs sage.modules 0 TESTS:: - sage: A.zero() is A.a_realization().zero() # optional - sage.combinat + sage: A.zero() is A.a_realization().zero() # needs sage.modules True - sage: A._test_zero() # optional - sage.combinat + sage: A._test_zero() # needs sage.modules """ return self.a_realization().zero() diff --git a/src/sage/categories/additive_semigroups.py b/src/sage/categories/additive_semigroups.py index 667e27eb1e9..038221fe5be 100644 --- a/src/sage/categories/additive_semigroups.py +++ b/src/sage/categories/additive_semigroups.py @@ -152,8 +152,8 @@ def algebra_generators(self): sage: S = CommutativeAdditiveSemigroups().example(); S An example of a commutative semigroup: the free commutative semigroup generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(QQ) # optional - sage.modules - sage: A.algebra_generators() # optional - sage.modules + sage: A = S.algebra(QQ) # needs sage.modules + sage: A.algebra_generators() # needs sage.modules Family (B[a], B[b], B[c], B[d]) """ return self.basis().keys().additive_semigroup_generators().map(self.monomial) @@ -172,9 +172,9 @@ def product_on_basis(self, g1, g2): sage: S = CommutativeAdditiveSemigroups().example(); S An example of a commutative semigroup: the free commutative semigroup generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(QQ) # optional - sage.modules - sage: a, b, c, d = A.algebra_generators() # optional - sage.modules - sage: b * d * c # optional - sage.modules + sage: A = S.algebra(QQ) # needs sage.modules + sage: a, b, c, d = A.algebra_generators() # needs sage.modules + sage: b * d * c # needs sage.modules B[b + c + d] """ return self.monomial(g1 + g2) diff --git a/src/sage/categories/affine_weyl_groups.py b/src/sage/categories/affine_weyl_groups.py index 3df85b07415..4eeea88b6c3 100644 --- a/src/sage/categories/affine_weyl_groups.py +++ b/src/sage/categories/affine_weyl_groups.py @@ -34,9 +34,9 @@ class AffineWeylGroups(Category_singleton): sage: C.example() NotImplemented - sage: W = WeylGroup(["A", 4, 1]); W # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 4, 1]); W # needs sage.combinat sage.groups Weyl Group of type ['A', 4, 1] (as a matrix group acting on the root space) - sage: W.category() # optional - sage.combinat sage.groups + sage: W.category() # needs sage.combinat sage.groups Category of irreducible affine weyl groups TESTS:: @@ -81,8 +81,8 @@ def special_node(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3, 1]) # optional - sage.combinat sage.groups - sage: W.special_node() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3, 1]) # needs sage.combinat sage.groups + sage: W.special_node() # needs sage.combinat sage.groups 0 """ return self.cartan_type().special_node() @@ -95,8 +95,8 @@ def affine_grassmannian_elements_of_given_length(self, k): EXAMPLES:: - sage: W = WeylGroup(['A', 3, 1]) # optional - sage.combinat sage.groups - sage: [x.reduced_word() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3, 1]) # needs sage.combinat sage.groups + sage: [x.reduced_word() # needs sage.combinat sage.groups ....: for x in W.affine_grassmannian_elements_of_given_length(3)] [[2, 1, 0], [3, 1, 0], [2, 3, 0]] @@ -137,14 +137,15 @@ def is_affine_grassmannian(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3, 1]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([2,1,0]) # optional - sage.combinat sage.groups - sage: w.is_affine_grassmannian() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 3, 1]) + sage: w = W.from_reduced_word([2,1,0]) + sage: w.is_affine_grassmannian() True - sage: w = W.from_reduced_word([2,0]) # optional - sage.combinat sage.groups - sage: w.is_affine_grassmannian() # optional - sage.combinat sage.groups + sage: w = W.from_reduced_word([2,0]) + sage: w.is_affine_grassmannian() False - sage: W.one().is_affine_grassmannian() # optional - sage.combinat sage.groups + sage: W.one().is_affine_grassmannian() True """ D = self.descents() @@ -169,17 +170,18 @@ def affine_grassmannian_to_core(self): EXAMPLES:: - sage: W = WeylGroup(['A', 2, 1]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([0,2,1,0]) # optional - sage.combinat sage.groups - sage: la = w.affine_grassmannian_to_core(); la # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 2, 1]) + sage: w = W.from_reduced_word([0,2,1,0]) + sage: la = w.affine_grassmannian_to_core(); la [4, 2] - sage: type(la) # optional - sage.combinat sage.groups + sage: type(la) - sage: la.to_grassmannian() == w # optional - sage.combinat sage.groups + sage: la.to_grassmannian() == w True - sage: w = W.from_reduced_word([0,2,1]) # optional - sage.combinat sage.groups - sage: w.affine_grassmannian_to_core() # optional - sage.combinat sage.groups + sage: w = W.from_reduced_word([0,2,1]) # needs sage.combinat sage.groups + sage: w.affine_grassmannian_to_core() # needs sage.combinat sage.groups Traceback (most recent call last): ... ValueError: this only works on type 'A' affine Grassmannian elements @@ -214,12 +216,13 @@ def affine_grassmannian_to_partition(self): EXAMPLES:: + sage: # needs sage.combinat sage.groups sage: k = 2 - sage: W = WeylGroup(['A', k, 1]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([0,2,1,0]) # optional - sage.combinat sage.groups - sage: la = w.affine_grassmannian_to_partition(); la # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', k, 1]) + sage: w = W.from_reduced_word([0,2,1,0]) + sage: la = w.affine_grassmannian_to_partition(); la [2, 2] - sage: la.from_kbounded_to_grassmannian(k) == w # optional - sage.combinat sage.groups + sage: la.from_kbounded_to_grassmannian(k) == w True """ return self.affine_grassmannian_to_core().to_bounded_partition() diff --git a/src/sage/categories/algebra_functor.py b/src/sage/categories/algebra_functor.py index 9142a9b6e38..dd56f26895f 100644 --- a/src/sage/categories/algebra_functor.py +++ b/src/sage/categories/algebra_functor.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups +# sage.doctest: needs sage.groups r""" Group algebras and beyond: the Algebra functorial construction diff --git a/src/sage/categories/algebra_ideals.py b/src/sage/categories/algebra_ideals.py index 3bea4f66f91..1d6e3775e7b 100644 --- a/src/sage/categories/algebra_ideals.py +++ b/src/sage/categories/algebra_ideals.py @@ -81,8 +81,8 @@ def super_categories(self): sage: AlgebraIdeals(QQ['x']).super_categories() [Category of algebra modules over Univariate Polynomial Ring in x over Rational Field] - sage: C = AlgebraIdeals(FreeAlgebra(QQ, 2, 'a,b')) # optional - sage.combinat sage.modules - sage: C.super_categories() # optional - sage.combinat sage.modules + sage: C = AlgebraIdeals(FreeAlgebra(QQ, 2, 'a,b')) # needs sage.combinat sage.modules + sage: C.super_categories() # needs sage.combinat sage.modules [] """ diff --git a/src/sage/categories/algebra_modules.py b/src/sage/categories/algebra_modules.py index 086b834f955..7be7de2c471 100644 --- a/src/sage/categories/algebra_modules.py +++ b/src/sage/categories/algebra_modules.py @@ -39,7 +39,7 @@ def __init__(self, A): sage: AlgebraModules(QQ['a']) Category of algebra modules over Univariate Polynomial Ring in a over Rational Field sage: AlgebraModules(QQ['a,b']) # todo: not implemented (QQ['a,b'] should be in Algebras(QQ)) - sage: AlgebraModules(FreeAlgebra(QQ, 2, 'a,b')) # optional - sage.combinat sage.modules + sage: AlgebraModules(FreeAlgebra(QQ, 2, 'a,b')) # needs sage.combinat sage.modules Traceback (most recent call last): ... TypeError: A (=Free Algebra on 2 generators (a, b) over Rational Field) must be a commutative algebra diff --git a/src/sage/categories/algebras.py b/src/sage/categories/algebras.py index 3b808b5d1b7..d93a51d28bd 100644 --- a/src/sage/categories/algebras.py +++ b/src/sage/categories/algebras.py @@ -68,9 +68,9 @@ def __contains__(self, x): sage: QQ['x'] in Algebras(QQ) True - sage: QQ^3 in Algebras(QQ) # optional - sage.modules + sage: QQ^3 in Algebras(QQ) # needs sage.modules False - sage: QQ['x'] in Algebras(CDF) + sage: QQ['x'] in Algebras(CDF) # needs sage.rings.complex_double False """ if super().__contains__(x): @@ -154,15 +154,15 @@ def _div_(self, y): EXAMPLES:: - sage: C = AlgebrasWithBasis(QQ).example() # optional - sage.combinat - sage: x = C(2); x # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: C = AlgebrasWithBasis(QQ).example() + sage: x = C(2); x 2*B[word: ] - sage: y = C.algebra_generators().first(); y # optional - sage.combinat + sage: y = C.algebra_generators().first(); y B[word: a] - - sage: y._div_(x) # optional - sage.combinat + sage: y._div_(x) 1/2*B[word: a] - sage: x._div_(y) # optional - sage.combinat + sage: x._div_(y) Traceback (most recent call last): ... ValueError: cannot invert self (= B[word: a]) @@ -182,6 +182,7 @@ def algebra_generators(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -215,9 +216,8 @@ def extra_super_categories(self): sage: C.extra_super_categories() [Category of algebras over Rational Field] sage: sorted(C.super_categories(), key=str) - [Category of Cartesian products of distributive magmas and additive magmas, - Category of Cartesian products of monoids, - Category of Cartesian products of vector spaces over Rational Field, + [Category of Cartesian products of monoids, + Category of Cartesian products of unital algebras over Rational Field, Category of algebras over Rational Field] """ return [self.base_category()] diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index e7762b50f24..28177a1ff45 100644 --- a/src/sage/categories/algebras_with_basis.py +++ b/src/sage/categories/algebras_with_basis.py @@ -33,37 +33,37 @@ class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring): We construct a typical parent in this category, and do some computations with it:: - sage: A = C.example(); A # optional - sage.combinat + sage: A = C.example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: A.category() # optional - sage.combinat + sage: A.category() # needs sage.combinat sage.modules Category of algebras with basis over Rational Field - sage: A.one_basis() # optional - sage.combinat + sage: A.one_basis() # needs sage.combinat sage.modules word: - sage: A.one() # optional - sage.combinat + sage: A.one() # needs sage.combinat sage.modules B[word: ] - sage: A.base_ring() # optional - sage.combinat + sage: A.base_ring() # needs sage.combinat sage.modules Rational Field - sage: A.basis().keys() # optional - sage.combinat + sage: A.basis().keys() # needs sage.combinat sage.modules Finite words over {'a', 'b', 'c'} - sage: (a,b,c) = A.algebra_generators() # optional - sage.combinat - sage: a^3, b^2 # optional - sage.combinat + sage: (a,b,c) = A.algebra_generators() # needs sage.combinat sage.modules + sage: a^3, b^2 # needs sage.combinat sage.modules (B[word: aaa], B[word: bb]) - sage: a * c * b # optional - sage.combinat + sage: a * c * b # needs sage.combinat sage.modules B[word: acb] - sage: A.product # optional - sage.combinat + sage: A.product # needs sage.combinat sage.modules - sage: A.product(a * b, b) # optional - sage.combinat + sage: A.product(a * b, b) # needs sage.combinat sage.modules B[word: abb] - sage: TestSuite(A).run(verbose=True) # optional - sage.combinat + sage: TestSuite(A).run(verbose=True) # needs sage.combinat sage.modules running ._test_additive_associativity() . . . pass running ._test_an_element() . . . pass running ._test_associativity() . . . pass @@ -93,9 +93,9 @@ class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring): running ._test_prod() . . . pass running ._test_some_elements() . . . pass running ._test_zero() . . . pass - sage: A.__class__ # optional - sage.combinat + sage: A.__class__ # needs sage.combinat sage.modules - sage: A.element_class # optional - sage.combinat + sage: A.element_class # needs sage.combinat sage.modules Please see the source code of `A` (with ``A??``) for how to @@ -112,13 +112,13 @@ def example(self, alphabet=('a','b','c')): EXAMPLES:: - sage: AlgebrasWithBasis(QQ).example() # optional - sage.combinat + sage: AlgebrasWithBasis(QQ).example() # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field An other set of generators can be specified as optional argument:: - sage: AlgebrasWithBasis(QQ).example((1,2,3)) # optional - sage.combinat + sage: AlgebrasWithBasis(QQ).example((1,2,3)) # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators (1, 2, 3) over Rational Field """ @@ -147,12 +147,12 @@ def hochschild_complex(self, M): EXAMPLES:: sage: R. = QQ[] - sage: A = algebras.DifferentialWeyl(R) # optional - sage.combinat - sage: H = A.hochschild_complex(A) # optional - sage.combinat + sage: A = algebras.DifferentialWeyl(R) # needs sage.modules + sage: H = A.hochschild_complex(A) # needs sage.modules - sage: SGA = SymmetricGroupAlgebra(QQ, 3) # optional - sage.combinat - sage: T = SGA.trivial_representation() # optional - sage.combinat - sage: H = SGA.hochschild_complex(T) # optional - sage.combinat + sage: SGA = SymmetricGroupAlgebra(QQ, 3) # needs sage.combinat sage.modules + sage: T = SGA.trivial_representation() # needs sage.combinat sage.modules + sage: H = SGA.hochschild_complex(T) # needs sage.combinat sage.modules """ from sage.homology.hochschild_complex import HochschildComplex return HochschildComplex(self, M) @@ -180,14 +180,15 @@ def __invert__(self): EXAMPLES:: - sage: C = AlgebrasWithBasis(QQ).example() # optional - sage.combinat - sage: x = C(2); x # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: C = AlgebrasWithBasis(QQ).example() + sage: x = C(2); x 2*B[word: ] - sage: ~x # optional - sage.combinat + sage: ~x 1/2*B[word: ] - sage: a = C.algebra_generators().first(); a # optional - sage.combinat + sage: a = C.algebra_generators().first(); a B[word: a] - sage: ~a # optional - sage.combinat + sage: ~a Traceback (most recent call last): ... ValueError: cannot invert self (= B[word: a]) @@ -230,7 +231,8 @@ class ParentMethods: @cached_method def one_from_cartesian_product_of_one_basis(self): """ - Returns the one of this Cartesian product of algebras, as per ``Monoids.ParentMethods.one`` + Return the one of this Cartesian product of algebras, as per + ``Monoids.ParentMethods.one`` It is constructed as the Cartesian product of the ones of the summands, using their :meth:`~AlgebrasWithBasis.ParentMethods.one_basis` methods. @@ -241,19 +243,19 @@ def one_from_cartesian_product_of_one_basis(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: A.one_basis() # optional - sage.combinat + sage: A.one_basis() # needs sage.combinat sage.modules word: - sage: B = cartesian_product((A, A, A)) # optional - sage.combinat - sage: B.one_from_cartesian_product_of_one_basis() # optional - sage.combinat + sage: B = cartesian_product((A, A, A)) # needs sage.combinat sage.modules + sage: B.one_from_cartesian_product_of_one_basis() # needs sage.combinat sage.modules B[(0, word: )] + B[(1, word: )] + B[(2, word: )] - sage: B.one() # optional - sage.combinat + sage: B.one() # needs sage.combinat sage.modules B[(0, word: )] + B[(1, word: )] + B[(2, word: )] - sage: cartesian_product([SymmetricGroupAlgebra(QQ, 3), # optional - sage.combinat + sage: cartesian_product([SymmetricGroupAlgebra(QQ, 3), # needs sage.combinat sage.modules ....: SymmetricGroupAlgebra(QQ, 4)]).one() B[(0, [1, 2, 3])] + B[(1, [1, 2, 3, 4])] """ @@ -264,17 +266,18 @@ def one(self): """ TESTS:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: B = cartesian_product((A, A, A)) # optional - sage.combinat - sage: B.one() # optional - sage.combinat + sage: B = cartesian_product((A, A, A)) # needs sage.combinat sage.modules + sage: B.one() # needs sage.combinat sage.modules B[(0, word: )] + B[(1, word: )] + B[(2, word: )] """ - if all(hasattr(module, "one_basis") for module in self._sets): + if all(hasattr(module, "one_basis") and module.one_basis is not NotImplemented for module in self._sets): return self.one_from_cartesian_product_of_one_basis - else: - return NotImplemented + return self._one_generic + + _one_generic = UnitalAlgebras.CartesianProducts.ParentMethods.one # def product_on_basis(self, t1, t2): # would be easy to implement, but without a special @@ -317,15 +320,16 @@ def one_basis(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example(); A An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: A.one_basis() # optional - sage.combinat + sage: A.one_basis() word: - sage: B = tensor((A, A, A)) # optional - sage.combinat - sage: B.one_basis() # optional - sage.combinat + sage: B = tensor((A, A, A)) + sage: B.one_basis() (word: , word: , word: ) - sage: B.one() # optional - sage.combinat + sage: B.one() B[word: ] # B[word: ] # B[word: ] """ # FIXME: this method should be conditionally defined, @@ -343,23 +347,23 @@ def product_on_basis(self, t1, t2): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: (a,b,c) = A.algebra_generators() # optional - sage.combinat + sage: (a,b,c) = A.algebra_generators() # needs sage.combinat sage.modules - sage: x = tensor((a, b, c)); x # optional - sage.combinat + sage: x = tensor((a, b, c)); x # needs sage.combinat sage.modules B[word: a] # B[word: b] # B[word: c] - sage: y = tensor((c, b, a)); y # optional - sage.combinat + sage: y = tensor((c, b, a)); y # needs sage.combinat sage.modules B[word: c] # B[word: b] # B[word: a] - sage: x * y # optional - sage.combinat + sage: x * y # needs sage.combinat sage.modules B[word: ac] # B[word: bb] # B[word: ca] - sage: x = tensor(((a + 2*b), c)); x # optional - sage.combinat + sage: x = tensor(((a + 2*b), c)); x # needs sage.combinat sage.modules B[word: a] # B[word: c] + 2*B[word: b] # B[word: c] - sage: y = tensor((c, a)) + 1; y # optional - sage.combinat + sage: y = tensor((c, a)) + 1; y # needs sage.combinat sage.modules B[word: ] # B[word: ] + B[word: c] # B[word: a] - sage: x * y # optional - sage.combinat + sage: x * y # needs sage.combinat sage.modules B[word: a] # B[word: c] + B[word: ac] # B[word: ca] + 2*B[word: b] # B[word: c] + 2*B[word: bc] # B[word: ca] diff --git a/src/sage/categories/bialgebras.py b/src/sage/categories/bialgebras.py index fa6a7a1a507..b927766568b 100644 --- a/src/sage/categories/bialgebras.py +++ b/src/sage/categories/bialgebras.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat +# sage.doctest: needs sage.combinat r""" Bialgebras """ @@ -69,6 +69,7 @@ def is_primitive(self): EXAMPLES:: + sage: # needs sage.modules sage: s = SymmetricFunctions(QQ).schur() sage: s([5]).is_primitive() False @@ -85,10 +86,10 @@ def is_grouplike(self): EXAMPLES:: - sage: s = SymmetricFunctions(QQ).schur() - sage: s([5]).is_grouplike() + sage: s = SymmetricFunctions(QQ).schur() # needs sage.modules + sage: s([5]).is_grouplike() # needs sage.modules False - sage: s([]).is_grouplike() + sage: s([]).is_grouplike() # needs sage.modules True """ return self.coproduct() == self.tensor(self) diff --git a/src/sage/categories/bialgebras_with_basis.py b/src/sage/categories/bialgebras_with_basis.py index 067d0b35b8e..36dd5fccf2a 100644 --- a/src/sage/categories/bialgebras_with_basis.py +++ b/src/sage/categories/bialgebras_with_basis.py @@ -92,24 +92,25 @@ def convolution_product(self, *maps): with the projection ``Proj2`` on the Hopf algebra of non-commutative symmetric functions:: - sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon() # optional - sage.combinat - sage: T = R.convolution_product([Id, Id]) # optional - sage.combinat - sage: [T(R(comp)) for comp in Compositions(3)] # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon() + sage: T = R.convolution_product([Id, Id]) + sage: [T(R(comp)) for comp in Compositions(3)] [4*R[1, 1, 1] + R[1, 2] + R[2, 1], 2*R[1, 1, 1] + 4*R[1, 2] + 2*R[2, 1] + 2*R[3], 2*R[1, 1, 1] + 2*R[1, 2] + 4*R[2, 1] + 2*R[3], R[1, 2] + R[2, 1] + 4*R[3]] - sage: T = R.convolution_product(Proj2, Id) # optional - sage.combinat - sage: [T(R([i])) for i in range(1, 5)] # optional - sage.combinat + sage: T = R.convolution_product(Proj2, Id) + sage: [T(R([i])) for i in range(1, 5)] [0, R[2], R[2, 1] + R[3], R[2, 2] + R[4]] Compute the convolution product of no maps on the Hopf algebra of symmetric functions in non-commuting variables. This is the composition of the counit with the unit:: - sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # optional - sage.combinat - sage: T = m.convolution_product() # optional - sage.combinat - sage: [T(m(lam)) # optional - sage.combinat + sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # needs sage.combinat sage.modules + sage: T = m.convolution_product() # needs sage.combinat sage.modules + sage: [T(m(lam)) # needs sage.combinat sage.modules ....: for lam in SetPartitions(0).list() + SetPartitions(2).list()] [m{}, 0, 0] @@ -117,8 +118,8 @@ def convolution_product(self, *maps): the identity on the Hopf algebra of symmetric functions in non-commuting variables:: - sage: T = m.convolution_product(Proj2, Id) # optional - sage.combinat - sage: [T(m(lam)) for lam in SetPartitions(3)] # optional - sage.combinat + sage: T = m.convolution_product(Proj2, Id) # needs sage.combinat sage.modules + sage: [T(m(lam)) for lam in SetPartitions(3)] # needs sage.combinat sage.modules [0, m{{1, 2}, {3}} + m{{1, 2, 3}}, m{{1, 2}, {3}} + m{{1, 2, 3}}, @@ -128,15 +129,16 @@ def convolution_product(self, *maps): Compute the convolution product of the antipode with itself and the identity map on group algebra of the symmetric group:: - sage: G = SymmetricGroup(3) # optional - sage.groups sage.combinat - sage: QG = GroupAlgebra(G, QQ) # optional - sage.groups sage.combinat - sage: x = QG.sum_of_terms( # optional - sage.groups sage.combinat + sage: # needs sage.combinat sage.groups + sage: G = SymmetricGroup(3) + sage: QG = GroupAlgebra(G, QQ) + sage: x = QG.sum_of_terms( ....: [(p, p.number_of_peaks() + p.number_of_inversions()) ....: for p in Permutations(3)] ....: ); x 2*[1, 3, 2] + [2, 1, 3] + 3*[2, 3, 1] + 2*[3, 1, 2] + 3*[3, 2, 1] - sage: T = QG.convolution_product(Antipode, Antipode, Id) # optional - sage.groups sage.combinat - sage: T(x) # optional - sage.groups sage.combinat + sage: T = QG.convolution_product(Antipode, Antipode, Id) + sage: T(x) 2*[1, 3, 2] + [2, 1, 3] + 2*[2, 3, 1] + 3*[3, 1, 2] + 3*[3, 2, 1] """ onbasis = lambda x: self.term(x).convolution_product(*maps) @@ -172,32 +174,33 @@ def adams_operator(self, n): EXAMPLES:: - sage: h = SymmetricFunctions(QQ).h() # optional - sage.combinat - sage: h[5].adams_operator(2) # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: h = SymmetricFunctions(QQ).h() + sage: h[5].adams_operator(2) 2*h[3, 2] + 2*h[4, 1] + 2*h[5] - sage: h[5].plethysm(2*h[1]) # optional - sage.combinat + sage: h[5].plethysm(2*h[1]) 2*h[3, 2] + 2*h[4, 1] + 2*h[5] - sage: h([]).adams_operator(0) # optional - sage.combinat + sage: h([]).adams_operator(0) h[] - sage: h([]).adams_operator(1) # optional - sage.combinat + sage: h([]).adams_operator(1) h[] - sage: h[3,2].adams_operator(0) # optional - sage.combinat + sage: h[3,2].adams_operator(0) 0 - sage: h[3,2].adams_operator(1) # optional - sage.combinat + sage: h[3,2].adams_operator(1) h[3, 2] :: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat - sage: S[4].adams_operator(5) # optional - sage.combinat + sage: S = NonCommutativeSymmetricFunctions(QQ).S() # needs sage.combinat sage.modules + sage: S[4].adams_operator(5) # needs sage.combinat sage.modules 5*S[1, 1, 1, 1] + 10*S[1, 1, 2] + 10*S[1, 2, 1] + 10*S[1, 3] + 10*S[2, 1, 1] + 10*S[2, 2] + 10*S[3, 1] + 5*S[4] :: - sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # optional - sage.combinat - sage: m[[1,3],[2]].adams_operator(-2) # optional - sage.combinat + sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # needs sage.combinat sage.modules + sage: m[[1,3],[2]].adams_operator(-2) # needs sage.combinat sage.modules 3*m{{1}, {2, 3}} + 3*m{{1, 2}, {3}} + 6*m{{1, 2, 3}} - 2*m{{1, 3}, {2}} """ if n < 0: @@ -259,18 +262,18 @@ def convolution_product(self, *maps): sage: Id = lambda x: x sage: Antipode = lambda x: x.antipode() - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat - sage: s[3].convolution_product(Id, Id) # optional - sage.combinat + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: s[3].convolution_product(Id, Id) # needs sage.combinat sage.modules 2*s[2, 1] + 4*s[3] - sage: s[3,2].convolution_product(Id) == s[3,2] # optional - sage.combinat + sage: s[3,2].convolution_product(Id) == s[3,2] # needs sage.combinat sage.modules True The method accepts multiple arguments, or a single argument consisting of a list of maps:: - sage: s[3,2].convolution_product(Id, Id) # optional - sage.combinat + sage: s[3,2].convolution_product(Id, Id) # needs sage.combinat sage.modules 2*s[2, 1, 1, 1] + 6*s[2, 2, 1] + 6*s[3, 1, 1] + 12*s[3, 2] + 6*s[4, 1] + 2*s[5] - sage: s[3,2].convolution_product([Id, Id]) # optional - sage.combinat + sage: s[3,2].convolution_product([Id, Id]) # needs sage.combinat sage.modules 2*s[2, 1, 1, 1] + 6*s[2, 2, 1] + 6*s[3, 1, 1] + 12*s[3, 2] + 6*s[4, 1] + 2*s[5] We test the defining property of the antipode morphism; namely, @@ -278,31 +281,32 @@ def convolution_product(self, *maps): convolution algebra whose identity element is the composition of the counit and unit:: - sage: (s[3,2].convolution_product() # optional - sage.combinat + sage: (s[3,2].convolution_product() # needs sage.combinat sage.modules ....: == s[3,2].convolution_product(Antipode, Id) ....: == s[3,2].convolution_product(Id, Antipode)) True :: - sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi() # optional - sage.combinat - sage: Psi[2,1].convolution_product(Id, Id, Id) # optional - sage.combinat + sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi() # needs sage.combinat sage.modules + sage: Psi[2,1].convolution_product(Id, Id, Id) # needs sage.combinat sage.modules 3*Psi[1, 2] + 6*Psi[2, 1] - sage: (Psi[5,1] - Psi[1,5]).convolution_product(Id, Id, Id) # optional - sage.combinat + sage: (Psi[5,1] - Psi[1,5]).convolution_product(Id, Id, Id) # needs sage.combinat sage.modules -3*Psi[1, 5] + 3*Psi[5, 1] :: - sage: G = SymmetricGroup(3) # optional - sage.combinat - sage: QG = GroupAlgebra(G, QQ) # optional - sage.combinat - sage: x = QG.sum_of_terms([(p, p.length()) # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: G = SymmetricGroup(3) + sage: QG = GroupAlgebra(G, QQ) + sage: x = QG.sum_of_terms([(p, p.length()) ....: for p in Permutations(3)]); x [1, 3, 2] + [2, 1, 3] + 2*[2, 3, 1] + 2*[3, 1, 2] + 3*[3, 2, 1] - sage: x.convolution_product(Id, Id) # optional - sage.combinat + sage: x.convolution_product(Id, Id) 5*[1, 2, 3] + 2*[2, 3, 1] + 2*[3, 1, 2] - sage: x.convolution_product(Id, Id, Id) # optional - sage.combinat + sage: x.convolution_product(Id, Id, Id) 4*[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + 3*[3, 2, 1] - sage: x.convolution_product([Id] * 6) # optional - sage.combinat + sage: x.convolution_product([Id] * 6) 9*[1, 2, 3] TESTS:: @@ -312,59 +316,63 @@ def convolution_product(self, *maps): :: - sage: h = SymmetricFunctions(QQ).h() # optional - sage.combinat - sage: h[5].convolution_product([Id, Id]) # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: h = SymmetricFunctions(QQ).h() + sage: h[5].convolution_product([Id, Id]) 2*h[3, 2] + 2*h[4, 1] + 2*h[5] - sage: h.one().convolution_product([Id, Antipode]) # optional - sage.combinat + sage: h.one().convolution_product([Id, Antipode]) h[] - sage: h[3,2].convolution_product([Id, Antipode]) # optional - sage.combinat + sage: h[3,2].convolution_product([Id, Antipode]) 0 - sage: (h.one().convolution_product([Id, Antipode]) # optional - sage.combinat + sage: (h.one().convolution_product([Id, Antipode]) ....: == h.one().convolution_product()) True :: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat - sage: S[4].convolution_product([Id] * 5) # optional - sage.combinat + sage: S = NonCommutativeSymmetricFunctions(QQ).S() # needs sage.combinat sage.modules + sage: S[4].convolution_product([Id] * 5) # needs sage.combinat sage.modules 5*S[1, 1, 1, 1] + 10*S[1, 1, 2] + 10*S[1, 2, 1] + 10*S[1, 3] + 10*S[2, 1, 1] + 10*S[2, 2] + 10*S[3, 1] + 5*S[4] :: - sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # optional - sage.combinat - sage: m[[1,3],[2]].convolution_product([Antipode, Antipode]) # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() + sage: m[[1,3],[2]].convolution_product([Antipode, Antipode]) 3*m{{1}, {2, 3}} + 3*m{{1, 2}, {3}} + 6*m{{1, 2, 3}} - 2*m{{1, 3}, {2}} - sage: m[[]].convolution_product([]) # optional - sage.combinat + sage: m[[]].convolution_product([]) m{} - sage: m[[1,3],[2]].convolution_product([]) # optional - sage.combinat + sage: m[[1,3],[2]].convolution_product([]) 0 :: - sage: QS = SymmetricGroupAlgebra(QQ, 5) # optional - sage.combinat - sage: x = QS.sum_of_terms(zip(Permutations(5)[3:6], [1,2,3])); x # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: QS = SymmetricGroupAlgebra(QQ, 5) + sage: x = QS.sum_of_terms(zip(Permutations(5)[3:6], [1,2,3])); x [1, 2, 4, 5, 3] + 2*[1, 2, 5, 3, 4] + 3*[1, 2, 5, 4, 3] - sage: x.convolution_product([Antipode, Id]) # optional - sage.combinat + sage: x.convolution_product([Antipode, Id]) 6*[1, 2, 3, 4, 5] - sage: x.convolution_product(Id, Antipode, Antipode, Antipode) # optional - sage.combinat + sage: x.convolution_product(Id, Antipode, Antipode, Antipode) 3*[1, 2, 3, 4, 5] + [1, 2, 4, 5, 3] + 2*[1, 2, 5, 3, 4] :: - sage: G = SymmetricGroup(3) # optional - sage.combinat - sage: QG = GroupAlgebra(G, QQ) # optional - sage.combinat - sage: x = QG.sum_of_terms([(p, p.length()) # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: G = SymmetricGroup(3) + sage: QG = GroupAlgebra(G, QQ) + sage: x = QG.sum_of_terms([(p, p.length()) ....: for p in Permutations(3)]); x [1, 3, 2] + [2, 1, 3] + 2*[2, 3, 1] + 2*[3, 1, 2] + 3*[3, 2, 1] - sage: x.convolution_product(Antipode, Id) # optional - sage.combinat + sage: x.convolution_product(Antipode, Id) 9*[1, 2, 3] - sage: x.convolution_product([Id, Antipode, Antipode, Antipode]) # optional - sage.combinat + sage: x.convolution_product([Id, Antipode, Antipode, Antipode]) 5*[1, 2, 3] + 2*[2, 3, 1] + 2*[3, 1, 2] :: - sage: (s[3,2].counit().parent() # optional - sage.combinat + sage: (s[3,2].counit().parent() # needs sage.combinat sage.modules ....: == s[3,2].convolution_product().parent()) False """ diff --git a/src/sage/categories/bimodules.py b/src/sage/categories/bimodules.py index d85af83880d..eccadf20a02 100644 --- a/src/sage/categories/bimodules.py +++ b/src/sage/categories/bimodules.py @@ -103,7 +103,7 @@ def an_instance(cls): EXAMPLES:: - sage: Bimodules.an_instance() + sage: Bimodules.an_instance() # needs sage.rings.real_mpfr Category of bimodules over Rational Field on the left and Real Field with 53 bits of precision on the right """ from sage.rings.rational_field import QQ @@ -118,7 +118,7 @@ def _repr_object_names(self): Category of bimodules over Rational Field on the left and Integer Ring on the right """ return "bimodules over %s on the left and %s on the right" \ - %(self._left_base_ring, self._right_base_ring) + % (self._left_base_ring, self._right_base_ring) def left_base_ring(self): """ diff --git a/src/sage/categories/cartesian_product.py b/src/sage/categories/cartesian_product.py index 39e9a316b9a..d7b380b2598 100644 --- a/src/sage/categories/cartesian_product.py +++ b/src/sage/categories/cartesian_product.py @@ -242,7 +242,7 @@ def _repr_object_names(self): """ # This method is only required for the capital `C` - return "Cartesian products of %s"%(self.base_category()._repr_object_names()) + return "Cartesian products of %s" % (self.base_category()._repr_object_names()) def CartesianProducts(self): """ @@ -271,6 +271,7 @@ def base_ring(self): """ return self.base_category().base_ring() + # Moved to avoid circular imports lazy_import('sage.categories.sets_cat', 'cartesian_product') """ diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index 83e88ef748a..57ef7f4184b 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -22,49 +22,49 @@ sage: Sets() Category of sets - sage: GSets(AbelianGroup([2, 4, 9])) # optional - sage.groups + sage: GSets(AbelianGroup([2, 4, 9])) # needs sage.groups Category of G-sets for Multiplicative Abelian group isomorphic to C2 x C4 x C9 sage: Semigroups() Category of semigroups - sage: VectorSpaces(FiniteField(11)) # optional - sage.rings.finite_rings + sage: VectorSpaces(FiniteField(11)) Category of vector spaces over Finite Field of size 11 sage: Ideals(IntegerRing()) Category of ring ideals in Integer Ring Let's request the category of some objects:: - sage: V = VectorSpace(RationalField(), 3) # optional - sage.modules - sage: V.category() # optional - sage.modules + sage: V = VectorSpace(RationalField(), 3) # needs sage.modules + sage: V.category() # needs sage.modules Category of finite dimensional vector spaces with basis over (number fields and quotient fields and metric spaces) - sage: G = SymmetricGroup(9) # optional - sage.groups - sage: G.category() # optional - sage.groups + sage: G = SymmetricGroup(9) # needs sage.groups + sage: G.category() # needs sage.groups Join of Category of finite enumerated permutation groups and Category of finite weyl groups and Category of well generated finite irreducible complex reflection groups - sage: P = PerfectMatchings(3) # optional - sage.combinat sage.graphs - sage: P.category() # optional - sage.combinat sage.graphs + sage: P = PerfectMatchings(3) # needs sage.combinat + sage: P.category() # needs sage.combinat Category of finite enumerated sets Let's check some memberships:: - sage: V in VectorSpaces(QQ) # optional - sage.modules + sage: V in VectorSpaces(QQ) # needs sage.modules True - sage: V in VectorSpaces(FiniteField(11)) # optional - sage.modules sage.rings.finite_rings + sage: V in VectorSpaces(FiniteField(11)) # needs sage.modules False - sage: G in Monoids() # optional - sage.groups + sage: G in Monoids() # needs sage.groups True - sage: P in Rings() # optional - sage.combinat sage.graphs + sage: P in Rings() # needs sage.combinat False For parametrized categories one can use the following shorthand:: - sage: V in VectorSpaces # optional - sage.modules + sage: V in VectorSpaces # needs sage.modules True - sage: G in VectorSpaces # optional - sage.groups + sage: G in VectorSpaces # needs sage.groups False A parent ``P`` is in a category ``C`` if ``P.category()`` is a subcategory of @@ -86,9 +86,9 @@ By default, the category of an element `x` of a parent `P` is the category of all objects of `P` (this is dubious and may be deprecated):: - sage: V = VectorSpace(RationalField(), 3) # optional - sage.modules - sage: v = V.gen(1) # optional - sage.modules - sage: v.category() # optional - sage.modules + sage: V = VectorSpace(RationalField(), 3) # needs sage.modules + sage: v = V.gen(1) # needs sage.modules + sage: v.category() # needs sage.modules Category of elements of Vector space of dimension 3 over Rational Field """ @@ -327,7 +327,7 @@ class inheritance from ``C.parent_class``. On the other hand, identical hierarchies of classes are, preferably, built only once (e.g. for categories over a base ring):: - sage: Algebras(GF(5)).parent_class is Algebras(GF(7)).parent_class # optional - sage.rings.finite_rings + sage: Algebras(GF(5)).parent_class is Algebras(GF(7)).parent_class True sage: F = FractionField(ZZ['t']) sage: Coalgebras(F).parent_class is Coalgebras(FractionField(F['x'])).parent_class @@ -566,7 +566,7 @@ def an_instance(cls): sage: Algebras.an_instance() Category of algebras over Rational Field - sage: Bimodules.an_instance() + sage: Bimodules.an_instance() # needs sage.rings.real_mpfr Category of bimodules over Rational Field on the left and Real Field with 53 bits of precision on the right sage: AlgebraIdeals.an_instance() @@ -629,7 +629,7 @@ def _latex_(self): sage: latex(CommutativeAdditiveSemigroups()) \mathbf{CommutativeAdditiveSemigroups} """ - return "\\mathbf{%s}"%self._short_name() + return "\\mathbf{%s}" % self._short_name() # The convention for which hash function to use should be decided at the level of UniqueRepresentation # The implementation below is bad (hash independent of the base ring) @@ -728,15 +728,15 @@ def __classcontains__(cls, x): This method makes it easy to test if an object is, say, a vector space, without having to specify the base ring:: - sage: F = FreeModule(QQ, 3) # optional - sage.modules - sage: F in VectorSpaces # optional - sage.modules + sage: F = FreeModule(QQ, 3) # needs sage.modules + sage: F in VectorSpaces # needs sage.modules True - sage: F = FreeModule(ZZ, 3) # optional - sage.modules - sage: F in VectorSpaces # optional - sage.modules + sage: F = FreeModule(ZZ, 3) # needs sage.modules + sage: F in VectorSpaces # needs sage.modules False - sage: F in Algebras # optional - sage.modules + sage: F in Algebras # needs sage.modules False TESTS: @@ -802,14 +802,14 @@ def category_graph(self): EXAMPLES:: sage: C = Algebras(QQ) - sage: G = C.category_graph() # optional - sage.graphs - sage: G.is_directed_acyclic() # optional - sage.graphs + sage: G = C.category_graph() # needs sage.graphs + sage: G.is_directed_acyclic() # needs sage.graphs True The girth of a directed acyclic graph is infinite, however, the girth of the underlying undirected graph is 4 in this case:: - sage: Graph(G).girth() # optional - sage.graphs + sage: Graph(G).girth() # needs sage.graphs 4 """ return category_graph([self]) @@ -932,8 +932,8 @@ def _set_of_super_categories(self): TESTS:: - sage: C = HopfAlgebrasWithBasis(GF(7)) # optional - sage.rings.finite_rings - sage: C._set_of_super_categories == set(C._all_super_categories_proper) # optional - sage.rings.finite_rings + sage: C = HopfAlgebrasWithBasis(GF(7)) + sage: C._set_of_super_categories == set(C._all_super_categories_proper) True """ return frozenset(self._all_super_categories_proper) @@ -1452,9 +1452,9 @@ def _test_category(self, **options): from sage.categories.sets_cat import Sets tester = self._tester(**options) tester.assertTrue(isinstance(self.super_categories(), list), - "%s.super_categories() should return a list"%self) + "%s.super_categories() should return a list" % self) tester.assertTrue(self.is_subcategory(Objects()), - "%s is not a subcategory of Objects()"%self) + "%s is not a subcategory of Objects()" % self) tester.assertTrue(isinstance(self.parent_class, type)) tester.assertTrue(all(not isinstance(cat, JoinCategory) for cat in self._super_categories)) if not isinstance(self, JoinCategory): @@ -1580,7 +1580,7 @@ def _make_named_class(self, name, method_provider, cache=False, picklable=True): cls = self.__class__ if isinstance(cls, DynamicMetaclass): cls = cls.__base__ - class_name = "%s.%s"%(cls.__name__, name) + class_name = "%s.%s" % (cls.__name__, name) method_provider_cls = getattr(self, method_provider, None) if method_provider_cls is None: # If the category provides no XXXMethods class, @@ -1589,10 +1589,10 @@ def _make_named_class(self, name, method_provider, cache=False, picklable=True): else: # Otherwise, check XXXMethods assert inspect.isclass(method_provider_cls),\ - "%s.%s should be a class"%(cls.__name__, method_provider) + "%s.%s should be a class" % (cls.__name__, method_provider) mro = inspect.getmro(method_provider_cls) if len(mro) > 2 or (len(mro) == 2 and mro[1] is not object): - warn("%s.%s should not have a super class"%(cls.__name__, method_provider)) + warn("%s.%s should not have a super class" % (cls.__name__, method_provider)) # and point the documentation to it doccls = method_provider_cls if picklable: @@ -1673,7 +1673,7 @@ def parent_class(self): the category of algebras over a finite field versus algebras over a non-field:: - sage: Algebras(GF(7)).parent_class is Algebras(GF(5)).parent_class # optional - sage.rings.finite_rings + sage: Algebras(GF(7)).parent_class is Algebras(GF(5)).parent_class True sage: Algebras(QQ).parent_class is Algebras(ZZ).parent_class False @@ -1718,7 +1718,7 @@ def element_class(self): category of algebras over a field versus algebras over a non-field:: - sage: Algebras(GF(5)).element_class is Algebras(GF(3)).element_class # optional - sage.rings.finite_rings + sage: Algebras(GF(5)).element_class is Algebras(GF(3)).element_class True sage: Algebras(QQ).element_class is Algebras(ZZ).element_class False @@ -1792,9 +1792,9 @@ def is_subcategory(self, c): :: - sage: M3 = VectorSpaces(FiniteField(3)) # optional - sage.rings.finite_rings sage.modules - sage: M9 = VectorSpaces(FiniteField(9, 'a')) # optional - sage.rings.finite_rings sage.modules - sage: M3.is_subcategory(M9) # optional - sage.rings.finite_rings sage.modules + sage: M3 = VectorSpaces(FiniteField(3)) + sage: M9 = VectorSpaces(FiniteField(9, 'a')) # needs sage.rings.finite_rings + sage: M3.is_subcategory(M9) # needs sage.rings.finite_rings False Join categories are properly handled:: @@ -1805,16 +1805,16 @@ def is_subcategory(self, c): :: - sage: V3 = VectorSpaces(FiniteField(3)) # optional - sage.rings.finite_rings + sage: V3 = VectorSpaces(FiniteField(3)) sage: POSet = PartiallyOrderedSets() - sage: PoV3 = Category.join((V3, POSet)) # optional - sage.rings.finite_rings - sage: A3 = AlgebrasWithBasis(FiniteField(3)) # optional - sage.rings.finite_rings - sage: PoA3 = Category.join((A3, POSet)) # optional - sage.rings.finite_rings - sage: PoA3.is_subcategory(PoV3) # optional - sage.rings.finite_rings + sage: PoV3 = Category.join((V3, POSet)) + sage: A3 = AlgebrasWithBasis(FiniteField(3)) + sage: PoA3 = Category.join((A3, POSet)) + sage: PoA3.is_subcategory(PoV3) True - sage: PoV3.is_subcategory(PoV3) # optional - sage.rings.finite_rings + sage: PoV3.is_subcategory(PoV3) True - sage: PoV3.is_subcategory(PoA3) # optional - sage.rings.finite_rings + sage: PoV3.is_subcategory(PoA3) False """ if c is self: @@ -2605,7 +2605,7 @@ def category_sample(): EXAMPLES:: sage: from sage.categories.category import category_sample - sage: sorted(category_sample(), key=str) # optional - sage.groups + sage: sorted(category_sample(), key=str) # needs sage.groups [Category of G-sets for Symmetric group of order 8! as a permutation group, Category of Hecke modules over Rational Field, Category of Lie algebras over Rational Field, @@ -2644,14 +2644,14 @@ def category_graph(categories=None): EXAMPLES:: - sage: G = sage.categories.category.category_graph(categories=[Groups()]) # optional - sage.graphs - sage: G.vertices(sort=True) # optional - sage.graphs + sage: G = sage.categories.category.category_graph(categories=[Groups()]) # needs sage.graphs + sage: G.vertices(sort=True) # needs sage.graphs ['groups', 'inverse unital magmas', 'magmas', 'monoids', 'objects', 'semigroups', 'sets', 'sets with partial maps', 'unital magmas'] - sage: G.plot() # optional - sage.graphs sage.plot + sage: G.plot() # needs sage.graphs sage.plot Graphics object consisting of 20 graphics primitives - sage: sage.categories.category.category_graph().plot() # optional - sage.graphs sage.plot + sage: sage.categories.category.category_graph().plot() # needs sage.graphs sage.plot Graphics object consisting of ... graphics primitives """ from sage import graphs @@ -2699,15 +2699,15 @@ class CategoryWithParameters(Category): EXAMPLES:: - sage: C1 = Algebras(GF(5)) # optional - sage.rings.finite_rings - sage: C2 = Algebras(GF(3)) # optional - sage.rings.finite_rings + sage: C1 = Algebras(GF(5)) + sage: C2 = Algebras(GF(3)) sage: C3 = Algebras(ZZ) sage: from sage.categories.category import CategoryWithParameters - sage: isinstance(C1, CategoryWithParameters) # optional - sage.rings.finite_rings + sage: isinstance(C1, CategoryWithParameters) True - sage: C1.parent_class is C2.parent_class # optional - sage.rings.finite_rings + sage: C1.parent_class is C2.parent_class True - sage: C1.parent_class is C3.parent_class # optional - sage.rings.finite_rings + sage: C1.parent_class is C3.parent_class False .. automethod:: Category._make_named_class @@ -2754,7 +2754,7 @@ def _make_named_class(self, name, method_provider, cache=False, **options): sage: Bimodules(ZZ,RR).parent_class is Bimodules(ZZ,RDF).parent_class # indirect doctest True - sage: Bimodules(CC,ZZ).element_class is Bimodules(RR,ZZ).element_class + sage: Bimodules(CC,ZZ).element_class is Bimodules(RR,ZZ).element_class # needs sage.rings.real_mpfr True On the other hand, modules over a field have more methods than @@ -2768,7 +2768,7 @@ def _make_named_class(self, name, method_provider, cache=False, **options): For a more subtle example, one could possibly share the classes for ``GF(3)`` and ``GF(2^3, 'x')``, but this is not currently the case:: - sage: Modules(GF(3)).parent_class is Modules(GF(2^3,'x')).parent_class + sage: Modules(GF(3)).parent_class is Modules(GF(2^3,'x')).parent_class # needs sage.rings.finite_rings False This is because those two fields do not have the exact same category:: @@ -2777,7 +2777,7 @@ def _make_named_class(self, name, method_provider, cache=False, **options): Join of Category of finite enumerated fields and Category of subquotients of monoids and Category of quotients of semigroups - sage: GF(2^3,'x').category() + sage: GF(2^3,'x').category() # needs sage.rings.finite_rings Category of finite enumerated fields Similarly for ``QQ`` and ``RR``:: @@ -2787,15 +2787,17 @@ def _make_named_class(self, name, method_provider, cache=False, **options): and Category of quotient fields and Category of metric spaces sage: RR.category() - Join of Category of fields and Category of infinite sets and Category of complete metric spaces + Join of Category of fields and Category of infinite sets + and Category of complete metric spaces sage: Modules(QQ).parent_class is Modules(RR).parent_class False Some other cases where one could potentially share those classes:: - sage: Modules(GF(3),dispatch=False).parent_class is Modules(ZZ).parent_class + sage: MF = Modules(GF(3), dispatch=False) + sage: MF.parent_class is Modules(ZZ).parent_class False - sage: Modules(GF(3),dispatch=False).element_class is Modules(ZZ).element_class + sage: MF.element_class is Modules(ZZ).element_class False TESTS:: @@ -2926,12 +2928,13 @@ class JoinCategory(CategoryWithParameters): the underlying implementation is the same for all finite fields, we have:: - sage: G = SymmetricGroup(10) # optional - sage.groups sage.rings.finite_rings - sage: A3 = G.algebra(GF(3)) # optional - sage.groups sage.rings.finite_rings - sage: A5 = G.algebra(GF(5)) # optional - sage.groups sage.rings.finite_rings - sage: type(A3.category()) # optional - sage.groups sage.rings.finite_rings + sage: # needs sage.groups sage.rings.finite_rings + sage: G = SymmetricGroup(10) + sage: A3 = G.algebra(GF(3)) + sage: A5 = G.algebra(GF(5)) + sage: type(A3.category()) - sage: type(A3) is type(A5) # optional - sage.groups sage.rings.finite_rings + sage: type(A3) is type(A5) True .. automethod:: Category._repr_object_names diff --git a/src/sage/categories/category_types.py b/src/sage/categories/category_types.py index ef0fb9472bb..cb18dcd42c0 100644 --- a/src/sage/categories/category_types.py +++ b/src/sage/categories/category_types.py @@ -72,14 +72,15 @@ def _call_(self, x): """ EXAMPLES:: - sage: V = VectorSpace(QQ, 3) # optional - sage.modules - sage: x = V.0 # optional - sage.modules - sage: C = x.category() # optional - sage.modules - sage: C # optional - sage.modules + sage: # needs sage.modules + sage: V = VectorSpace(QQ, 3) + sage: x = V.0 + sage: C = x.category() + sage: C Category of elements of Vector space of dimension 3 over Rational Field - sage: w = C([1, 2, 3]); w # indirect doctest # optional - sage.modules + sage: w = C([1, 2, 3]); w # indirect doctest (1, 2, 3) - sage: w.category() # optional - sage.modules + sage: w.category() Category of elements of Vector space of dimension 3 over Rational Field """ return self.__object(x) @@ -123,18 +124,18 @@ def _repr_object_names(self): sage: Elements(ZZ)._repr_object_names() 'elements of Integer Ring' """ - return "elements of %s"%self.object() + return "elements of %s" % self.object() def _latex_(self): r""" EXAMPLES:: - sage: V = VectorSpace(QQ, 3) # optional - sage.modules - sage: x = V.0 # optional - sage.modules - sage: latex(x.category()) # indirect doctest # optional - sage.modules + sage: V = VectorSpace(QQ, 3) # needs sage.modules + sage: x = V.0 # needs sage.modules + sage: latex(x.category()) # indirect doctest # needs sage.modules \mathbf{Elt}_{\Bold{Q}^{3}} """ - return "\\mathbf{Elt}_{%s}"%latex(self.__object) + return "\\mathbf{Elt}_{%s}" % latex(self.__object) ############################################################# @@ -153,11 +154,11 @@ class Category_over_base(CategoryWithParameters): EXAMPLES:: - sage: Algebras(GF(2)).element_class is Algebras(GF(3)).element_class # optional - sage.rings.finite_rings + sage: Algebras(GF(2)).element_class is Algebras(GF(3)).element_class True - sage: C = GF(2).category() # optional - sage.rings.finite_rings - sage: Algebras(GF(2)).parent_class is Algebras(C).parent_class # optional - sage.rings.finite_rings + sage: C = GF(2).category() + sage: Algebras(GF(2)).parent_class is Algebras(C).parent_class True sage: C = ZZ.category() @@ -278,7 +279,7 @@ def _repr_object_names(self): 'algebras over Rational Field' sage: Algebras(Fields())._repr_object_names() 'algebras over fields' - sage: Algebras(GF(2).category())._repr_object_names() # optional - sage.rings.finite_rings + sage: Algebras(GF(2).category())._repr_object_names() 'algebras over (finite enumerated fields and subquotients of monoids and quotients of semigroups)' """ base = self.__base @@ -289,7 +290,7 @@ def _repr_object_names(self): name = base._repr_object_names() else: name = base - return Category._repr_object_names(self) + " over %s"%name + return Category._repr_object_names(self) + " over %s" % name def _latex_(self): r""" @@ -298,7 +299,7 @@ def _latex_(self): sage: latex(ModulesWithBasis(ZZ)) \mathbf{ModulesWithBasis}_{\Bold{Z}} """ - return "\\mathbf{%s}_{%s}"%(self._label, latex(self.__base)) + return "\\mathbf{%s}_{%s}" % (self._label, latex(self.__base)) # def construction(self): # return (self.__class__, self.__base) @@ -338,9 +339,9 @@ def __init__(self, base, name=None): EXAMPLES:: - sage: C = Algebras(GF(2)); C # optional - sage.rings.finite_rings + sage: C = Algebras(GF(2)); C Category of algebras over Finite Field of size 2 - sage: TestSuite(C).run() # optional - sage.rings.finite_rings + sage: TestSuite(C).run() """ from sage.categories.rings import Rings if not (base in Rings() or @@ -355,8 +356,8 @@ def base_ring(self): EXAMPLES:: - sage: C = Algebras(GF(2)) # optional - sage.rings.finite_rings - sage: C.base_ring() # optional - sage.rings.finite_rings + sage: C = Algebras(GF(2)) + sage: C.base_ring() Finite Field of size 2 """ return self.base() @@ -399,11 +400,13 @@ def _subcategory_hook_(self, C): sage: VectorSpaces(QQ)._subcategory_hook_(VectorSpaces(QQ) & Rings()) Unknown - sage: Sym = SymmetricFunctions(QQ) # optional - sage.combinat - sage: from sage.combinat.sf.sfa import SymmetricFunctionsBases # optional - sage.combinat - sage: Modules(QQ)._subcategory_hook_(SymmetricFunctionsBases(Sym)) # optional - sage.combinat + + sage: # needs sage.combinat sage.modules + sage: Sym = SymmetricFunctions(QQ) + sage: from sage.combinat.sf.sfa import SymmetricFunctionsBases + sage: Modules(QQ)._subcategory_hook_(SymmetricFunctionsBases(Sym)) Unknown - sage: SymmetricFunctionsBases(Sym).is_subcategory(Modules(QQ)) # optional - sage.combinat + sage: SymmetricFunctionsBases(Sym).is_subcategory(Modules(QQ)) True Case 1: the two bases are categories; then the base of ``C`` @@ -428,18 +431,18 @@ def _subcategory_hook_(self, C): sage: VectorSpaces(QQ)._subcategory_hook_(Algebras(QQ)) True - sage: VectorSpaces(CC)._subcategory_hook_(Algebras(QQ)) # base ring in different categories + sage: VectorSpaces(CC)._subcategory_hook_(Algebras(QQ)) # base ring in different categories # needs sage.rings.real_mpfr False - sage: VectorSpaces(GF(2))._subcategory_hook_(Algebras(GF(3))) # base ring in the same category # optional - sage.rings.finite_rings + sage: VectorSpaces(GF(2))._subcategory_hook_(Algebras(GF(3))) # base ring in the same category False Note; we need both previous tests since the distinction is made respectively using the parent class or the base ring:: - sage: issubclass(Algebras(QQ).parent_class, # optional - sage.modules + sage: issubclass(Algebras(QQ).parent_class, # needs sage.modules ....: VectorSpaces(CC).parent_class) False - sage: issubclass(Algebras(GF(2)).parent_class, # optional - sage.modules sage.rings.finite_rings + sage: issubclass(Algebras(GF(2)).parent_class, ....: VectorSpaces(GF(3)).parent_class) True @@ -447,6 +450,7 @@ def _subcategory_hook_(self, C): method is only valid for :class:`Category_over_base_ring`, not :class:`Category_over_base`:: + sage: # needs sage.groups sage: from sage.categories.category_types import Category_over_base sage: D = Modules(Rings()) sage: class Cs(Category_over_base): @@ -551,7 +555,7 @@ def _repr_(self): sage: Ideals(IntegerRing()) Category of ring ideals in Integer Ring """ - return Category._repr_(self) + " in %s"%self.__ambient + return Category._repr_(self) + " in %s" % self.__ambient # def construction(self): # return (self.__class__, self.__ambient) diff --git a/src/sage/categories/category_with_axiom.py b/src/sage/categories/category_with_axiom.py index 2128dac2db9..5227792e725 100644 --- a/src/sage/categories/category_with_axiom.py +++ b/src/sage/categories/category_with_axiom.py @@ -2462,9 +2462,9 @@ def axioms(self): sage: C.axioms() frozenset({'Finite'}) - sage: C = Modules(GF(5)).FiniteDimensional(); C # optional - sage.rings.finite_rings + sage: C = Modules(GF(5)).FiniteDimensional(); C Category of finite dimensional vector spaces over Finite Field of size 5 - sage: sorted(C.axioms()) # optional - sage.rings.finite_rings + sage: sorted(C.axioms()) ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Finite', 'FiniteDimensional'] @@ -2472,7 +2472,7 @@ def axioms(self): ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Distributive', 'FiniteDimensional', 'Unital', 'WithBasis'] - sage: sorted(FiniteMonoids().Algebras(GF(3)).axioms()) # optional - sage.rings.finite_rings + sage: sorted(FiniteMonoids().Algebras(GF(3)).axioms()) ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Distributive', 'Finite', 'FiniteDimensional', 'Unital', 'WithBasis'] @@ -2524,6 +2524,7 @@ def __init__(self, base_category): class CategoryWithAxiom_singleton(Category_singleton, CategoryWithAxiom):#, Category_singleton, FastHashable_class): pass + """ The following workaround is needed until any :class:`CategoryWithAxiom` of a :class:`Category_over_base_ring` becomes automatically a diff --git a/src/sage/categories/chain_complexes.py b/src/sage/categories/chain_complexes.py index 8ce3e6145bc..db9c5d03f56 100644 --- a/src/sage/categories/chain_complexes.py +++ b/src/sage/categories/chain_complexes.py @@ -67,27 +67,29 @@ def homology(self, n=None): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # optional - sage.modules - sage: C.homology(0) # optional - sage.modules + sage: # needs sage.modules + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) + sage: C.homology(0) Z x Z - sage: C.homology(1) # optional - sage.modules + sage: C.homology(1) Z x C3 - sage: C.homology(2) # optional - sage.modules + sage: C.homology(2) 0 :: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # optional - sage.combinat sage.modules - sage: C = A.cdg_algebra({z: x*y}) # optional - sage.combinat sage.modules - sage: C.homology(0) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) + sage: C = A.cdg_algebra({z: x*y}) + sage: C.homology(0) Free module generated by {[1]} over Rational Field - sage: C.homology(1) # optional - sage.combinat sage.modules + sage: C.homology(1) Free module generated by {} over Rational Field - sage: C.homology(2) # optional - sage.combinat sage.modules + sage: C.homology(2) Free module generated by {[x], [y]} over Rational Field - sage: C.homology(3) # optional - sage.combinat sage.modules + sage: C.homology(3) Free module generated by {} over Rational Field - sage: C.homology(4) # optional - sage.combinat sage.modules + sage: C.homology(4) Free module generated by {[x^2], [y^2]} over Rational Field """ @@ -99,16 +101,16 @@ def differential(self, *args, **kwargs): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # optional - sage.modules - sage: C.differential(0) # optional - sage.modules + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # needs sage.modules + sage: C.differential(0) # needs sage.modules [3 0 0] [0 0 0] :: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # optional - sage.combinat sage.modules - sage: C = A.cdg_algebra({z: x*y}) # optional - sage.combinat sage.modules - sage: C.differential() # optional - sage.combinat sage.modules + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.combinat sage.modules + sage: C = A.cdg_algebra({z: x*y}) # needs sage.combinat sage.modules + sage: C.differential() # needs sage.combinat sage.modules Differential of Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (2, 2, 3) over Rational Field Defn: x --> 0 @@ -124,10 +126,11 @@ def lift_from_homology(self, x): EXAMPLES:: - sage: E3 = EuclideanSpace(3) # optional - sage.symbolic - sage: C = E3.de_rham_complex() # optional - sage.symbolic - sage: one = C.homology().one() # optional - sage.symbolic - sage: C.lift_from_homology(one) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: E3 = EuclideanSpace(3) + sage: C = E3.de_rham_complex() + sage: one = C.homology().one() + sage: C.lift_from_homology(one) Mixed differential form one on the Euclidean space E^3 """ @@ -144,10 +147,11 @@ def reduce_to_homology(self, x, n=None): EXAMPLES:: - sage: E3 = EuclideanSpace(3) # optional - sage.symbolic - sage: C = E3.de_rham_complex() # optional - sage.symbolic - sage: one = C.one() # optional - sage.symbolic - sage: C.reduce_to_homology(one) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: E3 = EuclideanSpace(3) + sage: C = E3.de_rham_complex() + sage: one = C.one() + sage: C.reduce_to_homology(one) [one] """ try: @@ -169,35 +173,38 @@ class HomologyFunctor(Functor): EXAMPLES:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # optional - sage.modules - sage: H = HomologyFunctor(ChainComplexes(ZZ), 1) # optional - sage.modules - sage: H(C) # optional - sage.modules + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # needs sage.modules + sage: H = HomologyFunctor(ChainComplexes(ZZ), 1) + sage: H(C) # needs sage.modules Z x C3 :: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # optional - sage.combinat sage.modules - sage: C = A.cdg_algebra({z: x*y}) # optional - sage.combinat sage.modules - sage: H = HomologyFunctor(ChainComplexes(QQ), 2) # optional - sage.combinat sage.modules - sage: H(C) # optional - sage.combinat sage.modules + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3)) # needs sage.combinat sage.modules + sage: C = A.cdg_algebra({z: x*y}) # needs sage.combinat sage.modules + sage: H = HomologyFunctor(ChainComplexes(QQ), 2) + sage: H(C) # needs sage.combinat sage.modules Free module generated by {[x], [y]} over Rational Field Applying to a chain map:: - sage: S = simplicial_complexes.Sphere(1); S # optional - sage.graphs + sage: # needs sage.graphs sage.modules + sage: S = simplicial_complexes.Sphere(1); S Minimal triangulation of the 1-sphere - sage: C = S.chain_complex() # optional - sage.graphs sage.modules - sage: C.differential() # optional - sage.graphs sage.modules - {0: [], 1: [-1 -1 0] - [ 1 0 -1] - [ 0 1 1], 2: []} - sage: f = {0: zero_matrix(ZZ,3,3), 1: zero_matrix(ZZ,3,3)} # optional - sage.modules - sage: G = Hom(C, C) # optional - sage.graphs sage.modules - sage: x = G(f) # optional - sage.graphs sage.modules - sage: H = HomologyFunctor(ChainComplexes(ZZ), 1) # optional - sage.graphs sage.modules - sage: H(C) # optional - sage.graphs sage.modules + sage: SCC = S.chain_complex() + sage: SCC.differential() + {0: [], + 1: [-1 -1 0] + [ 1 0 -1] + [ 0 1 1], + 2: []} + sage: f = {0: zero_matrix(ZZ,3,3), 1: zero_matrix(ZZ,3,3)} + sage: G = Hom(SCC, SCC) + sage: x = G(f) + sage: H = HomologyFunctor(ChainComplexes(ZZ), 1) + sage: H(SCC) Z - sage: H(x) # optional - sage.graphs sage.modules + sage: H(x) Generic morphism: From: Z To: Z @@ -226,9 +233,9 @@ def _apply_functor(self, x): TESTS:: - sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # optional - sage.modules - sage: H = HomologyFunctor(ChainComplexes(ZZ), 1) # optional - sage.modules - sage: H._apply_functor(C) # optional - sage.modules + sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])}) # needs sage.modules + sage: H = HomologyFunctor(ChainComplexes(ZZ), 1) + sage: H._apply_functor(C) # needs sage.modules Z x C3 """ @@ -240,15 +247,16 @@ def _apply_functor_to_morphism(self, f): TESTS:: - sage: E3 = EuclideanSpace(3) # optional - sage.symbolic - sage: C = E3.de_rham_complex() # optional - sage.symbolic - sage: id = Hom(C, C).identity() # optional - sage.symbolic - sage: H = HomologyFunctor(ChainComplexes(SR)) # optional - sage.symbolic - sage: id_star = H(id); id_star # optional - sage.symbolic + sage: # needs sage.symbolic + sage: E3 = EuclideanSpace(3) + sage: C = E3.de_rham_complex() + sage: id = Hom(C, C).identity() + sage: H = HomologyFunctor(ChainComplexes(SR)) + sage: id_star = H(id); id_star Generic endomorphism of De Rham cohomology ring on the Euclidean space E^3 - sage: one = H(C).one() # optional - sage.symbolic - sage: id_star(one) # optional - sage.symbolic + sage: one = H(C).one() + sage: id_star(one) [one] """ from .morphism import SetMorphism diff --git a/src/sage/categories/classical_crystals.py b/src/sage/categories/classical_crystals.py index 744b1cb6e44..fb5d2c7cde8 100644 --- a/src/sage/categories/classical_crystals.py +++ b/src/sage/categories/classical_crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.graphs, sage.combinat +# sage.doctest: needs sage.graphs sage.combinat r""" Classical Crystals """ diff --git a/src/sage/categories/coalgebras.py b/src/sage/categories/coalgebras.py index 870315dc644..abe36aef0bb 100644 --- a/src/sage/categories/coalgebras.py +++ b/src/sage/categories/coalgebras.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat +# sage.doctest: needs sage.combinat r""" Coalgebras """ @@ -67,6 +67,7 @@ def counit(self, x): EXAMPLES:: + sage: # needs sage.modules sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field @@ -91,6 +92,7 @@ def coproduct(self, x): EXAMPLES:: + sage: # needs sage.modules sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field @@ -109,6 +111,7 @@ def coproduct(self): EXAMPLES:: + sage: # needs sage.modules sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field @@ -126,6 +129,7 @@ def counit(self): EXAMPLES:: + sage: # needs sage.modules sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field @@ -292,6 +296,7 @@ def coproduct(self, x): EXAMPLES:: + sage: # needs sage.modules sage: N = NonCommutativeSymmetricFunctions(QQ) sage: S = N.complete() sage: N.coproduct.__module__ @@ -307,6 +312,7 @@ def counit(self, x): EXAMPLES:: + sage: # needs sage.modules sage: Sym = SymmetricFunctions(QQ) sage: s = Sym.schur() sage: f = s[2,1] @@ -317,6 +323,7 @@ def counit(self, x): :: + sage: # needs sage.modules sage: N = NonCommutativeSymmetricFunctions(QQ) sage: N.counit.__module__ 'sage.categories.coalgebras' @@ -340,6 +347,7 @@ def coproduct_by_coercion(self, x): EXAMPLES:: + sage: # needs sage.modules sage: Sym = SymmetricFunctions(QQ) sage: m = Sym.monomial() sage: f = m[2,1] @@ -354,6 +362,7 @@ def coproduct_by_coercion(self, x): :: + sage: # needs sage.modules sage: N = NonCommutativeSymmetricFunctions(QQ) sage: R = N.ribbon() sage: R.coproduct_by_coercion.__module__ @@ -375,16 +384,16 @@ def counit_by_coercion(self, x): EXAMPLES:: - sage: sp = SymmetricFunctions(QQ).sp() - sage: sp.an_element() + sage: sp = SymmetricFunctions(QQ).sp() # needs sage.modules + sage: sp.an_element() # needs sage.modules 2*sp[] + 2*sp[1] + 3*sp[2] - sage: sp.counit(sp.an_element()) + sage: sp.counit(sp.an_element()) # needs sage.modules 2 - sage: o = SymmetricFunctions(QQ).o() - sage: o.an_element() + sage: o = SymmetricFunctions(QQ).o() # needs sage.modules + sage: o.an_element() # needs sage.modules 2*o[] + 2*o[1] + 3*o[2] - sage: o.counit(o.an_element()) + sage: o.counit(o.an_element()) # needs sage.modules -1 """ R = self.realization_of().a_realization() diff --git a/src/sage/categories/coalgebras_with_basis.py b/src/sage/categories/coalgebras_with_basis.py index 844f5e5a294..1a3ecfe8302 100644 --- a/src/sage/categories/coalgebras_with_basis.py +++ b/src/sage/categories/coalgebras_with_basis.py @@ -61,12 +61,12 @@ def coproduct_on_basis(self, i): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example(); A # optional - sage.groups sage.modules + sage: A = HopfAlgebrasWithBasis(QQ).example(); A # needs sage.groups sage.modules An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: (a, b) = A._group.gens() # optional - sage.groups sage.modules - sage: A.coproduct_on_basis(a) # optional - sage.groups sage.modules + sage: (a, b) = A._group.gens() # needs sage.groups sage.modules + sage: A.coproduct_on_basis(a) # needs sage.groups sage.modules B[(1,2,3)] # B[(1,2,3)] """ @@ -81,14 +81,15 @@ def coproduct(self): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example(); A # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: a, b = A.algebra_generators() # optional - sage.groups sage.modules - sage: a, A.coproduct(a) # optional - sage.groups sage.modules + sage: a, b = A.algebra_generators() + sage: a, A.coproduct(a) (B[(1,2,3)], B[(1,2,3)] # B[(1,2,3)]) - sage: b, A.coproduct(b) # optional - sage.groups sage.modules + sage: b, A.coproduct(b) (B[(1,3)], B[(1,3)] # B[(1,3)]) """ @@ -115,12 +116,12 @@ def counit_on_basis(self, i): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example(); A # optional - sage.groups sage.modules + sage: A = HopfAlgebrasWithBasis(QQ).example(); A # needs sage.groups sage.modules An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: (a, b) = A._group.gens() # optional - sage.groups sage.modules - sage: A.counit_on_basis(a) # optional - sage.groups sage.modules + sage: (a, b) = A._group.gens() # needs sage.groups sage.modules + sage: A.counit_on_basis(a) # needs sage.groups sage.modules 1 """ @@ -133,14 +134,15 @@ def counit(self): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example(); A # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: a, b = A.algebra_generators() # optional - sage.groups sage.modules - sage: a, A.counit(a) # optional - sage.groups sage.modules + sage: a, b = A.algebra_generators() + sage: a, A.counit(a) (B[(1,2,3)], 1) - sage: b, A.counit(b) # optional - sage.groups sage.modules + sage: b, A.counit(b) (B[(1,3)], 1) """ @@ -160,29 +162,29 @@ def coproduct_iterated(self, n=1): EXAMPLES:: - sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi() # optional - sage.combinat - sage: Psi[2,2].coproduct_iterated(0) # optional - sage.combinat + sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi() # needs sage.combinat sage.modules + sage: Psi[2,2].coproduct_iterated(0) # needs sage.combinat sage.modules Psi[2, 2] - sage: Psi[2,2].coproduct_iterated(2) # optional - sage.combinat + sage: Psi[2,2].coproduct_iterated(2) # needs sage.combinat sage.modules Psi[] # Psi[] # Psi[2, 2] + 2*Psi[] # Psi[2] # Psi[2] + Psi[] # Psi[2, 2] # Psi[] + 2*Psi[2] # Psi[] # Psi[2] + 2*Psi[2] # Psi[2] # Psi[] + Psi[2, 2] # Psi[] # Psi[] TESTS:: - sage: p = SymmetricFunctions(QQ).p() # optional - sage.combinat - sage: p[5,2,2].coproduct_iterated() # optional - sage.combinat + sage: p = SymmetricFunctions(QQ).p() # needs sage.combinat sage.modules + sage: p[5,2,2].coproduct_iterated() # needs sage.combinat sage.modules p[] # p[5, 2, 2] + 2*p[2] # p[5, 2] + p[2, 2] # p[5] + p[5] # p[2, 2] + 2*p[5, 2] # p[2] + p[5, 2, 2] # p[] - sage: p([]).coproduct_iterated(3) # optional - sage.combinat + sage: p([]).coproduct_iterated(3) # needs sage.combinat sage.modules p[] # p[] # p[] # p[] :: - sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi() # optional - sage.combinat - sage: Psi[2,2].coproduct_iterated(0) # optional - sage.combinat + sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi() # needs sage.combinat sage.modules + sage: Psi[2,2].coproduct_iterated(0) # needs sage.combinat sage.modules Psi[2, 2] - sage: Psi[2,2].coproduct_iterated(3) # optional - sage.combinat + sage: Psi[2,2].coproduct_iterated(3) # needs sage.combinat sage.modules Psi[] # Psi[] # Psi[] # Psi[2, 2] + 2*Psi[] # Psi[] # Psi[2] # Psi[2] + Psi[] # Psi[] # Psi[2, 2] # Psi[] + 2*Psi[] # Psi[2] # Psi[] # Psi[2] + 2*Psi[] # Psi[2] # Psi[2] # Psi[] + Psi[] # Psi[2, 2] # Psi[] # Psi[] @@ -191,14 +193,14 @@ def coproduct_iterated(self, n=1): :: - sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # optional - sage.combinat - sage: m[[1,3],[2]].coproduct_iterated(2) # optional - sage.combinat + sage: m = SymmetricFunctionsNonCommutingVariables(QQ).m() # needs sage.combinat sage.modules + sage: m[[1,3],[2]].coproduct_iterated(2) # needs sage.combinat sage.modules m{} # m{} # m{{1, 3}, {2}} + m{} # m{{1}} # m{{1, 2}} + m{} # m{{1, 2}} # m{{1}} + m{} # m{{1, 3}, {2}} # m{} + m{{1}} # m{} # m{{1, 2}} + m{{1}} # m{{1, 2}} # m{} + m{{1, 2}} # m{} # m{{1}} + m{{1, 2}} # m{{1}} # m{} + m{{1, 3}, {2}} # m{} # m{} - sage: m[[]].coproduct_iterated(3), m[[1,3],[2]].coproduct_iterated(0) # optional - sage.combinat + sage: m[[]].coproduct_iterated(3), m[[1,3],[2]].coproduct_iterated(0) # needs sage.combinat sage.modules (m{} # m{} # m{} # m{}, m{{1, 3}, {2}}) """ if n < 0: diff --git a/src/sage/categories/commutative_additive_groups.py b/src/sage/categories/commutative_additive_groups.py index 9300f4d6db5..ce1dfc5186a 100644 --- a/src/sage/categories/commutative_additive_groups.py +++ b/src/sage/categories/commutative_additive_groups.py @@ -79,11 +79,12 @@ def additive_order(self): sage: G((0,1)).additive_order() +Infinity - sage: K = GF(9) # optional - sage.rings.finite_rings - sage: H = cartesian_product([ # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: K = GF(9) + sage: H = cartesian_product([ ....: cartesian_product([Zmod(2), Zmod(9)]), K]) - sage: z = H(((1,2), K.gen())) # optional - sage.rings.finite_rings - sage: z.additive_order() # optional - sage.rings.finite_rings + sage: z = H(((1,2), K.gen())) + sage: z.additive_order() 18 """ from sage.rings.infinity import Infinity diff --git a/src/sage/categories/commutative_algebra_ideals.py b/src/sage/categories/commutative_algebra_ideals.py index e0835848e91..070503ae6c8 100644 --- a/src/sage/categories/commutative_algebra_ideals.py +++ b/src/sage/categories/commutative_algebra_ideals.py @@ -45,7 +45,7 @@ def __init__(self, A): ... TypeError: A (=Ring of integers modulo 4) must be a commutative algebra - sage: CommutativeAlgebraIdeals(Partitions(4)) # optional - sage.combinat sage.modules + sage: CommutativeAlgebraIdeals(Partitions(4)) # needs sage.combinat Traceback (most recent call last): ... TypeError: A (=Partitions of the integer 4) must be a commutative algebra diff --git a/src/sage/categories/commutative_algebras.py b/src/sage/categories/commutative_algebras.py index bdff573db87..986a45db3e3 100644 --- a/src/sage/categories/commutative_algebras.py +++ b/src/sage/categories/commutative_algebras.py @@ -22,8 +22,8 @@ class CommutativeAlgebras(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: M = CommutativeAlgebras(GF(19)) # optional - sage.rings.finite_rings - sage: M # optional - sage.rings.finite_rings + sage: M = CommutativeAlgebras(GF(19)) + sage: M Category of commutative algebras over Finite Field of size 19 sage: CommutativeAlgebras(QQ).super_categories() [Category of algebras over Rational Field, Category of commutative rings] @@ -53,7 +53,7 @@ def __contains__(self, A): True sage: QQ['a,b'] in CommutativeAlgebras(QQ) True - sage: FreeAlgebra(QQ, 2, 'a,b') in CommutativeAlgebras(QQ) # optional - sage.combinat + sage: FreeAlgebra(QQ, 2, 'a,b') in CommutativeAlgebras(QQ) # needs sage.combinat sage.modules False TODO: get rid of this method once all commutative algebras in @@ -80,12 +80,13 @@ def extra_super_categories(self): TESTS:: - sage: X = algebras.Shuffle(QQ, 'ab') # optional - sage.combinat - sage: Y = algebras.Shuffle(QQ, 'bc') # optional - sage.combinat - sage: X in Algebras(QQ).Commutative() # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: X = algebras.Shuffle(QQ, 'ab') + sage: Y = algebras.Shuffle(QQ, 'bc') + sage: X in Algebras(QQ).Commutative() True - sage: T = tensor([X, Y]) # optional - sage.combinat - sage: T in CommutativeRings() # optional - sage.combinat + sage: T = tensor([X, Y]) + sage: T in CommutativeRings() True """ return [CommutativeRings()] diff --git a/src/sage/categories/commutative_ring_ideals.py b/src/sage/categories/commutative_ring_ideals.py index 837f1edf944..5aef6d7d31d 100644 --- a/src/sage/categories/commutative_ring_ideals.py +++ b/src/sage/categories/commutative_ring_ideals.py @@ -35,14 +35,14 @@ def __init__(self, R): TESTS:: - sage: CommutativeRingIdeals(Partitions(4)) # optional - sage.combinat + sage: CommutativeRingIdeals(Partitions(4)) # needs sage.combinat Traceback (most recent call last): ... TypeError: R (=Partitions of the integer 4) must be a commutative ring sage: TestSuite(CommutativeRingIdeals(ZZ)).run() """ if R not in CommutativeRings(): - raise TypeError("R (=%s) must be a commutative ring"%R) + raise TypeError("R (=%s) must be a commutative ring" % R) Category_ideal.__init__(self, R) def super_categories(self): diff --git a/src/sage/categories/commutative_rings.py b/src/sage/categories/commutative_rings.py index 6219c1070bb..9c28072ae0b 100644 --- a/src/sage/categories/commutative_rings.py +++ b/src/sage/categories/commutative_rings.py @@ -35,14 +35,14 @@ class CommutativeRings(CategoryWithAxiom): sage: QQ['x,y,z'] in CommutativeRings() True - sage: GroupAlgebra(DihedralGroup(3), QQ) in CommutativeRings() # optional - sage.groups sage.modules + sage: GroupAlgebra(DihedralGroup(3), QQ) in CommutativeRings() # needs sage.groups sage.modules False - sage: MatrixSpace(QQ, 2, 2) in CommutativeRings() # optional - sage.modules + sage: MatrixSpace(QQ, 2, 2) in CommutativeRings() # needs sage.modules False GroupAlgebra should be fixed:: - sage: GroupAlgebra(CyclicPermutationGroup(3), QQ) in CommutativeRings() # todo: not implemented # optional - sage.groups sage.modules + sage: GroupAlgebra(CyclicPermutationGroup(3), QQ) in CommutativeRings() # not implemented, needs sage.groups sage.modules True """ @@ -110,63 +110,62 @@ def over(self, base=None, gen=None, gens=None, name=None, names=None): We construct an extension of finite fields:: - sage: F = GF(5^2) # optional - sage.rings.finite_rings - sage: k = GF(5^4) # optional - sage.rings.finite_rings - sage: z4 = k.gen() # optional - sage.rings.finite_rings - - sage: K = k.over(F) # optional - sage.rings.finite_rings - sage: K # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: F = GF(5^2) + sage: k = GF(5^4) + sage: z4 = k.gen() + sage: K = k.over(F); K # needs sage.modules Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base If not explicitly given, the default generator of the top ring (here k) is used and the same name is kept:: - sage: K.gen() # optional - sage.rings.finite_rings + sage: K.gen() # needs sage.modules sage.rings.finite_rings z4 - sage: K(z4) # optional - sage.rings.finite_rings + sage: K(z4) # needs sage.modules sage.rings.finite_rings z4 However, it is possible to specify another generator and/or another name. For example:: - sage: Ka = k.over(F, name='a') # optional - sage.rings.finite_rings - sage: Ka # optional - sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings + sage: Ka = k.over(F, name='a'); Ka Field in a with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base - sage: Ka.gen() # optional - sage.rings.finite_rings + sage: Ka.gen() a - sage: Ka(z4) # optional - sage.rings.finite_rings + sage: Ka(z4) a - sage: Kb = k.over(F, gen=-z4+1, name='b') # optional - sage.rings.finite_rings - sage: Kb # optional - sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings + sage: Kb = k.over(F, gen=-z4+1, name='b') + sage: Kb Field in b with defining polynomial x^2 + z2*x + 4 over its base - sage: Kb.gen() # optional - sage.rings.finite_rings + sage: Kb.gen() b - sage: Kb(-z4+1) # optional - sage.rings.finite_rings + sage: Kb(-z4+1) b Note that the shortcut ``K.`` is also available:: - sage: KKa. = k.over(F) # optional - sage.rings.finite_rings - sage: KKa is Ka # optional - sage.rings.finite_rings + sage: KKa. = k.over(F) # needs sage.modules sage.rings.finite_rings + sage: KKa is Ka # needs sage.modules sage.rings.finite_rings True Building an extension on top of another extension is allowed:: - sage: L = GF(5^12).over(K) # optional - sage.rings.finite_rings - sage: L # optional - sage.rings.finite_rings + sage: L = GF(5^12).over(K); L # needs sage.modules sage.rings.finite_rings Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base - sage: L.base_ring() # optional - sage.rings.finite_rings + sage: L.base_ring() # needs sage.modules sage.rings.finite_rings Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base The successive bases of an extension are accessible via the method :meth:`sage.rings.ring_extension.RingExtension_generic.bases`:: - sage: L.bases() # optional - sage.rings.finite_rings + sage: L.bases() # needs sage.modules sage.rings.finite_rings [Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base, Field in z4 with defining polynomial @@ -176,32 +175,32 @@ def over(self, base=None, gen=None, gens=None, name=None, names=None): When ``base`` is omitted, the canonical base of the ring is used:: sage: S. = QQ[] - sage: E = S.over() # optional - sage.modules - sage: E # optional - sage.modules + sage: E = S.over(); E # needs sage.modules Univariate Polynomial Ring in x over Rational Field over its base - sage: E.base_ring() # optional - sage.modules + sage: E.base_ring() # needs sage.modules Rational Field Here is an example where ``base`` is a defining morphism:: - sage: k. = QQ.extension(x^2 - 2) # optional - sage.rings.number_field - sage: l. = QQ.extension(x^4 - 2) # optional - sage.rings.number_field - sage: f = k.hom([b^2]) # optional - sage.rings.number_field - sage: L = l.over(f) # optional - sage.rings.number_field - sage: L # optional - sage.rings.number_field + sage: # needs sage.modules sage.rings.number_field + sage: k. = QQ.extension(x^2 - 2) + sage: l. = QQ.extension(x^4 - 2) + sage: f = k.hom([b^2]) + sage: L = l.over(f) + sage: L Field in b with defining polynomial x^2 - a over its base - sage: L.base_ring() # optional - sage.rings.number_field + sage: L.base_ring() Number Field in a with defining polynomial x^2 - 2 Similarly, one can create a tower of extensions:: - sage: K = k.over() # optional - sage.rings.number_field - sage: L = l.over(Hom(K, l)(f)) # optional - sage.rings.number_field - sage: L # optional - sage.rings.number_field + sage: # needs sage.modules sage.rings.number_field + sage: K = k.over() + sage: L = l.over(Hom(K, l)(f)); L Field in b with defining polynomial x^2 - a over its base - sage: L.base_ring() # optional - sage.rings.number_field + sage: L.base_ring() Field in a with defining polynomial x^2 - 2 over its base - sage: L.bases() # optional - sage.rings.number_field + sage: L.bases() [Field in b with defining polynomial x^2 - a over its base, Field in a with defining polynomial x^2 - 2 over its base, Rational Field] @@ -227,7 +226,7 @@ class Finite(CategoryWithAxiom): EXAMPLES:: - sage: cartesian_product([Zmod(34), # optional - sage.rings.finite_rings + sage: cartesian_product([Zmod(34), ....: GF(5)]) in Rings().Commutative().Finite() True """ @@ -285,34 +284,36 @@ def cyclotomic_cosets(self, q, cosets=None): cyclic, the set of squares is a particular case of cyclotomic coset:: - sage: K = GF(25, 'z') # optional - sage.rings.finite_rings - sage: a = K.multiplicative_generator() # optional - sage.rings.finite_rings - sage: K.cyclotomic_cosets(a**2, cosets=[1]) # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: K = GF(25, 'z') + sage: a = K.multiplicative_generator() + sage: K.cyclotomic_cosets(a**2, cosets=[1]) [[1, 2, 3, 4, z + 1, z + 3, 2*z + 1, 2*z + 2, 3*z + 3, 3*z + 4, 4*z + 2, 4*z + 4]] - sage: sorted(b for b in K if not b.is_zero() and b.is_square()) # optional - sage.rings.finite_rings + sage: sorted(b for b in K if not b.is_zero() and b.is_square()) [1, 2, 3, 4, z + 1, z + 3, 2*z + 1, 2*z + 2, 3*z + 3, 3*z + 4, 4*z + 2, 4*z + 4] We compute some examples of minimal polynomials:: - sage: K = GF(27, 'z') # optional - sage.rings.finite_rings - sage: a = K.multiplicative_generator() # optional - sage.rings.finite_rings - sage: R. = PolynomialRing(K, 'X') # optional - sage.rings.finite_rings - sage: a.minimal_polynomial('X') # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: K = GF(27, 'z') + sage: a = K.multiplicative_generator() + sage: R. = PolynomialRing(K, 'X') + sage: a.minimal_polynomial('X') X^3 + 2*X + 1 - sage: cyc3 = Zmod(26).cyclotomic_cosets(3, cosets=[1]); cyc3 # optional - sage.rings.finite_rings + + sage: cyc3 = Zmod(26).cyclotomic_cosets(3, cosets=[1]); cyc3 [[1, 3, 9]] - sage: prod(X - a**i for i in cyc3[0]) # optional - sage.rings.finite_rings + sage: prod(X - a**i for i in cyc3[0]) # needs sage.rings.finite_rings X^3 + 2*X + 1 - - sage: (a**7).minimal_polynomial('X') # optional - sage.rings.finite_rings + sage: (a**7).minimal_polynomial('X') # needs sage.rings.finite_rings X^3 + X^2 + 2*X + 1 - sage: cyc7 = Zmod(26).cyclotomic_cosets(3, cosets=[7]); cyc7 # optional - sage.rings.finite_rings + sage: cyc7 = Zmod(26).cyclotomic_cosets(3, cosets=[7]); cyc7 [[7, 11, 21]] - sage: prod(X - a**i for i in cyc7[0]) # optional - sage.rings.finite_rings + sage: prod(X - a**i for i in cyc7[0]) # needs sage.rings.finite_rings X^3 + X^2 + 2*X + 1 Cyclotomic cosets of fields are useful in combinatorial design @@ -321,26 +322,26 @@ def cyclotomic_cosets(self, q, cosets=None): :mod:`~sage.combinat.designs.difference_family`). This is illustrated on the following examples:: - sage: K = GF(5) # optional - sage.rings.finite_rings - sage: a = K.multiplicative_generator() # optional - sage.rings.finite_rings - sage: H = K.cyclotomic_cosets(a**2, cosets=[1, 2]); H # optional - sage.rings.finite_rings + sage: K = GF(5) + sage: a = K.multiplicative_generator() # needs sage.libs.pari + sage: H = K.cyclotomic_cosets(a**2, cosets=[1, 2]); H # needs sage.rings.finite_rings [[1, 4], [2, 3]] - sage: sorted(x - y for D in H for x in D for y in D if x != y) # optional - sage.rings.finite_rings + sage: sorted(x - y for D in H for x in D for y in D if x != y) # needs sage.rings.finite_rings [1, 2, 3, 4] - sage: K = GF(37) # optional - sage.rings.finite_rings - sage: a = K.multiplicative_generator() # optional - sage.rings.finite_rings - sage: H = K.cyclotomic_cosets(a**4, cosets=[1]); H # optional - sage.rings.finite_rings + sage: K = GF(37) + sage: a = K.multiplicative_generator() # needs sage.libs.pari + sage: H = K.cyclotomic_cosets(a**4, cosets=[1]); H # needs sage.rings.finite_rings [[1, 7, 9, 10, 12, 16, 26, 33, 34]] - sage: sorted(x - y for D in H for x in D for y in D if x != y) # optional - sage.rings.finite_rings + sage: sorted(x - y for D in H for x in D for y in D if x != y) # needs sage.rings.finite_rings [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ..., 33, 34, 34, 35, 35, 36, 36] The method ``cyclotomic_cosets`` works on any finite commutative ring:: - sage: R = cartesian_product([GF(7), Zmod(14)]) # optional - sage.rings.finite_rings - sage: a = R((3,5)) # optional - sage.rings.finite_rings - sage: R.cyclotomic_cosets((3,5), [(1,1)]) # optional - sage.rings.finite_rings + sage: R = cartesian_product([GF(7), Zmod(14)]) + sage: a = R((3,5)) + sage: R.cyclotomic_cosets((3,5), [(1,1)]) [[(1, 1), (2, 11), (3, 5), (4, 9), (5, 3), (6, 13)]] """ q = self(q) @@ -348,7 +349,7 @@ def cyclotomic_cosets(self, q, cosets=None): try: ~q except ZeroDivisionError: - raise ValueError("%s is not invertible in %s"%(q,self)) + raise ValueError("%s is not invertible in %s" % (q,self)) if cosets is None: rest = set(self) @@ -380,7 +381,7 @@ def extra_super_categories(self): sage: CommutativeRings().Commutative().CartesianProducts().extra_super_categories() [Category of commutative rings] - sage: cartesian_product([ZZ, Zmod(34), # optional - sage.rings.finite_rings + sage: cartesian_product([ZZ, Zmod(34), ....: QQ, GF(5)]) in CommutativeRings() True """ diff --git a/src/sage/categories/complete_discrete_valuation.py b/src/sage/categories/complete_discrete_valuation.py index 71c7ec57015..442360465a1 100644 --- a/src/sage/categories/complete_discrete_valuation.py +++ b/src/sage/categories/complete_discrete_valuation.py @@ -22,13 +22,13 @@ class CompleteDiscreteValuationRings(Category_singleton): EXAMPLES:: - sage: Zp(7) in CompleteDiscreteValuationRings() # optional - sage.rings.padics + sage: Zp(7) in CompleteDiscreteValuationRings() # needs sage.rings.padics True sage: QQ in CompleteDiscreteValuationRings() False sage: QQ[['u']] in CompleteDiscreteValuationRings() True - sage: Qp(7) in CompleteDiscreteValuationRings() # optional - sage.rings.padics + sage: Qp(7) in CompleteDiscreteValuationRings() # needs sage.rings.padics False sage: TestSuite(CompleteDiscreteValuationRings()).run() """ @@ -49,10 +49,10 @@ def valuation(self): EXAMPLES:: - sage: R = Zp(7) # optional - sage.rings.padics - sage: x = R(7); x # optional - sage.rings.padics + sage: R = Zp(7) # needs sage.rings.padics + sage: x = R(7); x # needs sage.rings.padics 7 + O(7^21) - sage: x.valuation() # optional - sage.rings.padics + sage: x.valuation() # needs sage.rings.padics 1 """ @@ -63,32 +63,32 @@ def denominator(self): EXAMPLES:: - sage: K = Qp(7) # optional - sage.rings.padics - sage: x = K(1/21) # optional - sage.rings.padics - sage: x.denominator() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K = Qp(7) + sage: x = K(1/21) + sage: x.denominator() 7 + O(7^21) - - sage: x = K(7) # optional - sage.rings.padics - sage: x.denominator() # optional - sage.rings.padics + sage: x = K(7) + sage: x.denominator() 1 + O(7^20) Note that the denominator lives in the ring of integers:: - sage: x.denominator().parent() # optional - sage.rings.padics + sage: x.denominator().parent() # needs sage.rings.padics 7-adic Ring with capped relative precision 20 When the denominator is indistinguishable from 0 and the precision on the input is `O(p^n)`, the return value is `1` if `n` is nonnegative and `p^(-n)` otherwise:: - sage: x = K(0, 5); x # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: x = K(0, 5); x O(7^5) - sage: x.denominator() # optional - sage.rings.padics + sage: x.denominator() 1 + O(7^20) - - sage: x = K(0, -5); x # optional - sage.rings.padics + sage: x = K(0, -5); x O(7^-5) - sage: x.denominator() # optional - sage.rings.padics + sage: x.denominator() 7^5 + O(7^25) """ return self.parent()(1) @@ -101,26 +101,26 @@ def numerator(self): EXAMPLES:: - sage: K = Qp(7, 5) # optional - sage.rings.padics - sage: x = K(1/21) # optional - sage.rings.padics - sage: x.numerator() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K = Qp(7, 5) + sage: x = K(1/21) + sage: x.numerator() 5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + O(7^5) - - sage: x == x.numerator() / x.denominator() # optional - sage.rings.padics + sage: x == x.numerator() / x.denominator() True Note that the numerator lives in the ring of integers:: - sage: x.numerator().parent() # optional - sage.rings.padics + sage: x.numerator().parent() # needs sage.rings.padics 7-adic Ring with capped relative precision 5 TESTS:: - sage: x = K(0, -5); x # optional - sage.rings.padics + sage: x = K(0, -5); x # needs sage.rings.padics O(7^-5) - sage: x.numerator() # optional - sage.rings.padics + sage: x.numerator() # needs sage.rings.padics O(7^0) - sage: x.denominator() # optional - sage.rings.padics + sage: x.denominator() # needs sage.rings.padics 7^5 + O(7^10) """ return self @@ -146,22 +146,23 @@ def lift_to_precision(self, absprec=None): EXAMPLES:: - sage: R = ZpCA(17) # optional - sage.rings.padics - sage: R(-1, 2).lift_to_precision(10) # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R = ZpCA(17) + sage: R(-1, 2).lift_to_precision(10) 16 + 16*17 + O(17^10) - sage: R(1, 15).lift_to_precision(10) # optional - sage.rings.padics + sage: R(1, 15).lift_to_precision(10) 1 + O(17^15) - sage: R(1, 15).lift_to_precision(30) # optional - sage.rings.padics + sage: R(1, 15).lift_to_precision(30) Traceback (most recent call last): ... PrecisionError: precision higher than allowed by the precision cap - sage: (R(-1, 2).lift_to_precision().precision_absolute() # optional - sage.rings.padics + sage: (R(-1, 2).lift_to_precision().precision_absolute() ....: == R.precision_cap()) True - sage: R = Zp(5); c = R(17, 3); c.lift_to_precision(8) # optional - sage.rings.padics + sage: R = Zp(5); c = R(17, 3); c.lift_to_precision(8) # needs sage.rings.padics 2 + 3*5 + O(5^8) - sage: c.lift_to_precision().precision_relative() == R.precision_cap() # optional - sage.rings.padics + sage: c.lift_to_precision().precision_relative() == R.precision_cap() # needs sage.rings.padics True """ @@ -172,13 +173,13 @@ class CompleteDiscreteValuationFields(Category_singleton): EXAMPLES:: - sage: Zp(7) in CompleteDiscreteValuationFields() # optional - sage.rings.padics + sage: Zp(7) in CompleteDiscreteValuationFields() # needs sage.rings.padics False sage: QQ in CompleteDiscreteValuationFields() False sage: LaurentSeriesRing(QQ, 'u') in CompleteDiscreteValuationFields() True - sage: Qp(7) in CompleteDiscreteValuationFields() # optional - sage.rings.padics + sage: Qp(7) in CompleteDiscreteValuationFields() # needs sage.rings.padics True sage: TestSuite(CompleteDiscreteValuationFields()).run() """ @@ -200,10 +201,10 @@ def valuation(self): EXAMPLES:: - sage: K = Qp(7) # optional - sage.rings.padics - sage: x = K(7); x # optional - sage.rings.padics + sage: K = Qp(7) # needs sage.rings.padics + sage: x = K(7); x # needs sage.rings.padics 7 + O(7^21) - sage: x.valuation() # optional - sage.rings.padics + sage: x.valuation() # needs sage.rings.padics 1 """ @@ -214,32 +215,32 @@ def denominator(self): EXAMPLES:: - sage: K = Qp(7) # optional - sage.rings.padics - sage: x = K(1/21) # optional - sage.rings.padics - sage: x.denominator() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K = Qp(7) + sage: x = K(1/21) + sage: x.denominator() 7 + O(7^21) - - sage: x = K(7) # optional - sage.rings.padics - sage: x.denominator() # optional - sage.rings.padics + sage: x = K(7) + sage: x.denominator() 1 + O(7^20) Note that the denominator lives in the ring of integers:: - sage: x.denominator().parent() # optional - sage.rings.padics + sage: x.denominator().parent() # needs sage.rings.padics 7-adic Ring with capped relative precision 20 When the denominator is indistinguishable from 0 and the precision on the input is `O(p^n)`, the return value is `1` if `n` is nonnegative and `p^(-n)` otherwise:: - sage: x = K(0, 5); x # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: x = K(0, 5); x O(7^5) - sage: x.denominator() # optional - sage.rings.padics + sage: x.denominator() 1 + O(7^20) - - sage: x = K(0, -5); x # optional - sage.rings.padics + sage: x = K(0, -5); x O(7^-5) - sage: x.denominator() # optional - sage.rings.padics + sage: x.denominator() 7^5 + O(7^25) """ val = self.valuation() @@ -257,26 +258,26 @@ def numerator(self): EXAMPLES:: - sage: K = Qp(7, 5) # optional - sage.rings.padics - sage: x = K(1/21) # optional - sage.rings.padics - sage: x.numerator() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K = Qp(7, 5) + sage: x = K(1/21) + sage: x.numerator() 5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + O(7^5) - - sage: x == x.numerator() / x.denominator() # optional - sage.rings.padics + sage: x == x.numerator() / x.denominator() True Note that the numerator lives in the ring of integers:: - sage: x.numerator().parent() # optional - sage.rings.padics + sage: x.numerator().parent() # needs sage.rings.padics 7-adic Ring with capped relative precision 5 TESTS:: - sage: x = K(0, -5); x # optional - sage.rings.padics + sage: x = K(0, -5); x # needs sage.rings.padics O(7^-5) - sage: x.numerator() # optional - sage.rings.padics + sage: x.numerator() # needs sage.rings.padics O(7^0) - sage: x.denominator() # optional - sage.rings.padics + sage: x.denominator() # needs sage.rings.padics 7^5 + O(7^10) """ R = self.parent().integer_ring() diff --git a/src/sage/categories/complex_reflection_groups.py b/src/sage/categories/complex_reflection_groups.py index e55b16eb6a0..fbc04ff329c 100644 --- a/src/sage/categories/complex_reflection_groups.py +++ b/src/sage/categories/complex_reflection_groups.py @@ -64,18 +64,18 @@ class ComplexReflectionGroups(Category_singleton): An example of a reflection group:: - sage: W = ComplexReflectionGroups().example(); W # optional - sage.combinat sage.groups + sage: W = ComplexReflectionGroups().example(); W # needs sage.combinat 5-colored permutations of size 3 ``W`` is in the category of complex reflection groups:: - sage: W in ComplexReflectionGroups() # optional - sage.combinat sage.groups + sage: W in ComplexReflectionGroups() # needs sage.combinat True TESTS:: - sage: TestSuite(W).run() # optional - sage.combinat sage.groups - sage: TestSuite(ComplexReflectionGroups()).run() # optional - sage.combinat sage.groups + sage: TestSuite(W).run() # needs sage.combinat + sage: TestSuite(ComplexReflectionGroups()).run() """ @cached_method @@ -115,7 +115,7 @@ def example(self): EXAMPLES:: sage: from sage.categories.complex_reflection_groups import ComplexReflectionGroups - sage: ComplexReflectionGroups().example() # optional - sage.combinat sage.groups + sage: ComplexReflectionGroups().example() # needs sage.combinat 5-colored permutations of size 3 """ from sage.combinat.colored_permutations import ColoredPermutations @@ -133,9 +133,9 @@ def rank(self): EXAMPLES:: - sage: W = CoxeterGroups().example(); W # optional - sage.groups + sage: W = CoxeterGroups().example(); W The symmetric group on {0, ..., 3} - sage: W.rank() # optional - sage.groups + sage: W.rank() 3 """ diff --git a/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py b/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py index 3dff3b983a6..89667bfc237 100644 --- a/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py +++ b/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups +# sage.doctest: needs sage.groups r""" Common category for Generalized Coxeter Groups or Complex Reflection Groups """ @@ -419,14 +419,15 @@ def reflection_index_set(self): EXAMPLES:: - sage: W = ReflectionGroup((1,1,4)) # optional - gap3 - sage: W.reflection_index_set() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,4)) + sage: W.reflection_index_set() (1, 2, 3, 4, 5, 6) - sage: W = ReflectionGroup((1,1,4), reflection_index_set=[1,3,'asdf',7,9,11]) # optional - gap3 - sage: W.reflection_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), reflection_index_set=[1,3,'asdf',7,9,11]) + sage: W.reflection_index_set() (1, 3, 'asdf', 7, 9, 11) - sage: W = ReflectionGroup((1,1,4), reflection_index_set=('a','b','c','d','e','f')) # optional - gap3 - sage: W.reflection_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), reflection_index_set=('a','b','c','d','e','f')) + sage: W.reflection_index_set() ('a', 'b', 'c', 'd', 'e', 'f') """ @@ -533,14 +534,15 @@ def hyperplane_index_set(self): EXAMPLES:: - sage: W = ReflectionGroup((1,1,4)) # optional - gap3 - sage: W.hyperplane_index_set() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,4)) + sage: W.hyperplane_index_set() (1, 2, 3, 4, 5, 6) - sage: W = ReflectionGroup((1,1,4), hyperplane_index_set=[1,3,'asdf',7,9,11]) # optional - gap3 - sage: W.hyperplane_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), hyperplane_index_set=[1,3,'asdf',7,9,11]) + sage: W.hyperplane_index_set() (1, 3, 'asdf', 7, 9, 11) - sage: W = ReflectionGroup((1,1,4), hyperplane_index_set=('a','b','c','d','e','f')) # optional - gap3 - sage: W.hyperplane_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), hyperplane_index_set=('a','b','c','d','e','f')) + sage: W.hyperplane_index_set() ('a', 'b', 'c', 'd', 'e', 'f') """ @@ -1045,12 +1047,13 @@ def apply_reflections(self, word, side='right', word_type='all'): EXAMPLES:: - sage: W = ReflectionGroup((1,1,3)) # optional - gap3 - sage: W.one().apply_reflections([1]) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,3)) + sage: W.one().apply_reflections([1]) (1,4)(2,3)(5,6) - sage: W.one().apply_reflections([2]) # optional - gap3 + sage: W.one().apply_reflections([2]) (1,3)(2,5)(4,6) - sage: W.one().apply_reflections([2,1]) # optional - gap3 + sage: W.one().apply_reflections([2,1]) (1,2,6)(3,4,5) @@ -1079,14 +1082,15 @@ def apply_reflections(self, word, side='right', word_type='all'): s1 - sage: W = ReflectionGroup((1,1,3)) # optional - gap3 - sage: W.one().apply_reflections([1], word_type='distinguished') # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,3)) + sage: W.one().apply_reflections([1], word_type='distinguished') (1,4)(2,3)(5,6) - sage: W.one().apply_reflections([2], word_type='distinguished') # optional - gap3 + sage: W.one().apply_reflections([2], word_type='distinguished') (1,3)(2,5)(4,6) - sage: W.one().apply_reflections([3], word_type='distinguished') # optional - gap3 + sage: W.one().apply_reflections([3], word_type='distinguished') (1,5)(2,4)(3,6) - sage: W.one().apply_reflections([2,1], word_type='distinguished') # optional - gap3 + sage: W.one().apply_reflections([2,1], word_type='distinguished') (1,2,6)(3,4,5) sage: W = ReflectionGroup((1,1,3), hyperplane_index_set=['A','B','C']); W # optional - gap3 diff --git a/src/sage/categories/covariant_functorial_construction.py b/src/sage/categories/covariant_functorial_construction.py index 90a1c42b1cc..45c94bb7bc1 100644 --- a/src/sage/categories/covariant_functorial_construction.py +++ b/src/sage/categories/covariant_functorial_construction.py @@ -134,8 +134,8 @@ def category_from_parents(self, parents): EXAMPLES:: - sage: E = CombinatorialFreeModule(QQ, ["a", "b", "c"]) # optional - sage.modules - sage: tensor.category_from_parents((E, E, E)) # optional - sage.modules + sage: E = CombinatorialFreeModule(QQ, ["a", "b", "c"]) # needs sage.modules + sage: tensor.category_from_parents((E, E, E)) # needs sage.modules Category of tensor products of finite dimensional vector spaces with basis over Rational Field """ @@ -199,7 +199,7 @@ def _repr_(self): sage: tensor # indirect doctest The tensor functorial construction """ - return "The %s functorial construction"%self._functor_name + return "The %s functorial construction" % self._functor_name def __call__(self, args, **kwargs): """ @@ -214,8 +214,8 @@ def __call__(self, args, **kwargs): EXAMPLES:: - sage: E = CombinatorialFreeModule(QQ, ["a", "b", "c"]); E.rename("E") # optional - sage.modules - sage: tensor((E, E, E)) # optional - sage.modules + sage: E = CombinatorialFreeModule(QQ, ["a", "b", "c"]); E.rename("E") # needs sage.modules + sage: tensor((E, E, E)) # needs sage.modules E # E # E """ args = tuple(args) # a bit brute force; let's see if this becomes a bottleneck later @@ -494,7 +494,7 @@ def _repr_object_names(self): sage: Semigroups().Subquotients() # indirect doctest Category of subquotients of semigroups """ - return "%s of %s"%(Category._repr_object_names(self), self.base_category()._repr_object_names()) + return "%s of %s" % (Category._repr_object_names(self), self.base_category()._repr_object_names()) def _latex_(self): r""" @@ -508,7 +508,7 @@ def _latex_(self): \mathbf{Algebras}(\mathbf{Semigroups}) """ from sage.misc.latex import latex - return "\\mathbf{%s}(%s)"%(self._short_name(), latex(self.base_category())) + return "\\mathbf{%s}(%s)" % (self._short_name(), latex(self.base_category())) class CovariantConstructionCategory(FunctorialConstructionCategory): """ diff --git a/src/sage/categories/coxeter_group_algebras.py b/src/sage/categories/coxeter_group_algebras.py index 623b1078e60..5cececc3fef 100644 --- a/src/sage/categories/coxeter_group_algebras.py +++ b/src/sage/categories/coxeter_group_algebras.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat, sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Coxeter Group Algebras """ @@ -168,10 +168,10 @@ def demazure_lusztig_eigenvectors(self, q1, q2): sage: q1, q2 = K.gens() sage: KW = W.algebra(K) sage: E = KW.demazure_lusztig_eigenvectors(q1,q2) - sage: E.keys() + sage: E.keys() # needs sage.rings.number_field Weyl Group of type ['B', 2] (as a matrix group acting on the ambient space) sage: w = W.an_element() - sage: E[w] + sage: E[w] # needs sage.rings.number_field (q2/(-q1+q2))*2121 + ((-q2)/(-q1+q2))*121 - 212 + 12 """ W = self.basis().keys() diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index a131c61427e..b5e5da9ea1a 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -53,21 +53,21 @@ class CoxeterGroups(Category_singleton): Here are some further examples:: - sage: FiniteCoxeterGroups().example() # optional - sage.combinat sage.groups + sage: FiniteCoxeterGroups().example() The 5-th dihedral group of order 10 - sage: FiniteWeylGroups().example() # optional - sage.combinat sage.groups + sage: FiniteWeylGroups().example() The symmetric group on {0, ..., 3} - sage: WeylGroup(["B", 3]) # optional - sage.combinat sage.groups + sage: WeylGroup(["B", 3]) # needs sage.combinat sage.groups Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space) - sage: S4 = SymmetricGroup(4); S4 # optional - sage.groups + sage: S4 = SymmetricGroup(4); S4 # needs sage.groups Symmetric group of order 4! as a permutation group - sage: S4 in CoxeterGroups().Finite() # optional - sage.groups + sage: S4 in CoxeterGroups().Finite() # needs sage.groups True Those will eventually be also in this category:: - sage: DihedralGroup(5) # optional - sage.groups + sage: DihedralGroup(5) # needs sage.groups Dihedral group of order 10 as a permutation group .. TODO:: add a demo of usual computations on Coxeter groups. @@ -97,7 +97,7 @@ class CoxeterGroups(Category_singleton): TESTS:: sage: W = CoxeterGroups().example() - sage: TestSuite(W).run() # optional - sage.combinat + sage: TestSuite(W).run() """ def super_categories(self): @@ -136,8 +136,8 @@ def coxeter_matrix(self): EXAMPLES:: - sage: G = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: G.coxeter_matrix() # optional - sage.combinat sage.groups + sage: G = WeylGroup(['A', 3]) # needs sage.combinat sage.groups + sage: G.coxeter_matrix() # needs sage.combinat sage.groups [1 3 2] [3 1 3] [2 3 1] @@ -150,14 +150,15 @@ def index_set(self): EXAMPLES:: - sage: W = CoxeterGroup([[1,3],[3,1]]) # optional - sage.combinat sage.groups - sage: W.index_set() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = CoxeterGroup([[1,3],[3,1]]) + sage: W.index_set() (1, 2) - sage: W = CoxeterGroup([[1,3],[3,1]], index_set=['x', 'y']) # optional - sage.combinat sage.groups - sage: W.index_set() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup([[1,3],[3,1]], index_set=['x', 'y']) + sage: W.index_set() ('x', 'y') - sage: W = CoxeterGroup(['H', 3]) # optional - sage.combinat sage.groups - sage: W.index_set() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['H', 3]) + sage: W.index_set() (1, 2, 3) """ return self.coxeter_matrix().index_set() @@ -168,18 +169,19 @@ def coxeter_diagram(self): EXAMPLES:: - sage: W = CoxeterGroup(['H', 3], implementation="reflection") # optional - sage.combinat sage.groups - sage: G = W.coxeter_diagram(); G # optional - sage.combinat sage.groups sage.graphs + sage: # needs sage.combinat sage.graphs sage.groups + sage: W = CoxeterGroup(['H', 3], implementation="reflection") + sage: G = W.coxeter_diagram(); G Graph on 3 vertices - sage: G.edges(sort=True) # optional - sage.combinat sage.groups sage.graphs + sage: G.edges(sort=True) [(1, 2, 3), (2, 3, 5)] - sage: CoxeterGroup(G) is W # optional - sage.combinat sage.groups sage.graphs + sage: CoxeterGroup(G) is W True - sage: G = Graph([(0, 1, 3), (1, 2, oo)]) # optional - sage.combinat sage.groups sage.graphs - sage: W = CoxeterGroup(G) # optional - sage.combinat sage.groups sage.graphs - sage: W.coxeter_diagram() == G # optional - sage.combinat sage.groups sage.graphs + sage: G = Graph([(0, 1, 3), (1, 2, oo)]) + sage: W = CoxeterGroup(G) + sage: W.coxeter_diagram() == G True - sage: CoxeterGroup(W.coxeter_diagram()) is W # optional - sage.combinat sage.groups sage.graphs + sage: CoxeterGroup(W.coxeter_diagram()) is W True """ return self.coxeter_matrix().coxeter_graph() @@ -190,8 +192,8 @@ def coxeter_type(self): EXAMPLES:: - sage: W = CoxeterGroup(['H', 3]) # optional - sage.combinat sage.groups - sage: W.coxeter_type() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['H', 3]) # needs sage.combinat sage.groups + sage: W.coxeter_type() # needs sage.combinat sage.groups Coxeter type of ['H', 3] """ return self.coxeter_matrix().coxeter_type() @@ -203,12 +205,12 @@ def braid_relations(self): EXAMPLES:: - sage: W = WeylGroup(["A", 2]) # optional - sage.combinat sage.groups - sage: W.braid_relations() # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 2]) # needs sage.combinat sage.groups + sage: W.braid_relations() # needs sage.combinat sage.groups [[[1, 2, 1], [2, 1, 2]]] - sage: W = WeylGroup(["B", 3]) # optional - sage.combinat sage.groups - sage: W.braid_relations() # optional - sage.combinat sage.groups + sage: W = WeylGroup(["B", 3]) # needs sage.combinat sage.groups + sage: W.braid_relations() # needs sage.combinat sage.groups [[[1, 2, 1], [2, 1, 2]], [[1, 3], [3, 1]], [[2, 3, 2, 3], [3, 2, 3, 2]]] """ rels = [] @@ -228,12 +230,12 @@ def braid_group_as_finitely_presented_group(self): EXAMPLES:: - sage: W = CoxeterGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: W.braid_group_as_finitely_presented_group() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 2]) # needs sage.combinat sage.groups + sage: W.braid_group_as_finitely_presented_group() # needs sage.combinat sage.groups Finitely presented group < S1, S2 | S1*S2*S1*S2^-1*S1^-1*S2^-1 > - sage: W = WeylGroup(['B', 2]) # optional - sage.combinat sage.groups - sage: W.braid_group_as_finitely_presented_group() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['B', 2]) # needs sage.combinat sage.groups + sage: W.braid_group_as_finitely_presented_group() # needs sage.combinat sage.groups Finitely presented group < S1, S2 | (S1*S2)^2*(S1^-1*S2^-1)^2 > sage: W = ReflectionGroup(['B',3], index_set=["AA","BB","5"]) # optional - gap3 @@ -271,7 +273,7 @@ def braid_orbit_iter(self, word): EXAMPLES:: sage: W = CoxeterGroups().example() - sage: sorted(W.braid_orbit_iter([0, 1, 2, 1])) # optional - sage.combinat sage.groups + sage: sorted(W.braid_orbit_iter([0, 1, 2, 1])) # needs sage.combinat sage.graphs [[0, 1, 2, 1], [0, 2, 1, 2], [2, 0, 1, 2]] """ word = list(word) @@ -326,15 +328,16 @@ def braid_orbit(self, word): sage: word = w.reduced_word(); word [0, 1, 2, 1] - sage: sorted(W.braid_orbit(word)) # optional - sage.combinat sage.groups + sage: sorted(W.braid_orbit(word)) # needs sage.combinat sage.graphs [[0, 1, 2, 1], [0, 2, 1, 2], [2, 0, 1, 2]] - sage: sorted(W.braid_orbit([2,1,1,2,1])) # optional - sage.combinat sage.groups + sage: sorted(W.braid_orbit([2,1,1,2,1])) # needs sage.combinat sage.graphs [[1, 2, 1, 1, 2], [2, 1, 1, 2, 1], [2, 1, 2, 1, 2], [2, 2, 1, 2, 2]] - sage: W = ReflectionGroup(['A',3], index_set=["AA","BB","5"]) # optional - gap3 - sage: w = W.long_element() # optional - gap3 - sage: W.braid_orbit(w.reduced_word()) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',3], index_set=["AA","BB","5"]) + sage: w = W.long_element() + sage: W.braid_orbit(w.reduced_word()) [['BB', '5', 'AA', 'BB', '5', 'AA'], ['5', 'BB', '5', 'AA', 'BB', '5'], ['BB', 'AA', 'BB', '5', 'BB', 'AA'], @@ -382,17 +385,18 @@ def __iter__(self): (2, 1, 2), (2, 1, 2, 1)] - sage: W = WeylGroup(["A", 2, 1]) # optional - sage.combinat sage.groups - sage: g = iter(W) # optional - sage.combinat sage.groups - sage: next(g) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 2, 1]) + sage: g = iter(W) + sage: next(g) [1 0 0] [0 1 0] [0 0 1] - sage: next(g) # optional - sage.combinat sage.groups + sage: next(g) [-1 1 1] [ 0 1 0] [ 0 0 1] - sage: next(g) # optional - sage.combinat sage.groups + sage: next(g) [ 1 0 0] [ 1 -1 1] [ 0 0 1] @@ -405,19 +409,20 @@ def _element_constructor_(self, x, **args): EXAMPLES:: - sage: W1 = WeylGroup("G2", prefix="s") # optional - sage.combinat sage.groups - sage: W2 = CoxeterGroup("G2") # optional - sage.combinat sage.groups - sage: W3 = CoxeterGroup("G2", implementation="permutation") # optional - sage.combinat sage.groups - sage: W1(W2.an_element()) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W1 = WeylGroup("G2", prefix="s") + sage: W2 = CoxeterGroup("G2") + sage: W3 = CoxeterGroup("G2", implementation="permutation") + sage: W1(W2.an_element()) s1*s2 - sage: W2(W1.an_element()) # optional - sage.combinat sage.groups + sage: W2(W1.an_element()) [ 2 -a] [ a -1] - sage: W1(W3.an_element()) # optional - sage.combinat sage.groups + sage: W1(W3.an_element()) s1*s2 - sage: s1, s2 = W1.simple_reflections() # optional - sage.combinat sage.groups - sage: W = CoxeterGroup("A1") # optional - sage.combinat sage.groups - sage: W(s1 * s2) # optional - sage.combinat sage.groups + sage: s1, s2 = W1.simple_reflections() + sage: W = CoxeterGroup("A1") + sage: W(s1 * s2) Traceback (most recent call last): ... ValueError: inconsistent number of rows: should be 1 but got 3 @@ -455,9 +460,9 @@ def weak_order_ideal(self, predicate, side="right", category=None): We now consider an infinite Coxeter group:: - sage: W = WeylGroup(["A",1,1]) - sage: I = W.weak_order_ideal(predicate = lambda w: w.length() <= 2) - sage: list(iter(I)) + sage: W = WeylGroup(["A",1,1]) # needs sage.groups sage.rings.number_field + sage: I = W.weak_order_ideal(predicate=lambda w: w.length() <= 2) # needs sage.groups sage.rings.number_field + sage: list(iter(I)) # needs sage.groups sage.rings.number_field [ [1 0] [-1 2] [ 1 0] [ 3 -2] [-1 2] [0 1], [ 0 1], [ 2 -1], [ 2 -1], [-2 3] @@ -466,17 +471,17 @@ def weak_order_ideal(self, predicate, side="right", category=None): Even when the result is finite, some features of :class:`FiniteEnumeratedSets` are not available:: - sage: I.cardinality() # todo: not implemented + sage: I.cardinality() # todo: not implemented 5 - sage: list(I) # todo: not implemented + sage: list(I) # todo: not implemented unless this finiteness is explicitly specified:: - sage: I = W.weak_order_ideal(predicate = lambda w: w.length() <= 2, - ....: category = FiniteEnumeratedSets()) - sage: I.cardinality() + sage: I = W.weak_order_ideal(predicate=lambda w: w.length() <= 2, # needs sage.groups sage.rings.number_field + ....: category=FiniteEnumeratedSets()) + sage: I.cardinality() # needs sage.groups sage.rings.number_field 5 - sage: list(I) + sage: list(I) # needs sage.groups sage.rings.number_field [ [1 0] [-1 2] [ 1 0] [ 3 -2] [-1 2] [0 1], [ 0 1], [ 2 -1], [ 2 -1], [-2 3] @@ -499,8 +504,8 @@ def weak_order_ideal(self, predicate, side="right", category=None): We iterate over each level (i.e., breadth-first-search in the search forest), see :trac:`19926`:: - sage: W = CoxeterGroup(['A',2]) - sage: [x.length() for x in W] + sage: W = CoxeterGroup(['A',2]) # needs sage.groups sage.rings.number_field + sage: [x.length() for x in W] # needs sage.groups sage.rings.number_field [0, 1, 1, 2, 2, 3] """ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest @@ -513,9 +518,10 @@ def succ(u): from sage.categories.finite_coxeter_groups import FiniteCoxeterGroups default_category = FiniteEnumeratedSets() if self in FiniteCoxeterGroups() else EnumeratedSets() + cat = default_category.or_subcategory(category) return RecursivelyEnumeratedSet_forest((self.one(),), succ, - algorithm='breadth', - category=default_category.or_subcategory(category)) + algorithm='breadth', + category=cat) @cached_method def coxeter_element(self): @@ -539,17 +545,18 @@ def coxeter_element(self): EXAMPLES:: - sage: CoxeterGroup(['A', 4]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: CoxeterGroup(['A', 4]).coxeter_element().reduced_word() [1, 2, 3, 4] - sage: CoxeterGroup(['B', 4]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: CoxeterGroup(['B', 4]).coxeter_element().reduced_word() [1, 2, 3, 4] - sage: CoxeterGroup(['D', 4]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: CoxeterGroup(['D', 4]).coxeter_element().reduced_word() [1, 2, 4, 3] - sage: CoxeterGroup(['F', 4]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: CoxeterGroup(['F', 4]).coxeter_element().reduced_word() [1, 2, 3, 4] - sage: CoxeterGroup(['E', 8]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: CoxeterGroup(['E', 8]).coxeter_element().reduced_word() [1, 3, 2, 4, 5, 6, 7, 8] - sage: CoxeterGroup(['H', 3]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: CoxeterGroup(['H', 3]).coxeter_element().reduced_word() [1, 2, 3] This method is also used for well generated finite complex @@ -573,9 +580,9 @@ def coxeter_element(self): TESTS:: - sage: WeylGroup(['A', 4]).coxeter_element().reduced_word() # optional - sage.combinat sage.groups + sage: WeylGroup(['A', 4]).coxeter_element().reduced_word() # needs sage.combinat sage.groups [1, 2, 3, 4] - sage: SymmetricGroup(3).coxeter_element() # optional - sage.combinat sage.groups + sage: SymmetricGroup(3).coxeter_element() # needs sage.groups (1,3,2) """ return self.prod(self.simple_reflections()) @@ -603,24 +610,24 @@ class is not unique and we only obtain one such class. TESTS:: - sage: W = SymmetricGroup(3) # optional - sage.combinat sage.groups - sage: sorted(W.standard_coxeter_elements()) # optional - sage.combinat sage.groups + sage: W = SymmetricGroup(3) # needs sage.groups + sage: sorted(W.standard_coxeter_elements()) # needs sage.combinat sage.groups [(1,2,3), (1,3,2)] - sage: W = Permutations(3) # optional - sage.combinat sage.groups - sage: sorted(W.standard_coxeter_elements()) # optional - sage.combinat sage.groups + sage: W = Permutations(3) + sage: sorted(W.standard_coxeter_elements()) # needs sage.graphs [[2, 3, 1], [3, 1, 2]] - sage: W = CoxeterGroup(['D', 3]) # optional - sage.combinat sage.groups - sage: sorted(W.standard_coxeter_elements()) # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['D', 3]) # needs sage.combinat sage.groups + sage: sorted(W.standard_coxeter_elements()) # needs sage.combinat sage.groups [ [-1 1 1] [ 0 -1 1] [ 0 1 -1] [ 1 -1 -1] [-1 0 1] [ 1 -1 0] [ 0 0 -1] [ 1 -1 0] [-1 1 0], [ 0 -1 0], [ 1 0 -1], [ 1 0 -1] ] - sage: W = ColoredPermutations(3,2) # optional - sage.combinat sage.groups - sage: len(W.standard_coxeter_elements()) # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(3,2) # needs sage.combinat + sage: len(W.standard_coxeter_elements()) # needs sage.combinat sage.graphs 2 """ if not self.is_irreducible() or not self.is_well_generated(): @@ -670,7 +677,7 @@ def fully_commutative_elements(self): EXAMPLES:: - sage: CoxeterGroup(['A', 3]).fully_commutative_elements() # optional - sage.combinat sage.groups + sage: CoxeterGroup(['A', 3]).fully_commutative_elements() # needs sage.combinat sage.groups Fully commutative elements of Finite Coxeter group over Integer Ring with Coxeter matrix: [1 3 2] @@ -767,9 +774,10 @@ def kazhdan_lusztig_cells(self, side='left'): representation of elements in the output cells but not the method used for the cell computation:: - sage: W = CoxeterGroup('A2') # optional - sage.combinat sage.groups - sage: KL_cells = W.kazhdan_lusztig_cells(side='right') # optional - sage.combinat sage.groups - sage: set([tuple(sorted(C, key=lambda w: w.reduced_word())) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = CoxeterGroup('A2') + sage: KL_cells = W.kazhdan_lusztig_cells(side='right') + sage: set([tuple(sorted(C, key=lambda w: w.reduced_word())) ....: for C in KL_cells]) {( [-1 1] [ 0 -1] @@ -787,11 +795,11 @@ def kazhdan_lusztig_cells(self, side='left'): [ 1 0] [-1 1] [ 1 -1], [-1 0] )} - sage: len(KL_cells) # optional - sage.combinat sage.groups + sage: len(KL_cells) 4 - sage: W = CoxeterGroup('A2', implementation='permutation') # optional - sage.combinat sage.groups - sage: len(W.kazhdan_lusztig_cells(side='right')) # optional - sage.combinat sage.groups + sage: W = CoxeterGroup('A2', implementation='permutation') # needs sage.combinat sage.groups + sage: len(W.kazhdan_lusztig_cells(side='right')) # needs sage.combinat sage.groups 4 We compute the left cells in the Coxeter group of type `A_3` @@ -799,9 +807,10 @@ def kazhdan_lusztig_cells(self, side='left'): runs in the background even if the group is not created with the ``'coxeter3'`` implementation:: - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: KL_cells = W.kazhdan_lusztig_cells() # optional - coxeter3 - sage: set([tuple(sorted(C)) for C in KL_cells]) # optional - coxeter3 + sage: # optional - coxeter3, needs sage.combinat sage.groups sage.libs.gap sage.modules sage.rings.number_field + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: KL_cells = W.kazhdan_lusztig_cells() + sage: set([tuple(sorted(C)) for C in KL_cells]) {([],), ([1], [2, 1], [3, 2, 1]), ([1, 2], [2], [3, 2]), @@ -812,20 +821,20 @@ def kazhdan_lusztig_cells(self, side='left'): ([1, 2, 3], [2, 3], [3]), ([1, 3], [2, 1, 3]), ([1, 3, 2], [2, 1, 3, 2])} - sage: len(KL_cells) # optional - coxeter3 + sage: len(KL_cells) 10 - - sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 - sage: len(W.kazhdan_lusztig_cells()) # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='permutation') + sage: len(W.kazhdan_lusztig_cells()) 10 Computing the two sided cells in `B_3`:: - sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 - sage: b3_cells = W.kazhdan_lusztig_cells('two-sided') # optional - coxeter3 - sage: len(b3_cells) # optional - coxeter3 + sage: # optional - coxeter3, needs sage.combinat sage.groups sage.libs.gap sage.modules sage.rings.number_field + sage: W = CoxeterGroup('B3', implementation='coxeter3') + sage: b3_cells = W.kazhdan_lusztig_cells('two-sided') + sage: len(b3_cells) 6 - sage: set([tuple(sorted(C)) # optional - coxeter3 + sage: set([tuple(sorted(C)) ....: for C in W.kazhdan_lusztig_cells()]) {([],), ([1], [1, 2, 3, 2, 1], [2, 1], [2, 3, 2, 1], [3, 2, 1]), @@ -855,8 +864,8 @@ def kazhdan_lusztig_cells(self, side='left'): TESTS:: - sage: W = CoxeterGroup(['A', 2, 1]) # optional - sage.combinat sage.groups - sage: W.kazhdan_lusztig_cells() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 2, 1]) # needs sage.combinat sage.groups + sage: W.kazhdan_lusztig_cells() # needs sage.combinat sage.groups Traceback (most recent call last): ... ValueError: the Coxeter group must be finite to compute Kazhdan--Lusztig cells @@ -939,8 +948,8 @@ def sign_representation(self, base_ring=None, side="twosided"): EXAMPLES:: - sage: W = WeylGroup(["A", 1, 1]) # optional - sage.combinat sage.groups - sage: W.sign_representation() # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 1, 1]) # needs sage.combinat sage.groups + sage: W.sign_representation() # needs sage.combinat sage.groups Sign representation of Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space) over Integer Ring @@ -967,18 +976,18 @@ def demazure_product(self, Q): EXAMPLES:: - sage: W = WeylGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: w = W.demazure_product([2,2,1]) # optional - sage.combinat sage.groups - sage: w.reduced_word() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 2]) + sage: w = W.demazure_product([2,2,1]) + sage: w.reduced_word() [2, 1] - - sage: w = W.demazure_product([2,1,2,1,2]) # optional - sage.combinat sage.groups - sage: w.reduced_word() # optional - sage.combinat sage.groups + sage: w = W.demazure_product([2,1,2,1,2]) + sage: w.reduced_word() [1, 2, 1] - sage: W = WeylGroup(['B', 2]) # optional - sage.combinat sage.groups - sage: w = W.demazure_product([2,1,2,1,2]) # optional - sage.combinat sage.groups - sage: w.reduced_word() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['B', 2]) # needs sage.combinat sage.groups + sage: w = W.demazure_product([2,1,2,1,2]) # needs sage.combinat sage.groups + sage: w.reduced_word() # needs sage.combinat sage.groups [2, 1, 2, 1] """ return self.one().apply_demazure_product(Q) @@ -989,16 +998,16 @@ def bruhat_interval(self, x, y): EXAMPLES:: - sage: W = WeylGroup("A3", prefix="s") # optional - sage.combinat sage.groups - sage: s1, s2, s3 = W.simple_reflections() # optional - sage.combinat sage.groups - sage: W.bruhat_interval(s2, s1*s3*s2*s1*s3) # optional - sage.combinat sage.groups + sage: W = WeylGroup("A3", prefix="s") # needs sage.combinat sage.groups + sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.groups + sage: W.bruhat_interval(s2, s1*s3*s2*s1*s3) # needs sage.combinat sage.groups [s1*s2*s3*s2*s1, s2*s3*s2*s1, s3*s1*s2*s1, s1*s2*s3*s1, s1*s2*s3*s2, s3*s2*s1, s2*s3*s1, s2*s3*s2, s1*s2*s1, s3*s1*s2, s1*s2*s3, s2*s1, s3*s2, s2*s3, s1*s2, s2] - sage: W = WeylGroup(['A', 2, 1], prefix="s") # optional - sage.combinat sage.groups - sage: s0, s1, s2 = W.simple_reflections() # optional - sage.combinat sage.groups - sage: W.bruhat_interval(1, s0*s1*s2) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 2, 1], prefix="s") # needs sage.combinat sage.groups + sage: s0, s1, s2 = W.simple_reflections() # needs sage.combinat sage.groups + sage: W.bruhat_interval(1, s0*s1*s2) # needs sage.combinat sage.groups [s0*s1*s2, s1*s2, s0*s2, s0*s1, s2, s1, s0, 1] """ if x == 1: @@ -1028,19 +1037,19 @@ def bruhat_interval_poset(self, x, y, facade=False): EXAMPLES:: - sage: W = WeylGroup("A3", prefix="s") # optional - sage.combinat sage.groups - sage: s1, s2, s3 = W.simple_reflections() # optional - sage.combinat sage.groups - sage: W.bruhat_interval_poset(s2, s1*s3*s2*s1*s3) # optional - sage.combinat sage.groups + sage: W = WeylGroup("A3", prefix="s") # needs sage.combinat sage.groups + sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.groups + sage: W.bruhat_interval_poset(s2, s1*s3*s2*s1*s3) # needs sage.combinat sage.groups Finite poset containing 16 elements - sage: W = WeylGroup(['A', 2, 1], prefix="s") # optional - sage.combinat sage.groups - sage: s0, s1, s2 = W.simple_reflections() # optional - sage.combinat sage.groups - sage: W.bruhat_interval_poset(1, s0*s1*s2) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 2, 1], prefix="s") # needs sage.combinat sage.groups + sage: s0, s1, s2 = W.simple_reflections() # needs sage.combinat sage.groups + sage: W.bruhat_interval_poset(1, s0*s1*s2) # needs sage.combinat sage.groups Finite poset containing 8 elements TESTS:: - sage: W.bruhat_interval_poset(s0*s1*s2, s0*s1*s2) # optional - sage.combinat sage.groups + sage: W.bruhat_interval_poset(s0*s1*s2, s0*s1*s2) # needs sage.combinat sage.groups Finite poset containing 1 elements """ if x == 1: @@ -1095,27 +1104,27 @@ def bruhat_graph(self, x=None, y=None, edge_labels=False): EXAMPLES:: - sage: W = CoxeterGroup(['H', 3]) # optional - sage.combinat sage.groups sage.graphs - sage: G = W.bruhat_graph(); G # optional - sage.combinat sage.groups sage.graphs + sage: W = CoxeterGroup(['H', 3]) # needs sage.combinat sage.graphs sage.groups + sage: G = W.bruhat_graph(); G # needs sage.combinat sage.graphs sage.groups Digraph on 120 vertices - sage: W = CoxeterGroup(['A', 2, 1]) # optional - sage.combinat sage.groups sage.graphs - sage: s1, s2, s3 = W.simple_reflections() # optional - sage.combinat sage.groups sage.graphs - sage: W.bruhat_graph(s1, s1*s3*s2*s3) # optional - sage.combinat sage.groups sage.graphs + sage: # needs sage.combinat sage.graphs sage.groups + sage: W = CoxeterGroup(['A', 2, 1]) + sage: s1, s2, s3 = W.simple_reflections() + sage: W.bruhat_graph(s1, s1*s3*s2*s3) Digraph on 6 vertices - - sage: W.bruhat_graph(s1, s3*s2*s3) # optional - sage.combinat sage.groups sage.graphs + sage: W.bruhat_graph(s1, s3*s2*s3) Digraph on 0 vertices - sage: W = WeylGroup("A3", prefix="s") # optional - sage.combinat sage.groups sage.graphs - sage: s1, s2, s3 = W.simple_reflections() # optional - sage.combinat sage.groups sage.graphs - sage: G = W.bruhat_graph(s1*s3, s1*s2*s3*s2*s1); G # optional - sage.combinat sage.groups sage.graphs + sage: W = WeylGroup("A3", prefix="s") # needs sage.combinat sage.graphs sage.groups + sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.graphs sage.groups + sage: G = W.bruhat_graph(s1*s3, s1*s2*s3*s2*s1); G # needs sage.combinat sage.graphs sage.groups Digraph on 10 vertices Check that the graph has the correct number of edges (see :trac:`17744`):: - sage: len(G.edges(sort=False)) # optional - sage.combinat sage.groups sage.graphs + sage: len(G.edges(sort=False)) # needs sage.combinat sage.graphs sage.groups 16 """ if x is None or x == 1: @@ -1163,8 +1172,8 @@ def canonical_representation(self): EXAMPLES:: - sage: W = WeylGroup("A3") # optional - sage.combinat sage.groups - sage: W.canonical_representation() # optional - sage.combinat sage.groups + sage: W = WeylGroup("A3") # needs sage.combinat sage.groups + sage: W.canonical_representation() # needs sage.combinat sage.groups Finite Coxeter group over Integer Ring with Coxeter matrix: [1 3 2] [3 1 3] @@ -1180,16 +1189,16 @@ def elements_of_length(self, n): EXAMPLES:: - sage: A = AffinePermutationGroup(['A', 2, 1]) # optional - sage.combinat sage.groups - sage: [len(list(A.elements_of_length(i))) for i in [0..5]] # optional - sage.combinat sage.groups + sage: A = AffinePermutationGroup(['A', 2, 1]) # needs sage.combinat + sage: [len(list(A.elements_of_length(i))) for i in [0..5]] # needs sage.combinat [1, 3, 6, 9, 12, 15] - sage: W = CoxeterGroup(['H', 3]) # optional - sage.combinat sage.groups - sage: [len(list(W.elements_of_length(i))) for i in range(4)] # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['H', 3]) # needs sage.combinat sage.groups + sage: [len(list(W.elements_of_length(i))) for i in range(4)] # needs sage.combinat sage.groups [1, 3, 5, 7] - sage: W = CoxeterGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: [len(list(W.elements_of_length(i))) for i in range(6)] # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 2]) # needs sage.combinat sage.groups + sage: [len(list(W.elements_of_length(i))) for i in range(6)] # needs sage.combinat sage.groups [1, 2, 2, 1, 0, 0] """ I = self.weak_order_ideal(ConstantFunction(True), side='right') @@ -1207,18 +1216,20 @@ def random_element_of_length(self, n): EXAMPLES:: - sage: A = AffinePermutationGroup(['A', 7, 1]) # optional - sage.combinat sage.groups - sage: p = A.random_element_of_length(10) # optional - sage.combinat sage.groups - sage: p in A # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: A = AffinePermutationGroup(['A', 7, 1]) + sage: p = A.random_element_of_length(10) + sage: p in A True - sage: p.length() == 10 # optional - sage.combinat sage.groups + sage: p.length() == 10 True - sage: W = CoxeterGroup(['A', 4]) # optional - sage.combinat sage.groups - sage: p = W.random_element_of_length(5) # optional - sage.combinat sage.groups - sage: p in W # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 4]) + sage: p = W.random_element_of_length(5) + sage: p in W True - sage: p.length() == 5 # optional - sage.combinat sage.groups + sage: p.length() == 5 True """ from sage.misc.prandom import randint @@ -1229,10 +1240,6 @@ def random_element_of_length(self, n): x = x.apply_simple_reflection_right(antiD[rnd]) return x - # TODO: Groups() should have inverse() call __invert__ - # With strong doc stating that this is just a convenience for the user - # and links to ~ / __invert__ - # parabolic_subgroup def _test_simple_projections(self, **options): @@ -1270,14 +1277,15 @@ def _test_has_descent(self, **options): sage: W = CoxeterGroups().example() sage: W._test_has_descent() - sage: W = Permutations(4) # optional - sage.combinat sage.groups - sage: W._test_has_descent() # optional - sage.combinat sage.groups - sage: sage.combinat.permutation.Permutations.options.mult = "r2l" # optional - sage.combinat sage.groups - sage: W._test_has_descent() # optional - sage.combinat sage.groups - sage: sage.combinat.permutation.Permutations.options._reset() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = Permutations(4) + sage: W._test_has_descent() + sage: sage.combinat.permutation.Permutations.options.mult = "r2l" + sage: W._test_has_descent() + sage: sage.combinat.permutation.Permutations.options._reset() - sage: W = SignedPermutations(3) # optional - sage.combinat sage.groups - sage: W._test_has_descent() # optional - sage.combinat sage.groups + sage: W = SignedPermutations(3) # needs sage.combinat + sage: W._test_has_descent() """ tester = self._tester(**options) s = self.simple_reflections() @@ -1334,21 +1342,22 @@ def _test_coxeter_relations(self, **options): TESTS:: - sage: A = AffinePermutationGroup(['A', 7, 1]) # optional - sage.combinat sage.groups - sage: A._test_coxeter_relations() # optional - sage.combinat sage.groups + sage: A = AffinePermutationGroup(['A', 7, 1]) # needs sage.combinat + sage: A._test_coxeter_relations() # needs sage.combinat - sage: cm = CartanMatrix([[2,-5,0], [-2,2,-1], [0,-1,2]]) # optional - sage.combinat sage.groups - sage: W = WeylGroup(cm) # optional - sage.combinat sage.groups - sage: W._test_coxeter_relations() # optional - sage.combinat sage.groups + sage: cm = CartanMatrix([[2,-5,0], [-2,2,-1], [0,-1,2]]) # needs sage.graphs + sage: W = WeylGroup(cm) # needs sage.combinat sage.graphs sage.groups + sage: W._test_coxeter_relations() # needs sage.combinat sage.graphs sage.groups - sage: W = Permutations(4) # optional - sage.combinat sage.groups - sage: W._test_coxeter_relations() # optional - sage.combinat sage.groups - sage: sage.combinat.permutation.Permutations.options.mult = "r2l" # optional - sage.combinat sage.groups - sage: W._test_coxeter_relations() # optional - sage.combinat sage.groups - sage: sage.combinat.permutation.Permutations.options._reset() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = Permutations(4) + sage: W._test_coxeter_relations() + sage: sage.combinat.permutation.Permutations.options.mult = "r2l" + sage: W._test_coxeter_relations() + sage: sage.combinat.permutation.Permutations.options._reset() - sage: W = SignedPermutations(3) # optional - sage.combinat sage.groups - sage: W._test_coxeter_relations() # optional - sage.combinat sage.groups + sage: W = SignedPermutations(3) # needs sage.combinat + sage: W._test_coxeter_relations() # needs sage.combinat """ tester = self._tester(**options) s = self.simple_reflections() @@ -1569,6 +1578,7 @@ def is_fully_commutative(self) -> bool: EXAMPLES:: + sage: # needs sage.combinat sage.groups sage: W = CoxeterGroup(['A', 3]) sage: len([1 for w in W if w.is_fully_commutative()]) 14 @@ -1578,8 +1588,8 @@ def is_fully_commutative(self) -> bool: TESTS:: - sage: W = CoxeterGroup(matrix(2,2,[1,7,7,1]),index_set='ab') - sage: len([1 for w in W if w.is_fully_commutative()]) + sage: W = CoxeterGroup(matrix(2,2,[1,7,7,1]), index_set='ab') # needs sage.combinat sage.groups + sage: len([1 for w in W if w.is_fully_commutative()]) # needs sage.combinat sage.groups 13 """ word = self.reduced_word() @@ -1680,7 +1690,7 @@ def reduced_words_iter(self): sage: W = CoxeterGroups().example() sage: s = W.simple_reflections() sage: w = s[0] * s[2] - sage: sorted(w.reduced_words_iter()) # optional - sage.combinat + sage: sorted(w.reduced_words_iter()) # needs sage.combinat sage.graphs [[0, 2], [2, 0]] """ return self.parent().braid_orbit_iter(self.reduced_word()) @@ -1705,18 +1715,19 @@ def reduced_words(self): sage: W = CoxeterGroups().example() sage: s = W.simple_reflections() sage: w = s[0] * s[2] - sage: sorted(w.reduced_words()) # optional - sage.combinat + sage: sorted(w.reduced_words()) # needs sage.graphs sage.modules [[0, 2], [2, 0]] - sage: W = WeylGroup(['E', 6]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([2,3,4,2]) # optional - sage.combinat sage.groups - sage: sorted(w.reduced_words()) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['E', 6]) # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([2,3,4,2]) # needs sage.combinat sage.groups + sage: sorted(w.reduced_words()) # needs sage.combinat sage.groups [[2, 3, 4, 2], [3, 2, 4, 2], [3, 4, 2, 4]] - sage: W = ReflectionGroup(['A',3], # optional - gap3 + sage: # optional - gap3, needs sage.combinat sage.groups + sage: W = ReflectionGroup(['A',3], ....: index_set=["AA","BB","5"]) - sage: w = W.long_element() # optional - gap3 - sage: w.reduced_words() # optional - gap3 + sage: w = W.long_element() + sage: w.reduced_words() [['BB', '5', 'AA', 'BB', '5', 'AA'], ['5', 'BB', '5', 'AA', 'BB', '5'], ['BB', 'AA', 'BB', '5', 'BB', 'AA'], @@ -1799,32 +1810,34 @@ def reduced_word_graph(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3], prefix='s') # optional - sage.combinat sage.groups - sage: w0 = W.long_element() # optional - sage.combinat sage.groups - sage: G = w0.reduced_word_graph() # optional - sage.combinat sage.groups sage.graphs - sage: G.num_verts() # optional - sage.combinat sage.groups sage.graphs + sage: # needs sage.combinat sage.graphs sage.groups + sage: W = WeylGroup(['A', 3], prefix='s') + sage: w0 = W.long_element() + sage: G = w0.reduced_word_graph() + sage: G.num_verts() 16 - sage: len(w0.reduced_words()) # optional - sage.combinat sage.groups sage.graphs + sage: len(w0.reduced_words()) 16 - sage: G.num_edges() # optional - sage.combinat sage.groups sage.graphs + sage: G.num_edges() 18 - sage: len([e for e in G.edges(sort=False) if e[2] == 2]) # optional - sage.combinat sage.groups sage.graphs + sage: len([e for e in G.edges(sort=False) if e[2] == 2]) 10 - sage: len([e for e in G.edges(sort=False) if e[2] == 3]) # optional - sage.combinat sage.groups sage.graphs + sage: len([e for e in G.edges(sort=False) if e[2] == 3]) 8 TESTS:: - sage: p = Permutation([3,2,4,1]) # optional - sage.combinat - sage: pp = WeylGroup(['A',3]).from_reduced_word(p.reduced_word()) # optional - sage.combinat sage.groups - sage: pp.reduced_word_graph() # optional - sage.combinat sage.groups sage.graphs + sage: p = Permutation([3,2,4,1]) + sage: pp = WeylGroup(['A',3]).from_reduced_word(p.reduced_word()) # needs sage.combinat sage.groups + sage: pp.reduced_word_graph() # needs sage.combinat sage.graphs sage.groups Graph on 3 vertices - sage: w1 = W.one() # optional - sage.combinat sage.groups - sage: G = w1.reduced_word_graph() # optional - sage.combinat sage.groups sage.graphs - sage: G.num_verts() # optional - sage.combinat sage.groups sage.graphs + sage: # needs sage.combinat sage.graphs sage.groups + sage: w1 = W.one() + sage: G = w1.reduced_word_graph() + sage: G.num_verts() 1 - sage: G.num_edges() # optional - sage.combinat sage.groups sage.graphs + sage: G.num_edges() 0 .. SEEALSO:: @@ -1920,14 +1933,14 @@ def reflection_length(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: (s[1]*s[2]*s[3]).reflection_length() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups + sage: s = W.simple_reflections() # needs sage.combinat sage.groups + sage: (s[1]*s[2]*s[3]).reflection_length() # needs sage.combinat sage.groups 3 - sage: W = SymmetricGroup(4) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: (s[3]*s[2]*s[3]).reflection_length() # optional - sage.combinat sage.groups + sage: W = SymmetricGroup(4) # needs sage.groups + sage: s = W.simple_reflections() # needs sage.groups + sage: (s[3]*s[2]*s[3]).reflection_length() # needs sage.combinat sage.groups 1 """ @@ -1950,14 +1963,14 @@ def absolute_length(self): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: (s[1]*s[2]*s[3]).absolute_length() # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups + sage: s = W.simple_reflections() # needs sage.combinat sage.groups + sage: (s[1]*s[2]*s[3]).absolute_length() # needs sage.combinat sage.groups 3 - sage: W = SymmetricGroup(4) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: (s[3]*s[2]*s[1]).absolute_length() # optional - sage.combinat sage.groups + sage: W = SymmetricGroup(4) # needs sage.groups + sage: s = W.simple_reflections() # needs sage.groups + sage: (s[3]*s[2]*s[1]).absolute_length() # needs sage.combinat sage.groups 3 """ M = self.canonical_matrix() @@ -1982,45 +1995,48 @@ def absolute_le(self, other): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: w0 = s[1] # optional - sage.combinat sage.groups - sage: w1 = s[1]*s[2]*s[3] # optional - sage.combinat sage.groups - sage: w0.absolute_le(w1) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) + sage: s = W.simple_reflections() + sage: w0 = s[1] + sage: w1 = s[1]*s[2]*s[3] + sage: w0.absolute_le(w1) True - sage: w1.absolute_le(w0) # optional - sage.combinat sage.groups + sage: w1.absolute_le(w0) False - sage: w1.absolute_le(w1) # optional - sage.combinat sage.groups + sage: w1.absolute_le(w1) True TESTS: Check that this is independent of the implementation of the group, see :trac:`34799`:: - sage: W1 = WeylGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: W2 = Permutations(3) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W1 = WeylGroup(['A', 2]) + sage: W2 = Permutations(3) sage: P = lambda pi: W2(list(pi.to_permutation())) - sage: d1 = set((P(w1), P(w2)) for w1 in W1 for w2 in W1 # optional - sage.combinat sage.groups + sage: d1 = set((P(w1), P(w2)) for w1 in W1 for w2 in W1 ....: if w1.absolute_le(w2)) - sage: d2 = set((w1, w2) for w1 in W2 for w2 in W2 # optional - sage.combinat sage.groups + sage: d2 = set((w1, w2) for w1 in W2 for w2 in W2 ....: if w1.absolute_le(w2)) - sage: d1 == d2 # optional - sage.combinat sage.groups + sage: d1 == d2 True - sage: sage.combinat.permutation.Permutations.options.mult = "r2l" # optional - sage.combinat sage.groups - sage: d3 = set((w1, w2) # optional - sage.combinat sage.groups + sage: sage.combinat.permutation.Permutations.options.mult = "r2l" + sage: d3 = set((w1, w2) ....: for w1 in W2 for w2 in W2 if w1.absolute_le(w2)) - sage: d1 == d3 # optional - sage.combinat sage.groups + sage: d1 == d3 True - sage: sage.combinat.permutation.Permutations.options._reset() # optional - sage.combinat sage.groups + sage: sage.combinat.permutation.Permutations.options._reset() - sage: W1 = WeylGroup(['B', 2]) # optional - sage.combinat sage.groups - sage: W2 = SignedPermutations(2) # optional - sage.combinat sage.groups - sage: P = lambda pi: W2(list(pi.to_permutation())) # optional - sage.combinat sage.groups - sage: d1 = set((P(w1), P(w2)) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W1 = WeylGroup(['B', 2]) + sage: W2 = SignedPermutations(2) + sage: P = lambda pi: W2(list(pi.to_permutation())) + sage: d1 = set((P(w1), P(w2)) ....: for w1 in W1 for w2 in W1 if w1.absolute_le(w2)) - sage: d2 = set((w1, w2) # optional - sage.combinat sage.groups + sage: d2 = set((w1, w2) ....: for w1 in W2 for w2 in W2 if w1.absolute_le(w2)) - sage: d1 == d2 # optional - sage.combinat sage.groups + sage: d1 == d2 True """ if self == other: @@ -2039,11 +2055,12 @@ def absolute_covers(self): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: w0 = s[1] # optional - sage.combinat sage.groups - sage: w1 = s[1]*s[2]*s[3] # optional - sage.combinat sage.groups - sage: w0.absolute_covers() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) + sage: s = W.simple_reflections() + sage: w0 = s[1] + sage: w1 = s[1]*s[2]*s[3] + sage: w0.absolute_covers() [ [0 0 1 0] [0 1 0 0] [0 1 0 0] [0 0 0 1] [0 1 0 0] [1 0 0 0] [1 0 0 0] [0 0 1 0] [1 0 0 0] [0 0 0 1] @@ -2067,9 +2084,9 @@ def canonical_matrix(self): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: (s[1]*s[2]*s[3]).canonical_matrix() # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups + sage: s = W.simple_reflections() # needs sage.combinat sage.groups + sage: (s[1]*s[2]*s[3]).canonical_matrix() # needs sage.combinat sage.groups [ 0 0 -1] [ 1 0 -1] [ 0 1 -1] @@ -2150,15 +2167,17 @@ def apply_simple_projection(self, i, side='right', length_increasing=True): (1, 2, 3, 0) sage: w.apply_simple_projection(2, length_increasing=False) (1, 2, 0, 3) - sage: W = WeylGroup(['C', 4], prefix="s") # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([1,2,3,4,3,1]) # optional - sage.combinat sage.groups - sage: v # optional - sage.combinat sage.groups + + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['C', 4], prefix="s") + sage: v = W.from_reduced_word([1,2,3,4,3,1]) + sage: v s1*s2*s3*s4*s3*s1 - sage: v.apply_simple_projection(2) # optional - sage.combinat sage.groups + sage: v.apply_simple_projection(2) s1*s2*s3*s4*s3*s1*s2 - sage: v.apply_simple_projection(2, side='left') # optional - sage.combinat sage.groups + sage: v.apply_simple_projection(2, side='left') s1*s2*s3*s4*s3*s1 - sage: v.apply_simple_projection(1, length_increasing=False) # optional - sage.combinat sage.groups + sage: v.apply_simple_projection(1, length_increasing=False) s1*s2*s3*s4*s3 """ @@ -2186,15 +2205,16 @@ def binary_factorizations(self, predicate=ConstantFunction(True)): We construct the set of all factorizations of the maximal element of the group:: - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: w0 = W.from_reduced_word([1,2,3,1,2,1]) # optional - sage.combinat sage.groups - sage: w0.binary_factorizations().cardinality() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) + sage: s = W.simple_reflections() + sage: w0 = W.from_reduced_word([1,2,3,1,2,1]) + sage: w0.binary_factorizations().cardinality() 24 The same number of factorizations, by bounded length:: - sage: [w0.binary_factorizations( # optional - sage.combinat sage.groups + sage: [w0.binary_factorizations( # needs sage.combinat sage.groups ....: lambda u: u.length() <= l ....: ).cardinality() ....: for l in [-1,0,1,2,3,4,5,6]] @@ -2203,40 +2223,40 @@ def binary_factorizations(self, predicate=ConstantFunction(True)): The number of factorizations of the elements just below the maximal element:: - sage: [(s[i]*w0).binary_factorizations().cardinality() # optional - sage.combinat sage.groups + sage: [(s[i]*w0).binary_factorizations().cardinality() # needs sage.combinat sage.groups ....: for i in [1,2,3]] [12, 12, 12] - sage: w0.binary_factorizations(lambda u: False).cardinality() # optional - sage.combinat sage.groups + sage: w0.binary_factorizations(lambda u: False).cardinality() # needs sage.combinat sage.groups 0 TESTS:: - sage: w0.binary_factorizations().category() # optional - sage.combinat sage.groups + sage: w0.binary_factorizations().category() # needs sage.combinat sage.groups Category of finite enumerated sets Check that this is independent of the implementation of the group, see :trac:`34799`:: - sage: W1 = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: W2 = Permutations(4) # optional - sage.combinat sage.groups - sage: P = lambda pi: W2(list(pi.to_permutation())) # optional - sage.combinat sage.groups - sage: d1 = {P(pi): set((P(w[0]), P(w[1])) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W1 = WeylGroup(['A', 3]) + sage: W2 = Permutations(4) + sage: P = lambda pi: W2(list(pi.to_permutation())) + sage: d1 = {P(pi): set((P(w[0]), P(w[1])) ....: for w in pi.binary_factorizations()) ....: for pi in W1} - sage: d2 = {pi: set(pi.binary_factorizations()) for pi in W2} # optional - sage.combinat sage.groups - sage: d1 == d2 # optional - sage.combinat sage.groups + sage: d2 = {pi: set(pi.binary_factorizations()) for pi in W2} + sage: d1 == d2 True - sage: sage.combinat.permutation.Permutations.options.mult = "r2l" # optional - sage.combinat sage.groups - sage: d3 = {pi: set(pi.binary_factorizations()) for pi in W2} # optional - sage.combinat sage.groups - sage: d1 == d3 # optional - sage.combinat sage.groups + sage: sage.combinat.permutation.Permutations.options.mult = "r2l" + sage: d3 = {pi: set(pi.binary_factorizations()) for pi in W2} + sage: d1 == d3 True - sage: sage.combinat.permutation.Permutations.options._reset() # optional - sage.combinat sage.groups + sage: sage.combinat.permutation.Permutations.options._reset() """ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest W = self.parent() if not predicate(W.one()): from sage.sets.finite_enumerated_set import FiniteEnumeratedSet return FiniteEnumeratedSet([]) - s = W.simple_reflections() def succ(u_v): u, v = u_v @@ -2259,38 +2279,40 @@ def bruhat_lower_covers(self): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,2,3]) # optional - sage.combinat sage.groups - sage: print([v.reduced_word() for v in w.bruhat_lower_covers()]) # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,2,3]) # needs sage.combinat sage.groups + sage: print([v.reduced_word() for v in w.bruhat_lower_covers()]) # needs sage.combinat sage.groups [[3, 2], [2, 3]] - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: print([v.reduced_word() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) + sage: print([v.reduced_word() ....: for v in W.simple_reflection(1).bruhat_lower_covers()]) [[]] - sage: print([v.reduced_word() # optional - sage.combinat sage.groups + sage: print([v.reduced_word() ....: for v in W.one().bruhat_lower_covers()]) [] - sage: W = WeylGroup(["B", 4, 1]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([0,2]) # optional - sage.combinat sage.groups - sage: print([v.reduced_word() for v in w.bruhat_lower_covers()]) # optional - sage.combinat sage.groups + sage: W = WeylGroup(["B", 4, 1]) + sage: w = W.from_reduced_word([0,2]) + sage: print([v.reduced_word() for v in w.bruhat_lower_covers()]) [[2], [0]] - sage: W = WeylGroup("A3", prefix="s", implementation="permutation") # optional - sage.combinat sage.groups - sage: s1, s2, s3 = W.simple_reflections() # optional - sage.combinat sage.groups - sage: (s1*s2*s3*s1).bruhat_lower_covers() # optional - sage.combinat sage.groups + sage: W = WeylGroup("A3", prefix="s", implementation="permutation") + sage: s1, s2, s3 = W.simple_reflections() + sage: (s1*s2*s3*s1).bruhat_lower_covers() [s2*s1*s3, s1*s2*s1, s1*s2*s3] We now show how to construct the Bruhat poset:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: covers = tuple([u, v] # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) + sage: covers = tuple([u, v] ....: for v in W for u in v.bruhat_lower_covers()) - sage: P = Poset((W, covers), cover_relations = True) # optional - sage.combinat sage.groups sage.graphs - sage: P.show() # optional - sage.combinat sage.groups sage.graphs + sage: P = Poset((W, covers), cover_relations=True) # needs sage.graphs + sage: P.show() # needs sage.graphs sage.plot Alternatively, one can just use:: - sage: P = W.bruhat_poset() # optional - sage.combinat sage.groups sage.graphs + sage: P = W.bruhat_poset() # needs sage.combinat sage.graphs sage.groups The algorithm is taken from Stembridge's 'coxeter/weyl' package for Maple. """ @@ -2313,21 +2335,22 @@ def bruhat_upper_covers(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3, 1], prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([1,2,1]) # optional - sage.combinat sage.groups - sage: w.bruhat_upper_covers() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3, 1], prefix="s") # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([1,2,1]) # needs sage.combinat sage.groups + sage: w.bruhat_upper_covers() # needs sage.combinat sage.groups [s1*s2*s1*s0, s1*s2*s0*s1, s0*s1*s2*s1, s3*s1*s2*s1, s2*s3*s1*s2, s1*s2*s3*s1] - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: w = W.long_element() # optional - sage.combinat sage.groups - sage: w.bruhat_upper_covers() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups + sage: w = W.long_element() # needs sage.combinat sage.groups + sage: w.bruhat_upper_covers() # needs sage.combinat sage.groups [] - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([1,2,1]) # optional - sage.combinat sage.groups - sage: S = [v for v in W if w in v.bruhat_lower_covers()] # optional - sage.combinat sage.groups - sage: C = w.bruhat_upper_covers() # optional - sage.combinat sage.groups - sage: set(S) == set(C) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) + sage: w = W.from_reduced_word([1,2,1]) + sage: S = [v for v in W if w in v.bruhat_lower_covers()] + sage: C = w.bruhat_upper_covers() + sage: set(S) == set(C) True """ Covers = set() @@ -2351,17 +2374,17 @@ def bruhat_lower_covers_reflections(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3], prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,1,2,1]) # optional - sage.combinat sage.groups - sage: w.bruhat_lower_covers_reflections() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix="s") # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups + sage: w.bruhat_lower_covers_reflections() # needs sage.combinat sage.groups [(s1*s2*s1, s1*s2*s3*s2*s1), (s3*s2*s1, s2), (s3*s1*s2, s1)] TESTS: Check bug discovered in :trac:`32669` is fixed:: - sage: W = CoxeterGroup(['A', 3], implementation='permutation') # optional - sage.combinat sage.groups - sage: W.w0.bruhat_lower_covers_reflections() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 3], implementation='permutation') # needs sage.combinat sage.groups + sage: W.w0.bruhat_lower_covers_reflections() # needs sage.combinat sage.groups [((1,3,7,9)(2,11,6,10)(4,8,5,12), (2,5)(3,9)(4,6)(8,11)(10,12)), ((1,11)(3,10)(4,9)(5,7)(6,12), (1,4)(2,8)(3,5)(7,10)(9,11)), ((1,9,7,3)(2,10,6,11)(4,12,5,8), (1,7)(2,4)(5,6)(8,10)(11,12))] @@ -2372,7 +2395,7 @@ def bruhat_lower_covers_reflections(self): wi = self.apply_simple_reflection(i, side='right') return [(u.apply_simple_reflection(i, side='right'), r.apply_conjugation_by_simple_reflection(i)) - for u,r in wi.bruhat_lower_covers_reflections() + for u, r in wi.bruhat_lower_covers_reflections() if not u.has_descent(i, side='right')] + [ (wi, self.parent().simple_reflection(i))] @@ -2384,11 +2407,12 @@ def lower_cover_reflections(self, side='right'): EXAMPLES:: - sage: W = WeylGroup(['A', 3],prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,1,2,1]) # optional - sage.combinat sage.groups - sage: w.lower_cover_reflections() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 3],prefix="s") + sage: w = W.from_reduced_word([3,1,2,1]) + sage: w.lower_cover_reflections() [s1*s2*s3*s2*s1, s2, s1] - sage: w.lower_cover_reflections(side='left') # optional - sage.combinat sage.groups + sage: w.lower_cover_reflections(side='left') [s2*s3*s2, s3, s1] """ @@ -2407,9 +2431,9 @@ def bruhat_upper_covers_reflections(self): EXAMPLES:: - sage: W = WeylGroup(['A', 4], prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,1,2,1]) # optional - sage.combinat sage.groups - sage: w.bruhat_upper_covers_reflections() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 4], prefix="s") # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups + sage: w.bruhat_upper_covers_reflections() # needs sage.combinat sage.groups [(s1*s2*s3*s2*s1, s3), (s2*s3*s1*s2*s1, s2*s3*s2), (s3*s4*s1*s2*s1, s4), (s4*s3*s1*s2*s1, s1*s2*s3*s4*s3*s2*s1)] """ @@ -2431,11 +2455,12 @@ def cover_reflections(self, side='right'): EXAMPLES:: - sage: W = WeylGroup(['A', 4], prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,1,2,1]) # optional - sage.combinat sage.groups - sage: w.cover_reflections() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 4], prefix="s") + sage: w = W.from_reduced_word([3,1,2,1]) + sage: w.cover_reflections() [s3, s2*s3*s2, s4, s1*s2*s3*s4*s3*s2*s1] - sage: w.cover_reflections(side='left') # optional - sage.combinat sage.groups + sage: w.cover_reflections(side='left') [s4, s2, s1*s2*s1, s3*s4*s3] """ @@ -2456,19 +2481,20 @@ def bruhat_le(self, other): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: u = W.from_reduced_word([1,2,1]) # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([1,2,3,2,1]) # optional - sage.combinat sage.groups - sage: u.bruhat_le(u) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) + sage: u = W.from_reduced_word([1,2,1]) + sage: v = W.from_reduced_word([1,2,3,2,1]) + sage: u.bruhat_le(u) True - sage: u.bruhat_le(v) # optional - sage.combinat sage.groups + sage: u.bruhat_le(v) True - sage: v.bruhat_le(u) # optional - sage.combinat sage.groups + sage: v.bruhat_le(u) False - sage: v.bruhat_le(v) # optional - sage.combinat sage.groups + sage: v.bruhat_le(v) True - sage: s = W.simple_reflections() # optional - sage.combinat sage.groups - sage: s[1].bruhat_le(W.one()) # optional - sage.combinat sage.groups + sage: s = W.simple_reflections() + sage: s[1].bruhat_le(W.one()) False The implementation uses the equivalent condition that any @@ -2489,20 +2515,21 @@ def bruhat_le(self, other): We now run consistency tests with permutations and :meth:`bruhat_lower_covers`:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: P4 = Permutations(4) # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups + sage: P4 = Permutations(4) sage: def P4toW(w): return W.from_reduced_word(w.reduced_word()) - sage: for u in P4: # optional - sage.combinat sage.groups + sage: for u in P4: # needs sage.combinat sage.groups ....: for v in P4: ....: assert u.bruhat_lequal(v) == P4toW(u).bruhat_le(P4toW(v)) - sage: W = WeylGroup(["B", 3]) # optional - sage.combinat sage.groups - sage: P = W.bruhat_poset() # This is built from bruhat_lower_covers # optional - sage.combinat sage.groups sage.graphs - sage: Q = Poset((W, attrcall("bruhat_le"))) # long time (10s) # optional - sage.combinat sage.groups sage.graphs - sage: all(u.bruhat_le(v) == P.is_lequal(u,v) # long time (7s) # optional - sage.combinat sage.groups sage.graphs + sage: # needs sage.combinat sage.graphs sage.groups + sage: W = WeylGroup(["B", 3]) + sage: P = W.bruhat_poset() # This is built from bruhat_lower_covers + sage: Q = Poset((W, attrcall("bruhat_le"))) # long time (10s) + sage: all(u.bruhat_le(v) == P.is_lequal(u,v) # long time (7s) ....: for u in W for v in W) True - sage: all(P.is_lequal(u,v) == Q.is_lequal(u,v) # long time (9s) # optional - sage.combinat sage.groups sage.graphs + sage: all(P.is_lequal(u,v) == Q.is_lequal(u,v) # long time (9s) ....: for u in W for v in W) True """ @@ -2532,21 +2559,22 @@ def weak_le(self, other, side='right'): EXAMPLES:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: u = W.from_reduced_word([1,2]) # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([1,2,3,2]) # optional - sage.combinat sage.groups - sage: u.weak_le(u) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) + sage: u = W.from_reduced_word([1,2]) + sage: v = W.from_reduced_word([1,2,3,2]) + sage: u.weak_le(u) True - sage: u.weak_le(v) # optional - sage.combinat sage.groups + sage: u.weak_le(v) True - sage: v.weak_le(u) # optional - sage.combinat sage.groups + sage: v.weak_le(u) False - sage: v.weak_le(v) # optional - sage.combinat sage.groups + sage: v.weak_le(v) True Comparison for left weak order is achieved with the option ``side``:: - sage: u.weak_le(v, side='left') # optional - sage.combinat sage.groups + sage: u.weak_le(v, side='left') # needs sage.combinat sage.groups False The implementation uses the equivalent condition that any @@ -2562,10 +2590,10 @@ def weak_le(self, other, side='right'): We now run consistency tests with permutations:: - sage: W = WeylGroup(["A", 3]) # optional - sage.combinat sage.groups - sage: P4 = Permutations(4) # optional - sage.combinat sage.groups - sage: def P4toW(w): return W.from_reduced_word(w.reduced_word()) # optional - sage.combinat sage.groups - sage: for u in P4: # long time (5s on sage.math, 2011) # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A", 3]) # needs sage.combinat sage.groups + sage: P4 = Permutations(4) + sage: def P4toW(w): return W.from_reduced_word(w.reduced_word()) + sage: for u in P4: # long time (5s on sage.math, 2011), needs sage.combinat sage.groups ....: for v in P4: ....: assert u.permutohedron_lequal(v) == P4toW(u).weak_le(P4toW(v)) ....: assert u.permutohedron_lequal(v, side='left') == P4toW(u).weak_le(P4toW(v), side='left') @@ -2598,29 +2626,30 @@ def weak_covers(self, side='right', index_set=None, positive=False): EXAMPLES:: - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,2,1]) # optional - sage.combinat sage.groups - sage: [x.reduced_word() for x in w.weak_covers()] # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,2,1]) # needs sage.combinat sage.groups + sage: [x.reduced_word() for x in w.weak_covers()] # needs sage.combinat sage.groups [[3, 2]] To obtain instead elements that cover self, set ``positive=True``:: - sage: [x.reduced_word() for x in w.weak_covers(positive=True)] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.weak_covers(positive=True)] # needs sage.combinat sage.groups [[3, 1, 2, 1], [2, 3, 2, 1]] To obtain covers for left weak order, set the option side to 'left':: - sage: [x.reduced_word() for x in w.weak_covers(side='left')] # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: [x.reduced_word() for x in w.weak_covers(side='left')] [[2, 1]] - sage: w = W.from_reduced_word([3,2,3,1]) # optional - sage.combinat sage.groups - sage: [x.reduced_word() for x in w.weak_covers()] # optional - sage.combinat sage.groups + sage: w = W.from_reduced_word([3,2,3,1]) + sage: [x.reduced_word() for x in w.weak_covers()] [[2, 3, 2], [3, 2, 1]] - sage: [x.reduced_word() for x in w.weak_covers(side='left')] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.weak_covers(side='left')] [[3, 2, 1], [2, 3, 1]] Covers w.r.t. a parabolic subgroup are obtained with the option ``index_set``:: - sage: [x.reduced_word() for x in w.weak_covers(index_set=[1,2])] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.weak_covers(index_set=[1,2])] # needs sage.combinat sage.groups [[2, 3, 2]] """ return [self.apply_simple_reflection(i, side=side) @@ -2704,19 +2733,19 @@ def is_coxeter_sortable(self, c, sorting_word=None): sage: w.is_coxeter_sortable(c) True - sage: W = CoxeterGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: c = W.from_reduced_word([1,2,3]) # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 3]) # needs sage.combinat sage.groups + sage: c = W.from_reduced_word([1,2,3]) # needs sage.combinat sage.groups Number of `c`-sortable elements in `A_3` (Catalan number):: - sage: len([w for w in W if w.is_coxeter_sortable(c)]) # optional - sage.combinat sage.groups + sage: len([w for w in W if w.is_coxeter_sortable(c)]) 14 TESTS:: - sage: W = SymmetricGroup(3) # optional - sage.combinat sage.groups - sage: c = Permutation((1,2,3)) # optional - sage.combinat sage.groups - sage: sorted(w for w in W if w.is_coxeter_sortable(c)) # optional - sage.combinat sage.groups + sage: W = SymmetricGroup(3) # needs sage.groups + sage: c = Permutation((1,2,3)) + sage: sorted(w for w in W if w.is_coxeter_sortable(c)) # needs sage.combinat sage.groups [(), (2,3), (1,2), (1,3,2), (1,3)] """ if hasattr(c, "reduced_word"): @@ -2767,15 +2796,16 @@ def apply_demazure_product(self, element, side='right', EXAMPLES:: - sage: W = WeylGroup(['C', 4], prefix="s") # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([1,2,3,4,3,1]) # optional - sage.combinat sage.groups - sage: v.apply_demazure_product([1,3,4,3,3]) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['C', 4], prefix="s") + sage: v = W.from_reduced_word([1,2,3,4,3,1]) + sage: v.apply_demazure_product([1,3,4,3,3]) s4*s1*s2*s3*s4*s3*s1 - sage: v.apply_demazure_product([1,3,4,3], side='left') # optional - sage.combinat sage.groups + sage: v.apply_demazure_product([1,3,4,3], side='left') s3*s4*s1*s2*s3*s4*s2*s3*s1 - sage: v.apply_demazure_product((1,3,4,3), side='left') # optional - sage.combinat sage.groups + sage: v.apply_demazure_product((1,3,4,3), side='left') s3*s4*s1*s2*s3*s4*s2*s3*s1 - sage: v.apply_demazure_product(v) # optional - sage.combinat sage.groups + sage: v.apply_demazure_product(v) s2*s3*s4*s1*s2*s3*s4*s2*s3*s2*s1 """ @@ -2810,14 +2840,15 @@ def min_demazure_product_greater(self, element): EXAMPLES:: - sage: W = WeylGroup(['A', 4], prefix="s") # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([2,3,4,1,2]) # optional - sage.combinat sage.groups - sage: u = W.from_reduced_word([2,3,2,1]) # optional - sage.combinat sage.groups - sage: v.min_demazure_product_greater(u) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 4], prefix="s") + sage: v = W.from_reduced_word([2,3,4,1,2]) + sage: u = W.from_reduced_word([2,3,2,1]) + sage: v.min_demazure_product_greater(u) s4*s2 - sage: v.min_demazure_product_greater([2,3,2,1]) # optional - sage.combinat sage.groups + sage: v.min_demazure_product_greater([2,3,2,1]) s4*s2 - sage: v.min_demazure_product_greater((2,3,2,1)) # optional - sage.combinat sage.groups + sage: v.min_demazure_product_greater((2,3,2,1)) s4*s2 """ @@ -2857,17 +2888,19 @@ def deodhar_factor_element(self, w, index_set): EXAMPLES:: - sage: W = WeylGroup(['A', 5], prefix="s") # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([5]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([4,5,2,3,1,2]) # optional - sage.combinat sage.groups - sage: v.deodhar_factor_element(w, [1,3,4]) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 5], prefix="s") + sage: v = W.from_reduced_word([5]) + sage: w = W.from_reduced_word([4,5,2,3,1,2]) + sage: v.deodhar_factor_element(w, [1,3,4]) s3*s1 - sage: W = WeylGroup(['C', 2]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([2,1]) # optional - sage.combinat sage.groups - sage: w.deodhar_factor_element(W.from_reduced_word([2]),[1]) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['C', 2]) + sage: w = W.from_reduced_word([2,1]) + sage: w.deodhar_factor_element(W.from_reduced_word([2]),[1]) Traceback (most recent call last): ... - ValueError: [2, 1] is not of minimum length in its coset for the parabolic subgroup with index set [1] + ValueError: [2, 1] is not of minimum length in its coset + for the parabolic subgroup with index set [1] REFERENCES: @@ -2912,10 +2945,11 @@ def deodhar_lift_up(self, w, index_set): EXAMPLES:: - sage: W = WeylGroup(['A', 3], prefix="s") # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([1,2,3]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([1,3,2]) # optional - sage.combinat sage.groups - sage: v.deodhar_lift_up(w, [3]) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix="s") + sage: v = W.from_reduced_word([1,2,3]) + sage: w = W.from_reduced_word([1,3,2]) + sage: v.deodhar_lift_up(w, [3]) s1*s2*s3*s2 """ vmin = self.coset_representative(index_set) @@ -2946,10 +2980,11 @@ def deodhar_lift_down(self, w, index_set): EXAMPLES:: - sage: W = WeylGroup(['A', 3], prefix="s") # optional - sage.combinat sage.groups - sage: v = W.from_reduced_word([1,2,3,2]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,2]) # optional - sage.combinat sage.groups - sage: v.deodhar_lift_down(w, [3]) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix="s") + sage: v = W.from_reduced_word([1,2,3,2]) + sage: w = W.from_reduced_word([3,2]) + sage: v.deodhar_lift_down(w, [3]) s2*s3*s2 """ @@ -2969,9 +3004,9 @@ def inversions_as_reflections(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3], prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,1,2,1]) # optional - sage.combinat sage.groups - sage: w.inversions_as_reflections() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix="s") # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups + sage: w.inversions_as_reflections() # needs sage.combinat sage.groups [s1, s1*s2*s1, s2, s1*s2*s3*s2*s1] """ i = self.first_descent() @@ -2986,9 +3021,9 @@ def left_inversions_as_reflections(self): EXAMPLES:: - sage: W = WeylGroup(['A', 3], prefix="s") # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,1,2,1]) # optional - sage.combinat sage.groups - sage: w.left_inversions_as_reflections() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix="s") # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,1,2,1]) # needs sage.combinat sage.groups + sage: w.left_inversions_as_reflections() # needs sage.combinat sage.groups [s1, s3, s1*s2*s3*s2*s1, s2*s3*s2] """ return self.inverse().inversions_as_reflections() @@ -3006,24 +3041,24 @@ def lower_covers(self, side='right', index_set=None): EXAMPLES:: - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([3,2,1]) # optional - sage.combinat sage.groups - sage: [x.reduced_word() for x in w.lower_covers()] # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([3,2,1]) # needs sage.combinat sage.groups + sage: [x.reduced_word() for x in w.lower_covers()] # needs sage.combinat sage.groups [[3, 2]] To obtain covers for left weak order, set the option side to 'left':: - sage: [x.reduced_word() for x in w.lower_covers(side='left')] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.lower_covers(side='left')] # needs sage.combinat sage.groups [[2, 1]] - sage: w = W.from_reduced_word([3,2,3,1]) # optional - sage.combinat sage.groups - sage: [x.reduced_word() for x in w.lower_covers()] # optional - sage.combinat sage.groups + sage: w = W.from_reduced_word([3,2,3,1]) # needs sage.combinat sage.groups + sage: [x.reduced_word() for x in w.lower_covers()] # needs sage.combinat sage.groups [[2, 3, 2], [3, 2, 1]] Covers w.r.t. a parabolic subgroup are obtained with the option ``index_set``:: - sage: [x.reduced_word() for x in w.lower_covers(index_set=[1,2])] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.lower_covers(index_set=[1,2])] # needs sage.combinat sage.groups [[2, 3, 2]] - sage: [x.reduced_word() for x in w.lower_covers(side='left')] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.lower_covers(side='left')] # needs sage.combinat sage.groups [[3, 2, 1], [2, 3, 1]] """ return self.weak_covers(side=side, index_set=index_set, @@ -3042,21 +3077,21 @@ def upper_covers(self, side='right', index_set=None): EXAMPLES:: - sage: W = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: w = W.from_reduced_word([2,3]) # optional - sage.combinat sage.groups - sage: [x.reduced_word() for x in w.upper_covers()] # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3]) # needs sage.combinat sage.groups + sage: w = W.from_reduced_word([2,3]) # needs sage.combinat sage.groups + sage: [x.reduced_word() for x in w.upper_covers()] # needs sage.combinat sage.groups [[2, 3, 1], [2, 3, 2]] To obtain covers for left weak order, set the option ``side`` to 'left':: - sage: [x.reduced_word() for x in w.upper_covers(side='left')] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.upper_covers(side='left')] # needs sage.combinat sage.groups [[1, 2, 3], [2, 3, 2]] Covers w.r.t. a parabolic subgroup are obtained with the option ``index_set``:: - sage: [x.reduced_word() for x in w.upper_covers(index_set=[1])] # optional - sage.combinat sage.groups + sage: [x.reduced_word() for x in w.upper_covers(index_set=[1])] # needs sage.combinat sage.groups [[2, 3, 1]] - sage: [x.reduced_word() # optional - sage.combinat sage.groups + sage: [x.reduced_word() # needs sage.combinat sage.groups ....: for x in w.upper_covers(side='left', index_set=[1])] [[1, 2, 3]] """ @@ -3100,41 +3135,44 @@ def kazhdan_lusztig_cell(self, side='left'): choice of implementation affects the representation of elements in the output cell but not the method used for the cell computation:: - sage: W = CoxeterGroup('A3', implementation='permutation') # optional - sage.combinat sage.groups - sage: s1, s2, s3 = W.simple_reflections() # optional - sage.combinat sage.groups - sage: s1.kazhdan_lusztig_cell() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup('A3', implementation='permutation') # needs sage.combinat sage.groups + sage: s1, s2, s3 = W.simple_reflections() # needs sage.combinat sage.groups + sage: s1.kazhdan_lusztig_cell() # needs sage.combinat sage.groups {(1,2,3,12)(4,5,10,11)(6,7,8,9), (1,2,10)(3,6,5)(4,7,8)(9,12,11), (1,7)(2,4)(5,6)(8,10)(11,12)} The cell computation uses the optional package ``coxeter3`` in the background if available to speed up the computation, - even in the different implementations implementations:: + even in the different implementations:: - sage: W = WeylGroup('A3', prefix='s') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + sage: # optional - coxeter3, needs sage.combinat sage.groups sage.modules + sage: W = WeylGroup('A3', prefix='s') + sage: s1,s2,s3 = W.simple_reflections() + sage: s1.kazhdan_lusztig_cell() {s3*s2*s1, s2*s1, s1} - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: s1,s2,s3 = W.simple_reflections() + sage: s1.kazhdan_lusztig_cell() {[1], [2, 1], [3, 2, 1]} Next, we compute a right cell and a two-sided cell in `A_3`:: - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: w = s1 * s3 # optional - coxeter3 - sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 + sage: # optional - coxeter3, needs sage.combinat sage.groups sage.modules + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: s1,s2,s3 = W.simple_reflections() + sage: w = s1 * s3 + sage: w.kazhdan_lusztig_cell(side='right') {[1, 3], [1, 3, 2]} - sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 + sage: w.kazhdan_lusztig_cell(side='two-sided') {[1, 3], [1, 3, 2], [2, 1, 3], [2, 1, 3, 2]} Some slightly longer computations in `B_4`:: - sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell(side='right') # long time (4 seconds) # optional - coxeter3 + sage: # optional - coxeter3, needs sage.combinat sage.groups sage.modules + sage: W = CoxeterGroup('B4', implementation='coxeter3') + sage: s1,s2,s3,s4 = W.simple_reflections() + sage: s1.kazhdan_lusztig_cell(side='right') # long time (4 seconds) {[1], [1, 2], [1, 2, 3], @@ -3142,7 +3180,7 @@ def kazhdan_lusztig_cell(self, side='left'): [1, 2, 3, 4, 3], [1, 2, 3, 4, 3, 2], [1, 2, 3, 4, 3, 2, 1]} - sage: (s4*s2*s3*s4).kazhdan_lusztig_cell(side='two-sided') # long time (8 seconds) # optional - coxeter3 + sage: (s4*s2*s3*s4).kazhdan_lusztig_cell(side='two-sided') # long time (8 seconds) {[2, 3, 1], [2, 3, 1, 2], [2, 3, 4, 1], diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index 3ceb16529d6..edeb6fb9b35 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.graphs sage.combinat +# sage.doctest: needs sage.graphs sage.combinat r""" Crystals @@ -908,7 +908,7 @@ def digraph(self, subset=None, index_set=None): child = x.f(i) if child is None or child not in subset: continue - d[x][child]=i + d[x][child] = i G = DiGraph(d) from sage.graphs.dot2tex_utils import have_dot2tex if have_dot2tex(): @@ -1057,12 +1057,12 @@ def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, c2 = int(35*tallness*scaling_factor) c3 = int(12*scaling_factor) c4 = int(-12*scaling_factor) - outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\nsx:=35; sy:=30;\n\nz1000=(%d,0);\nz1001=(%d,%d);\nz1002=(%d,%d);\nz2001=(-3,3);\nz2002=(3,3);\nz2003=(0,-3);\nz2004=(7,0);\nz2005=(0,7);\nz2006=(-7,0);\nz2007=(0,7);\n\n"%(c0,c1,c2,c3,c4) + outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\nsx:=35; sy:=30;\n\nz1000=(%d,0);\nz1001=(%d,%d);\nz1002=(%d,%d);\nz2001=(-3,3);\nz2002=(3,3);\nz2003=(0,-3);\nz2004=(7,0);\nz2005=(0,7);\nz2006=(-7,0);\nz2007=(0,7);\n\n" % (c0,c1,c2,c3,c4) else: if labels: - outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\n\nsx := %d;\nsy=%d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-16,-10);\n\nz2001=(0,-3);\nz2002=(-5,3);\nz2003=(0,3);\nz2004=(5,3);\nz2005=(10,1);\nz2006=(0,10);\nz2007=(-10,1);\nz2008=(0,-8);\n\n"%(int(scaling_factor*40),int(tallness*scaling_factor*40)) + outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\n\nsx := %d;\nsy=%d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-16,-10);\n\nz2001=(0,-3);\nz2002=(-5,3);\nz2003=(0,3);\nz2004=(5,3);\nz2005=(10,1);\nz2006=(0,10);\nz2007=(-10,1);\nz2008=(0,-8);\n\n" % (int(scaling_factor*40),int(tallness*scaling_factor*40)) else: - outstring = "beginfig(-1);\n\nsx := %d;\nsy := %d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-5,-5);\n\nz1003=(10,10);\n\n"%(int(scaling_factor*35),int(tallness*scaling_factor*35)) + outstring = "beginfig(-1);\n\nsx := %d;\nsy := %d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-5,-5);\n\nz1003=(10,10);\n\n" % (int(scaling_factor*35),int(tallness*scaling_factor*35)) for i in range(size): if self.cartan_type()[0] == 'A': [a1,a2,a3] = string_data[i] @@ -1079,12 +1079,12 @@ def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, if b1+b3 == a1+a3 and b2+b4 == a2+a4: shift += 1 if self.cartan_type()[0] == 'A': - outstring = outstring +"z%d=%d*z1000+%d*z1001+%d*z1002;\n"%(i,a1+a3,a2,shift) + outstring = outstring + "z%d=%d*z1000+%d*z1001+%d*z1002;\n" % (i,a1+a3,a2,shift) else: - outstring = outstring +"z%d=%d*z1000+%d*z1001+%d*z1002;\n"%(i,a1+a3,a2+a4,shift) + outstring = outstring + "z%d=%d*z1000+%d*z1001+%d*z1002;\n" % (i,a1+a3,a2+a4,shift) outstring = outstring + "\n" if thicklines: - outstring = outstring +"pickup pencircle scaled 2\n\n" + outstring = outstring + "pickup pencircle scaled 2\n\n" for i in range(size): for j in range(1,3): dest = self.list()[i].f(j) @@ -1096,19 +1096,19 @@ def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, col = "green; " if self.cartan_type()[0] == 'A': [a1,a2,a3] = string_data[i] # included to facilitate hand editing of the .mp file - outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d\n"%(i,dest,col,a1,a2,a3) + outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d\n" % (i,dest,col,a1,a2,a3) else: [a1,a2,a3,a4] = string_data[i] - outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d %d\n"%(i,dest,col,a1,a2,a3,a4) + outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d %d\n" % (i,dest,col,a1,a2,a3,a4) outstring += "\npickup pencircle scaled 3;\n\n" for i in range(self.cardinality()): if labels: if self.cartan_type()[0] == 'A': - outstring = outstring+"pickup pencircle scaled 15;\nfill z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\npickup pencircle scaled .5;\ndraw z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle;\n"%(i,i,i,i,string_data[i][2],i,string_data[i][1],i,string_data[i][0],i,i,i,i,i) + outstring = outstring+"pickup pencircle scaled 15;\nfill z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\npickup pencircle scaled .5;\ndraw z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle;\n" % (i,i,i,i,string_data[i][2],i,string_data[i][1],i,string_data[i][0],i,i,i,i,i) else: - outstring = outstring+"%%%d %d %d %d\npickup pencircle scaled 1;\nfill z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\nlabel(btex %d etex, z%d+z2004);\npickup pencircle scaled .5;\ndraw z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle;\n\n"%(string_data[i][0],string_data[i][1],string_data[i][2],string_data[i][3],i,i,i,i,string_data[i][0],i,string_data[i][1],i,string_data[i][2],i,string_data[i][3],i,i,i,i,i) + outstring = outstring+"%%%d %d %d %d\npickup pencircle scaled 1;\nfill z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\nlabel(btex %d etex, z%d+z2004);\npickup pencircle scaled .5;\ndraw z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle;\n\n" % (string_data[i][0],string_data[i][1],string_data[i][2],string_data[i][3],i,i,i,i,string_data[i][0],i,string_data[i][1],i,string_data[i][2],i,string_data[i][3],i,i,i,i,i) else: - outstring += "drawdot z%d;\n"%i + outstring += "drawdot z%d;\n" % i outstring += "\nendfig;\n\nend;\n\n" f = open(filename, 'w') @@ -1153,8 +1153,8 @@ def dot_tex(self): else: option = "" (source, target) = (x, child) - result += " " + vertex_key(source) + " -> "+vertex_key(target)+ " [ "+option+"label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n" - result+="}" + result += " " + vertex_key(source) + " -> "+vertex_key(target) + " [ "+option+"label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n" + result += "}" return result def plot(self, **options): diff --git a/src/sage/categories/discrete_valuation.py b/src/sage/categories/discrete_valuation.py index 42829732859..4bb61a5aa67 100644 --- a/src/sage/categories/discrete_valuation.py +++ b/src/sage/categories/discrete_valuation.py @@ -20,7 +20,7 @@ class DiscreteValuationRings(Category_singleton): EXAMPLES:: - sage: GF(7)[['x']] in DiscreteValuationRings() # optional - sage.rings.finite_rings + sage: GF(7)[['x']] in DiscreteValuationRings() True sage: TestSuite(DiscreteValuationRings()).run() """ @@ -41,7 +41,7 @@ def uniformizer(self): EXAMPLES:: - sage: Zp(5).uniformizer() # optional - sage.rings.padics + sage: Zp(5).uniformizer() # needs sage.rings.padics 5 + O(5^21) sage: K. = QQ[[]] @@ -56,7 +56,7 @@ def residue_field(self): EXAMPLES:: - sage: Zp(5).residue_field() # optional - sage.rings.padics + sage: Zp(5).residue_field() # needs sage.rings.padics Finite Field of size 5 sage: K. = QQ[[]] @@ -70,38 +70,41 @@ def _matrix_charpoly(self, M, var): EXAMPLES:: - sage: R. = PowerSeriesRing(GF(5)) # optional - sage.rings.finite_rings - sage: M = matrix(4, 4, [(t^(i+j)).add_bigoh(10) # optional - sage.rings.finite_rings + sage: # needs sage.modules + sage: R. = PowerSeriesRing(GF(5)) + sage: M = matrix(4, 4, [(t^(i+j)).add_bigoh(10) ....: for i in range(4) for j in range(4)]) - sage: M # optional - sage.rings.finite_rings + sage: M [ 1 + O(t^10) t + O(t^10) t^2 + O(t^10) t^3 + O(t^10)] [ t + O(t^10) t^2 + O(t^10) t^3 + O(t^10) t^4 + O(t^10)] [t^2 + O(t^10) t^3 + O(t^10) t^4 + O(t^10) t^5 + O(t^10)] [t^3 + O(t^10) t^4 + O(t^10) t^5 + O(t^10) t^6 + O(t^10)] - sage: M.charpoly() # indirect doctest # optional - sage.rings.finite_rings + sage: M.charpoly() # indirect doctest x^4 + (4 + 4*t^2 + 4*t^4 + 4*t^6 + O(t^10))*x^3 Note that this function uses a Hessenberg-like algorithm that performs divisions. Hence, truncations may show up even if the input matrix is exact:: - sage: M = matrix(3, 3, [ 1, t, t^2, 1+t, t^2, t^3, t^2, t^3, t^4 ]) # optional - sage.rings.finite_rings - sage: M # optional - sage.rings.finite_rings + sage: # needs sage.modules + sage: M = matrix(3, 3, [ 1, t, t^2, 1+t, t^2, t^3, t^2, t^3, t^4 ]) + sage: M [ 1 t t^2] [1 + t t^2 t^3] [ t^2 t^3 t^4] - sage: M.charpoly() # optional - sage.rings.finite_rings + sage: M.charpoly() x^3 + (4 + 4*t^2 + 4*t^4 + O(t^25))*x^2 + (4*t + O(t^24))*x Another example over the p-adics:: - sage: R = Zp(5, print_mode="digits", prec=5) # optional - sage.rings.padics - sage: M = matrix(R, 3, 3, range(9)) # optional - sage.rings.padics - sage: M # optional - sage.rings.padics + sage: # needs sage.modules sage.rings.padics + sage: R = Zp(5, print_mode="digits", prec=5) + sage: M = matrix(R, 3, 3, range(9)) + sage: M [ 0 ...00001 ...00002] [ ...00003 ...00004 ...000010] [ ...00011 ...00012 ...00013] - sage: M.charpoly() # optional - sage.rings.padics + sage: M.charpoly() ...00001*x^3 + ...44423*x^2 + ...44412*x + ...00000 """ return M._charpoly_hessenberg(var) @@ -114,8 +117,9 @@ def valuation(self): EXAMPLES:: - sage: x = Zp(5)(50) # optional - sage.rings.padics - sage: x.valuation() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: x = Zp(5)(50) + sage: x.valuation() 2 """ @@ -125,10 +129,10 @@ def euclidean_degree(self): TESTS:: - sage: R. = GF(5)[[]] # optional - sage.rings.finite_rings - sage: (q^3).euclidean_degree() # optional - sage.rings.finite_rings + sage: R. = GF(5)[[]] + sage: (q^3).euclidean_degree() 3 - sage: R(0).euclidean_degree() # optional - sage.rings.finite_rings + sage: R(0).euclidean_degree() Traceback (most recent call last): ... ValueError: Euclidean degree of the zero element not defined @@ -145,12 +149,12 @@ def quo_rem(self, other): TESTS:: - sage: R. = GF(5)[[]] # optional - sage.rings.finite_rings - sage: (q^2 + q).quo_rem(q) # optional - sage.rings.finite_rings + sage: R. = GF(5)[[]] + sage: (q^2 + q).quo_rem(q) (1 + q, 0) - sage: (q + 1).quo_rem(q^2) # optional - sage.rings.finite_rings + sage: (q + 1).quo_rem(q^2) (0, 1 + q) - sage: q.quo_rem(0) # optional - sage.rings.finite_rings + sage: q.quo_rem(0) Traceback (most recent call last): ... ZeroDivisionError: Euclidean division by the zero element not defined @@ -166,16 +170,18 @@ def quo_rem(self, other): def is_unit(self): """ - Return True if self is invertible. + Return ``True`` if ``self`` is invertible. EXAMPLES:: - sage: x = Zp(5)(50) # optional - sage.rings.padics - sage: x.is_unit() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: x = Zp(5)(50) + sage: x.is_unit() False - sage: x = Zp(7)(50) # optional - sage.rings.padics - sage: x.is_unit() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: x = Zp(7)(50) + sage: x.is_unit() True """ return self.valuation() == 0 @@ -213,7 +219,7 @@ class DiscreteValuationFields(Category_singleton): EXAMPLES:: - sage: Qp(7) in DiscreteValuationFields() # optional - sage.rings.padics + sage: Qp(7) in DiscreteValuationFields() # needs sage.rings.padics True sage: TestSuite(DiscreteValuationFields()).run() """ @@ -235,7 +241,7 @@ def uniformizer(self): EXAMPLES:: - sage: Qp(5).uniformizer() # optional - sage.rings.padics + sage: Qp(5).uniformizer() # needs sage.rings.padics 5 + O(5^21) """ @@ -247,7 +253,7 @@ def residue_field(self): EXAMPLES:: - sage: Qp(5).residue_field() # optional - sage.rings.padics + sage: Qp(5).residue_field() # needs sage.rings.padics Finite Field of size 5 sage: K. = LaurentSeriesRing(QQ) @@ -261,17 +267,18 @@ def _matrix_hessenbergize(self, H): EXAMPLES:: - sage: R. = PowerSeriesRing(GF(5)) # optional - sage.rings.finite_rings - sage: K = R.fraction_field() # optional - sage.rings.finite_rings - sage: H = matrix(K, 4, 4, [(t^(i+j)).add_bigoh(10) # optional - sage.rings.finite_rings + sage: # needs sage.modules + sage: R. = PowerSeriesRing(GF(5)) + sage: K = R.fraction_field() + sage: H = matrix(K, 4, 4, [(t^(i+j)).add_bigoh(10) ....: for i in range(4) for j in range(4)]) - sage: H # optional - sage.rings.finite_rings + sage: H [ 1 + O(t^10) t + O(t^10) t^2 + O(t^10) t^3 + O(t^10)] [ t + O(t^10) t^2 + O(t^10) t^3 + O(t^10) t^4 + O(t^10)] [t^2 + O(t^10) t^3 + O(t^10) t^4 + O(t^10) t^5 + O(t^10)] [t^3 + O(t^10) t^4 + O(t^10) t^5 + O(t^10) t^6 + O(t^10)] - sage: H.hessenbergize() # optional - sage.rings.finite_rings - sage: H # optional - sage.rings.finite_rings + sage: H.hessenbergize() + sage: H [ 1 + O(t^10) t + t^3 + t^5 + O(t^10) t^2 + O(t^10) t^3 + O(t^10)] [ t + O(t^10) t^2 + t^4 + t^6 + O(t^10) t^3 + O(t^10) t^4 + O(t^10)] [ O(t^10) O(t^10) O(t^10) O(t^10)] @@ -279,14 +286,13 @@ def _matrix_hessenbergize(self, H): Another example over the p-adics:: - sage: K = Qp(5, print_mode="digits", prec=5) # optional - sage.rings.padics - sage: H = matrix(K, 3, 3, range(9)) # optional - sage.rings.padics - sage: H # optional - sage.rings.padics + sage: # needs sage.modules sage.rings.padics + sage: K = Qp(5, print_mode="digits", prec=5) + sage: H = matrix(K, 3, 3, range(9)); H [ 0 ...00001 ...00002] [ ...00003 ...00004 ...000010] [ ...00011 ...00012 ...00013] - sage: H.hessenbergize() # optional - sage.rings.padics - sage: H # optional - sage.rings.padics + sage: H.hessenbergize(); H [ 0 ...00010 ...00002] [ ...00003 ...00024 ...000010] [ ...00000 ...44440 ...44443] @@ -302,7 +308,8 @@ def valuation(self): EXAMPLES:: - sage: x = Qp(5)(50) # optional - sage.rings.padics - sage: x.valuation() # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: x = Qp(5)(50) + sage: x.valuation() 2 """ diff --git a/src/sage/categories/distributive_magmas_and_additive_magmas.py b/src/sage/categories/distributive_magmas_and_additive_magmas.py index 3518893c907..6d1c7511c11 100644 --- a/src/sage/categories/distributive_magmas_and_additive_magmas.py +++ b/src/sage/categories/distributive_magmas_and_additive_magmas.py @@ -68,7 +68,7 @@ def _test_distributivity(self, **options): However, the elements tested can be customized with the ``elements`` keyword argument:: - sage: CC._test_distributivity(elements=[CC(0),CC(1),CC(3),CC(I)]) + sage: CC._test_distributivity(elements=[CC(0),CC(1),CC(3),CC(I)]) # needs sage.symbolic See the documentation for :class:`TestSuite` for more information. """ diff --git a/src/sage/categories/domains.py b/src/sage/categories/domains.py index 02062390a02..18e2907b8ef 100644 --- a/src/sage/categories/domains.py +++ b/src/sage/categories/domains.py @@ -59,21 +59,22 @@ def _test_zero_divisors(self, **options): not have them in theory. For such inexact rings, these tests are not performed:: - sage: R = ZpFM(5); R # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R = ZpFM(5); R 5-adic Ring of fixed modulus 5^20 - sage: R.is_exact() # optional - sage.rings.padics + sage: R.is_exact() False - sage: a = R(5^19) # optional - sage.rings.padics - sage: a.is_zero() # optional - sage.rings.padics + sage: a = R(5^19) + sage: a.is_zero() False - sage: (a * a).is_zero() # optional - sage.rings.padics + sage: (a * a).is_zero() True - sage: R._test_zero_divisors() # optional - sage.rings.padics + sage: R._test_zero_divisors() EXAMPLES:: sage: ZZ._test_zero_divisors() - sage: ZpFM(5)._test_zero_divisors() # optional - sage.rings.padics + sage: ZpFM(5)._test_zero_divisors() # needs sage.rings.padics """ if not self.is_exact(): diff --git a/src/sage/categories/drinfeld_modules.py b/src/sage/categories/drinfeld_modules.py index fe64c6a4a59..380318c37ff 100644 --- a/src/sage/categories/drinfeld_modules.py +++ b/src/sage/categories/drinfeld_modules.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings r""" Drinfeld modules over a base diff --git a/src/sage/categories/dual.py b/src/sage/categories/dual.py index b08eb497d39..2b21f81cbda 100644 --- a/src/sage/categories/dual.py +++ b/src/sage/categories/dual.py @@ -36,4 +36,4 @@ def _repr_object_names(self): Category of duals of vector spaces over Rational Field """ # Just to remove the `objects` - return "duals of %s"%(self.base_category()._repr_object_names()) + return "duals of %s" % (self.base_category()._repr_object_names()) diff --git a/src/sage/categories/enumerated_sets.py b/src/sage/categories/enumerated_sets.py index de57384e2de..a8bea53f907 100644 --- a/src/sage/categories/enumerated_sets.py +++ b/src/sage/categories/enumerated_sets.py @@ -278,33 +278,34 @@ def iterator_range(self, start=None, stop=None, step=None): EXAMPLES:: - sage: P = Partitions() # optional - sage.combinat - sage: list(P.iterator_range(stop=5)) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = Partitions() + sage: list(P.iterator_range(stop=5)) [[], [1], [2], [1, 1], [3]] - sage: list(P.iterator_range(0, 5)) # optional - sage.combinat + sage: list(P.iterator_range(0, 5)) [[], [1], [2], [1, 1], [3]] - sage: list(P.iterator_range(3, 5)) # optional - sage.combinat + sage: list(P.iterator_range(3, 5)) [[1, 1], [3]] - sage: list(P.iterator_range(3, 10)) # optional - sage.combinat + sage: list(P.iterator_range(3, 10)) [[1, 1], [3], [2, 1], [1, 1, 1], [4], [3, 1], [2, 2]] - sage: list(P.iterator_range(3, 10, 2)) # optional - sage.combinat + sage: list(P.iterator_range(3, 10, 2)) [[1, 1], [2, 1], [4], [2, 2]] - sage: it = P.iterator_range(3) # optional - sage.combinat - sage: [next(it) for x in range(10)] # optional - sage.combinat + sage: it = P.iterator_range(3) + sage: [next(it) for x in range(10)] [[1, 1], [3], [2, 1], [1, 1, 1], [4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1], [5]] - sage: it = P.iterator_range(3, step=2) # optional - sage.combinat - sage: [next(it) for x in range(5)] # optional - sage.combinat + sage: it = P.iterator_range(3, step=2) + sage: [next(it) for x in range(5)] [[1, 1], [2, 1], [4], [2, 2], [1, 1, 1, 1]] - sage: next(P.iterator_range(stop=-3)) # optional - sage.combinat + sage: next(P.iterator_range(stop=-3)) Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set - sage: next(P.iterator_range(start=-3)) # optional - sage.combinat + sage: next(P.iterator_range(start=-3)) Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set @@ -357,26 +358,27 @@ def unrank_range(self, start=None, stop=None, step=None): EXAMPLES:: - sage: P = Partitions() # optional - sage.combinat - sage: P.unrank_range(stop=5) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = Partitions() + sage: P.unrank_range(stop=5) [[], [1], [2], [1, 1], [3]] - sage: P.unrank_range(0, 5) # optional - sage.combinat + sage: P.unrank_range(0, 5) [[], [1], [2], [1, 1], [3]] - sage: P.unrank_range(3, 5) # optional - sage.combinat + sage: P.unrank_range(3, 5) [[1, 1], [3]] - sage: P.unrank_range(3, 10) # optional - sage.combinat + sage: P.unrank_range(3, 10) [[1, 1], [3], [2, 1], [1, 1, 1], [4], [3, 1], [2, 2]] - sage: P.unrank_range(3, 10, 2) # optional - sage.combinat + sage: P.unrank_range(3, 10, 2) [[1, 1], [2, 1], [4], [2, 2]] - sage: P.unrank_range(3) # optional - sage.combinat + sage: P.unrank_range(3) Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set - sage: P.unrank_range(stop=-3) # optional - sage.combinat + sage: P.unrank_range(stop=-3) Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set - sage: P.unrank_range(start=-3) # optional - sage.combinat + sage: P.unrank_range(start=-3) Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set @@ -410,24 +412,25 @@ def __getitem__(self, i): EXAMPLES:: - sage: P = Partitions() # optional - sage.combinat - sage: P[:5] # optional - sage.combinat + sage: # needs sage.combinat + sage: P = Partitions() + sage: P[:5] [[], [1], [2], [1, 1], [3]] - sage: P[0:5] # optional - sage.combinat + sage: P[0:5] [[], [1], [2], [1, 1], [3]] - sage: P[3:5] # optional - sage.combinat + sage: P[3:5] [[1, 1], [3]] - sage: P[3:10] # optional - sage.combinat + sage: P[3:10] [[1, 1], [3], [2, 1], [1, 1, 1], [4], [3, 1], [2, 2]] - sage: P[3:10:2] # optional - sage.combinat + sage: P[3:10:2] [[1, 1], [2, 1], [4], [2, 2]] - sage: P[3:] # optional - sage.combinat + sage: P[3:] Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set - sage: P[3] # optional - sage.combinat + sage: P[3] [1, 1] - sage: P[-1] # optional - sage.combinat + sage: P[-1] Traceback (most recent call last): ... NotImplementedError: cannot list an infinite set @@ -468,9 +471,9 @@ def __len__(self): EXAMPLES:: - sage: len(GF(5)) # optional - sage.libs.pari + sage: len(GF(5)) 5 - sage: len(MatrixSpace(GF(2), 3, 3)) # optional - sage.libs.pari sage.modules + sage: len(MatrixSpace(GF(2), 3, 3)) # needs sage.modules 512 """ from sage.rings.infinity import Infinity @@ -495,7 +498,7 @@ def tuple(self): EXAMPLES:: - sage: (GF(3)^2).tuple() # optional - sage.libs.pari + sage: (GF(3)^2).tuple() # needs sage.modules ((0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)) sage: R = Integers(11) sage: l = R.tuple(); l @@ -576,7 +579,7 @@ def list(self): EXAMPLES:: - sage: (GF(3)^2).list() # optional - sage.libs.pari + sage: (GF(3)^2).list() # needs sage.modules [(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)] sage: R = Integers(11) sage: R.list() @@ -604,7 +607,7 @@ def _list_from_iterator(self): Trying to list an infinite vector space raises an error instead of running forever (see :trac:`10470`):: - sage: (QQ^2).list() # indirect test # optional - sage.modules + sage: (QQ^2).list() # indirect test # needs sage.modules Traceback (most recent call last): ... AttributeError: 'FreeModule_ambient_field_with_category' object has no attribute 'list' @@ -739,7 +742,7 @@ def _unrank_from_iterator(self, r): for counter, u in enumerate(self): if counter == r: return u - raise ValueError("the rank must be in the range from %s to %s"%(0,counter)) + raise ValueError("the rank must be in the range from %s to %s" % (0,counter)) unrank = _unrank_from_iterator def _rank_from_iterator(self, x): @@ -954,16 +957,16 @@ def map(self, f, name=None, *, is_injective=True): EXAMPLES:: - sage: R = Compositions(4).map(attrcall('partial_sums')); R # optional - sage.combinat + sage: R = Compositions(4).map(attrcall('partial_sums')); R Image of Compositions of 4 by The map *.partial_sums() from Compositions of 4 - sage: R.cardinality() # optional - sage.combinat + sage: R.cardinality() 8 - sage: R.list() # optional - sage.combinat + sage: R.list() [[1, 2, 3, 4], [1, 2, 4], [1, 3, 4], [1, 4], [2, 3, 4], [2, 4], [3, 4], [4]] - sage: [r for r in R] # optional - sage.combinat + sage: [r for r in R] [[1, 2, 3, 4], [1, 2, 4], [1, 3, 4], [1, 4], [2, 3, 4], [2, 4], [3, 4], [4]] - sage: R.category() # optional - sage.combinat + sage: R.category() Category of finite enumerated subobjects of sets .. WARNING:: @@ -971,20 +974,20 @@ def map(self, f, name=None, *, is_injective=True): If the function is not injective, then there may be repeated elements:: - sage: P = Compositions(4) # optional - sage.combinat - sage: P.list() # optional - sage.combinat + sage: P = Compositions(4) + sage: P.list() [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] - sage: P.map(attrcall('major_index')).list() # optional - sage.combinat + sage: P.map(attrcall('major_index')).list() [6, 3, 4, 1, 5, 2, 3, 0] Pass ``is_injective=False`` to get a correct result in this case:: - sage: P.map(attrcall('major_index'), is_injective=False).list() # optional - sage.combinat + sage: P.map(attrcall('major_index'), is_injective=False).list() [6, 3, 4, 1, 5, 2, 0] TESTS:: - sage: TestSuite(R).run(skip=['_test_an_element', # optional - sage.combinat + sage: TestSuite(R).run(skip=['_test_an_element', ....: '_test_enumerated_set_contains', ....: '_test_some_elements']) """ diff --git a/src/sage/categories/examples/algebras_with_basis.py b/src/sage/categories/examples/algebras_with_basis.py index ccbc3a3a9c0..e19d74ff3c9 100644 --- a/src/sage/categories/examples/algebras_with_basis.py +++ b/src/sage/categories/examples/algebras_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat +# sage.doctest: needs sage.combinat r""" Examples of algebras with basis """ @@ -26,9 +26,9 @@ def __init__(self, R, alphabet=("a", "b", "c")): """ EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: TestSuite(A).run() + sage: TestSuite(A).run() # needs sage.modules """ self._alphabet = alphabet @@ -40,10 +40,10 @@ def _repr_(self): """ EXAMPLES:: - sage: AlgebrasWithBasis(QQ).example() # indirect doctest + sage: AlgebrasWithBasis(QQ).example() # indirect doctest # needs sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field """ - return "An example of an algebra with basis: the free algebra on the generators %s over %s"%(self._alphabet, self.base_ring()) + return "An example of an algebra with basis: the free algebra on the generators %s over %s" % (self._alphabet, self.base_ring()) @cached_method def one_basis(self): @@ -53,10 +53,10 @@ def one_basis(self): EXAMPLES::r - sage: A = AlgebrasWithBasis(QQ).example() - sage: A.one_basis() + sage: A = AlgebrasWithBasis(QQ).example() # needs sage.modules + sage: A.one_basis() # needs sage.modules word: - sage: A.one() + sage: A.one() # needs sage.modules B[word: ] """ return self.basis().keys()([]) @@ -68,6 +68,7 @@ def product_on_basis(self, w1, w2): EXAMPLES:: + sage: # needs sage.modules sage: A = AlgebrasWithBasis(QQ).example() sage: Words = A.basis().keys() sage: A.product_on_basis(Words("acb"), Words("cba")) @@ -85,9 +86,9 @@ def algebra_generators(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: A.algebra_generators() + sage: A.algebra_generators() # needs sage.modules Family (B[word: a], B[word: b], B[word: c]) """ Words = self.basis().keys() @@ -96,4 +97,5 @@ def algebra_generators(self): # for the specifying the order of the elements in the family #return Family(self._alphabet, lambda a: self.term(self.basis().keys()(a))) + Example = FreeAlgebra diff --git a/src/sage/categories/examples/commutative_additive_monoids.py b/src/sage/categories/examples/commutative_additive_monoids.py index 5295afb55ef..20728722d9f 100644 --- a/src/sage/categories/examples/commutative_additive_monoids.py +++ b/src/sage/categories/examples/commutative_additive_monoids.py @@ -95,7 +95,7 @@ def _repr_(self): "An example of a commutative monoid: the free commutative monoid generated by ('a', 'b', 'c')" """ - return "An example of a commutative monoid: the free commutative monoid generated by %s"%(self.alphabet,) + return "An example of a commutative monoid: the free commutative monoid generated by %s" % (self.alphabet,) @cached_method def zero(self): diff --git a/src/sage/categories/examples/commutative_additive_semigroups.py b/src/sage/categories/examples/commutative_additive_semigroups.py index fdda759869a..ce501d5caef 100644 --- a/src/sage/categories/examples/commutative_additive_semigroups.py +++ b/src/sage/categories/examples/commutative_additive_semigroups.py @@ -94,7 +94,7 @@ def _repr_(self): "An example of a commutative semigroup: the free commutative semigroup generated by ('a', 'b', 'c')" """ - return "An example of a commutative semigroup: the free commutative semigroup generated by %s"%(self.alphabet,) + return "An example of a commutative semigroup: the free commutative semigroup generated by %s" % (self.alphabet,) def summation(self, x, y): r""" @@ -181,7 +181,7 @@ def _repr_(self): 0 """ d = self.value - result = ' + '.join( ("%s*%s"%(d[a],a) if d[a] != 1 else a) for a in sorted(d.keys()) if d[a] != 0) + result = ' + '.join( ("%s*%s" % (d[a],a) if d[a] != 1 else a) for a in sorted(d.keys()) if d[a] != 0) return '0' if result == '' else result def __hash__(self): @@ -194,4 +194,5 @@ def __hash__(self): """ return hash(tuple(self.value.items())) + Example = FreeCommutativeAdditiveSemigroup diff --git a/src/sage/categories/examples/crystals.py b/src/sage/categories/examples/crystals.py index c38117b3b70..520b97c34d5 100644 --- a/src/sage/categories/examples/crystals.py +++ b/src/sage/categories/examples/crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.graphs +# sage.doctest: needs sage.combinat sage.graphs r""" Example of a crystal """ @@ -117,7 +117,7 @@ def _repr_(self): sage: Crystals().example() Highest weight crystal of type A_3 of highest weight omega_1 """ - return "Highest weight crystal of type A_%s of highest weight omega_1"%(self.n) + return "Highest weight crystal of type A_%s of highest weight omega_1" % (self.n) # temporary workaround while an_element is overridden by Parent _an_element_ = EnumeratedSets.ParentMethods._an_element_ diff --git a/src/sage/categories/examples/cw_complexes.py b/src/sage/categories/examples/cw_complexes.py index 8422fc0a418..0fefb254c20 100644 --- a/src/sage/categories/examples/cw_complexes.py +++ b/src/sage/categories/examples/cw_complexes.py @@ -158,4 +158,5 @@ def dimension(self): """ return self._dim + Example = Surface diff --git a/src/sage/categories/examples/filtered_algebras_with_basis.py b/src/sage/categories/examples/filtered_algebras_with_basis.py index 5a83c54d1fd..57d106e4555 100644 --- a/src/sage/categories/examples/filtered_algebras_with_basis.py +++ b/src/sage/categories/examples/filtered_algebras_with_basis.py @@ -198,4 +198,5 @@ def product_on_basis(self, s, t): cur = cur * self.monomial(self._indices.gen(a)) return cur + Example = PBWBasisCrossProduct diff --git a/src/sage/categories/examples/filtered_modules_with_basis.py b/src/sage/categories/examples/filtered_modules_with_basis.py index 3cf9db3f57c..a76726099bc 100644 --- a/src/sage/categories/examples/filtered_modules_with_basis.py +++ b/src/sage/categories/examples/filtered_modules_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat +# sage.doctest: needs sage.combinat r""" Examples of filtered modules with basis """ @@ -34,7 +34,7 @@ class FilteredPartitionModule(CombinatorialFreeModule): :: - sage: A = ModulesWithBasis(QQ).Filtered().example() + sage: A = ModulesWithBasis(QQ).Filtered().example() # needs sage.modules - If the algebra is called ``A``, then its basis function is stored as ``A.basis``. Thus the function can be used to @@ -44,7 +44,7 @@ class FilteredPartitionModule(CombinatorialFreeModule): :: - sage: [m for m in A.basis(4)] + sage: [m for m in A.basis(4)] # needs sage.modules [P[4], P[3, 1], P[2, 2], P[2, 1, 1], P[1, 1, 1, 1]] - For dealing with basis elements: :meth:`degree_on_basis`, and @@ -58,9 +58,9 @@ class FilteredPartitionModule(CombinatorialFreeModule): :: - sage: A.degree_on_basis(Partition([4,3])) + sage: A.degree_on_basis(Partition([4,3])) # needs sage.modules 7 - sage: A._repr_term(Partition([4,3])) + sage: A._repr_term(Partition([4,3])) # needs sage.modules 'P[4, 3]' - There is a class for elements, which inherits from @@ -74,20 +74,20 @@ class FilteredPartitionModule(CombinatorialFreeModule): :: - sage: p = A.monomial(Partition([3,2,1])); p + sage: p = A.monomial(Partition([3,2,1])); p # needs sage.modules P[3, 2, 1] - sage: p.is_homogeneous() + sage: p.is_homogeneous() # needs sage.modules True - sage: p.degree() + sage: p.degree() # needs sage.modules 6 """ def __init__(self, base_ring): """ EXAMPLES:: - sage: A = ModulesWithBasis(QQ).Filtered().example(); A + sage: A = ModulesWithBasis(QQ).Filtered().example(); A # needs sage.modules An example of a filtered module with basis: the free module on partitions over Rational Field - sage: TestSuite(A).run() + sage: TestSuite(A).run() # needs sage.modules """ CombinatorialFreeModule.__init__(self, base_ring, Partitions(), category=FilteredModulesWithBasis(base_ring)) @@ -111,6 +111,7 @@ def degree_on_basis(self, t): EXAMPLES:: + sage: # needs sage.modules sage: A = ModulesWithBasis(QQ).Filtered().example() sage: A.degree_on_basis(Partition((2,1))) 3 @@ -127,7 +128,7 @@ def _repr_(self): EXAMPLES:: - sage: ModulesWithBasis(QQ).Filtered().example() # indirect doctest + sage: ModulesWithBasis(QQ).Filtered().example() # indirect doctest # needs sage.modules An example of a filtered module with basis: the free module on partitions over Rational Field """ return "An example of a filtered module with basis: the free module on partitions over %s" % self.base_ring() @@ -142,10 +143,11 @@ def _repr_term(self, t): EXAMPLES:: - sage: A = ModulesWithBasis(QQ).Filtered().example() - sage: A._repr_term(Partition((4,2,1))) + sage: A = ModulesWithBasis(QQ).Filtered().example() # needs sage.modules + sage: A._repr_term(Partition((4,2,1))) # needs sage.modules 'P[4, 2, 1]' """ return 'P' + t._repr_() + Example = FilteredPartitionModule diff --git a/src/sage/categories/examples/finite_coxeter_groups.py b/src/sage/categories/examples/finite_coxeter_groups.py index 57ada2a0c2b..84e4c1f95b4 100644 --- a/src/sage/categories/examples/finite_coxeter_groups.py +++ b/src/sage/categories/examples/finite_coxeter_groups.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Examples of finite Coxeter groups """ diff --git a/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py b/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py index ac18f69b6ec..df8957dbaf7 100644 --- a/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py +++ b/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.modules r""" Example of a finite dimensional algebra with basis """ @@ -56,7 +56,7 @@ def _repr_(self): """ return "An example of a finite dimensional algebra with basis: " \ "the path algebra of the Kronecker quiver " \ - "(containing the arrows a:x->y and b:x->y) over %s "%(self.base_ring()) + "(containing the arrows a:x->y and b:x->y) over %s " % (self.base_ring()) def one(self): r""" @@ -143,4 +143,5 @@ def _repr_term(self, p): """ return str(p) + Example = KroneckerQuiverPathAlgebra diff --git a/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py b/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py index db28f48dff7..9f221f1432e 100644 --- a/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +++ b/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.modules r""" Examples of a finite dimensional Lie algebra with basis """ @@ -363,7 +363,7 @@ def lift(self): sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() sage: a, b, c = L.lie_algebra_generators() sage: elt = 2*a + 2*b + 3*c - sage: elt.lift() + sage: elt.lift() # needs sage.combinat 2*b0 + 2*b1 + 3*b2 """ UEA = self.parent().universal_enveloping_algebra() @@ -404,4 +404,5 @@ def monomial_coefficients(self, copy=True): """ return self.value.monomial_coefficients(copy) + Example = AbelianLieAlgebra diff --git a/src/sage/categories/examples/finite_monoids.py b/src/sage/categories/examples/finite_monoids.py index 4d3e8fa7029..0a4c1374893 100644 --- a/src/sage/categories/examples/finite_monoids.py +++ b/src/sage/categories/examples/finite_monoids.py @@ -86,7 +86,7 @@ def _repr_(self): sage: M._repr_() 'An example of a finite multiplicative monoid: the integers modulo 12' """ - return "An example of a finite multiplicative monoid: the integers modulo %s"%self.n + return "An example of a finite multiplicative monoid: the integers modulo %s" % self.n def semigroup_generators(self): r""" @@ -146,4 +146,5 @@ def an_element(self): class Element (ElementWrapper): wrapped_class = Integer + Example = IntegerModMonoid diff --git a/src/sage/categories/examples/finite_semigroups.py b/src/sage/categories/examples/finite_semigroups.py index bf00b415b58..13712de76fe 100644 --- a/src/sage/categories/examples/finite_semigroups.py +++ b/src/sage/categories/examples/finite_semigroups.py @@ -70,9 +70,9 @@ class LeftRegularBand(UniqueRepresentation, Parent): Now, let us look at the structure of the semigroup:: sage: S = FiniteSemigroups().example(alphabet = ('a','b','c')) - sage: S.cayley_graph(side="left", simple=True).plot() # optional - sage.graphs + sage: S.cayley_graph(side="left", simple=True).plot() # needs sage.graphs sage.plot Graphics object consisting of 60 graphics primitives - sage: S.j_transversal_of_idempotents() # random (arbitrary choice) # optional - sage.graphs + sage: S.j_transversal_of_idempotents() # random (arbitrary choice) # needs sage.graphs ['acb', 'ac', 'ab', 'bc', 'a', 'c', 'b'] We conclude by running systematic tests on this semigroup:: @@ -129,7 +129,7 @@ def _repr_(self): sage: S._repr_() "An example of a finite semigroup: the left regular band generated by ('a', 'b', 'c', 'd')" """ - return "An example of a finite semigroup: the left regular band generated by %s"%(self.alphabet,) + return "An example of a finite semigroup: the left regular band generated by %s" % (self.alphabet,) def product(self, x, y): r""" @@ -187,4 +187,5 @@ class Element (ElementWrapper): wrapped_class = str __lt__ = ElementWrapper._lt_by_value + Example = LeftRegularBand diff --git a/src/sage/categories/examples/finite_weyl_groups.py b/src/sage/categories/examples/finite_weyl_groups.py index b4d6c05a233..a8b27cd7ffe 100644 --- a/src/sage/categories/examples/finite_weyl_groups.py +++ b/src/sage/categories/examples/finite_weyl_groups.py @@ -59,7 +59,7 @@ class SymmetricGroup(UniqueRepresentation, Parent): 24 sage: S.long_element() (3, 2, 1, 0) - sage: S.cayley_graph(side="left").plot() # optional - sage.graphs sage.plot + sage: S.cayley_graph(side="left").plot() # needs sage.graphs sage.plot Graphics object consisting of 120 graphics primitives Alternatively, one could have implemented @@ -69,7 +69,7 @@ class SymmetricGroup(UniqueRepresentation, Parent): TESTS:: - sage: TestSuite(S).run() # optional - sage.combinat + sage: TestSuite(S).run() """ def __init__(self, n=4): @@ -91,7 +91,7 @@ def _repr_(self): The symmetric group on {0, ..., 3} """ - return "The symmetric group on {0, ..., %s}"%(self.n-1) + return "The symmetric group on {0, ..., %s}" % (self.n-1) @cached_method def one(self): @@ -135,7 +135,7 @@ def cartan_type(self): EXAMPLES:: - sage: FiniteWeylGroups().example().cartan_type() # optional - sage.combinat + sage: FiniteWeylGroups().example().cartan_type() # needs sage.modules ['A', 3] relabelled by {1: 0, 2: 1, 3: 2} """ from sage.combinat.root_system.cartan_type import CartanType diff --git a/src/sage/categories/examples/graded_connected_hopf_algebras_with_basis.py b/src/sage/categories/examples/graded_connected_hopf_algebras_with_basis.py index 2d2a0f71f4b..2290419adb3 100644 --- a/src/sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +++ b/src/sage/categories/examples/graded_connected_hopf_algebras_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.modules r""" Examples of graded connected Hopf algebras with basis """ @@ -162,4 +162,5 @@ def coproduct_on_basis(self, i): for j in range(i+1) ) + Example = GradedConnectedCombinatorialHopfAlgebraWithPrimitiveGenerator diff --git a/src/sage/categories/examples/graded_modules_with_basis.py b/src/sage/categories/examples/graded_modules_with_basis.py index 86aa957c404..8ddfb7eed04 100644 --- a/src/sage/categories/examples/graded_modules_with_basis.py +++ b/src/sage/categories/examples/graded_modules_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat +# sage.doctest: needs sage.combinat r""" Examples of graded modules with basis """ @@ -35,7 +35,7 @@ class GradedPartitionModule(CombinatorialFreeModule): :: - sage: A = GradedModulesWithBasis(QQ).example() + sage: A = GradedModulesWithBasis(QQ).example() # needs sage.modules - A basis function - this module is graded by the non-negative integers, so there is a function defined in this module, @@ -45,9 +45,9 @@ class GradedPartitionModule(CombinatorialFreeModule): :: - sage: A.basis(2) + sage: A.basis(2) # needs sage.modules Lazy family (Term map from Partitions to An example of a graded module with basis: the free module on partitions over Rational Field(i))_{i in Partitions of the integer 2} - sage: A.basis(6)[Partition([3,2,1])] + sage: A.basis(6)[Partition([3,2,1])] # needs sage.modules P[3, 2, 1] - If the algebra is called ``A``, then its basis function is @@ -58,7 +58,7 @@ class GradedPartitionModule(CombinatorialFreeModule): :: - sage: [m for m in A.basis(4)] + sage: [m for m in A.basis(4)] # needs sage.modules [P[4], P[3, 1], P[2, 2], P[2, 1, 1], P[1, 1, 1, 1]] - For dealing with basis elements: :meth:`degree_on_basis`, and @@ -72,9 +72,9 @@ class GradedPartitionModule(CombinatorialFreeModule): :: - sage: A.degree_on_basis(Partition([4,3])) + sage: A.degree_on_basis(Partition([4,3])) # needs sage.modules 7 - sage: A._repr_term(Partition([4,3])) + sage: A._repr_term(Partition([4,3])) # needs sage.modules 'P[4, 3]' - There is a class for elements, which inherits from @@ -88,20 +88,20 @@ class GradedPartitionModule(CombinatorialFreeModule): :: - sage: p = A.monomial(Partition([3,2,1])); p + sage: p = A.monomial(Partition([3,2,1])); p # needs sage.modules P[3, 2, 1] - sage: p.is_homogeneous() + sage: p.is_homogeneous() # needs sage.modules True - sage: p.degree() + sage: p.degree() # needs sage.modules 6 """ def __init__(self, base_ring): """ EXAMPLES:: - sage: A = GradedModulesWithBasis(QQ).example(); A + sage: A = GradedModulesWithBasis(QQ).example(); A # needs sage.modules An example of a graded module with basis: the free module on partitions over Rational Field - sage: TestSuite(A).run() + sage: TestSuite(A).run() # needs sage.modules """ CombinatorialFreeModule.__init__(self, base_ring, Partitions(), category=GradedModulesWithBasis(base_ring)) @@ -125,6 +125,7 @@ def degree_on_basis(self, t): EXAMPLES:: + sage: # needs sage.modules sage: A = GradedModulesWithBasis(QQ).example() sage: A.degree_on_basis(Partition((2,1))) 3 @@ -141,7 +142,7 @@ def _repr_(self): EXAMPLES:: - sage: GradedModulesWithBasis(QQ).example() # indirect doctest + sage: GradedModulesWithBasis(QQ).example() # indirect doctest # needs sage.modules An example of a graded module with basis: the free module on partitions over Rational Field """ return "An example of a graded module with basis: the free module on partitions over %s" % self.base_ring() @@ -156,10 +157,11 @@ def _repr_term(self, t): EXAMPLES:: - sage: A = GradedModulesWithBasis(QQ).example() - sage: A._repr_term(Partition((4,2,1))) + sage: A = GradedModulesWithBasis(QQ).example() # needs sage.modules + sage: A._repr_term(Partition((4,2,1))) # needs sage.modules 'P[4, 2, 1]' """ return 'P' + t._repr_() + Example = GradedPartitionModule diff --git a/src/sage/categories/examples/graphs.py b/src/sage/categories/examples/graphs.py index 21c2d2a150a..063eeff1427 100644 --- a/src/sage/categories/examples/graphs.py +++ b/src/sage/categories/examples/graphs.py @@ -117,4 +117,5 @@ def dimension(self): return 2 return 1 + Example = Cycle diff --git a/src/sage/categories/examples/hopf_algebras_with_basis.py b/src/sage/categories/examples/hopf_algebras_with_basis.py index 265ab46836f..10c89b0f9ad 100644 --- a/src/sage/categories/examples/hopf_algebras_with_basis.py +++ b/src/sage/categories/examples/hopf_algebras_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.groups sage.modules r""" Examples of Hopf algebras with basis """ @@ -43,7 +43,7 @@ def _repr_(self): sage: HopfAlgebrasWithBasis(QQ).example() # indirect doctest An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field """ - return "An example of Hopf algebra with basis: the group algebra of the %s over %s"%(self._group, self.base_ring()) + return "An example of Hopf algebra with basis: the group algebra of the %s over %s" % (self._group, self.base_ring()) @cached_method def one_basis(self): diff --git a/src/sage/categories/examples/infinite_enumerated_sets.py b/src/sage/categories/examples/infinite_enumerated_sets.py index c4bb3d8e55d..df4151f21c2 100644 --- a/src/sage/categories/examples/infinite_enumerated_sets.py +++ b/src/sage/categories/examples/infinite_enumerated_sets.py @@ -185,4 +185,5 @@ def _element_constructor_(self, i): Element = Integer + Example = NonNegativeIntegers diff --git a/src/sage/categories/examples/lie_algebras.py b/src/sage/categories/examples/lie_algebras.py index 81c7f8457ab..135c122efa2 100644 --- a/src/sage/categories/examples/lie_algebras.py +++ b/src/sage/categories/examples/lie_algebras.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.modules r""" Examples of a Lie algebra """ @@ -69,11 +69,12 @@ def __classcall_private__(cls, gens): EXAMPLES:: - sage: S3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.combinat - sage: L1 = LieAlgebras(QQ).example() # optional - sage.combinat - sage: gens = list(S3.algebra_generators()) # optional - sage.combinat - sage: L2 = LieAlgebras(QQ).example(gens) # optional - sage.combinat - sage: L1 is L2 # optional - sage.combinat + sage: # needs sage.combinat + sage: S3 = SymmetricGroupAlgebra(QQ, 3) + sage: L1 = LieAlgebras(QQ).example() + sage: gens = list(S3.algebra_generators()) + sage: L2 = LieAlgebras(QQ).example(gens) + sage: L1 is L2 True """ return super().__classcall__(cls, tuple(gens)) @@ -82,8 +83,8 @@ def __init__(self, gens): """ EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat - sage: TestSuite(L).run() # optional - sage.combinat + sage: L = LieAlgebras(QQ).example() # needs sage.combinat + sage: TestSuite(L).run() # needs sage.combinat """ if not gens: raise ValueError("need at least one generator") @@ -96,7 +97,7 @@ def _repr_(self): """ EXAMPLES:: - sage: LieAlgebras(QQ).example() # optional - sage.combinat sage.groups + sage: LieAlgebras(QQ).example() # needs sage.combinat sage.groups An example of a Lie algebra: the Lie algebra from the associative algebra Symmetric group algebra of order 3 over Rational Field generated by ([2, 1, 3], [2, 3, 1]) @@ -111,10 +112,11 @@ def _element_constructor_(self, value): EXAMPLES:: - sage: S3 = SymmetricGroupAlgebra(ZZ, 3) # optional - sage.combinat sage.groups - sage: gens = S3.algebra_generators() # optional - sage.combinat sage.groups - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: L(3*gens[0] + gens[1]) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: S3 = SymmetricGroupAlgebra(ZZ, 3) + sage: gens = S3.algebra_generators() + sage: L = LieAlgebras(QQ).example() + sage: L(3*gens[0] + gens[1]) 3*[2, 1, 3] + [2, 3, 1] """ return self.element_class(self, self._A(value)) @@ -125,8 +127,8 @@ def zero(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: L.zero() # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: L.zero() # needs sage.combinat sage.groups 0 """ return self.element_class(self, self._A.zero()) @@ -137,8 +139,8 @@ def lie_algebra_generators(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: L.lie_algebra_generators() # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: L.lie_algebra_generators() # needs sage.combinat sage.groups Family ([2, 1, 3], [2, 3, 1]) """ return Family([self.element_class(self, g) for g in self._gens]) @@ -158,17 +160,18 @@ def __eq__(self, rhs): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: x == x # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() + sage: x, y = L.lie_algebra_generators() + sage: x == x True - sage: x.bracket(y) == -y.bracket(x) # optional - sage.combinat sage.groups + sage: x.bracket(y) == -y.bracket(x) True - sage: x == y # optional - sage.combinat sage.groups + sage: x == y False - sage: x.bracket(x) == L.zero() # optional - sage.combinat sage.groups + sage: x.bracket(x) == L.zero() True - sage: x.bracket(x) == 0 # optional - sage.combinat sage.groups + sage: x.bracket(x) == 0 True """ if not isinstance(rhs, LieAlgebraFromAssociative.Element): @@ -181,15 +184,16 @@ def __ne__(self, rhs): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: x != y # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() + sage: x, y = L.lie_algebra_generators() + sage: x != y True - sage: x != 0 # optional - sage.combinat sage.groups + sage: x != 0 True - sage: x != x # optional - sage.combinat sage.groups + sage: x != x False - sage: x.bracket(y) != -y.bracket(x) # optional - sage.combinat sage.groups + sage: x.bracket(y) != -y.bracket(x) False """ return not self.__eq__(rhs) @@ -200,10 +204,10 @@ def __bool__(self) -> bool: EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: bool(sum(L.lie_algebra_generators())) # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: bool(sum(L.lie_algebra_generators())) # needs sage.combinat sage.groups True - sage: bool(L.zero()) # optional - sage.combinat sage.groups + sage: bool(L.zero()) # needs sage.combinat sage.groups False """ return bool(self.value) @@ -214,9 +218,9 @@ def _add_(self, rhs): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: x + y # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: x, y = L.lie_algebra_generators() # needs sage.combinat sage.groups + sage: x + y # needs sage.combinat sage.groups [2, 1, 3] + [2, 3, 1] """ return self.__class__(self.parent(), self.value + rhs.value) @@ -227,9 +231,9 @@ def _sub_(self, rhs): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: x - y # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: x, y = L.lie_algebra_generators() # needs sage.combinat sage.groups + sage: x - y # needs sage.combinat sage.groups [2, 1, 3] - [2, 3, 1] """ return self.__class__(self.parent(), self.value - rhs.value) @@ -240,9 +244,9 @@ def _acted_upon_(self, scalar, self_on_left=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: 3 * x # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: x, y = L.lie_algebra_generators() # needs sage.combinat sage.groups + sage: 3 * x # needs sage.combinat sage.groups 3*[2, 1, 3] """ # This was copied, but IDK if it still applies: @@ -266,9 +270,9 @@ def __truediv__(self, x, self_on_left=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: y / 4 # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: x, y = L.lie_algebra_generators() # needs sage.combinat sage.groups + sage: y / 4 # needs sage.combinat sage.groups 1/4*[2, 3, 1] """ if self_on_left: @@ -281,9 +285,9 @@ def __neg__(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x, y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: -x # optional - sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() # needs sage.combinat sage.groups + sage: x, y = L.lie_algebra_generators() # needs sage.combinat sage.groups + sage: -x # needs sage.combinat sage.groups -[2, 1, 3] """ return self.__class__(self.parent(), -self.value) @@ -314,17 +318,19 @@ def _bracket_(self, rhs): EXAMPLES:: - sage: L = LieAlgebras(QQ).example() # optional - sage.combinat sage.groups - sage: x,y = L.lie_algebra_generators() # optional - sage.combinat sage.groups - sage: elt = 2*x - y # optional - sage.combinat sage.groups - sage: elt.bracket(elt) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: L = LieAlgebras(QQ).example() + sage: x,y = L.lie_algebra_generators() + sage: elt = 2*x - y + sage: elt.bracket(elt) 0 - sage: elt.bracket(x) # optional - sage.combinat sage.groups + sage: elt.bracket(x) -[1, 3, 2] + [3, 2, 1] - sage: elt2 = x.bracket(y) + x # optional - sage.combinat sage.groups - sage: elt.bracket(elt2) # optional - sage.combinat sage.groups + sage: elt2 = x.bracket(y) + x + sage: elt.bracket(elt2) -2*[2, 1, 3] + 4*[2, 3, 1] - 4*[3, 1, 2] + 2*[3, 2, 1] """ return self.__class__(self.parent(), self.value * rhs.value - rhs.value * self.value) + Example = LieAlgebraFromAssociative diff --git a/src/sage/categories/examples/lie_algebras_with_basis.py b/src/sage/categories/examples/lie_algebras_with_basis.py index e69711ddf03..ca711e1cdb4 100644 --- a/src/sage/categories/examples/lie_algebras_with_basis.py +++ b/src/sage/categories/examples/lie_algebras_with_basis.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.modules +# sage.doctest: needs sage.combinat sage.modules r""" Examples of a Lie algebra with basis """ @@ -100,6 +100,7 @@ def lift(self): I = UEA._indices return UEA.sum_of_terms((I.gen(t), c) for t, c in self) + Example = AbelianLieAlgebra ############## diff --git a/src/sage/categories/examples/manifolds.py b/src/sage/categories/examples/manifolds.py index e1d7c851202..6a748884eec 100644 --- a/src/sage/categories/examples/manifolds.py +++ b/src/sage/categories/examples/manifolds.py @@ -89,4 +89,5 @@ def an_element(self): Element = ElementWrapper + Example = Plane diff --git a/src/sage/categories/examples/monoids.py b/src/sage/categories/examples/monoids.py index 7336c680bdf..1d2b87279d2 100644 --- a/src/sage/categories/examples/monoids.py +++ b/src/sage/categories/examples/monoids.py @@ -104,7 +104,7 @@ def _repr_(self): "An example of a monoid: the free monoid generated by ('a', 'b', 'c')" """ - return "An example of a monoid: the free monoid generated by %s"%(self.alphabet,) + return "An example of a monoid: the free monoid generated by %s" % (self.alphabet,) @cached_method def one(self): @@ -141,4 +141,5 @@ def monoid_generators(self): class Element (ElementWrapper): wrapped_class = str + Example = FreeMonoid diff --git a/src/sage/categories/examples/semigroups.py b/src/sage/categories/examples/semigroups.py index 5502215ef8a..797fd1b4b03 100644 --- a/src/sage/categories/examples/semigroups.py +++ b/src/sage/categories/examples/semigroups.py @@ -209,7 +209,7 @@ def _repr_(self): "An example of a semigroup: the free semigroup generated by ('a', 'b', 'c')" """ - return "An example of a semigroup: the free semigroup generated by %s"%(self.alphabet,) + return "An example of a semigroup: the free semigroup generated by %s" % (self.alphabet,) def product(self, x, y): r""" diff --git a/src/sage/categories/examples/sets_cat.py b/src/sage/categories/examples/sets_cat.py index fbd7d8b1fc8..e0853d63f94 100644 --- a/src/sage/categories/examples/sets_cat.py +++ b/src/sage/categories/examples/sets_cat.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari """ Examples of sets """ @@ -144,7 +144,7 @@ def _element_constructor_(self, e): AssertionError: 14 is not a prime number """ p = self.element_class(e) - assert is_prime(p), "%s is not a prime number"%(p) + assert is_prime(p), "%s is not a prime number" % (p) return p element_class = Integer @@ -213,7 +213,7 @@ def _element_constructor_(self, i): if i in self: return self._from_integer_(i) else: - raise ValueError("%s is not a prime number"%(i)) + raise ValueError("%s is not a prime number" % (i)) @abstract_method def _from_integer_(self, i): diff --git a/src/sage/categories/examples/with_realizations.py b/src/sage/categories/examples/with_realizations.py index 627bd2a07c3..5a8c1149187 100644 --- a/src/sage/categories/examples/with_realizations.py +++ b/src/sage/categories/examples/with_realizations.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.modules +# sage.doctest: needs sage.combinat sage.modules r""" Examples of parents endowed with multiple realizations """ @@ -278,7 +278,7 @@ def _repr_(self): sage: Sets().WithRealizations().example() # indirect doctest The subset algebra of {1, 2, 3} over Rational Field """ - return "The subset algebra of %s over %s"%(self.base_set(), self.base_ring()) + return "The subset algebra of %s over %s" % (self.base_set(), self.base_ring()) class Bases(Category_realization_of_parent): r""" diff --git a/src/sage/categories/facade_sets.py b/src/sage/categories/facade_sets.py index 0ddebfe30d2..746622743fb 100644 --- a/src/sage/categories/facade_sets.py +++ b/src/sage/categories/facade_sets.py @@ -100,7 +100,7 @@ def _element_constructor_(self, element): return parent(element) except Exception: pass - raise ValueError("Can't coerce `%s` in any parent `%s` is a facade for"%(element, self)) + raise ValueError("Can't coerce `%s` in any parent `%s` is a facade for" % (element, self)) def facade_for(self): """ diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 28a93a314b5..fb5e1f06a1b 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -38,10 +38,10 @@ class Fields(CategoryWithAxiom): sage: K(IntegerRing()) Rational Field - sage: K(PolynomialRing(GF(3), 'x')) # optional - sage.rings.finite_rings + sage: K(PolynomialRing(GF(3), 'x')) Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 3 - sage: K(RealField()) + sage: K(RealField()) # needs sage.rings.real_mpfr Real Field with 53 bits of precision TESTS:: @@ -64,7 +64,7 @@ def __contains__(self, x): """ EXAMPLES:: - sage: GF(4, "a") in Fields() # optional - sage.rings.finite_rings + sage: GF(4, "a") in Fields() # needs sage.rings.finite_rings True sage: QQ in Fields() True @@ -81,15 +81,15 @@ def __contains__(self, x): Caveat: this should eventually be fixed:: - sage: gap.Rationals in Fields() # optional - sage.libs.gap + sage: gap.Rationals in Fields() # needs sage.libs.gap False typically by implementing the method :meth:`category` appropriately for Gap objects:: - sage: GR = gap.Rationals # optional - sage.libs.gap - sage: GR.category = lambda: Fields() # optional - sage.libs.gap - sage: GR in Fields() # optional - sage.libs.gap + sage: GR = gap.Rationals # needs sage.libs.gap + sage: GR.category = lambda: Fields() # needs sage.libs.gap + sage: GR in Fields() # needs sage.libs.gap True The following tests against a memory leak fixed in :trac:`13370`. In order @@ -101,7 +101,7 @@ def __contains__(self, x): sage: _ = gc.collect() sage: permstore = [X for X in gc.get_objects() if isinstance(X, sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic)] sage: n = len(permstore) - sage: for i in prime_range(100): # optional - sage.libs.pari + sage: for i in prime_range(100): # needs sage.libs.pari ....: R = ZZ.quotient(i) ....: t = R in Fields() @@ -139,17 +139,18 @@ def _contains_helper(cls): TESTS:: + sage: # needs sage.libs.pari sage: P. = QQ[] - sage: Q = P.quotient(x^2 + 2) # optional - sage.libs.pari - sage: Q.category() # optional - sage.libs.pari + sage: Q = P.quotient(x^2 + 2) + sage: Q.category() Category of commutative no zero divisors quotients of algebras over (number fields and quotient fields and metric spaces) sage: F = Fields() - sage: F._contains_helper(Q) # optional - sage.libs.pari + sage: F._contains_helper(Q) False - sage: Q in F # This changes the category! # optional - sage.libs.pari + sage: Q in F # This changes the category! True - sage: F._contains_helper(Q) # optional - sage.libs.pari + sage: F._contains_helper(Q) True """ @@ -167,18 +168,18 @@ def _call_(self, x): sage: Fields().super_categories() [Category of euclidean domains, Category of division rings] - sage: K(IntegerRing()) # indirect doctest + sage: K(IntegerRing()) # indirect doctest Rational Field - sage: K(PolynomialRing(GF(3), 'x')) # indirect doctest # optional - sage.rings.finite_rings + sage: K(PolynomialRing(GF(3), 'x')) # indirect doctest Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 3 - sage: K(RealField()) + sage: K(RealField()) # needs sage.rings.real_mpfr Real Field with 53 bits of precision """ try: return x.fraction_field() except AttributeError: - raise TypeError("unable to associate a field to %s"%x) + raise TypeError("unable to associate a field to %s" % x) Finite = LazyImport('sage.categories.finite_fields', 'FiniteFields', at_startup=True) @@ -207,11 +208,11 @@ def is_integrally_closed(self): sage: QQ.is_integrally_closed() True - sage: QQbar.is_integrally_closed() # optional - sage.rings.number_field + sage: QQbar.is_integrally_closed() # needs sage.rings.number_field True - sage: Z5 = GF(5); Z5 # optional - sage.rings.finite_rings + sage: Z5 = GF(5); Z5 Finite Field of size 5 - sage: Z5.is_integrally_closed() # optional - sage.rings.finite_rings + sage: Z5.is_integrally_closed() True """ return True @@ -231,14 +232,15 @@ def _gcd_univariate_polynomial(self, a, b): EXAMPLES:: - sage: R. = QQbar[] # optional - sage.rings.number_field - sage: QQbar._gcd_univariate_polynomial(2*x, 2*x^2) # optional - sage.rings.number_field + sage: R. = QQbar[] # needs sage.rings.number_field + sage: QQbar._gcd_univariate_polynomial(2*x, 2*x^2) # needs sage.rings.number_field x TESTS:: - sage: fields = [RR, CC] - sage: fields.append(QQbar) # optional - sage.rings.number_field + sage: fields = [] + sage: fields += [RR, CC] # needs sage.rings.real_mpfr + sage: fields.append(QQbar) # needs sage.rings.number_field sage: for A in fields: ....: g = A._gcd_univariate_polynomial ....: R. = A[] @@ -248,10 +250,11 @@ def _gcd_univariate_polynomial(self, a, b): ....: g(2*x, z) == x and ....: g(z, z) == z) + sage: # needs sage.rings.real_mpfr sage: R. = RR[] - sage: (x^3).gcd(x^5+1) + sage: (x^3).gcd(x^5 + 1) 1.00000000000000 - sage: (x^3).gcd(x^5+x^2) + sage: (x^3).gcd(x^5 + x^2) x^2 sage: f = (x+3)^2 * (x-1) sage: g = (x+3)^5 @@ -261,6 +264,7 @@ def _gcd_univariate_polynomial(self, a, b): The following example illustrates the fact that for inexact base rings, the returned gcd is often 1 due to rounding:: + sage: # needs sage.rings.real_mpfr sage: f = (x+RR.pi())^2 * (x-1) sage: g = (x+RR.pi())^5 sage: f.gcd(g) @@ -268,8 +272,9 @@ def _gcd_univariate_polynomial(self, a, b): Check :trac:`23012`:: + sage: # needs sage.libs.pari sage: R. = QQ[] - sage: Q = R.quotient(x^2-1) # Not a field + sage: Q = R.quotient(x^2 - 1) # Not a field sage: P. = Q[] sage: def always_True(*args, **kwds): return True sage: Q.is_field = always_True @@ -332,8 +337,9 @@ def _xgcd_univariate_polynomial(self, a, b): TESTS:: - sage: fields = [RR, CC] - sage: fields.append(QQbar) # optional - sage.rings.number_field + sage: fields = [] + sage: fields += [RR, CC] # needs sage.rings.real_mpfr + sage: fields.append(QQbar) # needs sage.rings.number_field sage: for A in fields: ....: g = A._xgcd_univariate_polynomial ....: R. = A[] @@ -354,6 +360,7 @@ def _xgcd_univariate_polynomial(self, a, b): We check that the behavior of xgcd with zero elements is compatible with gcd (:trac:`17671`):: + sage: # needs sage.rings.number_field sage: R. = QQbar[] sage: zero = R.zero() sage: zero.xgcd(2*x) @@ -392,9 +399,9 @@ def is_perfect(self): sage: QQ.is_perfect() True - sage: GF(2).is_perfect() # optional - sage.rings.finite_rings + sage: GF(2).is_perfect() True - sage: FunctionField(GF(2), 'x').is_perfect() # optional - sage.rings.finite_rings + sage: FunctionField(GF(2), 'x').is_perfect() False """ @@ -468,11 +475,11 @@ def _squarefree_decomposition_univariate_polynomial(self, f): sage: p = 37 * (x-2/3)^2 sage: p.squarefree_decomposition() (37) * (x - 2/3)^2 - sage: x = polygen(GF(3)) # optional - sage.rings.finite_rings - sage: x.squarefree_decomposition() # optional - sage.rings.finite_rings + sage: x = polygen(GF(3)) + sage: x.squarefree_decomposition() x - sage: f = QQbar['x'](1) # optional - sage.rings.number_field - sage: f.squarefree_decomposition() # optional - sage.rings.number_field + sage: f = QQbar['x'](1) # needs sage.rings.number_field + sage: f.squarefree_decomposition() # needs sage.rings.number_field 1 """ from sage.structure.factorization import Factorization @@ -529,10 +536,11 @@ def vector_space(self, *args, **kwds): EXAMPLES:: - sage: K. = Qq(125) # optional - sage.rings.padics - sage: V, fr, to = K.vector_space() # optional - sage.rings.padics - sage: v = V([1, 2, 3]) # optional - sage.rings.padics - sage: fr(v, 7) # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K. = Qq(125) + sage: V, fr, to = K.vector_space() + sage: v = V([1, 2, 3]) + sage: fr(v, 7) (3*a^2 + 2*a + 1) + O(5^7) """ return self.free_module(*args, **kwds) @@ -605,12 +613,12 @@ def gcd(self,other): EXAMPLES:: - sage: K = GF(5) # optional - sage.rings.finite_rings - sage: K(2).gcd(K(1)) # optional - sage.rings.finite_rings + sage: K = GF(5) + sage: K(2).gcd(K(1)) 1 - sage: K(0).gcd(K(0)) # optional - sage.rings.finite_rings + sage: K(0).gcd(K(0)) 0 - sage: all(x.gcd(y) == (0 if x == 0 and y == 0 else 1) # optional - sage.rings.finite_rings + sage: all(x.gcd(y) == (0 if x == 0 and y == 0 else 1) ....: for x in K for y in K) True @@ -663,9 +671,9 @@ def lcm(self, other): EXAMPLES:: - sage: GF(2)(1).lcm(GF(2)(0)) # optional - sage.rings.finite_rings + sage: GF(2)(1).lcm(GF(2)(0)) 0 - sage: GF(2)(1).lcm(GF(2)(1)) # optional - sage.rings.finite_rings + sage: GF(2)(1).lcm(GF(2)(1)) 1 For field of characteristic zero, the lcm of integers is considered @@ -726,14 +734,14 @@ def xgcd(self, other): EXAMPLES:: - sage: K = GF(5) # optional - sage.rings.finite_rings - sage: K(2).xgcd(K(1)) # optional - sage.rings.finite_rings + sage: K = GF(5) + sage: K(2).xgcd(K(1)) (1, 3, 0) - sage: K(0).xgcd(K(4)) # optional - sage.rings.finite_rings + sage: K(0).xgcd(K(4)) (1, 0, 4) - sage: K(1).xgcd(K(1)) # optional - sage.rings.finite_rings + sage: K(1).xgcd(K(1)) (1, 1, 0) - sage: GF(5)(0).xgcd(GF(5)(0)) # optional - sage.rings.finite_rings + sage: GF(5)(0).xgcd(GF(5)(0)) (0, 0, 0) The xgcd of non-zero floating point numbers will be a triple of @@ -777,8 +785,8 @@ def factor(self): EXAMPLES:: - sage: x = GF(7)(5) # optional - sage.rings.finite_rings - sage: x.factor() # optional - sage.rings.finite_rings + sage: x = GF(7)(5) + sage: x.factor() 5 sage: RR(0).factor() Traceback (most recent call last): @@ -797,7 +805,7 @@ def inverse_of_unit(self): EXAMPLES:: sage: x = polygen(ZZ, 'x') - sage: NumberField(x^7+2, 'a')(2).inverse_of_unit() # optional - sage.rings.number_field + sage: NumberField(x^7 + 2, 'a')(2).inverse_of_unit() # needs sage.rings.number_field 1/2 Trying to invert the zero element typically raises a diff --git a/src/sage/categories/filtered_algebras_with_basis.py b/src/sage/categories/filtered_algebras_with_basis.py index 90c7078e6cc..1abddc81a18 100644 --- a/src/sage/categories/filtered_algebras_with_basis.py +++ b/src/sage/categories/filtered_algebras_with_basis.py @@ -321,6 +321,7 @@ def induced_graded_map(self, other, f): `f` will lead into a graded algebra already, namely into the algebra of symmetric functions:: + sage: # needs sage.combinat sage.modules sage: h = SymmetricFunctions(QQ).h() sage: def map_on_basis(m): # redefining map_on_basis ....: d = m.dict() @@ -351,6 +352,7 @@ def induced_graded_map(self, other, f): is already graded, so its associated graded algebra is implemented as itself:: + sage: # needs sage.combinat sage.modules sage: grh = h.graded_algebra(); grh is h True sage: grf = A.induced_graded_map(h, f); grf @@ -384,6 +386,7 @@ def induced_graded_map(self, other, f): have one as the domain instead. Our new ``f`` will go from ``h`` to ``A``:: + sage: # needs sage.combinat sage.modules sage: def map_on_basis(lam): # redefining map_on_basis ....: return x ** (sum(lam)) + y ** (len(lam)) sage: f = h.module_morphism(on_basis=map_on_basis, @@ -426,6 +429,7 @@ def induced_graded_map(self, other, f): The construct `\operatorname{gr} f` also makes sense when `f` is a filtration-preserving map between graded algebras. :: + sage: # needs sage.combinat sage.modules sage: def map_on_basis(lam): # redefining map_on_basis ....: return h[lam] + h[len(lam)] sage: f = h.module_morphism(on_basis=map_on_basis, @@ -459,6 +463,7 @@ def induced_graded_map(self, other, f): For another example, let us compute `\operatorname{gr} f` for a map `f` between two Clifford algebras:: + sage: # needs sage.modules sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: B = CliffordAlgebra(Q, names=['u','v']); B The Clifford algebra of the Quadratic form in 2 diff --git a/src/sage/categories/filtered_hopf_algebras_with_basis.py b/src/sage/categories/filtered_hopf_algebras_with_basis.py index ca2dc9ac513..0310744d9e1 100644 --- a/src/sage/categories/filtered_hopf_algebras_with_basis.py +++ b/src/sage/categories/filtered_hopf_algebras_with_basis.py @@ -88,14 +88,15 @@ def antipode_on_basis(self, index): TESTS:: - sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() # optional - sage.combinat - sage: H.monomial(0).antipode() # indirect doctest # optional - sage.combinat + sage: # needs sage.modules + sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() + sage: H.monomial(0).antipode() # indirect doctest P0 - sage: H.monomial(1).antipode() # indirect doctest # optional - sage.combinat + sage: H.monomial(1).antipode() # indirect doctest -P1 - sage: H.monomial(2).antipode() # indirect doctest # optional - sage.combinat + sage: H.monomial(2).antipode() # indirect doctest P2 - sage: H.monomial(3).antipode() # indirect doctest # optional - sage.combinat + sage: H.monomial(3).antipode() # indirect doctest -P3 """ if self.monomial(index) == self.one(): @@ -116,15 +117,15 @@ def antipode(self, elem): TESTS:: - sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() # optional - sage.combinat - sage: H.antipode(H.monomial(14)) # optional - sage.combinat + sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() # needs sage.modules + sage: H.antipode(H.monomial(14)) # needs sage.modules P14 - sage: H.monomial(0).antipode() # optional - sage.combinat + sage: H.monomial(0).antipode() # needs sage.modules P0 - sage: H.monomial(2).antipode() # optional - sage.combinat + sage: H.monomial(2).antipode() # needs sage.modules P2 - sage: (2*H.monomial(1) + 3*H.monomial(4)).antipode() # optional - sage.combinat + sage: (2*H.monomial(1) + 3*H.monomial(4)).antipode() # needs sage.modules -2*P1 + 3*P4 """ return self.linear_combination( diff --git a/src/sage/categories/filtered_modules_with_basis.py b/src/sage/categories/filtered_modules_with_basis.py index 7a9b2684f79..15d0f490713 100644 --- a/src/sage/categories/filtered_modules_with_basis.py +++ b/src/sage/categories/filtered_modules_with_basis.py @@ -205,6 +205,7 @@ def homogeneous_component_basis(self, d): to An example of a graded module with basis: the free module on partitions over Integer Ring(i))_{i in Partitions of the integer 4} + sage: # needs sage.modules sage: cat = GradedModulesWithBasis(ZZ) sage: C = CombinatorialFreeModule(ZZ, ['a', 'b'], category=cat) sage: C.degree_on_basis = lambda x: 1 if x == 'a' else 2 @@ -318,12 +319,13 @@ def to_graded_conversion(self): EXAMPLES:: - sage: A = Modules(QQ).WithBasis().Filtered().example() # optional - sage.combinat - sage: p = -2 * A.an_element(); p # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: A = Modules(QQ).WithBasis().Filtered().example() + sage: p = -2 * A.an_element(); p -4*P[] - 4*P[1] - 6*P[2] - sage: q = A.to_graded_conversion()(p); q # optional - sage.combinat + sage: q = A.to_graded_conversion()(p); q -4*Bbar[[]] - 4*Bbar[[1]] - 6*Bbar[[2]] - sage: q.parent() is A.graded_algebra() # optional - sage.combinat + sage: q.parent() is A.graded_algebra() True """ base_one = self.base_ring().one() @@ -346,14 +348,15 @@ def from_graded_conversion(self): EXAMPLES:: - sage: A = Modules(QQ).WithBasis().Filtered().example() # optional - sage.combinat - sage: p = -2 * A.an_element(); p # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: A = Modules(QQ).WithBasis().Filtered().example() + sage: p = -2 * A.an_element(); p -4*P[] - 4*P[1] - 6*P[2] - sage: q = A.to_graded_conversion()(p); q # optional - sage.combinat + sage: q = A.to_graded_conversion()(p); q -4*Bbar[[]] - 4*Bbar[[1]] - 6*Bbar[[2]] - sage: A.from_graded_conversion()(q) == p # optional - sage.combinat + sage: A.from_graded_conversion()(q) == p True - sage: q.parent() is A.graded_algebra() # optional - sage.combinat + sage: q.parent() is A.graded_algebra() True """ base_one = self.base_ring().one() @@ -378,14 +381,15 @@ def projection(self, i): EXAMPLES:: - sage: A = Modules(ZZ).WithBasis().Filtered().example() # optional - sage.combinat - sage: p = -2 * A.an_element(); p # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: A = Modules(ZZ).WithBasis().Filtered().example() + sage: p = -2 * A.an_element(); p -4*P[] - 4*P[1] - 6*P[2] - sage: q = A.projection(2)(p); q # optional - sage.combinat + sage: q = A.projection(2)(p); q -6*Bbar[[2]] - sage: q.parent() is A.graded_algebra() # optional - sage.combinat + sage: q.parent() is A.graded_algebra() True - sage: A.projection(3)(p) # optional - sage.combinat + sage: A.projection(3)(p) 0 """ base_zero = self.base_ring().zero() @@ -439,12 +443,12 @@ def induced_graded_map(self, other, f): We start with the free `\QQ`-module with basis the set of all partitions:: - sage: A = Modules(QQ).WithBasis().Filtered().example(); A # optional - sage.combinat + sage: A = Modules(QQ).WithBasis().Filtered().example(); A # needs sage.combinat sage.modules An example of a filtered module with basis: the free module on partitions over Rational Field - sage: M = A.indices(); M # optional - sage.combinat + sage: M = A.indices(); M # needs sage.combinat sage.modules Partitions - sage: p1, p2, p21, p321 = [A.basis()[Partition(i)] # optional - sage.combinat + sage: p1, p2, p21, p321 = [A.basis()[Partition(i)] # needs sage.combinat sage.modules ....: for i in [[1], [2], [2,1], [3,2,1]]] Let us define a map from ``A`` to itself which acts on the @@ -452,42 +456,44 @@ def induced_graded_map(self, other, f): the conjugates of all partitions `\mu` for which `\lambda / \mu` is a horizontal strip:: - sage: def map_on_basis(lam): # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: def map_on_basis(lam): ....: def mus(k): ....: return lam.remove_horizontal_border_strip(k) ....: return A.sum_of_monomials([Partition(mu).conjugate() ....: for k in range(sum(lam) + 1) ....: for mu in mus(k)]) - sage: f = A.module_morphism(on_basis=map_on_basis, # optional - sage.combinat + sage: f = A.module_morphism(on_basis=map_on_basis, ....: codomain=A) - sage: f(p1) # optional - sage.combinat + sage: f(p1) P[] + P[1] - sage: f(p2) # optional - sage.combinat + sage: f(p2) P[] + P[1] + P[1, 1] - sage: f(p21) # optional - sage.combinat + sage: f(p21) P[1] + P[1, 1] + P[2] + P[2, 1] - sage: f(p21 - p1) # optional - sage.combinat + sage: f(p21 - p1) -P[] + P[1, 1] + P[2] + P[2, 1] - sage: f(p321) # optional - sage.combinat + sage: f(p321) P[2, 1] + P[2, 1, 1] + P[2, 2] + P[2, 2, 1] + P[3, 1] + P[3, 1, 1] + P[3, 2] + P[3, 2, 1] We now compute `\operatorname{gr} f` :: - sage: grA = A.graded_algebra(); grA # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: grA = A.graded_algebra(); grA Graded Module of An example of a filtered module with basis: the free module on partitions over Rational Field - sage: pp1, pp2, pp21, pp321 = [A.to_graded_conversion()(i) # optional - sage.combinat + sage: pp1, pp2, pp21, pp321 = [A.to_graded_conversion()(i) ....: for i in [p1, p2, p21, p321]] - sage: pp2 + 4 * pp21 # optional - sage.combinat + sage: pp2 + 4 * pp21 Bbar[[2]] + 4*Bbar[[2, 1]] - sage: grf = A.induced_graded_map(A, f); grf # optional - sage.combinat + sage: grf = A.induced_graded_map(A, f); grf Generic endomorphism of Graded Module of An example of a filtered module with basis: the free module on partitions over Rational Field - sage: grf(pp1) # optional - sage.combinat + sage: grf(pp1) Bbar[[1]] - sage: grf(pp2 + 4 * pp21) # optional - sage.combinat + sage: grf(pp2 + 4 * pp21) Bbar[[1, 1]] + 4*Bbar[[2, 1]] **Example 2.** @@ -497,48 +503,50 @@ def induced_graded_map(self, other, f): `f` will lead into a graded algebra already, namely into the algebra of symmetric functions:: - sage: h = SymmetricFunctions(QQ).h() # optional - sage.combinat - sage: def map_on_basis(lam): # redefining map_on_basis # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: h = SymmetricFunctions(QQ).h() + sage: def map_on_basis(lam): # redefining map_on_basis ....: def mus(k): ....: return lam.remove_horizontal_border_strip(k) ....: return h.sum_of_monomials([Partition(mu).conjugate() ....: for k in range(sum(lam) + 1) ....: for mu in mus(k)]) - sage: f = A.module_morphism(on_basis=map_on_basis, # optional - sage.combinat + sage: f = A.module_morphism(on_basis=map_on_basis, ....: codomain=h) # redefining f - sage: f(p1) # optional - sage.combinat + sage: f(p1) h[] + h[1] - sage: f(p2) # optional - sage.combinat + sage: f(p2) h[] + h[1] + h[1, 1] - sage: f(A.zero()) # optional - sage.combinat + sage: f(A.zero()) 0 - sage: f(p2 - 3*p1) # optional - sage.combinat + sage: f(p2 - 3*p1) -2*h[] - 2*h[1] + h[1, 1] The algebra ``h`` of symmetric functions in the `h`-basis is already graded, so its associated graded algebra is implemented as itself:: - sage: grh = h.graded_algebra(); grh is h # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: grh = h.graded_algebra(); grh is h True - sage: grf = A.induced_graded_map(h, f); grf # optional - sage.combinat + sage: grf = A.induced_graded_map(h, f); grf Generic morphism: From: Graded Module of An example of a filtered module with basis: the free module on partitions over Rational Field To: Symmetric Functions over Rational Field in the homogeneous basis - sage: grf(pp1) # optional - sage.combinat + sage: grf(pp1) h[1] - sage: grf(pp2) # optional - sage.combinat + sage: grf(pp2) h[1, 1] - sage: grf(pp321) # optional - sage.combinat + sage: grf(pp321) h[3, 2, 1] - sage: grf(pp2 - 3*pp1) # optional - sage.combinat + sage: grf(pp2 - 3*pp1) -3*h[1] + h[1, 1] - sage: grf(pp21) # optional - sage.combinat + sage: grf(pp21) h[2, 1] - sage: grf(grA.zero()) # optional - sage.combinat + sage: grf(grA.zero()) 0 **Example 3.** @@ -547,45 +555,46 @@ def induced_graded_map(self, other, f): have one as the domain instead. Our new ``f`` will go from ``h`` to ``A``:: - sage: def map_on_basis(lam): # redefining map_on_basis # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: def map_on_basis(lam): # redefining map_on_basis ....: def mus(k): ....: return lam.remove_horizontal_border_strip(k) ....: return A.sum_of_monomials([Partition(mu).conjugate() ....: for k in range(sum(lam) + 1) ....: for mu in mus(k)]) - sage: f = h.module_morphism(on_basis=map_on_basis, # optional - sage.combinat + sage: f = h.module_morphism(on_basis=map_on_basis, ....: codomain=A) # redefining f - sage: f(h[1]) # optional - sage.combinat + sage: f(h[1]) P[] + P[1] - sage: f(h[2]) # optional - sage.combinat + sage: f(h[2]) P[] + P[1] + P[1, 1] - sage: f(h[1, 1]) # optional - sage.combinat + sage: f(h[1, 1]) P[1] + P[2] - sage: f(h[2, 2]) # optional - sage.combinat + sage: f(h[2, 2]) P[1, 1] + P[2, 1] + P[2, 2] - sage: f(h[3, 2, 1]) # optional - sage.combinat + sage: f(h[3, 2, 1]) P[2, 1] + P[2, 1, 1] + P[2, 2] + P[2, 2, 1] + P[3, 1] + P[3, 1, 1] + P[3, 2] + P[3, 2, 1] - sage: f(h.one()) # optional - sage.combinat + sage: f(h.one()) P[] - sage: grf = h.induced_graded_map(A, f); grf # optional - sage.combinat + sage: grf = h.induced_graded_map(A, f); grf Generic morphism: From: Symmetric Functions over Rational Field in the homogeneous basis To: Graded Module of An example of a filtered module with basis: the free module on partitions over Rational Field - sage: grf(h[1]) # optional - sage.combinat + sage: grf(h[1]) Bbar[[1]] - sage: grf(h[2]) # optional - sage.combinat + sage: grf(h[2]) Bbar[[1, 1]] - sage: grf(h[1, 1]) # optional - sage.combinat + sage: grf(h[1, 1]) Bbar[[2]] - sage: grf(h[2, 2]) # optional - sage.combinat + sage: grf(h[2, 2]) Bbar[[2, 2]] - sage: grf(h[3, 2, 1]) # optional - sage.combinat + sage: grf(h[3, 2, 1]) Bbar[[3, 2, 1]] - sage: grf(h.one()) # optional - sage.combinat + sage: grf(h.one()) Bbar[[]] **Example 4.** @@ -593,36 +602,37 @@ def induced_graded_map(self, other, f): The construct `\operatorname{gr} f` also makes sense when `f` is a filtration-preserving map between graded modules. :: - sage: def map_on_basis(lam): # redefining map_on_basis # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: def map_on_basis(lam): # redefining map_on_basis ....: def mus(k): ....: return lam.remove_horizontal_border_strip(k) ....: return h.sum_of_monomials([Partition(mu).conjugate() ....: for k in range(sum(lam) + 1) ....: for mu in mus(k)]) - sage: f = h.module_morphism(on_basis=map_on_basis, # optional - sage.combinat + sage: f = h.module_morphism(on_basis=map_on_basis, ....: codomain=h) # redefining f - sage: f(h[1]) # optional - sage.combinat + sage: f(h[1]) h[] + h[1] - sage: f(h[2]) # optional - sage.combinat + sage: f(h[2]) h[] + h[1] + h[1, 1] - sage: f(h[1, 1]) # optional - sage.combinat + sage: f(h[1, 1]) h[1] + h[2] - sage: f(h[2, 1]) # optional - sage.combinat + sage: f(h[2, 1]) h[1] + h[1, 1] + h[2] + h[2, 1] - sage: f(h.one()) # optional - sage.combinat + sage: f(h.one()) h[] - sage: grf = h.induced_graded_map(h, f); grf # optional - sage.combinat + sage: grf = h.induced_graded_map(h, f); grf Generic endomorphism of Symmetric Functions over Rational Field in the homogeneous basis - sage: grf(h[1]) # optional - sage.combinat + sage: grf(h[1]) h[1] - sage: grf(h[2]) # optional - sage.combinat + sage: grf(h[2]) h[1, 1] - sage: grf(h[1, 1]) # optional - sage.combinat + sage: grf(h[1, 1]) h[2] - sage: grf(h[2, 1]) # optional - sage.combinat + sage: grf(h[2, 1]) h[2, 1] - sage: grf(h.one()) # optional - sage.combinat + sage: grf(h.one()) h[] """ grA = self.graded_algebra() @@ -659,26 +669,28 @@ def is_homogeneous(self): EXAMPLES:: - sage: A = ModulesWithBasis(ZZ).Filtered().example() # optional - sage.combinat - sage: x = A(Partition((3,2,1))) # optional - sage.combinat - sage: y = A(Partition((4,4,1))) # optional - sage.combinat - sage: z = A(Partition((2,2,2))) # optional - sage.combinat - sage: (3*x).is_homogeneous() # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: A = ModulesWithBasis(ZZ).Filtered().example() + sage: x = A(Partition((3,2,1))) + sage: y = A(Partition((4,4,1))) + sage: z = A(Partition((2,2,2))) + sage: (3*x).is_homogeneous() True - sage: (x - y).is_homogeneous() # optional - sage.combinat + sage: (x - y).is_homogeneous() False - sage: (x+2*z).is_homogeneous() # optional - sage.combinat + sage: (x+2*z).is_homogeneous() True Here is an example with a graded algebra:: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat - sage: (x, y) = (S[2], S[3]) # optional - sage.combinat - sage: (3*x).is_homogeneous() # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: S = NonCommutativeSymmetricFunctions(QQ).S() + sage: (x, y) = (S[2], S[3]) + sage: (3*x).is_homogeneous() True - sage: (x^3 - y^2).is_homogeneous() # optional - sage.combinat + sage: (x^3 - y^2).is_homogeneous() True - sage: ((x + y)^2).is_homogeneous() # optional - sage.combinat + sage: ((x + y)^2).is_homogeneous() False Let us now test a filtered algebra (but remember that the @@ -717,10 +729,10 @@ def degree_on_basis(self, m): EXAMPLES:: - sage: A = GradedModulesWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: A.degree_on_basis(Partition((2,1))) # optional - sage.combinat sage.modules + sage: A = GradedModulesWithBasis(QQ).example() # needs sage.combinat sage.modules + sage: A.degree_on_basis(Partition((2,1))) # needs sage.combinat sage.modules 3 - sage: A.degree_on_basis(Partition((4,2,1,1,1,1))) # optional - sage.combinat sage.modules + sage: A.degree_on_basis(Partition((4,2,1,1,1,1))) # needs sage.combinat sage.modules 10 """ @@ -738,28 +750,30 @@ def homogeneous_degree(self): EXAMPLES:: - sage: A = ModulesWithBasis(ZZ).Filtered().example() # optional - sage.combinat sage.modules - sage: x = A(Partition((3,2,1))) # optional - sage.combinat sage.modules - sage: y = A(Partition((4,4,1))) # optional - sage.combinat sage.modules - sage: z = A(Partition((2,2,2))) # optional - sage.combinat sage.modules - sage: x.degree() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = ModulesWithBasis(ZZ).Filtered().example() + sage: x = A(Partition((3,2,1))) + sage: y = A(Partition((4,4,1))) + sage: z = A(Partition((2,2,2))) + sage: x.degree() 6 - sage: (x + 2*z).degree() # optional - sage.combinat sage.modules + sage: (x + 2*z).degree() 6 - sage: (y - x).degree() # optional - sage.combinat sage.modules + sage: (y - x).degree() Traceback (most recent call last): ... ValueError: element is not homogeneous An example in a graded algebra:: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat sage.modules - sage: (x, y) = (S[2], S[3]) # optional - sage.combinat sage.modules - sage: x.homogeneous_degree() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: S = NonCommutativeSymmetricFunctions(QQ).S() + sage: (x, y) = (S[2], S[3]) + sage: x.homogeneous_degree() 2 - sage: (x^3 + 4*y^2).homogeneous_degree() # optional - sage.combinat sage.modules + sage: (x^3 + 4*y^2).homogeneous_degree() 6 - sage: ((1 + x)^3).homogeneous_degree() # optional - sage.combinat sage.modules + sage: ((1 + x)^3).homogeneous_degree() Traceback (most recent call last): ... ValueError: element is not homogeneous @@ -781,8 +795,8 @@ def homogeneous_degree(self): TESTS:: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat sage.modules - sage: S.zero().degree() # optional - sage.combinat sage.modules + sage: S = NonCommutativeSymmetricFunctions(QQ).S() # needs sage.combinat sage.modules + sage: S.zero().degree() # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: the zero element does not have a well-defined degree @@ -809,32 +823,35 @@ def maximal_degree(self): EXAMPLES:: - sage: A = ModulesWithBasis(ZZ).Filtered().example() # optional - sage.combinat - sage: x = A(Partition((3,2,1))) # optional - sage.combinat - sage: y = A(Partition((4,4,1))) # optional - sage.combinat - sage: z = A(Partition((2,2,2))) # optional - sage.combinat - sage: x.maximal_degree() # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: A = ModulesWithBasis(ZZ).Filtered().example() + sage: x = A(Partition((3,2,1))) + sage: y = A(Partition((4,4,1))) + sage: z = A(Partition((2,2,2))) + sage: x.maximal_degree() 6 - sage: (x + 2*z).maximal_degree() # optional - sage.combinat + sage: (x + 2*z).maximal_degree() 6 - sage: (y - x).maximal_degree() # optional - sage.combinat + sage: (y - x).maximal_degree() 9 - sage: (3*z).maximal_degree() # optional - sage.combinat + sage: (3*z).maximal_degree() 6 Now, we test this on a graded algebra:: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat - sage: (x, y) = (S[2], S[3]) # optional - sage.combinat - sage: x.maximal_degree() # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: S = NonCommutativeSymmetricFunctions(QQ).S() + sage: (x, y) = (S[2], S[3]) + sage: x.maximal_degree() 2 - sage: (x^3 + 4*y^2).maximal_degree() # optional - sage.combinat + sage: (x^3 + 4*y^2).maximal_degree() 6 - sage: ((1 + x)^3).maximal_degree() # optional - sage.combinat + sage: ((1 + x)^3).maximal_degree() 6 Let us now test a filtered algebra:: + sage: # needs sage.combinat sage.modules sage: A = AlgebrasWithBasis(QQ).Filtered().example() sage: x,y,z = A.algebra_generators() sage: (x*y).maximal_degree() @@ -852,8 +869,8 @@ def maximal_degree(self): TESTS:: - sage: S = NonCommutativeSymmetricFunctions(QQ).S() # optional - sage.combinat - sage: S.zero().degree() # optional - sage.combinat + sage: S = NonCommutativeSymmetricFunctions(QQ).S() # needs sage.combinat sage.modules + sage: S.zero().degree() # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: the zero element does not have a well-defined degree @@ -877,6 +894,7 @@ def homogeneous_component(self, n): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: A = ModulesWithBasis(ZZ).Filtered().example() sage: x = A.an_element(); x 2*P[] + 2*P[1] + 3*P[2] @@ -891,6 +909,7 @@ def homogeneous_component(self, n): sage: x.homogeneous_component(3) 0 + sage: # needs sage.combinat sage.modules sage: A = ModulesWithBasis(ZZ).Graded().example() sage: x = A.an_element(); x 2*P[] + 2*P[1] + 3*P[2] @@ -927,6 +946,7 @@ def homogeneous_component(self, n): Check that this really returns ``A.zero()`` and not a plain ``0``:: + sage: # needs sage.combinat sage.modules sage: A = ModulesWithBasis(ZZ).Filtered().example() sage: x = A.an_element() sage: x.homogeneous_component(3).parent() is A @@ -947,6 +967,7 @@ def truncate(self, n): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: A = ModulesWithBasis(ZZ).Filtered().example() sage: x = A.an_element(); x 2*P[] + 2*P[1] + 3*P[2] @@ -959,6 +980,7 @@ def truncate(self, n): sage: x.truncate(3) 2*P[] + 2*P[1] + 3*P[2] + sage: # needs sage.combinat sage.modules sage: A = ModulesWithBasis(ZZ).Graded().example() sage: x = A.an_element(); x 2*P[] + 2*P[1] + 3*P[2] @@ -996,6 +1018,7 @@ def truncate(self, n): Check that this really return ``A.zero()`` and not a plain ``0``:: + sage: # needs sage.combinat sage.modules sage: A = ModulesWithBasis(ZZ).Filtered().example() sage: x = A.an_element() sage: x.truncate(0).parent() is A @@ -1014,16 +1037,17 @@ def degree_on_basis(self, m): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: S = E.submodule([x + y, x*y - y*z, y]) # optional - sage.combinat sage.modules - sage: B = S.basis() # optional - sage.combinat sage.modules - sage: [B[0].lift(), B[1].lift(), B[2].lift()] # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: S = E.submodule([x + y, x*y - y*z, y]) + sage: B = S.basis() + sage: [B[0].lift(), B[1].lift(), B[2].lift()] [x, y, x*y - y*z] - sage: S.degree_on_basis(0) # optional - sage.combinat sage.modules + sage: S.degree_on_basis(0) 1 - sage: S.degree_on_basis(1) # optional - sage.combinat sage.modules + sage: S.degree_on_basis(1) 1 - sage: S.degree_on_basis(2) # optional - sage.combinat sage.modules + sage: S.degree_on_basis(2) 2 """ return self.basis()[m].lift().degree() @@ -1035,29 +1059,30 @@ def degree(self): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: S = E.submodule([x + y, x*y - y*z, y]) # optional - sage.combinat sage.modules - sage: B = S.basis() # optional - sage.combinat sage.modules - sage: [B[0].lift(), B[1].lift(), B[2].lift()] # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: S = E.submodule([x + y, x*y - y*z, y]) + sage: B = S.basis() + sage: [B[0].lift(), B[1].lift(), B[2].lift()] [x, y, x*y - y*z] - sage: B[0].degree() # optional - sage.combinat sage.modules + sage: B[0].degree() 1 - sage: B[1].degree() # optional - sage.combinat sage.modules + sage: B[1].degree() 1 - sage: (B[0] + 3*B[1]).degree() # optional - sage.combinat sage.modules + sage: (B[0] + 3*B[1]).degree() 1 The degree of inhomogeneous elements is not defined (following the behavior of the exterior algebra):: - sage: (B[0] + B[2]).degree() # optional - sage.combinat sage.modules + sage: (B[0] + B[2]).degree() # needs sage.modules Traceback (most recent call last): ... ValueError: element is not homogeneous We can still get the maximal degree:: - sage: (B[0] + B[2]).maximal_degree() # optional - sage.combinat sage.modules + sage: (B[0] + B[2]).maximal_degree() # needs sage.modules 2 """ return self.lift().degree() @@ -1075,14 +1100,15 @@ def maximal_degree(self): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: F = E.submodule([x + 1, x*y - 1]) # optional - sage.combinat sage.modules - sage: B = F.basis() # optional - sage.combinat sage.modules - sage: [B[0].lift(), B[1].lift()] # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: F = E.submodule([x + 1, x*y - 1]) + sage: B = F.basis() + sage: [B[0].lift(), B[1].lift()] [-x*y + 1, x*y + x] - sage: B[0].maximal_degree() # optional - sage.combinat sage.modules + sage: B[0].maximal_degree() 2 - sage: B[1].maximal_degree() # optional - sage.combinat sage.modules + sage: B[1].maximal_degree() 2 """ return self.lift().maximal_degree() diff --git a/src/sage/categories/finite_complex_reflection_groups.py b/src/sage/categories/finite_complex_reflection_groups.py index 69762bb353a..3ee374b739c 100644 --- a/src/sage/categories/finite_complex_reflection_groups.py +++ b/src/sage/categories/finite_complex_reflection_groups.py @@ -111,7 +111,7 @@ def WellGenerated(self): sage: CoxeterGroups().Finite().is_subcategory(C) True - sage: SymmetricGroup(3) in C # optional - sage.groups + sage: SymmetricGroup(3) in C # needs sage.groups True .. NOTE:: @@ -126,7 +126,7 @@ def WellGenerated(self): sage: TestSuite(W).run() # optional - gap3 sage: C = ComplexReflectionGroups().Finite().WellGenerated() - sage: TestSuite(C).run() # optional - gap3 + sage: TestSuite(C).run() sage: CoxeterGroups().Finite().WellGenerated.__module__ 'sage.categories.finite_complex_reflection_groups' @@ -149,12 +149,12 @@ def degrees(self): EXAMPLES:: - sage: W = ColoredPermutations(1,4) # optional - sage.combinat sage.groups - sage: W.degrees() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,4) # needs sage.combinat + sage: W.degrees() # needs sage.combinat (2, 3, 4) - sage: W = ColoredPermutations(3,3) # optional - sage.combinat sage.groups - sage: W.degrees() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(3,3) # needs sage.combinat + sage: W.degrees() # needs sage.combinat (3, 6, 9) sage: W = ReflectionGroup(31) # optional - gap3 @@ -171,12 +171,12 @@ def codegrees(self): EXAMPLES:: - sage: W = ColoredPermutations(1,4) # optional - sage.combinat sage.groups - sage: W.codegrees() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,4) # needs sage.combinat + sage: W.codegrees() # needs sage.combinat (2, 1, 0) - sage: W = ColoredPermutations(3,3) # optional - sage.combinat sage.groups - sage: W.codegrees() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(3,3) # needs sage.combinat + sage: W.codegrees() # needs sage.combinat (6, 3, 0) sage: W = ReflectionGroup(31) # optional - gap3 @@ -199,27 +199,27 @@ def _test_degrees(self, **options): Reducible real reflection group of rank 4 and type A2 x B2 sage: W._test_degrees() # optional - gap3 - sage: W = SymmetricGroup(5) # optional - sage.groups - sage: W._test_degrees() # optional - sage.groups + sage: W = SymmetricGroup(5) # needs sage.groups + sage: W._test_degrees() # needs sage.groups We now break the implementation of W.degrees and check that this is caught:: - sage: W.degrees = lambda: (1/1,5) # optional - sage.groups - sage: W._test_degrees() # optional - sage.groups + sage: W.degrees = lambda: (1/1,5) # needs sage.groups + sage: W._test_degrees() # needs sage.groups Traceback (most recent call last): ... AssertionError: the degrees should be integers - sage: W.degrees = lambda: (1,2,3) # optional - sage.groups - sage: W._test_degrees() # optional - sage.groups + sage: W.degrees = lambda: (1,2,3) # needs sage.groups + sage: W._test_degrees() # needs sage.groups Traceback (most recent call last): ... AssertionError: the degrees should be larger than 2 We restore W to its normal state:: - sage: del W.degrees # optional - sage.groups - sage: W._test_degrees() # optional - sage.groups + sage: del W.degrees # needs sage.groups + sage: W._test_degrees() # needs sage.groups See the documentation for :class:`TestSuite` for more information. """ @@ -254,27 +254,27 @@ def _test_codegrees(self, **options): Reducible real reflection group of rank 4 and type A2 x B2 sage: W._test_codegrees() # optional - gap3 - sage: W = SymmetricGroup(5) # optional - sage.groups - sage: W._test_codegrees() # optional - sage.groups + sage: W = SymmetricGroup(5) # needs sage.groups + sage: W._test_codegrees() # needs sage.groups We now break the implementation of W.degrees and check that this is caught:: - sage: W.codegrees = lambda: (1/1,5) # optional - sage.groups - sage: W._test_codegrees() # optional - sage.groups + sage: W.codegrees = lambda: (1/1,5) # needs sage.groups + sage: W._test_codegrees() # needs sage.groups Traceback (most recent call last): ... AssertionError: the codegrees should be integers - sage: W.codegrees = lambda: (2,1,-1) # optional - sage.groups - sage: W._test_codegrees() # optional - sage.groups + sage: W.codegrees = lambda: (2,1,-1) # needs sage.groups + sage: W._test_codegrees() # needs sage.groups Traceback (most recent call last): ... AssertionError: the codegrees should be nonnegative We restore W to its normal state:: - sage: del W.codegrees # optional - sage.groups - sage: W._test_codegrees() # optional - sage.groups + sage: del W.codegrees # needs sage.groups + sage: W._test_codegrees() # needs sage.groups See the documentation for :class:`TestSuite` for more information. """ @@ -311,14 +311,15 @@ def number_of_reflection_hyperplanes(self): EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflection_hyperplanes() # optional - sage.combinat sage.groups + sage: # needs sage.combinat + sage: W = ColoredPermutations(1,3) + sage: W.number_of_reflection_hyperplanes() 3 - sage: W = ColoredPermutations(2,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflection_hyperplanes() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,3) + sage: W.number_of_reflection_hyperplanes() 9 - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflection_hyperplanes() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) + sage: W.number_of_reflection_hyperplanes() 15 sage: W = ReflectionGroup((4,2,3)) # optional - gap3 sage: W.number_of_reflection_hyperplanes() # optional - gap3 @@ -342,21 +343,22 @@ def number_of_reflections(self): EXAMPLES:: - sage: [SymmetricGroup(i).number_of_reflections() # optional - sage.groups + sage: [SymmetricGroup(i).number_of_reflections() # needs sage.groups ....: for i in range(int(8))] [0, 0, 1, 3, 6, 10, 15, 21] - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflections() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) + sage: W.number_of_reflections() 3 - sage: W = ColoredPermutations(2,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflections() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,3) + sage: W.number_of_reflections() 9 - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflections() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) + sage: W.number_of_reflections() 21 - sage: W = ReflectionGroup((4,2,3)) # optional - gap3 # optional - sage.combinat sage.groups - sage: W.number_of_reflections() # optional - gap3 # optional - sage.combinat sage.groups + sage: W = ReflectionGroup((4,2,3)) # optional - gap3 + sage: W.number_of_reflections() # optional - gap3 15 """ from sage.rings.integer_ring import ZZ @@ -377,17 +379,20 @@ def rank(self): EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.rank() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) + sage: W.rank() 2 - sage: W = ColoredPermutations(2,3) # optional - sage.combinat sage.groups - sage: W.rank() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,3) + sage: W.rank() 3 - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.rank() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) + sage: W.rank() 3 - sage: W = ReflectionGroup((4,2,3)) # optional - gap3 # optional - sage.combinat sage.groups - sage: W.rank() # optional - gap3 # optional - sage.combinat sage.groups + + sage: # optional - gap3, needs sage.combinat sage.groups + sage: W = ReflectionGroup((4,2,3)) + sage: W.rank() 3 """ return len(self.degrees()) @@ -401,17 +406,20 @@ def cardinality(self): EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.cardinality() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) + sage: W.cardinality() 6 - sage: W = ColoredPermutations(2,3) # optional - sage.combinat sage.groups - sage: W.cardinality() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,3) + sage: W.cardinality() 48 - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.cardinality() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) + sage: W.cardinality() 384 - sage: W = ReflectionGroup((4,2,3)) # optional - gap3 # optional - sage.combinat sage.groups - sage: W.cardinality() # optional - gap3 # optional - sage.combinat sage.groups + + sage: # optional - gap3, needs sage.combinat sage.groups + sage: W = ReflectionGroup((4,2,3)) + sage: W.cardinality() 192 """ from sage.rings.integer_ring import ZZ @@ -439,20 +447,20 @@ def is_well_generated(self) -> bool: EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.is_well_generated() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) # needs sage.combinat + sage: W.is_well_generated() # needs sage.combinat True - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.is_well_generated() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) # needs sage.combinat + sage: W.is_well_generated() # needs sage.combinat True - sage: W = ReflectionGroup((4,2,3)) # optional - gap3 # optional - sage.combinat sage.groups - sage: W.is_well_generated() # optional - gap3 # optional - sage.combinat sage.groups + sage: # optional - gap3, needs sage.combinat sage.groups + sage: W = ReflectionGroup((4,2,3)) + sage: W.is_well_generated() False - - sage: W = ReflectionGroup((4,4,3)) # optional - gap3 # optional - sage.combinat sage.groups - sage: W.is_well_generated() # optional - gap3 # optional - sage.combinat sage.groups + sage: W = ReflectionGroup((4,4,3)) + sage: W.is_well_generated() True """ return self.number_of_simple_reflections() == self.rank() @@ -474,12 +482,12 @@ def is_real(self): EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.is_real() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) # needs sage.combinat + sage: W.is_real() # needs sage.combinat True - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.is_real() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) # needs sage.combinat + sage: W.is_real() # needs sage.combinat sage.groups False .. TODO:: @@ -527,6 +535,107 @@ def base_change_matrix(self): from sage.matrix.constructor import Matrix return Matrix(list(self.independent_roots())).inverse() + def milnor_fiber_poset(self): + r""" + Return the Milnor fiber poset of ``self``. + + The *Milnor fiber poset* of a finite complex reflection group `W` + is defined as the poset of (right) standard cosets `gW_J`, + where `J` is a subset of the index set `I` of `W`, ordered + by reverse inclusion. This is conjecturally a meet semilattice + if and only if `W` is well-generated. + + EXAMPLES:: + + sage: W = ColoredPermutations(3, 2) + sage: P = W.milnor_fiber_poset() + sage: P + Finite meet-semilattice containing 34 elements + sage: R. = ZZ[] + sage: sum(x**P.rank(elt) for elt in P) + 18*x^2 + 15*x + 1 + + sage: W = ReflectionGroup(4) # optional - gap3 + sage: P = W.milnor_fiber_poset() # optional - gap3 + sage: P # optional - gap3 + Finite meet-semilattice containing 41 elements + sage: sum(x**P.rank(elt) for elt in P) # optional - gap3 + 24*x^2 + 16*x + 1 + + sage: W = ReflectionGroup([4,2,2]) # optional - gap3 + sage: W.is_well_generated() # optional - gap3 + False + sage: P = W.milnor_fiber_poset() # optional - gap3 + sage: P # optional - gap3 + Finite poset containing 47 elements + sage: sum(x**P.rank(elt) for elt in P) # optional - gap3 + 16*x^3 + 24*x^2 + 6*x + 1 + sage: P.is_meet_semilattice() # optional - gap3 + False + """ + I = self.index_set() + data = {} + next_reprs = {(): [g for g in self]} + next_cosets = {(): [frozenset([g]) for g in next_reprs[()]]} + next_level = set((i, ()) for i in range(len(next_cosets[()]))) + while next_level: + cur = next_level + cosets = next_cosets + reprs = next_reprs + next_level = set() + next_cosets = {} + next_reprs = {} + for Y in cur: + index, J = Y + for i in I: + if i in J: + continue + Jp = tuple(sorted(J + (i,))) + # See if the coset is already there + found_coset = False + if Jp in next_cosets: + rep = reprs[J][index] + for ii, C in enumerate(next_cosets[Jp]): + if rep in C: + found_coset = True + Yp = (reprs[J][index], J) + Xp = (next_reprs[Jp][ii], Jp) + if Xp in data: + data[Xp].append(Yp) + else: + data[Xp] = [Yp] + else: + next_cosets[Jp] = [] + next_reprs[Jp] = [] + if found_coset: + continue + + # Otherwise build the coset + next_level.add((len(next_cosets[Jp]), Jp)) + H = set(cosets[J][index]) + to_test = [(g, i) for g in H] + while to_test: + g, j = to_test.pop() + gp = g.apply_simple_reflection(j, side='right') + if gp in H: + continue + H.add(gp) + to_test.extend((gp, j) for j in Jp) + rep = min(H, key=lambda g: g.length()) + next_cosets[Jp].append(frozenset(H)) + next_reprs[Jp].append(rep) + Yp = (reprs[J][index], J) + Xp = (rep, Jp) + if Xp in data: + data[Xp].append(Yp) + else: + data[Xp] = [Yp] + if self.is_well_generated(): + from sage.combinat.posets.lattices import MeetSemilattice + return MeetSemilattice(data) + from sage.combinat.posets.posets import Poset + return Poset(data) + class ElementMethods: @abstract_method(optional=True) @@ -544,8 +653,8 @@ def to_matrix(self): [0 1], [ 0 -1], [ 1 1], [ 1 0], [-1 -1], [-1 0] ] - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: [t.to_matrix() for t in W] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) # needs sage.combinat + sage: [t.to_matrix() for t in W] # needs sage.combinat sage.groups [ [1 0 0] [1 0 0] [0 1 0] [0 0 1] [0 1 0] [0 0 1] [0 1 0] [0 0 1] [1 0 0] [1 0 0] [0 0 1] [0 1 0] @@ -555,8 +664,8 @@ def to_matrix(self): A different representation is given by the colored permutations:: - sage: W = ColoredPermutations(3, 1) # optional - sage.combinat sage.groups - sage: [t.to_matrix() for t in W] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(3, 1) # needs sage.combinat + sage: [t.to_matrix() for t in W] # needs sage.combinat sage.groups [[1], [zeta3], [-zeta3 - 1]] """ @@ -582,9 +691,9 @@ def character_value(self): EXAMPLES:: - sage: W = ColoredPermutations(1,3); W # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3); W # needs sage.combinat 1-colored permutations of size 3 - sage: [t.character_value() for t in W] # optional - sage.combinat sage.groups + sage: [t.character_value() for t in W] # needs sage.combinat sage.groups [3, 1, 1, 0, 0, 1] Note that this could be a different (faithful) @@ -596,14 +705,14 @@ def character_value(self): sage: [t.character_value() for t in W] # optional - gap3 [2, 0, 0, -1, -1, 0] - sage: W = ColoredPermutations(2,2); W # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,2); W # needs sage.combinat 2-colored permutations of size 2 - sage: [t.character_value() for t in W] # optional - sage.combinat sage.groups + sage: [t.character_value() for t in W] # needs sage.combinat sage.groups [2, 0, 0, -2, 0, 0, 0, 0] - sage: W = ColoredPermutations(3,1); W # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(3,1); W # needs sage.combinat 3-colored permutations of size 1 - sage: [t.character_value() for t in W] # optional - sage.combinat sage.groups + sage: [t.character_value() for t in W] # needs sage.combinat sage.groups [1, zeta3, -zeta3 - 1] """ return self.to_matrix().trace() @@ -750,12 +859,12 @@ def absolute_order_ideal(self, gens=None, ....: for w in W.absolute_order_ideal(W.from_reduced_word([2]))) [[], [2]] - sage: W = CoxeterGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: len(list(W.absolute_order_ideal())) # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 3]) # needs sage.combinat sage.groups + sage: len(list(W.absolute_order_ideal())) # needs sage.combinat sage.groups 14 - sage: W = CoxeterGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: for (w, l) in W.absolute_order_ideal(return_lengths=True): # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 2]) # needs sage.combinat sage.groups + sage: for (w, l) in W.absolute_order_ideal(return_lengths=True): # needs sage.combinat sage.groups ....: print(w.reduced_word(), l) [1, 2] 2 [1, 2, 1] 1 @@ -822,12 +931,12 @@ def noncrossing_partition_lattice(self, c=None, L=None, EXAMPLES:: - sage: W = SymmetricGroup(4) # optional - sage.combinat sage.groups - sage: W.noncrossing_partition_lattice() # optional - sage.combinat sage.groups + sage: W = SymmetricGroup(4) # needs sage.combinat sage.groups + sage: W.noncrossing_partition_lattice() # needs sage.combinat sage.groups Finite lattice containing 14 elements - sage: W = WeylGroup(['G', 2]) # optional - sage.combinat sage.groups - sage: W.noncrossing_partition_lattice() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['G', 2]) # needs sage.combinat sage.groups + sage: W.noncrossing_partition_lattice() # needs sage.combinat sage.groups Finite lattice containing 8 elements sage: W = ReflectionGroup((1,1,3)) # optional - gap3 @@ -982,14 +1091,15 @@ def absolute_poset(self, in_unitary_group=False): TESTS:: - sage: W1 = CoxeterGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: W2 = WeylGroup(['A', 2]) # optional - sage.combinat sage.groups - sage: W3 = SymmetricGroup(3) # optional - sage.combinat sage.groups - sage: W1.absolute_poset() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W1 = CoxeterGroup(['A', 2]) + sage: W2 = WeylGroup(['A', 2]) + sage: W3 = SymmetricGroup(3) + sage: W1.absolute_poset() Finite poset containing 6 elements - sage: W2.absolute_poset() # optional - sage.combinat sage.groups + sage: W2.absolute_poset() Finite poset containing 6 elements - sage: W3.absolute_poset() # optional - sage.combinat sage.groups + sage: W3.absolute_poset() Finite poset containing 6 elements """ return self.noncrossing_partition_lattice(L=tuple(self), in_unitary_group=in_unitary_group) @@ -1070,6 +1180,59 @@ def coxeter_elements(self): """ return self.coxeter_element().conjugacy_class() + def milnor_fiber_complex(self): + r""" + Return the Milnor fiber complex of ``self``. + + The *Milnor fiber complex* of a finite well-generated + complex reflection group `W` is the simplicial complex whose + face poset is given by :meth:`milnor_fiber_poset`. When `W` + is an irreducible Shephard group, it is also an equivariant + strong deformation retract of the Milnor fiber `f_1^{-1}(1)`, + where `f_1: V \to \CC` is the polynomial invariant of smallest + degree acting on the reflection representation `V`. + + When `W` is a Coxeter group, this is isomorphic to the + :wikipedia:`Coxeter complex ` of `W`. + + EXAMPLES:: + + sage: W = ColoredPermutations(3, 2) + sage: C = W.milnor_fiber_complex() + sage: C.homology() + {0: 0, 1: Z x Z x Z x Z} + + sage: W = ReflectionGroup(5) # optional - gap3 + sage: C = W.milnor_fiber_complex() # optional - gap3 + sage: C.homology() # optional - gap3 + {0: 0, 1: Z^25} + """ + I = self.index_set() + cosets = {} + for i in I: + Ip = tuple([j for j in I if j != i]) + cosets[Ip] = [] + for g in self: + if any(g in C for C in cosets[Ip]): + continue + H = set([g]) + to_test = [(g, j) for j in Ip] + while to_test: + h, j = to_test.pop() + hp = h.apply_simple_reflection(j, side='right') + if hp in H: + continue + H.add(hp) + to_test.extend((hp, j) for j in Ip) + cosets[Ip].append(frozenset(H)) + verts = {} + for Ip in cosets: + for C in cosets[Ip]: + verts[C, Ip] = len(verts) + facets = [[verts[k] for k in verts if g in k[0]] for g in self] + from sage.topology.simplicial_complex import SimplicialComplex + return SimplicialComplex(facets) + class Irreducible(CategoryWithAxiom): r""" The category of finite irreducible well-generated @@ -1084,7 +1247,7 @@ def example(self): sage: from sage.categories.complex_reflection_groups import ComplexReflectionGroups sage: C = ComplexReflectionGroups().Finite().WellGenerated().Irreducible() - sage: C.example() # optional - sage.combinat sage.groups + sage: C.example() # needs sage.combinat 4-colored permutations of size 3 """ from sage.combinat.colored_permutations import ColoredPermutations @@ -1109,12 +1272,12 @@ def coxeter_number(self): EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: W.coxeter_number() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) # needs sage.combinat + sage: W.coxeter_number() # needs sage.combinat 3 - sage: W = ColoredPermutations(4,3) # optional - sage.combinat sage.groups - sage: W.coxeter_number() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(4,3) # needs sage.combinat + sage: W.coxeter_number() # needs sage.combinat 12 sage: W = ReflectionGroup((4,4,3)) # optional - gap3 @@ -1130,20 +1293,20 @@ def number_of_reflections_of_full_support(self): EXAMPLES:: - sage: W = Permutations(4) # optional - sage.combinat sage.groups - sage: W.number_of_reflections_of_full_support() # optional - sage.combinat sage.groups + sage: W = Permutations(4) + sage: W.number_of_reflections_of_full_support() 1 - sage: W = ColoredPermutations(1,4) # optional - sage.combinat sage.groups - sage: W.number_of_reflections_of_full_support() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,4) # needs sage.combinat + sage: W.number_of_reflections_of_full_support() 1 - sage: W = CoxeterGroup("B3") # optional - sage.combinat sage.groups - sage: W.number_of_reflections_of_full_support() # optional - sage.combinat sage.groups + sage: W = CoxeterGroup("B3") # needs sage.combinat sage.groups + sage: W.number_of_reflections_of_full_support() # needs sage.combinat sage.groups 3 - sage: W = ColoredPermutations(3,3) # optional - sage.combinat sage.groups - sage: W.number_of_reflections_of_full_support() # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(3,3) # needs sage.combinat + sage: W.number_of_reflections_of_full_support() # needs sage.combinat 3 """ n = self.rank() @@ -1175,18 +1338,18 @@ def rational_catalan_number(self, p, polynomial=False): EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: [W.rational_catalan_number(p) for p in [5,7,8]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) # needs sage.combinat + sage: [W.rational_catalan_number(p) for p in [5,7,8]] # needs sage.combinat [7, 12, 15] - sage: W = ColoredPermutations(2,2) # optional - sage.combinat sage.groups - sage: [W.rational_catalan_number(p) for p in [7,9,11]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,2) # needs sage.combinat + sage: [W.rational_catalan_number(p) for p in [7,9,11]] # needs sage.combinat [10, 15, 21] TESTS:: - sage: W = ColoredPermutations(1,4) # optional - sage.combinat sage.groups - sage: W.rational_catalan_number(3, polynomial=True) # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,4) # needs sage.combinat + sage: W.rational_catalan_number(3, polynomial=True) # needs sage.combinat q^6 + q^4 + q^3 + q^2 + 1 """ from sage.arith.misc import GCD as gcd @@ -1243,37 +1406,38 @@ def fuss_catalan_number(self, m, positive=False, EXAMPLES:: - sage: W = ColoredPermutations(1,3) # optional - sage.combinat sage.groups - sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,3) # needs sage.combinat + sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # needs sage.combinat [5, 12, 22] - sage: W = ColoredPermutations(1,4) # optional - sage.combinat sage.groups - sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,4) # needs sage.combinat + sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # needs sage.combinat [14, 55, 140] - sage: W = ColoredPermutations(1,5) # optional - sage.combinat sage.groups - sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(1,5) # needs sage.combinat + sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # needs sage.combinat [42, 273, 969] - sage: W = ColoredPermutations(2,2) # optional - sage.combinat sage.groups - sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,2) # needs sage.combinat + sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # needs sage.combinat [6, 15, 28] - sage: W = ColoredPermutations(2,3) # optional - sage.combinat sage.groups - sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,3) # needs sage.combinat + sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # needs sage.combinat [20, 84, 220] - sage: W = ColoredPermutations(2,4) # optional - sage.combinat sage.groups - sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,4) # needs sage.combinat + sage: [W.fuss_catalan_number(i) for i in [1,2,3]] # needs sage.combinat [70, 495, 1820] TESTS:: - sage: W = ColoredPermutations(2,4) # optional - sage.combinat sage.groups - sage: W.fuss_catalan_number(2, positive=True) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = ColoredPermutations(2,4) + sage: W.fuss_catalan_number(2, positive=True) 330 - sage: W = ColoredPermutations(2,2) # optional - sage.combinat sage.groups - sage: W.fuss_catalan_number(2, polynomial=True) # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,2) + sage: W.fuss_catalan_number(2, polynomial=True) q^16 + q^14 + 2*q^12 + 2*q^10 + 3*q^8 + 2*q^6 + 2*q^4 + q^2 + 1 """ @@ -1317,11 +1481,11 @@ def catalan_number(self, positive=False, polynomial=False): EXAMPLES:: - sage: [ColoredPermutations(1,n).catalan_number() # optional - sage.combinat sage.groups + sage: [ColoredPermutations(1,n).catalan_number() # needs sage.combinat ....: for n in [3,4,5]] [5, 14, 42] - sage: [ColoredPermutations(2,n).catalan_number() # optional - sage.combinat sage.groups + sage: [ColoredPermutations(2,n).catalan_number() # needs sage.combinat ....: for n in [3,4,5]] [20, 70, 252] @@ -1331,11 +1495,12 @@ def catalan_number(self, positive=False, polynomial=False): TESTS:: - sage: W = ColoredPermutations(3,6) # optional - sage.combinat sage.groups - sage: W.catalan_number(positive=True) # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: W = ColoredPermutations(3,6) + sage: W.catalan_number(positive=True) 462 - sage: W = ColoredPermutations(2,2) # optional - sage.combinat sage.groups - sage: W.catalan_number(polynomial=True) # optional - sage.combinat sage.groups + sage: W = ColoredPermutations(2,2) + sage: W.catalan_number(polynomial=True) q^8 + q^6 + 2*q^4 + q^2 + 1 """ return self.fuss_catalan_number(1, positive=positive, diff --git a/src/sage/categories/finite_coxeter_groups.py b/src/sage/categories/finite_coxeter_groups.py index a03a7ca5495..3459135c9c0 100644 --- a/src/sage/categories/finite_coxeter_groups.py +++ b/src/sage/categories/finite_coxeter_groups.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Finite Coxeter Groups """ @@ -357,7 +357,7 @@ def degrees_of_irreducible_component(I): c = self.prod(s[i] for i in I) roots = c.matrix().change_ring(QQbar).charpoly().roots() args = ((z.rational_argument(), m) for z, m in roots) - args = [(z if z >=0 else 1 + z, m) for z, m in args] + args = [(z if z >= 0 else 1 + z, m) for z, m in args] h = max(z.denominator() for z, m in args) return tuple(sorted(ZZ(z * h + 1) for z, m in args if z @@ -758,6 +758,151 @@ def permutahedron(self, point=None, base_ring=None): from sage.geometry.polyhedron.constructor import Polyhedron return Polyhedron(vertices=vertices, base_ring=base_ring) + def coxeter_poset(self): + r""" + Return the Coxeter poset of ``self``. + + Let `W` be a Coxeter group. The *Coxeter poset* is defined as + the set of (right) standard cosets `gW_J`, where `J` is a + subset of the index set `I` of `W`, ordered by reverse inclusion. + + This is equal to the face poset of the :meth:`Coxeter complex + `. + + EXAMPLES:: + + sage: W = CoxeterGroup(['A', 3]) + sage: P = W.coxeter_poset() + sage: P + Finite meet-semilattice containing 75 elements + sage: P.rank() + 3 + + sage: W = WeylGroup(['B', 3]) + sage: P = W.coxeter_poset() + sage: P + Finite meet-semilattice containing 147 elements + sage: P.rank() + 3 + + sage: W = CoxeterGroup(['I', 7]) + sage: P = W.coxeter_poset() + sage: P + Finite meet-semilattice containing 29 elements + sage: P.rank() + 2 + + sage: W = CoxeterGroup(['H', 3]) + sage: P = W.coxeter_poset() + sage: P + Finite meet-semilattice containing 363 elements + sage: P.rank() + 3 + + sage: W = CoxeterGroup(['H', 3], implementation="permutation") # optional - gap3 + sage: P = W.coxeter_poset() # optional - gap3 + sage: P # optional - gap3 + Finite meet-semilattice containing 363 elements + sage: P.rank() # optional - gap3 + 3 + """ + I = self.index_set() + data = {} + next_level = set((g, ()) for g in self) + while next_level: + cur = next_level + next_level = set() + for Y in cur: + g, J = Y + for i in I: + if i in J: + continue + Jp = tuple(sorted(J + (i,))) + gp = g.coset_representative(Jp, side='right') + X = (gp, Jp) + if X in data: + data[X].append(Y) + else: + data[X] = [Y] + next_level.add(X) + from sage.combinat.posets.lattices import MeetSemilattice + return MeetSemilattice(data) + + def coxeter_complex(self): + r""" + Return the Coxeter complex of ``self``. + + Let `W` be a Coxeter group, and let `X` be the corresponding Tits + cone, which is constructed as the `W` orbit of the fundamental + chamber in the reflection representation. The *Coxeter complex* + of `W` is the simplicial complex `(X \setminus \{0\}) / \RR_{>0}`. + The face poset of this simplicial complex is given by the + :meth:`coxeter_poset()`. When `W` is a finite group, then the + Coxeter complex is homeomorphic to an `(n-1)`-dimensional sphere, + where `n` is the rank of `W`. + + EXAMPLES:: + + sage: W = CoxeterGroup(['A', 3]) + sage: C = W.coxeter_complex() + sage: C + Simplicial complex with 14 vertices and 24 facets + sage: C.homology() + {0: 0, 1: 0, 2: Z} + + sage: W = WeylGroup(['B', 3]) + sage: C = W.coxeter_complex() + sage: C + Simplicial complex with 26 vertices and 48 facets + sage: C.homology() + {0: 0, 1: 0, 2: Z} + + sage: W = CoxeterGroup(['I', 7]) + sage: C = W.coxeter_complex() + sage: C + Simplicial complex with 14 vertices and 14 facets + sage: C.homology() + {0: 0, 1: Z} + + sage: W = CoxeterGroup(['H', 3]) + sage: C = W.coxeter_complex() + sage: C + Simplicial complex with 62 vertices and 120 facets + sage: C.homology() + {0: 0, 1: 0, 2: Z} + + sage: W = CoxeterGroup(['H', 3], implementation="permutation") # optional - gap3 + sage: C = W.coxeter_complex() # optional - gap3 + sage: C # optional - gap3 + Simplicial complex with 62 vertices and 120 facets + sage: C.homology() # optional - gap3 + {0: 0, 1: 0, 2: Z} + """ + I = self.index_set() + facets = {} + Ip = {i: tuple([j for j in I if j != i]) for i in I} + for g in self: + V = [] + for i in I: + gp = g + D = gp.descents(side='right') + if D and D[0] == i: + D.pop(0) + while D: + gp = gp.apply_simple_reflection(D[0]) + D = gp.descents(side='right') + if D and D[0] == i: + D.pop(0) + V.append((gp, Ip[i])) + facets[g] = V + verts = set() + for F in facets.values(): + verts.update(F) + labels = {x: i for i,x in enumerate(verts)} + result = [[labels[v] for v in F] for F in facets.values()] + from sage.topology.simplicial_complex import SimplicialComplex + return SimplicialComplex(result) + class ElementMethods: @cached_in_parent_method @@ -847,11 +992,11 @@ def coxeter_knuth_neighbor(self, w): v[i] = w[i-1] v[i-1] = w[i] d += [tuple(v)] - elif w[i-1]y and b:x->y) over Rational Field TESTS:: + sage: # needs sage.graphs sage.modules sage: TestSuite(C).run() sage: C is Algebras(QQ).FiniteDimensional().WithBasis() True @@ -80,6 +81,7 @@ def radical_basis(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -90,29 +92,29 @@ def radical_basis(self): We construct the group algebra of the Klein Four-Group over the rationals:: - sage: A = KleinFourGroup().algebra(QQ) # optional - sage.groups sage.modules + sage: A = KleinFourGroup().algebra(QQ) # needs sage.groups sage.modules This algebra belongs to the category of finite dimensional algebras over the rationals:: - sage: A in Algebras(QQ).FiniteDimensional().WithBasis() # optional - sage.groups sage.modules + sage: A in Algebras(QQ).FiniteDimensional().WithBasis() # needs sage.groups sage.modules True Since the field has characteristic `0`, Maschke's Theorem tells us that the group algebra is semisimple. So its radical is the zero ideal:: - sage: A in Algebras(QQ).Semisimple() # optional - sage.groups sage.modules + sage: A in Algebras(QQ).Semisimple() # needs sage.groups sage.modules True - sage: A.radical_basis() # optional - sage.groups sage.modules + sage: A.radical_basis() # needs sage.groups sage.modules () Let's work instead over a field of characteristic `2`:: - sage: A = KleinFourGroup().algebra(GF(2)) # optional - sage.groups sage.rings.finite_rings sage.modules - sage: A in Algebras(GF(2)).Semisimple() # optional - sage.groups sage.rings.finite_rings sage.modules + sage: A = KleinFourGroup().algebra(GF(2)) # needs sage.groups sage.modules + sage: A in Algebras(GF(2)).Semisimple() # needs sage.groups sage.modules False - sage: A.radical_basis() # optional - sage.groups sage.rings.finite_rings sage.modules + sage: A.radical_basis() # needs sage.groups sage.modules (() + (1,2)(3,4), (3,4) + (1,2)(3,4), (1,2) + (1,2)(3,4)) We now implement the algebra `A = K[x] / (x^p-1)`, where `K` @@ -120,7 +122,8 @@ def radical_basis(self): radical; alas, we currently need to wrap `A` to make it a proper :class:`ModulesWithBasis`:: - sage: class AnAlgebra(CombinatorialFreeModule): # optional - sage.modules + sage: # needs sage.modules + sage: class AnAlgebra(CombinatorialFreeModule): ....: def __init__(self, F): ....: R. = PolynomialRing(F) ....: I = R.ideal(x**F.characteristic()-F.one()) @@ -132,24 +135,24 @@ def radical_basis(self): ....: return self.basis()[self.base_ring().one()] ....: def product_on_basis(self, w1, w2): ....: return self.from_vector(vector(w1*w2)) - sage: AnAlgebra(GF(3)).radical_basis() # optional - sage.rings.finite_rings sage.modules + sage: AnAlgebra(GF(3)).radical_basis() (B[1] + 2*B[xbar^2], B[xbar] + 2*B[xbar^2]) - sage: AnAlgebra(GF(16,'a')).radical_basis() # optional - sage.rings.finite_rings sage.modules + sage: AnAlgebra(GF(16,'a')).radical_basis() # needs sage.rings.finite_rings (B[1] + B[xbar],) - sage: AnAlgebra(GF(49,'a')).radical_basis() # optional - sage.rings.finite_rings sage.modules + sage: AnAlgebra(GF(49,'a')).radical_basis() # needs sage.rings.finite_rings (B[1] + 6*B[xbar^6], B[xbar] + 6*B[xbar^6], B[xbar^2] + 6*B[xbar^6], B[xbar^3] + 6*B[xbar^6], B[xbar^4] + 6*B[xbar^6], B[xbar^5] + 6*B[xbar^6]) TESTS:: - sage: A = KleinFourGroup().algebra(GF(2)) # optional - sage.groups sage.rings.finite_rings sage.modules - sage: A.radical_basis() # optional - sage.groups sage.rings.finite_rings sage.modules + sage: A = KleinFourGroup().algebra(GF(2)) # needs sage.groups sage.modules + sage: A.radical_basis() # needs sage.groups sage.modules (() + (1,2)(3,4), (3,4) + (1,2)(3,4), (1,2) + (1,2)(3,4)) - sage: A = KleinFourGroup().algebra(QQ, category=Monoids()) # optional - sage.groups sage.modules - sage: A.radical_basis.__module__ # optional - sage.groups sage.modules + sage: A = KleinFourGroup().algebra(QQ, category=Monoids()) # needs sage.groups sage.modules + sage: A.radical_basis.__module__ # needs sage.groups sage.modules 'sage.categories.finite_dimensional_algebras_with_basis' - sage: A.radical_basis() # optional - sage.groups sage.modules + sage: A.radical_basis() # needs sage.groups sage.modules () """ F = self.base_ring() @@ -216,6 +219,7 @@ def radical(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -228,12 +232,14 @@ def radical(self): The radical is an ideal of `A`, and thus a finite dimensional non unital associative algebra:: + sage: # needs sage.graphs sage.modules sage: from sage.categories.associative_algebras import AssociativeAlgebras sage: radical in AssociativeAlgebras(QQ).WithBasis().FiniteDimensional() True sage: radical in Algebras(QQ) False + sage: # needs sage.graphs sage.modules sage: radical.dimension() 2 sage: radical.basis() @@ -251,6 +257,7 @@ def radical(self): TESTS:: + sage: # needs sage.graphs sage.modules sage: TestSuite(radical).run() """ category = AssociativeAlgebras(self.base_ring()).WithBasis().FiniteDimensional().Subobjects() @@ -271,6 +278,7 @@ def semisimple_quotient(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -292,10 +300,10 @@ def semisimple_quotient(self): descent algebra of the symmetric group is of dimension the number of partitions of `n`:: - sage: [ DescentAlgebra(QQ,n).B().semisimple_quotient().dimension() # optional - sage.combinat + sage: [ DescentAlgebra(QQ,n).B().semisimple_quotient().dimension() # needs sage.combinat sage.modules ....: for n in range(6) ] [1, 1, 2, 3, 5, 7] - sage: [Partitions(n).cardinality() for n in range(10)] # optional - sage.combinat + sage: [Partitions(n).cardinality() for n in range(10)] # needs sage.combinat [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] .. TODO:: @@ -305,7 +313,7 @@ def semisimple_quotient(self): TESTS:: - sage: TestSuite(S).run() + sage: TestSuite(S).run() # needs sage.graphs sage.modules """ ring = self.base_ring() category = Algebras(ring).WithBasis().FiniteDimensional().Quotients().Semisimple() @@ -326,6 +334,7 @@ def center_basis(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -344,6 +353,7 @@ def center(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -365,8 +375,8 @@ def center(self): The center of a semisimple algebra is semisimple:: - sage: A = DihedralGroup(6).algebra(QQ) # optional - sage.groups sage.modules - sage: A.center() in Algebras(QQ).Semisimple() # optional - sage.groups sage.modules + sage: A = DihedralGroup(6).algebra(QQ) # needs sage.groups sage.modules + sage: A.center() in Algebras(QQ).Semisimple() # needs sage.groups sage.modules True .. TODO:: @@ -376,7 +386,7 @@ def center(self): TESTS:: - sage: TestSuite(center).run() + sage: TestSuite(center).run() # needs sage.graphs sage.modules """ category = Algebras(self.base_ring()).FiniteDimensional().Subobjects().Commutative().WithBasis() if self in Algebras.Semisimple: @@ -397,6 +407,7 @@ def principal_ideal(self, a, side='left'): right principal ideals, our first example deals with a non commutative algebra:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -406,34 +417,34 @@ def principal_ideal(self, a, side='left'): In this algebra, multiplication on the right by `x` annihilates all basis elements but `x`:: - sage: x*x, y*x, a*x, b*x + sage: x*x, y*x, a*x, b*x # needs sage.graphs sage.modules (x, 0, 0, 0) so the left ideal generated by `x` is one-dimensional:: - sage: Ax = A.principal_ideal(x, side='left'); Ax + sage: Ax = A.principal_ideal(x, side='left'); Ax # needs sage.graphs sage.modules Free module generated by {0} over Rational Field - sage: [B.lift() for B in Ax.basis()] + sage: [B.lift() for B in Ax.basis()] # needs sage.graphs sage.modules [x] Multiplication on the left by `x` annihilates only `x` and fixes the other basis elements:: - sage: x*x, x*y, x*a, x*b + sage: x*x, x*y, x*a, x*b # needs sage.graphs sage.modules (x, 0, a, b) so the right ideal generated by `x` is 3-dimensional:: - sage: xA = A.principal_ideal(x, side='right'); xA + sage: xA = A.principal_ideal(x, side='right'); xA # needs sage.graphs sage.modules Free module generated by {0, 1, 2} over Rational Field - sage: [B.lift() for B in xA.basis()] + sage: [B.lift() for B in xA.basis()] # needs sage.graphs sage.modules [x, a, b] .. SEEALSO:: - :meth:`peirce_summand` """ - return self.submodule([(a * b if side=='right' else b * a) + return self.submodule([(a * b if side == 'right' else b * a) for b in self.basis()]) @cached_method @@ -470,20 +481,22 @@ def orthogonal_idempotents_central_mod_radical(self): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver (containing the arrows a:x->y and b:x->y) over Rational Field - sage: A.orthogonal_idempotents_central_mod_radical() # optional - sage.rings.number_field + sage: A.orthogonal_idempotents_central_mod_radical() # needs sage.rings.number_field (x, y) :: + sage: # needs sage.modules sage.rings.number_field sage: Z12 = Monoids().Finite().example(); Z12 An example of a finite multiplicative monoid: the integers modulo 12 sage: A = Z12.algebra(QQ) - sage: idempotents = A.orthogonal_idempotents_central_mod_radical() # optional - sage.rings.number_field - sage: sorted(idempotents, key=str) # optional - sage.rings.number_field + sage: idempotents = A.orthogonal_idempotents_central_mod_radical() + sage: sorted(idempotents, key=str) [-B[0] + 1/2*B[4] + 1/2*B[8], 1/2*B[4] - 1/2*B[8], 1/2*B[9] + 1/2*B[3] - B[0], @@ -493,26 +506,27 @@ def orthogonal_idempotents_central_mod_radical(self): 1/4*B[1] - 1/2*B[9] - 1/2*B[3] + 1/4*B[11] + 1/4*B[5] + 1/4*B[7] + B[0] - 1/2*B[4] - 1/2*B[8], 1/4*B[1] - 1/4*B[5] + 1/4*B[7] - 1/4*B[11] - 1/2*B[4] + 1/2*B[8], B[0]] - sage: sum(idempotents) == 1 # optional - sage.rings.number_field + sage: sum(idempotents) == 1 True - sage: all(e*e == e for e in idempotents) # optional - sage.rings.number_field + sage: all(e*e == e for e in idempotents) True - sage: all(e*f == 0 and f*e == 0 # optional - sage.rings.number_field + sage: all(e*f == 0 and f*e == 0 ....: for e in idempotents for f in idempotents if e != f) True This is best tested with:: - sage: A.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # optional - sage.rings.number_field + sage: A.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # needs sage.graphs sage.modules sage.rings.number_field True We construct orthogonal idempotents for the algebra of the `0`-Hecke monoid:: - sage: from sage.monoids.hecke_monoid import HeckeMonoid # optional - sage.groups - sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ) # optional - sage.groups - sage: idempotents = A.orthogonal_idempotents_central_mod_radical() # optional - sage.groups - sage: A.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # optional - sage.groups + sage: # needs sage.combinat sage.graphs sage.groups sage.modules + sage: from sage.monoids.hecke_monoid import HeckeMonoid + sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ) + sage: idempotents = A.orthogonal_idempotents_central_mod_radical() + sage: A.is_identity_decomposition_into_orthogonal_idempotents(idempotents) True """ one = self.one() @@ -555,6 +569,7 @@ def idempotent_lift(self, x): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example() sage: S = A.semisimple_quotient() sage: A.idempotent_lift(S.basis()['x']) @@ -570,7 +585,7 @@ def idempotent_lift(self, x): x = x.lift() p = self.semisimple_quotient().retract(x) if p * p != p: - raise ValueError("%s does not retract to an idempotent."%p) + raise ValueError("%s does not retract to an idempotent." % p) x_prev = None one = self.one() while x != x_prev: @@ -647,8 +662,8 @@ def cartan_invariants_matrix(self): in characteristic zero, the Cartan invariants matrix is the identity:: - sage: A3 = SymmetricGroup(3).algebra(QQ) # optional - sage.groups sage.modules - sage: A3.cartan_invariants_matrix() # optional - sage.groups sage.modules + sage: A3 = SymmetricGroup(3).algebra(QQ) # needs sage.groups sage.modules + sage: A3.cartan_invariants_matrix() # needs sage.groups sage.modules [1 0 0] [0 1 0] [0 0 1] @@ -657,7 +672,7 @@ def cartan_invariants_matrix(self): matrix counts the number of paths between two vertices:: sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example() - sage: A.cartan_invariants_matrix() # optional - sage.modules sage.rings.number_field + sage: A.cartan_invariants_matrix() # needs sage.modules sage.rings.number_field [1 2] [0 1] @@ -665,8 +680,8 @@ def cartan_invariants_matrix(self): sage: Z12 = Monoids().Finite().example(); Z12 An example of a finite multiplicative monoid: the integers modulo 12 - sage: A = Z12.algebra(QQ) # optional - sage.modules - sage: A.cartan_invariants_matrix() # optional - sage.modules sage.rings.number_fields + sage: A = Z12.algebra(QQ) # needs sage.modules + sage: A.cartan_invariants_matrix() # needs sage.modules sage.rings.number_field [1 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0] [0 0 2 0 0 0 0 0 0] @@ -679,9 +694,10 @@ def cartan_invariants_matrix(self): With the algebra of the `0`-Hecke monoid:: - sage: from sage.monoids.hecke_monoid import HeckeMonoid # optional - sage.groups sage.modules - sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ) # optional - sage.groups sage.modules - sage: A.cartan_invariants_matrix() # optional - sage.groups sage.modules sage.rings.number_field + sage: # needs sage.combinat sage.groups sage.modules + sage: from sage.monoids.hecke_monoid import HeckeMonoid + sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ) + sage: A.cartan_invariants_matrix() # needs sage.rings.number_field [1 0 0 0 0 0 0 0] [0 2 1 0 1 1 0 0] [0 1 1 0 1 0 0 0] @@ -737,14 +753,15 @@ def isotypic_projective_modules(self, side='left'): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage.rings.number_field sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver (containing the arrows a:x->y and b:x->y) over Rational Field - sage: Q = A.isotypic_projective_modules(side="left"); Q # optional - sage.rings.number_field + sage: Q = A.isotypic_projective_modules(side="left"); Q [Free module generated by {0} over Rational Field, Free module generated by {0, 1, 2} over Rational Field] - sage: [[x.lift() for x in Qi.basis()] # optional - sage.rings.number_field + sage: [[x.lift() for x in Qi.basis()] ....: for Qi in Q] [[x], [y, a, b]] @@ -752,7 +769,7 @@ def isotypic_projective_modules(self, side='left'): We check that the sum of the dimensions of the isotypic projective modules is the dimension of ``self``:: - sage: sum([Qi.dimension() for Qi in Q]) == A.dimension() # optional - sage.rings.number_field + sage: sum([Qi.dimension() for Qi in Q]) == A.dimension() # needs sage.graphs sage.modules sage.rings.number_field True .. SEEALSO:: @@ -784,19 +801,19 @@ def peirce_summand(self, ei, ej): EXAMPLES:: sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example() - sage: idemp = A.orthogonal_idempotents_central_mod_radical() # optional - sage.rings.number_field - sage: A.peirce_summand(idemp[0], idemp[1]) # optional - sage.rings.number_field + sage: idemp = A.orthogonal_idempotents_central_mod_radical() # needs sage.rings.number_field + sage: A.peirce_summand(idemp[0], idemp[1]) # needs sage.rings.number_field Free module generated by {0, 1} over Rational Field - sage: A.peirce_summand(idemp[1], idemp[0]) # optional - sage.rings.number_field + sage: A.peirce_summand(idemp[1], idemp[0]) # needs sage.rings.number_field Free module generated by {} over Rational Field We recover the `2\times2` block of `\QQ[S_4]` corresponding to the unique simple module of dimension `2` of the symmetric group `S_4`:: - sage: A4 = SymmetricGroup(4).algebra(QQ) # optional - sage.groups - sage: e = A4.central_orthogonal_idempotents()[2] # optional - sage.groups sage.rings.number_field - sage: A4.peirce_summand(e, e) # optional - sage.groups sage.rings.number_field + sage: A4 = SymmetricGroup(4).algebra(QQ) # needs sage.groups + sage: e = A4.central_orthogonal_idempotents()[2] # needs sage.groups sage.rings.number_field + sage: A4.peirce_summand(e, e) # needs sage.groups sage.rings.number_field Free module generated by {0, 1, 2, 3} over Rational Field TESTS: @@ -804,11 +821,12 @@ def peirce_summand(self, ei, ej): We check each idempotent belong to its own Peirce summand (see :trac:`24687`):: - sage: from sage.monoids.hecke_monoid import HeckeMonoid # optional - sage.groups - sage: M = HeckeMonoid(SymmetricGroup(4)) # optional - sage.groups - sage: A = M.algebra(QQ) # optional - sage.groups - sage: Idms = A.orthogonal_idempotents_central_mod_radical() # optional - sage.groups sage.rings.number_field - sage: all(A.peirce_summand(e, e).retract(e) # optional - sage.groups sage.rings.number_field + sage: # needs sage.groups + sage: from sage.monoids.hecke_monoid import HeckeMonoid + sage: M = HeckeMonoid(SymmetricGroup(4)) + sage: A = M.algebra(QQ) + sage: Idms = A.orthogonal_idempotents_central_mod_radical() # needs sage.rings.number_field + sage: all(A.peirce_summand(e, e).retract(e) # needs sage.rings.number_field ....: in A.peirce_summand(e, e) for e in Idms) True """ @@ -861,18 +879,19 @@ def peirce_decomposition(self, idempotents=None, check=True): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage.modules sage.rings.number_field sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver (containing the arrows a:x->y and b:x->y) over Rational Field - sage: A.orthogonal_idempotents_central_mod_radical() # optional - sage.groups + sage: A.orthogonal_idempotents_central_mod_radical() (x, y) - sage: decomposition = A.peirce_decomposition(); decomposition # optional - sage.groups sage.modules sage.rings.number_field + sage: decomposition = A.peirce_decomposition(); decomposition [[Free module generated by {0} over Rational Field, Free module generated by {0, 1} over Rational Field], [Free module generated by {} over Rational Field, Free module generated by {0} over Rational Field]] - sage: [ [[x.lift() for x in decomposition[i][j].basis()] # optional - sage.groups sage.modules sage.rings.number_field + sage: [ [[x.lift() for x in decomposition[i][j].basis()] ....: for j in range(2)] ....: for i in range(2)] [[[x], [a, b]], @@ -881,9 +900,10 @@ def peirce_decomposition(self, idempotents=None, check=True): We recover that the group algebra of the symmetric group `S_4` is a block matrix algebra:: - sage: A = SymmetricGroup(4).algebra(QQ) # optional - sage.groups sage.modules - sage: decomposition = A.peirce_decomposition() # long time # optional - sage.groups sage.modules sage.rings.number_field - sage: [[decomposition[i][j].dimension() # long time (4s) # optional - sage.groups sage.modules sage.rings.number_field + sage: # needs sage.groups sage.modules sage.rings.number_field + sage: A = SymmetricGroup(4).algebra(QQ) + sage: decomposition = A.peirce_decomposition() # long time + sage: [[decomposition[i][j].dimension() # long time (4s) ....: for j in range(len(decomposition))] ....: for i in range(len(decomposition))] [[9, 0, 0, 0, 0], @@ -896,7 +916,7 @@ def peirce_decomposition(self, idempotents=None, check=True): dimension of the corresponding simple module of `S_4`. The latter are given by:: - sage: [p.standard_tableaux().cardinality() for p in Partitions(4)] # optional - sage.combinat + sage: [p.standard_tableaux().cardinality() for p in Partitions(4)] # needs sage.combinat [1, 3, 2, 3, 1] """ if idempotents is None: @@ -918,14 +938,13 @@ def is_identity_decomposition_into_orthogonal_idempotents(self, l): EXAMPLES:: + sage: # needs sage.graphs sage.modules sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver (containing the arrows a:x->y and b:x->y) over Rational Field - sage: x,y,a,b = A.algebra_generators(); x,y,a,b (x, y, a, b) - sage: A.is_identity_decomposition_into_orthogonal_idempotents([A.one()]) True sage: A.is_identity_decomposition_into_orthogonal_idempotents([x, y]) @@ -935,20 +954,21 @@ def is_identity_decomposition_into_orthogonal_idempotents(self, l): Here the idempotents do not sum up to `1`:: - sage: A.is_identity_decomposition_into_orthogonal_idempotents([x]) + sage: A.is_identity_decomposition_into_orthogonal_idempotents([x]) # needs sage.graphs sage.modules False Here `1+x` and `-x` are neither idempotent nor orthogonal:: - sage: A.is_identity_decomposition_into_orthogonal_idempotents([1 + x, -x]) + sage: A.is_identity_decomposition_into_orthogonal_idempotents([1 + x, -x]) # needs sage.graphs sage.modules False With the algebra of the `0`-Hecke monoid:: - sage: from sage.monoids.hecke_monoid import HeckeMonoid # optional - sage.groups - sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ) # optional - sage.groups sage.modules - sage: idempotents = A.orthogonal_idempotents_central_mod_radical() # optional - sage.groups sage.modules sage.rings.number_field - sage: A.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # optional - sage.groups sage.modules sage.rings.number_field + sage: # needs sage.combinat sage.groups sage.modules + sage: from sage.monoids.hecke_monoid import HeckeMonoid + sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ) + sage: idempotents = A.orthogonal_idempotents_central_mod_radical() # needs sage.rings.number_field + sage: A.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # needs sage.rings.number_field True Here are some more counterexamples: @@ -956,6 +976,7 @@ def is_identity_decomposition_into_orthogonal_idempotents(self, l): 1. Some orthogonal elements summing to `1` but not being idempotent:: + sage: # needs sage.libs.pari sage.modules sage: class PQAlgebra(CombinatorialFreeModule): ....: def __init__(self, F, p): ....: # Construct the quotient algebra F[x] / p, @@ -973,40 +994,43 @@ def is_identity_decomposition_into_orthogonal_idempotents(self, l): ....: def product_on_basis(self, w1, w2): ....: return self.from_vector(vector(w1*w2)) sage: R. = PolynomialRing(QQ) - sage: A = PQAlgebra(QQ, x**3 - x**2 + x + 1); y = A.x() # optional - sage.libs.pari - sage: a, b = y, 1 - y # optional - sage.libs.pari - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, b)) # optional - sage.libs.pari + sage: A = PQAlgebra(QQ, x**3 - x**2 + x + 1); y = A.x() + sage: a, b = y, 1 - y + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, b)) False For comparison:: - sage: A = PQAlgebra(QQ, x**2 - x); y = A.x() # optional - sage.libs.pari - sage: a, b = y, 1-y # optional - sage.libs.pari - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, b)) # optional - sage.libs.pari + sage: # needs sage.libs.pari sage.modules + sage: A = PQAlgebra(QQ, x**2 - x); y = A.x() + sage: a, b = y, 1-y + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, b)) True - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, A.zero(), b)) # optional - sage.libs.pari + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, A.zero(), b)) True - sage: A = PQAlgebra(QQ, x**3 - x**2 + x - 1); y = A.x() # optional - sage.libs.pari - sage: a = (y**2 + 1) / 2 # optional - sage.libs.pari - sage: b = 1 - a # optional - sage.libs.pari - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, b)) # optional - sage.libs.pari + sage: A = PQAlgebra(QQ, x**3 - x**2 + x - 1); y = A.x() + sage: a = (y**2 + 1) / 2 + sage: b = 1 - a + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, b)) True 2. Some idempotents summing to 1 but not orthogonal:: - sage: R. = PolynomialRing(GF(2)) # optional - sage.rings.finite_rings - sage: A = PQAlgebra(GF(2), x) # optional - sage.rings.finite_rings - sage: a = A.one() # optional - sage.rings.finite_rings - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a,)) # optional - sage.rings.finite_rings + sage: # needs sage.libs.pari sage.modules + sage: R. = PolynomialRing(GF(2)) + sage: A = PQAlgebra(GF(2), x) + sage: a = A.one() + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a,)) True - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, a, a)) # optional - sage.rings.finite_rings + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a, a, a)) False 3. Some orthogonal idempotents not summing to the identity:: - sage: A.is_identity_decomposition_into_orthogonal_idempotents((a,a)) # optional - sage.rings.finite_rings + sage: # needs sage.libs.pari sage.modules + sage: A.is_identity_decomposition_into_orthogonal_idempotents((a,a)) False - sage: A.is_identity_decomposition_into_orthogonal_idempotents(()) # optional - sage.rings.finite_rings + sage: A.is_identity_decomposition_into_orthogonal_idempotents(()) False """ return (self.sum(l) == self.one() @@ -1021,11 +1045,12 @@ def is_commutative(self): EXAMPLES:: - sage: S4 = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules - sage: S4.is_commutative() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S4 = SymmetricGroupAlgebra(QQ, 4) + sage: S4.is_commutative() False - sage: S2 = SymmetricGroupAlgebra(QQ, 2) # optional - sage.groups sage.modules - sage: S2.is_commutative() # optional - sage.groups sage.modules + sage: S2 = SymmetricGroupAlgebra(QQ, 2) + sage: S2.is_commutative() True """ B = list(self.basis()) @@ -1049,23 +1074,24 @@ def to_matrix(self, base_ring=None, action=operator.mul, side='left'): EXAMPLES:: - sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: a = QS3([2,1,3]) # optional - sage.groups sage.modules - sage: a.to_matrix(side='left') # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: QS3 = SymmetricGroupAlgebra(QQ, 3) + sage: a = QS3([2,1,3]) + sage: a.to_matrix(side='left') [0 0 1 0 0 0] [0 0 0 0 1 0] [1 0 0 0 0 0] [0 0 0 0 0 1] [0 1 0 0 0 0] [0 0 0 1 0 0] - sage: a.to_matrix(side='right') # optional - sage.groups sage.modules + sage: a.to_matrix(side='right') [0 0 1 0 0 0] [0 0 0 1 0 0] [1 0 0 0 0 0] [0 1 0 0 0 0] [0 0 0 0 0 1] [0 0 0 0 1 0] - sage: a.to_matrix(base_ring=RDF, side="left") # optional - sage.groups sage.modules + sage: a.to_matrix(base_ring=RDF, side="left") [0.0 0.0 1.0 0.0 0.0 0.0] [0.0 0.0 0.0 0.0 1.0 0.0] [1.0 0.0 0.0 0.0 0.0 0.0] @@ -1102,47 +1128,50 @@ def __invert__(self): EXAMPLES:: - sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: P = Permutation # optional - sage.groups sage.modules - sage: a = 3 * QS3(P([1,2,3])) + QS3(P([1,3,2])) + QS3(P([2,1,3])) # optional - sage.groups sage.modules - sage: b = ~a; b # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: QS3 = SymmetricGroupAlgebra(QQ, 3) + sage: P = Permutation + sage: a = 3 * QS3(P([1,2,3])) + QS3(P([1,3,2])) + QS3(P([2,1,3])) + sage: b = ~a; b 9/20*[1, 2, 3] - 7/40*[1, 3, 2] - 7/40*[2, 1, 3] + 3/40*[2, 3, 1] + 3/40*[3, 1, 2] - 1/20*[3, 2, 1] - sage: a * b # optional - sage.groups sage.modules + sage: a * b [1, 2, 3] - sage: ~b == a # optional - sage.groups sage.modules + sage: ~b == a True - sage: a = 3 * QS3.one() # optional - sage.groups sage.modules - sage: b = ~a # optional - sage.groups sage.modules - sage: b * a == QS3.one() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: a = 3 * QS3.one() + sage: b = ~a + sage: b * a == QS3.one() True - sage: b == 1/3 * QS3.one() # optional - sage.groups sage.modules + sage: b == 1/3 * QS3.one() True - sage: ~b == a # optional - sage.groups sage.modules + sage: ~b == a True sage: R. = QQ[] - sage: RS3 = SymmetricGroupAlgebra(R, 3) # optional - sage.groups sage.modules - sage: a = RS3(P([1,2,3])) - RS3(P([1,3,2])) + RS3(P([2,1,3])); ~a # optional - sage.groups sage.modules + sage: RS3 = SymmetricGroupAlgebra(R, 3) # needs sage.groups sage.modules + sage: a = RS3(P([1,2,3])) - RS3(P([1,3,2])) + RS3(P([2,1,3])); ~a # needs sage.groups sage.modules -1/2*[1, 3, 2] + 1/2*[2, 1, 3] + 1/2*[2, 3, 1] + 1/2*[3, 1, 2] Some examples on elements that do not have an inverse:: - sage: c = 2 * QS3(P([1,2,3])) + QS3(P([1,3,2])) + QS3(P([2,1,3])) # optional - sage.groups sage.modules - sage: ~c # optional - sage.groups sage.modules + sage: c = 2 * QS3(P([1,2,3])) + QS3(P([1,3,2])) + QS3(P([2,1,3])) # needs sage.groups sage.modules + sage: ~c # needs sage.groups sage.modules Traceback (most recent call last): ... ValueError: cannot invert self (= 2*[1, 2, 3] + [1, 3, 2] + [2, 1, 3]) - sage: ZS3 = SymmetricGroupAlgebra(ZZ, 3) # optional - sage.groups sage.modules - sage: aZ = 3 * ZS3(P([1,2,3])) + ZS3(P([1,3,2])) + ZS3(P([2,1,3])) # optional - sage.groups sage.modules - sage: ~aZ # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: ZS3 = SymmetricGroupAlgebra(ZZ, 3) + sage: aZ = 3 * ZS3(P([1,2,3])) + ZS3(P([1,3,2])) + ZS3(P([2,1,3])) + sage: ~aZ Traceback (most recent call last): ... ValueError: cannot invert self (= 3*[1, 2, 3] + [1, 3, 2] + [2, 1, 3]) - sage: x = 2 * ZS3.one() # optional - sage.groups sage.modules - sage: ~x # optional - sage.groups sage.modules + sage: x = 2 * ZS3.one() + sage: ~x Traceback (most recent call last): ... ValueError: cannot invert self (= 2*[1, 2, 3]) @@ -1151,9 +1180,9 @@ def __invert__(self): An algebra that does not define ``one_basis()``:: - sage: I = DescentAlgebra(QQ, 3).I() # optional - sage.combinat sage.modules - sage: a = 3 * I.one() # optional - sage.combinat sage.modules - sage: ~a == 1/3 * I.one() # optional - sage.combinat sage.modules + sage: I = DescentAlgebra(QQ, 3).I() # needs sage.combinat sage.modules + sage: a = 3 * I.one() # needs sage.combinat sage.modules + sage: ~a == 1/3 * I.one() # needs sage.combinat sage.modules True """ alg = self.parent() @@ -1241,8 +1270,8 @@ def _test_cellular(self, **options): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.combinat sage.modules - sage: S._test_cellular() # optional - sage.combinat sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.combinat sage.modules + sage: S._test_cellular() # needs sage.combinat sage.modules """ tester = self._tester(**options) cell_basis = self.cellular_basis() @@ -1275,8 +1304,8 @@ def cell_poset(self): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules - sage: S.cell_poset() # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 4) # needs sage.groups sage.modules + sage: S.cell_poset() # needs sage.groups sage.modules Finite poset containing 5 elements """ @@ -1290,8 +1319,8 @@ def cell_module_indices(self, mu): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: S.cell_module_indices([2,1]) # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: S.cell_module_indices([2,1]) # needs sage.groups sage.modules Standard tableaux of shape [2, 1] """ @@ -1303,8 +1332,8 @@ def _to_cellular_element(self, i): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: S._to_cellular_element # no implementation currently uses this # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: S._to_cellular_element # no implementation currently uses this # needs sage.groups sage.modules NotImplemented """ @@ -1316,11 +1345,12 @@ def _from_cellular_index(self, x): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.combinat sage.groups sage.modules - sage: mu = Partition([2,1]) # optional - sage.combinat sage.groups sage.modules - sage: s = StandardTableau([[1,2],[3]]) # optional - sage.combinat sage.groups sage.modules - sage: t = StandardTableau([[1,3],[2]]) # optional - sage.combinat sage.groups sage.modules - sage: S._from_cellular_index((mu, s, t)) # optional - sage.combinat sage.groups sage.modules + sage: # needs sage.combinat sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) + sage: mu = Partition([2,1]) + sage: s = StandardTableau([[1,2],[3]]) + sage: t = StandardTableau([[1,3],[2]]) + sage: S._from_cellular_index((mu, s, t)) 1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1] """ @@ -1330,8 +1360,8 @@ def cellular_involution(self, x): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: for b in S.basis(): b, S.cellular_involution(b) # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: for b in S.basis(): b, S.cellular_involution(b) # needs sage.groups sage.modules ([1, 2, 3], [1, 2, 3]) ([1, 3, 2], 49/48*[1, 3, 2] + 7/48*[2, 3, 1] - 7/48*[3, 1, 2] - 1/48*[3, 2, 1]) @@ -1357,8 +1387,8 @@ def cells(self): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: dict(S.cells()) # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: dict(S.cells()) # needs sage.groups sage.modules {[1, 1, 1]: Standard tableaux of shape [1, 1, 1], [2, 1]: Standard tableaux of shape [2, 1], [3]: Standard tableaux of shape [3]} @@ -1372,8 +1402,8 @@ def cellular_basis(self): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: S.cellular_basis() # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: S.cellular_basis() # needs sage.groups sage.modules Cellular basis of Symmetric group algebra of order 3 over Rational Field """ @@ -1386,8 +1416,8 @@ def cell_module(self, mu, **kwds): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: S.cell_module(Partition([2,1])) # optional - sage.combinat sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: S.cell_module(Partition([2,1])) # needs sage.combinat sage.groups sage.modules Cell module indexed by [2, 1] of Cellular basis of Symmetric group algebra of order 3 over Rational Field """ @@ -1405,8 +1435,8 @@ def simple_module_parameterization(self): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules - sage: S.simple_module_parameterization() # optional - sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 4) # needs sage.groups sage.modules + sage: S.simple_module_parameterization() # needs sage.groups sage.modules ([4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]) """ return tuple([mu for mu in self.cell_poset() @@ -1419,12 +1449,13 @@ def cellular_involution(self): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules - sage: elt = S([3,1,2,4]) # optional - sage.groups sage.modules - sage: ci = elt.cellular_involution(); ci # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 4) + sage: elt = S([3,1,2,4]) + sage: ci = elt.cellular_involution(); ci 7/48*[1, 3, 2, 4] + 49/48*[2, 3, 1, 4] - 1/48*[3, 1, 2, 4] - 7/48*[3, 2, 1, 4] - sage: ci.cellular_involution() # optional - sage.groups sage.modules + sage: ci.cellular_involution() [3, 1, 2, 4] """ return self.parent().cellular_involution(self) @@ -1456,10 +1487,11 @@ def cell_poset(self): EXAMPLES:: - sage: S2 = SymmetricGroupAlgebra(QQ, 2) # optional - sage.groups sage.modules - sage: S3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: T = S2.tensor(S3) # optional - sage.groups sage.modules - sage: T.cell_poset() # optional - sage.combinat sage.graphs sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S2 = SymmetricGroupAlgebra(QQ, 2) + sage: S3 = SymmetricGroupAlgebra(QQ, 3) + sage: T = S2.tensor(S3) + sage: T.cell_poset() # needs sage.combinat sage.graphs Finite poset containing 6 elements """ ret = self._sets[0].cell_poset() @@ -1476,10 +1508,11 @@ def cell_module_indices(self, mu): EXAMPLES:: - sage: S2 = SymmetricGroupAlgebra(QQ, 2) # optional - sage.groups sage.modules - sage: S3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: T = S2.tensor(S3) # optional - sage.groups sage.modules - sage: T.cell_module_indices(([1,1], [2,1])) # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S2 = SymmetricGroupAlgebra(QQ, 2) + sage: S3 = SymmetricGroupAlgebra(QQ, 3) + sage: T = S2.tensor(S3) + sage: T.cell_module_indices(([1,1], [2,1])) The Cartesian product of (Standard tableaux of shape [1, 1], Standard tableaux of shape [2, 1]) """ @@ -1495,10 +1528,11 @@ def cellular_involution(self): EXAMPLES:: - sage: S2 = SymmetricGroupAlgebra(QQ, 2) # optional - sage.groups sage.modules - sage: S3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: T = S2.tensor(S3) # optional - sage.groups sage.modules - sage: for b in T.basis(): b, T.cellular_involution(b) # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S2 = SymmetricGroupAlgebra(QQ, 2) + sage: S3 = SymmetricGroupAlgebra(QQ, 3) + sage: T = S2.tensor(S3) + sage: for b in T.basis(): b, T.cellular_involution(b) ([1, 2] # [1, 2, 3], [1, 2] # [1, 2, 3]) ([1, 2] # [1, 3, 2], 49/48*[1, 2] # [1, 3, 2] + 7/48*[1, 2] # [2, 3, 1] @@ -1548,10 +1582,11 @@ def _to_cellular_element(self, i): EXAMPLES:: - sage: S2 = SymmetricGroupAlgebra(QQ, 2) # optional - sage.groups sage.modules - sage: S3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: T = S2.tensor(S3) # optional - sage.groups sage.modules - sage: all(T(T._to_cellular_element(k)).leading_support() == k # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S2 = SymmetricGroupAlgebra(QQ, 2) + sage: S3 = SymmetricGroupAlgebra(QQ, 3) + sage: T = S2.tensor(S3) + sage: all(T(T._to_cellular_element(k)).leading_support() == k ....: for k in T.basis().keys()) True """ @@ -1584,11 +1619,12 @@ def _from_cellular_index(self, x): EXAMPLES:: - sage: S2 = SymmetricGroupAlgebra(QQ, 2) # optional - sage.groups sage.modules - sage: S3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: T = S2.tensor(S3) # optional - sage.groups sage.modules - sage: C = T.cellular_basis() # optional - sage.groups sage.modules - sage: all(C(T._from_cellular_index(k)).leading_support() == k # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S2 = SymmetricGroupAlgebra(QQ, 2) + sage: S3 = SymmetricGroupAlgebra(QQ, 3) + sage: T = S2.tensor(S3) + sage: C = T.cellular_basis() + sage: all(C(T._from_cellular_index(k)).leading_support() == k ....: for k in C.basis().keys()) True """ diff --git a/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py b/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py index e10e30a5846..c5554a2f094 100644 --- a/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py @@ -53,14 +53,15 @@ def _test_grading(self, **options): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: C = LieAlgebras(QQ).WithBasis().Graded() sage: C = C.FiniteDimensional().Stratified().Nilpotent() - sage: L = LieAlgebra(QQ, {('x','y'): {'z': 1}}, # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, {('x','y'): {'z': 1}}, ....: nilpotent=True, category=C) - sage: L._test_grading() # optional - sage.combinat sage.modules - sage: L = LieAlgebra(QQ, {('x','y'): {'x': 1}}, # optional - sage.combinat sage.modules + sage: L._test_grading() + sage: L = LieAlgebra(QQ, {('x','y'): {'x': 1}}, ....: nilpotent=True, category=C) - sage: L._test_grading() # optional - sage.combinat sage.modules + sage: L._test_grading() Traceback (most recent call last): ... AssertionError: Lie bracket [x, y] has degree 1, not degree 2 @@ -96,9 +97,9 @@ def homogeneous_component_as_submodule(self, d): sage: C = LieAlgebras(QQ).WithBasis().Graded() sage: C = C.FiniteDimensional().Stratified().Nilpotent() - sage: L = LieAlgebra(QQ, {('x','y'): {'z': 1}}, # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, {('x','y'): {'z': 1}}, # needs sage.combinat sage.modules ....: nilpotent=True, category=C) - sage: L.homogeneous_component_as_submodule(2) # optional - sage.combinat sage.modules + sage: L.homogeneous_component_as_submodule(2) # needs sage.combinat sage.modules Sparse vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [0 0 1] @@ -147,12 +148,12 @@ def _test_generated_by_degree_one(self, **options): sage: C = LieAlgebras(QQ).WithBasis().Graded() sage: C = C.FiniteDimensional().Stratified().Nilpotent() sage: sc = {('x','y'): {'z': 1}} - sage: L. = LieAlgebra(QQ, sc, nilpotent=True, category=C) # optional - sage.combinat sage.modules - sage: L._test_generated_by_degree_one() # optional - sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, sc, nilpotent=True, category=C) # needs sage.combinat sage.modules + sage: L._test_generated_by_degree_one() # needs sage.combinat sage.modules sage: sc = {('x','y'): {'z': 1}, ('a','b'): {'c':1}, ('z','c'): {'m':1}} - sage: L. = LieAlgebra(QQ, sc, nilpotent=True, category=C) # optional - sage.combinat sage.modules - sage: L._test_generated_by_degree_one() # optional - sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, sc, nilpotent=True, category=C) # needs sage.combinat sage.modules + sage: L._test_generated_by_degree_one() # needs sage.combinat sage.modules Traceback (most recent call last): ... AssertionError: [a, b, x, y] does not generate Nilpotent Lie algebra @@ -196,19 +197,20 @@ def degree_on_basis(self, m): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: C = LieAlgebras(QQ).WithBasis().Graded() sage: C = C.FiniteDimensional().Stratified().Nilpotent() sage: sc = {('X','Y'): {'Z': 1}} - sage: L. = LieAlgebra(QQ, sc, nilpotent=True, category=C) # optional - sage.combinat sage.modules - sage: L.degree_on_basis(X.leading_support()) # optional - sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, sc, nilpotent=True, category=C) + sage: L.degree_on_basis(X.leading_support()) 1 - sage: X.degree() # optional - sage.combinat sage.modules + sage: X.degree() 1 - sage: Y.degree() # optional - sage.combinat sage.modules + sage: Y.degree() 1 - sage: L[X, Y] # optional - sage.combinat sage.modules + sage: L[X, Y] Z - sage: Z.degree() # optional - sage.combinat sage.modules + sage: Z.degree() 2 """ if not hasattr(self, '_basis_degrees'): diff --git a/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py b/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py index 67181caffa9..013b30dc281 100644 --- a/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py @@ -46,13 +46,13 @@ def example(self, n=3): EXAMPLES:: sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() - sage: C.example() # optional - sage.modules + sage: C.example() # needs sage.modules An example of a finite dimensional Lie algebra with basis: the 3-dimensional abelian Lie algebra over Rational Field Other dimensions can be specified as an optional argument:: - sage: C.example(5) # optional - sage.modules + sage: C.example(5) # needs sage.modules An example of a finite dimensional Lie algebra with basis: the 5-dimensional abelian Lie algebra over Rational Field """ @@ -70,29 +70,31 @@ def _construct_UEA(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules sage.combinat - sage: UEA = L._construct_UEA(); UEA # optional - sage.modules sage.combinat + sage: # needs sage.combinat sage.libs.singular sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: UEA = L._construct_UEA(); UEA Noncommutative Multivariate Polynomial Ring in b0, b1, b2 over Rational Field, nc-relations: {} - sage: UEA.relations(add_commutative=True) # optional - sage.modules sage.combinat + sage: UEA.relations(add_commutative=True) {b1*b0: b0*b1, b2*b0: b0*b2, b2*b1: b1*b2} :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'z':1}, # optional - sage.modules sage.combinat + sage: # needs sage.combinat sage.libs.singular sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'z':1}, ....: ('y','z'): {'x':1}, ....: ('z','x'):{'y':1}}) - sage: UEA = L._construct_UEA(); UEA # optional - sage.modules sage.combinat + sage: UEA = L._construct_UEA(); UEA Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {...} - sage: sorted(UEA.relations().items(), key=str) # optional - sage.modules sage.combinat + sage: sorted(UEA.relations().items(), key=str) [(y*x, x*y - z), (z*x, x*z + y), (z*y, y*z - x)] Singular's ``nc_algebra`` does not work over `\ZZ/6\ZZ`, so we fallback to the PBW basis in this case:: - sage: L = lie_algebras.pwitt(Zmod(6), 6) # optional - sage.modules sage.combinat - sage: L._construct_UEA() # optional - sage.modules sage.combinat + sage: L = lie_algebras.pwitt(Zmod(6), 6) # needs sage.combinat sage.modules + sage: L._construct_UEA() # needs sage.combinat sage.libs.singular sage.modules Universal enveloping algebra of The 6-Witt Lie algebra over Ring of integers modulo 6 in the Poincare-Birkhoff-Witt basis @@ -149,8 +151,8 @@ def _basis_ordering(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules sage.combinat - sage: L._basis_ordering # optional - sage.modules sage.combinat + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L._basis_ordering # needs sage.modules (0, 1, 2) """ return tuple(self.basis().keys()) @@ -163,10 +165,11 @@ def _basis_key_inverse(self): EXAMPLES:: - sage: G = SymmetricGroup(3) # optional - sage.groups - sage: S = GroupAlgebra(G, QQ) # optional - sage.groups sage.modules - sage: L = LieAlgebra(associative=S) # optional - sage.groups sage.modules - sage: [L._basis_key_inverse[k] for k in L._basis_ordering] # optional - sage.groups sage.modules + sage: # needs sage.combinat sage.groups sage.modules + sage: G = SymmetricGroup(3) + sage: S = GroupAlgebra(G, QQ) + sage: L = LieAlgebra(associative=S) + sage: [L._basis_key_inverse[k] for k in L._basis_ordering] [0, 1, 2, 3, 4, 5] """ return {k: i for i,k in enumerate(self._basis_ordering)} @@ -177,34 +180,35 @@ def _basis_key(self, x): TESTS:: - sage: L = lie_algebras.three_dimensional_by_rank(QQ, 3, # optional - sage.groups sage.modules + sage: L = lie_algebras.three_dimensional_by_rank(QQ, 3, # needs sage.groups sage.modules ....: names=['E','F','H']) - sage: PBW = L.pbw_basis() # optional - sage.groups sage.modules - sage: PBW._basis_key('E') < PBW._basis_key('H') # optional - sage.groups sage.modules + sage: PBW = L.pbw_basis() # needs sage.groups sage.modules + sage: PBW._basis_key('E') < PBW._basis_key('H') # needs sage.groups sage.modules True :: - sage: L = lie_algebras.sl(QQ, 2) # optional - sage.groups sage.modules - sage: def neg_key(x): # optional - sage.groups sage.modules + sage: L = lie_algebras.sl(QQ, 2) # needs sage.groups sage.modules + sage: def neg_key(x): ....: return -L.basis().keys().index(x) - sage: PBW = L.pbw_basis(basis_key=neg_key) # optional - sage.groups sage.modules - sage: prod(PBW.gens()) # indirect doctest # optional - sage.groups sage.modules + sage: PBW = L.pbw_basis(basis_key=neg_key) # needs sage.groups sage.modules + sage: prod(PBW.gens()) # indirect doctest # needs sage.groups sage.modules PBW[-alpha[1]]*PBW[alphacheck[1]]*PBW[alpha[1]] - 4*PBW[-alpha[1]]*PBW[alpha[1]] + PBW[alphacheck[1]]^2 - 2*PBW[alphacheck[1]] Check that :trac:`23266` is fixed:: - sage: sl2 = lie_algebras.sl(QQ, 2, 'matrix') # optional - sage.groups sage.modules - sage: sl2.indices() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: sl2 = lie_algebras.sl(QQ, 2, 'matrix') + sage: sl2.indices() {'e1', 'f1', 'h1'} - sage: type(sl2.basis().keys()) # optional - sage.groups sage.modules + sage: type(sl2.basis().keys()) - sage: Usl2 = sl2.pbw_basis() # optional - sage.groups sage.modules - sage: Usl2._basis_key(2) # optional - sage.groups sage.modules + sage: Usl2 = sl2.pbw_basis() + sage: Usl2._basis_key(2) 2 - sage: Usl2._basis_key(3) # optional - sage.groups sage.modules + sage: Usl2._basis_key(3) Traceback (most recent call last): ... KeyError: 3 @@ -217,8 +221,8 @@ def _dense_free_module(self, R=None): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: L._dense_free_module() # optional - sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L._dense_free_module() # needs sage.modules Vector space of dimension 3 over Rational Field """ if R is None: @@ -240,10 +244,10 @@ def from_vector(self, v, order=None): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: u = L.from_vector(vector(QQ, (1, 0, 0))); u # optional - sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: u = L.from_vector(vector(QQ, (1, 0, 0))); u # needs sage.modules (1, 0, 0) - sage: parent(u) is L # optional - sage.modules + sage: parent(u) is L # needs sage.modules True """ if order is None: @@ -263,17 +267,17 @@ def killing_matrix(self, x, y): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.modules - sage: L.killing_matrix(a, b) # optional - sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules + sage: L.killing_matrix(a, b) # needs sage.modules [0 0 0] [0 0 0] [0 0 0] :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.killing_matrix(y, x) # optional - sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # needs sage.combinat sage.modules + sage: L.killing_matrix(y, x) # needs sage.combinat sage.modules [ 0 -1] [ 0 0] """ @@ -294,9 +298,9 @@ def killing_form(self, x, y): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.combinat sage.modules - sage: L.killing_form(a, b) # optional - sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules + sage: L.killing_form(a, b) # needs sage.modules 0 """ return self.killing_matrix(x, y).trace() @@ -312,16 +316,16 @@ def killing_form_matrix(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: L.killing_form_matrix() # optional - sage.modules + sage: # needs sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.killing_form_matrix() [0 0 0] [0 0 0] [0 0 0] - - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example(0) # optional - sage.modules - sage: m = L.killing_form_matrix(); m # optional - sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example(0) + sage: m = L.killing_form_matrix(); m [] - sage: parent(m) # optional - sage.modules + sage: parent(m) Full MatrixSpace of 0 by 0 dense matrices over Rational Field """ from sage.matrix.constructor import matrix @@ -350,18 +354,19 @@ def structure_coefficients(self, include_zeros=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: L.structure_coefficients() # optional - sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L.structure_coefficients() # needs sage.modules Finite family {} - sage: L.structure_coefficients(True) # optional - sage.modules + sage: L.structure_coefficients(True) # needs sage.modules Finite family {(0, 1): (0, 0, 0), (0, 2): (0, 0, 0), (1, 2): (0, 0, 0)} :: - sage: G = SymmetricGroup(3) # optional - sage.groups - sage: S = GroupAlgebra(G, QQ) # optional - sage.groups sage.modules - sage: L = LieAlgebra(associative=S) # optional - sage.groups sage.modules sage.combinat - sage: L.structure_coefficients() # optional - sage.groups sage.modules sage.combinat + sage: # needs sage.combinat sage.groups sage.modules + sage: G = SymmetricGroup(3) + sage: S = GroupAlgebra(G, QQ) + sage: L = LieAlgebra(associative=S) + sage: L.structure_coefficients() Finite family {((2,3), (1,2)): (1,2,3) - (1,3,2), ((2,3), (1,3)): -(1,2,3) + (1,3,2), ((1,2,3), (2,3)): -(1,2) + (1,3), @@ -404,23 +409,25 @@ def centralizer_basis(self, S): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.modules - sage: L.centralizer_basis([a + b, 2*a + c]) # optional - sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: a, b, c = L.lie_algebra_generators() + sage: L.centralizer_basis([a + b, 2*a + c]) [(1, 0, 0), (0, 1, 0), (0, 0, 1)] - sage: H = lie_algebras.Heisenberg(QQ, 2) # optional - sage.combinat sage.modules - sage: H.centralizer_basis(H) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: H = lie_algebras.Heisenberg(QQ, 2) + sage: H.centralizer_basis(H) [z] - - sage: D = DescentAlgebra(QQ, 4).D() # optional - sage.combinat sage.modules - sage: L = LieAlgebra(associative=D) # optional - sage.combinat sage.modules - sage: L.centralizer_basis(L) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.groupssage.modules + sage: D = DescentAlgebra(QQ, 4).D() + sage: L = LieAlgebra(associative=D) + sage: L.centralizer_basis(L) [D{}, D{1} + D{1, 2} + D{2, 3} + D{3}, D{1, 2, 3} + D{1, 3} + D{2}] - sage: D.center_basis() # optional - sage.combinat sage.modules + sage: D.center_basis() (D{}, D{1} + D{1, 2} + D{2, 3} + D{3}, D{1, 2, 3} + D{1, 3} + D{2}) @@ -468,12 +475,13 @@ def centralizer(self, S): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.modules - sage: S = L.centralizer([a + b, 2*a + c]); S # optional - sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: a, b, c = L.lie_algebra_generators() + sage: S = L.centralizer([a + b, 2*a + c]); S An example of a finite dimensional Lie algebra with basis: the 3-dimensional abelian Lie algebra over Rational Field - sage: S.basis_matrix() # optional - sage.modules + sage: S.basis_matrix() [1 0 0] [0 1 0] [0 0 1] @@ -486,11 +494,12 @@ def center(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: Z = L.center(); Z # optional - sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: Z = L.center(); Z An example of a finite dimensional Lie algebra with basis: the 3-dimensional abelian Lie algebra over Rational Field - sage: Z.basis_matrix() # optional - sage.modules + sage: Z.basis_matrix() [1 0 0] [0 1 0] [0 0 1] @@ -517,8 +526,9 @@ def derivations_basis(self): We construct the derivations of the Heisenberg Lie algebra:: - sage: H = lie_algebras.Heisenberg(QQ, 1) # optional - sage.combinat sage.modules - sage: H.derivations_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: H = lie_algebras.Heisenberg(QQ, 1) + sage: H.derivations_basis() ( [1 0 0] [0 1 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [1 0 0] [0 1 0] [0 0 0] [0 0 0] @@ -527,8 +537,9 @@ def derivations_basis(self): We construct the derivations of `\mathfrak{sl}_2`:: - sage: sl2 = lie_algebras.sl(QQ, 2) # optional - sage.combinat sage.modules - sage: sl2.derivations_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: sl2 = lie_algebras.sl(QQ, 2) + sage: sl2.derivations_basis() ( [ 1 0 0] [ 0 1 0] [ 0 0 0] [ 0 0 0] [ 0 0 -1/2] [ 1 0 0] @@ -537,9 +548,10 @@ def derivations_basis(self): We verify these are derivations:: - sage: D = [sl2.module_morphism(matrix=M, codomain=sl2) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: D = [sl2.module_morphism(matrix=M, codomain=sl2) ....: for M in sl2.derivations_basis()] - sage: all(d(a.bracket(b)) == d(a).bracket(b) + a.bracket(d(b)) # optional - sage.combinat sage.modules + sage: all(d(a.bracket(b)) == d(a).bracket(b) + a.bracket(d(b)) ....: for a in sl2.basis() for b in sl2.basis() for d in D) True @@ -581,8 +593,9 @@ def inner_derivations_basis(self): EXAMPLES:: - sage: H = lie_algebras.Heisenberg(QQ, 1) # optional - sage.combinat sage.modules - sage: H.inner_derivations_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: H = lie_algebras.Heisenberg(QQ, 1) + sage: H.inner_derivations_basis() ( [0 0 0] [0 0 0] [0 0 0] [0 0 0] @@ -609,24 +622,26 @@ def subalgebra(self, *gens, **kwds): EXAMPLES:: - sage: H = lie_algebras.Heisenberg(QQ, 2) # optional - sage.combinat sage.modules - sage: p1,p2,q1,q2,z = H.basis() # optional - sage.combinat sage.modules - sage: S = H.subalgebra([p1, q1]) # optional - sage.combinat sage.modules - sage: S.basis().list() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: H = lie_algebras.Heisenberg(QQ, 2) + sage: p1,p2,q1,q2,z = H.basis() + sage: S = H.subalgebra([p1, q1]) + sage: S.basis().list() [p1, q1, z] - sage: S.basis_matrix() # optional - sage.combinat sage.modules + sage: S.basis_matrix() [1 0 0 0 0] [0 0 1 0 0] [0 0 0 0 1] Passing an extra category to a subalgebra:: - sage: L = LieAlgebra(QQ, 3, step=2) # optional - sage.combinat sage.modules - sage: x,y,z = L.homogeneous_component_basis(1) # optional - sage.combinat sage.modules - sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() # optional - sage.combinat sage.modules - sage: C = C.Subobjects().Graded().Stratified() # optional - sage.combinat sage.modules - sage: S = L.subalgebra([x, y], category=C) # optional - sage.combinat sage.modules - sage: S.homogeneous_component_basis(2).list() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, 3, step=2) + sage: x,y,z = L.homogeneous_component_basis(1) + sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() + sage: C = C.Subobjects().Graded().Stratified() + sage: S = L.subalgebra([x, y], category=C) + sage: S.homogeneous_component_basis(2).list() [X_12] """ from sage.algebras.lie_algebras.subalgebra import LieSubalgebra_finite_dimensional_with_basis @@ -648,21 +663,23 @@ def ideal(self, *gens, **kwds): EXAMPLES:: - sage: H = lie_algebras.Heisenberg(QQ, 2) # optional - sage.combinat sage.modules - sage: p1,p2,q1,q2,z = H.basis() # optional - sage.combinat sage.modules - sage: I = H.ideal([p1-p2, q1-q2]) # optional - sage.combinat sage.modules - sage: I.basis().list() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: H = lie_algebras.Heisenberg(QQ, 2) + sage: p1,p2,q1,q2,z = H.basis() + sage: I = H.ideal([p1 - p2, q1 - q2]) + sage: I.basis().list() [-p1 + p2, -q1 + q2, z] - sage: I.reduce(p1 + p2 + q1 + q2 + z) # optional - sage.combinat sage.modules + sage: I.reduce(p1 + p2 + q1 + q2 + z) 2*p1 + 2*q1 Passing an extra category to an ideal:: - sage: L. = LieAlgebra(QQ, abelian=True) # optional - sage.combinat sage.modules - sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() # optional - sage.combinat sage.modules - sage: C = C.Subobjects().Graded().Stratified() # optional - sage.combinat sage.modules - sage: I = L.ideal(x, y, category=C) # optional - sage.combinat sage.modules - sage: I.homogeneous_component_basis(1).list() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, abelian=True) + sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() + sage: C = C.Subobjects().Graded().Stratified() + sage: I = L.ideal(x, y, category=C) + sage: I.homogeneous_component_basis(1).list() [x, y] """ from sage.algebras.lie_algebras.subalgebra import LieSubalgebra_finite_dimensional_with_basis @@ -679,18 +696,19 @@ def is_ideal(self, A): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.combinat sage.modules - sage: I = L.ideal([2*a - c, b + c]) # optional - sage.combinat sage.modules - sage: I.is_ideal(L) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: a, b, c = L.lie_algebra_generators() + sage: I = L.ideal([2*a - c, b + c]) + sage: I.is_ideal(L) True - sage: L. = LieAlgebra(QQ, {('x','y'):{'x':1}}) # optional - sage.combinat sage.modules - sage: L.is_ideal(L) # optional - sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'):{'x':1}}) # needs sage.combinat sage.modules + sage: L.is_ideal(L) # needs sage.combinat sage.modules True - sage: F = LieAlgebra(QQ, 'F', representation='polynomial') # optional - sage.combinat sage.modules - sage: L.is_ideal(F) # optional - sage.combinat sage.modules + sage: F = LieAlgebra(QQ, 'F', representation='polynomial') # needs sage.combinat sage.modules + sage: L.is_ideal(F) # needs sage.combinat sage.modules Traceback (most recent call last): ... NotImplementedError: A must be a finite dimensional Lie algebra @@ -731,27 +749,29 @@ def quotient(self, I, names=None, category=None): The Engel Lie algebra as a quotient of the free nilpotent Lie algebra of step 3 with 2 generators:: - sage: L. = LieAlgebra(QQ, 2, step=3) # optional - sage.combinat sage.modules - sage: E = L.quotient(U); E # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, 2, step=3) + sage: E = L.quotient(U); E Lie algebra quotient L/I of dimension 4 over Rational Field where L: Free Nilpotent Lie algebra on 5 generators (X, Y, Z, W, U) over Rational Field I: Ideal (U) - sage: E.basis().list() # optional - sage.combinat sage.modules + sage: E.basis().list() [X, Y, Z, W] - sage: E(X).bracket(E(Y)) # optional - sage.combinat sage.modules + sage: E(X).bracket(E(Y)) Z - sage: Y.bracket(Z) # optional - sage.combinat sage.modules + sage: Y.bracket(Z) -U - sage: E(Y).bracket(E(Z)) # optional - sage.combinat sage.modules + sage: E(Y).bracket(E(Z)) 0 - sage: E(U) # optional - sage.combinat sage.modules + sage: E(U) 0 Quotients when the base ring is not a field are not implemented:: - sage: L = lie_algebras.Heisenberg(ZZ, 1) # optional - sage.combinat sage.modules - sage: L.quotient(L.an_element()) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.Heisenberg(ZZ, 1) + sage: L.quotient(L.an_element()) Traceback (most recent call last): ... NotImplementedError: quotients over non-fields not implemented @@ -773,43 +793,46 @@ def product_space(self, L, submodule=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: a,b,c = L.lie_algebra_generators() # optional - sage.combinat sage.modules - sage: X = L.subalgebra([a, b+c]) # optional - sage.combinat sage.modules - sage: L.product_space(X) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: a,b,c = L.lie_algebra_generators() + sage: X = L.subalgebra([a, b + c]) + sage: L.product_space(X) An example of a finite dimensional Lie algebra with basis: the 0-dimensional abelian Lie algebra over Rational Field with basis matrix: [] - sage: Y = L.subalgebra([a, 2*b-c]) # optional - sage.combinat sage.modules - sage: X.product_space(Y) # optional - sage.combinat sage.modules + sage: Y = L.subalgebra([a, 2*b - c]) + sage: X.product_space(Y) An example of a finite dimensional Lie algebra with basis: the 0-dimensional abelian Lie algebra over Rational Field with basis matrix: [] :: - sage: H = lie_algebras.Heisenberg(ZZ, 4) # optional - sage.combinat sage.modules - sage: Hp = H.product_space(H, submodule=True).basis() # optional - sage.combinat sage.modules - sage: [H.from_vector(v) for v in Hp] # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: H = lie_algebras.Heisenberg(ZZ, 4) + sage: Hp = H.product_space(H, submodule=True).basis() + sage: [H.from_vector(v) for v in Hp] [z] :: - sage: L. = LieAlgebra(QQ, {('x','y'):{'x':1}}) # optional - sage.combinat sage.modules - sage: Lp = L.product_space(L) # todo: not implemented - #17416 # optional - sage.combinat sage.modules - sage: Lp # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'):{'x':1}}) + sage: Lp = L.product_space(L) # not implemented + sage: Lp # not implemented Subalgebra generated of Lie algebra on 2 generators (x, y) over Rational Field with basis: (x,) - sage: Lp.product_space(L) # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: Lp.product_space(L) # not implemented Subalgebra generated of Lie algebra on 2 generators (x, y) over Rational Field with basis: (x,) - sage: L.product_space(Lp) # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: L.product_space(Lp) # not implemented Subalgebra generated of Lie algebra on 2 generators (x, y) over Rational Field with basis: (x,) - sage: Lp.product_space(Lp) # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: Lp.product_space(Lp) # not implemented Subalgebra generated of Lie algebra on 2 generators (x, y) over Rational Field with basis: () @@ -849,8 +872,9 @@ def derived_subalgebra(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.derived_subalgebra() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.derived_subalgebra() An example of a finite dimensional Lie algebra with basis: the 0-dimensional abelian Lie algebra over Rational Field with basis matrix: @@ -858,10 +882,11 @@ def derived_subalgebra(self): If ``self`` is semisimple, then the derived subalgebra is ``self``:: - sage: sl3 = LieAlgebra(QQ, cartan_type=['A', 2]) # optional - sage.combinat sage.modules - sage: sl3.derived_subalgebra() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: sl3 = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: sl3.derived_subalgebra() Lie algebra of ['A', 2] in the Chevalley basis - sage: sl3 is sl3.derived_subalgebra() # optional - sage.combinat sage.modules + sage: sl3 is sl3.derived_subalgebra() True """ @@ -900,8 +925,9 @@ def derived_series(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.derived_series() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.derived_series() (An example of a finite dimensional Lie algebra with basis: the 3-dimensional abelian Lie algebra over Rational Field, An example of a finite dimensional Lie algebra with basis: @@ -910,8 +936,9 @@ def derived_series(self): :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.derived_series() # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: L.derived_series() # not implemented (Lie algebra on 2 generators (x, y) over Rational Field, Subalgebra generated of Lie algebra on 2 generators (x, y) over Rational Field @@ -959,8 +986,9 @@ def lower_central_series(self, submodule=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.derived_series() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.derived_series() (An example of a finite dimensional Lie algebra with basis: the 3-dimensional abelian Lie algebra over Rational Field, An example of a finite dimensional Lie algebra with basis: @@ -969,16 +997,18 @@ def lower_central_series(self, submodule=False): The lower central series as submodules:: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.lower_central_series(submodule=True) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: L.lower_central_series(submodule=True) (Sparse vector space of dimension 2 over Rational Field, Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [1 0]) :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.lower_central_series() # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: L.lower_central_series() # not implemented (Lie algebra on 2 generators (x, y) over Rational Field, Subalgebra generated of Lie algebra on 2 generators (x, y) over Rational Field @@ -1001,14 +1031,16 @@ def is_abelian(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.is_abelian() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.is_abelian() True :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.is_abelian() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: L.is_abelian() False """ return len(self.structure_coefficients()) == 0 @@ -1024,14 +1056,16 @@ def is_solvable(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.is_solvable() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.is_solvable() True :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.is_solvable() # todo: not implemented - #17416 # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: L.is_solvable() # not implemented False """ return not self.derived_series()[-1].dimension() @@ -1045,8 +1079,9 @@ def is_nilpotent(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.is_nilpotent() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.is_nilpotent() True """ return not self.lower_central_series()[-1].dimension() @@ -1061,8 +1096,9 @@ def is_semisimple(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.is_semisimple() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.is_semisimple() False """ return not self.killing_form_matrix().is_singular() @@ -1107,24 +1143,27 @@ def chevalley_eilenberg_complex(self, M=None, dual=False, sparse=True, ncpus=Non EXAMPLES:: - sage: L = lie_algebras.sl(ZZ, 2) # optional - sage.combinat sage.modules - sage: C = L.chevalley_eilenberg_complex(); C # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.sl(ZZ, 2) + sage: C = L.chevalley_eilenberg_complex(); C Chain complex with at most 4 nonzero terms over Integer Ring - sage: ascii_art(C) # optional - sage.combinat sage.modules + sage: ascii_art(C) [ 2 0 0] [0] [ 0 -1 0] [0] [0 0 0] [ 0 0 2] [0] 0 <-- C_0 <-------- C_1 <----------- C_2 <---- C_3 <-- 0 - sage: L = LieAlgebra(QQ, cartan_type=['C',2]) # optional - sage.combinat sage.modules - sage: C = L.chevalley_eilenberg_complex() # long time # optional - sage.combinat sage.modules - sage: [C.free_module_rank(i) for i in range(11)] # long time # optional - sage.combinat sage.modules + sage: # long time, needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type=['C',2]) + sage: C = L.chevalley_eilenberg_complex() + sage: [C.free_module_rank(i) for i in range(11)] [1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1] - sage: g = lie_algebras.sl(QQ, 2) # optional - sage.combinat sage.modules - sage: E, F, H = g.basis() # optional - sage.combinat sage.modules - sage: n = g.subalgebra([F, H]) # optional - sage.combinat sage.modules - sage: ascii_art(n.chevalley_eilenberg_complex()) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: g = lie_algebras.sl(QQ, 2) + sage: E, F, H = g.basis() + sage: n = g.subalgebra([F, H]) + sage: ascii_art(n.chevalley_eilenberg_complex()) [0] [0 0] [2] 0 <-- C_0 <------ C_1 <---- C_2 <-- 0 @@ -1275,15 +1314,17 @@ def homology(self, deg=None, M=None, sparse=True, ncpus=None): EXAMPLES:: - sage: L = lie_algebras.cross_product(QQ) # optional - sage.combinat sage.modules - sage: L.homology() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.cross_product(QQ) + sage: L.homology() {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 0 over Rational Field, 2: Vector space of dimension 0 over Rational Field, 3: Vector space of dimension 1 over Rational Field} - sage: L = lie_algebras.pwitt(GF(5), 5) # optional - sage.combinat sage.libs.pari sage.modules - sage: L.homology() # optional - sage.combinat sage.libs.pari sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.pwitt(GF(5), 5) + sage: L.homology() {0: Vector space of dimension 1 over Finite Field of size 5, 1: Vector space of dimension 0 over Finite Field of size 5, 2: Vector space of dimension 1 over Finite Field of size 5, @@ -1291,9 +1332,10 @@ def homology(self, deg=None, M=None, sparse=True, ncpus=None): 4: Vector space of dimension 0 over Finite Field of size 5, 5: Vector space of dimension 1 over Finite Field of size 5} - sage: d = {('x', 'y'): {'y': 2}} # optional - sage.combinat sage.modules - sage: L. = LieAlgebra(ZZ, d) # optional - sage.combinat sage.modules - sage: L.homology() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: d = {('x', 'y'): {'y': 2}} + sage: L. = LieAlgebra(ZZ, d) + sage: L.homology() {0: Z, 1: Z x C2, 2: 0} .. SEEALSO:: @@ -1340,8 +1382,9 @@ def cohomology(self, deg=None, M=None, sparse=True, ncpus=None): EXAMPLES:: - sage: L = lie_algebras.so(QQ, 4) # optional - sage.combinat sage.modules - sage: L.cohomology() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.so(QQ, 4) + sage: L.cohomology() {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 0 over Rational Field, 2: Vector space of dimension 0 over Rational Field, @@ -1350,8 +1393,9 @@ def cohomology(self, deg=None, M=None, sparse=True, ncpus=None): 5: Vector space of dimension 0 over Rational Field, 6: Vector space of dimension 1 over Rational Field} - sage: L = lie_algebras.Heisenberg(QQ, 2) # optional - sage.combinat sage.modules - sage: L.cohomology() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.Heisenberg(QQ, 2) + sage: L.cohomology() {0: Vector space of dimension 1 over Rational Field, 1: Vector space of dimension 4 over Rational Field, 2: Vector space of dimension 5 over Rational Field, @@ -1359,9 +1403,10 @@ def cohomology(self, deg=None, M=None, sparse=True, ncpus=None): 4: Vector space of dimension 4 over Rational Field, 5: Vector space of dimension 1 over Rational Field} - sage: d = {('x', 'y'): {'y': 2}} # optional - sage.combinat sage.modules - sage: L. = LieAlgebra(ZZ, d) # optional - sage.combinat sage.modules - sage: L.cohomology() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: d = {('x', 'y'): {'y': 2}} + sage: L. = LieAlgebra(ZZ, d) + sage: L.cohomology() {0: Z, 1: Z, 2: C2} .. SEEALSO:: @@ -1382,13 +1427,14 @@ def as_finite_dimensional_algebra(self): EXAMPLES:: - sage: L = lie_algebras.cross_product(QQ) # optional - sage.combinat sage.modules - sage: x, y, z = L.basis() # optional - sage.combinat sage.modules - sage: F = L.as_finite_dimensional_algebra() # optional - sage.combinat sage.modules - sage: X, Y, Z = F.basis() # optional - sage.combinat sage.modules - sage: x.bracket(y) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.cross_product(QQ) + sage: x, y, z = L.basis() + sage: F = L.as_finite_dimensional_algebra() + sage: X, Y, Z = F.basis() + sage: x.bracket(y) Z - sage: X * Y # optional - sage.combinat sage.modules + sage: X * Y Z """ from sage.matrix.constructor import matrix @@ -1442,10 +1488,11 @@ def morphism(self, on_generators, codomain=None, base_map=None, check=True): A quotient type Lie algebra morphism :: - sage: L. = LieAlgebra(QQ, {('X','Y'): {'Z': 1}, # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('X','Y'): {'Z': 1}, ....: ('X','Z'): {'W': 1}}) - sage: K. = LieAlgebra(QQ, abelian=True) # optional - sage.combinat sage.modules - sage: L.morphism({X: A, Y: B}) # optional - sage.combinat sage.modules + sage: K. = LieAlgebra(QQ, abelian=True) + sage: L.morphism({X: A, Y: B}) Lie algebra morphism: From: Lie algebra on 4 generators (X, Y, Z, W) over Rational Field To: Abelian Lie algebra on 2 generators (A, B) over Rational Field @@ -1457,7 +1504,8 @@ def morphism(self, on_generators, codomain=None, base_map=None, check=True): The reverse map `A \mapsto X`, `B \mapsto Y` does not define a Lie algebra morphism, since `[A,B] = 0`, but `[X,Y] \neq 0`:: - sage: K.morphism({A:X, B: Y}) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: K.morphism({A:X, B: Y}) Traceback (most recent call last): ... ValueError: this does not define a Lie algebra morphism; @@ -1467,16 +1515,17 @@ def morphism(self, on_generators, codomain=None, base_map=None, check=True): on the coefficients, even though it's not a Lie algebra morphism (since it isn't linear):: - sage: R. = ZZ[] # optional - sage.combinat sage.modules - sage: K. = NumberField(x^2 + 1) # optional - sage.combinat sage.modules sage.rings.number_fields - sage: cc = K.hom([-i]) # optional - sage.combinat sage.modules sage.rings.number_fields - sage: L. = LieAlgebra(K, {('X','Y'): {'Z': 1}, # optional - sage.combinat sage.modules sage.rings.number_fields + sage: # needs sage.combinat sage.modules sage.rings.number_fields + sage: R. = ZZ[] + sage: K. = NumberField(x^2 + 1) + sage: cc = K.hom([-i]) + sage: L. = LieAlgebra(K, {('X','Y'): {'Z': 1}, ....: ('X','Z'): {'W': 1}}) - sage: M. = LieAlgebra(K, abelian=True) # optional - sage.combinat sage.modules sage.rings.number_fields - sage: phi = L.morphism({X: A, Y: B}, base_map=cc) # optional - sage.combinat sage.modules sage.rings.number_fields - sage: phi(X) # optional - sage.combinat sage.modules sage.rings.number_fields + sage: M. = LieAlgebra(K, abelian=True) + sage: phi = L.morphism({X: A, Y: B}, base_map=cc) + sage: phi(X) A - sage: phi(i*X) # optional - sage.combinat sage.modules sage.rings.number_fields + sage: phi(i*X) -i*A """ from sage.algebras.lie_algebras.morphism import LieAlgebraMorphism_from_generators @@ -1505,13 +1554,15 @@ def universal_polynomials(self): EXAMPLES:: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.universal_polynomials() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: L.universal_polynomials() Finite family {('x', 'x', 'y'): X01*X10 - X00*X11 + X00, ('y', 'x', 'y'): X10} - sage: L = LieAlgebra(QQ, cartan_type=['A',1]) # optional - sage.combinat sage.modules - sage: list(L.universal_polynomials()) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type=['A',1]) + sage: list(L.universal_polynomials()) [-2*X01*X10 + 2*X00*X11 - 2*X00, -2*X02*X10 + 2*X00*X12 + X01, -2*X02*X11 + 2*X01*X12 - 2*X02, @@ -1522,13 +1573,14 @@ def universal_polynomials(self): -2*X12*X20 + 2*X10*X22 + X21, -2*X12*X21 + 2*X11*X22 - 2*X22] - sage: L = LieAlgebra(QQ, cartan_type=['B', 2]) # optional - sage.combinat sage.modules - sage: al = RootSystem(['B', 2]).root_lattice().simple_roots() # optional - sage.combinat sage.modules - sage: k = list(L.basis().keys())[0] # optional - sage.combinat sage.modules - sage: UP = L.universal_polynomials() # long time # optional - sage.combinat sage.modules - sage: len(UP) # long time # optional - sage.combinat sage.modules + sage: # long time, needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: al = RootSystem(['B', 2]).root_lattice().simple_roots() + sage: k = list(L.basis().keys())[0] + sage: UP = L.universal_polynomials() + sage: len(UP) 450 - sage: UP[al[2], al[1], -al[1]] # long time # optional - sage.combinat sage.modules + sage: UP[al[2], al[1], -al[1]] X0_7*X4_1 - X0_1*X4_7 - 2*X0_7*X5_1 + 2*X0_1*X5_7 + X2_7*X7_1 - X2_1*X7_7 - X3_7*X8_1 + X3_1*X8_7 + X0_4 """ @@ -1582,12 +1634,13 @@ def universal_commutative_algebra(self): EXAMPLES:: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: A = L.universal_commutative_algebra() # optional - sage.combinat sage.modules - sage: a, b, c, d = A.gens() # optional - sage.combinat sage.modules - sage: a, b, c, d # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: A = L.universal_commutative_algebra() + sage: a, b, c, d = A.gens() + sage: a, b, c, d (X00bar, X01bar, 0, X11bar) - sage: a*d - a # optional - sage.combinat sage.modules + sage: a*d - a 0 """ P = list(self.universal_polynomials()) @@ -1638,6 +1691,7 @@ def casimir_element(self, order=2, UEA=None, force_generic=False): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: L = LieAlgebra(QQ, cartan_type=['A', 1]) sage: C = L.casimir_element(); C 1/8*b1^2 + 1/2*b0*b2 - 1/4*b1 @@ -1651,18 +1705,21 @@ def casimir_element(self, order=2, UEA=None, force_generic=False): sage: all(g * C == C * g for g in U.algebra_generators()) True + sage: # needs sage.combinat sage.modules sage: L = LieAlgebra(QQ, cartan_type=['B', 2]) sage: U = L.pbw_basis() sage: C = L.casimir_element(UEA=U) sage: all(g * C == C * g for g in U.algebra_generators()) True + sage: # needs sage.combinat sage.modules sage: L = LieAlgebra(QQ, cartan_type=['C', 3]) sage: U = L.pbw_basis() sage: C = L.casimir_element(UEA=U) sage: all(g * C == C * g for g in U.algebra_generators()) True + sage: # needs sage.combinat sage.modules sage: L = LieAlgebra(QQ, cartan_type=['A', 1]) sage: C4 = L.casimir_element(order=4, UEA=L.pbw_basis()); C4 4*PBW[alpha[1]]^2*PBW[-alpha[1]]^2 @@ -1672,12 +1729,14 @@ def casimir_element(self, order=2, UEA=None, force_generic=False): sage: all(g * C4 == C4 * g for g in L.pbw_basis().algebra_generators()) True + sage: # needs sage.combinat sage.modules sage: L = lie_algebras.Heisenberg(QQ, 2) sage: L.casimir_element() 0 TESTS:: + sage: # needs sage.combinat sage.modules sage: L = LieAlgebra(QQ, cartan_type=['A', 1]) sage: L.casimir_element(1) Traceback (most recent call last): @@ -1762,31 +1821,34 @@ def adjoint_matrix(self, sparse=False): # In #11111 (more or less) by using matr EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.an_element().adjoint_matrix() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.an_element().adjoint_matrix() [0 0 0] [0 0 0] [0 0 0] - sage: L.an_element().adjoint_matrix(sparse=True).is_sparse() # optional - sage.combinat sage.modules + sage: L.an_element().adjoint_matrix(sparse=True).is_sparse() True :: - sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: x.adjoint_matrix() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L. = LieAlgebra(QQ, {('x','y'): {'x':1}}) + sage: x.adjoint_matrix() [0 1] [0 0] - sage: y.adjoint_matrix() # optional - sage.combinat sage.modules + sage: y.adjoint_matrix() [-1 0] [ 0 0] We verify that this forms a representation:: - sage: sl3 = lie_algebras.sl(QQ, 3) # optional - sage.combinat sage.modules - sage: e1, e2 = sl3.e(1), sl3.e(2) # optional - sage.combinat sage.modules - sage: e12 = e1.bracket(e2) # optional - sage.combinat sage.modules - sage: E1, E2 = e1.adjoint_matrix(), e2.adjoint_matrix() # optional - sage.combinat sage.modules - sage: E1 * E2 - E2 * E1 == e12.adjoint_matrix() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: sl3 = lie_algebras.sl(QQ, 3) + sage: e1, e2 = sl3.e(1), sl3.e(2) + sage: e12 = e1.bracket(e2) + sage: E1, E2 = e1.adjoint_matrix(), e2.adjoint_matrix() + sage: E1 * E2 - E2 * E1 == e12.adjoint_matrix() True """ from sage.matrix.constructor import matrix @@ -1809,16 +1871,17 @@ def to_vector(self, order=None, sparse=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat sage.modules - sage: L.an_element().to_vector() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() + sage: L.an_element().to_vector() (0, 0, 0) - - sage: L.an_element().to_vector(sparse=True) # optional - sage.combinat sage.modules + sage: L.an_element().to_vector(sparse=True) (0, 0, 0) - sage: D = DescentAlgebra(QQ, 4).D() # optional - sage.combinat sage.modules - sage: L = LieAlgebra(associative=D) # optional - sage.combinat sage.modules - sage: L.an_element().to_vector() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.groupssage.modules + sage: D = DescentAlgebra(QQ, 4).D() + sage: L = LieAlgebra(associative=D) + sage: L.an_element().to_vector() (1, 1, 1, 1, 1, 1, 1, 1) TESTS: @@ -1826,13 +1889,14 @@ def to_vector(self, order=None, sparse=False): Check that the error raised agrees with the one from ``monomial_coefficients()`` (see :trac:`25007`):: - sage: L = lie_algebras.sp(QQ, 4, representation='matrix') # optional - sage.combinat sage.modules - sage: x = L.an_element() # optional - sage.combinat sage.modules - sage: x.monomial_coefficients() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.sp(QQ, 4, representation='matrix') + sage: x = L.an_element() + sage: x.monomial_coefficients() Traceback (most recent call last): ... NotImplementedError: the basis is not defined - sage: x.to_vector() # optional - sage.combinat sage.modules + sage: x.to_vector() Traceback (most recent call last): ... NotImplementedError: the basis is not defined @@ -1866,11 +1930,12 @@ def ambient(self): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() - sage: L = C.example() # optional - sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.combinat sage.modules - sage: S = L.subalgebra([2*a + b, b + c]) # optional - sage.combinat sage.modules - sage: S.ambient() == L # optional - sage.combinat sage.modules + sage: L = C.example() + sage: a, b, c = L.lie_algebra_generators() + sage: S = L.subalgebra([2*a + b, b + c]) + sage: S.ambient() == L True """ @@ -1881,11 +1946,12 @@ def basis_matrix(self): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: C = LieAlgebras(QQ).FiniteDimensional().WithBasis() - sage: L = C.example() # optional - sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # optional - sage.combinat sage.modules - sage: S = L.subalgebra([2*a + b, b + c]) # optional - sage.combinat sage.modules - sage: S.basis_matrix() # optional - sage.combinat sage.modules + sage: L = C.example() + sage: a, b, c = L.lie_algebra_generators() + sage: S = L.subalgebra([2*a + b, b + c]) + sage: S.basis_matrix() [ 1 0 -1/2] [ 0 1 1] """ diff --git a/src/sage/categories/finite_dimensional_modules_with_basis.py b/src/sage/categories/finite_dimensional_modules_with_basis.py index 573aec237a1..1462073c5f2 100644 --- a/src/sage/categories/finite_dimensional_modules_with_basis.py +++ b/src/sage/categories/finite_dimensional_modules_with_basis.py @@ -46,8 +46,8 @@ def gens(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, ['a', 'b', 'c']) # optional - sage.modules - sage: F.gens() # optional - sage.modules + sage: F = CombinatorialFreeModule(ZZ, ['a', 'b', 'c']) # needs sage.modules + sage: F.gens() # needs sage.modules (B['a'], B['b'], B['c']) """ return tuple(self.basis()) @@ -91,35 +91,38 @@ def annihilator(self, S, action=operator.mul, side='right', category=None): EXAMPLES:: - sage: F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F # optional - sage.modules + sage: # needs sage.modules + sage: F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver (containing the arrows a:x->y and b:x->y) over Rational Field - sage: x, y, a, b = F.basis() # optional - sage.modules - sage: A = F.annihilator([a + 3*b + 2*y]); A # optional - sage.modules + sage: x, y, a, b = F.basis() + sage: A = F.annihilator([a + 3*b + 2*y]); A Free module generated by {0} over Rational Field - sage: [b.lift() for b in A.basis()] # optional - sage.modules + sage: [b.lift() for b in A.basis()] [-1/2*a - 3/2*b + x] The category can be used to specify other properties of this subspace, like that this is a subalgebra:: - sage: center = F.annihilator(F.basis(), F.bracket, # optional - sage.modules + sage: # needs sage.modules + sage: center = F.annihilator(F.basis(), F.bracket, ....: category=Algebras(QQ).Subobjects()) - sage: (e,) = center.basis() # optional - sage.modules - sage: e.lift() # optional - sage.modules + sage: (e,) = center.basis() + sage: e.lift() x + y - sage: e * e == e # optional - sage.modules + sage: e * e == e True Taking annihilator is order reversing for inclusion:: - sage: A = F.annihilator([]); A .rename("A") # optional - sage.modules - sage: Ax = F.annihilator([x]); Ax .rename("Ax") # optional - sage.modules - sage: Ay = F.annihilator([y]); Ay .rename("Ay") # optional - sage.modules - sage: Axy = F.annihilator([x,y]); Axy.rename("Axy") # optional - sage.modules - sage: P = Poset(([A, Ax, Ay, Axy], attrcall("is_submodule"))) # optional - sage.combinat sage.graphs sage.modules - sage: sorted(P.cover_relations(), key=str) # optional - sage.combinat sage.graphs sage.modules + sage: # needs sage.modules + sage: A = F.annihilator([]); A .rename("A") + sage: Ax = F.annihilator([x]); Ax .rename("Ax") + sage: Ay = F.annihilator([y]); Ay .rename("Ay") + sage: Axy = F.annihilator([x,y]); Axy.rename("Axy") + sage: P = Poset(([A, Ax, Ay, Axy], attrcall("is_submodule"))) # needs sage.combinat sage.graphs + sage: sorted(P.cover_relations(), key=str) # needs sage.combinat sage.graphs [[Ax, A], [Axy, Ax], [Axy, Ay], [Ay, A]] """ return self.submodule(self.annihilator_basis(S, action, side), @@ -147,6 +150,7 @@ def annihilator_basis(self, S, action=operator.mul, side='right'): By default, the action is the standard `*` operation. So our first example is about an algebra:: + sage: # needs sage.graphs sage.modules sage: F = FiniteDimensionalAlgebrasWithBasis(QQ).example(); F An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver @@ -156,39 +160,40 @@ def annihilator_basis(self, S, action=operator.mul, side='right'): In this algebra, multiplication on the right by `x` annihilates all basis elements but `x`:: - sage: x*x, y*x, a*x, b*x + sage: x*x, y*x, a*x, b*x # needs sage.graphs sage.modules (x, 0, 0, 0) So the annihilator is the subspace spanned by `y`, `a`, and `b`:: - sage: F.annihilator_basis([x]) + sage: F.annihilator_basis([x]) # needs sage.graphs sage.modules (y, a, b) The same holds for `a` and `b`:: - sage: x*a, y*a, a*a, b*a + sage: x*a, y*a, a*a, b*a # needs sage.graphs sage.modules (a, 0, 0, 0) - sage: F.annihilator_basis([a]) + sage: F.annihilator_basis([a]) # needs sage.graphs sage.modules (y, a, b) On the other hand, `y` annihilates only `x`:: - sage: F.annihilator_basis([y]) + sage: F.annihilator_basis([y]) # needs sage.graphs sage.modules (x,) Here is a non trivial annihilator:: - sage: F.annihilator_basis([a + 3*b + 2*y]) + sage: F.annihilator_basis([a + 3*b + 2*y]) # needs sage.graphs sage.modules (-1/2*a - 3/2*b + x,) Let's check it:: - sage: (-1/2*a - 3/2*b + x) * (a + 3*b + 2*y) + sage: (-1/2*a - 3/2*b + x) * (a + 3*b + 2*y) # needs sage.graphs sage.modules 0 Doing the same calculations on the left exchanges the roles of `x` and `y`:: + sage: # needs sage.graphs sage.modules sage: F.annihilator_basis([y], side="left") (x, a, b) sage: F.annihilator_basis([a], side="left") @@ -197,28 +202,29 @@ def annihilator_basis(self, S, action=operator.mul, side='right'): (x, a, b) sage: F.annihilator_basis([x], side="left") (y,) - sage: F.annihilator_basis([a+3*b+2*x], side="left") + sage: F.annihilator_basis([a + 3*b + 2*x], side="left") (-1/2*a - 3/2*b + y,) By specifying an inner product, this method can be used to compute the orthogonal of a subspace:: + sage: # needs sage.graphs sage.modules sage: x,y,a,b = F.basis() sage: def scalar(u,v): ....: return vector([sum(u[i]*v[i] for i in F.basis().keys())]) - sage: F.annihilator_basis([x+y, a+b], scalar) + sage: F.annihilator_basis([x + y, a + b], scalar) (x - y, a - b) By specifying the standard Lie bracket as action, one can compute the commutator of a subspace of `F`:: - sage: F.annihilator_basis([a+b], action=F.bracket) + sage: F.annihilator_basis([a + b], action=F.bracket) # needs sage.graphs sage.modules (x + y, a, b) In particular one can compute a basis of the center of the algebra. In our example, it is reduced to the identity:: - sage: F.annihilator_basis(F.algebra_generators(), action=F.bracket) + sage: F.annihilator_basis(F.algebra_generators(), action=F.bracket) # needs sage.graphs sage.modules (x + y,) But see also @@ -252,13 +258,13 @@ def _dense_free_module(self, base_ring=None): EXAMPLES:: - sage: C = CombinatorialFreeModule(QQ['x'], ['a','b','c']); C # optional - sage.modules + sage: C = CombinatorialFreeModule(QQ['x'], ['a','b','c']); C # needs sage.modules Free module generated by {'a', 'b', 'c'} over Univariate Polynomial Ring in x over Rational Field - sage: C._dense_free_module() # optional - sage.modules + sage: C._dense_free_module() # needs sage.modules Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field - sage: C._dense_free_module(QQ['x,y']) # optional - sage.modules + sage: C._dense_free_module(QQ['x,y']) # needs sage.modules Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field """ @@ -273,11 +279,12 @@ def from_vector(self, vector, order=None, coerce=True): EXAMPLES:: - sage: p_mult = matrix([[0,0,0], [0,0,-1], [0,0,0]]) # optional - sage.modules - sage: q_mult = matrix([[0,0,1], [0,0,0], [0,0,0]]) # optional - sage.modules - sage: A = algebras.FiniteDimensional( # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: p_mult = matrix([[0,0,0], [0,0,-1], [0,0,0]]) + sage: q_mult = matrix([[0,0,1], [0,0,0], [0,0,0]]) + sage: A = algebras.FiniteDimensional( ....: QQ, [p_mult, q_mult, matrix(QQ, 3, 3)], 'p,q,z') - sage: A.from_vector(vector([1,0,2])) # optional - sage.combinat sage.modules + sage: A.from_vector(vector([1,0,2])) p + 2*z """ if order is None: @@ -313,42 +320,44 @@ def echelon_form(self, elements, row_reduced=False, order=None): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: V = X.echelon_form([x[0]-x[1], x[0]-x[2], x[1]-x[2]]); V # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") + sage: x = X.basis() + sage: V = X.echelon_form([x[0]-x[1], x[0]-x[2], x[1]-x[2]]); V [x[0] - x[2], x[1] - x[2]] - sage: matrix(list(map(vector, V))) # optional - sage.modules + sage: matrix(list(map(vector, V))) [ 1 0 -1] [ 0 1 -1] :: - sage: F = CombinatorialFreeModule(ZZ, [1,2,3,4]) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: elements = [B[1]-17*B[2]+6*B[3], B[1]-17*B[2]+B[4]] # optional - sage.modules - sage: F.echelon_form(elements) # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(ZZ, [1,2,3,4]) + sage: B = F.basis() + sage: elements = [B[1]-17*B[2]+6*B[3], B[1]-17*B[2]+B[4]] + sage: F.echelon_form(elements) [B[1] - 17*B[2] + B[4], 6*B[3] - B[4]] :: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: a,b,c = F.basis() # optional - sage.modules - sage: F.echelon_form([8*a+b+10*c, -3*a+b-c, a-b-c]) # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # needs sage.modules + sage: a,b,c = F.basis() # needs sage.modules + sage: F.echelon_form([8*a+b+10*c, -3*a+b-c, a-b-c]) # needs sage.modules [B['a'] + B['c'], B['b'] + 2*B['c']] :: sage: R. = QQ[] - sage: C = CombinatorialFreeModule(R, range(3), prefix='x') # optional - sage.modules - sage: x = C.basis() # optional - sage.modules - sage: C.echelon_form([x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]) # optional - sage.modules + sage: C = CombinatorialFreeModule(R, range(3), prefix='x') # needs sage.modules + sage: x = C.basis() # needs sage.modules + sage: C.echelon_form([x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]) # needs sage.modules sage.rings.function_field [x[0] - x[2], x[1] - x[2]] :: - sage: M = MatrixSpace(QQ, 3, 3) # optional - sage.modules - sage: A = M([[0, 0, 2], [0, 0, 0], [0, 0, 0]]) # optional - sage.modules - sage: M.echelon_form([A, A]) # optional - sage.modules + sage: M = MatrixSpace(QQ, 3, 3) # needs sage.modules + sage: A = M([[0, 0, 2], [0, 0, 0], [0, 0, 0]]) # needs sage.modules + sage: M.echelon_form([A, A]) # needs sage.modules [ [0 0 1] [0 0 0] @@ -359,8 +368,8 @@ def echelon_form(self, elements, row_reduced=False, order=None): We convert the input elements to ``self``:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.modules sage.combinat - sage: E.echelon_form([1, x + 2]) # optional - sage.modules sage.combinat + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: E.echelon_form([1, x + 2]) # needs sage.modules [1, x] """ # Make sure elements consists of elements of ``self`` @@ -411,36 +420,39 @@ def invariant_module(self, S, action=operator.mul, action_on_basis=None, We build the invariant module of the permutation representation of the symmetric group:: - sage: G = SymmetricGroup(3); G.rename('S3') # optional - sage.groups sage.modules - sage: M = FreeModule(ZZ, [1,2,3], prefix='M'); M.rename('M') # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: G = SymmetricGroup(3); G.rename('S3') + sage: M = FreeModule(ZZ, [1,2,3], prefix='M'); M.rename('M') sage: action = lambda g, x: M.term(g(x)) - sage: I = M.invariant_module(G, action_on_basis=action); I # optional - sage.groups sage.modules + sage: I = M.invariant_module(G, action_on_basis=action); I (S3)-invariant submodule of M - sage: I.basis() # optional - sage.groups sage.modules + sage: I.basis() Finite family {0: B[0]} - sage: [I.lift(b) for b in I.basis()] # optional - sage.groups sage.modules + sage: [I.lift(b) for b in I.basis()] [M[1] + M[2] + M[3]] - - sage: G.rename(); M.rename() # reset the names # optional - sage.groups sage.modules + sage: G.rename(); M.rename() # reset the names We can construct the invariant module of any module that has an action of ``S``. In this example, we consider the dihedral group `G = D_4` and the subgroup `H < G` of all rotations. We construct the `H`-invariant module of the group algebra `\QQ[G]`:: - sage: G = groups.permutation.Dihedral(4) # optional - sage.groups - sage: H = G.subgroup(G.gen(0)) # optional - sage.groups - sage: H # optional - sage.groups + sage: # needs sage.groups + sage: G = groups.permutation.Dihedral(4) + sage: H = G.subgroup(G.gen(0)) + sage: H Subgroup generated by [(1,2,3,4)] of (Dihedral group of order 8 as a permutation group) - sage: H.cardinality() # optional - sage.groups + sage: H.cardinality() 4 - sage: A = G.algebra(QQ) # optional - sage.groups sage.modules - sage: I = A.invariant_module(H) # optional - sage.groups sage.modules - sage: [I.lift(b) for b in I.basis()] # optional - sage.groups sage.modules + + sage: # needs sage.groups sage.modules + sage: A = G.algebra(QQ) + sage: I = A.invariant_module(H) + sage: [I.lift(b) for b in I.basis()] [() + (1,2,3,4) + (1,3)(2,4) + (1,4,3,2), (2,4) + (1,2)(3,4) + (1,3) + (1,4)(2,3)] - sage: all(h * I.lift(b) == I.lift(b) # optional - sage.groups sage.modules + sage: all(h * I.lift(b) == I.lift(b) ....: for b in I.basis() for h in H) True """ @@ -483,13 +495,14 @@ def twisted_invariant_module(self, G, chi, EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [1,2,3]) # optional - sage.groups sage.modules - sage: G = SymmetricGroup(3) # optional - sage.groups + sage: # needs sage.groups sage.modules + sage: M = CombinatorialFreeModule(QQ, [1,2,3]) + sage: G = SymmetricGroup(3) sage: def action(g,x): return(M.term(g(x))) # permute coordinates - sage: T = M.twisted_invariant_module(G, [2,0,-1], # optional - sage.groups sage.modules + sage: T = M.twisted_invariant_module(G, [2,0,-1], ....: action_on_basis=action) sage: import __main__; __main__.action = action - sage: TestSuite(T).run() # optional - sage.groups sage.modules + sage: TestSuite(T).run() """ if action_on_basis is not None: @@ -518,12 +531,13 @@ def dense_coefficient_list(self, order=None): EXAMPLES:: - sage: v = vector([0, -1, -3]) # optional - sage.modules - sage: v.dense_coefficient_list() # optional - sage.modules + sage: # needs sage.modules + sage: v = vector([0, -1, -3]) + sage: v.dense_coefficient_list() [0, -1, -3] - sage: v.dense_coefficient_list([2,1,0]) # optional - sage.modules + sage: v.dense_coefficient_list([2,1,0]) [-3, -1, 0] - sage: sorted(v.coefficients()) # optional - sage.modules + sage: sorted(v.coefficients()) [-3, -1] """ if order is None: @@ -539,11 +553,12 @@ def _vector_(self, order=None): EXAMPLES:: - sage: v = vector([0, -1, -3]) # optional - sage.modules - sage: v._vector_() # optional - sage.modules + sage: # needs sage.modules + sage: v = vector([0, -1, -3]) + sage: v._vector_() (0, -1, -3) - sage: C = CombinatorialFreeModule(QQ['x'], ['a','b','c']) # optional - sage.modules - sage: C.an_element()._vector_() # optional - sage.modules + sage: C = CombinatorialFreeModule(QQ['x'], ['a','b','c']) + sage: C.an_element()._vector_() (2, 2, 3) """ if order is None: @@ -581,31 +596,32 @@ def matrix(self, base_ring=None, side="left"): EXAMPLES:: - sage: X = CombinatorialFreeModule(ZZ, [1,2]); x = X.basis() # optional - sage.modules - sage: Y = CombinatorialFreeModule(ZZ, [3,4]); y = Y.basis() # optional - sage.modules - sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4], # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2]); x = X.basis() + sage: Y = CombinatorialFreeModule(ZZ, [3,4]); y = Y.basis() + sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4], ....: 2: 2*y[3] + 5*y[4]}.__getitem__, ....: codomain=Y) - sage: phi.matrix() # optional - sage.modules + sage: phi.matrix() [1 2] [3 5] - sage: phi.matrix(side="right") # optional - sage.modules + sage: phi.matrix(side="right") [1 3] [2 5] - sage: phi.matrix().parent() # optional - sage.modules + sage: phi.matrix().parent() # needs sage.modules Full MatrixSpace of 2 by 2 dense matrices over Integer Ring - sage: phi.matrix(QQ).parent() # optional - sage.modules + sage: phi.matrix(QQ).parent() # needs sage.modules Full MatrixSpace of 2 by 2 dense matrices over Rational Field The resulting matrix is immutable:: - sage: phi.matrix().is_mutable() # optional - sage.modules + sage: phi.matrix().is_mutable() # needs sage.modules False The zero morphism has a zero matrix:: - sage: Hom(X, Y).zero().matrix() # optional - sage.modules + sage: Hom(X, Y).zero().matrix() # needs sage.modules [0 0] [0 0] @@ -614,11 +630,11 @@ def matrix(self, base_ring=None, side="left"): Add support for morphisms where the codomain has a different base ring than the domain:: - sage: Y = CombinatorialFreeModule(QQ, [3,4]); y = Y.basis() # optional - sage.modules - sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4], # optional - sage.modules + sage: Y = CombinatorialFreeModule(QQ, [3,4]); y = Y.basis() # needs sage.modules + sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4], # needs sage.modules ....: 2: 2*y[3] + 5/2*y[4]}.__getitem__, ....: codomain=Y) - sage: phi.matrix().parent() # todo: not implemented # optional - sage.modules + sage: phi.matrix().parent() # not implemented # needs sage.modules Full MatrixSpace of 2 by 2 dense matrices over Rational Field This currently does not work because, in this case, @@ -626,20 +642,21 @@ def matrix(self, base_ring=None, side="left"): additive groups (i.e. the intersection of the categories of modules over `\ZZ` and over `\QQ`):: - sage: phi.parent().homset_category() # optional - sage.modules + sage: phi.parent().homset_category() # needs sage.modules Category of commutative additive semigroups - sage: phi.parent().homset_category() # todo: not implemented # optional - sage.modules + sage: phi.parent().homset_category() # not implemented, needs sage.modules Category of finite dimensional modules with basis over Integer Ring TESTS: Check that :trac:`23216` is fixed:: - sage: X = CombinatorialFreeModule(QQ, []) # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [1,2,3]) # optional - sage.modules - sage: Hom(X, Y).zero().matrix() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, []) + sage: Y = CombinatorialFreeModule(QQ, [1,2,3]) + sage: Hom(X, Y).zero().matrix() [] - sage: Hom(X, Y).zero().matrix().parent() # optional - sage.modules + sage: Hom(X, Y).zero().matrix().parent() Full MatrixSpace of 3 by 0 dense matrices over Rational Field """ if base_ring is None: @@ -668,42 +685,43 @@ def __invert__(self): EXAMPLES:: + sage: # needs sage.modules sage: category = FiniteDimensionalModulesWithBasis(ZZ) - sage: X = CombinatorialFreeModule(ZZ, [1,2], category=category); X.rename("X"); x = X.basis() # optional - sage.modules - sage: Y = CombinatorialFreeModule(ZZ, [3,4], category=category); Y.rename("Y"); y = Y.basis() # optional - sage.modules - sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4], 2: 2*y[3] + 5*y[4]}.__getitem__, # optional - sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2], category=category); X.rename("X"); x = X.basis() + sage: Y = CombinatorialFreeModule(ZZ, [3,4], category=category); Y.rename("Y"); y = Y.basis() + sage: phi = X.module_morphism(on_basis={1: y[3] + 3*y[4], 2: 2*y[3] + 5*y[4]}.__getitem__, ....: codomain=Y, category=category) - sage: psi = ~phi # optional - sage.modules - sage: psi # optional - sage.modules + sage: psi = ~phi + sage: psi Generic morphism: From: Y To: X - sage: psi.parent() # optional - sage.modules + sage: psi.parent() Set of Morphisms from Y to X in Category of finite dimensional modules with basis over Integer Ring - sage: psi(y[3]) # optional - sage.modules + sage: psi(y[3]) -5*B[1] + 3*B[2] - sage: psi(y[4]) # optional - sage.modules + sage: psi(y[4]) 2*B[1] - B[2] - sage: psi.matrix() # optional - sage.modules + sage: psi.matrix() [-5 2] [ 3 -1] - sage: psi(phi(x[1])), psi(phi(x[2])) # optional - sage.modules + sage: psi(phi(x[1])), psi(phi(x[2])) (B[1], B[2]) - sage: phi(psi(y[3])), phi(psi(y[4])) # optional - sage.modules + sage: phi(psi(y[3])), phi(psi(y[4])) (B[3], B[4]) We check that this function complains if the morphism is not invertible:: - sage: phi = X.module_morphism(on_basis={1: y[3] + y[4], 2: y[3] + y[4]}.__getitem__, # optional - sage.modules + sage: phi = X.module_morphism(on_basis={1: y[3] + y[4], 2: y[3] + y[4]}.__getitem__, # needs sage.modules ....: codomain=Y, category=category) - sage: ~phi # optional - sage.modules + sage: ~phi # needs sage.modules Traceback (most recent call last): ... RuntimeError: morphism is not invertible - sage: phi = X.module_morphism(on_basis={1: y[3] + y[4], 2: y[3] + 5*y[4]}.__getitem__, # optional - sage.modules + sage: phi = X.module_morphism(on_basis={1: y[3] + y[4], 2: y[3] + 5*y[4]}.__getitem__, # needs sage.modules ....: codomain=Y, category=category) - sage: ~phi # optional - sage.modules + sage: ~phi # needs sage.modules Traceback (most recent call last): ... RuntimeError: morphism is not invertible @@ -723,9 +741,9 @@ def kernel_basis(self): EXAMPLES:: - sage: SGA = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # optional - sage.groups sage.modules - sage: f.kernel_basis() # optional - sage.groups sage.modules + sage: SGA = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # needs sage.groups sage.modules + sage: f.kernel_basis() # needs sage.groups sage.modules ([1, 2, 3] - [3, 2, 1], [1, 3, 2] - [3, 2, 1], [2, 1, 3] - [3, 2, 1]) """ return tuple(map( self.domain().from_vector, @@ -737,12 +755,13 @@ def kernel(self): EXAMPLES:: - sage: SGA = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # optional - sage.groups sage.modules - sage: K = f.kernel() # optional - sage.groups sage.modules - sage: K # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: SGA = SymmetricGroupAlgebra(QQ, 3) + sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) + sage: K = f.kernel() + sage: K Free module generated by {0, 1, 2} over Rational Field - sage: K.ambient() # optional - sage.groups sage.modules + sage: K.ambient() Symmetric group algebra of order 3 over Rational Field """ D = self.domain() @@ -755,9 +774,9 @@ def image_basis(self): EXAMPLES:: - sage: SGA = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # optional - sage.groups sage.modules - sage: f.image_basis() # optional - sage.groups sage.modules + sage: SGA = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # needs sage.groups sage.modules + sage: f.image_basis() # needs sage.groups sage.modules ([1, 2, 3], [2, 3, 1], [3, 1, 2]) """ C = self.codomain() @@ -769,9 +788,9 @@ def image(self): EXAMPLES:: - sage: SGA = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups sage.modules - sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # optional - sage.groups sage.modules - sage: f.image() # optional - sage.groups sage.modules + sage: SGA = SymmetricGroupAlgebra(QQ, 3) # needs sage.groups sage.modules + sage: f = SGA.module_morphism(lambda x: SGA(x**2), codomain=SGA) # needs sage.groups sage.modules + sage: f.image() # needs sage.groups sage.modules Free module generated by {0, 1, 2} over Rational Field """ C = self.codomain() diff --git a/src/sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py b/src/sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py index d294ec75fae..78d801a5ef4 100644 --- a/src/sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py @@ -60,17 +60,18 @@ def _test_nilpotency(self, **options): EXAMPLES:: - sage: L = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, nilpotent=True) # optional - sage.combinat sage.modules - sage: L._test_nilpotency() # optional - sage.combinat sage.modules - sage: L = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, nilpotent=True) + sage: L._test_nilpotency() + sage: L = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, ....: nilpotent=True, step=3) - sage: L._test_nilpotency() # optional - sage.combinat sage.modules + sage: L._test_nilpotency() Traceback (most recent call last): ... AssertionError: claimed nilpotency step 3 does not match the actual nilpotency step 2 - sage: L = LieAlgebra(QQ, {('X','Y'): {'X': 1}}, nilpotent=True) # optional - sage.combinat sage.modules - sage: L._test_nilpotency() # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, {('X','Y'): {'X': 1}}, nilpotent=True) + sage: L._test_nilpotency() Traceback (most recent call last): ... AssertionError: final term of lower central series is non-zero @@ -101,29 +102,30 @@ def lie_group(self, name='G', **kwds): We define the Heisenberg group:: - sage: L = lie_algebras.Heisenberg(QQ, 1) # optional - sage.combinat sage.modules - sage: G = L.lie_group('G'); G # optional - sage.combinat sage.modules sage.symbolic + sage: L = lie_algebras.Heisenberg(QQ, 1) # needs sage.combinat sage.modules + sage: G = L.lie_group('G'); G # needs sage.combinat sage.modules sage.symbolic Lie group G of Heisenberg algebra of rank 1 over Rational Field We test multiplying elements of the group:: - sage: p, q, z = L.basis() # optional - sage.combinat sage.modules sage.symbolic - sage: g = G.exp(p); g # optional - sage.combinat sage.modules sage.symbolic + sage: # needs sage.combinat sage.modules sage.symbolic + sage: p, q, z = L.basis() + sage: g = G.exp(p); g exp(p1) - sage: h = G.exp(q); h # optional - sage.combinat sage.modules sage.symbolic + sage: h = G.exp(q); h exp(q1) - sage: g * h # optional - sage.combinat sage.modules sage.symbolic + sage: g * h exp(p1 + q1 + 1/2*z) We extend an element of the Lie algebra to a left-invariant vector field:: - sage: X = G.left_invariant_extension(2*p + 3*q, name='X'); X # optional - sage.combinat sage.modules sage.symbolic + sage: X = G.left_invariant_extension(2*p + 3*q, name='X'); X # needs sage.combinat sage.modules sage.symbolic Vector field X on the Lie group G of Heisenberg algebra of rank 1 over Rational Field - sage: X.at(G.one()).display() # optional - sage.combinat sage.modules sage.symbolic + sage: X.at(G.one()).display() # needs sage.combinat sage.modules sage.symbolic X = 2 ∂/∂x_0 + 3 ∂/∂x_1 - sage: X.display() # optional - sage.combinat sage.modules sage.symbolic + sage: X.display() # needs sage.combinat sage.modules sage.symbolic X = 2 ∂/∂x_0 + 3 ∂/∂x_1 + (3/2*x_0 - x_1) ∂/∂x_2 .. SEEALSO:: @@ -139,11 +141,12 @@ def step(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, nilpotent=True) # optional - sage.combinat sage.modules - sage: L.step() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, nilpotent=True) + sage: L.step() 2 - sage: sc = {('X','Y'): {'Z': 1}, ('X','Z'): {'W': 1}} # optional - sage.combinat sage.modules - sage: LieAlgebra(QQ, sc, nilpotent=True).step() # optional - sage.combinat sage.modules + sage: sc = {('X','Y'): {'Z': 1}, ('X','Z'): {'W': 1}} + sage: LieAlgebra(QQ, sc, nilpotent=True).step() 3 """ if not hasattr(self, '_step'): @@ -156,8 +159,8 @@ def is_nilpotent(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, {('x','y'): {'z': 1}}, nilpotent=True) # optional - sage.combinat sage.modules - sage: L.is_nilpotent() # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, {('x','y'): {'z': 1}}, nilpotent=True) # needs sage.combinat sage.modules + sage: L.is_nilpotent() # needs sage.combinat sage.modules True """ return True diff --git a/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py b/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py index 56303fc5eb0..531ee7145a4 100644 --- a/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py @@ -49,13 +49,13 @@ def radical_basis(self, **keywords): EXAMPLES:: - sage: A = SymmetricGroup(4).algebra(QQ) # optional - sage.groups sage.modules - sage: A.radical_basis() # optional - sage.groups sage.modules + sage: A = SymmetricGroup(4).algebra(QQ) # needs sage.groups sage.modules + sage: A.radical_basis() # needs sage.groups sage.modules () TESTS:: - sage: A.radical_basis.__module__ # optional - sage.groups sage.modules + sage: A.radical_basis.__module__ # needs sage.groups sage.modules 'sage.categories.finite_dimensional_semisimple_algebras_with_basis' """ return () @@ -81,25 +81,27 @@ def central_orthogonal_idempotents(self): acts on `V_i` as multiplication by the `i`-th power of a cube root of unity:: - sage: R = CyclotomicField(3) # optional - sage.rings.number_field - sage: A3 = AlternatingGroup(3).algebra(R) # optional - sage.rings.number_field sage.groups - sage: idempotents = A3.central_orthogonal_idempotents() # optional - sage.rings.number_field sage.groups - sage: idempotents # optional - sage.rings.number_field sage.groups + sage: # needs sage.groups sage.rings.number_field + sage: R = CyclotomicField(3) + sage: A3 = AlternatingGroup(3).algebra(R) + sage: idempotents = A3.central_orthogonal_idempotents() + sage: idempotents (1/3*() + 1/3*(1,2,3) + 1/3*(1,3,2), 1/3*() - (1/3*zeta3+1/3)*(1,2,3) - (-1/3*zeta3)*(1,3,2), 1/3*() - (-1/3*zeta3)*(1,2,3) - (1/3*zeta3+1/3)*(1,3,2)) - sage: A3.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # optional - sage.rings.number_field sage.groups + sage: A3.is_identity_decomposition_into_orthogonal_idempotents(idempotents) True For the semisimple quotient of a quiver algebra, we recover the vertices of the quiver:: - sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example(); A # optional - sage.combinat + sage: # needs sage.graphs sage.modules + sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example(); A An example of a finite dimensional algebra with basis: the path algebra of the Kronecker quiver (containing the arrows a:x->y and b:x->y) over Rational Field - sage: Aquo = A.semisimple_quotient() # optional - sage.combinat - sage: Aquo.central_orthogonal_idempotents() # optional - sage.combinat + sage: Aquo = A.semisimple_quotient() + sage: Aquo.central_orthogonal_idempotents() (B['x'], B['y']) """ return tuple([x.lift() @@ -157,8 +159,8 @@ def _orthogonal_decomposition(self, generators=None): center of the algebra of the symmetric group `S_4`:: - sage: Z4 = SymmetricGroup(4).algebra(QQ).center() # optional - sage.groups sage.modules - sage: Z4._orthogonal_decomposition() # optional - sage.groups sage.modules + sage: Z4 = SymmetricGroup(4).algebra(QQ).center() # needs sage.groups sage.modules + sage: Z4._orthogonal_decomposition() # needs sage.groups sage.modules (B[0] + B[1] + B[2] + B[3] + B[4], B[0] + 1/3*B[1] - 1/3*B[2] - 1/3*B[4], B[0] + B[2] - 1/2*B[3], @@ -201,7 +203,7 @@ def _orthogonal_decomposition(self, generators=None): for subalgebra in subalgebras for idempotent in subalgebra._orthogonal_decomposition()]) # TODO: Should this be an assertion check? - raise Exception("Unable to fully decompose %s!"%self) + raise Exception("Unable to fully decompose %s!" % self) @cached_method def central_orthogonal_idempotents(self): @@ -219,10 +221,11 @@ def central_orthogonal_idempotents(self): EXAMPLES:: - sage: A4 = SymmetricGroup(4).algebra(QQ) # optional - sage.groups sage.modules - sage: Z4 = A4.center() # optional - sage.groups sage.modules - sage: idempotents = Z4.central_orthogonal_idempotents() # optional - sage.groups sage.modules - sage: idempotents # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A4 = SymmetricGroup(4).algebra(QQ) + sage: Z4 = A4.center() + sage: idempotents = Z4.central_orthogonal_idempotents() + sage: idempotents (1/24*B[0] + 1/24*B[1] + 1/24*B[2] + 1/24*B[3] + 1/24*B[4], 3/8*B[0] + 1/8*B[1] - 1/8*B[2] - 1/8*B[4], 1/6*B[0] + 1/6*B[2] - 1/12*B[3], @@ -233,7 +236,7 @@ def central_orthogonal_idempotents(self): recognize among them the sum and alternating sum of all permutations:: - sage: [e.lift() for e in idempotents] # optional - sage.groups sage.modules + sage: [e.lift() for e in idempotents] # needs sage.groups sage.modules [1/24*() + 1/24*(3,4) + 1/24*(2,3) + 1/24*(2,3,4) + 1/24*(2,4,3) + 1/24*(2,4) + 1/24*(1,2) + 1/24*(1,2)(3,4) + 1/24*(1,2,3) + 1/24*(1,2,3,4) + 1/24*(1,2,4,3) + 1/24*(1,2,4) + 1/24*(1,3,2) @@ -251,7 +254,7 @@ def central_orthogonal_idempotents(self): We check that they indeed form a decomposition of the identity of `Z_4` into orthogonal idempotents:: - sage: Z4.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # optional - sage.groups sage.modules + sage: Z4.is_identity_decomposition_into_orthogonal_idempotents(idempotents) # needs sage.groups sage.modules True """ return tuple([(e.leading_coefficient()/(e*e).leading_coefficient())*e diff --git a/src/sage/categories/finite_enumerated_sets.py b/src/sage/categories/finite_enumerated_sets.py index 4d90a3cd3f9..8a3c0e42ca5 100644 --- a/src/sage/categories/finite_enumerated_sets.py +++ b/src/sage/categories/finite_enumerated_sets.py @@ -59,9 +59,9 @@ def _call_(self, X): EXAMPLES:: - sage: FiniteEnumeratedSets()(GF(3)) # optional - sage.rings.finite_rings + sage: FiniteEnumeratedSets()(GF(3)) Finite Field of size 3 - sage: Partitions(3) # optional - sage.combinat + sage: Partitions(3) # needs sage.combinat Partitions of the integer 3 For now, lists, tuples, sets, Sets are coerced into finite @@ -86,9 +86,9 @@ def __len__(self): EXAMPLES:: - sage: len(GF(5)) # optional - sage.rings.finite_rings + sage: len(GF(5)) 5 - sage: len(MatrixSpace(GF(2), 3, 3)) # optional - sage.rings.finite_rings sage.modules + sage: len(MatrixSpace(GF(2), 3, 3)) # needs sage.modules 512 """ return int(self.cardinality()) @@ -524,7 +524,7 @@ def _last_from_unrank(self): sage: C._last_from_unrank() 3 """ - return self.unrank(self.cardinality() -1) + return self.unrank(self.cardinality() - 1) def _test_enumerated_set_iter_cardinality(self, **options): """ @@ -590,17 +590,17 @@ class ParentMethods: inherit various methods from `Sets.CartesianProducts` and not from :class:`EnumeratedSets.Finite`:: - sage: C = cartesian_product([Partitions(10), Permutations(20)]) # optional - sage.combinat - sage: C in EnumeratedSets().Finite() # optional - sage.combinat + sage: C = cartesian_product([Partitions(10), Permutations(20)]) # needs sage.combinat + sage: C in EnumeratedSets().Finite() # needs sage.combinat True - sage: C.random_element.__module__ # optional - sage.combinat + sage: C.random_element.__module__ # needs sage.combinat 'sage.categories.sets_cat' - sage: C.cardinality.__module__ # optional - sage.combinat + sage: C.cardinality.__module__ # needs sage.combinat 'sage.categories.sets_cat' - sage: C.__iter__.__module__ # optional - sage.combinat + sage: C.__iter__.__module__ # needs sage.combinat 'sage.categories.sets_cat' """ random_element = raw_getattr(Sets.CartesianProducts.ParentMethods, "random_element") @@ -613,9 +613,9 @@ def last(self): EXAMPLES:: - sage: C = cartesian_product([Zmod(42), Partitions(10), # optional - sage.combinat + sage: C = cartesian_product([Zmod(42), Partitions(10), # needs sage.combinat ....: IntegerRange(5)]) - sage: C.last() # optional - sage.combinat + sage: C.last() # needs sage.combinat (41, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 4) """ return self._cartesian_product_of_elements( @@ -636,13 +636,13 @@ def rank(self, x): EXAMPLES:: - sage: C = cartesian_product([GF(2), GF(11), GF(7)]) # optional - sage.rings.finite_rings - sage: C.rank(C((1,2,5))) # optional - sage.rings.finite_rings + sage: C = cartesian_product([GF(2), GF(11), GF(7)]) + sage: C.rank(C((1,2,5))) 96 - sage: C.rank(C((0,0,0))) # optional - sage.rings.finite_rings + sage: C.rank(C((0,0,0))) 0 - sage: for c in C: print(C.rank(c)) # optional - sage.rings.finite_rings + sage: for c in C: print(C.rank(c)) 0 1 2 @@ -655,14 +655,15 @@ def rank(self, x): 152 153 + sage: # needs sage.combinat sage: F1 = FiniteEnumeratedSet('abcdefgh') sage: F2 = IntegerRange(250) - sage: F3 = Partitions(20) # optional - sage.combinat - sage: C = cartesian_product([F1, F2, F3]) # optional - sage.combinat - sage: c = C(('a', 86, [7,5,4,4])) # optional - sage.combinat - sage: C.rank(c) # optional - sage.combinat + sage: F3 = Partitions(20) + sage: C = cartesian_product([F1, F2, F3]) + sage: c = C(('a', 86, [7,5,4,4])) + sage: C.rank(c) 54213 - sage: C.unrank(54213) # optional - sage.combinat + sage: C.unrank(54213) ('a', 86, [7, 5, 4, 4]) """ from builtins import zip @@ -692,18 +693,18 @@ def unrank(self, i): EXAMPLES:: - sage: C = cartesian_product([GF(3), GF(11), GF(7), GF(5)]) # optional - sage.rings.finite_rings - sage: c = C.unrank(123); c # optional - sage.rings.finite_rings + sage: C = cartesian_product([GF(3), GF(11), GF(7), GF(5)]) + sage: c = C.unrank(123); c (0, 3, 3, 3) - sage: C.rank(c) # optional - sage.rings.finite_rings + sage: C.rank(c) 123 - sage: c = C.unrank(857); c # optional - sage.rings.finite_rings + sage: c = C.unrank(857); c (2, 2, 3, 2) - sage: C.rank(c) # optional - sage.rings.finite_rings + sage: C.rank(c) 857 - sage: C.unrank(2500) # optional - sage.rings.finite_rings + sage: C.unrank(2500) Traceback (most recent call last): ... IndexError: index i (=2) is greater than the cardinality diff --git a/src/sage/categories/finite_fields.py b/src/sage/categories/finite_fields.py index b685a249780..d9333c80707 100644 --- a/src/sage/categories/finite_fields.py +++ b/src/sage/categories/finite_fields.py @@ -34,7 +34,7 @@ class FiniteFields(CategoryWithAxiom): Some examples of membership testing and coercion:: - sage: FiniteField(17) in K # optional - sage.rings.finite_rings + sage: FiniteField(17) in K True sage: RationalField() in K False @@ -67,7 +67,7 @@ def __contains__(self, x): """ EXAMPLES:: - sage: GF(4, "a") in FiniteFields() # optional - sage.rings.finite_rings + sage: GF(4, "a") in FiniteFields() # needs sage.rings.finite_rings True sage: QQ in FiniteFields() False @@ -82,14 +82,14 @@ def _call_(self, x): """ EXAMPLES:: - sage: FiniteFields()(GF(4, "a")) # optional - sage.rings.finite_rings + sage: FiniteFields()(GF(4, "a")) # needs sage.rings.finite_rings Finite Field in a of size 2^2 sage: FiniteFields()(RationalField()) # indirect doctest Traceback (most recent call last): ... TypeError: unable to canonically associate a finite field to Rational Field """ - raise TypeError("unable to canonically associate a finite field to %s"%x) + raise TypeError("unable to canonically associate a finite field to %s" % x) # TODO: local dvr ring? class ParentMethods: diff --git a/src/sage/categories/finite_groups.py b/src/sage/categories/finite_groups.py index 1d0e7d72357..7461f6fabfd 100644 --- a/src/sage/categories/finite_groups.py +++ b/src/sage/categories/finite_groups.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups +# sage.doctest: needs sage.groups r""" Finite groups """ @@ -166,7 +166,7 @@ def conjugacy_classes(self): ... NotImplementedError: Listing the conjugacy classes for group is not implemented """ - raise NotImplementedError("Listing the conjugacy classes for group %s is not implemented"%self) + raise NotImplementedError("Listing the conjugacy classes for group %s is not implemented" % self) def conjugacy_classes_representatives(self): r""" diff --git a/src/sage/categories/finite_lattice_posets.py b/src/sage/categories/finite_lattice_posets.py index 1bb0de98fad..96f2385404c 100644 --- a/src/sage/categories/finite_lattice_posets.py +++ b/src/sage/categories/finite_lattice_posets.py @@ -49,8 +49,8 @@ def join_irreducibles(self): EXAMPLES:: - sage: L = LatticePoset({0:[1,2],1:[3],2:[3,4],3:[5],4:[5]}) # optional - sage.combinat sage.graphs - sage: L.join_irreducibles() # optional - sage.combinat sage.graphs + sage: L = LatticePoset({0:[1,2],1:[3],2:[3,4],3:[5],4:[5]}) # needs sage.graphs sage.modules + sage: L.join_irreducibles() # needs sage.graphs sage.modules [1, 2, 4] .. SEEALSO:: @@ -71,8 +71,8 @@ def join_irreducibles_poset(self): EXAMPLES:: - sage: L = LatticePoset({0:[1,2,3],1:[4],2:[4],3:[4]}) # optional - sage.combinat sage.graphs - sage: L.join_irreducibles_poset() # optional - sage.combinat sage.graphs + sage: L = LatticePoset({0:[1,2,3],1:[4],2:[4],3:[4]}) # needs sage.graphs sage.modules + sage: L.join_irreducibles_poset() # needs sage.graphs sage.modules Finite poset containing 3 elements .. SEEALSO:: @@ -92,8 +92,8 @@ def meet_irreducibles(self): EXAMPLES:: - sage: L = LatticePoset({0:[1,2],1:[3],2:[3,4],3:[5],4:[5]}) # optional - sage.combinat sage.graphs - sage: L.meet_irreducibles() # optional - sage.combinat sage.graphs + sage: L = LatticePoset({0:[1,2],1:[3],2:[3,4],3:[5],4:[5]}) # needs sage.graphs sage.modules + sage: L.meet_irreducibles() # needs sage.graphs sage.modules [1, 3, 4] .. SEEALSO:: @@ -114,8 +114,8 @@ def meet_irreducibles_poset(self): EXAMPLES:: - sage: L = LatticePoset({0:[1,2,3],1:[4],2:[4],3:[4]}) # optional - sage.combinat sage.graphs - sage: L.join_irreducibles_poset() # optional - sage.combinat sage.graphs + sage: L = LatticePoset({0:[1,2,3],1:[4],2:[4],3:[4]}) # needs sage.graphs sage.modules + sage: L.join_irreducibles_poset() # needs sage.graphs sage.modules Finite poset containing 3 elements .. SEEALSO:: @@ -143,20 +143,21 @@ def irreducibles_poset(self): EXAMPLES:: - sage: L = LatticePoset({1: [2, 3, 4], 2: [5, 6], 3: [5], # optional - sage.combinat sage.graphs + sage: # needs sage.combinat sage.graphs sage.modules + sage: L = LatticePoset({1: [2, 3, 4], 2: [5, 6], 3: [5], ....: 4: [6], 5: [9, 7], 6: [9, 8], 7: [10], ....: 8: [10], 9: [10], 10: [11]}) - sage: L_ = L.irreducibles_poset() # optional - sage.combinat sage.graphs - sage: sorted(L_) # optional - sage.combinat sage.graphs + sage: L_ = L.irreducibles_poset() + sage: sorted(L_) [2, 3, 4, 7, 8, 9, 10, 11] - sage: L_.completion_by_cuts().is_isomorphic(L) # optional - sage.combinat sage.graphs + sage: L_.completion_by_cuts().is_isomorphic(L) True TESTS:: - sage: LatticePoset().irreducibles_poset() # optional - sage.combinat sage.graphs + sage: LatticePoset().irreducibles_poset() # needs sage.graphs Finite poset containing 0 elements - sage: posets.ChainPoset(1).irreducibles_poset() # optional - sage.combinat sage.graphs + sage: posets.ChainPoset(1).irreducibles_poset() # needs sage.graphs Finite poset containing 1 elements """ if self.cardinality() == 1: @@ -191,36 +192,36 @@ def is_lattice_morphism(self, f, codomain): lattice of divisors of `60`, and check that the map `b \mapsto 5 \prod_{x\in b} x` is a morphism of lattices:: - sage: D = LatticePoset((divisors(60), attrcall("divides"))) # optional - sage.combinat sage.graphs - sage: B = LatticePoset((Subsets([2,2,3]), attrcall("issubset"))) # optional - sage.combinat sage.graphs - sage: def f(b): return D(5*prod(b)) # optional - sage.combinat sage.graphs - sage: B.is_lattice_morphism(f, D) # optional - sage.combinat sage.graphs + sage: D = LatticePoset((divisors(60), attrcall("divides"))) # needs sage.graphs sage.modules + sage: B = LatticePoset((Subsets([2,2,3]), attrcall("issubset"))) # needs sage.graphs sage.modules + sage: def f(b): return D(5*prod(b)) + sage: B.is_lattice_morphism(f, D) # needs sage.graphs sage.modules True We construct the boolean lattice `B_2`:: - sage: B = posets.BooleanLattice(2) # optional - sage.combinat sage.graphs - sage: B.cover_relations() # optional - sage.combinat sage.graphs + sage: B = posets.BooleanLattice(2) # needs sage.graphs + sage: B.cover_relations() # needs sage.graphs [[0, 1], [0, 2], [1, 3], [2, 3]] And the same lattice with new top and bottom elements numbered respectively `-1` and `3`:: - sage: G = DiGraph({-1:[0], 0:[1,2], 1:[3], 2:[3], 3:[4]}) # optional - sage.graphs - sage: L = LatticePoset(G) # optional - sage.combinat sage.graphs - sage: L.cover_relations() # optional - sage.combinat sage.graphs + sage: G = DiGraph({-1:[0], 0:[1,2], 1:[3], 2:[3], 3:[4]}) # needs sage.graphs + sage: L = LatticePoset(G) # needs sage.graphs sage.modules + sage: L.cover_relations() # needs sage.graphs sage.modules [[-1, 0], [0, 1], [0, 2], [1, 3], [2, 3], [3, 4]] - sage: f = {B(0): L(0), B(1): L(1), B(2): L(2), B(3): L(3)}.__getitem__ # optional - sage.combinat sage.graphs - sage: B.is_lattice_morphism(f, L) # optional - sage.combinat sage.graphs + sage: f = {B(0): L(0), B(1): L(1), B(2): L(2), B(3): L(3)}.__getitem__ # needs sage.graphs sage.modules + sage: B.is_lattice_morphism(f, L) # needs sage.graphs sage.modules True - sage: f = {B(0): L(-1),B(1): L(1), B(2): L(2), B(3): L(3)}.__getitem__ # optional - sage.combinat sage.graphs - sage: B.is_lattice_morphism(f, L) # optional - sage.combinat sage.graphs + sage: f = {B(0): L(-1),B(1): L(1), B(2): L(2), B(3): L(3)}.__getitem__ # needs sage.graphs sage.modules + sage: B.is_lattice_morphism(f, L) # needs sage.graphs sage.modules False - sage: f = {B(0): L(0), B(1): L(1), B(2): L(2), B(3): L(4)}.__getitem__ # optional - sage.combinat sage.graphs - sage: B.is_lattice_morphism(f, L) # optional - sage.combinat sage.graphs + sage: f = {B(0): L(0), B(1): L(1), B(2): L(2), B(3): L(4)}.__getitem__ # needs sage.graphs sage.modules + sage: B.is_lattice_morphism(f, L) # needs sage.graphs sage.modules False .. SEEALSO:: diff --git a/src/sage/categories/finite_monoids.py b/src/sage/categories/finite_monoids.py index 9531b671249..b446dc925cb 100644 --- a/src/sage/categories/finite_monoids.py +++ b/src/sage/categories/finite_monoids.py @@ -72,9 +72,9 @@ def nerve(self): The nerve (classifying space) of the cyclic group of order 2 is infinite-dimensional real projective space. :: - sage: Sigma2 = groups.permutation.Cyclic(2) # optional - sage.groups - sage: BSigma2 = Sigma2.nerve() # optional - sage.groups - sage: BSigma2.cohomology(4, base_ring=GF(2)) # optional - sage.groups sage.modules sage.rings.finite_rings + sage: Sigma2 = groups.permutation.Cyclic(2) # needs sage.groups + sage: BSigma2 = Sigma2.nerve() # needs sage.groups + sage: BSigma2.cohomology(4, base_ring=GF(2)) # needs sage.groups sage.modules Vector space of dimension 1 over Finite Field of size 2 The `k`-simplices of the nerve are named after the chains @@ -83,29 +83,30 @@ def nerve(self): element) and ``(1,2)`` in Sage. So the 1-cells and 2-cells in `B\Sigma_2` are:: - sage: BSigma2.n_cells(1) # optional - sage.groups + sage: BSigma2.n_cells(1) # needs sage.groups [(1,2)] - sage: BSigma2.n_cells(2) # optional - sage.groups + sage: BSigma2.n_cells(2) # needs sage.groups [(1,2) * (1,2)] Another construction of the group, with different names for its elements:: - sage: C2 = groups.misc.MultiplicativeAbelian([2]) # optional - sage.groups - sage: BC2 = C2.nerve() # optional - sage.groups - sage: BC2.n_cells(0) # optional - sage.groups + sage: # needs sage.groups + sage: C2 = groups.misc.MultiplicativeAbelian([2]) + sage: BC2 = C2.nerve() + sage: BC2.n_cells(0) [1] - sage: BC2.n_cells(1) # optional - sage.groups + sage: BC2.n_cells(1) [f] - sage: BC2.n_cells(2) # optional - sage.groups + sage: BC2.n_cells(2) [f * f] With mod `p` coefficients, `B \Sigma_p` should have its first nonvanishing homology group in dimension `p`:: - sage: Sigma3 = groups.permutation.Symmetric(3) # optional - sage.groups - sage: BSigma3 = Sigma3.nerve() # optional - sage.groups - sage: BSigma3.homology(range(4), base_ring=GF(3)) # optional - sage.groups sage.rings.finite_rings + sage: Sigma3 = groups.permutation.Symmetric(3) # needs sage.groups + sage: BSigma3 = Sigma3.nerve() # needs sage.groups + sage: BSigma3.homology(range(4), base_ring=GF(3)) # needs sage.groups {0: Vector space of dimension 0 over Finite Field of size 3, 1: Vector space of dimension 0 over Finite Field of size 3, 2: Vector space of dimension 0 over Finite Field of size 3, @@ -115,13 +116,13 @@ def nerve(self): `B\Sigma_2` for relatively large values of `n`, while for `B\Sigma_3`, the complexes get large pretty quickly:: - sage: Sigma2.nerve().n_skeleton(14) # optional - sage.groups + sage: # needs sage.groups + sage: Sigma2.nerve().n_skeleton(14) Simplicial set with 15 non-degenerate simplices - - sage: BSigma3 = Sigma3.nerve() # optional - sage.groups - sage: BSigma3.n_skeleton(3) # optional - sage.groups + sage: BSigma3 = Sigma3.nerve() + sage: BSigma3.n_skeleton(3) Simplicial set with 156 non-degenerate simplices - sage: BSigma3.n_skeleton(4) # optional - sage.groups + sage: BSigma3.n_skeleton(4) Simplicial set with 781 non-degenerate simplices Finally, note that the classifying space of the order `p` @@ -129,29 +130,28 @@ def nerve(self): on `p` letters, and its first homology group appears earlier:: - sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.groups - sage: list(C3) # optional - sage.groups + sage: # needs sage.groups + sage: C3 = groups.misc.MultiplicativeAbelian([3]) + sage: list(C3) [1, f, f^2] - sage: BC3 = C3.nerve() # optional - sage.groups - sage: BC3.n_cells(1) # optional - sage.groups + sage: BC3 = C3.nerve() + sage: BC3.n_cells(1) [f, f^2] - sage: BC3.n_cells(2) # optional - sage.groups + sage: BC3.n_cells(2) [f * f, f * f^2, f^2 * f, f^2 * f^2] - sage: len(BSigma3.n_cells(2)) # optional - sage.groups + sage: len(BSigma3.n_cells(2)) 25 - sage: len(BC3.n_cells(3)) # optional - sage.groups + sage: len(BC3.n_cells(3)) 8 - sage: len(BSigma3.n_cells(3)) # optional - sage.groups + sage: len(BSigma3.n_cells(3)) 125 - - sage: BC3.homology(range(4), base_ring=GF(3)) # optional - sage.groups sage.rings.finite_rings + sage: BC3.homology(range(4), base_ring=GF(3)) {0: Vector space of dimension 0 over Finite Field of size 3, 1: Vector space of dimension 1 over Finite Field of size 3, 2: Vector space of dimension 1 over Finite Field of size 3, 3: Vector space of dimension 1 over Finite Field of size 3} - - sage: BC5 = groups.permutation.Cyclic(5).nerve() # optional - sage.groups - sage: BC5.homology(range(4), base_ring=GF(5)) # optional - sage.groups sage.rings.finite_rings + sage: BC5 = groups.permutation.Cyclic(5).nerve() + sage: BC5.homology(range(4), base_ring=GF(5)) {0: Vector space of dimension 0 over Finite Field of size 5, 1: Vector space of dimension 1 over Finite Field of size 5, 2: Vector space of dimension 1 over Finite Field of size 5, @@ -179,20 +179,22 @@ def rhodes_radical_congruence(self, base_ring=None): EXAMPLES:: sage: M = Monoids().Finite().example() - sage: M.rhodes_radical_congruence() # optional - sage.groups sage.modules + sage: M.rhodes_radical_congruence() # needs sage.modules [(0, 6), (2, 8), (4, 10)] - sage: from sage.monoids.hecke_monoid import HeckeMonoid # optional - sage.groups sage.modules - sage: H3 = HeckeMonoid(SymmetricGroup(3)) # optional - sage.groups sage.modules - sage: H3.repr_element_method(style="reduced") # optional - sage.groups sage.modules - sage: H3.rhodes_radical_congruence() # optional - sage.groups sage.modules + + sage: # needs sage.combinat sage.groups sage.modules + sage: from sage.monoids.hecke_monoid import HeckeMonoid + sage: H3 = HeckeMonoid(SymmetricGroup(3)) + sage: H3.repr_element_method(style="reduced") + sage: H3.rhodes_radical_congruence() [([1, 2], [2, 1]), ([1, 2], [1, 2, 1]), ([2, 1], [1, 2, 1])] By Maschke's theorem, every group algebra over `\QQ` is semisimple hence the Rhodes radical of a group must be trivial:: - sage: SymmetricGroup(3).rhodes_radical_congruence() # optional - sage.groups sage.modules + sage: SymmetricGroup(3).rhodes_radical_congruence() # needs sage.groups sage.modules [] - sage: DihedralGroup(10).rhodes_radical_congruence() # optional - sage.groups sage.modules + sage: DihedralGroup(10).rhodes_radical_congruence() # needs sage.groups sage.modules [] REFERENCES: diff --git a/src/sage/categories/finite_permutation_groups.py b/src/sage/categories/finite_permutation_groups.py index e081d2d4f63..f14c66a96c9 100644 --- a/src/sage/categories/finite_permutation_groups.py +++ b/src/sage/categories/finite_permutation_groups.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups +# sage.doctest: needs sage.groups r""" Finite Permutation Groups """ @@ -270,8 +270,8 @@ def profile_series(self, variable='z'): Univariate Polynomial Ring in z over Rational Field sage: D8.profile_series(variable='y') y^8 + y^7 + 4*y^6 + 5*y^5 + 8*y^4 + 5*y^3 + 4*y^2 + y + 1 - sage: u = var('u') # optional - sage.symbolic - sage: D8.profile_series(u).parent() # optional - sage.symbolic + sage: u = var('u') # needs sage.symbolic + sage: D8.profile_series(u).parent() # needs sage.symbolic Symbolic Ring """ from sage.rings.integer_ring import ZZ diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py index 263033a2c9b..c50eb6c100d 100644 --- a/src/sage/categories/finite_posets.py +++ b/src/sage/categories/finite_posets.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.graphs +# sage.doctest: needs sage.combinat sage.graphs r""" Finite posets @@ -1439,10 +1439,10 @@ def rowmotion_orbits_plots(self): """ from sage.plot.plot import graphics_array - plot_of_orb_plots=[] + plot_of_orb_plots = [] max_orbit_size = 0 for orb in self.rowmotion_orbits(): - orb_plots=[] + orb_plots = [] if len(orb) > max_orbit_size: max_orbit_size = len(orb) for oi in orb: @@ -1525,10 +1525,10 @@ def toggling_orbits_plots(self, vs): """ from sage.plot.plot import graphics_array - plot_of_orb_plots=[] + plot_of_orb_plots = [] max_orbit_size = 0 for orb in self.toggling_orbits(vs): - orb_plots=[] + orb_plots = [] if len(orb) > max_orbit_size: max_orbit_size = len(orb) for oi in orb: diff --git a/src/sage/categories/finite_semigroups.py b/src/sage/categories/finite_semigroups.py index e9c31e1ad62..ad384fc2b79 100644 --- a/src/sage/categories/finite_semigroups.py +++ b/src/sage/categories/finite_semigroups.py @@ -87,7 +87,7 @@ def j_classes(self): EXAMPLES:: sage: S = FiniteSemigroups().example(alphabet=('a','b', 'c')) - sage: sorted(map(sorted, S.j_classes())) # optional - sage.graphs + sage: sorted(map(sorted, S.j_classes())) # needs sage.graphs [['a'], ['ab', 'ba'], ['abc', 'acb', 'bac', 'bca', 'cab', 'cba'], ['ac', 'ca'], ['b'], ['bc', 'cb'], ['c']] """ @@ -105,7 +105,7 @@ def j_classes_of_idempotents(self): EXAMPLES:: sage: S = FiniteSemigroups().example(alphabet=('a','b', 'c')) - sage: sorted(map(sorted, S.j_classes_of_idempotents())) # optional - sage.graphs + sage: sorted(map(sorted, S.j_classes_of_idempotents())) # needs sage.graphs [['a'], ['ab', 'ba'], ['abc', 'acb', 'bac', 'bca', 'cab', 'cba'], ['ac', 'ca'], ['b'], ['bc', 'cb'], ['c']] """ @@ -123,7 +123,7 @@ def j_transversal_of_idempotents(self): The chosen elements depend on the order of each `J`-class, and that order is random when using Python 3. :: - sage: sorted(S.j_transversal_of_idempotents()) # random # optional - sage.graphs + sage: sorted(S.j_transversal_of_idempotents()) # random # needs sage.graphs ['a', 'ab', 'abc', 'ac', 'b', 'c', 'cb'] """ def first_idempotent(l): diff --git a/src/sage/categories/finite_weyl_groups.py b/src/sage/categories/finite_weyl_groups.py index 1d1d0250c23..4420827c833 100644 --- a/src/sage/categories/finite_weyl_groups.py +++ b/src/sage/categories/finite_weyl_groups.py @@ -27,7 +27,7 @@ class FiniteWeylGroups(CategoryWithAxiom): TESTS:: sage: W = FiniteWeylGroups().example() - sage: TestSuite(W).run() # optional - sage.combinat + sage: TestSuite(W).run() """ class ParentMethods: diff --git a/src/sage/categories/finitely_generated_lambda_bracket_algebras.py b/src/sage/categories/finitely_generated_lambda_bracket_algebras.py index f8a36053753..c997118a3bc 100644 --- a/src/sage/categories/finitely_generated_lambda_bracket_algebras.py +++ b/src/sage/categories/finitely_generated_lambda_bracket_algebras.py @@ -27,7 +27,7 @@ class FinitelyGeneratedLambdaBracketAlgebras(CategoryWithAxiom_over_base_ring): EXAMPLES:: sage: from sage.categories.lambda_bracket_algebras import LambdaBracketAlgebras - sage: LambdaBracketAlgebras(QQbar).FinitelyGenerated() # optional - sage.rings.number_field + sage: LambdaBracketAlgebras(QQbar).FinitelyGenerated() # needs sage.rings.number_field Category of finitely generated lambda bracket algebras over Algebraic Field """ _base_category_class_and_axiom = (LambdaBracketAlgebras, "FinitelyGeneratedAsLambdaBracketAlgebra") @@ -39,12 +39,12 @@ def ngens(self): EXAMPLES:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ) # optional - sage.combinat sage.modules - sage: Vir.ngens() # optional - sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ) # needs sage.combinat sage.modules + sage: Vir.ngens() # needs sage.combinat sage.modules 2 - sage: V = lie_conformal_algebras.Affine(QQ, 'A2') # optional - sage.combinat sage.modules - sage: V.ngens() # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A2') # needs sage.combinat sage.modules + sage: V.ngens() # needs sage.combinat sage.modules 9 """ return len(self.gens()) @@ -55,12 +55,13 @@ def gen(self,i): EXAMPLES:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1') # optional - sage.combinat sage.modules - sage: V.gens() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1') + sage: V.gens() (B[alpha[1]], B[alphacheck[1]], B[-alpha[1]], B['K']) - sage: V.gen(0) # optional - sage.combinat sage.modules + sage: V.gen(0) B[alpha[1]] - sage: V.1 # optional - sage.combinat sage.modules + sage: V.1 B[alphacheck[1]] """ return self.gens()[i] @@ -74,11 +75,11 @@ def some_elements(self): EXAMPLES:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # needs sage.combinat sage.modules ....: names=('e', 'h', 'f')) - sage: V.some_elements() # optional - sage.combinat sage.modules + sage: V.some_elements() # needs sage.combinat sage.modules [e, h, f, K, ...] - sage: all(v.parent() is V for v in V.some_elements()) # optional - sage.combinat sage.modules + sage: all(v.parent() is V for v in V.some_elements()) # needs sage.combinat sage.modules True """ S = list(self.gens()) @@ -93,7 +94,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated lie conformal algebras over Algebraic Field """ @@ -103,7 +104,7 @@ def _repr_object_names(self): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated Lie conformal algebras with basis over Algebraic Field """ return "H-graded {}".format(self.base_category()._repr_object_names()) diff --git a/src/sage/categories/finitely_generated_lie_conformal_algebras.py b/src/sage/categories/finitely_generated_lie_conformal_algebras.py index 96433749aa4..53d5ed4ccf6 100644 --- a/src/sage/categories/finitely_generated_lie_conformal_algebras.py +++ b/src/sage/categories/finitely_generated_lie_conformal_algebras.py @@ -27,7 +27,7 @@ class FinitelyGeneratedLieConformalAlgebras(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).FinitelyGenerated() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).FinitelyGenerated() # needs sage.rings.number_field Category of finitely generated lie conformal algebras over Algebraic Field """ _base_category_class_and_axiom = (LieConformalAlgebras, "FinitelyGeneratedAsLambdaBracketAlgebra") @@ -43,11 +43,11 @@ def some_elements(self): EXAMPLES:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # needs sage.combinat sage.modules ....: names=('e', 'h', 'f')) - sage: V.some_elements() # optional - sage.combinat sage.modules + sage: V.some_elements() # needs sage.combinat sage.modules [e, h, f, K, ...] - sage: all(v.parent() is V for v in V.some_elements()) # optional - sage.combinat sage.modules + sage: all(v.parent() is V for v in V.some_elements()) # needs sage.combinat sage.modules True """ S = list(self.gens()) @@ -62,7 +62,7 @@ class Super(SuperModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(AA).FinitelyGenerated().Super() # optional - sage.rings.number_field + sage: LieConformalAlgebras(AA).FinitelyGenerated().Super() # needs sage.rings.number_field Category of super finitely generated lie conformal algebras over Algebraic Real Field """ @@ -72,7 +72,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Super().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Super().Graded() # needs sage.rings.number_field Category of H-graded super finitely generated lie conformal algebras over Algebraic Field """ @@ -82,8 +82,8 @@ def _repr_object_names(self): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar).FinitelyGenerated() # optional - sage.rings.number_field - sage: C.Super().Graded() # optional - sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar).FinitelyGenerated() # needs sage.rings.number_field + sage: C.Super().Graded() # needs sage.rings.number_field Category of H-graded super finitely generated lie conformal algebras over Algebraic Field """ @@ -95,7 +95,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated lie conformal algebras over Algebraic Field """ @@ -105,7 +105,7 @@ def _repr_object_names(self): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated Lie conformal algebras with basis over Algebraic Field """ diff --git a/src/sage/categories/function_fields.py b/src/sage/categories/function_fields.py index 093d2ff6fac..6c949b6197a 100644 --- a/src/sage/categories/function_fields.py +++ b/src/sage/categories/function_fields.py @@ -56,10 +56,10 @@ def _call_(self, x): sage: C(K) Rational function field in x over Rational Field sage: Ky. = K[] - sage: L = K.extension(y^2 - x) # optional - sage.rings.function_field - sage: C(L) # optional - sage.rings.function_field + sage: L = K.extension(y^2 - x) # needs sage.rings.function_field + sage: C(L) # needs sage.rings.function_field Function field in y defined by y^2 - x - sage: C(L.equation_order()) # optional - sage.rings.function_field + sage: C(L.equation_order()) # needs sage.rings.function_field Function field in y defined by y^2 - x """ try: diff --git a/src/sage/categories/functor.pyx b/src/sage/categories/functor.pyx index 823d3a2132f..c25e99f2164 100644 --- a/src/sage/categories/functor.pyx +++ b/src/sage/categories/functor.pyx @@ -117,7 +117,7 @@ cdef class Functor(SageObject): Functor from Category of rings to Category of fields sage: F(ZZ) Rational Field - sage: F(GF(2)) # optional - sage.rings.finite_rings + sage: F(GF(2)) Finite Field of size 2 Functors are not only about the objects of a category, but also about @@ -175,7 +175,7 @@ cdef class Functor(SageObject): Functor from Category of rings to Category of fields sage: F(ZZ) Rational Field - sage: F(GF(2)) # optional - sage.rings.finite_rings + sage: F(GF(2)) Finite Field of size 2 """ @@ -250,14 +250,15 @@ cdef class Functor(SageObject): TESTS:: + sage: # needs sage.rings.finite_rings sage: from sage.categories.functor import Functor sage: F = Functor(Rings(), Fields()) - sage: k. = GF(25) # optional - sage.rings.finite_rings - sage: f = k.hom([-a - 4]) # optional - sage.rings.finite_rings - sage: R. = k[] # optional - sage.rings.finite_rings - sage: fR = R.hom(f, R) # optional - sage.rings.finite_rings - sage: fF = F(fR) # indirect doctest # optional - sage.rings.finite_rings - sage: fF # optional - sage.rings.finite_rings + sage: k. = GF(25) + sage: f = k.hom([-a - 4]) + sage: R. = k[] + sage: fR = R.hom(f, R) + sage: fF = F(fR) # indirect doctest + sage: fF Ring endomorphism of Fraction Field of Univariate Polynomial Ring in t over Finite Field in a of size 5^2 Defn: Induced from base ring by @@ -266,7 +267,7 @@ cdef class Functor(SageObject): Defn: Induced from base ring by Ring endomorphism of Finite Field in a of size 5^2 Defn: a |--> 4*a + 1 - sage: fF((a^2+a)*t^2/(a*t - a^2)) # optional - sage.rings.finite_rings + sage: fF((a^2+a)*t^2/(a*t - a^2)) ((4*a + 2)*t^2)/(t + a + 4) """ try: @@ -338,13 +339,13 @@ cdef class Functor(SageObject): Functor from Category of rings to Category of fields sage: F(ZZ) Rational Field - sage: F(GF(2)) # optional - sage.rings.finite_rings + sage: F(GF(2)) Finite Field of size 2 Two subclasses:: sage: F1 = ForgetfulFunctor(FiniteFields(), Fields()) - sage: F1(GF(5)) # indirect doctest # optional - sage.rings.finite_rings + sage: F1(GF(5)) # indirect doctest Finite Field of size 5 sage: F1(ZZ) Traceback (most recent call last): @@ -372,10 +373,10 @@ cdef class Functor(SageObject): ....: def _apply_functor(self, R): ....: return MatrixSpace(R, self._m, self._n) sage: F = IllFunctor(2, 2) - sage: F(QQ) # optional - sage.modules + sage: F(QQ) # needs sage.modules Full MatrixSpace of 2 by 2 dense matrices over Rational Field sage: F = IllFunctor(2, 3) - sage: F(QQ) # optional - sage.modules + sage: F(QQ) # needs sage.modules Traceback (most recent call last): ... TypeError: Functor from Category of rings to Category of rings @@ -468,7 +469,7 @@ class ForgetfulFunctor_generic(Functor): The forgetful functor from Category of finite enumerated fields to Category of fields - sage: F(GF(3)) # optional - sage.rings.finite_rings + sage: F(GF(3)) Finite Field of size 3 """ diff --git a/src/sage/categories/g_sets.py b/src/sage/categories/g_sets.py index 0f8004ddbf0..7fd09bafea4 100644 --- a/src/sage/categories/g_sets.py +++ b/src/sage/categories/g_sets.py @@ -23,8 +23,8 @@ class GSets(Category): EXAMPLES:: - sage: S = SymmetricGroup(3) # optional - sage.groups - sage: GSets(S) # optional - sage.groups + sage: S = SymmetricGroup(3) # needs sage.groups + sage: GSets(S) # needs sage.groups Category of G-sets for Symmetric group of order 3! as a permutation group TODO: should this derive from Category_over_base? @@ -33,8 +33,8 @@ def __init__(self, G): """ TESTS:: - sage: S8 = SymmetricGroup(8) # optional - sage.groups - sage: TestSuite(GSets(S8)).run() # optional - sage.groups + sage: S8 = SymmetricGroup(8) # needs sage.groups + sage: TestSuite(GSets(S8)).run() # needs sage.groups """ Category.__init__(self) self.__G = G @@ -43,10 +43,10 @@ def _repr_object_names(self): """ EXAMPLES:: - sage: GSets(SymmetricGroup(8)) # indirect doctests # optional - sage.groups + sage: GSets(SymmetricGroup(8)) # indirect doctests # needs sage.groups Category of G-sets for Symmetric group of order 8! as a permutation group """ - return "G-sets for %s"%self.__G + return "G-sets for %s" % self.__G #def construction(self): # return (self.__class__, self.__G) @@ -55,7 +55,7 @@ def super_categories(self): """ EXAMPLES:: - sage: GSets(SymmetricGroup(8)).super_categories() # optional - sage.groups + sage: GSets(SymmetricGroup(8)).super_categories() # needs sage.groups [Category of sets] """ return [Sets()] @@ -67,7 +67,7 @@ def an_instance(cls): EXAMPLES:: - sage: GSets.an_instance() # indirect doctest # optional - sage.groups + sage: GSets.an_instance() # indirect doctest # needs sage.groups Category of G-sets for Symmetric group of order 8! as a permutation group """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup diff --git a/src/sage/categories/graded_algebras.py b/src/sage/categories/graded_algebras.py index efa1a501192..190355b59c5 100644 --- a/src/sage/categories/graded_algebras.py +++ b/src/sage/categories/graded_algebras.py @@ -39,8 +39,8 @@ def graded_algebra(self): EXAMPLES:: - sage: m = SymmetricFunctions(QQ).m() # optional - sage.combinat - sage: m.graded_algebra() is m # optional - sage.combinat + sage: m = SymmetricFunctions(QQ).m() # needs sage.combinat sage.modules + sage: m.graded_algebra() is m # needs sage.combinat sage.modules True """ return self diff --git a/src/sage/categories/graded_algebras_with_basis.py b/src/sage/categories/graded_algebras_with_basis.py index 52d80b78b4e..95fcebbb7a7 100644 --- a/src/sage/categories/graded_algebras_with_basis.py +++ b/src/sage/categories/graded_algebras_with_basis.py @@ -46,8 +46,8 @@ def graded_algebra(self): EXAMPLES:: - sage: m = SymmetricFunctions(QQ).m() # optional - sage.combinat - sage: m.graded_algebra() is m # optional - sage.combinat sage.modules + sage: m = SymmetricFunctions(QQ).m() # needs sage.combinat sage.modules + sage: m.graded_algebra() is m # needs sage.combinat sage.modules True TESTS: @@ -57,21 +57,22 @@ def graded_algebra(self): and :meth:`projection` (which form the interface of the associated graded algebra) work correctly here:: - sage: to_gr = m.to_graded_conversion() # optional - sage.combinat sage.modules - sage: from_gr = m.from_graded_conversion() # optional - sage.combinat sage.modules - sage: m[2] == to_gr(m[2]) == from_gr(m[2]) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: to_gr = m.to_graded_conversion() + sage: from_gr = m.from_graded_conversion() + sage: m[2] == to_gr(m[2]) == from_gr(m[2]) True - sage: u = 3*m[1] - (1/2)*m[3] # optional - sage.combinat sage.modules - sage: u == to_gr(u) == from_gr(u) # optional - sage.combinat sage.modules + sage: u = 3*m[1] - (1/2)*m[3] + sage: u == to_gr(u) == from_gr(u) True - sage: m.zero() == to_gr(m.zero()) == from_gr(m.zero()) # optional - sage.combinat sage.modules + sage: m.zero() == to_gr(m.zero()) == from_gr(m.zero()) True - sage: p2 = m.projection(2) # optional - sage.combinat sage.modules - sage: p2(m[2] - 4*m[1,1] + 3*m[1] - 2*m[[]]) # optional - sage.combinat sage.modules + sage: p2 = m.projection(2) + sage: p2(m[2] - 4*m[1,1] + 3*m[1] - 2*m[[]]) -4*m[1, 1] + m[2] - sage: p2(4*m[1]) # optional - sage.combinat sage.modules + sage: p2(4*m[1]) 0 - sage: p2(m.zero()) == m.zero() # optional - sage.combinat sage.modules + sage: p2(m.zero()) == m.zero() True """ return self @@ -111,13 +112,14 @@ def free_graded_module(self, generator_degrees, names=None): EXAMPLES:: - sage: Q = QuadraticForm(QQ, 3, [1,2,3,4,5,6]) # optional - sage.modules - sage: Cl = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: M = Cl.free_graded_module((0, 2, 3)) # optional - sage.combinat sage.modules - sage: M.gens() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: Q = QuadraticForm(QQ, 3, [1,2,3,4,5,6]) + sage: Cl = CliffordAlgebra(Q) + sage: M = Cl.free_graded_module((0, 2, 3)) + sage: M.gens() (g[0], g[2], g[3]) - sage: N. = Cl.free_graded_module((1, 2)) # optional - sage.combinat sage.modules - sage: N.generators() # optional - sage.combinat sage.modules + sage: N. = Cl.free_graded_module((1, 2)) + sage: N.generators() (xy, z) """ try: @@ -134,10 +136,11 @@ def formal_series_ring(self): EXAMPLES:: - sage: NCSF = NonCommutativeSymmetricFunctions(QQ) # optional - sage.combinat - sage: S = NCSF.Complete() # optional - sage.combinat - sage: L = S.formal_series_ring() # optional - sage.combinat - sage: L # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: NCSF = NonCommutativeSymmetricFunctions(QQ) + sage: S = NCSF.Complete() + sage: L = S.formal_series_ring() + sage: L Lazy completion of Non-Commutative Symmetric Functions over the Rational Field in the Complete basis """ @@ -185,13 +188,14 @@ def one_basis(self): EXAMPLES:: - sage: A. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: A.one_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A. = ExteriorAlgebra(QQ) + sage: A.one_basis() 0 - sage: B = tensor((A, A, A)) # optional - sage.combinat sage.modules - sage: B.one_basis() # optional - sage.combinat sage.modules + sage: B = tensor((A, A, A)) + sage: B.one_basis() (0, 0, 0) - sage: B.one() # optional - sage.combinat sage.modules + sage: B.one() 1 # 1 # 1 """ # FIXME: this method should be conditionally defined, @@ -211,10 +215,11 @@ def product_on_basis(self, t0, t1): Test the sign in the super tensor product:: - sage: A = SteenrodAlgebra(3) # optional - sage.combinat sage.modules - sage: x = A.Q(0) # optional - sage.combinat sage.modules - sage: y = x.coproduct() # optional - sage.combinat sage.modules - sage: y^2 # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = SteenrodAlgebra(3) + sage: x = A.Q(0) + sage: y = x.coproduct() + sage: y^2 0 TODO: optimize this implementation! diff --git a/src/sage/categories/graded_hopf_algebras_with_basis.py b/src/sage/categories/graded_hopf_algebras_with_basis.py index 204ab23013e..41beadad8a4 100644 --- a/src/sage/categories/graded_hopf_algebras_with_basis.py +++ b/src/sage/categories/graded_hopf_algebras_with_basis.py @@ -44,7 +44,7 @@ def example(self): TESTS:: - sage: GradedHopfAlgebrasWithBasis(QQ).example() # optional - sage.modules + sage: GradedHopfAlgebrasWithBasis(QQ).example() # needs sage.modules An example of a graded connected Hopf algebra with basis over Rational Field """ from sage.categories.examples.graded_connected_hopf_algebras_with_basis import \ @@ -85,7 +85,7 @@ def example(self): TESTS:: - sage: GradedHopfAlgebrasWithBasis(QQ).Connected().example() # optional - sage.modules + sage: GradedHopfAlgebrasWithBasis(QQ).Connected().example() # needs sage.modules An example of a graded connected Hopf algebra with basis over Rational Field """ from sage.categories.examples.graded_connected_hopf_algebras_with_basis import \ @@ -114,10 +114,10 @@ def counit_on_basis(self, i): EXAMPLES:: - sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() # optional - sage.modules - sage: H.monomial(4).counit() # indirect doctest # optional - sage.modules + sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() # needs sage.modules + sage: H.monomial(4).counit() # indirect doctest # needs sage.modules 0 - sage: H.monomial(0).counit() # indirect doctest # optional - sage.modules + sage: H.monomial(0).counit() # indirect doctest # needs sage.modules 1 """ if i == self.one_basis(): @@ -144,14 +144,15 @@ def antipode_on_basis(self, index): TESTS:: - sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() # optional - sage.modules - sage: H.monomial(0).antipode() # indirect doctest # optional - sage.modules + sage: # needs sage.modules + sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example() + sage: H.monomial(0).antipode() # indirect doctest P0 - sage: H.monomial(1).antipode() # indirect doctest # optional - sage.modules + sage: H.monomial(1).antipode() # indirect doctest -P1 - sage: H.monomial(2).antipode() # indirect doctest # optional - sage.modules + sage: H.monomial(2).antipode() # indirect doctest P2 - sage: H.monomial(3).antipode() # indirect doctest # optional - sage.modules + sage: H.monomial(3).antipode() # indirect doctest -P3 """ if self.monomial(index) == self.one(): diff --git a/src/sage/categories/graded_lie_conformal_algebras.py b/src/sage/categories/graded_lie_conformal_algebras.py index 2650492898d..a17c067ae4e 100644 --- a/src/sage/categories/graded_lie_conformal_algebras.py +++ b/src/sage/categories/graded_lie_conformal_algebras.py @@ -31,11 +31,12 @@ def Super(self, base_ring=None): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar) # optional - sage.rings.number_field - sage: C.Graded().Super() is C.Super().Graded() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar) + sage: C.Graded().Super() is C.Super().Graded() True - sage: Cp = C.WithBasis() # optional - sage.rings.number_field - sage: Cp.Graded().Super() is Cp.Super().Graded() # optional - sage.rings.number_field + sage: Cp = C.WithBasis() + sage: Cp.Graded().Super() is Cp.Super().Graded() True """ return self.base_category().Super(base_ring).Graded() @@ -46,10 +47,10 @@ def _repr_object_names(self): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).Graded() # needs sage.rings.number_field Category of H-graded Lie conformal algebras over Algebraic Field - sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated Lie conformal algebras with basis over Algebraic Field """ return "H-graded {}".format(self.base_category()._repr_object_names()) @@ -60,7 +61,7 @@ class GradedLieConformalAlgebras(GradedLieConformalAlgebrasCategory): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar).Graded(); C # optional - sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar).Graded(); C # needs sage.rings.number_field Category of H-graded Lie conformal algebras over Algebraic Field sage: CS = LieConformalAlgebras(QQ).Graded().Super(); CS diff --git a/src/sage/categories/graded_modules_with_basis.py b/src/sage/categories/graded_modules_with_basis.py index b1185e20352..c813b05e2ec 100644 --- a/src/sage/categories/graded_modules_with_basis.py +++ b/src/sage/categories/graded_modules_with_basis.py @@ -46,18 +46,18 @@ def degree_negation(self, element): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: E.degree_negation((1 + a) * (1 + b)) # optional - sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: E.degree_negation((1 + a) * (1 + b)) # needs sage.modules a*b - a - b + 1 - sage: E.degree_negation(E.zero()) # optional - sage.combinat sage.modules + sage: E.degree_negation(E.zero()) # needs sage.modules 0 - sage: P = GradedModulesWithBasis(ZZ).example(); P # optional - sage.combinat sage.modules + sage: P = GradedModulesWithBasis(ZZ).example(); P # needs sage.combinat sage.modules An example of a graded module with basis: the free module on partitions over Integer Ring - sage: pbp = lambda x: P.basis()[Partition(list(x))] # optional - sage.combinat sage.modules - sage: p = pbp([3,1]) - 2 * pbp([2]) + 4 * pbp([1]) # optional - sage.combinat sage.modules - sage: P.degree_negation(p) # optional - sage.combinat sage.modules + sage: pbp = lambda x: P.basis()[Partition(list(x))] + sage: p = pbp([3,1]) - 2 * pbp([2]) + 4 * pbp([1]) # needs sage.combinat sage.modules + sage: P.degree_negation(p) # needs sage.combinat sage.modules -4*P[1] - 2*P[2] + P[3, 1] """ base_one = self.base_ring().one() @@ -115,22 +115,23 @@ def submodule(self, gens, check=True, already_echelonized=False, A graded submodule of a graded module generated by homogeneous elements is naturally graded:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: S = E.submodule([x + y, x*y - y*z]) # optional - sage.combinat sage.modules - sage: S.category() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: S = E.submodule([x + y, x*y - y*z]) + sage: S.category() Join of Category of graded vector spaces with basis over Rational Field and Category of subobjects of filtered modules with basis over Rational Field and Category of finite dimensional vector spaces with basis over Rational Field - sage: S.basis()[0].degree() # optional - sage.combinat sage.modules + sage: S.basis()[0].degree() 1 - sage: S.basis()[1].degree() # optional - sage.combinat sage.modules + sage: S.basis()[1].degree() 2 We check on the echelonized basis:: - sage: Sp = E.submodule([1, x + y + 5, x*y - y*z + x + y - 2]) # optional - sage.combinat sage.modules - sage: Sp.category() # optional - sage.combinat sage.modules + sage: Sp = E.submodule([1, x + y + 5, x*y - y*z + x + y - 2]) # needs sage.combinat sage.modules + sage: Sp.category() # needs sage.combinat sage.modules Join of Category of graded vector spaces with basis over Rational Field and Category of subobjects of filtered modules with basis over Rational Field and @@ -139,8 +140,8 @@ def submodule(self, gens, check=True, already_echelonized=False, If it is generated by inhomogeneous elements, then it is filtered by default:: - sage: F = E.submodule([x + y*z, x*z + y*x]) # optional - sage.combinat sage.modules - sage: F.category() # optional - sage.combinat sage.modules + sage: F = E.submodule([x + y*z, x*z + y*x]) # needs sage.combinat sage.modules + sage: F.category() # needs sage.combinat sage.modules Join of Category of subobjects of filtered modules with basis over Rational Field and Category of filtered vector spaces with basis over Rational Field and @@ -150,15 +151,16 @@ def submodule(self, gens, check=True, already_echelonized=False, structure to the submodule (we can think of this as applying the forgetful functor):: - sage: SM = E.submodule([x + y, x*y - y*z], # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: SM = E.submodule([x + y, x*y - y*z], ....: category=ModulesWithBasis(QQ)) - sage: SM.category() # optional - sage.combinat sage.modules + sage: SM.category() Join of Category of finite dimensional vector spaces with basis over Rational Field and Category of subobjects of sets - sage: FM = E.submodule([x + 1, x*y - x*y*z], # optional - sage.combinat sage.modules + sage: FM = E.submodule([x + 1, x*y - x*y*z], ....: category=ModulesWithBasis(QQ)) - sage: FM.category() # optional - sage.combinat sage.modules + sage: FM.category() Join of Category of finite dimensional vector spaces with basis over Rational Field and Category of subobjects of sets @@ -167,11 +169,11 @@ def submodule(self, gens, check=True, already_echelonized=False, module, then the echelonized elements must be homogeneous:: sage: Cat = ModulesWithBasis(QQ).Graded().Subobjects() - sage: E.submodule([x + y, x*y - 1], category=Cat) # optional - sage.combinat sage.modules + sage: E.submodule([x + y, x*y - 1], category=Cat) # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: all of the generators must be homogeneous - sage: E.submodule([x + y, x*y - x - y], category=Cat) # optional - sage.combinat sage.modules + sage: E.submodule([x + y, x*y - x - y], category=Cat) # needs sage.combinat sage.modules Free module generated by {0, 1} over Rational Field """ # Make sure gens consists of elements of ``self`` @@ -223,10 +225,11 @@ def quotient_module(self, submodule, check=True, already_echelonized=False, cate EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: S = E.submodule([x + y, x*y - y*z, y]) # optional - sage.combinat sage.modules - sage: Q = E.quotient_module(S) # optional - sage.combinat sage.modules - sage: Q.category() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: S = E.submodule([x + y, x*y - y*z, y]) + sage: Q = E.quotient_module(S) + sage: Q.category() Join of Category of quotients of graded modules with basis over Rational Field and Category of graded vector spaces with basis over Rational Field and @@ -267,18 +270,18 @@ def degree_negation(self): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: ((1 + a) * (1 + b)).degree_negation() # optional - sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: ((1 + a) * (1 + b)).degree_negation() # needs sage.modules a*b - a - b + 1 - sage: E.zero().degree_negation() # optional - sage.combinat sage.modules + sage: E.zero().degree_negation() # needs sage.modules 0 - sage: P = GradedModulesWithBasis(ZZ).example(); P # optional - sage.combinat sage.modules + sage: P = GradedModulesWithBasis(ZZ).example(); P # needs sage.combinat sage.modules An example of a graded module with basis: the free module on partitions over Integer Ring - sage: pbp = lambda x: P.basis()[Partition(list(x))] # optional - sage.combinat sage.modules - sage: p = pbp([3,1]) - 2 * pbp([2]) + 4 * pbp([1]) # optional - sage.combinat sage.modules - sage: p.degree_negation() # optional - sage.combinat sage.modules + sage: pbp = lambda x: P.basis()[Partition(list(x))] + sage: p = pbp([3,1]) - 2 * pbp([2]) + 4 * pbp([1]) # needs sage.combinat sage.modules + sage: p.degree_negation() # needs sage.combinat sage.modules -4*P[1] - 2*P[2] + P[3, 1] """ return self.parent().degree_negation(self) @@ -292,13 +295,14 @@ def degree_on_basis(self, m): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: S = E.submodule([x + y, x*y - y*z, y]) # optional - sage.combinat sage.modules - sage: Q = E.quotient_module(S) # optional - sage.combinat sage.modules - sage: B = Q.basis() # optional - sage.combinat sage.modules - sage: [B[i].lift() for i in Q.indices()] # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: S = E.submodule([x + y, x*y - y*z, y]) + sage: Q = E.quotient_module(S) + sage: B = Q.basis() + sage: [B[i].lift() for i in Q.indices()] [1, z, x*z, y*z, x*y*z] - sage: [Q.degree_on_basis(i) for i in Q.indices()] # optional - sage.combinat sage.modules + sage: [Q.degree_on_basis(i) for i in Q.indices()] [0, 1, 2, 2, 3] """ return self.basis()[m].lift().degree() @@ -310,13 +314,14 @@ def degree(self): EXAMPLES:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: S = E.submodule([x + y, x*y - y*z, y]) # optional - sage.combinat sage.modules - sage: Q = E.quotient_module(S) # optional - sage.combinat sage.modules - sage: B = Q.basis() # optional - sage.combinat sage.modules - sage: [B[i].lift() for i in Q.indices()] # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: S = E.submodule([x + y, x*y - y*z, y]) + sage: Q = E.quotient_module(S) + sage: B = Q.basis() + sage: [B[i].lift() for i in Q.indices()] [1, z, x*z, y*z, x*y*z] - sage: [B[i].degree() for i in Q.indices()] # optional - sage.combinat sage.modules + sage: [B[i].degree() for i in Q.indices()] [0, 1, 2, 2, 3] """ return self.lift().degree() diff --git a/src/sage/categories/group_algebras.py b/src/sage/categories/group_algebras.py index 36c7e069f34..1f68c28c3b4 100644 --- a/src/sage/categories/group_algebras.py +++ b/src/sage/categories/group_algebras.py @@ -50,16 +50,16 @@ class GroupAlgebras(AlgebrasCategory): Here is how to create the group algebra of a group `G`:: - sage: G = DihedralGroup(5) # optional - sage.groups - sage: QG = G.algebra(QQ); QG # optional - sage.groups sage.modules + sage: G = DihedralGroup(5) # needs sage.groups + sage: QG = G.algebra(QQ); QG # needs sage.groups sage.modules Algebra of Dihedral group of order 10 as a permutation group over Rational Field and an example of computation:: - sage: g = G.an_element(); g # optional - sage.groups sage.modules + sage: g = G.an_element(); g # needs sage.groups sage.modules (1,4)(2,3) - sage: (QG.term(g) + 1)**3 # optional - sage.groups sage.modules + sage: (QG.term(g) + 1)**3 # needs sage.groups sage.modules 4*() + 4*(1,4)(2,3) .. TODO:: @@ -69,14 +69,15 @@ class GroupAlgebras(AlgebrasCategory): TESTS:: - sage: A = GroupAlgebras(QQ).example(GL(3, GF(11))) # optional - sage.groups sage.modules sage.rings.finite_rings - sage: A.one_basis() # optional - sage.groups sage.modules sage.rings.finite_rings + sage: # needs sage.groups sage.modules + sage: A = GroupAlgebras(QQ).example(GL(3, GF(11))) + sage: A.one_basis() [1 0 0] [0 1 0] [0 0 1] - sage: A = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules sage.combinat - sage: x = Permutation([4,3,2,1]) # optional - sage.groups sage.modules sage.combinat - sage: A.product_on_basis(x, x) # optional - sage.groups sage.modules sage.combinat + sage: A = SymmetricGroupAlgebra(QQ, 4) # needs sage.combinat + sage: x = Permutation([4,3,2,1]) + sage: A.product_on_basis(x, x) # needs sage.combinat [1, 2, 3, 4] sage: C = GroupAlgebras(ZZ) @@ -105,13 +106,13 @@ def example(self, G=None): EXAMPLES:: - sage: GroupAlgebras(QQ['x']).example() # optional - sage.groups sage.modules + sage: GroupAlgebras(QQ['x']).example() # needs sage.groups sage.modules Algebra of Dihedral group of order 8 as a permutation group over Univariate Polynomial Ring in x over Rational Field An other group can be specified as optional argument:: - sage: GroupAlgebras(QQ).example(AlternatingGroup(4)) # optional - sage.groups sage.modules + sage: GroupAlgebras(QQ).example(AlternatingGroup(4)) # needs sage.groups sage.modules Algebra of Alternating group of order 4!/2 as a permutation group over Rational Field """ @@ -127,19 +128,20 @@ def __init_extra__(self): EXAMPLES:: - sage: A = GroupAlgebra(SymmetricGroup(4), QQ) # optional - sage.groups sage.modules - sage: B = GroupAlgebra(SymmetricGroup(3), ZZ) # optional - sage.groups sage.modules - sage: A.has_coerce_map_from(B) # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A = GroupAlgebra(SymmetricGroup(4), QQ) + sage: B = GroupAlgebra(SymmetricGroup(3), ZZ) + sage: A.has_coerce_map_from(B) True - sage: B.has_coerce_map_from(A) # optional - sage.groups sage.modules + sage: B.has_coerce_map_from(A) False - sage: A.has_coerce_map_from(ZZ) # optional - sage.groups sage.modules + sage: A.has_coerce_map_from(ZZ) True - sage: A.has_coerce_map_from(CC) # optional - sage.groups sage.modules + sage: A.has_coerce_map_from(CC) False - sage: A.has_coerce_map_from(SymmetricGroup(5)) # optional - sage.groups sage.modules + sage: A.has_coerce_map_from(SymmetricGroup(5)) False - sage: A.has_coerce_map_from(SymmetricGroup(2)) # optional - sage.groups sage.modules + sage: A.has_coerce_map_from(SymmetricGroup(2)) True """ if not self.base_ring().has_coerce_map_from(self.group()): @@ -155,8 +157,8 @@ def _latex_(self): EXAMPLES:: - sage: A = GroupAlgebra(KleinFourGroup(), ZZ) # optional - sage.groups sage.modules - sage: latex(A) # indirect doctest # optional - sage.groups sage.modules + sage: A = GroupAlgebra(KleinFourGroup(), ZZ) # needs sage.groups sage.modules + sage: latex(A) # indirect doctest # needs sage.groups sage.modules \Bold{Z}[\langle (3,4), (1,2) \rangle] """ from sage.misc.latex import latex @@ -168,9 +170,9 @@ def group(self): EXAMPLES:: - sage: GroupAlgebras(QQ).example(GL(3, GF(11))).group() # optional - sage.groups sage.modules sage.rings.finite_rings + sage: GroupAlgebras(QQ).example(GL(3, GF(11))).group() # needs sage.groups sage.modules General Linear Group of degree 3 over Finite Field of size 11 - sage: SymmetricGroup(10).algebra(QQ).group() # optional - sage.groups sage.modules + sage: SymmetricGroup(10).algebra(QQ).group() # needs sage.groups sage.modules Symmetric group of order 10! as a permutation group """ return self.basis().keys() @@ -198,7 +200,7 @@ def center_basis(self): EXAMPLES:: - sage: SymmetricGroup(3).algebra(QQ).center_basis() # optional - sage.groups sage.modules + sage: SymmetricGroup(3).algebra(QQ).center_basis() # needs sage.groups sage.modules ((), (2,3) + (1,2) + (1,3), (1,2,3) + (1,3,2)) .. SEEALSO:: @@ -220,16 +222,17 @@ def coproduct_on_basis(self, g): EXAMPLES:: - sage: A = CyclicPermutationGroup(6).algebra(ZZ); A # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A = CyclicPermutationGroup(6).algebra(ZZ); A Algebra of Cyclic group of order 6 as a permutation group over Integer Ring - sage: g = CyclicPermutationGroup(6).an_element(); g # optional - sage.groups sage.modules + sage: g = CyclicPermutationGroup(6).an_element(); g (1,2,3,4,5,6) - sage: A.coproduct_on_basis(g) # optional - sage.groups sage.modules + sage: A.coproduct_on_basis(g) (1,2,3,4,5,6) # (1,2,3,4,5,6) - sage: a = A.an_element(); a # optional - sage.groups sage.modules + sage: a = A.an_element(); a () + 3*(1,2,3,4,5,6) + 3*(1,3,5)(2,4,6) - sage: a.coproduct() # optional - sage.groups sage.modules + sage: a.coproduct() () # () + 3*(1,2,3,4,5,6) # (1,2,3,4,5,6) + 3*(1,3,5)(2,4,6) # (1,3,5)(2,4,6) """ from sage.categories.tensor import tensor @@ -246,16 +249,17 @@ def antipode_on_basis(self,g): EXAMPLES:: - sage: A = CyclicPermutationGroup(6).algebra(ZZ); A # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A = CyclicPermutationGroup(6).algebra(ZZ); A Algebra of Cyclic group of order 6 as a permutation group over Integer Ring - sage: g = CyclicPermutationGroup(6).an_element(); g # optional - sage.groups sage.modules + sage: g = CyclicPermutationGroup(6).an_element(); g (1,2,3,4,5,6) - sage: A.antipode_on_basis(g) # optional - sage.groups sage.modules + sage: A.antipode_on_basis(g) (1,6,5,4,3,2) - sage: a = A.an_element(); a # optional - sage.groups sage.modules + sage: a = A.an_element(); a () + 3*(1,2,3,4,5,6) + 3*(1,3,5)(2,4,6) - sage: a.antipode() # optional - sage.groups sage.modules + sage: a.antipode() () + 3*(1,5,3)(2,6,4) + 3*(1,6,5,4,3,2) """ return self.term(~g) @@ -270,12 +274,12 @@ def counit_on_basis(self,g): EXAMPLES:: - sage: A = CyclicPermutationGroup(6).algebra(ZZ); A # optional - sage.groups sage.modules + sage: A = CyclicPermutationGroup(6).algebra(ZZ); A # needs sage.groups sage.modules Algebra of Cyclic group of order 6 as a permutation group over Integer Ring - sage: g = CyclicPermutationGroup(6).an_element(); g # optional - sage.groups sage.modules + sage: g = CyclicPermutationGroup(6).an_element(); g # needs sage.groups sage.modules (1,2,3,4,5,6) - sage: A.counit_on_basis(g) # optional - sage.groups sage.modules + sage: A.counit_on_basis(g) # needs sage.groups sage.modules 1 """ return self.base_ring().one() @@ -290,12 +294,12 @@ def counit(self,x): EXAMPLES:: - sage: A = CyclicPermutationGroup(6).algebra(ZZ); A # optional - sage.groups sage.modules + sage: A = CyclicPermutationGroup(6).algebra(ZZ); A # needs sage.groups sage.modules Algebra of Cyclic group of order 6 as a permutation group over Integer Ring - sage: a = A.an_element(); a # optional - sage.groups sage.modules + sage: a = A.an_element(); a # needs sage.groups sage.modules () + 3*(1,2,3,4,5,6) + 3*(1,3,5)(2,4,6) - sage: a.counit() # optional - sage.groups sage.modules + sage: a.counit() # needs sage.groups sage.modules 7 """ return self.base_ring().sum(x.coefficients()) @@ -312,19 +316,20 @@ def is_integral_domain(self, proof=True): EXAMPLES:: - sage: S2 = SymmetricGroup(2) # optional - sage.groups - sage: GroupAlgebra(S2).is_integral_domain() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S2 = SymmetricGroup(2) + sage: GroupAlgebra(S2).is_integral_domain() False - sage: S1 = SymmetricGroup(1) # optional - sage.groups - sage: GroupAlgebra(S1).is_integral_domain() # optional - sage.groups sage.modules + sage: S1 = SymmetricGroup(1) + sage: GroupAlgebra(S1).is_integral_domain() True - sage: GroupAlgebra(S1, IntegerModRing(4)).is_integral_domain() # optional - sage.groups sage.modules + sage: GroupAlgebra(S1, IntegerModRing(4)).is_integral_domain() False - sage: GroupAlgebra(AbelianGroup(1)).is_integral_domain() # optional - sage.groups sage.modules + sage: GroupAlgebra(AbelianGroup(1)).is_integral_domain() True - sage: GroupAlgebra(AbelianGroup(2, [0,2])).is_integral_domain() # optional - sage.groups sage.modules + sage: GroupAlgebra(AbelianGroup(2, [0,2])).is_integral_domain() False - sage: GroupAlgebra(GL(2, ZZ)).is_integral_domain() # not implemented # optional - sage.groups sage.modules + sage: GroupAlgebra(GL(2, ZZ)).is_integral_domain() # not implemented False """ from sage.sets.set import Set @@ -394,22 +399,24 @@ def central_form(self): EXAMPLES:: - sage: QS3 = SymmetricGroup(3).algebra(QQ) # optional - sage.groups sage.modules - sage: A = QS3([2,3,1]) + QS3([3,1,2]) # optional - sage.groups sage.modules - sage: A.central_form() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: QS3 = SymmetricGroup(3).algebra(QQ) + sage: A = QS3([2,3,1]) + QS3([3,1,2]) + sage: A.central_form() B[(1,2,3)] - sage: QS4 = SymmetricGroup(4).algebra(QQ) # optional - sage.groups sage.modules - sage: B = sum(len(s.cycle_type()) * QS4(s) for s in Permutations(4)) # optional - sage.groups sage.modules - sage: B.central_form() # optional - sage.groups sage.modules + sage: QS4 = SymmetricGroup(4).algebra(QQ) + sage: B = sum(len(s.cycle_type()) * QS4(s) for s in Permutations(4)) + sage: B.central_form() 4*B[()] + 3*B[(1,2)] + 2*B[(1,2)(3,4)] + 2*B[(1,2,3)] + B[(1,2,3,4)] The following test fails due to a bug involving combinatorial free modules and the coercion system (see :trac:`28544`):: - sage: G = PermutationGroup([[(1,2,3),(4,5)], [(3,4)]]) # optional - sage.groups sage.modules - sage: QG = GroupAlgebras(QQ).example(G) # optional - sage.groups sage.modules - sage: s = sum(QG.basis()) # optional - sage.groups sage.modules - sage: s.central_form() # not tested # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: G = PermutationGroup([[(1,2,3),(4,5)], [(3,4)]]) + sage: QG = GroupAlgebras(QQ).example(G) + sage: s = sum(QG.basis()) + sage: s.central_form() # not tested B[()] + B[(4,5)] + B[(3,4,5)] + B[(2,3)(4,5)] + B[(2,3,4,5)] + B[(1,2)(3,4,5)] + B[(1,2,3,4,5)] diff --git a/src/sage/categories/groupoid.py b/src/sage/categories/groupoid.py index 9eee3750655..850e63a2c09 100644 --- a/src/sage/categories/groupoid.py +++ b/src/sage/categories/groupoid.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups +# sage.doctest: needs sage.groups r""" Groupoid """ @@ -52,7 +52,7 @@ def _repr_(self): sage: Groupoid(S8) Groupoid with underlying set Symmetric group of order 8! as a permutation group """ - return "Groupoid with underlying set %s"%self.__G + return "Groupoid with underlying set %s" % self.__G #def construction(self): # return (self.__class__, self.__G) diff --git a/src/sage/categories/groups.py b/src/sage/categories/groups.py index 569cfc0d36d..445ba111c09 100644 --- a/src/sage/categories/groups.py +++ b/src/sage/categories/groups.py @@ -42,7 +42,7 @@ def example(self): """ EXAMPLES:: - sage: Groups().example() # optional - sage.groups + sage: Groups().example() # needs sage.modules General Linear Group of degree 4 over Rational Field """ from sage.rings.rational_field import QQ @@ -69,13 +69,14 @@ def free(index_set=None, names=None, **kwds): EXAMPLES:: - sage: Groups.free(index_set=ZZ) # optional - sage.groups + sage: # needs sage.groups + sage: Groups.free(index_set=ZZ) Free group indexed by Integer Ring - sage: Groups().free(ZZ) # optional - sage.groups + sage: Groups().free(ZZ) Free group indexed by Integer Ring - sage: Groups().free(5) # optional - sage.groups + sage: Groups().free(5) Free Group on generators {x0, x1, x2, x3, x4} - sage: F. = Groups().free(); F # optional - sage.groups + sage: F. = Groups().free(); F Free Group on generators {x, y, z} """ from sage.rings.integer_ring import ZZ @@ -99,8 +100,8 @@ def group_generators(self): EXAMPLES:: - sage: A = AlternatingGroup(4) # optional - sage.groups - sage: A.group_generators() # optional - sage.groups + sage: A = AlternatingGroup(4) # needs sage.groups + sage: A.group_generators() # needs sage.groups Family ((2,3,4), (1,2,3)) """ from sage.sets.family import Family @@ -120,11 +121,12 @@ def monoid_generators(self): EXAMPLES:: - sage: A = AlternatingGroup(4) # optional - sage.groups - sage: A.monoid_generators() # optional - sage.groups + sage: # needs sage.groups + sage: A = AlternatingGroup(4) + sage: A.monoid_generators() Family ((2,3,4), (1,2,3)) - sage: F. = FreeGroup() # optional - sage.groups - sage: F.monoid_generators() # optional - sage.groups + sage: F. = FreeGroup() + sage: F.monoid_generators() Family (x, y, x^-1, y^-1) """ G = self.group_generators() @@ -142,8 +144,8 @@ def _test_inverse(self, **options): EXAMPLES:: - sage: G = SymmetricGroup(3) # optional - sage.groups - sage: G._test_inverse() # optional - sage.groups + sage: G = SymmetricGroup(3) # needs sage.groups + sage: G._test_inverse() # needs sage.groups """ tester = self._tester(**options) for x in tester.some_elements(): @@ -156,8 +158,8 @@ def semidirect_product(self, N, mapping, check=True): EXAMPLES:: - sage: G = Groups().example() # optional - sage.groups - sage: G.semidirect_product(G, Morphism(G, G)) # optional - sage.groups + sage: G = Groups().example() # needs sage.modules + sage: G.semidirect_product(G, Morphism(G, G)) # needs sage.modules Traceback (most recent call last): ... NotImplementedError: semidirect product of General Linear Group of degree 4 @@ -178,14 +180,14 @@ def holomorph(self): EXAMPLES:: - sage: G = Groups().example() # optional - sage.groups - sage: G.holomorph() # optional - sage.groups + sage: G = Groups().example() # needs sage.modules + sage: G.holomorph() # needs sage.modules Traceback (most recent call last): ... NotImplementedError: holomorph of General Linear Group of degree 4 over Rational Field not yet implemented """ - raise NotImplementedError("holomorph of %s not yet implemented"%self) + raise NotImplementedError("holomorph of %s not yet implemented" % self) def cayley_table(self, names='letters', elements=None): r""" @@ -246,11 +248,12 @@ def cayley_table(self, names='letters', elements=None): Permutation groups, matrix groups and abelian groups can all compute their multiplication tables. :: - sage: G = DiCyclicGroup(3) # optional - sage.groups - sage: T = G.cayley_table() # optional - sage.groups - sage: T.column_keys() # optional - sage.groups + sage: # needs sage.groups + sage: G = DiCyclicGroup(3) + sage: T = G.cayley_table() + sage: T.column_keys() ((), (5,6,7), ..., (1,4,2,3)(5,7)) - sage: T # optional - sage.groups + sage: T * a b c d e f g h i j k l +------------------------ a| a b c d e f g h i j k l @@ -268,8 +271,8 @@ def cayley_table(self, names='letters', elements=None): :: - sage: M = SL(2, 2) # optional - sage.groups - sage: M.cayley_table() # optional - sage.groups + sage: M = SL(2, 2) # needs sage.modules + sage: M.cayley_table() # needs sage.modules * a b c d e f +------------ a| a b c d e f @@ -282,8 +285,8 @@ def cayley_table(self, names='letters', elements=None): :: - sage: A = AbelianGroup([2, 3]) # optional - sage.groups - sage: A.cayley_table() # optional - sage.groups + sage: A = AbelianGroup([2, 3]) # needs sage.groups + sage: A.cayley_table() # needs sage.groups * a b c d e f +------------ a| a b c d e f @@ -301,8 +304,8 @@ def cayley_table(self, names='letters', elements=None): you can choose to just use the string representations of the elements themselves. :: - sage: C = CyclicPermutationGroup(11) # optional - sage.groups - sage: C.cayley_table(names='digits') # optional - sage.groups + sage: C = CyclicPermutationGroup(11) # needs sage.groups + sage: C.cayley_table(names='digits') # needs sage.groups * 00 01 02 03 04 05 06 07 08 09 10 +--------------------------------- 00| 00 01 02 03 04 05 06 07 08 09 10 @@ -319,9 +322,9 @@ def cayley_table(self, names='letters', elements=None): :: - sage: G = QuaternionGroup() # optional - sage.groups - sage: names = ['1', 'I', '-1', '-I', 'J', '-K', '-J', 'K'] # optional - sage.groups - sage: G.cayley_table(names=names) # optional - sage.groups + sage: G = QuaternionGroup() # needs sage.groups + sage: names = ['1', 'I', '-1', '-I', 'J', '-K', '-J', 'K'] + sage: G.cayley_table(names=names) # needs sage.groups * 1 I -1 -I J -K -J K +------------------------ 1| 1 I -1 -I J -K -J K @@ -335,8 +338,8 @@ def cayley_table(self, names='letters', elements=None): :: - sage: A = AbelianGroup([2, 2]) # optional - sage.groups - sage: A.cayley_table(names='elements') # optional - sage.groups + sage: A = AbelianGroup([2, 2]) # needs sage.groups + sage: A.cayley_table(names='elements') # needs sage.groups * 1 f1 f0 f0*f1 +------------------------ 1| 1 f1 f0 f0*f1 @@ -348,10 +351,11 @@ def cayley_table(self, names='letters', elements=None): routine behaves similarly, but changes an existing table "in-place." :: - sage: G = AlternatingGroup(3) # optional - sage.groups - sage: T = G.cayley_table() # optional - sage.groups - sage: T.change_names('digits') # optional - sage.groups - sage: T # optional - sage.groups + sage: # needs sage.groups + sage: G = AlternatingGroup(3) + sage: T = G.cayley_table() + sage: T.change_names('digits') + sage: T * 0 1 2 +------ 0| 0 1 2 @@ -363,11 +367,11 @@ def cayley_table(self, names='letters', elements=None): Elements will be coerced into the group as part of setting up the table. :: - sage: G = SL(2,ZZ) # optional - sage.groups - sage: G # optional - sage.groups + sage: # needs sage.modules + sage: G = SL(2,ZZ); G Special Linear Group of degree 2 over Integer Ring - sage: identity = matrix(ZZ, [[1,0], [0,1]]) # optional - sage.groups - sage: G.cayley_table(elements=[identity, -identity]) # optional - sage.groups + sage: identity = matrix(ZZ, [[1,0], [0,1]]) + sage: G.cayley_table(elements=[identity, -identity]) * a b +---- a| a b @@ -384,11 +388,11 @@ class provides even greater flexibility, including changing confirms that they form a closed subset in the group. :: - sage: from sage.matrix.operation_table import OperationTable # optional - sage.groups - sage: G = DiCyclicGroup(3) # optional - sage.groups - sage: commutator = lambda x, y: x*y*x^-1*y^-1 # optional - sage.groups - sage: T = OperationTable(G, commutator) # optional - sage.groups - sage: T # optional - sage.groups + sage: # needs sage.groups sage.modules + sage: from sage.matrix.operation_table import OperationTable + sage: G = DiCyclicGroup(3) + sage: commutator = lambda x, y: x*y*x^-1*y^-1 + sage: T = OperationTable(G, commutator); T . a b c d e f g h i j k l +------------------------ a| a a a a a a a a a a a a @@ -403,13 +407,12 @@ class provides even greater flexibility, including changing j| a b c a b c a c b a c b k| a b c a b c b a c b a c l| a b c a b c c b a c b a - - sage: trans = T.translation() # optional - sage.groups - sage: comm = [trans['a'], trans['b'], trans['c']] # optional - sage.groups - sage: comm # optional - sage.groups + sage: trans = T.translation() + sage: comm = [trans['a'], trans['b'], trans['c']] + sage: comm [(), (5,6,7), (5,7,6)] - sage: P = G.cayley_table(elements=comm) # optional - sage.groups - sage: P # optional - sage.groups + sage: P = G.cayley_table(elements=comm) + sage: P * a b c +------ a| a b c @@ -440,9 +443,9 @@ def conjugacy_class(self, g): EXAMPLES:: - sage: A = AbelianGroup([2, 2]) # optional - sage.groups - sage: c = A.conjugacy_class(A.an_element()) # optional - sage.groups - sage: type(c) # optional - sage.groups + sage: A = AbelianGroup([2, 2]) # needs sage.groups + sage: c = A.conjugacy_class(A.an_element()) # needs sage.groups + sage: type(c) # needs sage.groups """ from sage.groups.conjugacy_classes import ConjugacyClass @@ -455,16 +458,16 @@ def conjugacy_class(self): EXAMPLES:: - sage: D = DihedralGroup(5) # optional - sage.groups - sage: g = D((1,3,5,2,4)) # optional - sage.groups - sage: g.conjugacy_class() # optional - sage.groups + sage: D = DihedralGroup(5) # needs sage.groups + sage: g = D((1,3,5,2,4)) # needs sage.groups + sage: g.conjugacy_class() # needs sage.groups Conjugacy class of (1,3,5,2,4) in Dihedral group of order 10 as a permutation group - sage: H = MatrixGroup([matrix(GF(5), 2, [1,2, -1,1]), # optional - sage.groups sage.rings.finite_rings sage.modules + sage: H = MatrixGroup([matrix(GF(5), 2, [1,2, -1,1]), # needs sage.modules ....: matrix(GF(5), 2, [1,1, 0,1])]) - sage: h = H(matrix(GF(5), 2, [1,2, -1,1])) # optional - sage.groups sage.rings.finite_rings sage.modules - sage: h.conjugacy_class() # optional - sage.groups sage.rings.finite_rings sage.modules + sage: h = H(matrix(GF(5), 2, [1,2, -1,1])) # needs sage.modules + sage: h.conjugacy_class() # needs sage.groups sage.modules Conjugacy class of [1 2] [4 1] in Matrix group over Finite Field of size 5 with 2 generators ( @@ -472,15 +475,15 @@ def conjugacy_class(self): [4 1], [0 1] ) - sage: G = SL(2, GF(2)) # optional - sage.groups sage.rings.finite_rings sage.modules - sage: g = G.gens()[0] # optional - sage.groups sage.rings.finite_rings sage.modules - sage: g.conjugacy_class() # optional - sage.groups sage.rings.finite_rings sage.modules + sage: G = SL(2, GF(2)) # needs sage.modules + sage: g = G.gens()[0] # needs sage.modules + sage: g.conjugacy_class() # needs sage.modules Conjugacy class of [1 1] [0 1] in Special Linear Group of degree 2 over Finite Field of size 2 - sage: G = SL(2, QQ) # optional - sage.groups sage.modules - sage: g = G([[1,1], [0,1]]) # optional - sage.groups sage.modules - sage: g.conjugacy_class() # optional - sage.groups sage.modules + sage: G = SL(2, QQ) # needs sage.modules + sage: g = G([[1,1], [0,1]]) # needs sage.modules + sage: g.conjugacy_class() # needs sage.groups sage.modules Conjugacy class of [1 1] [0 1] in Special Linear Group of degree 2 over Rational Field """ @@ -511,13 +514,14 @@ def free(index_set=None, names=None, **kwds): EXAMPLES:: - sage: Groups.Commutative.free(index_set=ZZ) # optional - sage.groups + sage: # needs sage.groups + sage: Groups.Commutative.free(index_set=ZZ) Free abelian group indexed by Integer Ring - sage: Groups().Commutative().free(ZZ) # optional - sage.groups + sage: Groups().Commutative().free(ZZ) Free abelian group indexed by Integer Ring - sage: Groups().Commutative().free(5) # optional - sage.groups + sage: Groups().Commutative().free(5) Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z - sage: F. = Groups().Commutative().free(); F # optional - sage.groups + sage: F. = Groups().Commutative().free(); F Multiplicative Abelian group isomorphic to Z x Z x Z """ from sage.rings.integer_ring import ZZ @@ -574,11 +578,12 @@ def group_generators(self): EXAMPLES:: - sage: C5 = CyclicPermutationGroup(5) # optional - sage.groups - sage: C4 = CyclicPermutationGroup(4) # optional - sage.groups - sage: S4 = SymmetricGroup(3) # optional - sage.groups - sage: C = cartesian_product([C5, C4, S4]) # optional - sage.groups - sage: C.group_generators() # optional - sage.groups + sage: # needs sage.groups + sage: C5 = CyclicPermutationGroup(5) + sage: C4 = CyclicPermutationGroup(4) + sage: S4 = SymmetricGroup(3) + sage: C = cartesian_product([C5, C4, S4]) + sage: C.group_generators() Family (((1,2,3,4,5), (), ()), ((), (1,2,3,4), ()), ((), (), (1,2)), @@ -586,16 +591,17 @@ def group_generators(self): We check the other portion of :trac:`16718` is fixed:: - sage: len(C.j_classes()) # optional - sage.groups + sage: len(C.j_classes()) # needs sage.groups 1 An example with an infinitely generated group (a better output is needed):: - sage: G = Groups.free([1,2]) # optional - sage.groups - sage: H = Groups.free(ZZ) # optional - sage.groups - sage: C = cartesian_product([G, H]) # optional - sage.groups - sage: C.monoid_generators() # optional - sage.groups + sage: # needs sage.groups + sage: G = Groups.free([1,2]) + sage: H = Groups.free(ZZ) + sage: C = cartesian_product([G, H]) + sage: C.monoid_generators() Lazy family (gen(i))_{i in The Cartesian product of (...)} """ F = self.cartesian_factors() @@ -628,13 +634,13 @@ def order(self): EXAMPLES:: - sage: C = cartesian_product([SymmetricGroup(10), SL(2, GF(3))]) # optional - sage.groups sage.rings.finite_rings - sage: C.order() # optional - sage.groups sage.rings.finite_rings + sage: C = cartesian_product([SymmetricGroup(10), SL(2, GF(3))]) # needs sage.groups sage.rings.finite_rings + sage: C.order() # needs sage.groups sage.rings.finite_rings 87091200 TESTS:: - sage: C.order.__module__ # optional - sage.groups sage.rings.finite_rings + sage: C.order.__module__ # needs sage.groups sage.rings.finite_rings 'sage.categories.groups' .. TODO:: diff --git a/src/sage/categories/hecke_modules.py b/src/sage/categories/hecke_modules.py index ae3d638b06b..118e155654e 100644 --- a/src/sage/categories/hecke_modules.py +++ b/src/sage/categories/hecke_modules.py @@ -46,7 +46,7 @@ class HeckeModules(Category_module): sage: HeckeModules(IntegerRing()) Category of Hecke modules over Integer Ring - sage: HeckeModules(FiniteField(5)) # optional - sage.rings.finite_rings + sage: HeckeModules(FiniteField(5)) Category of Hecke modules over Finite Field of size 5 The base ring doesn't have to be a principal ideal domain:: @@ -64,7 +64,7 @@ def __init__(self, R): sage: TestSuite(HeckeModules(ZZ)).run() - sage: HeckeModules(Partitions(3)).run() # optional - sage.combinat + sage: HeckeModules(Partitions(3)).run() # needs sage.combinat Traceback (most recent call last): ... TypeError: R (=Partitions of the integer 3) must be a commutative ring @@ -121,15 +121,16 @@ def _Hom_(self, Y, category): EXAMPLES:: - sage: M = ModularForms(Gamma0(7), 4) # optional - sage.modular - sage: H = M._Hom_(M, category=HeckeModules(QQ)); H # optional - sage.modular + sage: # needs sage.modular + sage: M = ModularForms(Gamma0(7), 4) + sage: H = M._Hom_(M, category=HeckeModules(QQ)); H Set of Morphisms from Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(7) of weight 4 over Rational Field to Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(7) of weight 4 over Rational Field in Category of Hecke modules over Rational Field - sage: H.__class__ # optional - sage.modular + sage: H.__class__ - sage: TestSuite(H).run(skip=["_test_elements", "_test_an_element", "_test_elements_eq", # optional - sage.modular + sage: TestSuite(H).run(skip=["_test_elements", "_test_an_element", "_test_elements_eq", ....: "_test_elements_eq_reflexive", "_test_elements_eq_transitive", ....: "_test_elements_eq_symmetric", "_test_elements_neq", "_test_some_elements", ....: "_test_zero", "_test_additive_associativity", @@ -142,7 +143,7 @@ def _Hom_(self, Y, category): TESTS:: - sage: H = M._Hom_(M, category=HeckeModules(GF(5))); H # optional - sage.modular sage.rings.finite_rings + sage: H = M._Hom_(M, category=HeckeModules(GF(5))); H # needs sage.modular sage.rings.finite_rings Traceback (most recent call last): ... TypeError: Category of Hecke modules over Finite Field of size 5 @@ -150,7 +151,7 @@ def _Hom_(self, Y, category): """ # TODO: double check that it's the correct HeckeModules category below: if category is not None and not category.is_subcategory(HeckeModules(self.base_ring())): - raise TypeError("%s is not a subcategory of %s"%(category, HeckeModules(self.base_ring()))) + raise TypeError("%s is not a subcategory of %s" % (category, HeckeModules(self.base_ring()))) from sage.modular.hecke.homspace import HeckeModuleHomspace return HeckeModuleHomspace(self, Y, category=category) diff --git a/src/sage/categories/highest_weight_crystals.py b/src/sage/categories/highest_weight_crystals.py index 226d310eb35..35cec0173a6 100644 --- a/src/sage/categories/highest_weight_crystals.py +++ b/src/sage/categories/highest_weight_crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.graphs, sage.combinat +# sage.doctest: needs sage.combinat sage.graphs r""" Highest Weight Crystals """ diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py index 46c9de2ab04..22ba9d047fc 100644 --- a/src/sage/categories/homset.py +++ b/src/sage/categories/homset.py @@ -11,26 +11,27 @@ In the following, the :class:`Hom` object is indeed cached:: - sage: K = GF(17) # optional - sage.rings.finite_rings - sage: H = Hom(ZZ, K) # optional - sage.rings.finite_rings - sage: H # optional - sage.rings.finite_rings + sage: K = GF(17) + sage: H = Hom(ZZ, K) + sage: H Set of Homomorphisms from Integer Ring to Finite Field of size 17 - sage: H is Hom(ZZ, K) # optional - sage.rings.finite_rings + sage: H is Hom(ZZ, K) True Nonetheless, garbage collection occurs when the original references are overwritten:: - sage: for p in prime_range(200): # optional - sage.rings.finite_rings + sage: # needs sage.libs.pari + sage: for p in prime_range(200): ....: K = GF(p) ....: H = Hom(ZZ, K) sage: import gc sage: _ = gc.collect() - sage: from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn as FF # optional - sage.rings.finite_rings - sage: L = [x for x in gc.get_objects() if isinstance(x, FF)] # optional - sage.rings.finite_rings - sage: len(L) # optional - sage.rings.finite_rings + sage: from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn as FF + sage: L = [x for x in gc.get_objects() if isinstance(x, FF)] + sage: len(L) 1 - sage: L # optional - sage.rings.finite_rings + sage: L [Finite Field of size 199] AUTHORS: @@ -104,26 +105,26 @@ def Hom(X, Y, category=None, check=True): EXAMPLES:: - sage: V = VectorSpace(QQ, 3) # optional - sage.modules - sage: Hom(V, V) # optional - sage.modules + sage: V = VectorSpace(QQ, 3) # needs sage.modules + sage: Hom(V, V) # needs sage.modules Set of Morphisms (Linear Transformations) from Vector space of dimension 3 over Rational Field to Vector space of dimension 3 over Rational Field - sage: G = AlternatingGroup(3) # optional - sage.groups - sage: Hom(G, G) # optional - sage.groups + sage: G = AlternatingGroup(3) # needs sage.groups + sage: Hom(G, G) # needs sage.groups Set of Morphisms from Alternating group of order 3!/2 as a permutation group to Alternating group of order 3!/2 as a permutation group in Category of finite enumerated permutation groups - sage: Hom(ZZ, QQ, Sets()) # optional - sage.groups + sage: Hom(ZZ, QQ, Sets()) Set of Morphisms from Integer Ring to Rational Field in Category of sets - sage: Hom(FreeModule(ZZ, 1), FreeModule(QQ, 1)) # optional - sage.modules + sage: Hom(FreeModule(ZZ, 1), FreeModule(QQ, 1)) # needs sage.modules Set of Morphisms from Ambient free module of rank 1 over the principal ideal domain Integer Ring to Vector space of dimension 1 over Rational Field in Category of commutative additive groups - sage: Hom(FreeModule(QQ, 1), FreeModule(ZZ, 1)) # optional - sage.modules + sage: Hom(FreeModule(QQ, 1), FreeModule(ZZ, 1)) # needs sage.modules Set of Morphisms from Vector space of dimension 1 over Rational Field to Ambient free module of rank 1 over the principal ideal domain Integer Ring @@ -132,15 +133,16 @@ def Hom(X, Y, category=None, check=True): Here, we test against a memory leak that has been fixed at :trac:`11521` by using a weak cache:: - sage: for p in prime_range(10^3): # optional - sage.rings.finite_rings + sage: # needs sage.libs.pari + sage: for p in prime_range(10^3): ....: K = GF(p) ....: a = K(0) sage: import gc sage: gc.collect() # random 624 - sage: from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn as FF # optional - sage.rings.finite_rings - sage: L = [x for x in gc.get_objects() if isinstance(x, FF)] # optional - sage.rings.finite_rings - sage: len(L), L[0] # optional - sage.rings.finite_rings + sage: from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn as FF + sage: L = [x for x in gc.get_objects() if isinstance(x, FF)] + sage: len(L), L[0] (1, Finite Field of size 997) To illustrate the choice of the category, we consider the @@ -148,13 +150,13 @@ def Hom(X, Y, category=None, check=True): sage: X = ZZ; X Integer Ring - sage: Y = SymmetricGroup(3); Y # optional - sage.groups + sage: Y = SymmetricGroup(3); Y # needs sage.groups Symmetric group of order 3! as a permutation group By default, the smallest category containing both ``X`` and ``Y``, is used:: - sage: Hom(X, Y) # optional - sage.groups + sage: Hom(X, Y) # needs sage.groups Set of Morphisms from Integer Ring to Symmetric group of order 3! as a permutation group in Category of enumerated monoids @@ -162,13 +164,13 @@ def Hom(X, Y, category=None, check=True): Otherwise, if ``category`` is specified, then ``category`` is used, after checking that ``X`` and ``Y`` are indeed in ``category``:: - sage: Hom(X, Y, Magmas()) # optional - sage.groups + sage: Hom(X, Y, Magmas()) # needs sage.groups Set of Morphisms from Integer Ring to Symmetric group of order 3! as a permutation group in Category of magmas - sage: Hom(X, Y, Groups()) # optional - sage.groups + sage: Hom(X, Y, Groups()) # needs sage.groups Traceback (most recent call last): ... ValueError: Integer Ring is not in Category of groups @@ -195,10 +197,10 @@ def Hom(X, Y, category=None, check=True): Homset are unique parents:: - sage: k = GF(5) # optional - sage.rings.finite_rings - sage: H1 = Hom(k, k) # optional - sage.rings.finite_rings - sage: H2 = Hom(k, k) # optional - sage.rings.finite_rings - sage: H1 is H2 # optional - sage.rings.finite_rings + sage: k = GF(5) + sage: H1 = Hom(k, k) + sage: H2 = Hom(k, k) + sage: H1 is H2 True Moreover, if no category is provided, then the result is identical @@ -243,16 +245,17 @@ def Hom(X, Y, category=None, check=True): Variation on the theme:: - sage: U1 = FreeModule(ZZ, 2) # optional - sage.modules - sage: U2 = FreeModule(ZZ, 2, inner_product_matrix=matrix([[1,0], [0,-1]])) # optional - sage.modules - sage: U1 == U2, U1 is U2 # optional - sage.modules + sage: # needs sage.modules + sage: U1 = FreeModule(ZZ, 2) + sage: U2 = FreeModule(ZZ, 2, inner_product_matrix=matrix([[1,0], [0,-1]])) + sage: U1 == U2, U1 is U2 (False, False) - sage: V = ZZ^3 # optional - sage.modules - sage: H1 = Hom(U1, V); H2 = Hom(U2, V) # optional - sage.modules - sage: H1 == H2, H1 is H2 # optional - sage.modules + sage: V = ZZ^3 + sage: H1 = Hom(U1, V); H2 = Hom(U2, V) + sage: H1 == H2, H1 is H2 (False, False) - sage: H1 = Hom(V, U1); H2 = Hom(V, U2) # optional - sage.modules - sage: H1 == H2, H1 is H2 # optional - sage.modules + sage: H1 = Hom(V, U1); H2 = Hom(V, U2) + sage: H1 == H2, H1 is H2 (False, False) Since :trac:`11900`, the meet of the categories of the given arguments is @@ -298,17 +301,15 @@ def Hom(X, Y, category=None, check=True): Checks that the domain and codomain are in the specified category. Case of a non parent:: - sage: S = SimplicialComplex([[1,2], [1,4]]); S.rename("S") # optional - sage.graphs - sage: Hom(S, S, SimplicialComplexes()) # optional - sage.graphs + sage: # needs sage.graphs + sage: S = SimplicialComplex([[1,2], [1,4]]); S.rename("S") + sage: Hom(S, S, SimplicialComplexes()) Set of Morphisms from S to S in Category of finite simplicial complexes - - sage: Hom(Set(), S, Sets()) # optional - sage.graphs + sage: Hom(Set(), S, Sets()) Set of Morphisms from {} to S in Category of sets - - sage: Hom(S, Set(), Sets()) # optional - sage.graphs + sage: Hom(S, Set(), Sets()) Set of Morphisms from S to {} in Category of sets - - sage: H = Hom(S, S, ChainComplexes(QQ)) # optional - sage.graphs + sage: H = Hom(S, S, ChainComplexes(QQ)) Traceback (most recent call last): ... ValueError: S is not in Category of chain complexes over Rational Field @@ -317,15 +318,16 @@ def Hom(X, Y, category=None, check=True): and not ``X.category().is_subcategory(category)`` as it used to be before :trac:`16275` (see :trac:`15801` for a real use case):: + sage: # needs sage.graphs sage: class PermissiveCategory(Category): ....: def super_categories(self): return [Objects()] ....: def __contains__(self, X): return True sage: C = PermissiveCategory(); C.rename("Permissive category") - sage: S.category().is_subcategory(C) # optional - sage.graphs + sage: S.category().is_subcategory(C) False - sage: S in C # optional - sage.graphs + sage: S in C True - sage: Hom(S, S, C) # optional - sage.graphs + sage: Hom(S, S, C) Set of Morphisms from S to S in Permissive category With ``check=False``, uninitialized parents, as can appear upon @@ -339,6 +341,7 @@ def Hom(X, Y, category=None, check=True): Case of a non parent:: + sage: # needs sage.graphs sage: cls = type(SimplicialComplex([[1,2], [1,4]])) sage: S = unpickle_newobj(cls, ()) sage: H = Hom(S, S, Sets(), check=False) @@ -349,16 +352,16 @@ def Hom(X, Y, category=None, check=True): uninitialized parent:: sage: P. = QQ['x,y'] - sage: Q = P.quotient([x^2-1, y^2-1]) # optional - sage.libs.singular - sage: q = Q.an_element() # optional - sage.libs.singular - sage: explain_pickle(dumps(Q)) # optional - sage.libs.singular + sage: Q = P.quotient([x^2 - 1, y^2 - 1]) + sage: q = Q.an_element() # needs sage.libs.singular + sage: explain_pickle(dumps(Q)) # needs sage.libs.singular pg_... ... = pg_dynamic_class('QuotientRing_generic_with_category', (pg_QuotientRing_generic, pg_getattr(..., 'parent_class')), None, None, pg_QuotientRing_generic) si... = unpickle_newobj(..., ()) ... si... = pg_unpickle_MPolynomialRing_libsingular(..., ('x', 'y'), ...) si... = ... pg_Hom(si..., si..., ...) ... - sage: Q == loads(dumps(Q)) # optional - sage.libs.singular + sage: Q == loads(dumps(Q)) True Check that the ``_Hom_`` method of the ``category`` input is used:: @@ -504,24 +507,25 @@ def End(X, category=None): EXAMPLES:: - sage: V = VectorSpace(QQ, 3) # optional - sage.modules - sage: End(V) # optional - sage.modules + sage: V = VectorSpace(QQ, 3) # needs sage.modules + sage: End(V) # needs sage.modules Set of Morphisms (Linear Transformations) from Vector space of dimension 3 over Rational Field to Vector space of dimension 3 over Rational Field :: - sage: G = AlternatingGroup(3) # optional - sage.groups - sage: S = End(G); S # optional - sage.groups + sage: # needs sage.groups + sage: G = AlternatingGroup(3) + sage: S = End(G); S Set of Morphisms from Alternating group of order 3!/2 as a permutation group to Alternating group of order 3!/2 as a permutation group in Category of finite enumerated permutation groups sage: from sage.categories.homset import is_Endset - sage: is_Endset(S) # optional - sage.groups + sage: is_Endset(S) True - sage: S.domain() # optional - sage.groups + sage: S.domain() Alternating group of order 3!/2 as a permutation group To avoid creating superfluous categories, a homset in a category @@ -533,13 +537,14 @@ def End(X, category=None): groups currently implement nothing more than unital magmas about their homsets, we have:: - sage: G = GL(3, 3) # optional - sage.groups - sage: G.category() # optional - sage.groups + sage: # needs sage.groups + sage: G = GL(3, 3) + sage: G.category() Category of finite groups - sage: H = Hom(G, G) # optional - sage.groups - sage: H.homset_category() # optional - sage.groups + sage: H = Hom(G, G) + sage: H.homset_category() Category of finite groups - sage: H.category() # optional - sage.groups + sage: H.category() Category of endsets of unital magmas Similarly, a ring morphism just needs to preserve addition, @@ -578,29 +583,29 @@ class Homset(Set_generic): EXAMPLES:: - sage: H = Hom(QQ^2, QQ^3) # optional - sage.modules - sage: loads(H.dumps()) is H # optional - sage.modules + sage: H = Hom(QQ^2, QQ^3) # needs sage.modules + sage: loads(H.dumps()) is H # needs sage.modules True Homsets of unique parents are unique as well:: - sage: H = End(AffineSpace(2, names='x,y')) # optional - sage.modules - sage: loads(dumps(AffineSpace(2, names='x,y'))) is AffineSpace(2, names='x,y') # optional - sage.modules + sage: H = End(AffineSpace(2, names='x,y')) + sage: loads(dumps(AffineSpace(2, names='x,y'))) is AffineSpace(2, names='x,y') True - sage: loads(dumps(H)) is H # optional - sage.modules + sage: loads(dumps(H)) is H True Conversely, homsets of non-unique parents are non-unique:: - sage: P11 = ProductProjectiveSpaces(QQ, [1, 1]) # optional - sage.schemes - sage: H = End(P11) # optional - sage.schemes - sage: loads(dumps(P11)) is ProductProjectiveSpaces(QQ, [1, 1]) # optional - sage.schemes + sage: P11 = ProductProjectiveSpaces(QQ, [1, 1]) + sage: H = End(P11) + sage: loads(dumps(P11)) is ProductProjectiveSpaces(QQ, [1, 1]) False - sage: loads(dumps(P11)) == ProductProjectiveSpaces(QQ, [1, 1]) # optional - sage.schemes + sage: loads(dumps(P11)) == ProductProjectiveSpaces(QQ, [1, 1]) True - sage: loads(dumps(H)) is H # optional - sage.schemes + sage: loads(dumps(H)) is H False - sage: loads(dumps(H)) == H # optional - sage.schemes + sage: loads(dumps(H)) == H True """ def __init__(self, X, Y, category=None, base=None, check=True): @@ -613,7 +618,7 @@ def __init__(self, X, Y, category=None, base=None, check=True): sage: class MyHomset(Homset): ....: def _an_element_(self): ....: return sage.categories.morphism.SetMorphism(self, f) - sage: import __main__; __main__.MyHomset = MyHomset # fakes MyHomset being defined in a Python module + sage: import __main__; __main__.MyHomset = MyHomset # fakes MyHomset being defined in a Python module sage: H = MyHomset(X, Y, category=Monoids(), base = ZZ) sage: H Set of Morphisms from X to Y in Category of monoids @@ -643,12 +648,12 @@ def __init__(self, X, Y, category=None, base=None, check=True): sage: Hom(R, R, category=Sets()).base_ring() sage: Hom(R, R, category=Modules(QQ)).base_ring() Rational Field - sage: Hom(QQ^3, QQ^3, category=Modules(QQ)).base_ring() # optional - sage.modules + sage: Hom(QQ^3, QQ^3, category=Modules(QQ)).base_ring() # needs sage.modules Rational Field For whatever it's worth, the ``base`` arguments takes precedence:: - sage: MyHomset(ZZ^3, ZZ^3, base=QQ).base_ring() # optional - sage.modules + sage: MyHomset(ZZ^3, ZZ^3, base=QQ).base_ring() # needs sage.modules Rational Field """ self._domain = X @@ -658,7 +663,7 @@ def __init__(self, X, Y, category=None, base=None, check=True): self.__category = category if check: if not isinstance(category, Category): - raise TypeError("category (=%s) must be a category"%category) + raise TypeError("category (=%s) must be a category" % category) #if not X in category: # raise TypeError, "X (=%s) must be in category (=%s)"%(X, category) #if not Y in category: @@ -701,8 +706,8 @@ def __reduce__(self): EXAMPLES:: - sage: H = Hom(QQ^2, QQ^3) # optional - sage.modules - sage: H.__reduce__() # optional - sage.modules + sage: H = Hom(QQ^2, QQ^3) # needs sage.modules + sage: H.__reduce__() # needs sage.modules (, (Vector space of dimension 2 over Rational Field, Vector space of dimension 3 over Rational Field, @@ -712,18 +717,19 @@ def __reduce__(self): TESTS:: - sage: loads(H.dumps()) is H # optional - sage.modules + sage: loads(H.dumps()) is H # needs sage.modules True Homsets of non-unique parents are non-unique as well:: - sage: G = PermutationGroup([[(1, 2, 3), (4, 5)], [(3, 4)]]) # optional - sage.groups - sage: G is loads(dumps(G)) # optional - sage.groups + sage: # needs sage.groups + sage: G = PermutationGroup([[(1, 2, 3), (4, 5)], [(3, 4)]]) + sage: G is loads(dumps(G)) False - sage: H = Hom(G, G) # optional - sage.groups - sage: H is loads(dumps(H)) # optional - sage.groups + sage: H = Hom(G, G) + sage: H is loads(dumps(H)) False - sage: H == loads(dumps(H)) # optional - sage.groups + sage: H == loads(dumps(H)) True """ return Hom, (self._domain, self._codomain, self.__category, False) @@ -732,7 +738,7 @@ def _repr_(self): """ TESTS:: - sage: Hom(ZZ^2, QQ, category=Sets())._repr_() # optional - sage.modules + sage: Hom(ZZ^2, QQ, category=Sets())._repr_() # needs sage.modules 'Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Rational Field in Category of sets' """ return "Set of Morphisms from {} to {} in {}".format(self._domain, @@ -749,10 +755,10 @@ def __hash__(self): sage: hash(Hom(QQ, ZZ)) == hash((QQ, ZZ, QQ)) True - sage: E = EllipticCurve('37a') # optional - sage.symbolic - sage: H = E(0).parent(); H # optional - sage.symbolic + sage: E = EllipticCurve('37a') # needs sage.schemes + sage: H = E(0).parent(); H # needs sage.schemes Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field - sage: hash(H) == hash((H.domain(), H.codomain(), H.base())) # optional - sage.symbolic + sage: hash(H) == hash((H.domain(), H.codomain(), H.base())) # needs sage.schemes True """ return hash((self._domain, self._codomain, self.base())) @@ -773,8 +779,8 @@ def homset_category(self): EXAMPLES:: - sage: H = Hom(AlternatingGroup(4), AlternatingGroup(7)) # optional - sage.groups - sage: H.homset_category() # optional - sage.groups + sage: H = Hom(AlternatingGroup(4), AlternatingGroup(7)) # needs sage.groups + sage: H.homset_category() # needs sage.groups Category of finite enumerated permutation groups """ return self.__category @@ -785,9 +791,9 @@ def _element_constructor_(self, x, check=None, **options): EXAMPLES:: - sage: H = Hom(SymmetricGroup(4), SymmetricGroup(7)) # optional - sage.groups - sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map() # optional - sage.groups - sage: phi # optional - sage.groups + sage: H = Hom(SymmetricGroup(4), SymmetricGroup(7)) # needs sage.groups + sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map() # needs sage.groups + sage: phi # needs sage.groups Coercion morphism: From: Symmetric group of order 5! as a permutation group To: Symmetric group of order 6! as a permutation group @@ -799,7 +805,7 @@ def _element_constructor_(self, x, check=None, **options): collection, if there is a strong reference to its domain (which is the case here):: - sage: H(phi) # optional - sage.groups + sage: H(phi) # needs sage.groups Composite map: From: Symmetric group of order 4! as a permutation group To: Symmetric group of order 7! as a permutation group @@ -820,7 +826,7 @@ def _element_constructor_(self, x, check=None, **options): Also note that making a copy of the resulting map will automatically make strengthened copies of the composed maps:: - sage: copy(H(phi)) # optional - sage.groups + sage: copy(H(phi)) # needs sage.groups Composite map: From: Symmetric group of order 4! as a permutation group To: Symmetric group of order 7! as a permutation group @@ -906,24 +912,25 @@ def _element_constructor_(self, x, check=None, **options): TESTS:: - sage: G. = FreeGroup() # optional - sage.groups - sage: H = Hom(G, G) # optional - sage.groups - sage: H(H.identity()) # optional - sage.groups + sage: # needs sage.groups + sage: G. = FreeGroup() + sage: H = Hom(G, G) + sage: H(H.identity()) Identity endomorphism of Free Group on generators {x, y, z} - sage: H() # optional - sage.groups + sage: H() Traceback (most recent call last): ... TypeError: unable to convert 0 to an element of Set of Morphisms from Free Group on generators {x, y, z} to Free Group on generators {x, y, z} in Category of infinite groups - sage: H("whatever") # optional - sage.groups + sage: H("whatever") Traceback (most recent call last): ... TypeError: unable to convert 'whatever' to an element of Set of Morphisms from Free Group on generators {x, y, z} to Free Group on generators {x, y, z} in Category of infinite groups - sage: HH = Hom(H, H) # optional - sage.groups - sage: HH(HH.identity(), foo="bar") # optional - sage.groups + sage: HH = Hom(H, H) + sage: HH(HH.identity(), foo="bar") Traceback (most recent call last): ... NotImplementedError: no keywords are implemented for @@ -950,12 +957,12 @@ def _element_constructor_(self, x, check=None, **options): if x.domain() != self.domain(): mor = x.domain()._internal_coerce_map_from(self.domain()) if mor is None: - raise TypeError("Incompatible domains: x (=%s) cannot be an element of %s"%(x,self)) + raise TypeError("Incompatible domains: x (=%s) cannot be an element of %s" % (x,self)) x = x * mor if x.codomain() != self.codomain(): mor = self.codomain()._internal_coerce_map_from(x.codomain()) if mor is None: - raise TypeError("Incompatible codomains: x (=%s) cannot be an element of %s"%(x,self)) + raise TypeError("Incompatible codomains: x (=%s) cannot be an element of %s" % (x,self)) x = mor * x return x @@ -1003,45 +1010,47 @@ class of ``C`` will be inherited by *all* subcategories of Let's take a homset of finite commutative groups as example; at this point this is the simplest one to create (gosh):: + sage: # needs sage.groups sage: cat = Groups().Finite().Commutative() - sage: C3 = PermutationGroup([(1,2,3)]) # optional - sage.groups - sage: C3._refine_category_(cat) # optional - sage.groups - sage: C2 = PermutationGroup([(1,2)]) # optional - sage.groups - sage: C2._refine_category_(cat) # optional - sage.groups - sage: H = Hom(C3, C2, cat) # optional - sage.groups - sage: H.homset_category() # optional - sage.groups + sage: C3 = PermutationGroup([(1,2,3)]) + sage: C3._refine_category_(cat) + sage: C2 = PermutationGroup([(1,2)]) + sage: C2._refine_category_(cat) + sage: H = Hom(C3, C2, cat) + sage: H.homset_category() Category of finite commutative groups - sage: H.category() # optional - sage.groups + sage: H.category() Category of homsets of unital magmas - sage: cls = H._abstract_element_class; cls # optional - sage.groups + sage: cls = H._abstract_element_class; cls - sage: cls.__bases__ == (H.category().element_class, H.homset_category().morphism_class) # optional - sage.groups + sage: cls.__bases__ == (H.category().element_class, H.homset_category().morphism_class) True A morphism of finite commutative semigroups is also a morphism of semigroups, of magmas, ...; it thus inherits code from all those categories:: - sage: issubclass(cls, Semigroups().Finite().morphism_class) # optional - sage.groups + sage: # needs sage.groups + sage: issubclass(cls, Semigroups().Finite().morphism_class) True - sage: issubclass(cls, Semigroups().morphism_class) # optional - sage.groups + sage: issubclass(cls, Semigroups().morphism_class) True - sage: issubclass(cls, Magmas().Commutative().morphism_class) # optional - sage.groups + sage: issubclass(cls, Magmas().Commutative().morphism_class) True - sage: issubclass(cls, Magmas().morphism_class) # optional - sage.groups + sage: issubclass(cls, Magmas().morphism_class) True - sage: issubclass(cls, Sets().morphism_class) # optional - sage.groups + sage: issubclass(cls, Sets().morphism_class) True Recall that FiniteMonoids() is a full subcategory of ``Monoids()``, but not of ``FiniteSemigroups()``. Thus:: - sage: issubclass(cls, Monoids().Finite().Homsets().element_class) # optional - sage.groups + sage: issubclass(cls, Monoids().Finite().Homsets().element_class) # needs sage.groups True - sage: issubclass(cls, Semigroups().Finite().Homsets().element_class) # optional - sage.groups + sage: issubclass(cls, Semigroups().Finite().Homsets().element_class) # needs sage.groups False """ - class_name = "%s._abstract_element_class"%self.__class__.__name__ + class_name = "%s._abstract_element_class" % self.__class__.__name__ return dynamic_class(class_name, (self.category().element_class, self.homset_category().morphism_class)) @lazy_attribute @@ -1139,8 +1148,8 @@ def natural_map(self): Coercion morphism: From: Univariate Polynomial Ring in t over Integer Ring To: Univariate Polynomial Ring in t over Rational Field - sage: H = Hom(QQ['t'], GF(3)['t']) # optional - sage.rings.finite_rings - sage: H.natural_map() # optional - sage.rings.finite_rings + sage: H = Hom(QQ['t'], GF(3)['t']) + sage: H.natural_map() Traceback (most recent call last): ... TypeError: natural coercion morphism @@ -1186,8 +1195,8 @@ def one(self): EXAMPLES:: - sage: K = GaussianIntegers() # optional - sage.rings.number_field - sage: End(K).one() # optional - sage.rings.number_field + sage: K = GaussianIntegers() # needs sage.rings.number_field + sage: End(K).one() # needs sage.rings.number_field Identity endomorphism of Gaussian Integers in Number Field in I with defining polynomial x^2 + 1 with I = 1*I """ @@ -1230,21 +1239,22 @@ def reversed(self): EXAMPLES:: - sage: H = Hom(ZZ^2, ZZ^3); H # optional - sage.modules + sage: # needs sage.modules + sage: H = Hom(ZZ^2, ZZ^3); H Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Ambient free module of rank 3 over the principal ideal domain Integer Ring in Category of finite dimensional modules with basis over (euclidean domains and infinite enumerated sets and metric spaces) - sage: type(H) # optional - sage.modules + sage: type(H) - sage: H.reversed() # optional - sage.modules + sage: H.reversed() Set of Morphisms from Ambient free module of rank 3 over the principal ideal domain Integer Ring to Ambient free module of rank 2 over the principal ideal domain Integer Ring in Category of finite dimensional modules with basis over (euclidean domains and infinite enumerated sets and metric spaces) - sage: type(H.reversed()) # optional - sage.modules + sage: type(H.reversed()) """ return Hom(self.codomain(), self.domain(), diff --git a/src/sage/categories/homsets.py b/src/sage/categories/homsets.py index 7604ec9df72..794d79d304e 100644 --- a/src/sage/categories/homsets.py +++ b/src/sage/categories/homsets.py @@ -199,7 +199,7 @@ def _repr_object_names(self): except ValueError: assert isinstance(base_category, JoinCategory) object_names = ' and '.join(cat._repr_object_names() for cat in base_category.super_categories()) - return "homsets of %s"%(object_names) + return "homsets of %s" % (object_names) def super_categories(self): r""" diff --git a/src/sage/categories/hopf_algebras.py b/src/sage/categories/hopf_algebras.py index ecff3fd58cc..41e349690fe 100644 --- a/src/sage/categories/hopf_algebras.py +++ b/src/sage/categories/hopf_algebras.py @@ -67,18 +67,19 @@ def antipode(self): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example(); A # optional - sage.groups + sage: # needs sage.groups + sage: A = HopfAlgebrasWithBasis(QQ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: [a,b] = A.algebra_generators() # optional - sage.groups - sage: a, a.antipode() # optional - sage.groups + sage: [a,b] = A.algebra_generators() + sage: a, a.antipode() (B[(1,2,3)], B[(1,3,2)]) - sage: b, b.antipode() # optional - sage.groups + sage: b, b.antipode() (B[(1,3)], B[(1,3)]) TESTS:: - sage: all(x.antipode() * x == A.one() for x in A.basis()) # optional - sage.groups + sage: all(x.antipode() * x == A.one() for x in A.basis()) # needs sage.groups True """ return self.parent().antipode(self) @@ -136,9 +137,9 @@ def antipode(self): EXAMPLES:: - sage: A = SteenrodAlgebra(3) # optional - sage.combinat sage.modules - sage: a = A.an_element() # optional - sage.combinat sage.modules - sage: a, a.antipode() # optional - sage.combinat sage.modules + sage: A = SteenrodAlgebra(3) # needs sage.combinat sage.modules + sage: a = A.an_element() # needs sage.combinat sage.modules + sage: a, a.antipode() # needs sage.combinat sage.modules (2 Q_1 Q_3 P(2,1), Q_1 Q_3 P(2,1)) """ return self.parent().antipode(self) @@ -205,11 +206,12 @@ def antipode_by_coercion(self, x): EXAMPLES:: - sage: N = NonCommutativeSymmetricFunctions(QQ) # optional - sage.combinat - sage: R = N.ribbon() # optional - sage.combinat - sage: R.antipode_by_coercion.__module__ # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: N = NonCommutativeSymmetricFunctions(QQ) + sage: R = N.ribbon() + sage: R.antipode_by_coercion.__module__ 'sage.categories.hopf_algebras' - sage: R.antipode_by_coercion(R[1,3,1]) # optional - sage.combinat + sage: R.antipode_by_coercion(R[1,3,1]) -R[2, 1, 2] """ R = self.realization_of().a_realization() diff --git a/src/sage/categories/hopf_algebras_with_basis.py b/src/sage/categories/hopf_algebras_with_basis.py index ea401896ca0..615fc4eae06 100644 --- a/src/sage/categories/hopf_algebras_with_basis.py +++ b/src/sage/categories/hopf_algebras_with_basis.py @@ -33,44 +33,45 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): We now show how to use a simple Hopf algebra, namely the group algebra of the dihedral group (see also AlgebrasWithBasis):: - sage: A = C.example(); A # optional - sage.groups + sage: A = C.example(); A # needs sage.groups An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: A.__custom_name = "A" # optional - sage.groups - sage: A.category() # optional - sage.groups + sage: A.rename("A") # needs sage.groups + sage: A.category() # needs sage.groups Category of finite dimensional hopf algebras with basis over Rational Field - sage: A.one_basis() # optional - sage.groups + sage: A.one_basis() # needs sage.groups () - sage: A.one() # optional - sage.groups + sage: A.one() # needs sage.groups B[()] - sage: A.base_ring() # optional - sage.groups + sage: A.base_ring() # needs sage.groups Rational Field - sage: A.basis().keys() # optional - sage.groups + sage: A.basis().keys() # needs sage.groups Dihedral group of order 6 as a permutation group - sage: [a,b] = A.algebra_generators() # optional - sage.groups - sage: a, b # optional - sage.groups + sage: # needs sage.groups + sage: [a,b] = A.algebra_generators() + sage: a, b (B[(1,2,3)], B[(1,3)]) - sage: a^3, b^2 # optional - sage.groups + sage: a^3, b^2 (B[()], B[()]) - sage: a*b # optional - sage.groups + sage: a*b B[(1,2)] - sage: A.product # todo: not quite ... # optional - sage.groups + sage: A.product # todo: not quite ... # needs sage.groups - sage: A.product(b, b) # optional - sage.groups + sage: A.product(b, b) # needs sage.groups B[()] - sage: A.zero().coproduct() # optional - sage.groups + sage: A.zero().coproduct() # needs sage.groups 0 - sage: A.zero().coproduct().parent() # optional - sage.groups + sage: A.zero().coproduct().parent() # needs sage.groups A # A - sage: a.coproduct() # optional - sage.groups + sage: a.coproduct() # needs sage.groups B[(1,2,3)] # B[(1,2,3)] - sage: TestSuite(A).run(verbose=True) # optional - sage.groups + sage: TestSuite(A).run(verbose=True) # needs sage.groups running ._test_additive_associativity() . . . pass running ._test_an_element() . . . pass running ._test_antipode() . . . pass @@ -101,33 +102,33 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): running ._test_prod() . . . pass running ._test_some_elements() . . . pass running ._test_zero() . . . pass - sage: A.__class__ # optional - sage.groups + sage: A.__class__ # needs sage.groups - sage: A.element_class # optional - sage.groups + sage: A.element_class # needs sage.groups Let us look at the code for implementing A:: - sage: A?? # todo: not implemented # optional - sage.groups + sage: A?? # not implemented # needs sage.groups TESTS:: - sage: TestSuite(A).run() # optional - sage.groups - sage: TestSuite(C).run() # optional - sage.groups + sage: TestSuite(A).run() # needs sage.groups + sage: TestSuite(C).run() """ def example(self, G=None): """ Returns an example of algebra with basis:: - sage: HopfAlgebrasWithBasis(QQ['x']).example() # optional - sage.groups + sage: HopfAlgebrasWithBasis(QQ['x']).example() # needs sage.groups An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Univariate Polynomial Ring in x over Rational Field An other group can be specified as optional argument:: - sage: HopfAlgebrasWithBasis(QQ).example(SymmetricGroup(4)) # optional - sage.groups + sage: HopfAlgebrasWithBasis(QQ).example(SymmetricGroup(4)) # needs sage.groups An example of Hopf algebra with basis: the group algebra of the Symmetric group of order 4! as a permutation group over Rational Field """ @@ -179,12 +180,13 @@ def antipode_on_basis(self, x): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example() # optional - sage.groups - sage: W = A.basis().keys(); W # optional - sage.groups + sage: # needs sage.groups + sage: A = HopfAlgebrasWithBasis(QQ).example() + sage: W = A.basis().keys(); W Dihedral group of order 6 as a permutation group - sage: w = W.gen(0); w # optional - sage.groups + sage: w = W.gen(0); w (1,2,3) - sage: A.antipode_on_basis(w) # optional - sage.groups + sage: A.antipode_on_basis(w) B[(1,3,2)] """ @@ -200,19 +202,20 @@ def antipode(self): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(ZZ).example(); A # optional - sage.groups + sage: # needs sage.groups + sage: A = HopfAlgebrasWithBasis(ZZ).example(); A An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Integer Ring - sage: A = HopfAlgebrasWithBasis(QQ).example() # optional - sage.groups - sage: [a,b] = A.algebra_generators() # optional - sage.groups - sage: a, A.antipode(a) # optional - sage.groups + sage: A = HopfAlgebrasWithBasis(QQ).example() + sage: [a,b] = A.algebra_generators() + sage: a, A.antipode(a) (B[(1,2,3)], B[(1,3,2)]) - sage: b, A.antipode(b) # optional - sage.groups + sage: b, A.antipode(b) (B[(1,3)], B[(1,3)]) TESTS:: - sage: all(A.antipode(x) * x == A.one() for x in A.basis()) # optional - sage.groups + sage: all(A.antipode(x) * x == A.one() for x in A.basis()) # needs sage.groups True """ if self.antipode_on_basis is not NotImplemented: @@ -244,13 +247,13 @@ def _test_antipode(self, **options): TESTS:: - sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon() # optional - sage.combinat - sage: R._test_antipode() # optional - sage.combinat + sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon() # needs sage.combinat sage.modules + sage: R._test_antipode() # needs sage.combinat sage.modules :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat - sage: s._test_antipode() # optional - sage.combinat + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: s._test_antipode() # needs sage.combinat sage.modules """ tester = self._tester(**options) diff --git a/src/sage/categories/integral_domains.py b/src/sage/categories/integral_domains.py index ca910a16e60..b6e6f59a196 100644 --- a/src/sage/categories/integral_domains.py +++ b/src/sage/categories/integral_domains.py @@ -45,7 +45,7 @@ def __contains__(self, x): """ EXAMPLES:: - sage: GF(4, "a") in IntegralDomains() # optional - sage.rings.finite_rings + sage: GF(4, "a") in IntegralDomains() # needs sage.rings.finite_rings True sage: QQ in IntegralDomains() True @@ -108,10 +108,10 @@ def is_integral_domain(self, proof=True): sage: Parent(QQ, category=IntegralDomains()).is_integral_domain() True - sage: L. = LazyLaurentSeriesRing(QQ) # optional - sage.combinat - sage: L.is_integral_domain() # optional - sage.combinat + sage: L. = LazyLaurentSeriesRing(QQ) # needs sage.combinat + sage: L.is_integral_domain() # needs sage.combinat True - sage: L.is_integral_domain(proof=True) # optional - sage.combinat + sage: L.is_integral_domain(proof=True) # needs sage.combinat True """ return True diff --git a/src/sage/categories/kac_moody_algebras.py b/src/sage/categories/kac_moody_algebras.py index 040387a3325..52f738243b8 100644 --- a/src/sage/categories/kac_moody_algebras.py +++ b/src/sage/categories/kac_moody_algebras.py @@ -43,12 +43,12 @@ def example(self, n=2): EXAMPLES:: sage: from sage.categories.kac_moody_algebras import KacMoodyAlgebras - sage: KacMoodyAlgebras(QQ).example() # optional - sage.combinat sage.modules + sage: KacMoodyAlgebras(QQ).example() # needs sage.combinat sage.modules Lie algebra of ['A', 2] in the Chevalley basis We can specify the rank of the example:: - sage: KacMoodyAlgebras(QQ).example(4) # optional - sage.combinat sage.modules + sage: KacMoodyAlgebras(QQ).example(4) # needs sage.combinat sage.modules Lie algebra of ['A', 4] in the Chevalley basis """ from sage.algebras.lie_algebras.classical_lie_algebra import LieAlgebraChevalleyBasis @@ -61,8 +61,8 @@ def cartan_type(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['A', 2]) # optional - sage.combinat sage.modules - sage: L.cartan_type() # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type=['A', 2]) # needs sage.combinat sage.modules + sage: L.cartan_type() # needs sage.combinat sage.modules ['A', 2] """ return self._cartan_type @@ -73,8 +73,8 @@ def weyl_group(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['A', 2]) # optional - sage.combinat sage.modules - sage: L.weyl_group() # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type=['A', 2]) # needs sage.combinat sage.modules + sage: L.weyl_group() # needs sage.combinat sage.modules Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) """ from sage.combinat.root_system.weyl_group import WeylGroup diff --git a/src/sage/categories/lambda_bracket_algebras.py b/src/sage/categories/lambda_bracket_algebras.py index c8277ae1f26..40cb5ed70c4 100644 --- a/src/sage/categories/lambda_bracket_algebras.py +++ b/src/sage/categories/lambda_bracket_algebras.py @@ -45,7 +45,7 @@ def __classcall_private__(cls, R, check=True): EXAMPLES:: - sage: LieConformalAlgebras(QuaternionAlgebra(2)) # optional - sage.combinat sage.modules + sage: LieConformalAlgebras(QuaternionAlgebra(2)) # needs sage.combinat sage.modules Traceback (most recent call last): ValueError: base must be a commutative ring got Quaternion Algebra (-1, -1) with base ring Rational Field @@ -118,8 +118,8 @@ def ideal(self, *gens, **kwds): EXAMPLES:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ) # optional - sage.combinat sage.modules - sage: Vir.ideal() # optional - sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ) # needs sage.combinat sage.modules + sage: Vir.ideal() # needs sage.combinat sage.modules Traceback (most recent call last): ... NotImplementedError: ideals of Lie Conformal algebras are not implemented yet @@ -138,21 +138,22 @@ def bracket(self, rhs): The brackets of the Virasoro Lie conformal algebra:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 # optional - sage.combinat sage.modules - sage: L.bracket(L) # optional - sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 # needs sage.combinat sage.modules + sage: L.bracket(L) # needs sage.combinat sage.modules {0: TL, 1: 2*L, 3: 1/2*C} - sage: L.bracket(L.T()) # optional - sage.combinat sage.modules + sage: L.bracket(L.T()) # needs sage.combinat sage.modules {0: 2*T^(2)L, 1: 3*TL, 2: 4*L, 4: 2*C} Now with a current algebra:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1') # optional - sage.combinat sage.modules - sage: V.gens() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1') + sage: V.gens() (B[alpha[1]], B[alphacheck[1]], B[-alpha[1]], B['K']) - sage: E = V.0; H = V.1; F = V.2 # optional - sage.combinat sage.modules - sage: H.bracket(H) # optional - sage.combinat sage.modules + sage: E = V.0; H = V.1; F = V.2 + sage: H.bracket(H) {1: 2*B['K']} - sage: E.bracket(F) # optional - sage.combinat sage.modules + sage: E.bracket(F) {0: B[alphacheck[1]], 1: B['K']} """ return self._bracket_(rhs) @@ -171,21 +172,22 @@ def _bracket_(self, rhs): The brackets of the Virasoro Lie conformal Algebra:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 # optional - sage.combinat sage.modules - sage: L._bracket_(L) # optional - sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 # needs sage.combinat sage.modules + sage: L._bracket_(L) # needs sage.combinat sage.modules {0: TL, 1: 2*L, 3: 1/2*C} - sage: L._bracket_(L.T()) # optional - sage.combinat sage.modules + sage: L._bracket_(L.T()) # needs sage.combinat sage.modules {0: 2*T^(2)L, 1: 3*TL, 2: 4*L, 4: 2*C} Now with a current algebra:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1') # optional - sage.combinat sage.modules - sage: V.gens() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1') + sage: V.gens() (B[alpha[1]], B[alphacheck[1]], B[-alpha[1]], B['K']) - sage: E = V.0; H = V.1; F = V.2 # optional - sage.combinat sage.modules - sage: H._bracket_(H) # optional - sage.combinat sage.modules + sage: E = V.0; H = V.1; F = V.2 + sage: H._bracket_(H) {1: 2*B['K']} - sage: E._bracket_(F) # optional - sage.combinat sage.modules + sage: E._bracket_(F) {0: B[alphacheck[1]], 1: B['K']} """ @@ -196,16 +198,17 @@ def nproduct(self, rhs, n): EXAMPLES:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 # optional - sage.combinat sage.modules - sage: L.nproduct(L, 3) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 + sage: L.nproduct(L, 3) 1/2*C - sage: L.nproduct(L.T(), 0) # optional - sage.combinat sage.modules + sage: L.nproduct(L.T(), 0) 2*T^(2)L - sage: V = lie_conformal_algebras.Affine(QQ, 'A1') # optional - sage.combinat sage.modules - sage: E = V.0; H = V.1; F = V.2 # optional - sage.combinat sage.modules - sage: E.nproduct(H, 0) == - 2*E # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1') + sage: E = V.0; H = V.1; F = V.2 + sage: E.nproduct(H, 0) == - 2*E True - sage: E.nproduct(F, 1) # optional - sage.combinat sage.modules + sage: E.nproduct(F, 1) B['K'] """ return self._nproduct_(rhs,n) @@ -221,16 +224,17 @@ def _nproduct_(self, rhs, n): EXAMPLES:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 # optional - sage.combinat sage.modules - sage: L._nproduct_(L, 3) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ); L = Vir.0 + sage: L._nproduct_(L, 3) 1/2*C - sage: L._nproduct_(L.T(), 0) # optional - sage.combinat sage.modules + sage: L._nproduct_(L.T(), 0) 2*T^(2)L - sage: V = lie_conformal_algebras.Affine(QQ, 'A1') # optional - sage.combinat sage.modules - sage: E = V.0; H = V.1; F = V.2 # optional - sage.combinat sage.modules - sage: E._nproduct_(H, 0) == - 2*E # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1') + sage: E = V.0; H = V.1; F = V.2 + sage: E._nproduct_(H, 0) == - 2*E True - sage: E._nproduct_(F, 1) # optional - sage.combinat sage.modules + sage: E._nproduct_(F, 1) B['K'] """ if n >= 0: @@ -255,14 +259,15 @@ def T(self, n=1): EXAMPLES:: - sage: Vir = lie_conformal_algebras.Virasoro(QQ) # optional - sage.combinat sage.modules - sage: Vir.inject_variables() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: Vir = lie_conformal_algebras.Virasoro(QQ) + sage: Vir.inject_variables() Defining L, C - sage: L.T() # optional - sage.combinat sage.modules + sage: L.T() TL - sage: L.T(3) # optional - sage.combinat sage.modules + sage: L.T(3) 6*T^(3)L - sage: C.T() # optional - sage.combinat sage.modules + sage: C.T() 0 """ diff --git a/src/sage/categories/lambda_bracket_algebras_with_basis.py b/src/sage/categories/lambda_bracket_algebras_with_basis.py index bb0e30908b4..62fe41f3336 100644 --- a/src/sage/categories/lambda_bracket_algebras_with_basis.py +++ b/src/sage/categories/lambda_bracket_algebras_with_basis.py @@ -25,7 +25,7 @@ class LambdaBracketAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis() # needs sage.rings.number_field Category of Lie conformal algebras with basis over Algebraic Field """ class ElementMethods: @@ -36,14 +36,15 @@ def index(self): EXAMPLES:: - sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # optional - sage.combinat sage.modules - sage: V.inject_variables() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) + sage: V.inject_variables() Defining L, G, C - sage: G.T(3).index() # optional - sage.combinat sage.modules + sage: G.T(3).index() ('G', 3) - sage: v = V.an_element(); v # optional - sage.combinat sage.modules + sage: v = V.an_element(); v L + G + C - sage: v.index() # optional - sage.combinat sage.modules + sage: v.index() Traceback (most recent call last): ... ValueError: index can only be computed for monomials, got L + G + C @@ -63,14 +64,15 @@ class FinitelyGeneratedAsLambdaBracketAlgebra(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar) # optional - sage.rings.number_field - sage: C1 = C.WithBasis().FinitelyGenerated(); C1 # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar) + sage: C1 = C.WithBasis().FinitelyGenerated(); C1 Category of finitely generated Lie conformal algebras with basis over Algebraic Field - sage: C2 = C.FinitelyGenerated().WithBasis(); C2 # optional - sage.rings.number_field + sage: C2 = C.FinitelyGenerated().WithBasis(); C2 Category of finitely generated Lie conformal algebras with basis over Algebraic Field - sage: C1 is C2 # optional - sage.rings.number_field + sage: C1 is C2 True """ class Graded(GradedModulesCategory): @@ -80,8 +82,8 @@ class Graded(GradedModulesCategory): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar) # optional - sage.rings.number_field - sage: C.WithBasis().FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar) # needs sage.rings.number_field + sage: C.WithBasis().FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated Lie conformal algebras with basis over Algebraic Field """ @@ -94,8 +96,8 @@ def degree_on_basis(self, m): EXAMPLES:: - sage: V = lie_conformal_algebras.Virasoro(QQ) # optional - sage.combinat sage.modules - sage: V.degree_on_basis(('L', 2)) # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Virasoro(QQ) # needs sage.combinat sage.modules + sage: V.degree_on_basis(('L', 2)) # needs sage.combinat sage.modules 4 """ if m[0] in self._central_elements: diff --git a/src/sage/categories/lattice_posets.py b/src/sage/categories/lattice_posets.py index 3872ca9b51f..f14fa364415 100644 --- a/src/sage/categories/lattice_posets.py +++ b/src/sage/categories/lattice_posets.py @@ -66,8 +66,8 @@ def meet(self, x, y): EXAMPLES:: - sage: D = LatticePoset((divisors(30), attrcall("divides"))) # optional - sage.combinat - sage: D.meet( D(6), D(15) ) # optional - sage.combinat + sage: D = LatticePoset((divisors(30), attrcall("divides"))) # needs sage.graphs sage.modules + sage: D.meet( D(6), D(15) ) # needs sage.graphs sage.modules 3 """ @@ -82,7 +82,7 @@ def join(self, x, y): EXAMPLES:: - sage: D = LatticePoset((divisors(60), attrcall("divides"))) # optional - sage.combinat - sage: D.join( D(6), D(10) ) # optional - sage.combinat + sage: D = LatticePoset((divisors(60), attrcall("divides"))) # needs sage.graphs sage.modules + sage: D.join( D(6), D(10) ) # needs sage.graphs sage.modules 30 """ diff --git a/src/sage/categories/lie_algebras.py b/src/sage/categories/lie_algebras.py index 0bd0c3185e7..7244eab161b 100644 --- a/src/sage/categories/lie_algebras.py +++ b/src/sage/categories/lie_algebras.py @@ -70,8 +70,8 @@ class LieAlgebras(Category_over_base_ring): TESTS:: - sage: C = LieAlgebras(QQ) # needs sage.combinat sage.modules - sage: TestSuite(C).run() # needs sage.combinat sage.modules + sage: C = LieAlgebras(QQ) + sage: TestSuite(C).run() sage: TestSuite(C.example()).run() # needs sage.combinat sage.modules .. TODO:: @@ -189,14 +189,14 @@ def extra_super_categories(self): [Category of finite sets] sage: LieAlgebras(ZZ).FiniteDimensional().extra_super_categories() [] - sage: C = LieAlgebras(GF(5)).FiniteDimensional() # needs sage.rings.finite_rings - sage: C.is_subcategory(Sets().Finite()) # needs sage.rings.finite_rings + sage: C = LieAlgebras(GF(5)).FiniteDimensional() + sage: C.is_subcategory(Sets().Finite()) True sage: C = LieAlgebras(ZZ).FiniteDimensional() sage: C.is_subcategory(Sets().Finite()) False - sage: C = LieAlgebras(GF(5)).WithBasis().FiniteDimensional() # needs sage.rings.finite_rings - sage: C.is_subcategory(Sets().Finite()) # needs sage.rings.finite_rings + sage: C = LieAlgebras(GF(5)).WithBasis().FiniteDimensional() + sage: C.is_subcategory(Sets().Finite()) True """ if self.base_ring() in Sets().Finite(): @@ -209,8 +209,8 @@ class Nilpotent(CategoryWithAxiom_over_base_ring): TESTS:: - sage: C = LieAlgebras(QQ).Nilpotent() # needs sage.combinat sage.modules - sage: TestSuite(C).run() # needs sage.combinat sage.modules + sage: C = LieAlgebras(QQ).Nilpotent() + sage: TestSuite(C).run() """ class ParentMethods: @abstract_method @@ -301,7 +301,7 @@ def universal_enveloping_algebra(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules sage: L.universal_enveloping_algebra() # needs sage.combinat sage.modules Noncommutative Multivariate Polynomial Ring in b0, b1, b2 over Rational Field, nc-relations: {} @@ -334,7 +334,7 @@ def _construct_UEA(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules sage: L._construct_UEA() # needs sage.combinat sage.modules Noncommutative Multivariate Polynomial Ring in b0, b1, b2 over Rational Field, nc-relations: {} @@ -342,7 +342,7 @@ def _construct_UEA(self): :: sage: L = LieAlgebra(QQ, 3, 'x', abelian=True) # needs sage.combinat sage.modules - sage: L.universal_enveloping_algebra() # indirect doctest # needs sage.combinat sage.modules + sage: L.universal_enveloping_algebra() # indirect doctest # needs sage.combinat sage.modules Multivariate Polynomial Ring in x0, x1, x2 over Rational Field """ @@ -398,8 +398,8 @@ def module(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: L.module() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L.module() # needs sage.modules Vector space of dimension 3 over Rational Field """ @@ -414,10 +414,10 @@ def from_vector(self, v, order=None, coerce=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: u = L.from_vector(vector(QQ, (1, 0, 0))); u # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: u = L.from_vector(vector(QQ, (1, 0, 0))); u # needs sage.modules (1, 0, 0) - sage: parent(u) is L # needs sage.combinat sage.modules + sage: parent(u) is L # needs sage.modules True """ @@ -452,9 +452,9 @@ def subalgebra(self, gens, names=None, index_set=None, category=None): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # needs sage.combinat sage.modules - sage: L.subalgebra([2*a - c, b + c]) # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules + sage: L.subalgebra([2*a - c, b + c]) # needs sage.modules An example of a finite dimensional Lie algebra with basis: the 2-dimensional abelian Lie algebra over Rational Field with basis matrix: @@ -480,9 +480,9 @@ def ideal(self, *gens, **kwds): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # needs sage.combinat sage.modules - sage: L.ideal([2*a - c, b + c]) # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules + sage: L.ideal([2*a - c, b + c]) # needs sage.modules An example of a finite dimensional Lie algebra with basis: the 2-dimensional abelian Lie algebra over Rational Field with basis matrix: @@ -530,9 +530,9 @@ def killing_form(self, x, y): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # needs sage.combinat sage.modules - sage: L.killing_form(a, b + c) # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules + sage: L.killing_form(a, b + c) # needs sage.modules 0 """ @@ -596,8 +596,8 @@ def is_solvable(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: L.is_solvable() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L.is_solvable() # needs sage.modules True """ @@ -608,8 +608,8 @@ def is_nilpotent(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: L.is_nilpotent() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L.is_nilpotent() # needs sage.modules True """ @@ -866,10 +866,10 @@ def to_vector(self, order=None): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: u = L((1, 0, 0)).to_vector(); u # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: u = L((1, 0, 0)).to_vector(); u # needs sage.modules (1, 0, 0) - sage: parent(u) # needs sage.combinat sage.modules + sage: parent(u) # needs sage.modules Vector space of dimension 3 over Rational Field """ @@ -901,9 +901,9 @@ def killing_form(self, x): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # needs sage.combinat sage.modules - sage: a.killing_form(b) # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules + sage: a.killing_form(b) # needs sage.modules 0 """ return self.parent().killing_form(self, x) @@ -959,7 +959,7 @@ def __init__(self, domain, codomain): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules sage: f = L.lift # needs sage.combinat sage.modules We skip the category test since this is currently not an element of @@ -975,8 +975,8 @@ def _call_(self, x): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.combinat sage.modules - sage: a, b, c = L.lie_algebra_generators() # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: a, b, c = L.lie_algebra_generators() # needs sage.modules sage: L.lift(3*a + b - c) # needs sage.combinat sage.modules 3*b0 + b1 - b2 """ diff --git a/src/sage/categories/lie_algebras_with_basis.py b/src/sage/categories/lie_algebras_with_basis.py index 4f6cf394651..6eaebfde844 100644 --- a/src/sage/categories/lie_algebras_with_basis.py +++ b/src/sage/categories/lie_algebras_with_basis.py @@ -34,13 +34,13 @@ def example(self, gens=None): EXAMPLES:: - sage: LieAlgebras(QQ).WithBasis().example() # optional - sage.combinat + sage: LieAlgebras(QQ).WithBasis().example() # needs sage.combinat sage.modules An example of a Lie algebra: the abelian Lie algebra on the generators indexed by Partitions over Rational Field Another set of generators can be specified as an optional argument:: - sage: LieAlgebras(QQ).WithBasis().example(Compositions()) # optional - sage.combinat + sage: LieAlgebras(QQ).WithBasis().example(Compositions()) # needs sage.combinat sage.modules An example of a Lie algebra: the abelian Lie algebra on the generators indexed by Compositions of non-negative integers over Rational Field @@ -64,8 +64,8 @@ def _basis_key(self, x): TESTS:: - sage: L = LieAlgebras(QQ).WithBasis().example() # optional - sage.combinat - sage: L._basis_key(Partition([3,1])) # optional - sage.combinat + sage: L = LieAlgebras(QQ).WithBasis().example() # needs sage.combinat sage.modules + sage: L._basis_key(Partition([3,1])) # needs sage.combinat sage.modules [3, 1] """ return x @@ -79,8 +79,8 @@ def bracket_on_basis(self, x, y): EXAMPLES:: - sage: L = LieAlgebras(QQ).WithBasis().example() # optional - sage.combinat - sage: L.bracket_on_basis(Partition([3,1]), Partition([2,2,1,1])) # optional - sage.combinat + sage: L = LieAlgebras(QQ).WithBasis().example() # needs sage.combinat sage.modules + sage: L.bracket_on_basis(Partition([3,1]), Partition([2,2,1,1])) # needs sage.combinat sage.modules 0 """ @@ -95,8 +95,8 @@ def module(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).WithBasis().example() # optional - sage.combinat - sage: L.module() # optional - sage.combinat + sage: L = LieAlgebras(QQ).WithBasis().example() # needs sage.combinat sage.modules + sage: L.module() # needs sage.combinat sage.modules Free module generated by Partitions over Rational Field """ from sage.combinat.free_module import CombinatorialFreeModule @@ -119,10 +119,10 @@ def from_vector(self, v, order=None, coerce=False): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat - sage: u = L.from_vector(vector(QQ, (1, 0, 0))); u # optional - sage.combinat + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: u = L.from_vector(vector(QQ, (1, 0, 0))); u # needs sage.modules (1, 0, 0) - sage: parent(u) is L # optional - sage.combinat + sage: parent(u) is L # needs sage.modules True """ B = self.basis() @@ -135,14 +135,14 @@ def dimension(self): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.combinat - sage: L.dimension() # optional - sage.combinat + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L.dimension() # needs sage.modules 3 :: - sage: L = LieAlgebra(QQ, 'x,y', {('x','y'): {'x':1}}) # optional - sage.combinat sage.modules - sage: L.dimension() # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, 'x,y', {('x','y'): {'x':1}}) # needs sage.combinat sage.modules + sage: L.dimension() # needs sage.combinat sage.modules 2 """ return self.basis().cardinality() @@ -154,8 +154,8 @@ def pbw_basis(self, basis_key=None, **kwds): EXAMPLES:: - sage: L = lie_algebras.sl(QQ, 2) # optional - sage.combinat sage.modules - sage: PBW = L.pbw_basis() # optional - sage.combinat sage.modules + sage: L = lie_algebras.sl(QQ, 2) # needs sage.combinat sage.modules + sage: PBW = L.pbw_basis() # needs sage.combinat sage.modules """ from sage.algebras.lie_algebras.poincare_birkhoff_witt \ import PoincareBirkhoffWittBasis @@ -173,11 +173,12 @@ def _bracket_(self, y): EXAMPLES:: - sage: L = LieAlgebras(QQ).WithBasis().example() # optional - sage.combinat - sage: G = L.lie_algebra_generators() # optional - sage.combinat - sage: x = G[Partition([4,3,3,1])] # optional - sage.combinat - sage: y = G[Partition([6,1])] # optional - sage.combinat - sage: x.bracket(y) # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebras(QQ).WithBasis().example() + sage: G = L.lie_algebra_generators() + sage: x = G[Partition([4,3,3,1])] + sage: y = G[Partition([6,1])] + sage: x.bracket(y) 0 """ P = self.parent() @@ -206,8 +207,8 @@ def to_vector(self, order=None): EXAMPLES:: - sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # optional - sage.modules - sage: L.an_element().to_vector() # optional - sage.modules + sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example() # needs sage.modules + sage: L.an_element().to_vector() # needs sage.modules (0, 0, 0) .. TODO:: @@ -224,15 +225,16 @@ def lift(self): EXAMPLES:: - sage: S = SymmetricGroup(3).algebra(QQ) # optional - sage.groups - sage: L = LieAlgebra(associative=S) # optional - sage.groups - sage: x = L.gen(3) # optional - sage.groups - sage: y = L.gen(1) # optional - sage.groups - sage: x.lift() # optional - sage.groups + sage: # needs sage.groups + sage: S = SymmetricGroup(3).algebra(QQ) + sage: L = LieAlgebra(associative=S) + sage: x = L.gen(3) + sage: y = L.gen(1) + sage: x.lift() b3 - sage: y.lift() # optional - sage.groups + sage: y.lift() b1 - sage: x * y # optional - sage.groups + sage: x * y b1*b3 + b4 - b5 """ P = self.parent() diff --git a/src/sage/categories/lie_conformal_algebras.py b/src/sage/categories/lie_conformal_algebras.py index 4e59d4758b0..ee48889dd0b 100644 --- a/src/sage/categories/lie_conformal_algebras.py +++ b/src/sage/categories/lie_conformal_algebras.py @@ -152,16 +152,16 @@ class LieConformalAlgebras(Category_over_base_ring): Some subcategories:: - sage: LieConformalAlgebras(QQbar).FinitelyGenerated().WithBasis() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).FinitelyGenerated().WithBasis() # needs sage.rings.number_field Category of finitely generated Lie conformal algebras with basis over Algebraic Field In addition we support functorial constructions ``Graded`` and ``Super``. These functors commute:: - sage: CGS = LieConformalAlgebras(AA).Graded().Super(); CGS # optional - sage.rings.number_field + sage: CGS = LieConformalAlgebras(AA).Graded().Super(); CGS # needs sage.rings.number_field Category of H-graded super Lie conformal algebras over Algebraic Real Field - sage: CGS is LieConformalAlgebras(AA).Super().Graded() # optional - sage.rings.number_field + sage: CGS is LieConformalAlgebras(AA).Super().Graded() # needs sage.rings.number_field True That is, we only consider gradings on super Lie conformal algebras @@ -169,7 +169,7 @@ class LieConformalAlgebras(Category_over_base_ring): The base ring needs to be a commutative ring:: - sage: LieConformalAlgebras(QuaternionAlgebra(2)) # optional - sage.combinat sage.modules + sage: LieConformalAlgebras(QuaternionAlgebra(2)) # needs sage.combinat sage.modules Traceback (most recent call last): ValueError: base must be a commutative ring got Quaternion Algebra (-1, -1) with base ring Rational Field @@ -221,7 +221,7 @@ def example(self): EXAMPLES:: - sage: LieConformalAlgebras(QQ).example() # optional - sage.combinat sage.modules + sage: LieConformalAlgebras(QQ).example() # needs sage.combinat sage.modules The Virasoro Lie conformal algebra over Rational Field """ from sage.algebras.lie_conformal_algebras.virasoro_lie_conformal_algebra\ @@ -254,27 +254,28 @@ def _test_jacobi(self, **options): By default, this method tests only the elements returned by ``self.some_elements()``:: - sage: V = lie_conformal_algebras.Affine(QQ, 'B2') # optional - sage.combinat sage.modules - sage: V._test_jacobi() # long time (6 seconds) # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'B2') # needs sage.combinat sage.modules + sage: V._test_jacobi() # long time (6 seconds) # needs sage.combinat sage.modules It works for super Lie conformal algebras too:: - sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # optional - sage.combinat sage.modules - sage: V._test_jacobi() # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # needs sage.combinat sage.modules + sage: V._test_jacobi() # needs sage.combinat sage.modules We can use specific elements by passing the ``elements`` keyword argument:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1', names=('e', 'h', 'f')) # optional - sage.combinat sage.modules - sage: V.inject_variables() # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # needs sage.combinat sage.modules + ....: names=('e', 'h', 'f')) + sage: V.inject_variables() # needs sage.combinat sage.modules Defining e, h, f, K - sage: V._test_jacobi(elements=(e, 2*f+h, 3*h)) # optional - sage.combinat sage.modules + sage: V._test_jacobi(elements=(e, 2*f+h, 3*h)) # needs sage.combinat sage.modules TESTS:: sage: wrongdict = {('a', 'a'): {0: {('b', 0): 1}}, ('b', 'a'): {0: {('a', 0): 1}}} - sage: V = LieConformalAlgebra(QQ, wrongdict, names=('a', 'b'), parity=(1, 0)) # optional - sage.combinat sage.modules - sage: V._test_jacobi() # optional - sage.combinat sage.modules + sage: V = LieConformalAlgebra(QQ, wrongdict, names=('a', 'b'), parity=(1, 0)) # needs sage.combinat sage.modules + sage: V._test_jacobi() # needs sage.combinat sage.modules Traceback (most recent call last): ... AssertionError: {(0, 0): -3*a} != {} @@ -325,10 +326,10 @@ def is_even_odd(self): EXAMPLES:: - sage: R = lie_conformal_algebras.NeveuSchwarz(QQ) # optional - sage.combinat sage.modules - sage: R.inject_variables() # optional - sage.combinat sage.modules + sage: R = lie_conformal_algebras.NeveuSchwarz(QQ) # needs sage.combinat sage.modules + sage: R.inject_variables() # needs sage.combinat sage.modules Defining L, G, C - sage: G.is_even_odd() # optional - sage.combinat sage.modules + sage: G.is_even_odd() # needs sage.combinat sage.modules 1 """ return 0 diff --git a/src/sage/categories/lie_conformal_algebras_with_basis.py b/src/sage/categories/lie_conformal_algebras_with_basis.py index 6f31b6b4cca..bedf8934fc4 100644 --- a/src/sage/categories/lie_conformal_algebras_with_basis.py +++ b/src/sage/categories/lie_conformal_algebras_with_basis.py @@ -27,7 +27,7 @@ class LieConformalAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis() # needs sage.rings.number_field Category of Lie conformal algebras with basis over Algebraic Field """ class Super(SuperModulesCategory): @@ -36,7 +36,7 @@ class Super(SuperModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(AA).WithBasis().Super() # optional - sage.rings.number_field + sage: LieConformalAlgebras(AA).WithBasis().Super() # needs sage.rings.number_field Category of super Lie conformal algebras with basis over Algebraic Real Field """ @@ -53,9 +53,9 @@ def _even_odd_on_basis(self, m): EXAMPLES:: - sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # optional - sage.combinat sage.modules - sage: B = V._indices # optional - sage.combinat sage.modules - sage: V._even_odd_on_basis(B(('G', 1))) # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # needs sage.combinat sage.modules + sage: B = V._indices # needs sage.combinat sage.modules + sage: V._even_odd_on_basis(B(('G', 1))) # needs sage.combinat sage.modules 1 """ return self._parity[self.monomial((m[0],0))] @@ -66,7 +66,7 @@ class Graded(GradedLieConformalAlgebrasCategory): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis().Super().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis().Super().Graded() # needs sage.rings.number_field Category of H-graded super Lie conformal algebras with basis over Algebraic Field """ @@ -77,7 +77,7 @@ class Graded(GradedLieConformalAlgebrasCategory): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis().Graded() # needs sage.rings.number_field Category of H-graded Lie conformal algebras with basis over Algebraic Field """ @@ -88,11 +88,11 @@ class FinitelyGeneratedAsLambdaBracketAlgebra(CategoryWithAxiom_over_base_ring): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar) # optional - sage.rings.number_field - sage: CWF = C.WithBasis().FinitelyGenerated(); CWF # optional - sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar) # needs sage.rings.number_field + sage: CWF = C.WithBasis().FinitelyGenerated(); CWF # needs sage.rings.number_field Category of finitely generated Lie conformal algebras with basis over Algebraic Field - sage: CWF is C.FinitelyGenerated().WithBasis() # optional - sage.rings.number_field + sage: CWF is C.FinitelyGenerated().WithBasis() # needs sage.rings.number_field True """ class Super(SuperModulesCategory): @@ -102,7 +102,7 @@ class Super(SuperModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(AA).WithBasis().FinitelyGenerated().Super() # optional - sage.rings.number_field + sage: LieConformalAlgebras(AA).WithBasis().FinitelyGenerated().Super() # needs sage.rings.number_field Category of super finitely generated Lie conformal algebras with basis over Algebraic Real Field """ @@ -113,11 +113,11 @@ class Graded(GradedModulesCategory): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated() # optional - sage.rings.number_field - sage: C.Graded().Super() # optional - sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated() # needs sage.rings.number_field + sage: C.Graded().Super() # needs sage.rings.number_field Category of H-graded super finitely generated Lie conformal algebras with basis over Algebraic Field - sage: C.Graded().Super() is C.Super().Graded() # optional - sage.rings.number_field + sage: C.Graded().Super() is C.Super().Graded() # needs sage.rings.number_field True """ def _repr_object_names(self): @@ -126,8 +126,8 @@ def _repr_object_names(self): EXAMPLES:: - sage: C = LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated() # optional - sage.rings.number_field - sage: C.Super().Graded() # optional - sage.rings.number_field + sage: C = LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated() # needs sage.rings.number_field + sage: C.Super().Graded() # needs sage.rings.number_field Category of H-graded super finitely generated Lie conformal algebras with basis over Algebraic Field """ return "H-graded {}".format(self.base_category()._repr_object_names()) @@ -139,7 +139,7 @@ class Graded(GradedLieConformalAlgebrasCategory): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).WithBasis().FinitelyGenerated().Graded() # needs sage.rings.number_field Category of H-graded finitely generated Lie conformal algebras with basis over Algebraic Field """ diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index 83c403323cd..ad49bd42892 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.graphs sage.combinat +# sage.doctest: needs sage.graphs sage.combinat r""" Loop Crystals """ diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py index 178361b2961..603e68ad186 100644 --- a/src/sage/categories/magmas.py +++ b/src/sage/categories/magmas.py @@ -383,11 +383,11 @@ def is_field(self, proof=True): EXAMPLES:: - sage: SymmetricGroup(1).algebra(QQ).is_field() # optional - sage.groups + sage: SymmetricGroup(1).algebra(QQ).is_field() # needs sage.groups True - sage: SymmetricGroup(1).algebra(ZZ).is_field() # optional - sage.groups + sage: SymmetricGroup(1).algebra(ZZ).is_field() # needs sage.groups False - sage: SymmetricGroup(2).algebra(QQ).is_field() # optional - sage.groups + sage: SymmetricGroup(2).algebra(QQ).is_field() # needs sage.groups False """ if not self.base_ring().is_field(proof): @@ -540,8 +540,8 @@ def is_empty(self): EXAMPLES:: - sage: S = SymmetricGroup(2) # optional - sage.groups - sage: S.is_empty() # optional - sage.groups + sage: S = SymmetricGroup(2) # needs sage.groups + sage: S.is_empty() # needs sage.groups False sage: M = Monoids().example() @@ -550,7 +550,7 @@ def is_empty(self): TESTS:: - sage: S.is_empty.__module__ # optional - sage.groups + sage: S.is_empty.__module__ # needs sage.groups 'sage.categories.magmas' sage: M.is_empty.__module__ 'sage.categories.magmas' @@ -638,7 +638,7 @@ def one(self): EXAMPLES:: - sage: cartesian_product([QQ, ZZ, RR]).one() + sage: cartesian_product([QQ, ZZ, RR]).one() # needs sage.rings.real_mpfr (1, 1, 1.00000000000000) """ return self._cartesian_product_of_elements( @@ -665,21 +665,21 @@ def __invert__(self): EXAMPLES:: - sage: C = cartesian_product([QQ, ZZ, RR, GF(5)]) # optional - sage.rings.finite_rings - sage: c = C([2,-1,2,2]); c # optional - sage.rings.finite_rings + sage: C = cartesian_product([QQ, ZZ, RR, GF(5)]) + sage: c = C([2,-1,2,2]); c # needs sage.rings.real_mpfr (2, -1, 2.00000000000000, 2) - sage: ~c # optional - sage.rings.finite_rings + sage: ~c # needs sage.rings.real_mpfr (1/2, -1, 0.500000000000000, 3) This fails as soon as one of the entries is not invertible:: - sage: ~C([0,2,2,2]) # optional - sage.rings.finite_rings + sage: ~C([0,2,2,2]) Traceback (most recent call last): ... ZeroDivisionError: rational division by zero - sage: ~C([2,2,2,2]) # optional - sage.rings.finite_rings + sage: ~C([2,2,2,2]) # needs sage.rings.real_mpfr (1/2, 1/2, 0.500000000000000, 3) """ # variant without coercion: @@ -724,11 +724,12 @@ def one(self): EXAMPLES:: - sage: from sage.combinat.root_system.extended_affine_weyl_group import ExtendedAffineWeylGroup # optional - sage.combinat sage.groups - sage: PvW0 = ExtendedAffineWeylGroup(['A',2,1]).PvW0() # optional - sage.combinat sage.groups - sage: PvW0 in Magmas().Unital().Realizations() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: from sage.combinat.root_system.extended_affine_weyl_group import ExtendedAffineWeylGroup + sage: PvW0 = ExtendedAffineWeylGroup(['A',2,1]).PvW0() + sage: PvW0 in Magmas().Unital().Realizations() True - sage: PvW0.one() # optional - sage.combinat sage.groups + sage: PvW0.one() 1 """ return self(self.realization_of().a_realization().one()) @@ -884,8 +885,8 @@ def multiplication_table(self, names='letters', elements=None): The default is to represent elements as lowercase ASCII letters. :: - sage: G = CyclicPermutationGroup(5) # optional - sage.groups - sage: G.multiplication_table() # optional - sage.groups + sage: G = CyclicPermutationGroup(5) # needs sage.groups + sage: G.multiplication_table() # needs sage.groups * a b c d e +---------- a| a b c d e @@ -902,10 +903,10 @@ def multiplication_table(self, names='letters', elements=None): sage: from sage.categories.examples.finite_semigroups import LeftRegularBand sage: L = LeftRegularBand(('a', 'b')) - sage: T = L.multiplication_table(names='digits') # optional - sage.modules - sage: T.column_keys() # optional - sage.modules + sage: T = L.multiplication_table(names='digits') # needs sage.modules + sage: T.column_keys() # needs sage.modules ('a', 'ab', 'b', 'ba') - sage: T # optional - sage.modules + sage: T # needs sage.modules * 0 1 2 3 +-------- 0| 0 1 1 1 @@ -918,7 +919,7 @@ def multiplication_table(self, names='letters', elements=None): sage: L = LeftRegularBand(('a', 'b', 'c')) sage: elts = sorted(L.list()) - sage: L.multiplication_table(elements=elts) # optional - sage.modules + sage: L.multiplication_table(elements=elts) # needs sage.modules * a b c d e f g h i j k l m n o +------------------------------ a| a b c d e b b c c c d d e e e @@ -947,7 +948,7 @@ def multiplication_table(self, names='letters', elements=None): sage: L = LeftRegularBand(('a','b','c')) sage: elts=['a', 'c', 'ac', 'ca'] - sage: L.multiplication_table(names='elements', elements=elts) # optional - sage.modules + sage: L.multiplication_table(names='elements', elements=elts) # needs sage.modules * 'a' 'c' 'ac' 'ca' +-------------------- 'a'| 'a' 'ac' 'ac' 'ac' @@ -960,16 +961,17 @@ def multiplication_table(self, names='letters', elements=None): :class:`~sage.matrix.operation_table.OperationTable` for more comprehensive documentation. :: - sage: G = AlternatingGroup(3) # optional - sage.groups - sage: T = G.multiplication_table() # optional - sage.groups sage.modules - sage: T.column_keys() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: G = AlternatingGroup(3) + sage: T = G.multiplication_table() + sage: T.column_keys() ((), (1,2,3), (1,3,2)) - sage: T.translation() # optional - sage.groups sage.modules + sage: T.translation() {'a': (), 'b': (1,2,3), 'c': (1,3,2)} - sage: T.change_names(['x', 'y', 'z']) # optional - sage.groups sage.modules - sage: T.translation() # optional - sage.groups sage.modules + sage: T.change_names(['x', 'y', 'z']) + sage: T.translation() {'x': (), 'y': (1,2,3), 'z': (1,3,2)} - sage: T # optional - sage.groups sage.modules + sage: T * x y z +------ x| x y z @@ -1084,12 +1086,13 @@ def product(self, left, right): sage: x * x (1/4, 1, 1) - sage: A = SymmetricGroupAlgebra(QQ, 3) # optional - sage.groups - sage: x = cartesian_product([A([1,3,2]), A([2,3,1])]) # optional - sage.groups - sage: y = cartesian_product([A([1,3,2]), A([2,3,1])]) # optional - sage.groups - sage: cartesian_product([A,A]).product(x,y) # optional - sage.groups + sage: # needs sage.groups sage.modules + sage: A = SymmetricGroupAlgebra(QQ, 3) + sage: x = cartesian_product([A([1,3,2]), A([2,3,1])]) + sage: y = cartesian_product([A([1,3,2]), A([2,3,1])]) + sage: cartesian_product([A,A]).product(x,y) B[(0, [1, 2, 3])] + B[(1, [3, 1, 2])] - sage: x*y # optional - sage.groups + sage: x*y B[(0, [1, 2, 3])] + B[(1, [3, 1, 2])] """ prods = ((a * b) for a, b in zip(left.cartesian_factors(), @@ -1138,9 +1141,9 @@ def product(self, x, y): Here is a more elaborate example involving a sub algebra:: - sage: Z = SymmetricGroup(5).algebra(QQ).center() # optional - sage.groups - sage: B = Z.basis() # optional - sage.groups - sage: B[3] * B[2] # optional - sage.groups + sage: Z = SymmetricGroup(5).algebra(QQ).center() # needs sage.groups + sage: B = Z.basis() # needs sage.groups + sage: B[3] * B[2] # needs sage.groups 4*B[2] + 6*B[3] + 5*B[6] """ assert x in self @@ -1162,18 +1165,19 @@ def product_by_coercion(self, left, right): EXAMPLES:: - sage: Out = Sets().WithRealizations().example().Out(); Out # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: Out = Sets().WithRealizations().example().Out(); Out The subset algebra of {1, 2, 3} over Rational Field in the Out basis - sage: Out.product # optional - sage.combinat sage.modules + sage: Out.product - sage: Out.product.__module__ # optional - sage.combinat sage.modules + sage: Out.product.__module__ 'sage.categories.magmas' - sage: x = Out.an_element() # optional - sage.combinat sage.modules - sage: y = Out.an_element() # optional - sage.combinat sage.modules - sage: Out.product(x, y) # optional - sage.combinat sage.modules + sage: x = Out.an_element() + sage: y = Out.an_element() + sage: Out.product(x, y) Out[{}] + 4*Out[{1}] + 9*Out[{2}] + Out[{1, 2}] """ diff --git a/src/sage/categories/magmatic_algebras.py b/src/sage/categories/magmatic_algebras.py index 171f564534e..9d37608569d 100644 --- a/src/sage/categories/magmatic_algebras.py +++ b/src/sage/categories/magmatic_algebras.py @@ -110,10 +110,10 @@ def algebra_generators(self): EXAMPLES:: - sage: F = AlgebrasWithBasis(QQ).example(); F # optional - sage.combinat sage.modules + sage: F = AlgebrasWithBasis(QQ).example(); F # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: F.algebra_generators() # optional - sage.combinat sage.modules + sage: F.algebra_generators() # needs sage.combinat sage.modules Family (B[word: a], B[word: b], B[word: c]) """ @@ -136,13 +136,13 @@ def algebra_generators(self): EXAMPLES:: - sage: D4 = DescentAlgebra(QQ, 4).B() # optional - sage.combinat sage.modules - sage: D4.algebra_generators() # optional - sage.combinat sage.modules + sage: D4 = DescentAlgebra(QQ, 4).B() # needs sage.combinat sage.modules + sage: D4.algebra_generators() # needs sage.combinat sage.modules Lazy family (...)_{i in Compositions of 4} sage: R. = ZZ[] - sage: P = PartitionAlgebra(1, x, R) # optional - sage.combinat sage.modules - sage: P.algebra_generators() # optional - sage.combinat sage.modules + sage: P = PartitionAlgebra(1, x, R) # needs sage.combinat sage.modules + sage: P.algebra_generators() # needs sage.combinat sage.modules Lazy family (Term map from Partition diagrams of order 1 to Partition Algebra of rank 1 with parameter x @@ -169,9 +169,9 @@ def product_on_basis(self, i, j): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: Word = A.basis().keys() # optional - sage.combinat sage.modules - sage: A.product_on_basis(Word("abc"), Word("cba")) # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() # needs sage.combinat sage.modules + sage: Word = A.basis().keys() # needs sage.combinat sage.modules + sage: A.product_on_basis(Word("abc"), Word("cba")) # needs sage.combinat sage.modules B[word: abccba] """ @@ -190,9 +190,9 @@ def product(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: a, b, c = A.algebra_generators() # optional - sage.combinat sage.modules - sage: A.product(a + 2*b, 3*c) # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() # needs sage.combinat sage.modules + sage: a, b, c = A.algebra_generators() # needs sage.combinat sage.modules + sage: A.product(a + 2*b, 3*c) # needs sage.combinat sage.modules 3*B[word: ac] + 6*B[word: bc] """ if self.product_on_basis is not NotImplemented: @@ -212,11 +212,11 @@ def _product_from_product_on_basis_multiply( self, left, right ): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: a, b, c = A.algebra_generators() # optional - sage.combinat sage.modules - sage: A._product_from_product_on_basis_multiply(a*b + 2*c, a - b) # optional - sage.combinat sage.modules + sage: a, b, c = A.algebra_generators() # needs sage.combinat sage.modules + sage: A._product_from_product_on_basis_multiply(a*b + 2*c, a - b) # needs sage.combinat sage.modules B[word: aba] - B[word: abb] + 2*B[word: ca] - 2*B[word: cb] """ @@ -247,17 +247,18 @@ def derivations_basis(self): We construct the Heisenberg Lie algebra as a multiplicative algebra:: - sage: p_mult = matrix([[0,0,0], [0,0,-1], [0,0,0]]) # optional - sage.combinat sage.modules - sage: q_mult = matrix([[0,0,1], [0,0,0], [0,0,0]]) # optional - sage.combinat sage.modules - sage: A = algebras.FiniteDimensional(QQ, # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: p_mult = matrix([[0,0,0], [0,0,-1], [0,0,0]]) + sage: q_mult = matrix([[0,0,1], [0,0,0], [0,0,0]]) + sage: A = algebras.FiniteDimensional(QQ, ....: [p_mult, q_mult, matrix(QQ, 3, 3)], 'p,q,z') - sage: A.inject_variables() # optional - sage.combinat sage.modules + sage: A.inject_variables() Defining p, q, z - sage: p * q # optional - sage.combinat sage.modules + sage: p * q z - sage: q * p # optional - sage.combinat sage.modules + sage: q * p -z - sage: A.derivations_basis() # optional - sage.combinat sage.modules + sage: A.derivations_basis() ( [1 0 0] [0 1 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [1 0 0] [0 1 0] [0 0 0] [0 0 0] @@ -267,16 +268,17 @@ def derivations_basis(self): We construct another example using the exterior algebra and verify we obtain a derivation:: - sage: A = algebras.Exterior(QQ, 1) # optional - sage.combinat sage.modules - sage: A.derivations_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = algebras.Exterior(QQ, 1) + sage: A.derivations_basis() ( [0 0] [0 1] ) - sage: D = A.module_morphism(matrix=A.derivations_basis()[0], # optional - sage.combinat sage.modules + sage: D = A.module_morphism(matrix=A.derivations_basis()[0], ....: codomain=A) - sage: one, e = A.basis() # optional - sage.combinat sage.modules - sage: all(D(a*b) == D(a) * b + a * D(b) # optional - sage.combinat sage.modules + sage: one, e = A.basis() + sage: all(D(a*b) == D(a) * b + a * D(b) ....: for a in A.basis() for b in A.basis()) True diff --git a/src/sage/categories/manifolds.py b/src/sage/categories/manifolds.py index 39ba682764e..f8dc1da4de0 100644 --- a/src/sage/categories/manifolds.py +++ b/src/sage/categories/manifolds.py @@ -25,6 +25,7 @@ class Manifolds(Category_over_base_ring): EXAMPLES:: + sage: # needs sage.rings.real_mpfr sage: from sage.categories.manifolds import Manifolds sage: C = Manifolds(RR); C Category of manifolds over Real Field with 53 bits of precision @@ -33,7 +34,7 @@ class Manifolds(Category_over_base_ring): TESTS:: - sage: TestSuite(C).run(skip="_test_category_over_bases") + sage: TestSuite(C).run(skip="_test_category_over_bases") # needs sage.rings.real_mpfr """ def __init__(self, base, name=None): r""" @@ -100,7 +101,7 @@ def Connected(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).Connected() + sage: Manifolds(RR).Connected() # needs sage.rings.real_mpfr Category of connected manifolds over Real Field with 53 bits of precision @@ -120,7 +121,7 @@ def FiniteDimensional(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: C = Manifolds(RR).Connected().FiniteDimensional(); C + sage: C = Manifolds(RR).Connected().FiniteDimensional(); C # needs sage.rings.real_mpfr Category of finite dimensional connected manifolds over Real Field with 53 bits of precision @@ -141,7 +142,7 @@ def Differentiable(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).Differentiable() + sage: Manifolds(RR).Differentiable() # needs sage.rings.real_mpfr Category of differentiable manifolds over Real Field with 53 bits of precision @@ -161,7 +162,7 @@ def Smooth(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).Smooth() + sage: Manifolds(RR).Smooth() # needs sage.rings.real_mpfr Category of smooth manifolds over Real Field with 53 bits of precision @@ -181,7 +182,7 @@ def Analytic(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).Analytic() + sage: Manifolds(RR).Analytic() # needs sage.rings.real_mpfr Category of analytic manifolds over Real Field with 53 bits of precision @@ -202,7 +203,7 @@ def AlmostComplex(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).AlmostComplex() + sage: Manifolds(RR).AlmostComplex() # needs sage.rings.real_mpfr Category of almost complex manifolds over Real Field with 53 bits of precision @@ -222,14 +223,14 @@ def Complex(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(CC).Complex() + sage: Manifolds(CC).Complex() # needs sage.rings.real_mpfr Category of complex manifolds over Complex Field with 53 bits of precision TESTS:: - sage: TestSuite(Manifolds(CC).Complex()).run() - sage: Manifolds(CC).Complex.__module__ + sage: TestSuite(Manifolds(CC).Complex()).run() # needs sage.rings.real_mpfr + sage: Manifolds(CC).Complex.__module__ # needs sage.rings.real_mpfr 'sage.categories.manifolds' """ return ComplexManifolds(self.base())._with_axioms(self.axioms()) @@ -256,7 +257,7 @@ def extra_super_categories(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).Smooth().super_categories() # indirect doctest + sage: Manifolds(RR).Smooth().super_categories() # indirect doctest # needs sage.rings.real_mpfr [Category of differentiable manifolds over Real Field with 53 bits of precision] """ @@ -277,7 +278,7 @@ def extra_super_categories(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).Analytic().super_categories() # indirect doctest + sage: Manifolds(RR).Analytic().super_categories() # indirect doctest # needs sage.rings.real_mpfr [Category of smooth manifolds over Real Field with 53 bits of precision] """ @@ -301,7 +302,7 @@ def extra_super_categories(self): EXAMPLES:: sage: from sage.categories.manifolds import Manifolds - sage: Manifolds(RR).AlmostComplex().super_categories() # indirect doctest + sage: Manifolds(RR).AlmostComplex().super_categories() # indirect doctest # needs sage.rings.real_mpfr [Category of smooth manifolds over Real Field with 53 bits of precision] """ diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 50853348b53..45c30ae6c31 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -115,7 +115,7 @@ cdef class Map(Element): Using domain and codomain:: - sage: Map(QQ['x'], SymmetricGroup(6)) # optional - sage.groups + sage: Map(QQ['x'], SymmetricGroup(6)) # needs sage.groups Generic map: From: Univariate Polynomial Ring in x over Rational Field To: Symmetric group of order 6! as a permutation group @@ -196,9 +196,9 @@ cdef class Map(Element): EXAMPLES:: - sage: Q = QuadraticField(-5) # optional - sage.rings.number_field - sage: phi = CDF._internal_convert_map_from(Q) # optional - sage.rings.number_field - sage: print(phi.parent()) # optional - sage.rings.number_field + sage: Q = QuadraticField(-5) # needs sage.rings.number_field + sage: phi = CDF._internal_convert_map_from(Q) # needs sage.rings.number_field + sage: print(phi.parent()) # needs sage.rings.number_field Set of field embeddings from Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I @@ -208,9 +208,9 @@ cdef class Map(Element): not prevent `Q` from being garbage collected:: sage: import gc - sage: del Q # optional - sage.rings.number_field + sage: del Q # needs sage.rings.number_field sage: _ = gc.collect() - sage: phi.parent() # optional - sage.rings.number_field + sage: phi.parent() # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: This map is in an invalid state, @@ -219,17 +219,18 @@ cdef class Map(Element): You can still obtain copies of the maps used by the coercion system with strong references:: - sage: Q = QuadraticField(-5) # optional - sage.rings.number_field - sage: phi = CDF.convert_map_from(Q) # optional - sage.rings.number_field - sage: print(phi.parent()) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Q = QuadraticField(-5) + sage: phi = CDF.convert_map_from(Q) + sage: print(phi.parent()) Set of field embeddings from Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I to Complex Double Field sage: import gc - sage: del Q # optional - sage.rings.number_field + sage: del Q sage: _ = gc.collect() - sage: phi.parent() # optional - sage.rings.number_field + sage: phi.parent() Set of field embeddings from Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I @@ -260,31 +261,32 @@ cdef class Map(Element): EXAMPLES:: - sage: Q = QuadraticField(-5) # optional - sage.rings.number_field - sage: phi = CDF._internal_convert_map_from(Q) # optional - sage.rings.number_field + sage: Q = QuadraticField(-5) # needs sage.rings.number_field + sage: phi = CDF._internal_convert_map_from(Q) # needs sage.rings.number_field By :trac:`14711`, maps used in the coercion and conversion system use *weak* references to domain and codomain, in contrast to other maps:: - sage: phi.domain # optional - sage.rings.number_field + sage: phi.domain # needs sage.rings.number_field - sage: phi._make_strong_references() # optional - sage.rings.number_field - sage: print(phi.domain) # optional - sage.rings.number_field + sage: phi._make_strong_references() # needs sage.rings.number_field + sage: print(phi.domain) # needs sage.rings.number_field The constant function (...) -> Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I Now, as there is a strong reference, `Q` cannot be garbage collected:: + sage: # needs sage.rings.number_field sage: import gc sage: _ = gc.collect() - sage: C = Q.__class__.__base__ # optional - sage.rings.number_field + sage: C = Q.__class__.__base__ sage: x = None - sage: numberQuadFields = len([x for x in gc.get_objects() # optional - sage.rings.number_field + sage: numberQuadFields = len([x for x in gc.get_objects() ....: if isinstance(x, C)]) - sage: del Q, x # optional - sage.rings.number_field + sage: del Q, x sage: _ = gc.collect() - sage: numberQuadFields == len([x for x in gc.get_objects() # optional - sage.rings.number_field + sage: numberQuadFields == len([x for x in gc.get_objects() ....: if isinstance(x, C)]) True @@ -293,12 +295,13 @@ cdef class Map(Element): invalid. This is why :meth:`_make_weak_references` should only be used if one really knows what one is doing:: - sage: phi._make_weak_references() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: phi._make_weak_references() sage: _ = gc.collect() - sage: numberQuadFields == len([x for x in gc.get_objects() # optional - sage.rings.number_field + sage: numberQuadFields == len([x for x in gc.get_objects() ....: if isinstance(x, C)]) + 1 True - sage: phi # optional - sage.rings.number_field + sage: phi Defunct map """ if not isinstance(self.domain, ConstantFunction): @@ -326,31 +329,32 @@ cdef class Map(Element): EXAMPLES:: - sage: Q = QuadraticField(-5) # optional - sage.rings.number_field - sage: phi = CDF._internal_convert_map_from(Q) # optional - sage.rings.number_field + sage: Q = QuadraticField(-5) # needs sage.rings.number_field + sage: phi = CDF._internal_convert_map_from(Q) # needs sage.rings.number_field By :trac:`14711`, maps used in the coercion and conversion system use *weak* references to domain and codomain, in contrast to other maps:: - sage: phi.domain # optional - sage.rings.number_field + sage: phi.domain # needs sage.rings.number_field - sage: phi._make_strong_references() # optional - sage.rings.number_field - sage: print(phi.domain) # optional - sage.rings.number_field + sage: phi._make_strong_references() # needs sage.rings.number_field + sage: print(phi.domain) # needs sage.rings.number_field The constant function (...) -> Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I Now, as there is a strong reference, `Q` cannot be garbage collected:: + sage: # needs sage.rings.number_field sage: import gc sage: _ = gc.collect() - sage: C = Q.__class__.__base__ # optional - sage.rings.number_field + sage: C = Q.__class__.__base__ sage: x = None - sage: numberQuadFields = len([x for x in gc.get_objects() # optional - sage.rings.number_field + sage: numberQuadFields = len([x for x in gc.get_objects() ....: if isinstance(x, C)]) - sage: del Q, x # optional - sage.rings.number_field + sage: del Q, x sage: _ = gc.collect() - sage: numberQuadFields == len([x for x in gc.get_objects() # optional - sage.rings.number_field + sage: numberQuadFields == len([x for x in gc.get_objects() ....: if isinstance(x, C)]) True @@ -359,18 +363,19 @@ cdef class Map(Element): invalid. This is why :meth:`_make_weak_references` should only be used if one really knows what one is doing:: - sage: phi._make_weak_references() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: phi._make_weak_references() sage: _ = gc.collect() - sage: numberQuadFields == len([x for x in gc.get_objects() # optional - sage.rings.number_field + sage: numberQuadFields == len([x for x in gc.get_objects() ....: if isinstance(x, C)]) + 1 True - sage: phi # optional - sage.rings.number_field + sage: phi Defunct map - sage: phi._make_strong_references() # optional - sage.rings.number_field + sage: phi._make_strong_references() Traceback (most recent call last): ... RuntimeError: The domain of this map became garbage collected - sage: phi.parent() # optional - sage.rings.number_field + sage: phi.parent() Traceback (most recent call last): ... ValueError: This map is in an invalid state, the domain has been garbage collected @@ -400,6 +405,7 @@ cdef class Map(Element): Since it is a ``cdef``d method, it is tested using a dummy python method. :: + sage: # needs sage.rings.real_mpfr sage: from sage.categories.map import Map sage: f = Map(Hom(QQ, ZZ, Rings())) sage: f._update_slots_test({"_domain": RR, "_codomain": QQ}) # indirect doctest @@ -430,6 +436,7 @@ cdef class Map(Element): TESTS:: + sage: # needs sage.rings.real_mpfr sage: from sage.categories.map import Map sage: f = Map(Hom(QQ, ZZ, Rings())) sage: f._update_slots_test({"_domain": RR, "_codomain": QQ}) @@ -564,16 +571,17 @@ cdef class Map(Element): TESTS:: - sage: Q = QuadraticField(-5) # optional - sage.rings.number_field - sage: phi = CDF._internal_coerce_map_from(Q); phi # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Q = QuadraticField(-5) + sage: phi = CDF._internal_coerce_map_from(Q); phi (map internal to coercion system -- copy before use) Composite map: From: Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I To: Complex Double Field - sage: del Q # optional - sage.rings.number_field + sage: del Q sage: import gc sage: _ = gc.collect() - sage: phi # optional - sage.rings.number_field + sage: phi Defunct map """ D = self.domain() @@ -767,11 +775,11 @@ cdef class Map(Element): ``pushforward`` fails, ``_call_`` is tried after conversion:: sage: g = FOO(QQ, ZZ) - sage: g(SR(3)) # optional - sage.symbolic + sage: g(SR(3)) # needs sage.symbolic pushforward Symbolic Ring _call_ Rational Field 3 - sage: g(SR(3), exponent=2) # optional - sage.symbolic + sage: g(SR(3), exponent=2) # needs sage.symbolic pushforward Symbolic Ring _call_with_args Rational Field 9 @@ -1084,7 +1092,7 @@ cdef class Map(Element): - ``self`` -- a Map in some ``Hom(X, Y, category_right)`` - ``left`` -- a Map in some ``Hom(Y, Z, category_left)`` - Returns the composition of ``self`` followed by ``right`` as a + Returns the composition of ``self`` followed by ``left`` as a morphism in ``Hom(X, Z, category)`` where ``category`` is the meet of ``category_left`` and ``category_right``. @@ -1125,10 +1133,11 @@ cdef class Map(Element): OUTPUT: An element of Hom(X, Z) obtained by composing self with `\phi`. If - no canonical `\phi` exists, a TypeError is raised. + no canonical `\phi` exists, a :class:`TypeError` is raised. EXAMPLES:: + sage: # needs sage.rings.complex_double sage: mor = CDF.coerce_map_from(RDF) sage: mor.extend_domain(QQ) Composite map: @@ -1169,7 +1178,7 @@ cdef class Map(Element): OUTPUT: An element of Hom(X, Z) obtained by composing self with `\phi`. If - no canonical `\phi` exists, a TypeError is raised. + no canonical `\phi` exists, a :class:`TypeError` is raised. EXAMPLES:: @@ -1185,7 +1194,7 @@ cdef class Map(Element): Native morphism: From: Rational Field To: Real Double Field - sage: mor.extend_codomain(GF(7)) # optional - sage.rings.finite_rings + sage: mor.extend_codomain(GF(7)) Traceback (most recent call last): ... TypeError: No coercion from Rational Field to Finite Field of size 7 @@ -1240,14 +1249,15 @@ cdef class Map(Element): ... TypeError: self must be an endomorphism - sage: K. = NumberField(x^4 - 5*x + 5) # optional - sage.rings.number_field - sage: C5. = CyclotomicField(5) # optional - sage.rings.number_field - sage: tau = K.hom([z - z^2]); tau # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^4 - 5*x + 5) + sage: C5. = CyclotomicField(5) + sage: tau = K.hom([z - z^2]); tau Ring morphism: From: Number Field in a with defining polynomial x^4 - 5*x + 5 To: Cyclotomic Field of order 5 and degree 4 Defn: a |--> -z^2 + z - sage: tau^-1 # optional - sage.rings.number_field + sage: tau^-1 Ring morphism: From: Cyclotomic Field of order 5 and degree 4 To: Number Field in a with defining polynomial x^4 - 5*x + 5 @@ -1874,26 +1884,27 @@ cdef class FormalCompositeMap(Map): EXAMPLES:: - sage: V1 = QQ^2 # optional - sage.modules - sage: V2 = QQ^3 # optional - sage.modules - sage: phi1 = (QQ^1).hom(Matrix([[1, 1]]), V1) # optional - sage.modules - sage: phi2 = V1.hom(Matrix([[1, 2, 3], [4, 5, 6]]), V2) # optional - sage.modules + sage: # needs sage.modules + sage: V1 = QQ^2 + sage: V2 = QQ^3 + sage: phi1 = (QQ^1).hom(Matrix([[1, 1]]), V1) + sage: phi2 = V1.hom(Matrix([[1, 2, 3], [4, 5, 6]]), V2) If both constituents are injective, the composition is injective:: sage: from sage.categories.map import FormalCompositeMap - sage: c1 = FormalCompositeMap(Hom(QQ^1, V2, phi1.category_for()), # optional - sage.modules + sage: c1 = FormalCompositeMap(Hom(QQ^1, V2, phi1.category_for()), # needs sage.modules ....: phi1, phi2) - sage: c1.is_injective() # optional - sage.modules + sage: c1.is_injective() # needs sage.modules True If it cannot be determined whether the composition is injective, an error is raised:: - sage: psi1 = V2.hom(Matrix([[1, 2], [3, 4], [5, 6]]), V1) # optional - sage.modules - sage: c2 = FormalCompositeMap(Hom(V1, V1, phi2.category_for()), # optional - sage.modules + sage: psi1 = V2.hom(Matrix([[1, 2], [3, 4], [5, 6]]), V1) # needs sage.modules + sage: c2 = FormalCompositeMap(Hom(V1, V1, phi2.category_for()), # needs sage.modules ....: phi2, psi1) - sage: c2.is_injective() # optional - sage.modules + sage: c2.is_injective() # needs sage.modules Traceback (most recent call last): ... NotImplementedError: not enough information to deduce injectivity @@ -1901,18 +1912,18 @@ cdef class FormalCompositeMap(Map): If the first map is surjective and the second map is not injective, then the composition is not injective:: - sage: psi2 = V1.hom([[1], [1]], QQ^1) # optional - sage.modules - sage: c3 = FormalCompositeMap(Hom(V2, QQ^1, phi2.category_for()), # optional - sage.modules + sage: psi2 = V1.hom([[1], [1]], QQ^1) # needs sage.modules + sage: c3 = FormalCompositeMap(Hom(V2, QQ^1, phi2.category_for()), # needs sage.modules ....: psi2, psi1) - sage: c3.is_injective() # optional - sage.modules + sage: c3.is_injective() # needs sage.modules False TESTS: Check that :trac:`23205` has been resolved:: - sage: f = QQ.hom(QQbar) * ZZ.hom(QQ) # optional - sage.rings.number_field - sage: f.is_injective() # optional - sage.rings.number_field + sage: f = QQ.hom(QQbar) * ZZ.hom(QQ) # needs sage.rings.number_field + sage: f.is_injective() # needs sage.rings.number_field True """ @@ -1949,23 +1960,24 @@ cdef class FormalCompositeMap(Map): EXAMPLES:: sage: from sage.categories.map import FormalCompositeMap - sage: V3 = QQ^3 # optional - sage.modules - sage: V2 = QQ^2 # optional - sage.modules - sage: V1 = QQ^1 # optional - sage.modules + sage: V3 = QQ^3 # needs sage.modules + sage: V2 = QQ^2 # needs sage.modules + sage: V1 = QQ^1 # needs sage.modules If both maps are surjective, the composition is surjective:: - sage: phi32 = V3.hom(Matrix([[1, 2], [3, 4], [5, 6]]), V2) # optional - sage.modules - sage: phi21 = V2.hom(Matrix([[1], [1]]), V1) # optional - sage.modules - sage: c_phi = FormalCompositeMap(Hom(V3, V1, phi32.category_for()), # optional - sage.modules + sage: # needs sage.modules + sage: phi32 = V3.hom(Matrix([[1, 2], [3, 4], [5, 6]]), V2) + sage: phi21 = V2.hom(Matrix([[1], [1]]), V1) + sage: c_phi = FormalCompositeMap(Hom(V3, V1, phi32.category_for()), ....: phi32, phi21) - sage: c_phi.is_surjective() # optional - sage.modules + sage: c_phi.is_surjective() True If the second map is not surjective, the composition is not surjective:: - sage: FormalCompositeMap(Hom(V3, V1, phi32.category_for()), # optional - sage.modules + sage: FormalCompositeMap(Hom(V3, V1, phi32.category_for()), # needs sage.modules ....: phi32, ....: V2.hom(Matrix([[0], [0]]), V1)).is_surjective() False @@ -1973,14 +1985,14 @@ cdef class FormalCompositeMap(Map): If the second map is an isomorphism and the first map is not surjective, then the composition is not surjective:: - sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()), # optional - sage.modules + sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()), # needs sage.modules ....: V2.hom(Matrix([[0], [0]]), V1), ....: V1.hom(Matrix([[1]]), V1)).is_surjective() False Otherwise, surjectivity of the composition cannot be determined:: - sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()), # optional - sage.modules + sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()), # needs sage.modules ....: V2.hom(Matrix([[1, 1], [1, 1]]), V2), ....: V2.hom(Matrix([[1], [1]]), V1)).is_surjective() Traceback (most recent call last): @@ -2022,8 +2034,8 @@ cdef class FormalCompositeMap(Map): EXAMPLES:: sage: f = QQ.coerce_map_from(ZZ) - sage: g = MatrixSpace(QQ, 2, 2).coerce_map_from(QQ) # optional - sage.modules - sage: list((g * f).domains()) # optional - sage.modules + sage: g = MatrixSpace(QQ, 2, 2).coerce_map_from(QQ) # needs sage.modules + sage: list((g * f).domains()) # needs sage.modules [Integer Ring, Rational Field] """ for f in self.__list: @@ -2057,9 +2069,9 @@ cdef class FormalCompositeMap(Map): of :class:`sage.rings.polynomial.polynomial_element.Polynomial` before (see comment there):: - sage: k = GF(47) # optional - sage.rings.finite_rings - sage: R. = PolynomialRing(k) # optional - sage.rings.finite_rings - sage: R.coerce_map_from(ZZ).section() # optional - sage.rings.finite_rings + sage: k = GF(47) + sage: R. = PolynomialRing(k) + sage: R.coerce_map_from(ZZ).section() Composite map: From: Univariate Polynomial Ring in x over Finite Field of size 47 To: Integer Ring @@ -2070,9 +2082,9 @@ cdef class FormalCompositeMap(Map): Lifting map: From: Finite Field of size 47 To: Integer Ring - sage: ZZ(R(45)) # indirect doctest # optional - sage.rings.finite_rings + sage: ZZ(R(45)) # indirect doctest 45 - sage: ZZ(3*x + 45) # indirect doctest # optional - sage.rings.finite_rings + sage: ZZ(3*x + 45) # indirect doctest Traceback (most recent call last): ... TypeError: not a constant polynomial diff --git a/src/sage/categories/metric_spaces.py b/src/sage/categories/metric_spaces.py index 6608ca7d4e5..205e8746363 100644 --- a/src/sage/categories/metric_spaces.py +++ b/src/sage/categories/metric_spaces.py @@ -127,10 +127,11 @@ def _test_metric_function(self, **options): EXAMPLES:: - sage: UHP = HyperbolicPlane().UHP() # optional - sage.symbolic - sage: UHP._test_metric_function() # optional - sage.symbolic - sage: elts = [UHP.random_element() for i in range(5)] # optional - sage.symbolic - sage: UHP._test_metric_function(some_elements=elts) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: UHP = HyperbolicPlane().UHP() + sage: UHP._test_metric_function() + sage: elts = [UHP.random_element() for i in range(5)] + sage: UHP._test_metric_function(some_elements=elts) """ tester = self._tester(**options) S = tester.some_elements() @@ -149,11 +150,12 @@ def metric_function(self): EXAMPLES:: - sage: UHP = HyperbolicPlane().UHP() # optional - sage.symbolic - sage: m = UHP.metric_function() # optional - sage.symbolic - sage: p1 = UHP.get_point(5 + 7*I) # optional - sage.symbolic - sage: p2 = UHP.get_point(1.0 + I) # optional - sage.symbolic - sage: m(p1, p2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: UHP = HyperbolicPlane().UHP() + sage: m = UHP.metric_function() + sage: p1 = UHP.get_point(5 + 7*I) + sage: p2 = UHP.get_point(1.0 + I) + sage: m(p1, p2) 2.23230104635820 """ return lambda a,b: a.dist(b) @@ -166,27 +168,28 @@ def dist(self, a, b): EXAMPLES:: - sage: UHP = HyperbolicPlane().UHP() # optional - sage.symbolic - sage: p1 = UHP.get_point(5 + 7*I) # optional - sage.symbolic - sage: p2 = UHP.get_point(1.0 + I) # optional - sage.symbolic - sage: UHP.dist(p1, p2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: UHP = HyperbolicPlane().UHP() + sage: p1 = UHP.get_point(5 + 7*I) + sage: p2 = UHP.get_point(1.0 + I) + sage: UHP.dist(p1, p2) 2.23230104635820 - sage: PD = HyperbolicPlane().PD() # optional - sage.symbolic - sage: PD.dist(PD.get_point(0), PD.get_point(I/2)) # optional - sage.symbolic + sage: PD = HyperbolicPlane().PD() # needs sage.symbolic + sage: PD.dist(PD.get_point(0), PD.get_point(I/2)) # needs sage.symbolic arccosh(5/3) TESTS:: - sage: RR.dist(-1, pi) # optional - sage.symbolic + sage: RR.dist(-1, pi) # needs sage.rings.real_mpfr sage.symbolic 4.14159265358979 sage: RDF.dist(1, -1/2) 1.5 - sage: CC.dist(3, 2) + sage: CC.dist(3, 2) # needs sage.rings.real_mpfr 1.00000000000000 - sage: CC.dist(-1, I) + sage: CC.dist(-1, I) # needs sage.rings.real_mpfr sage.symbolic 1.41421356237310 - sage: CDF.dist(-1, I) + sage: CDF.dist(-1, I) # needs sage.rings.real_mpfr sage.symbolic 1.4142135623730951 """ return (self(a) - self(b)).abs() @@ -198,7 +201,7 @@ def abs(self): EXAMPLES:: - sage: CC(I).abs() + sage: CC(I).abs() # needs sage.rings.real_mpfr sage.symbolic 1.00000000000000 """ P = self.parent() @@ -210,10 +213,11 @@ def dist(self, b): EXAMPLES:: - sage: UHP = HyperbolicPlane().UHP() # optional - sage.symbolic - sage: p1 = UHP.get_point(5 + 7*I) # optional - sage.symbolic - sage: p2 = UHP.get_point(1 + I) # optional - sage.symbolic - sage: p1.dist(p2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: UHP = HyperbolicPlane().UHP() + sage: p1 = UHP.get_point(5 + 7*I) + sage: p2 = UHP.get_point(1 + I) + sage: p1.dist(p2) arccosh(33/7) """ return self.parent().dist(self, b) @@ -266,11 +270,12 @@ def dist(self, a, b): EXAMPLES:: - sage: H = HyperbolicPlane() # optional - sage.symbolic - sage: PD = H.PD() # optional - sage.symbolic - sage: p1 = PD.get_point(0) # optional - sage.symbolic - sage: p2 = PD.get_point(I/2) # optional - sage.symbolic - sage: H.dist(p1, p2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: H = HyperbolicPlane() + sage: PD = H.PD() + sage: p1 = PD.get_point(0) + sage: p2 = PD.get_point(I/2) + sage: H.dist(p1, p2) arccosh(5/3) """ R = self.a_realization() diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index 81f6df6f51f..e65bab4faf8 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -214,23 +214,25 @@ def base_ring(self): sage: C.base_ring.__module__ 'sage.categories.modules' - sage: C = Modules(Rings()) & Semigroups(); C + sage: C2 = Modules(Rings()) & Semigroups(); C2 Join of Category of semigroups and Category of modules over rings - sage: C.base_ring() + sage: C2.base_ring() Category of rings - sage: C.base_ring.__module__ + sage: C2.base_ring.__module__ 'sage.categories.modules' - sage: C = DescentAlgebra(QQ,3).B().category() # optional - sage.combinat sage.modules - sage: C.base_ring.__module__ # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: C3 = DescentAlgebra(QQ,3).B().category() + sage: C3.base_ring.__module__ 'sage.categories.modules' - sage: C.base_ring() # optional - sage.combinat sage.modules + sage: C3.base_ring() Rational Field - sage: C = QuasiSymmetricFunctions(QQ).F().category() # optional - sage.combinat sage.modules - sage: C.base_ring.__module__ # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: C4 = QuasiSymmetricFunctions(QQ).F().category() + sage: C4.base_ring.__module__ 'sage.categories.modules' - sage: C.base_ring() # optional - sage.combinat sage.modules + sage: C4.base_ring() Rational Field """ for C in self.super_categories(): @@ -365,9 +367,9 @@ def FinitelyPresented(self): sage: Modules(ZZ).FinitelyPresented() Category of finitely presented modules over Integer Ring - sage: A = SteenrodAlgebra(2) # optional - sage.combinat sage.modules - sage: from sage.modules.fp_graded.module import FPModule # optional - sage.combinat sage.modules - sage: FPModule(A, [0, 1], [[Sq(2), Sq(1)]]).category() # optional - sage.combinat sage.modules + sage: A = SteenrodAlgebra(2) # needs sage.combinat sage.modules + sage: from sage.modules.fp_graded.module import FPModule # needs sage.combinat sage.modules + sage: FPModule(A, [0, 1], [[Sq(2), Sq(1)]]).category() # needs sage.combinat sage.modules Category of finitely presented graded modules over mod 2 Steenrod algebra, milnor basis @@ -521,7 +523,7 @@ def extra_super_categories(self): [Category of finite sets] sage: Modules(ZZ).FiniteDimensional().extra_super_categories() [] - sage: Modules(GF(5)).FiniteDimensional().is_subcategory(Sets().Finite()) # optional - sage.rings.finite_rings + sage: Modules(GF(5)).FiniteDimensional().is_subcategory(Sets().Finite()) True sage: Modules(ZZ).FiniteDimensional().is_subcategory(Sets().Finite()) False @@ -571,7 +573,7 @@ def extra_super_categories(self): [Category of finite sets] sage: Modules(ZZ).FiniteDimensional().extra_super_categories() [] - sage: Modules(GF(5)).FiniteDimensional().is_subcategory(Sets().Finite()) # optional - sage.rings.finite_rings + sage: Modules(GF(5)).FiniteDimensional().is_subcategory(Sets().Finite()) True sage: Modules(ZZ).FiniteDimensional().is_subcategory(Sets().Finite()) False @@ -618,9 +620,9 @@ def linear_combination(self, iter_of_elements_coeff, factor_on_left=True): EXAMPLES:: - sage: m = matrix([[0,1], [1,1]]) # optional - sage.modules - sage: J. = JordanAlgebra(m) # optional - sage.combinat sage.modules - sage: J.linear_combination(((a+b, 1), (-2*b + c, -1))) # optional - sage.combinat sage.modules + sage: m = matrix([[0,1], [1,1]]) # needs sage.modules + sage: J. = JordanAlgebra(m) # needs sage.combinat sage.modules + sage: J.linear_combination(((a+b, 1), (-2*b + c, -1))) # needs sage.combinat sage.modules 1 + (3, -1) """ if factor_on_left: @@ -637,8 +639,8 @@ def tensor_square(self): EXAMPLES:: - sage: A = HopfAlgebrasWithBasis(QQ).example() # optional - sage.groups sage.modules - sage: A.tensor_square() # optional - sage.groups sage.modules + sage: A = HopfAlgebrasWithBasis(QQ).example() # needs sage.groups sage.modules + sage: A.tensor_square() # needs sage.groups sage.modules An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field # An example @@ -667,14 +669,15 @@ def module_morphism(self, *, function, category=None, codomain, **keywords): EXAMPLES:: - sage: V = FiniteRankFreeModule(QQ, 2) # optional - sage.modules - sage: e = V.basis('e'); e # optional - sage.modules + sage: # needs sage.modules + sage: V = FiniteRankFreeModule(QQ, 2) + sage: e = V.basis('e'); e Basis (e_0,e_1) on the 2-dimensional vector space over the Rational Field - sage: neg = V.module_morphism(function=operator.neg, codomain=V); neg # optional - sage.modules + sage: neg = V.module_morphism(function=operator.neg, codomain=V); neg Generic endomorphism of 2-dimensional vector space over the Rational Field - sage: neg(e[0]) # optional - sage.modules + sage: neg(e[0]) Element -e_0 of the 2-dimensional vector space over the Rational Field """ @@ -706,9 +709,9 @@ def quotient(self, submodule, check=True, **kwds): EXAMPLES:: - sage: C = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: TA = TensorAlgebra(C) # optional - sage.modules - sage: TA.quotient # optional - sage.modules + sage: C = CombinatorialFreeModule(QQ, ['a','b','c']) # needs sage.modules + sage: TA = TensorAlgebra(C) # needs sage.combinat sage.modules + sage: TA.quotient # needs sage.combinat sage.modules @@ -757,21 +760,22 @@ def base_ring(self): EXAMPLES:: - sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) # optional - sage.modules - sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) # optional - sage.modules - sage: H = Hom(E, F) # optional - sage.modules - sage: H.base_ring() # optional - sage.modules + sage: # needs sage.modules + sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) + sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) + sage: H = Hom(E, F) + sage: H.base_ring() Integer Ring This ``base_ring`` method is actually overridden by :meth:`sage.structure.category_object.CategoryObject.base_ring`:: - sage: H.base_ring.__module__ # optional - sage.modules + sage: H.base_ring.__module__ # needs sage.modules Here we call it directly:: - sage: method = H.category().parent_class.base_ring # optional - sage.modules - sage: method.__get__(H)() # optional - sage.modules + sage: method = H.category().parent_class.base_ring # needs sage.modules + sage: method.__get__(H)() # needs sage.modules Integer Ring """ return self.domain().base_ring() @@ -781,24 +785,25 @@ def zero(self): """ EXAMPLES:: - sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) # optional - sage.modules - sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) # optional - sage.modules - sage: H = Hom(E, F) # optional - sage.modules - sage: f = H.zero() # optional - sage.modules - sage: f # optional - sage.modules + sage: # needs sage.modules + sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) + sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) + sage: H = Hom(E, F) + sage: f = H.zero() + sage: f Generic morphism: From: Free module generated by {1, 2, 3} over Integer Ring To: Free module generated by {2, 3, 4} over Integer Ring - sage: f(E.monomial(2)) # optional - sage.modules + sage: f(E.monomial(2)) 0 - sage: f(E.monomial(3)) == F.zero() # optional - sage.modules + sage: f(E.monomial(3)) == F.zero() True TESTS: We check that ``H.zero()`` is picklable:: - sage: loads(dumps(f.parent().zero())) # optional - sage.modules + sage: loads(dumps(f.parent().zero())) # needs sage.modules Generic morphism: From: Free module generated by {1, 2, 3} over Integer Ring To: Free module generated by {2, 3, 4} over Integer Ring @@ -822,7 +827,7 @@ def extra_super_categories(self): sage: Modules(ZZ).Endsets().extra_super_categories() [Category of magmatic algebras over Integer Ring] - sage: End(ZZ^3) in Algebras(ZZ) # optional - sage.modules + sage: End(ZZ^3) in Algebras(ZZ) # needs sage.modules True """ from .magmatic_algebras import MagmaticAlgebras @@ -861,46 +866,47 @@ def __init_extra__(self): EXAMPLES:: - sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) # optional - sage.modules - sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) # optional - sage.modules - sage: C = cartesian_product([E, F]); C # optional - sage.modules + sage: # needs sage.modules + sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) + sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) + sage: C = cartesian_product([E, F]); C Free module generated by {1, 2, 3} over Integer Ring (+) Free module generated by {2, 3, 4} over Integer Ring - sage: C.base_ring() # optional - sage.modules + sage: C.base_ring() Integer Ring Check that :trac:`29225` is fixed:: - sage: M = cartesian_product((ZZ^2, ZZ^3)); M # optional - sage.modules + sage: M = cartesian_product((ZZ^2, ZZ^3)); M # needs sage.modules The Cartesian product of (Ambient free module of rank 2 over the principal ideal domain Integer Ring, Ambient free module of rank 3 over the principal ideal domain Integer Ring) - sage: M.category() # optional - sage.modules + sage: M.category() # needs sage.modules Category of Cartesian products of modules with basis over (euclidean domains and infinite enumerated sets and metric spaces) - sage: M.base_ring() # optional - sage.modules + sage: M.base_ring() # needs sage.modules Integer Ring - sage: A = cartesian_product((QQ^2, QQ['x'])); A # optional - sage.modules + sage: A = cartesian_product((QQ^2, QQ['x'])); A # needs sage.modules The Cartesian product of (Vector space of dimension 2 over Rational Field, Univariate Polynomial Ring in x over Rational Field) - sage: A.category() # optional - sage.modules + sage: A.category() # needs sage.modules Category of Cartesian products of vector spaces over (number fields and quotient fields and metric spaces) - sage: A.base_ring() # optional - sage.modules + sage: A.base_ring() # needs sage.modules Rational Field This currently only works if all factors have the same base ring:: - sage: B = cartesian_product((ZZ['x'], QQ^3)); B # optional - sage.modules + sage: B = cartesian_product((ZZ['x'], QQ^3)); B # needs sage.modules The Cartesian product of (Univariate Polynomial Ring in x over Integer Ring, Vector space of dimension 3 over Rational Field) - sage: B.category() # optional - sage.modules + sage: B.category() # needs sage.modules Category of Cartesian products of commutative additive groups - sage: B.base_ring() # optional - sage.modules + sage: B.base_ring() # needs sage.modules """ factors = self._sets if factors: @@ -916,12 +922,12 @@ def _lmul_(self, x): EXAMPLES:: - sage: A = FreeModule(ZZ, 2) # optional - sage.modules - sage: B = cartesian_product([A, A]); B # optional - sage.modules + sage: A = FreeModule(ZZ, 2) # needs sage.modules + sage: B = cartesian_product([A, A]); B # needs sage.modules The Cartesian product of (Ambient free module of rank 2 over the principal ideal domain Integer Ring, Ambient free module of rank 2 over the principal ideal domain Integer Ring) - sage: 5*B(([1, 2], [3, 4])) # optional - sage.modules + sage: 5*B(([1, 2], [3, 4])) # needs sage.modules ((5, 10), (15, 20)) """ return self.parent()._cartesian_product_of_elements( @@ -953,9 +959,9 @@ def construction(self): EXAMPLES:: - sage: A = algebras.Free(QQ, 2) # optional - sage.combinat sage.modules - sage: T = A.tensor(A) # optional - sage.combinat sage.modules - sage: T.construction() # optional - sage.combinat sage.modules + sage: A = algebras.Free(QQ, 2) # needs sage.combinat sage.modules + sage: T = A.tensor(A) # needs sage.combinat sage.modules + sage: T.construction() # needs sage.combinat sage.modules (The tensor functorial construction, (Free Algebra on 2 generators (None0, None1) over Rational Field, Free Algebra on 2 generators (None0, None1) over Rational Field)) @@ -976,20 +982,21 @@ def tensor_factors(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [1,2]) # optional - sage.modules - sage: F.rename("F") # optional - sage.modules - sage: G = CombinatorialFreeModule(ZZ, [3,4]) # optional - sage.modules - sage: G.rename("G") # optional - sage.modules - sage: T = tensor([F, G]); T # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(ZZ, [1,2]) + sage: F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [3,4]) + sage: G.rename("G") + sage: T = tensor([F, G]); T F # G - sage: T.tensor_factors() # optional - sage.modules + sage: T.tensor_factors() (F, G) TESTS:: - sage: Cat = ModulesWithBasis(ZZ).FiniteDimensional().TensorProducts() # optional - sage.modules - sage: M = CombinatorialFreeModule(ZZ, ((1, 1), (1, 2), (2, 1), (2, 2)), category=Cat) # optional - sage.modules - sage: M.construction() # optional - sage.modules + sage: Cat = ModulesWithBasis(ZZ).FiniteDimensional().TensorProducts() + sage: M = CombinatorialFreeModule(ZZ, ((1, 1), (1, 2), (2, 1), (2, 2)), category=Cat) # needs sage.modules + sage: M.construction() # needs sage.modules doctest:warning... DeprecationWarning: implementations of Modules().TensorProducts() now must define the method tensor_factors See https://github.com/sagemath/sage/issues/34393 for details. diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 85a0d50239a..e97bf851388 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -66,23 +66,23 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring): Let `X` and `Y` be two modules with basis. We can build `Hom(X,Y)`:: - sage: X = CombinatorialFreeModule(QQ, [1,2]); X.__custom_name = "X" # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.__custom_name = "Y" # optional - sage.modules - sage: H = Hom(X, Y); H # optional - sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2]); X.rename("X") # needs sage.modules + sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.rename("Y") # needs sage.modules + sage: H = Hom(X, Y); H # needs sage.modules Set of Morphisms from X to Y in Category of finite dimensional vector spaces with basis over Rational Field The simplest morphism is the zero map:: - sage: H.zero() # todo: move this test into module once we have an example # optional - sage.modules + sage: H.zero() # todo: move this test into module once we have an example # needs sage.modules Generic morphism: From: X To: Y which we can apply to elements of `X`:: - sage: x = X.monomial(1) + 3 * X.monomial(2) # optional - sage.modules - sage: H.zero()(x) # optional - sage.modules + sage: x = X.monomial(1) + 3 * X.monomial(2) # needs sage.modules + sage: H.zero()(x) # needs sage.modules 0 EXAMPLES: @@ -90,17 +90,17 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring): We now construct a more interesting morphism by extending a function by linearity:: - sage: phi = H(on_basis=lambda i: Y.monomial(i + 2)); phi # optional - sage.modules + sage: phi = H(on_basis=lambda i: Y.monomial(i + 2)); phi # needs sage.modules Generic morphism: From: X To: Y - sage: phi(x) # optional - sage.modules + sage: phi(x) # needs sage.modules B[3] + 3*B[4] We can retrieve the function acting on indices of the basis:: - sage: f = phi.on_basis() # optional - sage.modules - sage: f(1), f(2) # optional - sage.modules + sage: f = phi.on_basis() # needs sage.modules + sage: f(1), f(2) # needs sage.modules (B[3], B[4]) `Hom(X,Y)` has a natural module structure (except for the zero, @@ -109,14 +109,14 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring): basis; but see :class:`FiniteDimensionalModulesWithBasis` and :class:`GradedModulesWithBasis`:: - sage: H in ModulesWithBasis(QQ), H in Modules(QQ) # optional - sage.modules + sage: H in ModulesWithBasis(QQ), H in Modules(QQ) # needs sage.modules (False, True) Some more playing around with categories and higher order homsets:: - sage: H.category() # optional - sage.modules + sage: H.category() # needs sage.modules Category of homsets of modules with basis over Rational Field - sage: Hom(H, H).category() # optional - sage.modules + sage: Hom(H, H).category() # needs sage.modules Category of endsets of homsets of modules with basis over Rational Field .. TODO:: ``End(X)`` is an algebra. @@ -129,10 +129,10 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring): TESTS:: - sage: f = H.zero().on_basis() # optional - sage.modules - sage: f(1) # optional - sage.modules + sage: f = H.zero().on_basis() # needs sage.modules + sage: f(1) # needs sage.modules 0 - sage: f(2) # optional - sage.modules + sage: f(2) # needs sage.modules 0 sage: TestSuite(ModulesWithBasis(ZZ)).run() @@ -152,20 +152,20 @@ def _call_(self, x): ``x`` is returned unchanged if it is already in this category:: - sage: CZ(CombinatorialFreeModule(ZZ, ('a', 'b', 'c'))) # optional - sage.modules + sage: CZ(CombinatorialFreeModule(ZZ, ('a', 'b', 'c'))) # needs sage.modules Free module generated by {'a', 'b', 'c'} over Integer Ring - sage: CZ(ZZ^3) # optional - sage.modules + sage: CZ(ZZ^3) # needs sage.modules Ambient free module of rank 3 over the principal ideal domain Integer Ring If needed (and possible) the base ring is changed appropriately:: - sage: CQ(ZZ^3) # indirect doctest # optional - sage.modules + sage: CQ(ZZ^3) # indirect doctest # needs sage.modules Vector space of dimension 3 over Rational Field If ``x`` itself is not a module with basis, but there is a canonical one associated to it, the latter is returned:: - sage: CQ(AbelianVariety(Gamma0(37))) # indirect doctest # optional - sage.modular sage.modules + sage: CQ(AbelianVariety(Gamma0(37))) # indirect doctest # needs sage.modular sage.modules Vector space of dimension 4 over Rational Field """ try: @@ -173,7 +173,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): @@ -210,14 +210,14 @@ def basis(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules - sage: F.basis() # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules + sage: F.basis() # needs sage.modules Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']} :: - sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.group sage.modules - sage: list(QS3.basis()) # optional - sage.group sage.modules + sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # needs sage.combinat sage.groups sage.modules + sage: list(QS3.basis()) # needs sage.combinat sage.groups sage.modules [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ from sage.sets.family import Family @@ -298,16 +298,16 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, :: - sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") + sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") sage: def f(i): ....: return Y.monomial(i) + 2*Y.monomial(i+1) - sage: phi = X.module_morphism(f, codomain=Y) # optional - sage.modules - sage: x = X.basis(); y = Y.basis() # optional - sage.modules - sage: phi(x[1] + x[3]) # optional - sage.modules + sage: phi = X.module_morphism(f, codomain=Y) + sage: x = X.basis(); y = Y.basis() + sage: phi(x[1] + x[3]) B[1] + 2*B[2] + B[3] + 2*B[4] - - sage: phi # optional - sage.modules + sage: phi Generic morphism: From: X To: Y @@ -318,7 +318,7 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, ``CommutativeAdditiveMonoids()`` that contains both the domain and the codomain:: - sage: phi.category_for() # optional - sage.modules + sage: phi.category_for() # needs sage.modules Category of finite dimensional vector spaces with basis over Rational Field @@ -326,42 +326,44 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, sage: def f(i): ....: return Y.monomial(i) + 2*Y.monomial(i+1) - sage: phi = X.module_morphism(f, codomain=Y, zero=10*y[1]) # optional - sage.modules - sage: phi(x[1] + x[3]) # optional - sage.modules + sage: phi = X.module_morphism(f, codomain=Y, zero=10*y[1]) # needs sage.modules + sage: phi(x[1] + x[3]) # needs sage.modules 11*B[1] + 2*B[2] + B[3] + 2*B[4] In this special case, the default category is ``Sets()``:: - sage: phi.category_for() # optional - sage.modules + sage: phi.category_for() # needs sage.modules Category of sets One can construct morphisms with the base ring as codomain:: - sage: X = CombinatorialFreeModule(ZZ, [1, -1]) # optional - sage.modules - sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=ZZ) # optional - sage.modules - sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1, -1]) + sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=ZZ) + sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) -1 - sage: phi.category_for() # optional - sage.modules + sage: phi.category_for() Category of commutative additive semigroups - sage: phi.category_for() # todo: not implemented (ZZ is currently not in Modules(ZZ)) # optional - sage.modules + sage: phi.category_for() # not implemented Category of modules over Integer Ring Or more generally any ring admitting a coercion map from the base ring:: - sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=RR) # optional - sage.modules - sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # optional - sage.modules + sage: # needs sage.modules + sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=RR) + sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) -1.00000000000000 - sage: phi.category_for() # optional - sage.modules + sage: phi.category_for() Category of commutative additive semigroups - sage: phi.category_for() # todo: not implemented (RR is currently not in Modules(ZZ)) # optional - sage.modules + sage: phi.category_for() # not implemented Category of modules over Integer Ring - sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # optional - sage.modules - sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # optional - sage.modules + sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # needs sage.modules + sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # needs sage.modules 3 - sage: phi = Y.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # optional - sage.modules + sage: phi = Y.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # needs sage.modules Traceback (most recent call last): ... ValueError: codomain(=Ring of integers modulo 4) should be a module @@ -371,46 +373,48 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, over different base rings; here we implement the natural map from `X = \RR^2` to `Y = \CC`:: - sage: X = CombinatorialFreeModule(RR, ['x', 'y']) # optional - sage.modules - sage: Y = CombinatorialFreeModule(CC, ['z']) # optional - sage.modules - sage: x = X.monomial('x') # optional - sage.modules - sage: y = X.monomial('y') # optional - sage.modules - sage: z = Y.monomial('z') # optional - sage.modules - sage: def on_basis(a): # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(RR, ['x', 'y']) + sage: Y = CombinatorialFreeModule(CC, ['z']) + sage: x = X.monomial('x') + sage: y = X.monomial('y') + sage: z = Y.monomial('z') + sage: def on_basis(a): ....: if a == 'x': ....: return CC(1) * z ....: elif a == 'y': ....: return CC(I) * z - sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # optional - sage.modules - sage: v = 3 * x + 2 * y; v # optional - sage.modules + sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) + sage: v = 3 * x + 2 * y; v 3.00000000000000*B['x'] + 2.00000000000000*B['y'] - sage: phi(v) # optional - sage.modules + sage: phi(v) # needs sage.symbolic (3.00000000000000+2.00000000000000*I)*B['z'] - sage: phi.category_for() # optional - sage.modules + sage: phi.category_for() Category of commutative additive semigroups - sage: phi.category_for() # todo: not implemented (CC is currently not in Modules(RR)!) # optional - sage.modules + sage: phi.category_for() # not implemented Category of vector spaces over Real Field with 53 bits of precision - sage: Y = CombinatorialFreeModule(CC['q'], ['z']) # optional - sage.modules - sage: z = Y.monomial('z') # optional - sage.modules - sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # optional - sage.modules - sage: phi(v) # optional - sage.modules + sage: # needs sage.modules + sage: Y = CombinatorialFreeModule(CC['q'], ['z']) + sage: z = Y.monomial('z') + sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) + sage: phi(v) # needs sage.symbolic (3.00000000000000+2.00000000000000*I)*B['z'] Of course, there should be a coercion between the respective base rings of the domain and the codomain for this to be meaningful:: - sage: Y = CombinatorialFreeModule(QQ, ['z']) # optional - sage.modules - sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # optional - sage.modules + sage: Y = CombinatorialFreeModule(QQ, ['z']) # needs sage.modules + sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # needs sage.modules Traceback (most recent call last): ... ValueError: codomain(=Free module generated by {'z'} over Rational Field) should be a module over the base ring of the domain(=Free module generated by {'x', 'y'} over Real Field with 53 bits of precision) - sage: Y = CombinatorialFreeModule(RR['q'], ['z']) # optional - sage.modules - sage: phi = Y.module_morphism(on_basis=on_basis, codomain=X) # optional - sage.modules + sage: Y = CombinatorialFreeModule(RR['q'], ['z']) # needs sage.modules + sage: phi = Y.module_morphism(on_basis=on_basis, codomain=X) # needs sage.modules Traceback (most recent call last): ... ValueError: codomain(=Free module generated by {'x', 'y'} @@ -429,11 +433,12 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, This assumes that the respective bases `x` and `y` of `X` and `Y` have the same index set `I`:: - sage: X = CombinatorialFreeModule(ZZ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: from sage.arith.misc import factorial # optional - sage.modules - sage: phi = X.module_morphism(diagonal=factorial, codomain=X) # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: phi(x[1]), phi(x[2]), phi(x[3]) # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1, 2, 3]); X.rename("X") + sage: from sage.arith.misc import factorial + sage: phi = X.module_morphism(diagonal=factorial, codomain=X) + sage: x = X.basis() + sage: phi(x[1]), phi(x[2]), phi(x[3]) (B[1], 2*B[2], 6*B[3]) See also: :class:`sage.modules.with_basis.morphism.DiagonalModuleMorphism`. @@ -442,15 +447,16 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, morphism whose matrix in the distinguished basis of `X` and `Y` is `m`:: - sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename("Y") # optional - sage.modules - sage: y = Y.basis() # optional - sage.modules - sage: m = matrix([[0,1,2], [3,5,0]]) # optional - sage.modules - sage: phi = X.module_morphism(matrix=m, codomain=Y) # optional - sage.modules - sage: phi(x[1]) # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") + sage: x = X.basis() + sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename("Y") + sage: y = Y.basis() + sage: m = matrix([[0,1,2], [3,5,0]]) + sage: phi = X.module_morphism(matrix=m, codomain=Y) + sage: phi(x[1]) 3*B[4] - sage: phi(x[2]) # optional - sage.modules + sage: phi(x[2]) B[3] + 5*B[4] @@ -462,37 +468,39 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, invertible elements on its diagonal. This is used to compute preimages and to invert the morphism:: + sage: # needs sage.modules sage: I = list(range(1, 200)) - sage: X = CombinatorialFreeModule(QQ, I); X.rename("X"); x = X.basis() # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, I); Y.rename("Y"); y = Y.basis() # optional - sage.modules - sage: f = Y.sum_of_monomials * divisors # optional - sage.modules - sage: phi = X.module_morphism(f, triangular="upper", codomain=Y) # optional - sage.modules - sage: phi(x[2]) # optional - sage.modules + sage: X = CombinatorialFreeModule(QQ, I); X.rename("X"); x = X.basis() + sage: Y = CombinatorialFreeModule(QQ, I); Y.rename("Y"); y = Y.basis() + sage: f = Y.sum_of_monomials * divisors + sage: phi = X.module_morphism(f, triangular="upper", codomain=Y) + sage: phi(x[2]) B[1] + B[2] - sage: phi(x[6]) # optional - sage.modules + sage: phi(x[6]) B[1] + B[2] + B[3] + B[6] - sage: phi(x[30]) # optional - sage.modules + sage: phi(x[30]) B[1] + B[2] + B[3] + B[5] + B[6] + B[10] + B[15] + B[30] - sage: phi.preimage(y[2]) # optional - sage.modules + sage: phi.preimage(y[2]) -B[1] + B[2] - sage: phi.preimage(y[6]) # optional - sage.modules + sage: phi.preimage(y[6]) B[1] - B[2] - B[3] + B[6] - sage: phi.preimage(y[30]) # optional - sage.modules + sage: phi.preimage(y[30]) -B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30] - sage: (phi^-1)(y[30]) # optional - sage.modules + sage: (phi^-1)(y[30]) -B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30] Since :trac:`8678`, one can also define a triangular morphism from a function:: - sage: X = CombinatorialFreeModule(QQ, [0,1,2,3,4]); x = X.basis() # optional - sage.modules - sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismFromFunction # optional - sage.modules - sage: def f(x): return x + X.term(0, sum(x.coefficients())) # optional - sage.modules - sage: phi = X.module_morphism(function=f, codomain=X, # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [0,1,2,3,4]); x = X.basis() + sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismFromFunction + sage: def f(x): return x + X.term(0, sum(x.coefficients())) + sage: phi = X.module_morphism(function=f, codomain=X, ....: triangular="upper") - sage: phi(x[2] + 3*x[4]) # optional - sage.modules + sage: phi(x[2] + 3*x[4]) 4*B[0] + B[2] + 3*B[4] - sage: phi.preimage(_) # optional - sage.modules + sage: phi.preimage(_) B[2] + 3*B[4] For details and further optional arguments, see @@ -515,8 +523,8 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, TESTS:: - sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: phi = X.module_morphism(codomain=X) # optional - sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # needs sage.modules + sage: phi = X.module_morphism(codomain=X) # needs sage.modules Traceback (most recent call last): ... ValueError: module_morphism() takes exactly one option @@ -524,8 +532,8 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, :: - sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: phi = X.module_morphism(diagonal=factorial, matrix=matrix(), # optional - sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # needs sage.modules + sage: phi = X.module_morphism(diagonal=factorial, matrix=matrix(), # needs sage.modules ....: codomain=X) Traceback (most recent call last): ... @@ -534,16 +542,16 @@ def module_morphism(self, on_basis=None, matrix=None, function=None, :: - sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: phi = X.module_morphism(matrix=factorial, codomain=X) # optional - sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # needs sage.modules + sage: phi = X.module_morphism(matrix=factorial, codomain=X) # needs sage.modules Traceback (most recent call last): ... ValueError: matrix (=...factorial...) should be a matrix :: - sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: phi = X.module_morphism(diagonal=3, codomain=X) # optional - sage.modules + sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # needs sage.modules + sage: phi = X.module_morphism(diagonal=3, codomain=X) # needs sage.modules Traceback (most recent call last): ... ValueError: diagonal (=3) should be a function @@ -582,14 +590,13 @@ def _repr_(self): """ EXAMPLES:: - sage: class FooBar(CombinatorialFreeModule): pass # optional - sage.modules - sage: C = FooBar(QQ, (1,2,3)); C # indirect doctest # optional - sage.modules + sage: # needs sage.modules + sage: class FooBar(CombinatorialFreeModule): pass + sage: C = FooBar(QQ, (1,2,3)); C # indirect doctest Free module generated by {1, 2, 3} over Rational Field - - sage: C._name = "foobar"; C # optional - sage.modules + sage: C._name = "foobar"; C foobar over Rational Field - - sage: C.rename("barfoo"); C # optional - sage.modules + sage: C.rename("barfoo"); C barfoo sage: class FooBar(Parent): @@ -619,28 +626,30 @@ def _compute_support_order(self, elements, support_order=None): A finite dimensional module:: - sage: V = CombinatorialFreeModule(QQ, range(10), prefix='x') # optional - sage.modules - sage: B = V.basis() # optional - sage.modules - sage: elts = [B[0] - 2*B[3], B[5] + 2*B[0], # optional - sage.modules + sage: # needs sage.modules + sage: V = CombinatorialFreeModule(QQ, range(10), prefix='x') + sage: B = V.basis() + sage: elts = [B[0] - 2*B[3], B[5] + 2*B[0], ....: B[2], B[3], B[1] + B[2] + B[8]] - sage: V._compute_support_order(elts) # optional - sage.modules + sage: V._compute_support_order(elts) (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - sage: V._compute_support_order(elts, [1,2,0,4,3,5,9,8,7,6]) # optional - sage.modules + sage: V._compute_support_order(elts, [1,2,0,4,3,5,9,8,7,6]) (1, 2, 0, 4, 3, 5, 9, 8, 7, 6) - sage: V._compute_support_order(elts, lambda x: -x) # optional - sage.modules + sage: V._compute_support_order(elts, lambda x: -x) (8, 5, 3, 2, 1, 0) An infinite dimensional module:: - sage: V = CombinatorialFreeModule(QQ, ZZ, prefix='z') # optional - sage.modules - sage: B = V.basis() # optional - sage.modules - sage: elts = [B[0] - 2*B[3], B[5] + 2*B[0], # optional - sage.modules + sage: # needs sage.modules + sage: V = CombinatorialFreeModule(QQ, ZZ, prefix='z') + sage: B = V.basis() + sage: elts = [B[0] - 2*B[3], B[5] + 2*B[0], ....: B[2], B[3], B[1] + B[2] + B[8]] - sage: V._compute_support_order(elts) # optional - sage.modules + sage: V._compute_support_order(elts) (0, 1, 2, 3, 5, 8) - sage: V._compute_support_order(elts, [1,2,0,4,3,5,9,8,7,6]) # optional - sage.modules + sage: V._compute_support_order(elts, [1,2,0,4,3,5,9,8,7,6]) (1, 2, 0, 4, 3, 5, 9, 8, 7, 6) - sage: V._compute_support_order(elts, lambda x: -x) # optional - sage.modules + sage: V._compute_support_order(elts, lambda x: -x) (8, 5, 3, 2, 1, 0) """ if support_order is None: @@ -685,17 +694,17 @@ def echelon_form(self, elements, row_reduced=False, order=None): EXAMPLES:: sage: R. = QQ[] - sage: C = CombinatorialFreeModule(R, ZZ, prefix='z') # optional - sage.modules - sage: z = C.basis() # optional - sage.modules - sage: C.echelon_form([z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]]) # optional - sage.modules + sage: C = CombinatorialFreeModule(R, ZZ, prefix='z') # needs sage.modules + sage: z = C.basis() # needs sage.modules + sage: C.echelon_form([z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]]) # needs sage.libs.singular sage.modules [z[0] - z[2], z[1] - z[2]] TESTS: We convert the input elements to ``self``:: - sage: s = SymmetricFunctions(QQ).s() # optional - sage.combinat sage.modules - sage: s.echelon_form([1, s[1] + 5]) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).s() # needs sage.combinat sage.modules + sage: s.echelon_form([1, s[1] + 5]) # needs sage.combinat sage.modules [s[], s[1]] """ # Make sure elements consists of elements of ``self`` @@ -764,21 +773,22 @@ def submodule(self, gens, check=True, already_echelonized=False, `x_0, x_1, x_2`. The submodule is spanned by `y_0 = x_0 - x_1` and `y_1 - x_1 - x_2`, and its basis elements are indexed by `0` and `1`:: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: gens = [x[0] - x[1], x[1] - x[2]]; gens # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") + sage: x = X.basis() + sage: gens = [x[0] - x[1], x[1] - x[2]]; gens [x[0] - x[1], x[1] - x[2]] - sage: Y = X.submodule(gens, already_echelonized=True) # optional - sage.modules - sage: Y.print_options(prefix='y'); Y # optional - sage.modules + sage: Y = X.submodule(gens, already_echelonized=True) + sage: Y.print_options(prefix='y'); Y Free module generated by {0, 1} over Rational Field - sage: y = Y.basis() # optional - sage.modules - sage: y[1] # optional - sage.modules + sage: y = Y.basis() + sage: y[1] y[1] - sage: y[1].lift() # optional - sage.modules + sage: y[1].lift() x[1] - x[2] - sage: Y.retract(x[0] - x[2]) # optional - sage.modules + sage: Y.retract(x[0] - x[2]) y[0] + y[1] - sage: Y.retract(x[0]) # optional - sage.modules + sage: Y.retract(x[0]) Traceback (most recent call last): ... ValueError: x[0] is not in the image @@ -786,23 +796,24 @@ def submodule(self, gens, check=True, already_echelonized=False, By using a family to specify a basis of the submodule, we obtain a submodule whose index set coincides with the index set of the family:: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: gens = Family({1: x[0] - x[1], 3: x[1] - x[2]}); gens # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") + sage: x = X.basis() + sage: gens = Family({1: x[0] - x[1], 3: x[1] - x[2]}); gens Finite family {1: x[0] - x[1], 3: x[1] - x[2]} - sage: Y = X.submodule(gens, already_echelonized=True) # optional - sage.modules - sage: Y.print_options(prefix='y'); Y # optional - sage.modules + sage: Y = X.submodule(gens, already_echelonized=True) + sage: Y.print_options(prefix='y'); Y Free module generated by {1, 3} over Rational Field - sage: y = Y.basis() # optional - sage.modules - sage: y[1] # optional - sage.modules + sage: y = Y.basis() + sage: y[1] y[1] - sage: y[1].lift() # optional - sage.modules + sage: y[1].lift() x[0] - x[1] - sage: y[3].lift() # optional - sage.modules + sage: y[3].lift() x[1] - x[2] - sage: Y.retract(x[0] - x[2]) # optional - sage.modules + sage: Y.retract(x[0] - x[2]) y[1] + y[3] - sage: Y.retract(x[0]) # optional - sage.modules + sage: Y.retract(x[0]) Traceback (most recent call last): ... ValueError: x[0] is not in the image @@ -810,56 +821,59 @@ def submodule(self, gens, check=True, already_echelonized=False, It is not necessary that the generators of the submodule form a basis (an explicit basis will be computed):: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]; gens # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") + sage: x = X.basis() + sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]; gens [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] - sage: Y = X.submodule(gens, already_echelonized=False) # optional - sage.modules - sage: Y.print_options(prefix='y') # optional - sage.modules - sage: Y # optional - sage.modules + sage: Y = X.submodule(gens, already_echelonized=False) + sage: Y.print_options(prefix='y') + sage: Y Free module generated by {0, 1} over Rational Field - sage: [b.lift() for b in Y.basis()] # optional - sage.modules + sage: [b.lift() for b in Y.basis()] [x[0] - x[2], x[1] - x[2]] We now implement by hand the center of the algebra of the symmetric group `S_3`:: - sage: S3 = SymmetricGroup(3) # optional - sage.groups sage.modules - sage: S3A = S3.algebra(QQ) # optional - sage.groups sage.modules - sage: basis = S3A.annihilator_basis(S3A.algebra_generators(), # optional - sage.groups sage.modules + sage: # needs sage.combinat sage.groups sage.modules + sage: S3 = SymmetricGroup(3) + sage: S3A = S3.algebra(QQ) + sage: basis = S3A.annihilator_basis(S3A.algebra_generators(), ....: S3A.bracket) - sage: basis # optional - sage.groups sage.modules + sage: basis ((), (1,2,3) + (1,3,2), (2,3) + (1,2) + (1,3)) - sage: center = S3A.submodule(basis, # optional - sage.groups sage.modules + sage: center = S3A.submodule(basis, ....: category=AlgebrasWithBasis(QQ).Subobjects(), ....: already_echelonized=True) - sage: center # optional - sage.groups sage.modules + sage: center Free module generated by {0, 1, 2} over Rational Field - sage: center in Algebras # optional - sage.groups sage.modules + sage: center in Algebras True - sage: center.print_options(prefix='c') # optional - sage.groups sage.modules - sage: c = center.basis() # optional - sage.groups sage.modules - sage: c[1].lift() # optional - sage.groups sage.modules + sage: center.print_options(prefix='c') + sage: c = center.basis() + sage: c[1].lift() (1,2,3) + (1,3,2) - sage: c[0]^2 # optional - sage.groups sage.modules + sage: c[0]^2 c[0] - sage: e = 1/6 * (c[0]+c[1]+c[2]) # optional - sage.groups sage.modules - sage: e.is_idempotent() # optional - sage.groups sage.modules + sage: e = 1/6 * (c[0]+c[1]+c[2]) + sage: e.is_idempotent() True Of course, this center is best constructed using:: - sage: center = S3A.center() # optional - sage.groups sage.modules + sage: center = S3A.center() # needs sage.combinat sage.groups sage.modules We can also automatically construct a basis such that the lift morphism is (lower) unitriangular:: + sage: # needs sage.modules sage: R. = QQ[] - sage: C = CombinatorialFreeModule(R, range(3), prefix='x') # optional - sage.modules - sage: x = C.basis() # optional - sage.modules - sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] # optional - sage.modules - sage: Y = C.submodule(gens, unitriangular=True) # optional - sage.modules - sage: Y.lift.matrix() # optional - sage.modules + sage: C = CombinatorialFreeModule(R, range(3), prefix='x') + sage: x = C.basis() + sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] + sage: Y = C.submodule(gens, unitriangular=True) + sage: Y.lift.matrix() [ 1 0] [ 0 1] [-1 -1] @@ -867,17 +881,18 @@ def submodule(self, gens, check=True, already_echelonized=False, We now construct a (finite-dimensional) submodule of an infinite dimensional free module:: - sage: C = CombinatorialFreeModule(QQ, ZZ, prefix='z') # optional - sage.modules - sage: z = C.basis() # optional - sage.modules - sage: gens = [z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]] # optional - sage.modules - sage: Y = C.submodule(gens) # optional - sage.modules - sage: [Y.lift(b) for b in Y.basis()] # optional - sage.modules + sage: # needs sage.modules + sage: C = CombinatorialFreeModule(QQ, ZZ, prefix='z') + sage: z = C.basis() + sage: gens = [z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]] + sage: Y = C.submodule(gens) + sage: [Y.lift(b) for b in Y.basis()] [z[0] - z[2], z[1] - z[2]] TESTS:: - sage: TestSuite(Y).run() # optional - sage.modules - sage: TestSuite(center).run() # optional - sage.groups sage.modules + sage: TestSuite(Y).run() # needs sage.modules + sage: TestSuite(center).run() # needs sage.combinat sage.groups sage.modules """ # Make sure gens consists of elements of ``self`` from sage.sets.family import Family, AbstractFamily @@ -920,25 +935,27 @@ def quotient_module(self, submodule, check=True, already_echelonized=False, cate EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: Y = X.quotient_module([x[0] - x[1], x[1] - x[2]], # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") + sage: x = X.basis() + sage: Y = X.quotient_module([x[0] - x[1], x[1] - x[2]], ....: already_echelonized=True) - sage: Y.print_options(prefix='y'); Y # optional - sage.modules + sage: Y.print_options(prefix='y'); Y Free module generated by {2} over Rational Field - sage: y = Y.basis() # optional - sage.modules - sage: y[2] # optional - sage.modules + sage: y = Y.basis() + sage: y[2] y[2] - sage: y[2].lift() # optional - sage.modules + sage: y[2].lift() x[2] - sage: Y.retract(x[0] + 2*x[1]) # optional - sage.modules + sage: Y.retract(x[0] + 2*x[1]) 3*y[2] + sage: # needs sage.modules sage: R. = QQ[] - sage: C = CombinatorialFreeModule(R, range(3), prefix='x') # optional - sage.modules - sage: x = C.basis() # optional - sage.modules - sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] # optional - sage.modules - sage: Y = C.quotient_module(gens) # optional - sage.modules + sage: C = CombinatorialFreeModule(R, range(3), prefix='x') + sage: x = C.basis() + sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] + sage: Y = C.quotient_module(gens) .. SEEALSO:: @@ -960,10 +977,10 @@ def tensor(*parents, **kwargs): EXAMPLES:: sage: C = AlgebrasWithBasis(QQ) - sage: A = C.example(); A.rename("A") # optional - sage.combinat sage.modules - sage: A.tensor(A, A) # optional - sage.combinat sage.modules + sage: A = C.example(); A.rename("A") # needs sage.combinat sage.modules + sage: A.tensor(A, A) # needs sage.combinat sage.modules A # A # A - sage: A.rename(None) # optional - sage.combinat sage.modules + sage: A.rename(None) # needs sage.combinat sage.modules """ constructor = kwargs.pop('constructor', tensor) cat = constructor.category_from_parents(parents) @@ -975,24 +992,26 @@ def cardinality(self): EXAMPLES:: - sage: S = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules - sage: S.cardinality() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: S = SymmetricGroupAlgebra(QQ, 4) + sage: S.cardinality() +Infinity - sage: S = SymmetricGroupAlgebra(GF(2), 4) # not tested -- MRO bug trac #15475 # optional - sage.groups sage.rings.finite_rings sage.modules - sage: S.cardinality() # not tested -- MRO bug trac #15475 # optional - sage.groups sage.rings.finite_rings sage.modules + sage: S = SymmetricGroupAlgebra(GF(2), 4) # not tested + sage: S.cardinality() # not tested 16777216 - sage: S.cardinality().factor() # not tested -- MRO bug trac #15475 # optional - sage.groups sage.rings.finite_rings sage.modules + sage: S.cardinality().factor() # not tested 2^24 - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: E.cardinality() # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: E.cardinality() +Infinity - sage: E. = ExteriorAlgebra(GF(3)) # optional - sage.combinat sage.rings.finite_rings sage.modules - sage: E.cardinality() # optional - sage.combinat sage.rings.finite_rings sage.modules + sage: E. = ExteriorAlgebra(GF(3)) + sage: E.cardinality() 81 - sage: s = SymmetricFunctions(GF(2)).s() # optional - sage.combinat sage.rings.finite_rings sage.modules - sage: s.cardinality() # optional - sage.combinat sage.rings.finite_rings sage.modules + sage: s = SymmetricFunctions(GF(2)).s() # needs sage.combinat sage.modules + sage: s.cardinality() # needs sage.combinat sage.modules +Infinity """ from sage.rings.infinity import Infinity @@ -1009,11 +1028,11 @@ def is_finite(self): EXAMPLES:: - sage: GroupAlgebra(SymmetricGroup(2), IntegerModRing(10)).is_finite() # optional - sage.groups sage.modules + sage: GroupAlgebra(SymmetricGroup(2), IntegerModRing(10)).is_finite() # needs sage.combinat sage.groups sage.modules True - sage: GroupAlgebra(SymmetricGroup(2)).is_finite() # optional - sage.groups sage.modules + sage: GroupAlgebra(SymmetricGroup(2)).is_finite() # needs sage.combinat sage.groups sage.modules False - sage: GroupAlgebra(AbelianGroup(1), IntegerModRing(10)).is_finite() # optional - sage.groups sage.modules + sage: GroupAlgebra(AbelianGroup(1), IntegerModRing(10)).is_finite() # needs sage.groups sage.modules False """ return (self.base_ring().is_finite() and self.group().is_finite()) @@ -1028,13 +1047,13 @@ def monomial(self, i): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules - sage: F.monomial('a') # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules + sage: F.monomial('a') # needs sage.modules B['a'] ``F.monomial`` is in fact (almost) a map:: - sage: F.monomial # optional - sage.modules + sage: F.monomial # needs sage.modules Term map from {'a', 'b', 'c'} to Free module generated by {'a', 'b', 'c'} over Rational Field """ @@ -1045,8 +1064,8 @@ def _sum_of_monomials(self, indices): TESTS:: sage: R. = QQ[] - sage: W = DifferentialWeylAlgebra(R) # optional - sage.combinat sage.modules - sage: W._sum_of_monomials([((1,0), (1,0)), ((0,0), (0,1))]) # optional - sage.combinat sage.modules + sage: W = DifferentialWeylAlgebra(R) # needs sage.modules + sage: W._sum_of_monomials([((1,0), (1,0)), ((0,0), (0,1))]) # needs sage.modules dy + x*dx """ # This is the generic implementation. When implementing a @@ -1067,16 +1086,16 @@ def sum_of_monomials(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules - sage: F.sum_of_monomials(['a', 'b']) # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules + sage: F.sum_of_monomials(['a', 'b']) # needs sage.modules B['a'] + B['b'] - sage: F.sum_of_monomials(['a', 'b', 'a']) # optional - sage.modules + sage: F.sum_of_monomials(['a', 'b', 'a']) # needs sage.modules 2*B['a'] + B['b'] ``F.sum_of_monomials`` is in fact (almost) a map:: - sage: F.sum_of_monomials # optional - sage.modules + sage: F.sum_of_monomials # needs sage.modules A map to Free module generated by {'a', 'b', 'c'} over Rational Field """ # domain = iterables of basis indices of self. @@ -1086,10 +1105,10 @@ def monomial_or_zero_if_none(self, i): """ EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules - sage: F.monomial_or_zero_if_none('a') # optional - sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules + sage: F.monomial_or_zero_if_none('a') # needs sage.modules B['a'] - sage: F.monomial_or_zero_if_none(None) # optional - sage.modules + sage: F.monomial_or_zero_if_none(None) # needs sage.modules 0 """ if i is None: @@ -1111,9 +1130,9 @@ def term(self, index, coeff=None): EXAMPLES:: - sage: m = matrix([[0,1], [1,1]]) # optional - sage.modules - sage: J. = JordanAlgebra(m) # optional - sage.combinat sage.modules - sage: J.term(1, -2) # optional - sage.combinat sage.modules + sage: m = matrix([[0,1], [1,1]]) # needs sage.modules + sage: J. = JordanAlgebra(m) # needs sage.combinat sage.modules + sage: J.term(1, -2) # needs sage.combinat sage.modules 0 + (-2, 0) Design: should this do coercion on the coefficient ring? @@ -1137,9 +1156,9 @@ def sum_of_terms(self, terms): EXAMPLES:: - sage: m = matrix([[0,1], [1,1]]) # optional - sage.modules - sage: J. = JordanAlgebra(m) # optional - sage.combinat sage.modules - sage: J.sum_of_terms([(0, 2), (2, -3)]) # optional - sage.combinat sage.modules + sage: m = matrix([[0,1], [1,1]]) # needs sage.modules + sage: J. = JordanAlgebra(m) # needs sage.combinat sage.modules + sage: J.sum_of_terms([(0, 2), (2, -3)]) # needs sage.combinat sage.modules 2 + (0, -3) """ return self.sum(self.term(index, coeff) for (index, coeff) in terms) @@ -1166,21 +1185,22 @@ def _apply_module_morphism(self, x, on_basis, codomain=False): EXAMPLES:: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: a = s([3]) + s([2,1]) + s([1,1,1]) # optional - sage.combinat sage.modules - sage: b = 2*a # optional - sage.combinat sage.modules - sage: f = lambda part: Integer(len(part)) # optional - sage.combinat sage.modules - sage: s._apply_module_morphism(a, f) #1+2+3 # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() + sage: a = s([3]) + s([2,1]) + s([1,1,1]) + sage: b = 2*a + sage: f = lambda part: Integer(len(part)) + sage: s._apply_module_morphism(a, f) #1+2+3 6 - sage: s._apply_module_morphism(b, f) #2*(1+2+3) # optional - sage.combinat sage.modules + sage: s._apply_module_morphism(b, f) #2*(1+2+3) 12 - sage: s._apply_module_morphism(s(0), f) # optional - sage.combinat sage.modules + sage: s._apply_module_morphism(s(0), f) 0 - sage: s._apply_module_morphism(s(1), f) # optional - sage.combinat sage.modules + sage: s._apply_module_morphism(s(1), f) 0 - sage: s._apply_module_morphism(s(1), lambda part: len(part), ZZ) # optional - sage.combinat sage.modules + sage: s._apply_module_morphism(s(1), lambda part: len(part), ZZ) 0 - sage: s._apply_module_morphism(s(1), lambda part: len(part)) # optional - sage.combinat sage.modules + sage: s._apply_module_morphism(s(1), lambda part: len(part)) Traceback (most recent call last): ... ValueError: codomain could not be determined @@ -1222,9 +1242,9 @@ def _apply_module_endomorphism(self, x, on_basis): EXAMPLES:: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = lambda part: 2 * s(part.conjugate()) # optional - sage.combinat sage.modules - sage: s._apply_module_endomorphism(s([2,1]) + s([1,1,1]), f) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = lambda part: 2 * s(part.conjugate()) + sage: s._apply_module_endomorphism(s([2,1]) + s([1,1,1]), f) # needs sage.combinat sage.modules 2*s[2, 1] + 2*s[3] """ mc = x.monomial_coefficients(copy=False) @@ -1237,8 +1257,8 @@ def dimension(self): EXAMPLES:: - sage: A. = algebras.DifferentialWeyl(QQ) # optional - sage.combinat sage.modules - sage: A.dimension() # optional - sage.combinat sage.modules + sage: A. = algebras.DifferentialWeyl(QQ) # needs sage.modules + sage: A.dimension() # needs sage.modules +Infinity """ try: @@ -1258,17 +1278,18 @@ def _from_dict(self, d, coerce=True, remove_zeros=True): EXAMPLES:: - sage: A. = algebras.DifferentialWeyl(QQ) # optional - sage.combinat sage.modules - sage: K = A.basis().keys() # optional - sage.combinat sage.modules - sage: d = {K[0]: 3, K[12]: -4/3} # optional - sage.combinat sage.modules - sage: A._from_dict(d) # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: A. = algebras.DifferentialWeyl(QQ) + sage: K = A.basis().keys() + sage: d = {K[0]: 3, K[12]: -4/3} + sage: A._from_dict(d) -4/3*dx^2 + 3 sage: R. = QQ[] - sage: d = {K[0]: y, K[12]: -4/3} # optional - sage.combinat sage.modules - sage: A._from_dict(d, coerce=False) # optional - sage.combinat sage.modules + sage: d = {K[0]: y, K[12]: -4/3} # needs sage.modules + sage: A._from_dict(d, coerce=False) # needs sage.modules -4/3*dx^2 + y - sage: A._from_dict(d, coerce=True) # optional - sage.combinat sage.modules + sage: A._from_dict(d, coerce=True) # needs sage.modules Traceback (most recent call last): ... TypeError: not a constant polynomial @@ -1307,21 +1328,21 @@ def random_element(self, n=2): EXAMPLES:: - sage: x = DihedralGroup(6).algebra(QQ).random_element() # optional - sage.groups sage.modules - sage: x.parent() is DihedralGroup(6).algebra(QQ) # optional - sage.groups sage.modules + sage: x = DihedralGroup(6).algebra(QQ).random_element() # needs sage.groups sage.modules + sage: x.parent() is DihedralGroup(6).algebra(QQ) # needs sage.groups sage.modules True Note, this result can depend on the PRNG state in libgap in a way that depends on which packages are loaded, so we must re-seed GAP to ensure a consistent result for this example:: - sage: libgap.set_seed(0) # optional - sage.libs.gap + sage: libgap.set_seed(0) # needs sage.libs.gap 0 - sage: m = SU(2, 13).algebra(QQ).random_element(1) # optional - sage.groups sage.modules - sage: m.parent() is SU(2, 13).algebra(QQ) # optional - sage.groups sage.modules + sage: m = SU(2, 13).algebra(QQ).random_element(1) # needs sage.groups sage.libs.pari sage.modules + sage: m.parent() is SU(2, 13).algebra(QQ) # needs sage.groups sage.libs.pari sage.modules True - sage: p = CombinatorialFreeModule(ZZ, Partitions(4)).random_element() # optional - sage.combinat sage.modules - sage: p.parent() is CombinatorialFreeModule(ZZ, Partitions(4)) # optional - sage.combinat sage.modules + sage: p = CombinatorialFreeModule(ZZ, Partitions(4)).random_element() # needs sage.combinat sage.modules + sage: p.parent() is CombinatorialFreeModule(ZZ, Partitions(4)) # needs sage.combinat sage.modules True TESTS: @@ -1331,7 +1352,7 @@ def random_element(self, n=2): coerce the base ring's zero into the algebra, and that we can find a random element in a trivial module:: - sage: class Foo(CombinatorialFreeModule): # optional - sage.modules + sage: class Foo(CombinatorialFreeModule): # needs sage.modules ....: def _element_constructor_(self,x): ....: if x in self: ....: return x @@ -1339,8 +1360,8 @@ def random_element(self, n=2): ....: raise ValueError sage: from sage.categories.magmatic_algebras import MagmaticAlgebras sage: C = MagmaticAlgebras(QQ).WithBasis().Unital() - sage: F = Foo(QQ, tuple(), category=C) # optional - sage.modules - sage: F.random_element() == F.zero() # optional - sage.modules + sage: F = Foo(QQ, tuple(), category=C) # needs sage.modules + sage: F.random_element() == F.zero() # needs sage.modules True """ @@ -1380,25 +1401,27 @@ def monomial_coefficients(self, copy=True): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] + 3*B['c'] # optional - sage.modules - sage: d = f.monomial_coefficients() # optional - sage.modules - sage: d['a'] # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: d = f.monomial_coefficients() + sage: d['a'] 1 - sage: d['c'] # optional - sage.modules + sage: d['c'] 3 TESTS: We check that we make a copy of the coefficient dictionary:: - sage: F = CombinatorialFreeModule(ZZ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] + 3*B['c'] # optional - sage.modules - sage: d = f.monomial_coefficients() # optional - sage.modules - sage: d['a'] = 5 # optional - sage.modules - sage: f # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(ZZ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: d = f.monomial_coefficients() + sage: d['a'] = 5 + sage: f B['a'] + 3*B['c'] """ @@ -1408,10 +1431,10 @@ def __getitem__(self, m): EXAMPLES:: - sage: W. = DifferentialWeylAlgebra(QQ) # optional - sage.combinat sage.modules - sage: x[((0,0,0), (0,0,0))] # optional - sage.combinat sage.modules + sage: W. = DifferentialWeylAlgebra(QQ) # needs sage.modules + sage: x[((0,0,0), (0,0,0))] # needs sage.modules 0 - sage: x[((1,0,0), (0,0,0))] # optional - sage.combinat sage.modules + sage: x[((1,0,0), (0,0,0))] # needs sage.modules 1 """ res = self.monomial_coefficients(copy=False).get(m) @@ -1437,19 +1460,20 @@ def coefficient(self, m): EXAMPLES:: - sage: s = CombinatorialFreeModule(QQ, Partitions()) # optional - sage.combinat sage.modules - sage: z = s([4]) - 2*s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules - sage: z.coefficient([4]) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: s = CombinatorialFreeModule(QQ, Partitions()) + sage: z = s([4]) - 2*s([2,1]) + s([1,1,1]) + s([1]) + sage: z.coefficient([4]) 1 - sage: z.coefficient([2,1]) # optional - sage.combinat sage.modules + sage: z.coefficient([2,1]) -2 - sage: z.coefficient(Partition([2,1])) # optional - sage.combinat sage.modules + sage: z.coefficient(Partition([2,1])) -2 - sage: z.coefficient([1,2]) # optional - sage.combinat sage.modules + sage: z.coefficient([1,2]) Traceback (most recent call last): ... AssertionError: [1, 2] should be an element of Partitions - sage: z.coefficient(Composition([2,1])) # optional - sage.combinat sage.modules + sage: z.coefficient(Composition([2,1])) Traceback (most recent call last): ... AssertionError: [2, 1] should be an element of Partitions @@ -1457,19 +1481,20 @@ def coefficient(self, m): Test that ``coefficient`` also works for those parents that do not have an ``element_class``:: - sage: H = pAdicWeightSpace(3) # optional - sage.modules sage.rings.padics - sage: F = CombinatorialFreeModule(QQ, H) # optional - sage.modules sage.rings.padics - sage: hasattr(H, "element_class") # optional - sage.modules sage.rings.padics + sage: # needs sage.modules sage.rings.padics + sage: H = pAdicWeightSpace(3) + sage: F = CombinatorialFreeModule(QQ, H) + sage: hasattr(H, "element_class") False - sage: h = H.an_element() # optional - sage.modules sage.rings.padics - sage: (2*F.monomial(h)).coefficient(h) # optional - sage.modules sage.rings.padics + sage: h = H.an_element() + sage: (2*F.monomial(h)).coefficient(h) 2 """ # NT: coefficient_fast should be the default, just with appropriate assertions # that can be turned on or off C = self.parent().basis().keys() # TODO: This should raise a ValueError - TS - assert m in C, "%s should be an element of %s"%(m, C) + assert m in C, "%s should be an element of %s" % (m, C) if hasattr(C, "element_class") and not isinstance(m, C.element_class): m = C(m) return self[m] @@ -1480,22 +1505,24 @@ def is_zero(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] - 3*B['c'] # optional - sage.modules - sage: f.is_zero() # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: f.is_zero() False - sage: F.zero().is_zero() # optional - sage.modules + sage: F.zero().is_zero() True :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: s([2,1]).is_zero() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() + sage: s([2,1]).is_zero() False - sage: s(0).is_zero() # optional - sage.combinat sage.modules + sage: s(0).is_zero() True - sage: (s([2,1]) - s([2,1])).is_zero() # optional - sage.combinat sage.modules + sage: (s([2,1]) - s([2,1])).is_zero() True """ zero = self.parent().base_ring().zero() @@ -1508,17 +1535,18 @@ def __len__(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] - 3*B['c'] # optional - sage.modules - sage: len(f) # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: len(f) 2 :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules - sage: len(z) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules + sage: len(z) # needs sage.combinat sage.modules 4 """ return len(self.support()) @@ -1530,17 +1558,18 @@ def length(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] - 3*B['c'] # optional - sage.modules - sage: f.length() # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: f.length() 2 :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules - sage: z.length() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules + sage: z.length() # needs sage.combinat sage.modules 4 """ return len(self) @@ -1555,17 +1584,18 @@ def support(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] - 3*B['c'] # optional - sage.modules - sage: sorted(f.support()) # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: sorted(f.support()) ['a', 'c'] :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules - sage: sorted(z.support()) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules + sage: sorted(z.support()) # needs sage.combinat sage.modules [[1], [1, 1, 1], [2, 1], [4]] """ try: @@ -1593,13 +1623,14 @@ def monomials(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] + 2*B['c'] # optional - sage.modules - sage: f.monomials() # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 2*B['c'] + sage: f.monomials() [B['a'], B['c']] - sage: (F.zero()).monomials() # optional - sage.modules + sage: (F.zero()).monomials() # needs sage.modules [] """ P = self.parent() @@ -1614,10 +1645,11 @@ def terms(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] + 2*B['c'] # optional - sage.modules - sage: f.terms() # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 2*B['c'] + sage: f.terms() [B['a'], 2*B['c']] """ P = self.parent() @@ -1642,20 +1674,21 @@ def coefficients(self, sort=True): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] - 3*B['c'] # optional - sage.modules - sage: f.coefficients() # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: f.coefficients() [1, -3] - sage: f = B['c'] - 3*B['a'] # optional - sage.modules - sage: f.coefficients() # optional - sage.modules + sage: f = B['c'] - 3*B['a'] + sage: f.coefficients() [-3, 1] :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules - sage: z.coefficients() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules + sage: z.coefficients() # needs sage.combinat sage.modules [1, 1, 1, 1] """ zero = self.parent().base_ring().zero() @@ -1674,15 +1707,15 @@ def support_of_term(self): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename("X") # optional - sage.modules - sage: X.monomial(2).support_of_term() # optional - sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename("X") # needs sage.modules + sage: X.monomial(2).support_of_term() # needs sage.modules 2 - sage: X.term(3, 2).support_of_term() # optional - sage.modules + sage: X.term(3, 2).support_of_term() # needs sage.modules 3 An exception is raised if ``self`` has more than one term:: - sage: (X.monomial(2) + X.monomial(3)).support_of_term() # optional - sage.modules + sage: (X.monomial(2) + X.monomial(3)).support_of_term() # needs sage.modules Traceback (most recent call last): ... ValueError: B[2] + B[3] is not a single term @@ -1704,18 +1737,19 @@ def leading_support(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]) # optional - sage.modules - sage: X.rename("X"); x = X.basis() # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # optional - sage.modules - sage: x.leading_support() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]) + sage: X.rename("X"); x = X.basis() + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) + sage: x.leading_support() 3 - sage: def key(x): return -x # optional - sage.modules - sage: x.leading_support(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.leading_support(key=key) 1 - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.leading_support() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.leading_support() # needs sage.combinat sage.modules [3] """ return max(self.support(), *args, **kwds) @@ -1739,17 +1773,18 @@ def leading_item(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # optional - sage.modules - sage: x.leading_item() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) + sage: x.leading_item() (3, 4) - sage: def key(x): return -x # optional - sage.modules - sage: x.leading_item(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.leading_item(key=key) (1, 3) - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.leading_item() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.leading_item() # needs sage.combinat sage.modules ([3], -5) """ k = self.leading_support(*args, **kwds) @@ -1768,17 +1803,18 @@ def leading_monomial(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.leading_monomial() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.leading_monomial() B[3] - sage: def key(x): return -x # optional - sage.modules - sage: x.leading_monomial(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.leading_monomial(key=key) B[1] - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.leading_monomial() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.leading_monomial() # needs sage.combinat sage.modules s[3] """ return self.parent().monomial(self.leading_support(*args, **kwds)) @@ -1796,17 +1832,18 @@ def leading_coefficient(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.leading_coefficient() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.leading_coefficient() 1 - sage: def key(x): return -x # optional - sage.modules - sage: x.leading_coefficient(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.leading_coefficient(key=key) 3 - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.leading_coefficient() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.leading_coefficient() # needs sage.combinat sage.modules -5 """ return self.leading_item(*args, **kwds)[1] @@ -1824,17 +1861,18 @@ def leading_term(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.leading_term() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.leading_term() B[3] - sage: def key(x): return -x # optional - sage.modules - sage: x.leading_term(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.leading_term(key=key) 3*B[1] - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.leading_term() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.leading_term() # needs sage.combinat sage.modules -5*s[3] """ return self.parent().term(*self.leading_item(*args, **kwds)) @@ -1850,18 +1888,18 @@ def trailing_support(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # optional - sage.modules - sage: x.trailing_support() # optional - sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # needs sage.modules + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # needs sage.modules + sage: x.trailing_support() # needs sage.modules 1 - sage: def key(x): return -x # optional - sage.modules - sage: x.trailing_support(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.trailing_support(key=key) # needs sage.modules 3 - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.trailing_support() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.trailing_support() # needs sage.combinat sage.modules [1] """ return min(self.support(), *args, **kwds) @@ -1880,17 +1918,18 @@ def trailing_item(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.trailing_item() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.trailing_item() (1, 3) - sage: def key(x): return -x # optional - sage.modules - sage: x.trailing_item(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.trailing_item(key=key) (3, 1) - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.trailing_item() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.trailing_item() # needs sage.combinat sage.modules ([1], 2) """ k = self.trailing_support(*args, **kwds) @@ -1909,17 +1948,18 @@ def trailing_monomial(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.trailing_monomial() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.trailing_monomial() B[1] - sage: def key(x): return -x # optional - sage.modules - sage: x.trailing_monomial(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.trailing_monomial(key=key) B[3] - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.trailing_monomial() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.trailing_monomial() # needs sage.combinat sage.modules s[1] """ return self.parent().monomial(self.trailing_support(*args, **kwds)) @@ -1937,17 +1977,18 @@ def trailing_coefficient(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.trailing_coefficient() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.trailing_coefficient() 3 - sage: def key(x): return -x # optional - sage.modules - sage: x.trailing_coefficient(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.trailing_coefficient(key=key) 1 - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.trailing_coefficient() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.trailing_coefficient() # needs sage.combinat sage.modules 2 """ return self.trailing_item(*args, **kwds)[1] @@ -1965,17 +2006,18 @@ def trailing_term(self, *args, **kwds): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules - sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules - sage: x.trailing_term() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") + sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) + sage: x.trailing_term() 3*B[1] - sage: def key(x): return -x # optional - sage.modules - sage: x.trailing_term(key=key) # optional - sage.modules + sage: def key(x): return -x + sage: x.trailing_term(key=key) B[3] - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules - sage: f.trailing_term() # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules + sage: f.trailing_term() # needs sage.combinat sage.modules 2*s[1] """ return self.parent().term(*self.trailing_item(*args, **kwds)) @@ -1994,24 +2036,25 @@ def map_coefficients(self, f): EXAMPLES:: - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules - sage: B = F.basis() # optional - sage.modules - sage: f = B['a'] - 3*B['c'] # optional - sage.modules - sage: f.map_coefficients(lambda x: x + 5) # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: f.map_coefficients(lambda x: x + 5) 6*B['a'] + 2*B['c'] Killed coefficients are handled properly:: - sage: f.map_coefficients(lambda x: 0) # optional - sage.modules + sage: f.map_coefficients(lambda x: 0) # needs sage.modules 0 - sage: list(f.map_coefficients(lambda x: 0)) # optional - sage.modules + sage: list(f.map_coefficients(lambda x: 0)) # needs sage.modules [] :: - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: a = s([2,1]) + 2*s([3,2]) # optional - sage.combinat sage.modules - sage: a.map_coefficients(lambda x: x * 2) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + 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 ) @@ -2030,30 +2073,30 @@ def map_support(self, f): EXAMPLES:: - sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # optional - sage.modules - sage: x = B.an_element(); x # optional - sage.modules + sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # needs sage.modules + sage: x = B.an_element(); x # needs sage.modules 2*B[-1] + 2*B[0] + 3*B[1] - sage: x.map_support(lambda i: -i) # optional - sage.modules + sage: x.map_support(lambda i: -i) # needs sage.modules 3*B[-1] + 2*B[0] + 2*B[1] ``f`` needs not be injective:: - sage: x.map_support(lambda i: 1) # optional - sage.modules + sage: x.map_support(lambda i: 1) # needs sage.modules 7*B[1] - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: a = s([2,1]) + 2*s([3,2]) # optional - sage.combinat sage.modules - sage: a.map_support(lambda x: x.conjugate()) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: a = s([2,1]) + 2*s([3,2]) # needs sage.combinat sage.modules + sage: a.map_support(lambda x: x.conjugate()) # needs sage.combinat sage.modules s[2, 1] + 2*s[2, 2, 1] TESTS:: - sage: B.zero() # This actually failed at some point!!! See #8890 # optional - sage.modules + sage: B.zero() # This actually failed at some point!!! See #8890 # needs sage.modules 0 - sage: y = B.zero().map_support(lambda i: i/0); y # optional - sage.modules + sage: y = B.zero().map_support(lambda i: i/0); y # needs sage.modules 0 - sage: y.parent() is B # optional - sage.modules + sage: y.parent() is B # needs sage.modules True """ return self.parent().sum_of_terms( (f(m), c) for m,c in self ) @@ -2072,22 +2115,22 @@ def map_support_skip_none(self, f): EXAMPLES:: - sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # optional - sage.modules - sage: x = B.an_element(); x # optional - sage.modules + sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # needs sage.modules + sage: x = B.an_element(); x # needs sage.modules 2*B[-1] + 2*B[0] + 3*B[1] - sage: x.map_support_skip_none(lambda i: -i if i else None) # optional - sage.modules + sage: x.map_support_skip_none(lambda i: -i if i else None) # needs sage.modules 3*B[-1] + 2*B[1] ``f`` needs not be injective:: - sage: x.map_support_skip_none(lambda i: 1 if i else None) # optional - sage.modules + sage: x.map_support_skip_none(lambda i: 1 if i else None) # needs sage.modules 5*B[1] TESTS:: - sage: y = x.map_support_skip_none(lambda i: None); y # optional - sage.modules + sage: y = x.map_support_skip_none(lambda i: None); y # needs sage.modules 0 - sage: y.parent() is B # optional - sage.modules + 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) @@ -2107,21 +2150,21 @@ def map_item(self, f): EXAMPLES:: - sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # optional - sage.modules - sage: x = B.an_element(); x # optional - sage.modules + sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # needs sage.modules + sage: x = B.an_element(); x # needs sage.modules 2*B[-1] + 2*B[0] + 3*B[1] - sage: x.map_item(lambda i, c: (-i, 2*c)) # optional - sage.modules + sage: x.map_item(lambda i, c: (-i, 2*c)) # needs sage.modules 6*B[-1] + 4*B[0] + 4*B[1] ``f`` needs not be injective:: - sage: x.map_item(lambda i, c: (1, 2*c)) # optional - sage.modules + sage: x.map_item(lambda i, c: (1, 2*c)) # needs sage.modules 14*B[1] - sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules - sage: f = lambda m, c: (m.conjugate(), 2 * c) # optional - sage.combinat sage.modules - sage: a = s([2,1]) + s([1,1,1]) # optional - sage.combinat sage.modules - sage: a.map_item(f) # optional - sage.combinat sage.modules + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules + sage: f = lambda m, c: (m.conjugate(), 2 * c) + sage: a = s([2,1]) + s([1,1,1]) # needs sage.combinat sage.modules + 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 ) @@ -2134,9 +2177,9 @@ def tensor(*elements): EXAMPLES:: sage: C = AlgebrasWithBasis(QQ) - sage: A = C.example() # optional - sage.combinat sage.modules - sage: a, b, c = A.algebra_generators() # optional - sage.combinat sage.modules - sage: a.tensor(b, c) # optional - sage.combinat sage.modules + sage: A = C.example() # needs sage.combinat sage.modules + sage: a, b, c = A.algebra_generators() # needs sage.combinat sage.modules + sage: a.tensor(b, c) # needs sage.combinat sage.modules B[word: a] # B[word: b] # B[word: c] FIXME: is this a policy that we want to enforce on all parents? @@ -2166,50 +2209,51 @@ def __call_on_basis__(self, **options): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") # optional - sage.modules - sage: H = Hom(X, Y) # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") + sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") + sage: H = Hom(X, Y) + sage: x = X.basis() sage: def on_basis(i): ....: return Y.monomial(i) + 2*Y.monomial(i + 1) - sage: phi = H(on_basis=on_basis) # indirect doctest # optional - sage.modules - sage: phi # optional - sage.modules + sage: phi = H(on_basis=on_basis) # indirect doctest + sage: phi Generic morphism: - From: X - To: Y - sage: phi(x[1] + x[3]) # optional - sage.modules + From: X + To: Y + sage: phi(x[1] + x[3]) B[1] + 2*B[2] + B[3] + 2*B[4] Diagonal functions can be constructed using the ``diagonal`` option:: - sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename("X") # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4], # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename("X") + sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4], ....: key="Y"); Y.rename("Y") - sage: H = Hom(X, Y) # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - sage: phi = H(diagonal=lambda x: x^2) # optional - sage.modules - sage: phi(x[1] + x[2] + x[3]) # optional - sage.modules + sage: H = Hom(X, Y) + sage: x = X.basis() + sage: phi = H(diagonal=lambda x: x^2) + sage: phi(x[1] + x[2] + x[3]) B[1] + 4*B[2] + 9*B[3] TESTS: As for usual homsets, the argument can be a Python function:: - sage: phi = H(lambda x: Y.zero()) # optional - sage.modules - sage: phi # optional - sage.modules + sage: phi = H(lambda x: Y.zero()); phi # needs sage.modules Generic morphism: From: X To: Y - sage: phi(x[1] + x[3]) # optional - sage.modules + sage: phi(x[1] + x[3]) # needs sage.modules 0 We check that the homset category is properly set up:: - sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") # optional - sage.modules - sage: H = Hom(X, Y) # optional - sage.modules - sage: H.zero().category_for() # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") + sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") + sage: H = Hom(X, Y) + sage: H.zero().category_for() Category of finite dimensional vector spaces with basis over Rational Field """ return self.domain().module_morphism(codomain=self.codomain(), @@ -2228,20 +2272,19 @@ def on_basis(self): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") # optional - sage.modules - sage: H = Hom(X, Y) # optional - sage.modules - sage: x = X.basis() # optional - sage.modules - - sage: f = H(lambda x: Y.zero()).on_basis() # optional - sage.modules - sage: f(2) # optional - sage.modules + sage: # needs sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") + sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") + sage: H = Hom(X, Y) + sage: x = X.basis() + sage: f = H(lambda x: Y.zero()).on_basis() + sage: f(2) 0 - - sage: f = lambda i: Y.monomial(i) + 2*Y.monomial(i+1) # optional - sage.modules - sage: g = H(on_basis=f).on_basis() # optional - sage.modules - sage: g(2) # optional - sage.modules + sage: f = lambda i: Y.monomial(i) + 2*Y.monomial(i+1) + sage: g = H(on_basis=f).on_basis() + sage: g(2) B[2] + 2*B[3] - sage: g == f # optional - sage.modules + sage: g == f True """ return self._on_basis @@ -2256,9 +2299,9 @@ def _on_basis(self, i): EXAMPLES:: - sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules - sage: phi = End(X)(lambda x: 2*x) # optional - sage.modules - sage: phi._on_basis(3) # optional - sage.modules + sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # needs sage.modules + sage: phi = End(X)(lambda x: 2*x) # needs sage.modules + sage: phi._on_basis(3) # needs sage.modules 2*B[3] """ return self(self.domain().monomial(i)) @@ -2288,20 +2331,21 @@ def _an_element_(self): """ EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.groups sage.modules + sage: A = AlgebrasWithBasis(QQ).example(); A An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: B = HopfAlgebrasWithBasis(QQ).example(); B # optional - sage.combinat sage.modules + sage: B = HopfAlgebrasWithBasis(QQ).example(); B An example of Hopf algebra with basis: the group algebra of the Dihedral group of order 6 as a permutation group over Rational Field - sage: A.an_element() # optional - sage.combinat sage.modules + sage: A.an_element() B[word: ] + 2*B[word: a] + 3*B[word: b] + B[word: bab] - sage: B.an_element() # optional - sage.combinat sage.modules + sage: B.an_element() B[()] + B[(1,2)] + 3*B[(1,2,3)] + 2*B[(1,3,2)] - sage: ABA = cartesian_product((A, B, A)) # optional - sage.combinat sage.modules - sage: ABA.an_element() # indirect doctest # optional - sage.combinat sage.modules + sage: ABA = cartesian_product((A, B, A)) + sage: ABA.an_element() # indirect doctest 2*B[(0, word: )] + 2*B[(0, word: a)] + 3*B[(0, word: b)] """ from .cartesian_product import cartesian_product @@ -2364,10 +2408,11 @@ def apply_multilinear_morphism(self, f, codomain=None): We start with simple (admittedly not so interesting) examples, with two modules `A` and `B`:: - sage: A = CombinatorialFreeModule(ZZ, [1,2], prefix="A") # optional - sage.modules - sage: A.rename("A") # optional - sage.modules - sage: B = CombinatorialFreeModule(ZZ, [3,4], prefix="B") # optional - sage.modules - sage: B.rename("B") # optional - sage.modules + sage: # needs sage.modules + sage: A = CombinatorialFreeModule(ZZ, [1,2], prefix="A") + sage: A.rename("A") + sage: B = CombinatorialFreeModule(ZZ, [3,4], prefix="B") + sage: B.rename("B") and `f` the bilinear morphism `(a,b) \mapsto b \otimes a` from `A \times B` to `B \otimes A`:: @@ -2378,13 +2423,14 @@ def apply_multilinear_morphism(self, f, codomain=None): Now, calling applying `f` on `a \otimes b` returns the same as `f(a,b)`:: - sage: a = A.monomial(1) + 2 * A.monomial(2); a # optional - sage.modules + sage: # needs sage.modules + sage: a = A.monomial(1) + 2 * A.monomial(2); a A[1] + 2*A[2] - sage: b = B.monomial(3) - 2 * B.monomial(4); b # optional - sage.modules + sage: b = B.monomial(3) - 2 * B.monomial(4); b B[3] - 2*B[4] - sage: f(a, b) # optional - sage.modules + sage: f(a, b) B[3] # A[1] + 2*B[3] # A[2] - 2*B[4] # A[1] - 4*B[4] # A[2] - sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules + sage: tensor([a, b]).apply_multilinear_morphism(f) B[3] # A[1] + 2*B[3] # A[2] - 2*B[4] # A[1] - 4*B[4] # A[2] `f` may be a bilinear morphism to any module over the @@ -2392,9 +2438,9 @@ def apply_multilinear_morphism(self, f, codomain=None): sage: def f(a, b): ....: return sum(a.coefficients(), 0) * sum(b.coefficients(), 0) - sage: f(a, b) # optional - sage.modules + sage: f(a, b) # needs sage.modules -3 - sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules + sage: tensor([a, b]).apply_multilinear_morphism(f) # needs sage.modules -3 Mind the `0` in the sums above; otherwise `f` would @@ -2402,12 +2448,12 @@ def apply_multilinear_morphism(self, f, codomain=None): sage: def f(a,b): ....: return sum(a.coefficients()) * sum(b.coefficients()) - sage: type(f(A.zero(), B.zero())) # optional - sage.modules + sage: type(f(A.zero(), B.zero())) # needs sage.modules <... 'int'> Which would be wrong and break this method:: - sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules + sage: tensor([a, b]).apply_multilinear_morphism(f) # needs sage.modules Traceback (most recent call last): ... AttributeError: 'int' object has no attribute 'parent' @@ -2415,14 +2461,15 @@ def apply_multilinear_morphism(self, f, codomain=None): Here we consider an example where the codomain is a module with basis with a different base ring:: - sage: C = CombinatorialFreeModule(QQ, [(1,3),(2,4)], prefix="C") # optional - sage.modules - sage: C.rename("C") # optional - sage.modules + sage: # needs sage.modules + sage: C = CombinatorialFreeModule(QQ, [(1,3),(2,4)], prefix="C") + sage: C.rename("C") sage: def f(a, b): ....: return C.sum_of_terms([((1,3), QQ(a[1]*b[3])), ....: ((2,4), QQ(a[2]*b[4]))]) - sage: f(a,b) # optional - sage.modules + sage: f(a,b) C[(1, 3)] - 4*C[(2, 4)] - sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules + sage: tensor([a, b]).apply_multilinear_morphism(f) C[(1, 3)] - 4*C[(2, 4)] We conclude with a real life application, where we @@ -2430,14 +2477,15 @@ def apply_multilinear_morphism(self, f, codomain=None): Symmetric functions on the Schur basis satisfies its defining formula:: - sage: Sym = SymmetricFunctions(QQ) # optional - sage.combinat sage.modules - sage: s = Sym.schur() # optional - sage.combinat sage.modules - sage: def f(a, b): return a * b.antipode() # optional - sage.combinat sage.modules - sage: x = 4 * s.an_element(); x # optional - sage.combinat sage.modules + sage: # needs lrcalc_python sage.combinat sage.modules + sage: Sym = SymmetricFunctions(QQ) + sage: s = Sym.schur() + sage: def f(a, b): return a * b.antipode() + sage: x = 4 * s.an_element(); x 8*s[] + 8*s[1] + 12*s[2] - sage: x.coproduct().apply_multilinear_morphism(f) # optional - sage.combinat sage.modules + sage: x.coproduct().apply_multilinear_morphism(f) 8*s[] - sage: x.coproduct().apply_multilinear_morphism(f) == x.counit() # optional - sage.combinat sage.modules + sage: x.coproduct().apply_multilinear_morphism(f) == x.counit() True We recover the constant term of `x`, as desired. diff --git a/src/sage/categories/monoids.py b/src/sage/categories/monoids.py index ecf591c7559..38dd7248c9d 100644 --- a/src/sage/categories/monoids.py +++ b/src/sage/categories/monoids.py @@ -69,7 +69,7 @@ class Monoids(CategoryWithAxiom): Check for :trac:`31212`:: sage: R = IntegerModRing(15) - sage: R.submonoid([R.one()]).list() # optional - sage.groups + sage: R.submonoid([R.one()]).list() # needs sage.combinat [1] """ _base_category_class_and_axiom = (Semigroups, "Unital") @@ -98,11 +98,11 @@ def free(index_set=None, names=None, **kwds): EXAMPLES:: - sage: Monoids.free(index_set=ZZ) # optional - sage.groups + sage: Monoids.free(index_set=ZZ) # needs sage.combinat Free monoid indexed by Integer Ring - sage: Monoids().free(ZZ) # optional - sage.groups + sage: Monoids().free(ZZ) # needs sage.combinat Free monoid indexed by Integer Ring - sage: F. = Monoids().free(); F # optional - sage.groups + sage: F. = Monoids().free(); F # needs sage.combinat Free monoid indexed by {'x', 'y', 'z'} """ if names is not None: @@ -130,8 +130,8 @@ def semigroup_generators(self): EXAMPLES:: - sage: M = Monoids().free([1,2,3]) # optional - sage.groups - sage: M.semigroup_generators() # optional - sage.groups + sage: M = Monoids().free([1,2,3]) # needs sage.combinat + sage: M.semigroup_generators() # needs sage.combinat Family (1, F[1], F[2], F[3]) """ G = self.monoid_generators() @@ -212,22 +212,22 @@ def submonoid(self, generators, category=None): EXAMPLES:: sage: R = IntegerModRing(15) - sage: M = R.submonoid([R(3), R(5)]); M # optional - sage.groups + sage: M = R.submonoid([R(3), R(5)]); M # needs sage.combinat A submonoid of (Ring of integers modulo 15) with 2 generators - sage: M.list() # optional - sage.groups + sage: M.list() # needs sage.combinat [1, 3, 5, 9, 0, 10, 12, 6] Not the presence of the unit, unlike in:: - sage: S = R.subsemigroup([R(3), R(5)]); S # optional - sage.groups + sage: S = R.subsemigroup([R(3), R(5)]); S # needs sage.combinat A subsemigroup of (Ring of integers modulo 15) with 2 generators - sage: S.list() # optional - sage.groups + sage: S.list() # needs sage.combinat [3, 5, 9, 0, 10, 12, 6] This method is really a shorthand for subsemigroup:: - sage: M2 = R.subsemigroup([R(3), R(5)], one=R.one()) # optional - sage.groups - sage: M2 is M # optional - sage.groups + sage: M2 = R.subsemigroup([R(3), R(5)], one=R.one()) # needs sage.combinat + sage: M2 is M # needs sage.combinat True """ return self.subsemigroup(generators, one=self.one()) @@ -245,11 +245,12 @@ def _div_(left, right): EXAMPLES:: - sage: G = FreeGroup(2) # optional - sage.groups - sage: x0, x1 = G.group_generators() # optional - sage.groups - sage: c1 = cartesian_product([x0, x1]) # optional - sage.groups - sage: c2 = cartesian_product([x1, x0]) # optional - sage.groups - sage: c1._div_(c2) # optional - sage.groups + sage: # needs sage.groups + sage: G = FreeGroup(2) + sage: x0, x1 = G.group_generators() + sage: c1 = cartesian_product([x0, x1]) + sage: c2 = cartesian_product([x1, x0]) + sage: c1._div_(c2) (x0*x1^-1, x1*x0^-1) With this default implementation, division will fail as @@ -267,7 +268,7 @@ def _div_(left, right): TESTS:: - sage: c1._div_.__module__ # optional - sage.groups + sage: c1._div_.__module__ # needs sage.groups 'sage.categories.monoids' """ return left * ~right @@ -336,8 +337,8 @@ def powers(self, n): EXAMPLES:: - sage: A = Matrix([[1, 1], [-1, 0]]) # optional - sage.modules - sage: A.powers(6) # optional - sage.modules + sage: A = Matrix([[1, 1], [-1, 0]]) # needs sage.modules + sage: A.powers(6) # needs sage.modules [ [1 0] [ 1 1] [ 0 1] [-1 0] [-1 -1] [ 0 -1] [0 1], [-1 0], [-1 -1], [ 0 -1], [ 1 0], [ 1 1] @@ -363,8 +364,8 @@ def __invert__(self): EXAMPLES:: - sage: A = Matrix([[1, 0], [1, 1]]) # optional - sage.modules - sage: ~A # optional - sage.modules + sage: A = Matrix([[1, 0], [1, 1]]) # needs sage.modules + sage: ~A # needs sage.modules [ 1 0] [-1 1] """ @@ -377,9 +378,11 @@ def inverse(self): This is an alias for inversion, which can also be invoked by ``~x`` for an element ``x``. + Nota Bene: Element classes should implement ``__invert__`` only. + EXAMPLES:: - sage: AA(sqrt(~2)).inverse() # optional - sage.symbolic sage.rings.number_field + sage: AA(sqrt(~2)).inverse() # needs sage.rings.number_field sage.symbolic 1.414213562373095? """ # Nota Bene: Element classes should implement ``__invert__`` only. @@ -412,11 +415,11 @@ def free(index_set=None, names=None, **kwds): EXAMPLES:: - sage: Monoids.Commutative.free(index_set=ZZ) # optional - sage.groups + sage: Monoids.Commutative.free(index_set=ZZ) # needs sage.combinat Free abelian monoid indexed by Integer Ring - sage: Monoids().Commutative().free(ZZ) # optional - sage.groups + sage: Monoids().Commutative().free(ZZ) # needs sage.combinat Free abelian monoid indexed by Integer Ring - sage: F. = Monoids().Commutative().free(); F # optional - sage.groups + sage: F. = Monoids().Commutative().free(); F # needs sage.combinat Free abelian monoid indexed by {'x', 'y', 'z'} """ if names is not None: @@ -447,18 +450,18 @@ def one(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.one.__module__ # optional - sage.combinat sage.modules + sage: A.one.__module__ # needs sage.modules 'sage.categories.monoids' - sage: A.one() # optional - sage.combinat sage.modules + sage: A.one() # needs sage.modules F[{}] TESTS:: - sage: A.one() is A.a_realization().one() # optional - sage.combinat sage.modules + sage: A.one() is A.a_realization().one() # needs sage.modules True - sage: A._test_one() # optional - sage.combinat sage.modules + sage: A._test_one() # needs sage.modules """ return self.a_realization().one() @@ -510,12 +513,13 @@ def one_basis(self): EXAMPLES:: - sage: A = Monoids().example().algebra(ZZ) # optional - sage.modules - sage: A.one_basis() # optional - sage.modules + sage: # needs sage.modules + sage: A = Monoids().example().algebra(ZZ) + sage: A.one_basis() '' - sage: A.one() # optional - sage.modules + sage: A.one() B[''] - sage: A(3) # optional - sage.modules + sage: A(3) 3*B[''] """ return self.basis().keys().one() @@ -542,7 +546,7 @@ def algebra_generators(self): the free monoid generated by ('a', 'b', 'c', 'd') sage: M.monoid_generators() Finite family {'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd'} - sage: M.algebra(ZZ).algebra_generators() # optional - sage.modules + sage: M.algebra(ZZ).algebra_generators() # needs sage.modules Finite family {'a': B['a'], 'b': B['b'], 'c': B['c'], 'd': B['d']} sage: Z12 = Monoids().Finite().example(); Z12 @@ -555,18 +559,18 @@ def algebra_generators(self): has no attribute 'monoid_generators' sage: Z12.semigroup_generators() Family (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) - sage: Z12.algebra(QQ).algebra_generators() # optional - sage.modules + sage: Z12.algebra(QQ).algebra_generators() # needs sage.modules Family (B[0], B[1], B[2], B[3], B[4], B[5], B[6], B[7], B[8], B[9], B[10], B[11]) - sage: A10 = AlternatingGroup(10) # optional - sage.groups - sage: GroupAlgebras(QQ).example(A10).algebra_generators() # optional - sage.groups sage.modules + sage: A10 = AlternatingGroup(10) # needs sage.groups + sage: GroupAlgebras(QQ).example(A10).algebra_generators() # needs sage.groups sage.modules Family ((8,9,10), (1,2,3,4,5,6,7,8,9)) - sage: A = DihedralGroup(3).algebra(QQ); A # optional - sage.groups sage.modules + sage: A = DihedralGroup(3).algebra(QQ); A # needs sage.groups sage.modules Algebra of Dihedral group of order 6 as a permutation group over Rational Field - sage: A.algebra_generators() # optional - sage.groups sage.modules + sage: A.algebra_generators() # needs sage.groups sage.modules Family ((1,2,3), (1,3)) """ monoid = self.basis().keys() @@ -584,16 +588,16 @@ def is_central(self): EXAMPLES:: - sage: SG4 = SymmetricGroupAlgebra(ZZ,4) # optional - sage.groups sage.modules - sage: SG4(1).is_central() # optional - sage.groups sage.modules + sage: SG4 = SymmetricGroupAlgebra(ZZ,4) # needs sage.groups sage.modules + sage: SG4(1).is_central() # needs sage.groups sage.modules True - sage: SG4(Permutation([1,3,2,4])).is_central() # optional - sage.groups sage.modules + sage: SG4(Permutation([1,3,2,4])).is_central() # needs sage.groups sage.modules False - sage: A = GroupAlgebras(QQ).example(); A # optional - sage.groups sage.modules + sage: A = GroupAlgebras(QQ).example(); A # needs sage.groups sage.modules Algebra of Dihedral group of order 8 as a permutation group over Rational Field - sage: sum(A.basis()).is_central() # optional - sage.groups sage.modules + sage: sum(A.basis()).is_central() # needs sage.groups sage.modules True """ return all(i * self == self * i @@ -631,19 +635,20 @@ def monoid_generators(self): EXAMPLES:: - sage: M = Monoids.free([1, 2, 3]) # optional - sage.groups - sage: N = Monoids.free(['a', 'b']) # optional - sage.groups - sage: C = cartesian_product([M, N]) # optional - sage.groups - sage: C.monoid_generators() # optional - sage.groups + sage: # needs sage.groups + sage: M = Monoids.free([1, 2, 3]) + sage: N = Monoids.free(['a', 'b']) + sage: C = cartesian_product([M, N]) + sage: C.monoid_generators() Family ((F[1], 1), (F[2], 1), (F[3], 1), (1, F['a']), (1, F['b'])) An example with an infinitely generated group (a better output is needed):: - sage: N = Monoids.free(ZZ) # optional - sage.groups - sage: C = cartesian_product([M, N]) # optional - sage.groups - sage: C.monoid_generators() # optional - sage.groups + sage: N = Monoids.free(ZZ) # needs sage.combinat + sage: C = cartesian_product([M, N]) # needs sage.combinat sage.groups + sage: C.monoid_generators() # needs sage.combinat sage.groups Lazy family (gen(i))_{i in The Cartesian product of (...)} """ F = self.cartesian_factors() @@ -680,10 +685,11 @@ def multiplicative_order(self): EXAMPLES:: - sage: G1 = SymmetricGroup(3) # optional - sage.groups sage.modules - sage: G2 = SL(2, 3) # optional - sage.groups sage.modules - sage: G = cartesian_product([G1, G2]) # optional - sage.groups sage.modules - sage: G((G1.gen(0), G2.gen(1))).multiplicative_order() # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: G1 = SymmetricGroup(3) + sage: G2 = SL(2, 3) + sage: G = cartesian_product([G1, G2]) + sage: G((G1.gen(0), G2.gen(1))).multiplicative_order() 12 """ from sage.rings.infinity import Infinity @@ -700,10 +706,11 @@ def __invert__(self): EXAMPLES:: - sage: a1 = Permutation((4,2,1,3)) # optional - sage.groups sage.modules - sage: a2 = SL(2, 3)([2,1,1,1]) # optional - sage.groups sage.modules - sage: h = cartesian_product([a1, a2]) # optional - sage.groups sage.modules - sage: ~h # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: a1 = Permutation((4,2,1,3)) + sage: a2 = SL(2, 3)([2,1,1,1]) + sage: h = cartesian_product([a1, a2]) + sage: ~h ([2, 4, 1, 3], [1 2] [2 2]) """ diff --git a/src/sage/categories/morphism.pyx b/src/sage/categories/morphism.pyx index 514140b2333..571f90a7330 100644 --- a/src/sage/categories/morphism.pyx +++ b/src/sage/categories/morphism.pyx @@ -76,18 +76,18 @@ cdef class Morphism(Map): TESTS:: - sage: K = CyclotomicField(12) # optional - sage.rings.number_field - sage: L = CyclotomicField(132) # optional - sage.rings.number_field - sage: phi = L._internal_coerce_map_from(K); phi # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K = CyclotomicField(12) + sage: L = CyclotomicField(132) + sage: phi = L._internal_coerce_map_from(K); phi (map internal to coercion system -- copy before use) Generic morphism: From: Cyclotomic Field of order 12 and degree 4 To: Cyclotomic Field of order 132 and degree 40 - - sage: del K # optional - sage.rings.number_field + sage: del K sage: import gc sage: _ = gc.collect() - sage: phi # optional - sage.rings.number_field + sage: phi Defunct morphism """ D = self.domain() @@ -182,10 +182,11 @@ cdef class Morphism(Map): and left modules over (euclidean domains and infinite enumerated sets and metric spaces) - sage: K = CyclotomicField(12) # optional - sage.rings.number_field - sage: L = CyclotomicField(132) # optional - sage.rings.number_field - sage: phi = L._internal_coerce_map_from(K) # optional - sage.rings.number_field - sage: phi.category() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K = CyclotomicField(12) + sage: L = CyclotomicField(132) + sage: phi = L._internal_coerce_map_from(K) + sage: phi.category() Category of homsets of number fields """ # Should it be Category of elements of ...? @@ -202,10 +203,11 @@ cdef class Morphism(Map): sage: f.is_endomorphism() True - sage: K = CyclotomicField(12) # optional - sage.rings.number_field - sage: L = CyclotomicField(132) # optional - sage.rings.number_field - sage: phi = L._internal_coerce_map_from(K) # optional - sage.rings.number_field - sage: phi.is_endomorphism() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K = CyclotomicField(12) + sage: L = CyclotomicField(132) + sage: phi = L._internal_coerce_map_from(K) + sage: phi.is_endomorphism() False """ return self.parent().is_endomorphism_set() @@ -224,7 +226,7 @@ cdef class Morphism(Map): sage: f = R.hom([t]) sage: f.is_identity() True - sage: g = R.hom([t+1]) + sage: g = R.hom([t + 1]) sage: g.is_identity() False @@ -304,14 +306,15 @@ cdef class Morphism(Map): Let us declare a conversion from the symmetric group to `\ZZ` through the sign map:: - sage: S = SymmetricGroup(4) # optional - sage.groups - sage: phi = Hom(S, ZZ)(lambda x: ZZ(x.sign())) # optional - sage.groups - sage: x = S.an_element(); x # optional - sage.groups + sage: # needs sage.groups + sage: S = SymmetricGroup(4) + sage: phi = Hom(S, ZZ)(lambda x: ZZ(x.sign())) + sage: x = S.an_element(); x (2,3,4) - sage: phi(x) # optional - sage.groups + sage: phi(x) 1 - sage: phi.register_as_conversion() # optional - sage.groups - sage: ZZ(x) # optional - sage.groups + sage: phi.register_as_conversion() + sage: ZZ(x) 1 """ self._codomain.register_conversion(self) @@ -350,11 +353,12 @@ cdef class Morphism(Map): TESTS:: + sage: # needs sage.combinat sage: from sage.categories.morphism import SetMorphism - sage: E = End(Partitions(5)) # optional - sage.combinat - sage: f = E.identity() # optional - sage.combinat - sage: g = SetMorphism(E, lambda x: x) # optional - sage.combinat - sage: f == g # optional - sage.combinat + sage: E = End(Partitions(5)) + sage: f = E.identity() + sage: g = SetMorphism(E, lambda x: x) + sage: f == g Traceback (most recent call last): ... NotImplementedError: unable to compare morphisms of type <... 'sage.categories.morphism.IdentityMorphism'> @@ -362,16 +366,16 @@ cdef class Morphism(Map): We check that :trac:`28617` is fixed:: - sage: FF = GF(2^20) # optional - sage.libs.combinat - sage: f = FF.frobenius_endomorphism() # optional - sage.libs.combinat - sage: f == FF.frobenius_endomorphism() # optional - sage.libs.combinat + sage: FF = GF(2^20) # needs sage.rings.finite_rings + sage: f = FF.frobenius_endomorphism() # needs sage.rings.finite_rings + sage: f == FF.frobenius_endomorphism() # needs sage.rings.finite_rings True and that :trac:`29632` is fixed:: - sage: R. = QuadraticField(-1)[] # optional - sage.rings.number_field - sage: f = R.hom(R.gens(), R) # optional - sage.rings.number_field - sage: f.is_identity() # optional - sage.rings.number_field + sage: R. = QuadraticField(-1)[] # needs sage.rings.number_field + sage: f = R.hom(R.gens(), R) # needs sage.rings.number_field + sage: f.is_identity() # needs sage.rings.number_field True """ if self is other: @@ -507,17 +511,18 @@ cdef class IdentityMorphism(Morphism): EXAMPLES:: - sage: E = End(Partitions(5)) # optional - sage.combinat - sage: E.identity().is_identity() # optional - sage.combinat + sage: E = End(Partitions(5)) # needs sage.combinat + sage: E.identity().is_identity() # needs sage.combinat True Check that :trac:`15478` is fixed:: - sage: K. = GF(4) # optional - sage.rings.finite_rings - sage: phi = End(K)([z^2]) # optional - sage.rings.finite_rings - sage: R. = K[] # optional - sage.rings.finite_rings - sage: psi = End(R)(phi) # optional - sage.rings.finite_rings - sage: psi.is_identity() # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: K. = GF(4) + sage: phi = End(K)([z^2]) + sage: R. = K[] + sage: psi = End(R)(phi) + sage: psi.is_identity() False """ return True @@ -683,7 +688,7 @@ cdef class SetMorphism(Morphism): sage: f = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__) sage: g = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__) - sage: h = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Rings()), operator.__abs__) # todo: replace by the more correct Monoids + sage: h = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Rings()), operator.__abs__) # todo: replace by the more correct Monoids sage: i = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__neg__) sage: f._eq_c_impl(g) True @@ -709,7 +714,7 @@ cdef class SetMorphism(Morphism): sage: f = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__) sage: g = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__) - sage: h = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Rings()), operator.__abs__) # todo: replace by the more correct Monoids + sage: h = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Rings()), operator.__abs__) # todo: replace by the more correct Monoids sage: i = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__neg__) sage: f == f, f != f, f < f, f > f, f <= f, f >= f (True, False, False, False, True, True) diff --git a/src/sage/categories/number_fields.py b/src/sage/categories/number_fields.py index f3610cd8b7f..3c070bd65b2 100644 --- a/src/sage/categories/number_fields.py +++ b/src/sage/categories/number_fields.py @@ -42,16 +42,16 @@ class NumberFields(Category_singleton): course also in this category:: sage: x = PolynomialRing(RationalField(), 'x').gen() - sage: K = NumberField(x - 1, 'a'); K # optional - sage.rings.number_field + sage: K = NumberField(x - 1, 'a'); K # needs sage.rings.number_field Number Field in a with defining polynomial x - 1 - sage: K in C # optional - sage.rings.number_field + sage: K in C # needs sage.rings.number_field True Number fields all lie in this category, regardless of the name of the variable:: - sage: K = NumberField(x^2 + 1, 'a') # optional - sage.rings.number_field - sage: K in C # optional - sage.rings.number_field + sage: K = NumberField(x^2 + 1, 'a') # needs sage.rings.number_field + sage: K in C # needs sage.rings.number_field True TESTS:: @@ -75,11 +75,11 @@ def __contains__(self, x): EXAMPLES:: sage: x = polygen(QQ, 'x') - sage: NumberField(x^2 + 1, 'a') in NumberFields() # optional - sage.rings.number_field + sage: NumberField(x^2 + 1, 'a') in NumberFields() # needs sage.rings.number_field True - sage: QuadraticField(-97, 'theta') in NumberFields() # optional - sage.rings.number_field + sage: QuadraticField(-97, 'theta') in NumberFields() # needs sage.rings.number_field True - sage: CyclotomicField(97) in NumberFields() # optional - sage.rings.number_field + sage: CyclotomicField(97) in NumberFields() # needs sage.rings.number_field True Note that the rational numbers QQ are a number field:: @@ -105,10 +105,10 @@ def _call_(self, x): sage: C(QQ) Rational Field - sage: C(NumberField(x^2 + 1, 'a')) # optional - sage.rings.number_field + sage: C(NumberField(x^2 + 1, 'a')) # needs sage.rings.number_field Number Field in a with defining polynomial x^2 + 1 - sage: C(UnitGroup(NumberField(x^2 + 1, 'a'))) # indirect doctest # optional - sage.rings.number_field + sage: C(UnitGroup(NumberField(x^2 + 1, 'a'))) # indirect doctest # needs sage.rings.number_field Number Field in a with defining polynomial x^2 + 1 sage: C(ZZ) @@ -151,35 +151,35 @@ def zeta_function(self, prec=53, EXAMPLES:: - sage: K. = NumberField(ZZ['x'].0^2 + ZZ['x'].0 - 1) # optional - sage.rings.number_field - sage: Z = K.zeta_function(); Z # optional - sage.rings.number_field sage.symbolic + sage: K. = NumberField(ZZ['x'].0^2 + ZZ['x'].0 - 1) # needs sage.rings.number_field + sage: Z = K.zeta_function(); Z # needs sage.rings.number_field sage.symbolic PARI zeta function associated to Number Field in a with defining polynomial x^2 + x - 1 - sage: Z(-1) # optional - sage.rings.number_field sage.symbolic + sage: Z(-1) # needs sage.rings.number_field sage.symbolic 0.0333333333333333 sage: x = polygen(QQ, 'x') - sage: L. = NumberField([x^2 - 5, x^2 + 3, x^2 + 1]) # optional - sage.rings.number_field - sage: Z = L.zeta_function() # optional - sage.rings.number_field sage.symbolic - sage: Z(5) # optional - sage.rings.number_field sage.symbolic + sage: L. = NumberField([x^2 - 5, x^2 + 3, x^2 + 1]) # needs sage.rings.number_field + sage: Z = L.zeta_function() # needs sage.rings.number_field sage.symbolic + sage: Z(5) # needs sage.rings.number_field sage.symbolic 1.00199015670185 Using the algorithm "pari":: - sage: K. = NumberField(ZZ['x'].0^2 + ZZ['x'].0 - 1) # optional - sage.rings.number_field - sage: Z = K.zeta_function(algorithm="pari") # optional - sage.rings.number_field sage.symbolic - sage: Z(-1) # optional - sage.rings.number_field sage.symbolic + sage: K. = NumberField(ZZ['x'].0^2 + ZZ['x'].0 - 1) # needs sage.rings.number_field + sage: Z = K.zeta_function(algorithm="pari") # needs sage.rings.number_field sage.symbolic + sage: Z(-1) # needs sage.rings.number_field sage.symbolic 0.0333333333333333 sage: x = polygen(QQ, 'x') - sage: L. = NumberField([x^2 - 5, x^2 + 3, x^2 + 1]) # optional - sage.rings.number_field - sage: Z = L.zeta_function(algorithm="pari") # optional - sage.rings.number_field sage.symbolic - sage: Z(5) # optional - sage.rings.number_field sage.symbolic + sage: L. = NumberField([x^2 - 5, x^2 + 3, x^2 + 1]) # needs sage.rings.number_field + sage: Z = L.zeta_function(algorithm="pari") # needs sage.rings.number_field sage.symbolic + sage: Z(5) # needs sage.rings.number_field sage.symbolic 1.00199015670185 TESTS:: - sage: QQ.zeta_function() # optional - sage.symbolic + sage: QQ.zeta_function() # needs sage.symbolic PARI zeta function associated to Rational Field """ if algorithm == 'gp': @@ -224,8 +224,8 @@ def _test_absolute_disc(self, **options): EXAMPLES:: sage: x = polygen(ZZ, 'x') - sage: S = NumberField(x**3 - x - 1, 'a') # optional - sage.rings.number_field - sage: S._test_absolute_disc() # optional - sage.rings.number_field + sage: S = NumberField(x**3 - x - 1, 'a') # needs sage.rings.number_field + sage: S._test_absolute_disc() # needs sage.rings.number_field """ from sage.rings.integer import Integer tester = self._tester(**options) diff --git a/src/sage/categories/polyhedra.py b/src/sage/categories/polyhedra.py index 7bfb89bd2ae..256eb99498d 100644 --- a/src/sage/categories/polyhedra.py +++ b/src/sage/categories/polyhedra.py @@ -26,10 +26,11 @@ class PolyhedralSets(Category_over_base_ring): sage: TestSuite(PolyhedralSets(RDF)).run() - sage: P = Polyhedron() # optional - sage.geometry.polyhedron - sage: P.parent().category().element_class # optional - sage.geometry.polyhedron + sage: # needs sage.geometry.polyhedron + sage: P = Polyhedron() + sage: P.parent().category().element_class - sage: P.parent().category().element_class.mro() # optional - sage.geometry.polyhedron + sage: P.parent().category().element_class.mro() [, , , @@ -45,7 +46,7 @@ class PolyhedralSets(Category_over_base_ring): , , ] - sage: isinstance(P, P.parent().category().element_class) # optional - sage.geometry.polyhedron + sage: isinstance(P, P.parent().category().element_class) True """ @@ -53,7 +54,7 @@ def __init__(self, R): """ TESTS:: - sage: PolyhedralSets(AA) # optional - sage.rings.number_field + sage: PolyhedralSets(AA) # needs sage.rings.number_field Category of polyhedral sets over Algebraic Real Field """ Category_over_base_ring.__init__(self, R) diff --git a/src/sage/categories/poor_man_map.py b/src/sage/categories/poor_man_map.py index 6912c4878cf..b8d0bdb4de9 100644 --- a/src/sage/categories/poor_man_map.py +++ b/src/sage/categories/poor_man_map.py @@ -94,8 +94,8 @@ def _repr_(self): """ return ((self._name if self._name is not None else "A map") + - (" from %s"%(self._domain,) if self._domain is not None else "" ) + - (" to %s"%(self._codomain,) if self._codomain is not None else "" )) + (" from %s" % (self._domain,) if self._domain is not None else "" ) + + (" to %s" % (self._codomain,) if self._codomain is not None else "" )) def domain(self): """ @@ -209,12 +209,13 @@ def __mul__(self, other): But it is detected here:: sage: g = PoorManMap(factorial, domain=ZZ, codomain=ZZ) - sage: h = PoorManMap(sqrt, domain=RR, codomain=CC) - sage: g*h + sage: h = PoorManMap(sqrt, domain=RR, codomain=CC) # needs sage.rings.real_mpfr + sage: g*h # needs sage.rings.real_mpfr Traceback (most recent call last): ... - ValueError: the codomain Complex Field with 53 bits of precision does not coerce into the domain Integer Ring - sage: h*g + ValueError: the codomain Complex Field with 53 bits of precision + does not coerce into the domain Integer Ring + sage: h*g # needs sage.rings.real_mpfr A map from Integer Ring to Complex Field with 53 bits of precision """ self_domain = self.domain() @@ -266,8 +267,8 @@ def _sympy_(self): EXAMPLES:: sage: from sage.categories.poor_man_map import PoorManMap - sage: h = PoorManMap(sin, domain=RR, codomain=RR) # optional - sage.symbolic - sage: h._sympy_() # optional - sage.symbolic + sage: h = PoorManMap(sin, domain=RR, codomain=RR) + sage: h._sympy_() # needs sympy sage.symbolic sin """ from sympy import Lambda, sympify diff --git a/src/sage/categories/posets.py b/src/sage/categories/posets.py index 47408110da2..5cad3c70f73 100644 --- a/src/sage/categories/posets.py +++ b/src/sage/categories/posets.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.graphs, sage.combinat +# sage.doctest: needs sage.graphs, sage.combinat r""" Posets """ @@ -401,7 +401,7 @@ def order_ideal_toggle(self, I, v): sage: P = Poset({1: [2,3], 2: [4], 3: []}) sage: I = Set({1, 2}) - sage: I in P.order_ideals_lattice() + sage: I in P.order_ideals_lattice() # needs sage.modules True sage: P.order_ideal_toggle(I, 1) {1, 2} @@ -412,7 +412,7 @@ def order_ideal_toggle(self, I, v): sage: P.order_ideal_toggle(I, 4) {1, 2, 4} sage: P4 = Posets(4) - sage: all(all(all(P.order_ideal_toggle(P.order_ideal_toggle(I, i), i) == I + sage: all(all(all(P.order_ideal_toggle(P.order_ideal_toggle(I, i), i) == I # needs sage.modules ....: for i in range(4)) ....: for I in P.order_ideals_lattice(facade=True)) ....: for P in P4) diff --git a/src/sage/categories/primer.py b/src/sage/categories/primer.py index d57c38b77fa..14f8d5fbbe5 100644 --- a/src/sage/categories/primer.py +++ b/src/sage/categories/primer.py @@ -75,15 +75,15 @@ Similar objects should behave similarly:: - sage: Permutations(5).cardinality() # optional - sage.combinat + sage: Permutations(5).cardinality() 120 - sage: GL(2,2).cardinality() # optional - sage.groups + sage: GL(2,2).cardinality() # needs sage.modules 6 - sage: A = random_matrix(ZZ, 6, 3, x=7) # optional - sage.modules - sage: L = LatticePolytope(A.rows()) # optional - sage.geometry.polyhedron sage.modules - sage: L.npoints() # oops! # random # optional - sage.geometry.polyhedron sage.modules + sage: A = random_matrix(ZZ, 6, 3, x=7) # needs sage.modules + sage: L = LatticePolytope(A.rows()) # needs sage.geometry.polyhedron sage.modules + sage: L.npoints() # oops! # random # needs sage.geometry.polyhedron sage.modules 37 - How to ensure robustness? @@ -98,9 +98,10 @@ :: - sage: m = random_matrix(QQ, 4, algorithm='echelonizable', # optional - sage.modules + sage: # needs sage.modules + sage: m = random_matrix(QQ, 4, algorithm='echelonizable', ....: rank=3, upper_bound=60) - sage: m^8 == m*m*m*m*m*m*m*m == ((m^2)^2)^2 # optional - sage.modules + sage: m^8 == m*m*m*m*m*m*m*m == ((m^2)^2)^2 True We want to implement binary powering only once, as *generic* code @@ -126,12 +127,12 @@ and sure enough, binary powering is defined there:: - sage: m._pow_int.__module__ + sage: m._pow_int.__module__ # needs sage.modules 'sage.categories.monoids' That's our bookshelf! And it's used in many places:: - sage: GL(2, ZZ) in Monoids() # optional - sage.modules + sage: GL(2, ZZ) in Monoids() # needs sage.modules True sage: NN in Monoids() True @@ -169,20 +170,20 @@ Each set in Sage knows which bookshelf of generic algorithms it can use, that is to which category it belongs:: - sage: G = GL(2, ZZ) # optional - sage.modules - sage: G.category() # optional - sage.modules + sage: G = GL(2, ZZ) # needs sage.modules + sage: G.category() # needs sage.modules Category of infinite groups In fact a group is a semigroup, and Sage knows about this:: sage: Groups().is_subcategory(Semigroups()) True - sage: G in Semigroups() # optional - sage.modules + sage: G in Semigroups() # needs sage.modules True Altogether, our group gets algorithms from a bunch of bookshelves:: - sage: G.categories() # optional - sage.modules + sage: G.categories() # needs sage.modules [Category of infinite groups, Category of groups, Category of monoids, ..., Category of magmas, @@ -190,19 +191,19 @@ Those can be viewed graphically:: - sage: g = Groups().category_graph() # optional - sage.modules sage.graphs - sage: g.set_latex_options(format="dot2tex") # optional - sage.modules sage.graphs - sage: view(g) # not tested # optional - sage.modules sage.graphs sage.plot + sage: g = Groups().category_graph() # needs sage.graphs + sage: g.set_latex_options(format="dot2tex") # needs sage.graphs sage.modules + sage: view(g) # not tested # needs sage.graphs sage.modules sage.plot In case ``dot2tex`` is not available, you can use instead:: - sage: g.show(vertex_shape=None, figsize=20) # optional - sage.modules sage.graphs sage.plot + sage: g.show(vertex_shape=None, figsize=20) # needs sage.graphs sage.modules sage.plot Here is an overview of all categories in Sage:: - sage: g = sage.categories.category.category_graph() # optional - sage.modules sage.graphs - sage: g.set_latex_options(format="dot2tex") # optional - sage.modules sage.graphs - sage: view(g) # not tested # optional - sage.modules sage.graphs sage.plot + sage: g = sage.categories.category.category_graph() # needs sage.graphs sage.modules + sage: g.set_latex_options(format="dot2tex") # needs sage.graphs sage.modules + sage: view(g) # not tested # needs sage.graphs sage.modules sage.plot Wrap-up: generic algorithms in Sage are organized in a hierarchy of bookshelves modelled upon the usual hierarchy of categories provided @@ -371,9 +372,9 @@ Category of sets with partial maps, Category of objects] - sage: g = EuclideanDomains().category_graph() # optional - sage.graphs - sage: g.set_latex_options(format="dot2tex") # optional - sage.graphs - sage: view(g) # not tested # optional - sage.graphs sage.plot + sage: g = EuclideanDomains().category_graph() # needs sage.graphs + sage: g.set_latex_options(format="dot2tex") # needs sage.graphs sage.plot + sage: view(g) # not tested # needs sage.graphs sage.plot A bit of help from computer science =================================== @@ -407,24 +408,27 @@ class implements: sage: i.factor() 2^2 * 3 - sage: x = var('x') # optional - sage.symbolic - sage: p = 6*x^2 + 12*x + 6 # optional - sage.symbolic - sage: type(p) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: x = var('x') + sage: p = 6*x^2 + 12*x + 6 + sage: type(p) - sage: p.factor() # optional - sage.symbolic + sage: p.factor() 6*(x + 1)^2 + sage: # needs sage.symbolic sage: R. = PolynomialRing(QQ, sparse=True) - sage: pQ = R(p) # optional - sage.symbolic - sage: type(pQ) # optional - sage.symbolic + sage: pQ = R(p) + sage: type(pQ) - sage: pQ.factor() # optional - sage.symbolic + sage: pQ.factor() (6) * (x + 1)^2 - sage: pZ = ZZ['x'](p) # optional - sage.symbolic - sage: type(pZ) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: pZ = ZZ['x'](p) + sage: type(pZ) - sage: pZ.factor() # optional - sage.symbolic + sage: pZ.factor() 2 * 3 * (x + 1)^2 Factoring integers, expressions, or polynomials are distinct tasks, @@ -444,9 +448,9 @@ class implements: sage: i._pow_.__module__ # not tested (Issue #24275) 'sage.categories.semigroups' - sage: pQ._mul_.__module__ # optional - sage.symbolic + sage: pQ._mul_.__module__ # needs sage.symbolic 'sage.rings.polynomial.polynomial_element_generic' - sage: pQ._pow_.__module__ # not tested (Issue #24275) # optional - sage.symbolic + sage: pQ._pow_.__module__ # not tested (Issue #24275) # needs sage.symbolic 'sage.categories.semigroups' We see that integers and polynomials have each their own @@ -467,9 +471,9 @@ class implements: hierarchy of categories (bookshelves). Here is for example a piece of the hierarchy of classes for an element of a group of permutations:: - sage: P = Permutations(4) # optional - sage.combinat - sage: m = P.an_element() # optional - sage.combinat - sage: for cls in m.__class__.mro(): print(cls) # optional - sage.combinat + sage: P = Permutations(4) + sage: m = P.an_element() + sage: for cls in m.__class__.mro(): print(cls) @@ -487,9 +491,9 @@ class implements: The full hierarchy is best viewed graphically:: - sage: g = class_graph(m.__class__) # optional - sage.combinat sage.graphs - sage: g.set_latex_options(format="dot2tex") # optional - sage.combinat sage.graphs - sage: view(g) # not tested # optional - sage.combinat sage.graphs sage.plot + sage: g = class_graph(m.__class__) # needs sage.combinat sage.graphs + sage: g.set_latex_options(format="dot2tex") # needs sage.combinat sage.graphs + sage: view(g) # not tested # needs sage.combinat sage.graphs sage.plot Parallel hierarchy of classes for parents ----------------------------------------- @@ -523,13 +527,13 @@ class implements: modelled by instances of some (hierarchy of) classes. For example, our group `G` is an instance of the following class:: - sage: G = GL(2, ZZ) # optional - sage.modules - sage: type(G) # optional - sage.modules + sage: G = GL(2, ZZ) # needs sage.modules + sage: type(G) # needs sage.libs.gap sage.modules Here is a piece of the hierarchy of classes above it:: - sage: for cls in G.__class__.mro(): print(cls) # optional - sage.modules + sage: for cls in G.__class__.mro(): print(cls) # needs sage.libs.gap sage.modules ... @@ -541,10 +545,11 @@ class implements: categories and parallel to that we had seen for the elements. This is best viewed graphically:: - sage: g = class_graph(m.__class__) # optional - sage.modules sage.graphs - sage: g.relabel(lambda x: x.replace("_",r"\_")) # optional - sage.modules sage.graphs - sage: g.set_latex_options(format="dot2tex") # optional - sage.modules sage.graphs - sage: view(g) # not tested # optional - sage.modules sage.graphs sage.plot + sage: # needs sage.graphs sage.modules + sage: g = class_graph(m.__class__) + sage: g.relabel(lambda x: x.replace("_",r"\_")) + sage: g.set_latex_options(format="dot2tex") + sage: view(g) # not tested # needs sage.plot .. NOTE:: @@ -725,7 +730,7 @@ class SubcategoryMethods: Note that categories themselves are naturally modelled by instances because they can have operations of their own. An important one is:: - sage: Groups().example() # optional - sage.modules + sage: Groups().example() # needs sage.modules General Linear Group of degree 4 over Rational Field which gives an example of object of the category. Besides illustrating @@ -1018,17 +1023,17 @@ class SubcategoryMethods: example, permutation groups are by default in the category of finite permutation groups (no surprise):: - sage: P = PermutationGroup([[(1,2,3)]]); P # optional - sage.combinat + sage: P = PermutationGroup([[(1,2,3)]]); P # needs sage.combinat sage.groups Permutation Group with generators [(1,2,3)] - sage: P.category() # optional - sage.combinat + sage: P.category() # needs sage.combinat Category of finite enumerated permutation groups In this case, the group is commutative, so we can specify this:: - sage: P = PermutationGroup([[(1,2,3)]], # optional - sage.combinat + sage: P = PermutationGroup([[(1,2,3)]], # needs sage.combinat sage.groups ....: category=PermutationGroups().Finite().Commutative()); P Permutation Group with generators [(1,2,3)] - sage: P.category() # optional - sage.combinat + sage: P.category() # needs sage.combinat Category of finite enumerated commutative permutation groups This feature can even be used, typically in experimental code, to add @@ -1043,18 +1048,19 @@ class SubcategoryMethods: ....: class ElementMethods: ....: def bar(self): print("bar") - sage: P = PermutationGroup([[(1,2,3)]], category=Foos()) # optional - sage.combinat - sage: P.foo() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = PermutationGroup([[(1,2,3)]], category=Foos()) # needs sage.groups + sage: P.foo() foo - sage: p = P.an_element() # optional - sage.combinat - sage: p.bar() # optional - sage.combinat + sage: p = P.an_element() + sage: p.bar() bar In the long run, it would be thinkable to use this idiom to implement forgetful functors; for example the above group could be constructed as a plain set with:: - sage: P = PermutationGroup([[(1,2,3)]], category=Sets()) # todo: not implemented # optional - sage.combinat + sage: P = PermutationGroup([[(1,2,3)]], category=Sets()) # not implemented, needs sage.combinat At this stage though, this is still to be explored for robustness and practicality. For now, most parents that accept a category argument @@ -1102,9 +1108,9 @@ class SubcategoryMethods: Let for example `A` and `B` be two parents, and let us construct the Cartesian product `A \times B \times B`:: - sage: A = AlgebrasWithBasis(QQ).example(); A.rename("A") # optional - sage.combinat sage.modules - sage: B = HopfAlgebrasWithBasis(QQ).example(); B.rename("B") # optional - sage.combinat sage.modules - sage: C = cartesian_product([A, B, B]); C # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example(); A.rename("A") # needs sage.combinat sage.modules + sage: B = HopfAlgebrasWithBasis(QQ).example(); B.rename("B") # needs sage.combinat sage.modules + sage: C = cartesian_product([A, B, B]); C # needs sage.combinat sage.modules A (+) B (+) B In which category should this new parent be? Since `A` and `B` are @@ -1113,14 +1119,14 @@ class SubcategoryMethods: are monoids, `A \times B \times B` is naturally endowed with a monoid structure for pointwise multiplication:: - sage: C in Monoids() # optional - sage.combinat sage.modules + sage: C in Monoids() # needs sage.combinat sage.modules True the unit being the Cartesian product of the units of the operands:: - sage: C.one() # optional - sage.combinat sage.modules + sage: C.one() # needs sage.combinat sage.modules B[(0, word: )] + B[(1, ())] + B[(2, ())] - sage: cartesian_product([A.one(), B.one(), B.one()]) # optional - sage.combinat sage.modules + sage: cartesian_product([A.one(), B.one(), B.one()]) # needs sage.combinat sage.modules B[(0, word: )] + B[(1, ())] + B[(2, ())] The pointwise product can be implemented generically for all magmas @@ -1128,7 +1134,7 @@ class SubcategoryMethods: constructed as Cartesian products. It's thus implemented in the :class:`Magmas` category:: - sage: C.product.__module__ # optional - sage.combinat sage.modules + sage: C.product.__module__ # needs sage.combinat sage.modules 'sage.categories.magmas' More specifically, keeping on using nested classes to structure the @@ -1160,7 +1166,7 @@ class naming and introspection. Sage currently works around the Let us now look at the categories of ``C``:: - sage: C.categories() # optional - sage.combinat sage.modules + sage: C.categories() # needs sage.combinat sage.modules [Category of finite dimensional Cartesian products of algebras with basis over Rational Field, ... Category of Cartesian products of algebras over Rational Field, ... Category of Cartesian products of semigroups, Category of semigroups, ... @@ -1392,9 +1398,9 @@ class naming and introspection. Sage currently works around the or for more advanced categories:: - sage: g = HopfAlgebras(QQ).WithBasis().Graded().Connected().category_graph() # optional - sage.graphs - sage: g.set_latex_options(format="dot2tex") # optional - sage.graphs - sage: view(g) # not tested # optional - sage.graphs sage.plot + sage: g = HopfAlgebras(QQ).WithBasis().Graded().Connected().category_graph() # needs sage.graphs + sage: g.set_latex_options(format="dot2tex") # needs sage.graphs + sage: view(g) # not tested # needs sage.graphs sage.plot Difference between axioms and regressive covariant functorial constructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/sage/categories/principal_ideal_domains.py b/src/sage/categories/principal_ideal_domains.py index fa8b2632cc1..7d9ee8c1e32 100644 --- a/src/sage/categories/principal_ideal_domains.py +++ b/src/sage/categories/principal_ideal_domains.py @@ -70,22 +70,23 @@ def _test_gcd_vs_xgcd(self, **options): sage: ZZ._test_gcd_vs_xgcd() sage: QQ._test_gcd_vs_xgcd() sage: QQ['x']._test_gcd_vs_xgcd() - sage: QQbar['x']._test_gcd_vs_xgcd() # optional - sage.rings.number_field + sage: QQbar['x']._test_gcd_vs_xgcd() # needs sage.rings.number_field sage: RR._test_gcd_vs_xgcd() sage: RR['x']._test_gcd_vs_xgcd() A slightly more involved example of polynomial ring with a non UFD base ring:: - sage: K = QuadraticField(5) # optional - sage.rings.number_field - sage: O = K.maximal_order() # optional - sage.rings.number_field - sage: O in UniqueFactorizationDomains() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K = QuadraticField(5) + sage: O = K.maximal_order() + sage: O in UniqueFactorizationDomains() False - sage: R = PolynomialRing(O, 'x') # optional - sage.rings.number_field - sage: F = R.fraction_field() # optional - sage.rings.number_field - sage: F in PrincipalIdealDomains() # optional - sage.rings.number_field + sage: R = PolynomialRing(O, 'x') + sage: F = R.fraction_field() + sage: F in PrincipalIdealDomains() True - sage: F._test_gcd_vs_xgcd() # optional - sage.rings.number_field + sage: F._test_gcd_vs_xgcd() """ tester = self._tester(**options) elts = list(tester.some_elements()) @@ -109,14 +110,14 @@ def _test_gcd_vs_xgcd(self, **options): tester.assertTrue(has_gcd, "The ring {} provides a xgcd but no gcd".format(self)) for (x,y),gcd,xgcd in zip(pairs,gcds,xgcds): - tester.assertTrue(gcd.parent()==self, + tester.assertTrue(gcd.parent() == self, "The parent of the gcd is {} for element of {}".format( gcd.parent(), self)) - tester.assertTrue(xgcd[0].parent()==self and - xgcd[1].parent()==self and xgcd[2].parent()==self, + tester.assertTrue(xgcd[0].parent() == self and + xgcd[1].parent() == self and xgcd[2].parent() == self, "The parent of output in xgcd is different from " "the parent of input for elements in {}".format(self)) - tester.assertTrue(gcd==xgcd[0], + tester.assertTrue(gcd == xgcd[0], "The methods gcd and xgcd disagree on {}:\n" " gcd({},{}) = {}\n" " xgcd({},{}) = {}\n".format(self,x,y,gcd,x,y,xgcd)) diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 7bb97cd83fd..3b7b8238d52 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -107,12 +107,12 @@ class ConstructionFunctor(Functor): sage: P. = ZZ[] sage: F = P.construction()[0]; F MPoly[x,y] - sage: A. = GF(5)[] # optional - sage.rings.finite_rings - sage: f = A.hom([a + b, a - b], A) # optional - sage.rings.finite_rings - sage: F(A) # optional - sage.rings.finite_rings + sage: A. = GF(5)[] + sage: f = A.hom([a + b, a - b], A) + sage: F(A) Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 - sage: F(f) # optional - sage.rings.finite_rings + sage: F(f) Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 Defn: Induced from base ring by @@ -120,7 +120,7 @@ class ConstructionFunctor(Functor): over Finite Field of size 5 Defn: a |--> a + b b |--> a - b - sage: F(f)(F(A)(x)*a) # optional - sage.rings.finite_rings + sage: F(f)(F(A)(x)*a) (a + b)*x """ @@ -441,7 +441,7 @@ class CompositeConstructionFunctor(ConstructionFunctor): True sage: F == CompositeConstructionFunctor(*F.all) True - sage: F(GF(2)['t']) # optional - sage.rings.finite_rings + sage: F(GF(2)['t']) # needs sage.libs.ntl Univariate Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Univariate Polynomial Ring in t @@ -812,32 +812,32 @@ class PolynomialFunctor(ConstructionFunctor): EXAMPLES:: sage: P = ZZ['t'].construction()[0] - sage: P(GF(3)) # optional - sage.rings.finite_rings + sage: P(GF(3)) Univariate Polynomial Ring in t over Finite Field of size 3 - sage: P == loads(dumps(P)) # optional - sage.rings.finite_rings + sage: P == loads(dumps(P)) True - sage: R. = GF(5)[] # optional - sage.rings.finite_rings - sage: f = R.hom([x + 2*y, 3*x - y], R) # optional - sage.rings.finite_rings - sage: P(f)((x+y) * P(R).0) # optional - sage.rings.finite_rings + sage: R. = GF(5)[] + sage: f = R.hom([x + 2*y, 3*x - y], R) + sage: P(f)((x+y) * P(R).0) (-x + y)*t By :trac:`9944`, the construction functor distinguishes sparse and dense polynomial rings. Before, the following example failed:: - sage: R. = PolynomialRing(GF(5), sparse=True) # optional - sage.rings.finite_rings - sage: F, B = R.construction() # optional - sage.rings.finite_rings - sage: F(B) is R # optional - sage.rings.finite_rings + sage: R. = PolynomialRing(GF(5), sparse=True) + sage: F, B = R.construction() + sage: F(B) is R True sage: S. = PolynomialRing(ZZ) - sage: R.has_coerce_map_from(S) # optional - sage.rings.finite_rings + sage: R.has_coerce_map_from(S) False - sage: S.has_coerce_map_from(R) # optional - sage.rings.finite_rings + sage: S.has_coerce_map_from(R) False - sage: S.0 + R.0 # optional - sage.rings.finite_rings + sage: S.0 + R.0 2*x - sage: (S.0 + R.0).parent() # optional - sage.rings.finite_rings + sage: (S.0 + R.0).parent() Univariate Polynomial Ring in x over Finite Field of size 5 - sage: (S.0 + R.0).parent().is_sparse() # optional - sage.rings.finite_rings + sage: (S.0 + R.0).parent().is_sparse() False """ @@ -849,7 +849,7 @@ def __init__(self, var, multi_variate=False, sparse=False, implementation=None): sage: from sage.categories.pushout import PolynomialFunctor sage: P = PolynomialFunctor('x') - sage: P(GF(3)) # optional - sage.rings.finite_rings + sage: P(GF(3)) Univariate Polynomial Ring in x over Finite Field of size 3 There is an optional parameter ``multi_variate``, but @@ -876,7 +876,7 @@ def _apply_functor(self, R): TESTS:: sage: P = ZZ['x'].construction()[0] - sage: P(GF(3)) # indirect doctest # optional - sage.rings.finite_rings + sage: P(GF(3)) # indirect doctest Univariate Polynomial Ring in x over Finite Field of size 3 """ @@ -893,7 +893,7 @@ def _apply_functor_to_morphism(self, f): TESTS:: sage: P = ZZ['x'].construction()[0] - sage: P(ZZ.hom(GF(3))) # indirect doctest # optional - sage.rings.finite_rings + sage: P(ZZ.hom(GF(3))) # indirect doctest Ring morphism: From: Univariate Polynomial Ring in x over Integer Ring To: Univariate Polynomial Ring in x over Finite Field of size 3 @@ -1003,19 +1003,19 @@ class MultiPolynomialFunctor(ConstructionFunctor): sage: P. = ZZ[] sage: F = P.construction()[0]; F MPoly[x,y] - sage: A. = GF(5)[] # optional - sage.rings.finite_rings - sage: F(A) # optional - sage.rings.finite_rings + sage: A. = GF(5)[] + sage: F(A) Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 - sage: f = A.hom([a+b, a-b], A) # optional - sage.rings.finite_rings - sage: F(f) # optional - sage.rings.finite_rings + sage: f = A.hom([a+b, a-b], A) + sage: F(f) Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 Defn: Induced from base ring by Ring endomorphism of Multivariate Polynomial Ring in a, b over Finite Field of size 5 Defn: a |--> a + b b |--> a - b - sage: F(f)(F(A)(x)*a) # optional - sage.rings.finite_rings + sage: F(f)(F(A)(x)*a) (a + b)*x """ @@ -1031,7 +1031,7 @@ def __init__(self, vars, term_order): MPoly[x,y] sage: F(ZZ) Multivariate Polynomial Ring in x, y over Integer Ring - sage: F(CC) + sage: F(CC) # needs sage.rings.real_mpfr Multivariate Polynomial Ring in x, y over Complex Field with 53 bits of precision """ Functor.__init__(self, Rings(), Rings()) @@ -1051,7 +1051,7 @@ def _apply_functor(self, R): sage: F(ZZ) # indirect doctest Multivariate Polynomial Ring in x, y, z over Integer Ring - sage: F(RR) # indirect doctest + sage: F(RR) # indirect doctest # needs sage.rings.real_mpfr Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -1170,8 +1170,8 @@ def expand(self): 'Multivariate Polynomial Ring in x, y, z over Integer Ring' and 'Multivariate Polynomial Ring in y, s over Rational Field' sage: R = PolynomialRing(ZZ, 'x', 50) - sage: S = PolynomialRing(GF(5), 'x', 20) # optional - sage.rings.finite_rings - sage: R.gen(0) + S.gen(0) # optional - sage.rings.finite_rings + sage: S = PolynomialRing(GF(5), 'x', 20) + sage: R.gen(0) + S.gen(0) 2*x0 """ if len(self.vars) <= 1: @@ -1574,17 +1574,18 @@ class MatrixFunctor(ConstructionFunctor): EXAMPLES:: - sage: MS = MatrixSpace(ZZ, 2, 3) # optional - sage.modules - sage: F = MS.construction()[0]; F # optional - sage.modules + sage: # needs sage.modules + sage: MS = MatrixSpace(ZZ, 2, 3) + sage: F = MS.construction()[0]; F MatrixFunctor - sage: MS = MatrixSpace(ZZ, 2) # optional - sage.modules - sage: F = MS.construction()[0]; F # optional - sage.modules + sage: MS = MatrixSpace(ZZ, 2) + sage: F = MS.construction()[0]; F MatrixFunctor - sage: P. = QQ[] # optional - sage.modules - sage: R = F(P); R # optional - sage.modules + sage: P. = QQ[] + sage: R = F(P); R Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field - sage: f = P.hom([x+y, x-y], P); F(f) # optional - sage.modules + sage: f = P.hom([x+y, x-y], P); F(f) Ring endomorphism of Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field @@ -1593,8 +1594,8 @@ class MatrixFunctor(ConstructionFunctor): of Multivariate Polynomial Ring in x, y over Rational Field Defn: x |--> x + y y |--> x - y - sage: M = R([x, y, x*y, x + y]) # optional - sage.modules - sage: F(f)(M) # optional - sage.modules + sage: M = R([x, y, x*y, x + y]) + sage: F(f)(M) [ x + y x - y] [x^2 - y^2 2*x] @@ -1605,22 +1606,23 @@ def __init__(self, nrows, ncols, is_sparse=False): """ TESTS:: + sage: # needs sage.modules sage: from sage.categories.pushout import MatrixFunctor - sage: F = MatrixFunctor(2, 3) # optional - sage.modules - sage: F == MatrixSpace(ZZ, 2, 3).construction()[0] # optional - sage.modules + sage: F = MatrixFunctor(2, 3) + sage: F == MatrixSpace(ZZ, 2, 3).construction()[0] True - sage: F.codomain() # optional - sage.modules + sage: F.codomain() Category of commutative additive groups - sage: R = MatrixSpace(ZZ, 2, 2).construction()[0] # optional - sage.modules - sage: R.codomain() # optional - sage.modules + sage: R = MatrixSpace(ZZ, 2, 2).construction()[0] + sage: R.codomain() Category of rings - sage: F(ZZ) # optional - sage.modules + sage: F(ZZ) Full MatrixSpace of 2 by 3 dense matrices over Integer Ring - sage: F(ZZ) in F.codomain() # optional - sage.modules + sage: F(ZZ) in F.codomain() True - sage: R(GF(2)) # optional - sage.rings.finite_rings sage.modules + sage: R(GF(2)) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 - sage: R(GF(2)) in R.codomain() # optional - sage.rings.finite_rings sage.modules + sage: R(GF(2)) in R.codomain() True """ if nrows == ncols: @@ -1640,10 +1642,10 @@ def _apply_functor(self, R): The following is a test against a bug discussed at :trac:`8800`:: - sage: F = MatrixSpace(ZZ, 2, 3).construction()[0] # optional - sage.modules - sage: F(RR) # indirect doctest # optional - sage.modules + sage: F = MatrixSpace(ZZ, 2, 3).construction()[0] # needs sage.modules + sage: F(RR) # indirect doctest # needs sage.modules Full MatrixSpace of 2 by 3 dense matrices over Real Field with 53 bits of precision - sage: F(RR) in F.codomain() # optional - sage.modules + sage: F(RR) in F.codomain() # needs sage.modules True """ @@ -1654,10 +1656,10 @@ def __eq__(self, other): """ TESTS:: - sage: F = MatrixSpace(ZZ, 2, 3).construction()[0] # optional - sage.modules - sage: F == loads(dumps(F)) # optional - sage.modules + sage: F = MatrixSpace(ZZ, 2, 3).construction()[0] # needs sage.modules + sage: F == loads(dumps(F)) # needs sage.modules True - sage: F == MatrixSpace(ZZ, 2, 2).construction()[0] # optional - sage.modules + sage: F == MatrixSpace(ZZ, 2, 2).construction()[0] # needs sage.modules False """ if isinstance(other, MatrixFunctor): @@ -1670,10 +1672,10 @@ def __ne__(self, other): EXAMPLES:: - sage: F = MatrixSpace(ZZ, 2, 3).construction()[0] # optional - sage.modules - sage: F != loads(dumps(F)) # optional - sage.modules + sage: F = MatrixSpace(ZZ, 2, 3).construction()[0] # needs sage.modules + sage: F != loads(dumps(F)) # needs sage.modules False - sage: F != MatrixSpace(ZZ, 2, 2).construction()[0] # optional - sage.modules + sage: F != MatrixSpace(ZZ, 2, 2).construction()[0] # needs sage.modules True """ return not (self == other) @@ -1688,20 +1690,21 @@ def merge(self, other): EXAMPLES:: - sage: F1 = MatrixSpace(ZZ, 2, 2).construction()[0] # optional - sage.modules - sage: F2 = MatrixSpace(ZZ, 2, 3).construction()[0] # optional - sage.modules - sage: F3 = MatrixSpace(ZZ, 2, 2, sparse=True).construction()[0] # optional - sage.modules - sage: F1.merge(F2) # optional - sage.modules - sage: F1.merge(F3) # optional - sage.modules + sage: # needs sage.modules + sage: F1 = MatrixSpace(ZZ, 2, 2).construction()[0] + sage: F2 = MatrixSpace(ZZ, 2, 3).construction()[0] + sage: F3 = MatrixSpace(ZZ, 2, 2, sparse=True).construction()[0] + sage: F1.merge(F2) + sage: F1.merge(F3) MatrixFunctor - sage: F13 = F1.merge(F3) # optional - sage.modules - sage: F13.is_sparse # optional - sage.modules + sage: F13 = F1.merge(F3) + sage: F13.is_sparse False - sage: F1.is_sparse # optional - sage.modules + sage: F1.is_sparse False - sage: F3.is_sparse # optional - sage.modules + sage: F3.is_sparse True - sage: F3.merge(F3).is_sparse # optional - sage.modules + sage: F3.merge(F3).is_sparse True """ @@ -1760,9 +1763,9 @@ def __init__(self, var, multi_variate=False): sage: F1(F2(QQ)) Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field - sage: F2(F1(QQ)) # optional - sage.modules + sage: F2(F1(QQ)) # needs sage.modules Multivariate Laurent Polynomial Ring in t, s over Rational Field - sage: F3(QQ) # optional - sage.modules + sage: F3(QQ) # needs sage.modules Multivariate Laurent Polynomial Ring in s, t over Rational Field """ @@ -1785,9 +1788,9 @@ def _apply_functor(self, R): sage: F1(F2(QQ)) # indirect doctest Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field - sage: F2(F1(QQ)) # optional - sage.modules + sage: F2(F1(QQ)) # needs sage.modules Multivariate Laurent Polynomial Ring in t, s over Rational Field - sage: F3(QQ) # optional - sage.modules + sage: F3(QQ) # needs sage.modules Multivariate Laurent Polynomial Ring in s, t over Rational Field """ @@ -1855,9 +1858,9 @@ def merge(self, other): sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True) sage: F1.merge(F2) LaurentPolynomialFunctor - sage: F1.merge(F2)(LaurentPolynomialRing(GF(2), 'a')) # optional - sage.rings.finite_rings + sage: F1.merge(F2)(LaurentPolynomialRing(GF(2), 'a')) # needs sage.modules Multivariate Laurent Polynomial Ring in a, t over Finite Field of size 2 - sage: F1.merge(F1)(LaurentPolynomialRing(GF(2), 'a')) # optional - sage.rings.finite_rings + sage: F1.merge(F1)(LaurentPolynomialRing(GF(2), 'a')) # needs sage.modules Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in a over Finite Field of size 2 @@ -1874,12 +1877,14 @@ class VectorFunctor(ConstructionFunctor): EXAMPLES:: - sage: F = (ZZ^3).construction()[0] # optional - sage.modules - sage: F # optional - sage.modules + sage: # needs sage.modules + sage: F = (ZZ^3).construction()[0] + sage: F VectorFunctor - sage: F(GF(2)['t']) # optional - sage.rings.finite_rings sage.modules + sage: F(GF(2)['t']) # needs sage.libs.ntl Ambient free module of rank 3 - over the principal ideal domain Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) + over the principal ideal domain Univariate Polynomial Ring in t + over Finite Field of size 2 (using GF2X) """ rank = 10 # ranking of functor, not rank of module. # This coincides with the rank of the matrix construction functor, but this is OK since they cannot both be applied in any order @@ -1898,22 +1903,23 @@ def __init__(self, n=None, is_sparse=False, inner_product_matrix=None, *, TESTS:: + sage: # needs sage.modules sage: from sage.categories.pushout import VectorFunctor - sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) # optional - sage.modules - sage: F1.domain() # optional - sage.modules + sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) + sage: F1.domain() Category of commutative rings - sage: F1.codomain() # optional - sage.modules + sage: F1.codomain() Category of commutative additive groups - sage: M1 = F1(ZZ) # optional - sage.modules - sage: M1.is_sparse() # optional - sage.modules + sage: M1 = F1(ZZ) + sage: M1.is_sparse() False - sage: v = M1([3, 2, 1]) # optional - sage.modules - sage: v * Matrix(3, 3, range(9)) * v.column() # optional - sage.modules + sage: v = M1([3, 2, 1]) + sage: v * Matrix(3, 3, range(9)) * v.column() (96) - sage: v.inner_product(v) # optional - sage.modules + sage: v.inner_product(v) 96 sage: F2 = VectorFunctor(3, is_sparse=True) - sage: M2 = F2(QQ); M2; M2.is_sparse() # optional - sage.modules + sage: M2 = F2(QQ); M2; M2.is_sparse() Sparse vector space of dimension 3 over Rational Field True @@ -1940,29 +1946,31 @@ def _apply_functor(self, R): TESTS:: + sage: # needs sage.modules sage: from sage.categories.pushout import VectorFunctor, pushout - sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) # optional - sage.modules - sage: M1 = F1(ZZ) # indirect doctest # optional - sage.modules - sage: M1.is_sparse() # optional - sage.modules + sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) + sage: M1 = F1(ZZ) # indirect doctest + sage: M1.is_sparse() False - sage: v = M1([3, 2, 1]) # optional - sage.modules - sage: v * Matrix(3, 3, range(9)) * v.column() # optional - sage.modules + sage: v = M1([3, 2, 1]) + sage: v * Matrix(3, 3, range(9)) * v.column() (96) - sage: v.inner_product(v) # optional - sage.modules + sage: v.inner_product(v) 96 - sage: F2 = VectorFunctor(3, is_sparse=True) # optional - sage.modules - sage: M2 = F2(QQ); M2; M2.is_sparse() # optional - sage.modules + sage: F2 = VectorFunctor(3, is_sparse=True) + sage: M2 = F2(QQ); M2; M2.is_sparse() Sparse vector space of dimension 3 over Rational Field True - sage: v = M2([3, 2, 1]) # optional - sage.modules - sage: v.inner_product(v) # optional - sage.modules + sage: v = M2([3, 2, 1]) + sage: v.inner_product(v) 14 - sage: M = FreeModule(ZZ, 4, with_basis=None, name='M') # optional - sage.modules - sage: latex(M) # optional - sage.modules + sage: # needs sage.modules + sage: M = FreeModule(ZZ, 4, with_basis=None, name='M') + sage: latex(M) M - sage: M_QQ = pushout(M, QQ) # optional - sage.modules - sage: latex(M_QQ) # optional - sage.modules + sage: M_QQ = pushout(M, QQ) + sage: latex(M_QQ) M \otimes \Bold{Q} """ @@ -1990,10 +1998,10 @@ def _apply_functor_to_morphism(self, f): TESTS:: - sage: F = (ZZ^3).construction()[0] # optional - sage.modules + sage: F = (ZZ^3).construction()[0] # needs sage.modules sage: P. = ZZ[] sage: f = P.hom([x + 2*y, 3*x - y], P) - sage: F(f) # indirect doctest # optional - sage.modules + sage: F(f) # indirect doctest # needs sage.modules Traceback (most recent call last): ... NotImplementedError: Cannot create induced morphisms of free modules yet @@ -2007,14 +2015,15 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.modules sage: from sage.categories.pushout import VectorFunctor - sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) # optional - sage.modules - sage: F2 = (ZZ^3).construction()[0] # optional - sage.modules - sage: F1 == F2 # optional - sage.modules + sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) + sage: F2 = (ZZ^3).construction()[0] + sage: F1 == F2 False - sage: F1(QQ) == F2(QQ) # optional - sage.modules + sage: F1(QQ) == F2(QQ) False - sage: F1 == loads(dumps(F1)) # optional - sage.modules + sage: F1 == loads(dumps(F1)) True """ if isinstance(other, VectorFunctor): @@ -2032,14 +2041,15 @@ def __ne__(self, other): EXAMPLES:: + sage: # needs sage.modules sage: from sage.categories.pushout import VectorFunctor - sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) # optional - sage.modules - sage: F2 = (ZZ^3).construction()[0] # optional - sage.modules - sage: F1 != F2 # optional - sage.modules + sage: F1 = VectorFunctor(3, inner_product_matrix=Matrix(3, 3, range(9))) + sage: F2 = (ZZ^3).construction()[0] + sage: F1 != F2 True - sage: F1(QQ) != F2(QQ) # optional - sage.modules + sage: F1(QQ) != F2(QQ) True - sage: F1 != loads(dumps(F1)) # optional - sage.modules + sage: F1 != loads(dumps(F1)) False """ return not (self == other) @@ -2055,19 +2065,19 @@ def merge(self, other): Two modules without explicitly given inner product allow coercion:: - sage: M1 = QQ^3 # optional - sage.modules + sage: M1 = QQ^3 # needs sage.modules sage: P. = ZZ[] - sage: M2 = FreeModule(P, 3) # optional - sage.modules - sage: M1([1,1/2,1/3]) + M2([t,t^2+t,3]) # indirect doctest # optional - sage.modules + sage: M2 = FreeModule(P, 3) # needs sage.modules + sage: M1([1,1/2,1/3]) + M2([t,t^2+t,3]) # indirect doctest # needs sage.modules (t + 1, t^2 + t + 1/2, 10/3) If only one summand has an explicit inner product, the result will be provided with it:: - sage: M3 = FreeModule(P, 3, inner_product_matrix=Matrix(3, 3, range(9))) # optional - sage.modules - sage: M1([1,1/2,1/3]) + M3([t,t^2+t,3]) # optional - sage.modules + sage: M3 = FreeModule(P, 3, inner_product_matrix=Matrix(3, 3, range(9))) # needs sage.modules + sage: M1([1,1/2,1/3]) + M3([t,t^2+t,3]) # needs sage.modules (t + 1, t^2 + t + 1/2, 10/3) - sage: (M1([1,1/2,1/3]) + M3([t,t^2+t,3])).parent().inner_product_matrix() # optional - sage.modules + sage: (M1([1,1/2,1/3]) + M3([t,t^2+t,3])).parent().inner_product_matrix() # needs sage.modules [0 1 2] [3 4 5] [6 7 8] @@ -2078,12 +2088,13 @@ def merge(self, other): inner product was *explicitly* requested for ``M4``. It is therefore not possible to coerce with a different inner product:: - sage: M4 = FreeModule(QQ, 3, inner_product_matrix=Matrix(3, 3, 1)) # optional - sage.modules - sage: M4 == M1 # optional - sage.modules + sage: # needs sage.modules + sage: M4 = FreeModule(QQ, 3, inner_product_matrix=Matrix(3, 3, 1)) + sage: M4 == M1 True - sage: M4.inner_product_matrix() == M1.inner_product_matrix() # optional - sage.modules + sage: M4.inner_product_matrix() == M1.inner_product_matrix() True - sage: M4([1,1/2,1/3]) + M3([t,t^2+t,3]) # indirect doctest # optional - sage.modules + sage: M4([1,1/2,1/3]) + M3([t,t^2+t,3]) # indirect doctest Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for +: @@ -2101,16 +2112,17 @@ def merge(self, other): Names are removed when they conflict:: + sage: # needs sage.modules sage: from sage.categories.pushout import VectorFunctor, pushout - sage: M_ZZx = FreeModule(ZZ['x'], 4, with_basis=None, name='M_ZZx') # optional - sage.modules - sage: N_ZZx = FreeModule(ZZ['x'], 4, with_basis=None, name='N_ZZx') # optional - sage.modules - sage: pushout(M_ZZx, QQ) # optional - sage.modules + sage: M_ZZx = FreeModule(ZZ['x'], 4, with_basis=None, name='M_ZZx') + sage: N_ZZx = FreeModule(ZZ['x'], 4, with_basis=None, name='N_ZZx') + sage: pushout(M_ZZx, QQ) Rank-4 free module M_ZZx_base_ext over the Univariate Polynomial Ring in x over Rational Field - sage: pushout(M_ZZx, N_ZZx) # optional - sage.modules + sage: pushout(M_ZZx, N_ZZx) Rank-4 free module over the Univariate Polynomial Ring in x over Integer Ring - sage: pushout(pushout(M_ZZx, N_ZZx), QQ) # optional - sage.modules + sage: pushout(pushout(M_ZZx, N_ZZx), QQ) Rank-4 free module over the Univariate Polynomial Ring in x over Rational Field """ @@ -2182,14 +2194,15 @@ class SubspaceFunctor(ConstructionFunctor): EXAMPLES:: - sage: M = ZZ^3 # optional - sage.modules - sage: S = M.submodule([(1,2,3), (4,5,6)]); S # optional - sage.modules + sage: # needs sage.modules + sage: M = ZZ^3 + sage: S = M.submodule([(1,2,3), (4,5,6)]); S Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [1 2 3] [0 3 6] - sage: F = S.construction()[0] # optional - sage.modules - sage: F(GF(2)^3) # optional - sage.rings.finite_rings sage.modules + sage: F = S.construction()[0] + sage: F(GF(2)^3) Vector space of degree 3 and dimension 2 over Finite Field of size 2 User basis matrix: [1 0 1] @@ -2211,9 +2224,9 @@ def __init__(self, basis): TESTS:: sage: from sage.categories.pushout import SubspaceFunctor - sage: M = ZZ^3 # optional - sage.modules - sage: F = SubspaceFunctor([M([1,2,3]), M([4,5,6])]) # optional - sage.modules - sage: F(GF(5)^3) # optional - sage.rings.finite_rings sage.modules + sage: M = ZZ^3 # needs sage.modules + sage: F = SubspaceFunctor([M([1,2,3]), M([4,5,6])]) # needs sage.modules + sage: F(GF(5)^3) # needs sage.modules Vector space of degree 3 and dimension 2 over Finite Field of size 5 User basis matrix: [1 2 3] @@ -2233,14 +2246,15 @@ def _apply_functor(self, ambient): TESTS:: - sage: M = ZZ^3 # optional - sage.modules - sage: S = M.submodule([(1,2,3), (4,5,6)]); S # optional - sage.modules + sage: # needs sage.modules + sage: M = ZZ^3 + sage: S = M.submodule([(1,2,3), (4,5,6)]); S Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [1 2 3] [0 3 6] - sage: F = S.construction()[0] # optional - sage.modules - sage: F(GF(2)^3) # indirect doctest # optional - sage.rings.finite_rings sage.modules + sage: F = S.construction()[0] + sage: F(GF(2)^3) # indirect doctest Vector space of degree 3 and dimension 2 over Finite Field of size 2 User basis matrix: [1 0 1] @@ -2254,10 +2268,11 @@ def _apply_functor_to_morphism(self, f): TESTS:: - sage: F = (ZZ^3).span([(1,2,3), (4,5,6)]).construction()[0] # optional - sage.modules - sage: P. = ZZ[] # optional - sage.modules - sage: f = P.hom([x + 2*y, 3*x - y],P) # optional - sage.modules - sage: F(f) # indirect doctest # optional - sage.modules + sage: # needs sage.modules + sage: F = (ZZ^3).span([(1,2,3), (4,5,6)]).construction()[0] + sage: P. = ZZ[] + sage: f = P.hom([x + 2*y, 3*x - y],P) + sage: F(f) # indirect doctest Traceback (most recent call last): ... NotImplementedError: Cannot create morphisms of free sub-modules yet @@ -2268,32 +2283,34 @@ def __eq__(self, other): """ TESTS:: - sage: F1 = (GF(5)^3).span([(1,2,3),(4,5,6)]).construction()[0] # optional - sage.modules sage.rings.finite_rings - sage: F2 = (ZZ^3).span([(1,2,3),(4,5,6)]).construction()[0] # optional - sage.modules - sage: F3 = (QQ^3).span([(1,2,3),(4,5,6)]).construction()[0] # optional - sage.modules - sage: F4 = (ZZ^3).span([(1,0,-1),(0,1,2)]).construction()[0] # optional - sage.modules - sage: F1 == loads(dumps(F1)) # optional - sage.modules sage.rings.finite_rings + sage: # needs sage.modules + sage: F1 = (GF(5)^3).span([(1,2,3),(4,5,6)]).construction()[0] + sage: F2 = (ZZ^3).span([(1,2,3),(4,5,6)]).construction()[0] + sage: F3 = (QQ^3).span([(1,2,3),(4,5,6)]).construction()[0] + sage: F4 = (ZZ^3).span([(1,0,-1),(0,1,2)]).construction()[0] + sage: F1 == loads(dumps(F1)) True The ``span`` method automatically transforms the given basis into echelon form. The bases look like that:: - sage: F1.basis # optional - sage.modules sage.rings.finite_rings + sage: # needs sage.modules + sage: F1.basis [ (1, 0, 4), (0, 1, 2) ] - sage: F2.basis # optional - sage.modules + sage: F2.basis [ (1, 2, 3), (0, 3, 6) ] - sage: F3.basis # optional - sage.modules + sage: F3.basis [ (1, 0, -1), (0, 1, 2) ] - sage: F4.basis # optional - sage.modules + sage: F4.basis [ (1, 0, -1), (0, 1, 2) @@ -2303,18 +2320,18 @@ def __eq__(self, other): The basis of ``F2`` is modulo 5 different from the other bases. So, we have:: - sage: F1 != F2 != F3 # optional - sage.modules sage.rings.finite_rings + sage: F1 != F2 != F3 # needs sage.modules True The bases of ``F1``, ``F3`` and ``F4`` are the same modulo 5; however, there is no coercion from ``QQ^3`` to ``GF(5)^3``. Therefore, we have:: - sage: F1 == F3 # optional - sage.modules sage.rings.finite_rings + sage: F1 == F3 # needs sage.modules False But there are coercions from ``ZZ^3`` to ``QQ^3`` and ``GF(5)^3``, thus:: - sage: F1 == F4 == F3 # optional - sage.modules sage.rings.finite_rings + sage: F1 == F4 == F3 # needs sage.modules True """ @@ -2340,8 +2357,8 @@ def __ne__(self, other): EXAMPLES:: - sage: F1 = (GF(5)^3).span([(1,2,3),(4,5,6)]).construction()[0] # optional - sage.modules sage.rings.finite_rings - sage: F1 != loads(dumps(F1)) # optional - sage.modules sage.rings.finite_rings + sage: F1 = (GF(5)^3).span([(1,2,3),(4,5,6)]).construction()[0] # needs sage.modules + sage: F1 != loads(dumps(F1)) # needs sage.modules False """ return not (self == other) @@ -2354,16 +2371,17 @@ def merge(self, other): EXAMPLES:: - sage: M = GF(5)^3 # optional - sage.modules sage.rings.finite_rings - sage: S1 = M.submodule([(1,2,3),(4,5,6)]) # optional - sage.modules sage.rings.finite_rings - sage: S2 = M.submodule([(2,2,3)]) # optional - sage.modules sage.rings.finite_rings - sage: F1 = S1.construction()[0] # optional - sage.modules sage.rings.finite_rings - sage: F2 = S2.construction()[0] # optional - sage.modules sage.rings.finite_rings - sage: F1.merge(F2) # optional - sage.modules sage.rings.finite_rings + sage: # needs sage.modules + sage: M = GF(5)^3 + sage: S1 = M.submodule([(1,2,3),(4,5,6)]) + sage: S2 = M.submodule([(2,2,3)]) + sage: F1 = S1.construction()[0] + sage: F2 = S2.construction()[0] + sage: F1.merge(F2) SubspaceFunctor - sage: F1.merge(F2)(GF(5)^3) == S1 + S2 # optional - sage.modules sage.rings.finite_rings + sage: F1.merge(F2)(GF(5)^3) == S1 + S2 True - sage: F1.merge(F2)(GF(5)['t']^3) # optional - sage.modules sage.rings.finite_rings + sage: F1.merge(F2)(GF(5)['t']^3) Free module of degree 3 and rank 3 over Univariate Polynomial Ring in t over Finite Field of size 5 User basis matrix: @@ -2373,12 +2391,13 @@ def merge(self, other): TESTS:: + sage: # needs sage.modules sage: P. = ZZ[] - sage: S1 = (ZZ^3).submodule([(1,2,3), (4,5,6)]) # optional - sage.modules - sage: S2 = (Frac(P)^3).submodule([(t,t^2,t^3+1), (4*t,0,1)]) # optional - sage.modules - sage: v = S1([0,3,6]) + S2([2,0,1/(2*t)]); v # indirect doctest # optional - sage.modules + sage: S1 = (ZZ^3).submodule([(1,2,3), (4,5,6)]) + sage: S2 = (Frac(P)^3).submodule([(t,t^2,t^3+1), (4*t,0,1)]) + sage: v = S1([0,3,6]) + S2([2,0,1/(2*t)]); v # indirect doctest (2, 3, (-12*t - 1)/(-2*t)) - sage: v.parent() # optional - sage.modules + sage: v.parent() Vector space of degree 3 and dimension 3 over Fraction Field of Univariate Polynomial Ring in t over Integer Ring User basis matrix: @@ -2425,7 +2444,7 @@ class FractionField(ConstructionFunctor): Category of integral domains sage: F.codomain() Category of fields - sage: F(GF(5)) is GF(5) # optional - sage.rings.finite_rings + sage: F(GF(5)) is GF(5) True sage: F(ZZ['t']) Fraction Field of Univariate Polynomial Ring in t over Integer Ring @@ -2466,7 +2485,7 @@ def _apply_functor(self, R): TESTS:: sage: F = QQ.construction()[0] - sage: F(GF(5)['t']) # indirect doctest # optional - sage.rings.finite_rings + sage: F(GF(5)['t']) # indirect doctest Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 """ @@ -2479,36 +2498,40 @@ class CompletionFunctor(ConstructionFunctor): EXAMPLES:: - sage: R = Zp(5) # optional - sage.rings.padics - sage: R # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R = Zp(5) + sage: R 5-adic Ring with capped relative precision 20 - sage: F1 = R.construction()[0] # optional - sage.rings.padics - sage: F1 # optional - sage.rings.padics + sage: F1 = R.construction()[0] + sage: F1 Completion[5, prec=20] - sage: F1(ZZ) is R # optional - sage.rings.padics + sage: F1(ZZ) is R True - sage: F1(QQ) # optional - sage.rings.padics + sage: F1(QQ) 5-adic Field with capped relative precision 20 + sage: F2 = RR.construction()[0] sage: F2 Completion[+Infinity, prec=53] sage: F2(QQ) is RR True + sage: P. = ZZ[] sage: Px = P.completion(x) # currently the only implemented completion of P sage: Px Power Series Ring in x over Integer Ring sage: F3 = Px.construction()[0] - sage: F3(GF(3)['x']) # optional - sage.rings.finite_rings + sage: F3(GF(3)['x']) Power Series Ring in x over Finite Field of size 3 TESTS:: - sage: R1. = Zp(5, prec=20)[] # optional - sage.rings.padics - sage: R2 = Qp(5, prec=40) # optional - sage.rings.padics - sage: R2(1) + a # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R1. = Zp(5, prec=20)[] + sage: R2 = Qp(5, prec=40) + sage: R2(1) + a (1 + O(5^20))*a + 1 + O(5^40) - sage: 1/2 + a # optional - sage.rings.padics + sage: 1/2 + a (1 + O(5^20))*a + 3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 2*5^8 + 2*5^9 + 2*5^10 + 2*5^11 + 2*5^12 + 2*5^13 + 2*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 2*5^18 + 2*5^19 + O(5^20) """ @@ -2539,21 +2562,21 @@ def __init__(self, p, prec, extras=None): TESTS:: sage: from sage.categories.pushout import CompletionFunctor - sage: F1 = CompletionFunctor(5, 100) # optional - sage.rings.padics - sage: F1(QQ) # optional - sage.rings.padics + sage: F1 = CompletionFunctor(5, 100) + sage: F1(QQ) # needs sage.rings.padics 5-adic Field with capped relative precision 100 - sage: F1(ZZ) # optional - sage.rings.padics + sage: F1(ZZ) # needs sage.rings.padics 5-adic Ring with capped relative precision 100 - sage: F1.type is None # optional - sage.rings.padics + sage: F1.type is None True - sage: sorted(F1.extras.items()) # optional - sage.rings.padics + sage: sorted(F1.extras.items()) [] sage: F2 = RR.construction()[0] sage: F2 Completion[+Infinity, prec=53] - sage: F2.type + sage: F2.type # needs sage.rings.real_mpfr 'MPFR' - sage: F2.extras + sage: F2.extras # needs sage.rings.real_mpfr {'rnd': 0, 'sci_not': False} """ Functor.__init__(self, Rings(), Rings()) @@ -2578,7 +2601,7 @@ def _repr_(self): """ TESTS:: - sage: Zp(7).construction() # indirect doctest # optional - sage.rings.padics + sage: Zp(7).construction() # indirect doctest # needs sage.rings.padics (Completion[7, prec=20], Integer Ring) sage: RR.construction() # indirect doctest @@ -2592,11 +2615,12 @@ def _apply_functor(self, R): TESTS:: - sage: R = Zp(5) # optional - sage.rings.padics - sage: F1 = R.construction()[0] # optional - sage.rings.padics - sage: F1(ZZ) is R # indirect doctest # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R = Zp(5) + sage: F1 = R.construction()[0] + sage: F1(ZZ) is R # indirect doctest True - sage: F1(QQ) # optional - sage.rings.padics + sage: F1(QQ) 5-adic Field with capped relative precision 20 """ @@ -2635,19 +2659,20 @@ def __eq__(self, other): TESTS:: - sage: R1 = Zp(5, prec=30) # optional - sage.rings.padics - sage: R2 = Zp(5, prec=40) # optional - sage.rings.padics - sage: F1 = R1.construction()[0] # optional - sage.rings.padics - sage: F2 = R2.construction()[0] # optional - sage.rings.padics - sage: F1 == loads(dumps(F1)) # indirect doctest # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R1 = Zp(5, prec=30) + sage: R2 = Zp(5, prec=40) + sage: F1 = R1.construction()[0] + sage: F2 = R2.construction()[0] + sage: F1 == loads(dumps(F1)) # indirect doctest True - sage: F1 == F2 # optional - sage.rings.padics + sage: F1 == F2 True - sage: F1(QQ) == F2(QQ) # optional - sage.rings.padics + sage: F1(QQ) == F2(QQ) False - sage: R3 = Zp(7) # optional - sage.rings.padics - sage: F3 = R3.construction()[0] # optional - sage.rings.padics - sage: F1 == F3 # optional - sage.rings.padics + sage: R3 = Zp(7) + sage: F3 = R3.construction()[0] + sage: F1 == F3 False """ if isinstance(other, CompletionFunctor): @@ -2660,19 +2685,20 @@ def __ne__(self, other): EXAMPLES:: - sage: R1 = Zp(5, prec=30) # optional - sage.rings.padics - sage: R2 = Zp(5, prec=40) # optional - sage.rings.padics - sage: F1 = R1.construction()[0] # optional - sage.rings.padics - sage: F2 = R2.construction()[0] # optional - sage.rings.padics - sage: F1 != loads(dumps(F1)) # indirect doctest # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R1 = Zp(5, prec=30) + sage: R2 = Zp(5, prec=40) + sage: F1 = R1.construction()[0] + sage: F2 = R2.construction()[0] + sage: F1 != loads(dumps(F1)) # indirect doctest False - sage: F1 != F2 # optional - sage.rings.padics + sage: F1 != F2 False - sage: F1(QQ) != F2(QQ) # optional - sage.rings.padics + sage: F1(QQ) != F2(QQ) True - sage: R3 = Zp(7) # optional - sage.rings.padics - sage: F3 = R3.construction()[0] # optional - sage.rings.padics - sage: F1 != F3 # optional - sage.rings.padics + sage: R3 = Zp(7) + sage: F3 = R3.construction()[0] + sage: F1 != F3 True """ return not (self == other) @@ -2690,22 +2716,23 @@ def merge(self, other): EXAMPLES:: - sage: R1. = Zp(5, prec=20)[] # optional - sage.rings.padics - sage: R2 = Qp(5, prec=40) # optional - sage.rings.padics - sage: R2(1) + a # indirect doctest # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R1. = Zp(5, prec=20)[] + sage: R2 = Qp(5, prec=40) + sage: R2(1) + a # indirect doctest (1 + O(5^20))*a + 1 + O(5^40) - sage: R3 = RealField(30) # optional - sage.rings.padics - sage: R4 = RealField(50) # optional - sage.rings.padics - sage: R3(1) + R4(1) # indirect doctest # optional - sage.rings.padics + sage: R3 = RealField(30) + sage: R4 = RealField(50) + sage: R3(1) + R4(1) # indirect doctest 2.0000000 - sage: (R3(1) + R4(1)).parent() # optional - sage.rings.padics + sage: (R3(1) + R4(1)).parent() Real Field with 30 bits of precision TESTS: We check that :trac:`12353` has been resolved:: - sage: RIF(1) > RR(1) + sage: RIF(1) > RR(1) # needs sage.rings.real_interval_field Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for >: @@ -2713,6 +2740,7 @@ def merge(self, other): We check that various pushouts work:: + sage: # needs sage.rings.real_interval_field sage.rings.real_mpfr sage: R0 = RealIntervalField(30) sage: R1 = RealIntervalField(30, sci_not=True) sage: R2 = RealIntervalField(53) @@ -2733,19 +2761,20 @@ def merge(self, other): :: - sage: P0 = ZpFM(5, 10) # optional - sage.rings.padics - sage: P1 = ZpFM(5, 20) # optional - sage.rings.padics - sage: P2 = ZpCR(5, 10) # optional - sage.rings.padics - sage: P3 = ZpCR(5, 20) # optional - sage.rings.padics - sage: P4 = ZpCA(5, 10) # optional - sage.rings.padics - sage: P5 = ZpCA(5, 20) # optional - sage.rings.padics - sage: P6 = Qp(5, 10) # optional - sage.rings.padics - sage: P7 = Qp(5, 20) # optional - sage.rings.padics - sage: Plist = [P2,P3,P4,P5,P6,P7] # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: P0 = ZpFM(5, 10) + sage: P1 = ZpFM(5, 20) + sage: P2 = ZpCR(5, 10) + sage: P3 = ZpCR(5, 20) + sage: P4 = ZpCA(5, 10) + sage: P5 = ZpCA(5, 20) + sage: P6 = Qp(5, 10) + sage: P7 = Qp(5, 20) + sage: Plist = [P2,P3,P4,P5,P6,P7] sage: from sage.categories.pushout import pushout - sage: pushouts = [P2,P3,P4,P5,P6,P7,P3,P3,P5,P5,P7,P7,P4,P5,P4,P5,P6,P7, # optional - sage.rings.padics + sage: pushouts = [P2,P3,P4,P5,P6,P7,P3,P3,P5,P5,P7,P7,P4,P5,P4,P5,P6,P7, ....: P5,P5,P5,P5,P7,P7,P6,P7,P6,P7,P6,P7,P7,P7,P7,P7,P7,P7] - sage: all(P is Q # optional - sage.rings.padics + sage: all(P is Q ....: for P, Q in zip(pushouts, [pushout(a, b) for a in Plist for b in Plist])) True """ @@ -2788,9 +2817,9 @@ def commutes(self, other): EXAMPLES:: - sage: F1 = Zp(5).construction()[0] # optional - sage.rings.padics + sage: F1 = Zp(5).construction()[0] # needs sage.rings.padics sage: F2 = QQ.construction()[0] - sage: F1.commutes(F2) # optional - sage.rings.padics + sage: F1.commutes(F2) # needs sage.rings.padics True TESTS: @@ -2817,7 +2846,7 @@ def commutes(self, other): Ambiguous base extension error raised):: sage: from sage.categories.pushout import pushout - sage: pushout(Qp(7), RLF) # optional - sage.rings.padics + sage: pushout(Qp(7), RLF) # needs sage.rings.padics Traceback (most recent call last): ... CoercionException: Don't know how to @@ -2840,19 +2869,19 @@ class QuotientFunctor(ConstructionFunctor): EXAMPLES:: sage: P. = ZZ[] - sage: Q = P.quo([x^2 + y^2] * P) # optional - sage.rings.finite_rings - sage: F = Q.construction()[0] # optional - sage.rings.finite_rings - sage: F(QQ['x','y']) # optional - sage.rings.finite_rings + sage: Q = P.quo([x^2 + y^2] * P) + sage: F = Q.construction()[0] + sage: F(QQ['x','y']) Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) - sage: F(QQ['x','y']) == QQ['x','y'].quo([x^2 + y^2] * QQ['x','y']) # optional - sage.rings.finite_rings + sage: F(QQ['x','y']) == QQ['x','y'].quo([x^2 + y^2] * QQ['x','y']) True - sage: F(QQ['x','y','z']) # optional - sage.rings.finite_rings + sage: F(QQ['x','y','z']) Traceback (most recent call last): ... CoercionException: Cannot apply this quotient functor to Multivariate Polynomial Ring in x, y, z over Rational Field - sage: F(QQ['y','z']) # optional - sage.rings.finite_rings + sage: F(QQ['y','z']) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: Could not find a mapping of the passed element to this ring. @@ -2882,24 +2911,24 @@ def __init__(self, I, names=None, as_field=False, domain=None, sage: from sage.categories.pushout import QuotientFunctor sage: P. = ZZ[] sage: F = QuotientFunctor([5 + t^2] * P) - sage: F(P) # optional - sage.rings.finite_rings + sage: F(P) # needs sage.libs.pari Univariate Quotient Polynomial Ring in tbar over Integer Ring with modulus t^2 + 5 - sage: F(QQ['t']) # optional - sage.rings.finite_rings + sage: F(QQ['t']) # needs sage.libs.pari Univariate Quotient Polynomial Ring in tbar over Rational Field with modulus t^2 + 5 sage: F = QuotientFunctor([5 + t^2] * P, names='s') - sage: F(P) # optional - sage.rings.finite_rings + sage: F(P) # needs sage.libs.pari Univariate Quotient Polynomial Ring in s over Integer Ring with modulus t^2 + 5 - sage: F(QQ['t']) # optional - sage.rings.finite_rings + sage: F(QQ['t']) # needs sage.libs.pari Univariate Quotient Polynomial Ring in s over Rational Field with modulus t^2 + 5 sage: F = QuotientFunctor([5] * ZZ, as_field=True) - sage: F(ZZ) # optional - sage.rings.finite_rings + sage: F(ZZ) Finite Field of size 5 sage: F = QuotientFunctor([5] * ZZ) - sage: F(ZZ) # optional - sage.rings.finite_rings + sage: F(ZZ) Ring of integers modulo 5 """ @@ -2926,10 +2955,10 @@ def _apply_functor(self, R): TESTS:: sage: P. = ZZ[] - sage: Q = P.quo([2 + x^2, 3*x + y^2]) # optional - sage.rings.finite_rings - sage: F = Q.construction()[0]; F # optional - sage.rings.finite_rings + sage: Q = P.quo([2 + x^2, 3*x + y^2]) + sage: F = Q.construction()[0]; F QuotientFunctor - sage: F(QQ['x','y']) # indirect doctest # optional - sage.rings.finite_rings + sage: F(QQ['x','y']) # indirect doctest Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + 2, y^2 + 3*x) @@ -2973,15 +3002,16 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.libs.pari sage: P. = QQ[] - sage: F = P.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] # optional - sage.rings.finite_rings - sage: F == loads(dumps(F)) # optional - sage.rings.finite_rings + sage: F = P.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] + sage: F == loads(dumps(F)) True sage: P2. = QQ[] - sage: F == P2.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] # optional - sage.rings.finite_rings + sage: F == P2.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] False sage: P3. = ZZ[] - sage: F == P3.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] # optional - sage.rings.finite_rings + sage: F == P3.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] True """ if not isinstance(other, QuotientFunctor): @@ -2998,15 +3028,16 @@ def __ne__(self, other): EXAMPLES:: + sage: # needs sage.libs.pari sage: P. = QQ[] - sage: F = P.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] # optional - sage.rings.finite_rings - sage: F != loads(dumps(F)) # optional - sage.rings.finite_rings + sage: F = P.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] + sage: F != loads(dumps(F)) False sage: P2. = QQ[] - sage: F != P2.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] # optional - sage.rings.finite_rings + sage: F != P2.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] True sage: P3. = ZZ[] - sage: F != P3.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] # optional - sage.rings.finite_rings + sage: F != P3.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] False """ return not (self == other) @@ -3024,17 +3055,18 @@ def merge(self, other): EXAMPLES:: + sage: # needs sage.libs.pari sage: P. = QQ[] - sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)]) # optional - sage.rings.finite_rings - sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)]) # optional - sage.rings.finite_rings + sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)]) + sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)]) sage: from sage.categories.pushout import pushout - sage: pushout(Q1,Q2) # indirect doctest # optional - sage.rings.finite_rings + sage: pushout(Q1,Q2) # indirect doctest Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^4 + 2*x^2 + 1 The following was fixed in :trac:`8800`:: - sage: pushout(GF(5), Integers(5)) # optional - sage.rings.finite_rings + sage: pushout(GF(5), Integers(5)) # needs sage.libs.pari Finite Field of size 5 """ @@ -3066,13 +3098,13 @@ def merge(self, other): for k,v in self.kwds.items(): kwds[k] = v for k,v in other.kwds.items(): - if k=='category': + if k == 'category': if kwds[k] is not None: kwds[k] = v.join([v,kwds[k]]) else: kwds[k] = v continue - if k in kwds and kwds[k] is not None and v!=kwds[k]: + if k in kwds and kwds[k] is not None and v != kwds[k]: # Don't know what default to choose. Hence: No merge! return None kwds[k] = v @@ -3094,9 +3126,9 @@ class AlgebraicExtensionFunctor(ConstructionFunctor): EXAMPLES:: sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 + x^2 + 1) # optional - sage.rings.number_field - sage: F = K.construction()[0] # optional - sage.rings.number_field - sage: F(ZZ['t']) # optional - sage.rings.number_field + sage: K. = NumberField(x^3 + x^2 + 1) # needs sage.rings.number_field + sage: F = K.construction()[0] # needs sage.rings.number_field + sage: F(ZZ['t']) # needs sage.rings.number_field Univariate Quotient Polynomial Ring in a over Univariate Polynomial Ring in t over Integer Ring with modulus a^3 + a^2 + 1 @@ -3105,11 +3137,11 @@ class AlgebraicExtensionFunctor(ConstructionFunctor): extension will be constructed as the quotient of a univariate polynomial ring:: - sage: F(CC) # optional - sage.rings.number_field + sage: F(CC) # needs sage.rings.number_field Univariate Quotient Polynomial Ring in a over Complex Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 - sage: F(RR) # optional - sage.rings.number_field + sage: F(RR) # needs sage.rings.number_field Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 @@ -3118,48 +3150,51 @@ class AlgebraicExtensionFunctor(ConstructionFunctor): the integers returns an order (not necessarily maximal) of that field, similar to the behaviour of ``ZZ.extension(...)``:: - sage: F(ZZ) # optional - sage.rings.number_field + sage: F(ZZ) # needs sage.rings.number_field Order in Number Field in a with defining polynomial x^3 + x^2 + 1 This also holds for non-absolute number fields:: + sage: # needs sage.rings.number_field sage: x = polygen(QQ, 'x') - sage: K. = NumberField([x^3 + x^2 + 1, x^2 + x + 1]) # optional - sage.rings.number_field - sage: F = K.construction()[0] # optional - sage.rings.number_field - sage: O = F(ZZ); O # optional - sage.rings.number_field + sage: K. = NumberField([x^3 + x^2 + 1, x^2 + x + 1]) + sage: F = K.construction()[0] + sage: O = F(ZZ); O Relative Order in Number Field in a with defining polynomial x^3 + x^2 + 1 over its base field - sage: O.ambient() is K # optional - sage.rings.number_field + sage: O.ambient() is K True Special cases are made for cyclotomic fields and residue fields:: - sage: C = CyclotomicField(8) # optional - sage.rings.number_field - sage: F, R = C.construction() # optional - sage.rings.number_field - sage: F # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: C = CyclotomicField(8) + sage: F, R = C.construction() + sage: F AlgebraicExtensionFunctor - sage: R # optional - sage.rings.number_field + sage: R Rational Field - sage: F(R) # optional - sage.rings.number_field + sage: F(R) Cyclotomic Field of order 8 and degree 4 - sage: F(ZZ) # optional - sage.rings.number_field + sage: F(ZZ) Maximal Order in Cyclotomic Field of order 8 and degree 4 :: - sage: K. = CyclotomicField(7) # optional - sage.rings.number_field - sage: P = K.factor(17)[0][0] # optional - sage.rings.number_field - sage: k = K.residue_field(P) # optional - sage.rings.number_field - sage: F, R = k.construction() # optional - sage.rings.number_field - sage: F # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = CyclotomicField(7) + sage: P = K.factor(17)[0][0] + sage: k = K.residue_field(P) + sage: F, R = k.construction() + sage: F AlgebraicExtensionFunctor - sage: R # optional - sage.rings.number_field + sage: R Cyclotomic Field of order 7 and degree 6 - sage: F(R) is k # optional - sage.rings.number_field + sage: F(R) is k True - sage: F(ZZ) # optional - sage.rings.number_field + sage: F(ZZ) Residue field of Integers modulo 17 - sage: F(CyclotomicField(49)) # optional - sage.rings.number_field + sage: F(CyclotomicField(49)) Residue field in zbar of Fractional ideal (17) """ @@ -3221,25 +3256,25 @@ def __init__(self, polys, names, embeddings=None, structures=None, sage: from sage.categories.pushout import AlgebraicExtensionFunctor sage: P. = ZZ[] - sage: F1 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [None]) # optional - sage.rings.number_field - sage: F2 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [0]) # optional - sage.rings.number_field - sage: F1 == F2 # optional - sage.rings.number_field + sage: F1 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [None]) + sage: F2 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [0]) + sage: F1 == F2 False - sage: F1(QQ) # optional - sage.rings.number_field + sage: F1(QQ) # needs sage.rings.number_field Number Field in a with defining polynomial x^3 - x^2 + 1 - sage: F1(QQ).coerce_embedding() # optional - sage.rings.number_field - sage: phi = F2(QQ).coerce_embedding().__copy__(); phi # optional - sage.rings.number_field + sage: F1(QQ).coerce_embedding() # needs sage.rings.number_field + sage: phi = F2(QQ).coerce_embedding().__copy__(); phi # needs sage.rings.number_field Generic morphism: From: Number Field in a with defining polynomial x^3 - x^2 + 1 with a = -0.7548776662466928? To: Real Lazy Field Defn: a -> -0.7548776662466928? - sage: F1(QQ) == F2(QQ) # optional - sage.rings.number_field + sage: F1(QQ) == F2(QQ) # needs sage.rings.number_field False - sage: F1(GF(5)) # optional - sage.rings.finite_rings sage.rings.number_field + sage: F1(GF(5)) # needs sage.libs.pari Univariate Quotient Polynomial Ring in a over Finite Field of size 5 with modulus a^3 + 4*a^2 + 1 - sage: F2(GF(5)) # optional - sage.rings.finite_rings sage.rings.number_field + sage: F2(GF(5)) # needs sage.libs.pari Traceback (most recent call last): ... NotImplementedError: ring extension with prescribed embedding is not implemented @@ -3248,38 +3283,40 @@ def __init__(self, polys, names, embeddings=None, structures=None, integers, an order (not necessarily maximal) of that field is returned, similar to the behaviour of ``ZZ.extension``:: - sage: F1(ZZ) # optional - sage.rings.number_field + sage: F1(ZZ) # needs sage.rings.number_field Order in Number Field in a with defining polynomial x^3 - x^2 + 1 The cyclotomic fields form a special case of number fields with prescribed embeddings:: - sage: C = CyclotomicField(8) # optional - sage.rings.number_field - sage: F, R = C.construction() # optional - sage.rings.number_field - sage: F # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: C = CyclotomicField(8) + sage: F, R = C.construction() + sage: F AlgebraicExtensionFunctor - sage: R # optional - sage.rings.number_field + sage: R Rational Field - sage: F(R) # optional - sage.rings.number_field + sage: F(R) Cyclotomic Field of order 8 and degree 4 - sage: F(ZZ) # optional - sage.rings.number_field + sage: F(ZZ) Maximal Order in Cyclotomic Field of order 8 and degree 4 The data stored in this construction includes structural morphisms of number fields (see :trac:`20826`):: + sage: # needs sage.rings.number_field sage: R. = ZZ[] - sage: K. = NumberField(x^2 - 3) # optional - sage.rings.number_field - sage: L0. = K.change_names() # optional - sage.rings.number_field - sage: L0.structure() # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3) + sage: L0. = K.change_names() + sage: L0.structure() (Isomorphism given by variable name change map: From: Number Field in b with defining polynomial x^2 - 3 To: Number Field in a with defining polynomial x^2 - 3, Isomorphism given by variable name change map: From: Number Field in a with defining polynomial x^2 - 3 To: Number Field in b with defining polynomial x^2 - 3) - sage: L1 = (b*x).parent().base_ring() # optional - sage.rings.number_field - sage: L1 is L0 # optional - sage.rings.number_field + sage: L1 = (b*x).parent().base_ring() + sage: L1 is L0 True """ Functor.__init__(self, Rings(), Rings()) @@ -3322,25 +3359,27 @@ def _apply_functor(self, R): TESTS:: + sage: # needs sage.rings.number_field sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 + x^2 + 1) # optional - sage.rings.number_field - sage: F = K.construction()[0] # optional - sage.rings.number_field - sage: F(ZZ) # indirect doctest # optional - sage.rings.number_field + sage: K. = NumberField(x^3 + x^2 + 1) + sage: F = K.construction()[0] + sage: F(ZZ) # indirect doctest Order in Number Field in a with defining polynomial x^3 + x^2 + 1 - sage: F(ZZ['t']) # indirect doctest # optional - sage.rings.number_field + sage: F(ZZ['t']) # indirect doctest Univariate Quotient Polynomial Ring in a over Univariate Polynomial Ring in t over Integer Ring with modulus a^3 + a^2 + 1 - sage: F(RR) # indirect doctest # optional - sage.rings.number_field + sage: F(RR) # indirect doctest Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 Check that :trac:`13538` is fixed:: + sage: # needs sage.rings.padics sage: from sage.categories.pushout import AlgebraicExtensionFunctor - sage: K = Qp(3, 3) # optional - sage.rings.padics - sage: R. = K[] # optional - sage.rings.padics - sage: AEF = AlgebraicExtensionFunctor([a^2 - 3], ['a'], [None]) # optional - sage.rings.padics - sage: AEF(K) # optional - sage.rings.padics + sage: K = Qp(3, 3) + sage: R. = K[] + sage: AEF = AlgebraicExtensionFunctor([a^2 - 3], ['a'], [None]) + sage: AEF(K) 3-adic Eisenstein Extension Field in a defined by a^2 - 3 """ @@ -3370,20 +3409,21 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.rings.number_field sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 + x^2 + 1) # optional - sage.rings.number_field - sage: F = K.construction()[0] # optional - sage.rings.number_field - sage: F == loads(dumps(F)) # optional - sage.rings.number_field + sage: K. = NumberField(x^3 + x^2 + 1) + sage: F = K.construction()[0] + sage: F == loads(dumps(F)) True - sage: K2. = NumberField(x^3 + x^2 + 1, latex_names='a') # optional - sage.rings.number_field - sage: F2 = K2.construction()[0] # optional - sage.rings.number_field - sage: F2 == F # optional - sage.rings.number_field + sage: K2. = NumberField(x^3 + x^2 + 1, latex_names='a') # needs sage.rings.number_field + sage: F2 = K2.construction()[0] # needs sage.rings.number_field + sage: F2 == F # needs sage.rings.number_field True - sage: K3. = NumberField(x^3 + x^2 + 1, latex_names='alpha') # optional - sage.rings.number_field - sage: F3 = K3.construction()[0] # optional - sage.rings.number_field - sage: F3 == F # optional - sage.rings.number_field + sage: K3. = NumberField(x^3 + x^2 + 1, latex_names='alpha') # needs sage.rings.number_field + sage: F3 = K3.construction()[0] # needs sage.rings.number_field + sage: F3 == F # needs sage.rings.number_field False """ if not isinstance(other, AlgebraicExtensionFunctor): @@ -3402,9 +3442,9 @@ def __ne__(self, other): EXAMPLES:: sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 + x^2 + 1) # optional - sage.rings.number_field - sage: F = K.construction()[0] # optional - sage.rings.number_field - sage: F != loads(dumps(F)) # optional - sage.rings.number_field + sage: K. = NumberField(x^3 + x^2 + 1) # needs sage.rings.number_field + sage: F = K.construction()[0] # needs sage.rings.number_field + sage: F != loads(dumps(F)) # needs sage.rings.number_field False """ return not (self == other) @@ -3448,36 +3488,38 @@ def merge(self, other): The following demonstrate coercions for finite fields using Conway or pseudo-Conway polynomials:: - sage: k = GF(3^2, prefix='z'); a = k.gen() # optional - sage.rings.finite_rings - sage: l = GF(3^3, prefix='z'); b = l.gen() # optional - sage.rings.finite_rings - sage: a + b # indirect doctest # optional - sage.rings.finite_rings + sage: k = GF(3^2, prefix='z'); a = k.gen() # needs sage.rings.finite_rings + sage: l = GF(3^3, prefix='z'); b = l.gen() # needs sage.rings.finite_rings + sage: a + b # indirect doctest # needs sage.rings.finite_rings z6^5 + 2*z6^4 + 2*z6^3 + z6^2 + 2*z6 + 1 Note that embeddings are compatible in lattices of such finite fields:: - sage: m = GF(3^5, prefix='z'); c = m.gen() # optional - sage.rings.finite_rings - sage: (a + b) + c == a + (b + c) # indirect doctest # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: m = GF(3^5, prefix='z'); c = m.gen() + sage: (a + b) + c == a + (b + c) # indirect doctest True sage: from sage.categories.pushout import pushout - sage: n = pushout(k, l) # optional - sage.rings.finite_rings - sage: o = pushout(l, m) # optional - sage.rings.finite_rings - sage: q = pushout(n, o) # optional - sage.rings.finite_rings - sage: q(o(b)) == q(n(b)) # indirect doctest # optional - sage.rings.finite_rings + sage: n = pushout(k, l) + sage: o = pushout(l, m) + sage: q = pushout(n, o) + sage: q(o(b)) == q(n(b)) # indirect doctest True Coercion is also available for number fields:: - sage: P. = QQ[] # optional - sage.rings.number_field - sage: L. = NumberField(x^8 - x^4 + 1, embedding=CDF.0) # optional - sage.rings.number_field - sage: M1. = NumberField(x^2 + x + 1, embedding=b^4 - 1) # optional - sage.rings.number_field - sage: M2. = NumberField(x^2 + 1, embedding=-b^6) # optional - sage.rings.number_field - sage: M1.coerce_map_from(M2) # optional - sage.rings.number_field - sage: M2.coerce_map_from(M1) # optional - sage.rings.number_field - sage: c1 + c2; parent(c1 + c2) #indirect doctest # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P. = QQ[] + sage: L. = NumberField(x^8 - x^4 + 1, embedding=CDF.0) + sage: M1. = NumberField(x^2 + x + 1, embedding=b^4 - 1) + sage: M2. = NumberField(x^2 + 1, embedding=-b^6) + sage: M1.coerce_map_from(M2) + sage: M2.coerce_map_from(M1) + sage: c1 + c2; parent(c1 + c2) #indirect doctest -b^6 + b^4 - 1 Number Field in b with defining polynomial x^8 - x^4 + 1 with b = -0.2588190451025208? + 0.9659258262890683?*I - sage: pushout(M1['x'], M2['x']) # optional - sage.rings.number_field + sage: pushout(M1['x'], M2['x']) # needs sage.rings.finite_rings Univariate Polynomial Ring in x over Number Field in b with defining polynomial x^8 - x^4 + 1 with b = -0.2588190451025208? + 0.9659258262890683?*I @@ -3488,13 +3530,14 @@ def merge(self, other): are embedded into a field that is not a numberfield, no merging occurs:: + sage: # needs sage.rings.complex_double sage.rings.number_field sage: cbrt2 = CDF(2)^(1/3) sage: zeta3 = CDF.zeta(3) - sage: K. = NumberField(x^3 - 2, embedding=cbrt2 * zeta3) # optional - sage.rings.number_field - sage: L. = NumberField(x^6 - 2, embedding=1.1) # optional - sage.rings.number_field - sage: L.coerce_map_from(K) # optional - sage.rings.number_field - sage: K.coerce_map_from(L) # optional - sage.rings.number_field - sage: pushout(K, L) # optional - sage.rings.number_field + sage: K. = NumberField(x^3 - 2, embedding=cbrt2 * zeta3) + sage: L. = NumberField(x^6 - 2, embedding=1.1) + sage: L.coerce_map_from(K) + sage: K.coerce_map_from(L) + sage: pushout(K, L) # needs sage.rings.finite_rings Traceback (most recent call last): ... CoercionException: ('Ambiguous Base Extension', Number Field in a with @@ -3568,11 +3611,12 @@ def __mul__(self, other): TESTS:: + sage: # needs sage.rings.number_field sage: P. = QQ[] - sage: K. = NumberField(x^3 - 5, embedding=0) # optional - sage.rings.number_field - sage: L. = K.extension(x^2 + a) # optional - sage.rings.number_field - sage: F, R = L.construction() # optional - sage.rings.number_field - sage: prod(F.expand())(R) == L #indirect doctest # optional - sage.rings.number_field + sage: K. = NumberField(x^3 - 5, embedding=0) + sage: L. = K.extension(x^2 + a) + sage: F, R = L.construction() + sage: prod(F.expand())(R) == L #indirect doctest True """ @@ -3600,19 +3644,20 @@ def expand(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: P. = QQ[] - sage: K. = NumberField(x^3 - 5, embedding=0) # optional - sage.rings.number_field - sage: L. = K.extension(x^2 + a) # optional - sage.rings.number_field - sage: F, R = L.construction() # optional - sage.rings.number_field - sage: prod(F.expand())(R) == L # optional - sage.rings.number_field + sage: K. = NumberField(x^3 - 5, embedding=0) + sage: L. = K.extension(x^2 + a) + sage: F, R = L.construction() + sage: prod(F.expand())(R) == L True - sage: K = NumberField([x^2 - 2, x^2 - 3],'a') # optional - sage.rings.number_field - sage: F, R = K.construction() # optional - sage.rings.number_field - sage: F # optional - sage.rings.number_field + sage: K = NumberField([x^2 - 2, x^2 - 3],'a') + sage: F, R = K.construction() + sage: F AlgebraicExtensionFunctor - sage: L = F.expand(); L # optional - sage.rings.number_field + sage: L = F.expand(); L [AlgebraicExtensionFunctor, AlgebraicExtensionFunctor] - sage: L[-1](QQ) # optional - sage.rings.number_field + sage: L[-1](QQ) Number Field in a1 with defining polynomial x^2 - 3 """ n = len(self.polys) @@ -3631,12 +3676,13 @@ class AlgebraicClosureFunctor(ConstructionFunctor): EXAMPLES:: + sage: # needs sage.rings.complex_double sage.rings.number_field sage: F = CDF.construction()[0] - sage: F(QQ) # optional - sage.rings.number_field + sage: F(QQ) Algebraic Field - sage: F(RR) + sage: F(RR) # needs sage.rings.real_mpfr Complex Field with 53 bits of precision - sage: F(F(QQ)) is F(QQ) # optional - sage.rings.number_field + sage: F(F(QQ)) is F(QQ) True """ @@ -3648,9 +3694,9 @@ def __init__(self): sage: from sage.categories.pushout import AlgebraicClosureFunctor sage: F = AlgebraicClosureFunctor() - sage: F(QQ) # optional - sage.rings.number_field + sage: F(QQ) # needs sage.rings.number_field Algebraic Field - sage: F(RR) + sage: F(RR) # needs sage.rings.real_mpfr Complex Field with 53 bits of precision sage: F == loads(dumps(F)) True @@ -3664,8 +3710,8 @@ def _apply_functor(self, R): TESTS:: - sage: F = CDF.construction()[0] - sage: F(QQ) # indirect doctest # optional - sage.rings.number_field + sage: F = CDF.construction()[0] # needs sage.rings.complex_double + sage: F(QQ) # indirect doctest # needs sage.rings.complex_double sage.rings.number_field Algebraic Field """ try: @@ -3685,10 +3731,10 @@ def merge(self, other): TESTS:: sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 + x^2 + 1) # optional - sage.rings.number_field - sage: CDF.construction()[0].merge(K.construction()[0]) is None # optional - sage.rings.number_field + sage: K. = NumberField(x^3 + x^2 + 1) # needs sage.rings.number_field + sage: CDF.construction()[0].merge(K.construction()[0]) is None # needs sage.rings.number_field True - sage: CDF.construction()[0].merge(CDF.construction()[0]) # optional - sage.rings.number_field + sage: CDF.construction()[0].merge(CDF.construction()[0]) # needs sage.rings.complex_double AlgebraicClosureFunctor """ @@ -3711,7 +3757,7 @@ def __init__(self, gens, domain): EXAMPLES:: sage: from sage.categories.pushout import PermutationGroupFunctor - sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])], # optional - sage.groups + sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])], # needs sage.groups ....: [1,2]); PF PermutationGroupFunctor[(1,2)] """ @@ -3723,9 +3769,9 @@ def _repr_(self): """ EXAMPLES:: - sage: P1 = PermutationGroup([[(1,2)]]) # optional - sage.groups - sage: PF, P = P1.construction() # optional - sage.groups - sage: PF # optional - sage.groups + sage: P1 = PermutationGroup([[(1,2)]]) # needs sage.groups + sage: PF, P = P1.construction() # needs sage.groups + sage: PF # needs sage.groups PermutationGroupFunctor[(1,2)] """ return "PermutationGroupFunctor%s" % list(self.gens()) @@ -3734,9 +3780,9 @@ def __call__(self, R): """ EXAMPLES:: - sage: P1 = PermutationGroup([[(1,2)]]) # optional - sage.groups - sage: PF, P = P1.construction() # optional - sage.groups - sage: PF(P) # optional - sage.groups + sage: P1 = PermutationGroup([[(1,2)]]) # needs sage.groups + sage: PF, P = P1.construction() # needs sage.groups + sage: PF(P) # needs sage.groups Permutation Group with generators [(1,2)] """ from sage.groups.perm_gps.permgroup import PermutationGroup @@ -3747,9 +3793,9 @@ def gens(self): """ EXAMPLES:: - sage: P1 = PermutationGroup([[(1,2)]]) # optional - sage.groups - sage: PF, P = P1.construction() # optional - sage.groups - sage: PF.gens() # optional - sage.groups + sage: P1 = PermutationGroup([[(1,2)]]) # needs sage.groups + sage: PF, P = P1.construction() # needs sage.groups + sage: PF.gens() # needs sage.groups ((1,2),) """ return self._gens @@ -3760,11 +3806,12 @@ def merge(self, other): EXAMPLES:: - sage: P1 = PermutationGroup([[(1,2)]]) # optional - sage.groups - sage: PF1, P = P1.construction() # optional - sage.groups - sage: P2 = PermutationGroup([[(1,3)]]) # optional - sage.groups - sage: PF2, P = P2.construction() # optional - sage.groups - sage: PF1.merge(PF2) # optional - sage.groups + sage: # needs sage.groups + sage: P1 = PermutationGroup([[(1,2)]]) + sage: PF1, P = P1.construction() + sage: P2 = PermutationGroup([[(1,3)]]) + sage: PF2, P = P2.construction() + sage: PF1.merge(PF2) PermutationGroupFunctor[(1,2), (1,3)] """ if self.__class__ != other.__class__: @@ -3810,13 +3857,14 @@ class EquivariantSubobjectConstructionFunctor(ConstructionFunctor): column (index 1); the order of the extra element 2 in a permutation determines whether it is a symmetry or an antisymmetry:: - sage: GSym01 = PermutationGroup([[(0,1),(2,),(3,)]]); GSym01 # optional - sage.groups + sage: # needs sage.groups sage.modules + sage: GSym01 = PermutationGroup([[(0,1),(2,),(3,)]]); GSym01 Permutation Group with generators [(0,1)] - sage: GASym01 = PermutationGroup([[(0,1),(2,3)]]); GASym01 # optional - sage.groups + sage: GASym01 = PermutationGroup([[(0,1),(2,3)]]); GASym01 Permutation Group with generators [(0,1)(2,3)] sage: from sage.categories.action import Action sage: from sage.structure.element import Matrix - sage: class TensorIndexAction(Action): # optional - sage.modules + sage: class TensorIndexAction(Action): ....: def _act_(self, g, x): ....: if isinstance(x, Matrix): ....: if g(0) == 1: @@ -3827,40 +3875,40 @@ class EquivariantSubobjectConstructionFunctor(ConstructionFunctor): ....: else: ....: return x ....: raise NotImplementedError - sage: M = matrix([[1, 2], [3, 4]]); M # optional - sage.modules + sage: M = matrix([[1, 2], [3, 4]]); M [1 2] [3 4] - sage: GSym01_action = TensorIndexAction(GSym01, M.parent()) # optional - sage.groups sage.modules - sage: GASym01_action = TensorIndexAction(GASym01, M.parent()) # optional - sage.groups sage.modules - sage: GSym01_action.act(GSym01.0, M) # optional - sage.groups sage.modules + sage: GSym01_action = TensorIndexAction(GSym01, M.parent()) + sage: GASym01_action = TensorIndexAction(GASym01, M.parent()) + sage: GSym01_action.act(GSym01.0, M) [1 3] [2 4] - sage: GASym01_action.act(GASym01.0, M) # optional - sage.groups sage.modules + sage: GASym01_action.act(GASym01.0, M) [-1 -3] [-2 -4] - sage: Sym01 = M.parent().invariant_module(GSym01, action=GSym01_action); Sym01 # optional - sage.groups sage.modules + sage: Sym01 = M.parent().invariant_module(GSym01, action=GSym01_action); Sym01 (Permutation Group with generators [(0,1)])-invariant submodule of Full MatrixSpace of 2 by 2 dense matrices over Integer Ring - sage: list(Sym01.basis()) # optional - sage.groups sage.modules + sage: list(Sym01.basis()) [B[0], B[1], B[2]] - sage: list(Sym01.basis().map(Sym01.lift)) # optional - sage.groups sage.modules + sage: list(Sym01.basis().map(Sym01.lift)) [ [1 0] [0 1] [0 0] [0 0], [1 0], [0 1] ] - sage: ASym01 = M.parent().invariant_module(GASym01, action=GASym01_action) # optional - sage.groups sage.modules - sage: ASym01 # optional - sage.groups sage.modules + sage: ASym01 = M.parent().invariant_module(GASym01, action=GASym01_action) + sage: ASym01 (Permutation Group with generators [(0,1)(2,3)])-invariant submodule of Full MatrixSpace of 2 by 2 dense matrices over Integer Ring - sage: list(ASym01.basis()) # optional - sage.groups sage.modules + sage: list(ASym01.basis()) [B[0]] - sage: list(ASym01.basis().map(ASym01.lift)) # optional - sage.groups sage.modules + sage: list(ASym01.basis().map(ASym01.lift)) [ [ 0 1] [-1 0] ] sage: from sage.categories.pushout import pushout - sage: pushout(Sym01, QQ) # optional - sage.groups sage.modules + sage: pushout(Sym01, QQ) (Permutation Group with generators [(0,1)])-invariant submodule of Full MatrixSpace of 2 by 2 dense matrices over Rational Field """ @@ -3869,12 +3917,13 @@ def __init__(self, S, action=operator.mul, side='left', """ EXAMPLES:: - sage: G = SymmetricGroup(3); G.rename('S3') # optional - sage.groups sage.modules - sage: M = FreeModule(ZZ, [1,2,3], prefix='M'); M.rename('M') # optional - sage.groups sage.modules - sage: action = lambda g, x: M.term(g(x)) # optional - sage.groups sage.modules - sage: I = M.invariant_module(G, action_on_basis=action); I # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: G = SymmetricGroup(3); G.rename('S3') + sage: M = FreeModule(ZZ, [1,2,3], prefix='M'); M.rename('M') + sage: action = lambda g, x: M.term(g(x)) + sage: I = M.invariant_module(G, action_on_basis=action); I (S3)-invariant submodule of M - sage: I.construction() # optional - sage.groups sage.modules + sage: I.construction() (EquivariantSubobjectConstructionFunctor, Representation of S3 indexed by {1, 2, 3} over Integer Ring) """ @@ -3893,13 +3942,13 @@ def _apply_functor(self, X): TESTS:: sage: from sage.categories.pushout import EquivariantSubobjectConstructionFunctor - sage: M2 = MatrixSpace(QQ, 2); M2 # optional - sage.groups sage.modules + sage: M2 = MatrixSpace(QQ, 2); M2 # needs sage.modules Full MatrixSpace of 2 by 2 dense matrices over Rational Field - sage: F = EquivariantSubobjectConstructionFunctor(M2, # optional - sage.groups sage.modules + sage: F = EquivariantSubobjectConstructionFunctor(M2, # needs sage.modules ....: operator.mul, 'left', ....: operator.mul, 'right'); F EquivariantSubobjectConstructionFunctor - sage: F(M2) # optional - sage.groups sage.modules + sage: F(M2) # needs sage.modules Traceback (most recent call last): ... NotImplementedError: non-trivial other_action= is not implemented @@ -3918,24 +3967,24 @@ class BlackBoxConstructionFunctor(ConstructionFunctor): EXAMPLES:: sage: from sage.categories.pushout import BlackBoxConstructionFunctor - sage: FG = BlackBoxConstructionFunctor(gap) # optional - sage.libs.gap - sage: FS = BlackBoxConstructionFunctor(singular) # optional - sage.libs.singular - sage: FG # optional - sage.libs.gap + sage: FG = BlackBoxConstructionFunctor(gap) + sage: FS = BlackBoxConstructionFunctor(singular) + sage: FG BlackBoxConstructionFunctor - sage: FG(ZZ) # optional - sage.libs.gap + sage: FG(ZZ) # needs sage.libs.gap Integers - sage: FG(ZZ).parent() # optional - sage.libs.gap + sage: FG(ZZ).parent() # needs sage.libs.gap Gap - sage: FS(QQ['t']) # optional - sage.libs.singular + sage: FS(QQ['t']) # needs sage.libs.singular polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 1 // block 1 : ordering lp // : names t // block 2 : ordering C - sage: FG == FS # optional - sage.libs.gap sage.libs.singular + sage: FG == FS # needs sage.libs.gap sage.libs.singular False - sage: FG == loads(dumps(FG)) # optional - sage.libs.gap + sage: FG == loads(dumps(FG)) # needs sage.libs.gap True """ rank = 100 @@ -3945,11 +3994,11 @@ def __init__(self, box): TESTS:: sage: from sage.categories.pushout import BlackBoxConstructionFunctor - sage: FG = BlackBoxConstructionFunctor(gap) # optional - sage.libs.gap - sage: FM = BlackBoxConstructionFunctor(maxima) # optional - sage.symbolic - sage: FM == FG # optional - sage.libs.gap sage.symbolic + sage: FG = BlackBoxConstructionFunctor(gap) + sage: FM = BlackBoxConstructionFunctor(maxima) # needs sage.symbolic + sage: FM == FG # needs sage.libs.gap sage.symbolic False - sage: FM == loads(dumps(FM)) # optional - sage.symbolic + sage: FM == loads(dumps(FM)) # needs sage.symbolic True """ ConstructionFunctor.__init__(self, Objects(), Objects()) @@ -3966,7 +4015,7 @@ def _apply_functor(self, R): sage: from sage.categories.pushout import BlackBoxConstructionFunctor sage: f = lambda x: x^2 sage: F = BlackBoxConstructionFunctor(f) - sage: F(ZZ) # indirect doctest # optional - sage.modules + sage: F(ZZ) # indirect doctest # needs sage.modules Ambient free module of rank 2 over the principal ideal domain Integer Ring """ @@ -3977,11 +4026,11 @@ def __eq__(self, other): TESTS:: sage: from sage.categories.pushout import BlackBoxConstructionFunctor - sage: FG = BlackBoxConstructionFunctor(gap) # optional - sage.libs.gap - sage: FM = BlackBoxConstructionFunctor(maxima) # optional - sage.symbolic - sage: FM == FG # indirect doctest # optional - sage.libs.gap sage.symbolic + sage: FG = BlackBoxConstructionFunctor(gap) + sage: FM = BlackBoxConstructionFunctor(maxima) # needs sage.symbolic + sage: FM == FG # indirect doctest # needs sage.libs.gap sage.symbolic False - sage: FM == loads(dumps(FM)) # optional - sage.symbolic + sage: FM == loads(dumps(FM)) # needs sage.symbolic True """ if not isinstance(other, BlackBoxConstructionFunctor): @@ -3996,11 +4045,11 @@ def __ne__(self, other): EXAMPLES:: sage: from sage.categories.pushout import BlackBoxConstructionFunctor - sage: FG = BlackBoxConstructionFunctor(gap) # optional - sage.libs.gap - sage: FM = BlackBoxConstructionFunctor(maxima) # optional - sage.symbolic - sage: FM != FG # indirect doctest # optional - sage.libs.gap sage.symbolic + sage: FG = BlackBoxConstructionFunctor(gap) + sage: FM = BlackBoxConstructionFunctor(maxima) # needs sage.symbolic + sage: FM != FG # indirect doctest # needs sage.libs.gap sage.symbolic True - sage: FM != loads(dumps(FM)) # optional - sage.symbolic + sage: FM != loads(dumps(FM)) # needs sage.symbolic False """ return not (self == other) @@ -4059,17 +4108,17 @@ def pushout(R, S): which give us `Frac(Poly_x(Complete_7(Frac(\ZZ))))`:: sage: from sage.categories.pushout import pushout - sage: pushout(Qp(7), Frac(ZZ['x'])) # optional - sage.rings.padics + sage: pushout(Qp(7), Frac(ZZ['x'])) # needs sage.rings.padics Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 Note we get the same thing with :: - sage: pushout(Zp(7), Frac(QQ['x'])) # optional - sage.rings.padics + sage: pushout(Zp(7), Frac(QQ['x'])) # needs sage.rings.padics Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 - sage: pushout(Zp(7)['x'], Frac(QQ['x'])) # optional - sage.rings.padics + sage: pushout(Zp(7)['x'], Frac(QQ['x'])) # needs sage.rings.padics Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 @@ -4087,17 +4136,17 @@ def pushout(R, S): Some other examples:: - sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z']) # optional - sage.rings.padics + sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z']) # needs sage.rings.padics Multivariate Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20 sage: pushout(ZZ['x,y,z'], Frac(ZZ['x'])['y']) Multivariate Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring - sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x'])) # optional - sage.modules + sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x'])) # needs sage.modules Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in x over Real Double Field - sage: pushout(ZZ, MatrixSpace(ZZ[['x']], 3, 3)) # optional - sage.modules + sage: pushout(ZZ, MatrixSpace(ZZ[['x']], 3, 3)) # needs sage.modules Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring sage: pushout(QQ['x,y'], ZZ[['x']]) @@ -4110,20 +4159,22 @@ def pushout(R, S): the :class:`SubspaceFunctor` construction) is only applied if it leads to a valid coercion:: - sage: A = ZZ^2 # optional - sage.modules - sage: V = span([[1, 2]], QQ) # optional - sage.modules - sage: P = sage.categories.pushout.pushout(A, V) # optional - sage.modules - sage: P # optional - sage.modules + sage: # needs sage.modules + sage: A = ZZ^2 + sage: V = span([[1, 2]], QQ) + sage: P = sage.categories.pushout.pushout(A, V) + sage: P Vector space of dimension 2 over Rational Field - sage: P.has_coerce_map_from(A) # optional - sage.modules + sage: P.has_coerce_map_from(A) True - sage: V = (QQ^3).span([[1, 2, 3/4]]) # optional - sage.modules - sage: A = ZZ^3 # optional - sage.modules - sage: pushout(A, V) # optional - sage.modules + sage: # needs sage.modules + sage: V = (QQ^3).span([[1, 2, 3/4]]) + sage: A = ZZ^3 + sage: pushout(A, V) Vector space of dimension 3 over Rational Field - sage: B = A.span([[0, 0, 2/3]]) # optional - sage.modules - sage: pushout(B, V) # optional - sage.modules + sage: B = A.span([[0, 0, 2/3]]) + sage: pushout(B, V) Vector space of degree 3 and dimension 2 over Rational Field User basis matrix: [1 2 0] @@ -4153,26 +4204,26 @@ def pushout(R, S): Even Power Univariate Polynomial Ring in x over Rational Field sage: pushout(EvenPolynomialRing(QQ, 'x'), QQ) Even Power Univariate Polynomial Ring in x over Rational Field - sage: pushout(EvenPolynomialRing(QQ, 'x'), RR) + sage: pushout(EvenPolynomialRing(QQ, 'x'), RR) # needs sage.rings.real_mpfr Even Power Univariate Polynomial Ring in x over Real Field with 53 bits of precision sage: pushout(EvenPolynomialRing(QQ, 'x'), ZZ['x']) Univariate Polynomial Ring in x over Rational Field sage: pushout(EvenPolynomialRing(QQ, 'x'), QQ['x']) Univariate Polynomial Ring in x over Rational Field - sage: pushout(EvenPolynomialRing(QQ, 'x'), RR['x']) + sage: pushout(EvenPolynomialRing(QQ, 'x'), RR['x']) # needs sage.rings.real_mpfr Univariate Polynomial Ring in x over Real Field with 53 bits of precision sage: pushout(EvenPolynomialRing(QQ, 'x'), EvenPolynomialRing(QQ, 'x')) Even Power Univariate Polynomial Ring in x over Rational Field - sage: pushout(EvenPolynomialRing(QQ, 'x'), EvenPolynomialRing(RR, 'x')) + sage: pushout(EvenPolynomialRing(QQ, 'x'), EvenPolynomialRing(RR, 'x')) # needs sage.rings.real_mpfr Even Power Univariate Polynomial Ring in x over Real Field with 53 bits of precision - sage: pushout(EvenPolynomialRing(QQ, 'x')^2, RR^2) # optional - sage.modules + sage: pushout(EvenPolynomialRing(QQ, 'x')^2, RR^2) # needs sage.modules sage.rings.real_mpfr Ambient free module of rank 2 over the principal ideal domain Even Power Univariate Polynomial Ring in x over Real Field with 53 bits of precision - sage: pushout(EvenPolynomialRing(QQ, 'x')^2, RR['x']^2) # optional - sage.modules + sage: pushout(EvenPolynomialRing(QQ, 'x')^2, RR['x']^2) # needs sage.modules sage.rings.real_mpfr Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Real Field with 53 bits of precision @@ -4360,7 +4411,7 @@ def pushout(R, S): (Univariate Polynomial Ring in x over Integer Ring, Univariate Polynomial Ring in y over Integer Ring, Univariate Polynomial Ring in z over Integer Ring) - sage: pushout(CartesianProductPoly((QQ['a,b']['x'], QQ['y'])), # optional - sage.symbolic + sage: pushout(CartesianProductPoly((QQ['a,b']['x'], QQ['y'])), # needs sage.symbolic ....: CartesianProductPoly((ZZ['b,c']['x'], SR['z']))) The Cartesian product of (Univariate Polynomial Ring in x over @@ -4573,14 +4624,14 @@ def pushout_lattice(R, S): EXAMPLES:: sage: from sage.categories.pushout import pushout_lattice - sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) # optional - sage.rings.padics - sage: A.codomain() # optional - sage.rings.padics + sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) # needs sage.rings.padics + sage: A.codomain() # needs sage.rings.padics Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 - sage: A.codomain() is B.codomain() # optional - sage.rings.padics + sage: A.codomain() is B.codomain() # needs sage.rings.padics True - sage: A, B = pushout_lattice(ZZ, MatrixSpace(ZZ[['x']], 3, 3)) # optional - sage.modules - sage: B # optional - sage.modules + sage: A, B = pushout_lattice(ZZ, MatrixSpace(ZZ[['x']], 3, 3)) # needs sage.modules + sage: B # needs sage.modules Identity endomorphism of Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring @@ -4751,7 +4802,7 @@ def construction_tower(R): EXAMPLES:: sage: from sage.categories.pushout import construction_tower - sage: construction_tower(MatrixSpace(FractionField(QQ['t']), 2)) # optional - sage.modules + sage: construction_tower(MatrixSpace(FractionField(QQ['t']), 2)) # needs sage.modules [(None, Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in t over Rational Field), (MatrixFunctor, Fraction Field @@ -4833,7 +4884,7 @@ def type_to_parent(P): Integer Ring sage: type_to_parent(float) Real Double Field - sage: type_to_parent(complex) + sage: type_to_parent(complex) # needs sage.rings.complex_double Complex Double Field sage: type_to_parent(list) Traceback (most recent call last): diff --git a/src/sage/categories/quantum_group_representations.py b/src/sage/categories/quantum_group_representations.py index 08219858ca5..fc8a4697941 100644 --- a/src/sage/categories/quantum_group_representations.py +++ b/src/sage/categories/quantum_group_representations.py @@ -51,7 +51,7 @@ def example(self): sage: from sage.categories.quantum_group_representations import QuantumGroupRepresentations sage: Cat = QuantumGroupRepresentations(ZZ['q'].fraction_field()) - sage: Cat.example() # optional - sage.combinat sage.modules + sage: Cat.example() # needs sage.combinat sage.modules V((2, 1, 0)) """ from sage.algebras.quantum_groups.representations import AdjointRepresentation @@ -96,34 +96,35 @@ def e_on_basis(self, i, b): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import ( # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() - sage: CM = crystals.Tableaux(['D',4], shape=[1]) # optional - sage.combinat sage.modules - sage: VM = MinusculeRepresentation(R, CM) # optional - sage.combinat sage.modules - sage: CA = crystals.Tableaux(['D',4], shape=[1,1]) # optional - sage.combinat sage.modules - sage: VA = AdjointRepresentation(R, CA) # optional - sage.combinat sage.modules - sage: v = tensor([VM.an_element(), VA.an_element()]); v # optional - sage.combinat sage.modules + sage: CM = crystals.Tableaux(['D',4], shape=[1]) + sage: VM = MinusculeRepresentation(R, CM) + sage: CA = crystals.Tableaux(['D',4], shape=[1,1]) + sage: VA = AdjointRepresentation(R, CA) + sage: v = tensor([VM.an_element(), VA.an_element()]); v 4*B[[[1]]] # B[[[1], [2]]] + 4*B[[[1]]] # B[[[1], [3]]] + 6*B[[[1]]] # B[[[2], [3]]] + 4*B[[[2]]] # B[[[1], [2]]] + 4*B[[[2]]] # B[[[1], [3]]] + 6*B[[[2]]] # B[[[2], [3]]] + 6*B[[[3]]] # B[[[1], [2]]] + 6*B[[[3]]] # B[[[1], [3]]] + 9*B[[[3]]] # B[[[2], [3]]] - sage: v.e(1) # indirect doctest # optional - sage.combinat sage.modules + sage: v.e(1) # indirect doctest 4*B[[[1]]] # B[[[1], [2]]] + ((4*q+6)/q)*B[[[1]]] # B[[[1], [3]]] + 6*B[[[1]]] # B[[[2], [3]]] + 6*q*B[[[2]]] # B[[[1], [3]]] + 9*B[[[3]]] # B[[[1], [3]]] - sage: v.e(2) # indirect doctest # optional - sage.combinat sage.modules + sage: v.e(2) # indirect doctest 4*B[[[1]]] # B[[[1], [2]]] + ((6*q+4)/q)*B[[[2]]] # B[[[1], [2]]] + 6*B[[[2]]] # B[[[1], [3]]] + 9*B[[[2]]] # B[[[2], [3]]] + 6*q*B[[[3]]] # B[[[1], [2]]] - sage: v.e(3) # indirect doctest # optional - sage.combinat sage.modules + sage: v.e(3) # indirect doctest 0 - sage: v.e(4) # indirect doctest # optional - sage.combinat sage.modules + sage: v.e(4) # indirect doctest 0 """ K_elt = [self._sets[k].K_on_basis(i, elt, -1) for k,elt in enumerate(b)] @@ -146,38 +147,39 @@ def f_on_basis(self, i, b): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import ( # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() - sage: KM = crystals.KirillovReshetikhin(['B',3,1], 3,1) # optional - sage.combinat sage.modules - sage: VM = MinusculeRepresentation(R, KM) # optional - sage.combinat sage.modules - sage: KA = crystals.KirillovReshetikhin(['B',3,1], 2,1) # optional - sage.combinat sage.modules - sage: VA = AdjointRepresentation(R, KA) # optional - sage.combinat sage.modules - sage: v = tensor([VM.an_element(), VA.an_element()]); v # optional - sage.combinat sage.modules + sage: KM = crystals.KirillovReshetikhin(['B',3,1], 3,1) + sage: VM = MinusculeRepresentation(R, KM) + sage: KA = crystals.KirillovReshetikhin(['B',3,1], 2,1) + sage: VA = AdjointRepresentation(R, KA) + sage: v = tensor([VM.an_element(), VA.an_element()]); v 4*B[[+++, []]] # B[[]] + 4*B[[+++, []]] # B[[[1], [2]]] + 6*B[[+++, []]] # B[[[1], [3]]] + 4*B[[++-, []]] # B[[]] + 4*B[[++-, []]] # B[[[1], [2]]] + 6*B[[++-, []]] # B[[[1], [3]]] + 6*B[[+-+, []]] # B[[]] + 6*B[[+-+, []]] # B[[[1], [2]]] + 9*B[[+-+, []]] # B[[[1], [3]]] - sage: v.f(0) # indirect doctest # optional - sage.combinat sage.modules + sage: v.f(0) # indirect doctest ((4*q^4+4)/q^2)*B[[+++, []]] # B[[[1], [2]]] + ((4*q^4+4)/q^2)*B[[++-, []]] # B[[[1], [2]]] + ((6*q^4+6)/q^2)*B[[+-+, []]] # B[[[1], [2]]] - sage: v.f(1) # indirect doctest # optional - sage.combinat sage.modules + sage: v.f(1) # indirect doctest 6*B[[+++, []]] # B[[[2], [3]]] + 6*B[[++-, []]] # B[[[2], [3]]] + 9*B[[+-+, []]] # B[[[2], [3]]] + 6*B[[-++, []]] # B[[]] + 6*B[[-++, []]] # B[[[1], [2]]] + 9*q^2*B[[-++, []]] # B[[[1], [3]]] - sage: v.f(2) # indirect doctest # optional - sage.combinat sage.modules + sage: v.f(2) # indirect doctest 4*B[[+++, []]] # B[[[1], [3]]] + 4*B[[++-, []]] # B[[[1], [3]]] + 4*B[[+-+, []]] # B[[]] + 4*q^2*B[[+-+, []]] # B[[[1], [2]]] + ((6*q^2+6)/q^2)*B[[+-+, []]] # B[[[1], [3]]] - sage: v.f(3) # indirect doctest # optional - sage.combinat sage.modules + sage: v.f(3) # indirect doctest 6*B[[+++, []]] # B[[[1], [0]]] + 4*B[[++-, []]] # B[[]] + 4*B[[++-, []]] # B[[[1], [2]]] @@ -209,22 +211,23 @@ def K_on_basis(self, i, b, power=1): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import ( # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() - sage: CM = crystals.Tableaux(['A',2], shape=[1]) # optional - sage.combinat sage.modules - sage: VM = MinusculeRepresentation(R, CM) # optional - sage.combinat sage.modules - sage: CA = crystals.Tableaux(['A',2], shape=[2,1]) # optional - sage.combinat sage.modules - sage: VA = AdjointRepresentation(R, CA) # optional - sage.combinat sage.modules - sage: v = tensor([sum(VM.basis()), VA.module_generator()]); v # optional - sage.combinat sage.modules + sage: CM = crystals.Tableaux(['A',2], shape=[1]) + sage: VM = MinusculeRepresentation(R, CM) + sage: CA = crystals.Tableaux(['A',2], shape=[2,1]) + sage: VA = AdjointRepresentation(R, CA) + sage: v = tensor([sum(VM.basis()), VA.module_generator()]); v B[[[1]]] # B[[[1, 1], [2]]] + B[[[2]]] # B[[[1, 1], [2]]] + B[[[3]]] # B[[[1, 1], [2]]] - sage: v.K(1) # indirect doctest # optional - sage.combinat sage.modules + sage: v.K(1) # indirect doctest q^2*B[[[1]]] # B[[[1, 1], [2]]] + B[[[2]]] # B[[[1, 1], [2]]] + q*B[[[3]]] # B[[[1, 1], [2]]] - sage: v.K(2, -1) # indirect doctest # optional - sage.combinat sage.modules + sage: v.K(2, -1) # indirect doctest 1/q*B[[[1]]] # B[[[1, 1], [2]]] + 1/q^2*B[[[2]]] # B[[[1, 1], [2]]] + B[[[3]]] # B[[[1, 1], [2]]] @@ -241,24 +244,25 @@ def tensor(*factors): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import ( # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) sage: R = ZZ['q'].fraction_field() - sage: CM = crystals.Tableaux(['D',4], shape=[1]) # optional - sage.combinat sage.modules - sage: CA = crystals.Tableaux(['D',4], shape=[1,1]) # optional - sage.combinat sage.modules - sage: V = MinusculeRepresentation(R, CM) # optional - sage.combinat sage.modules - sage: V.tensor(V, V) # optional - sage.combinat sage.modules + sage: CM = crystals.Tableaux(['D',4], shape=[1]) + sage: CA = crystals.Tableaux(['D',4], shape=[1,1]) + sage: V = MinusculeRepresentation(R, CM) + sage: V.tensor(V, V) V((1, 0, 0, 0)) # V((1, 0, 0, 0)) # V((1, 0, 0, 0)) - sage: A = MinusculeRepresentation(R, CA) # optional - sage.combinat sage.modules - sage: V.tensor(A) # optional - sage.combinat sage.modules + sage: A = MinusculeRepresentation(R, CA) + sage: V.tensor(A) V((1, 0, 0, 0)) # V((1, 1, 0, 0)) - sage: B = crystals.Tableaux(['A',2], shape=[1]) # optional - sage.combinat sage.modules - sage: W = MinusculeRepresentation(R, B) # optional - sage.combinat sage.modules - sage: tensor([W,V]) # optional - sage.combinat sage.modules + sage: B = crystals.Tableaux(['A',2], shape=[1]) + sage: W = MinusculeRepresentation(R, B) + sage: tensor([W,V]) Traceback (most recent call last): ... ValueError: all factors must be of the same Cartan type - sage: tensor([V,A,W]) # optional - sage.combinat sage.modules + sage: tensor([V,A,W]) Traceback (most recent call last): ... ValueError: all factors must be of the same Cartan type @@ -279,15 +283,16 @@ def e(self, i): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation # optional - sage.combinat sage.modules - sage: C = crystals.Tableaux(['G',2], shape=[1,1]) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = AdjointRepresentation(R, C) # optional - sage.combinat sage.modules - sage: v = V.an_element(); v # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation + sage: C = crystals.Tableaux(['G',2], shape=[1,1]) + sage: R = ZZ['q'].fraction_field() + sage: V = AdjointRepresentation(R, C) + sage: v = V.an_element(); v 2*B[[[1], [2]]] + 2*B[[[1], [3]]] + 3*B[[[2], [3]]] - sage: v.e(1) # optional - sage.combinat sage.modules + sage: v.e(1) ((3*q^4+3*q^2+3)/q^2)*B[[[1], [3]]] - sage: v.e(2) # optional - sage.combinat sage.modules + sage: v.e(2) 2*B[[[1], [2]]] """ F = self.parent() @@ -305,21 +310,22 @@ def f(self, i): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation # optional - sage.combinat sage.modules - sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = AdjointRepresentation(R, K) # optional - sage.combinat sage.modules - sage: v = V.an_element(); v # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation + sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1) + sage: R = ZZ['q'].fraction_field() + sage: V = AdjointRepresentation(R, K) + sage: v = V.an_element(); v 2*B[[]] + 2*B[[[1], [2]]] + 3*B[[[1], [3]]] - sage: v.f(0) # optional - sage.combinat sage.modules + sage: v.f(0) ((2*q^2+2)/q)*B[[[1], [2]]] - sage: v.f(1) # optional - sage.combinat sage.modules + sage: v.f(1) 3*B[[[2], [3]]] - sage: v.f(2) # optional - sage.combinat sage.modules + sage: v.f(2) 2*B[[[1], [3]]] - sage: v.f(3) # optional - sage.combinat sage.modules + sage: v.f(3) 3*B[[[1], [4]]] - sage: v.f(4) # optional - sage.combinat sage.modules + sage: v.f(4) 3*B[[[1], [-4]]] """ F = self.parent() @@ -338,19 +344,20 @@ def K(self, i, power=1): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation # optional - sage.combinat sage.modules - sage: K = crystals.KirillovReshetikhin(['D',4,2], 1,1) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = AdjointRepresentation(R, K) # optional - sage.combinat sage.modules - sage: v = V.an_element(); v # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import AdjointRepresentation + sage: K = crystals.KirillovReshetikhin(['D',4,2], 1,1) + sage: R = ZZ['q'].fraction_field() + sage: V = AdjointRepresentation(R, K) + sage: v = V.an_element(); v 2*B[[]] + 2*B[[[1]]] + 3*B[[[2]]] - sage: v.K(0) # optional - sage.combinat sage.modules + sage: v.K(0) 2*B[[]] + 2/q^2*B[[[1]]] + 3*B[[[2]]] - sage: v.K(1) # optional - sage.combinat sage.modules + sage: v.K(1) 2*B[[]] + 2*q^2*B[[[1]]] + 3/q^2*B[[[2]]] - sage: v.K(1, 2) # optional - sage.combinat sage.modules + sage: v.K(1, 2) 2*B[[]] + 2*q^4*B[[[1]]] + 3/q^4*B[[[2]]] - sage: v.K(1, -1) # optional - sage.combinat sage.modules + sage: v.K(1, -1) 2*B[[]] + 2/q^2*B[[[1]]] + 3*q^2*B[[[2]]] """ F = self.parent() @@ -388,12 +395,13 @@ def cartan_type(self): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation # optional - sage.combinat sage.modules - sage: C = crystals.Tableaux(['C',2], shape=[1]) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = MinusculeRepresentation(R, C) # optional - sage.combinat sage.modules - sage: T = tensor([V,V]) # optional - sage.combinat sage.modules - sage: T.cartan_type() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation + sage: C = crystals.Tableaux(['C',2], shape=[1]) + sage: R = ZZ['q'].fraction_field() + sage: V = MinusculeRepresentation(R, C) + sage: T = tensor([V,V]) + sage: T.cartan_type() ['C', 2] """ return self._sets[0].cartan_type() @@ -407,18 +415,19 @@ def _test_representation(self, tester=None, **options): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import ( # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import ( ....: MinusculeRepresentation, AdjointRepresentation) - sage: C = crystals.Tableaux(['G',2], shape=[1,1]) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = AdjointRepresentation(R, C) # optional - sage.combinat sage.modules - sage: V._test_representation() # optional - sage.combinat sage.modules + sage: C = crystals.Tableaux(['G',2], shape=[1,1]) + sage: R = ZZ['q'].fraction_field() + sage: V = AdjointRepresentation(R, C) + sage: V._test_representation() We verify that ``C`` does not define a minuscule representation:: - sage: M = MinusculeRepresentation(R, C) # optional - sage.combinat sage.modules - sage: M._test_representation() # optional - sage.combinat sage.modules + sage: M = MinusculeRepresentation(R, C) # needs sage.combinat sage.modules + sage: M._test_representation() # needs sage.combinat sage.modules Traceback (most recent call last): ... AssertionError: [e,f] = (K-K^-1)/(q_i-q_i^-1) -- i: 1 j: 1 @@ -489,11 +498,12 @@ def cartan_type(self): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation # optional - sage.combinat sage.modules - sage: C = crystals.Tableaux(['C',4], shape=[1]) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = MinusculeRepresentation(R, C) # optional - sage.combinat sage.modules - sage: V.cartan_type() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation + sage: C = crystals.Tableaux(['C',4], shape=[1]) + sage: R = ZZ['q'].fraction_field() + sage: V = MinusculeRepresentation(R, C) + sage: V.cartan_type() ['C', 4] """ @@ -504,11 +514,12 @@ def index_set(self): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation # optional - sage.combinat sage.modules - sage: C = crystals.Tableaux(['C',4], shape=[1]) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = MinusculeRepresentation(R, C) # optional - sage.combinat sage.modules - sage: V.index_set() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation + sage: C = crystals.Tableaux(['C',4], shape=[1]) + sage: R = ZZ['q'].fraction_field() + sage: V = MinusculeRepresentation(R, C) + sage: V.index_set() (1, 2, 3, 4) """ return self.cartan_type().index_set() @@ -519,11 +530,12 @@ def q(self): EXAMPLES:: - sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation # optional - sage.combinat sage.modules - sage: C = crystals.Tableaux(['C',4], shape=[1]) # optional - sage.combinat sage.modules - sage: R = ZZ['q'].fraction_field() # optional - sage.combinat sage.modules - sage: V = MinusculeRepresentation(R, C) # optional - sage.combinat sage.modules - sage: V.q() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation + sage: C = crystals.Tableaux(['C',4], shape=[1]) + sage: R = ZZ['q'].fraction_field() + sage: V = MinusculeRepresentation(R, C) + sage: V.q() q """ return self._q diff --git a/src/sage/categories/quotient_fields.py b/src/sage/categories/quotient_fields.py index 2a79049bd62..f5d8495489d 100644 --- a/src/sage/categories/quotient_fields.py +++ b/src/sage/categories/quotient_fields.py @@ -72,20 +72,21 @@ def gcd(self, other): EXAMPLES:: + sage: # needs sage.libs.pari sage: R. = QQ['x'] sage: p = (1+x)^3*(1+2*x^2)/(1-x^5) sage: q = (1+x)^2*(1+3*x^2)/(1-x^4) - sage: factor(p) # optional - sage.libs.pari + sage: factor(p) (-2) * (x - 1)^-1 * (x + 1)^3 * (x^2 + 1/2) * (x^4 + x^3 + x^2 + x + 1)^-1 - sage: factor(q) # optional - sage.libs.pari + sage: factor(q) (-3) * (x - 1)^-1 * (x + 1) * (x^2 + 1)^-1 * (x^2 + 1/3) sage: gcd(p, q) (x + 1)/(x^7 + x^5 - x^2 - 1) - sage: factor(gcd(p, q)) # optional - sage.libs.pari + sage: factor(gcd(p, q)) (x - 1)^-1 * (x + 1) * (x^2 + 1)^-1 * (x^4 + x^3 + x^2 + x + 1)^-1 - sage: factor(gcd(p, 1 + x)) # optional - sage.libs.pari + sage: factor(gcd(p, 1 + x)) (x - 1)^-1 * (x + 1) * (x^4 + x^3 + x^2 + x + 1)^-1 - sage: factor(gcd(1 + x, q)) # optional - sage.libs.pari + sage: factor(gcd(1 + x, q)) (x - 1)^-1 * (x + 1) * (x^2 + 1)^-1 TESTS: @@ -93,25 +94,26 @@ def gcd(self, other): The following tests that the fraction field returns a correct gcd even if the base ring does not provide lcm and gcd:: - sage: R = ZZ.extension(x^2 + 1, names='i') # optional - sage.rings.number_field - sage: i = R.1 # optional - sage.rings.number_field - sage: gcd(5, 3 + 4*i) # optional - sage.rings.number_field + sage: # needs sage.libs.pari sage.rings.number_field + sage: R = ZZ.extension(x^2 + 1, names='i') + sage: i = R.1 + sage: gcd(5, 3 + 4*i) -i - 2 - sage: P. = R[] # optional - sage.rings.number_field - sage: gcd(t, i) # optional - sage.rings.number_field + sage: P. = R[] + sage: gcd(t, i) Traceback (most recent call last): ... NotImplementedError: Gaussian Integers in Number Field in i with defining polynomial x^2 + 1 does not provide a gcd implementation for univariate polynomials - sage: q = t/(t + 1); q.parent() # optional - sage.rings.number_field + sage: q = t/(t + 1); q.parent() Fraction Field of Univariate Polynomial Ring in t over Gaussian Integers in Number Field in i with defining polynomial x^2 + 1 - sage: gcd(q, q) # optional - sage.rings.number_field + sage: gcd(q, q) 1 - sage: q.gcd(0) # optional - sage.rings.number_field + sage: q.gcd(0) 1 - sage: (q*0).gcd(0) # optional - sage.rings.number_field + sage: (q*0).gcd(0) 0 """ P = self.parent() @@ -177,18 +179,19 @@ def lcm(self, other): Some more involved examples:: + sage: # needs sage.libs.pari sage: R. = QQ[] sage: p = (1+x)^3*(1+2*x^2)/(1-x^5) sage: q = (1+x)^2*(1+3*x^2)/(1-x^4) - sage: factor(p) # optional - sage.libs.pari + sage: factor(p) (-2) * (x - 1)^-1 * (x + 1)^3 * (x^2 + 1/2) * (x^4 + x^3 + x^2 + x + 1)^-1 - sage: factor(q) # optional - sage.libs.pari + sage: factor(q) (-3) * (x - 1)^-1 * (x + 1) * (x^2 + 1)^-1 * (x^2 + 1/3) - sage: factor(lcm(p, q)) # optional - sage.libs.pari + sage: factor(lcm(p, q)) (x - 1)^-1 * (x + 1)^3 * (x^2 + 1/3) * (x^2 + 1/2) - sage: factor(lcm(p, 1 + x)) # optional - sage.libs.pari + sage: factor(lcm(p, 1 + x)) (x + 1)^3 * (x^2 + 1/2) - sage: factor(lcm(1 + x, q)) # optional - sage.libs.pari + sage: factor(lcm(1 + x, q)) (x + 1) * (x^2 + 1/3) TESTS: @@ -196,23 +199,24 @@ def lcm(self, other): The following tests that the fraction field returns a correct lcm even if the base ring does not provide lcm and gcd:: - sage: R = ZZ.extension(x^2+1, names='i') # optional - sage.rings.number_field - sage: i = R.1 # optional - sage.rings.number_field - sage: P. = R[] # optional - sage.rings.number_field - sage: lcm(t, i) # optional - sage.rings.number_field + sage: # needs sage.libs.pari sage.rings.number_field + sage: R = ZZ.extension(x^2+1, names='i') + sage: i = R.1 + sage: P. = R[] + sage: lcm(t, i) Traceback (most recent call last): ... NotImplementedError: Gaussian Integers in Number Field in i with defining polynomial x^2 + 1 does not provide a gcd implementation for univariate polynomials - sage: q = t/(t + 1); q.parent() # optional - sage.rings.number_field + sage: q = t/(t + 1); q.parent() Fraction Field of Univariate Polynomial Ring in t over Gaussian Integers in Number Field in i with defining polynomial x^2 + 1 - sage: lcm(q, q) # optional - sage.rings.number_field + sage: lcm(q, q) 1 - sage: q.lcm(0) # optional - sage.rings.number_field + sage: q.lcm(0) 0 - sage: (q*0).lcm(0) # optional - sage.rings.number_field + sage: (q*0).lcm(0) 0 Check that it is possible to take lcm of a rational and an integer @@ -272,9 +276,9 @@ def xgcd(self, other): sage: R. = QQ['x'] sage: p = (1+x)^3*(1+2*x^2)/(1-x^5) sage: q = (1+x)^2*(1+3*x^2)/(1-x^4) - sage: factor(p) # optional - sage.libs.pari + sage: factor(p) # needs sage.libs.pari (-2) * (x - 1)^-1 * (x + 1)^3 * (x^2 + 1/2) * (x^4 + x^3 + x^2 + x + 1)^-1 - sage: factor(q) # optional - sage.libs.pari + sage: factor(q) # needs sage.libs.pari (-3) * (x - 1)^-1 * (x + 1) * (x^2 + 1)^-1 * (x^2 + 1/3) sage: g, s, t = xgcd(p, q) sage: g @@ -284,21 +288,22 @@ def xgcd(self, other): An example without a well defined gcd or xgcd on its base ring:: - sage: K = QuadraticField(5) # optional - sage.rings.number_field - sage: O = K.maximal_order() # optional - sage.rings.number_field - sage: R = PolynomialRing(O, 'x') # optional - sage.rings.number_field - sage: F = R.fraction_field() # optional - sage.rings.number_field - sage: x = F.gen(0) # optional - sage.rings.number_field - sage: x.gcd(x+1) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K = QuadraticField(5) + sage: O = K.maximal_order() + sage: R = PolynomialRing(O, 'x') + sage: F = R.fraction_field() + sage: x = F.gen(0) + sage: x.gcd(x+1) 1 - sage: x.xgcd(x+1) # optional - sage.rings.number_field + sage: x.xgcd(x+1) (1, 1/x, 0) - sage: zero = F.zero() # optional - sage.rings.number_field - sage: zero.gcd(x) # optional - sage.rings.number_field + sage: zero = F.zero() + sage: zero.gcd(x) 1 - sage: zero.xgcd(x) # optional - sage.rings.number_field + sage: zero.xgcd(x) (1, 0, 1/x) - sage: zero.xgcd(zero) # optional - sage.rings.number_field + sage: zero.xgcd(zero) (0, 0, 0) """ P = self.parent() @@ -346,14 +351,14 @@ def factor(self, *args, **kwds): sage: K. = QQ[] sage: f = (x^3+x)/(x-3) - sage: f.factor() # optional - sage.libs.pari + sage: f.factor() # needs sage.libs.pari (x - 3)^-1 * x * (x^2 + 1) Here is an example to show that :trac:`7868` has been resolved:: - sage: R. = GF(2)[] # optional - sage.rings.finite_rings - sage: f = x*y/(x+y) # optional - sage.rings.finite_rings - sage: f.factor() # optional - sage.rings.finite_rings + sage: R. = GF(2)[] + sage: f = x*y/(x+y) + sage: f.factor() # needs sage.rings.finite_rings (x + y)^-1 * y * x """ return (self.numerator().factor(*args, **kwds) / @@ -361,21 +366,20 @@ def factor(self, *args, **kwds): def partial_fraction_decomposition(self, decompose_powers=True): """ - Decomposes fraction field element into a whole part and a list of + Decompose fraction field element into a whole part and a list of fraction field elements over prime power denominators. The sum will be equal to the original fraction. INPUT: - - decompose_powers -- whether to decompose prime power - denominators as opposed to having a single - term for each irreducible factor of the - denominator (default: True) + - ``decompose_powers`` -- boolean (default: ``True``); + whether to decompose prime power denominators as opposed to having + a single term for each irreducible factor of the denominator OUTPUT: - - Partial fraction decomposition of self over the base ring. + Partial fraction decomposition of ``self`` over the base ring. AUTHORS: @@ -383,53 +387,55 @@ def partial_fraction_decomposition(self, decompose_powers=True): EXAMPLES:: + sage: # needs sage.libs.pari sage: S. = QQ[] sage: q = 1/(t+1) + 2/(t+2) + 3/(t-3); q (6*t^2 + 4*t - 6)/(t^3 - 7*t - 6) - sage: whole, parts = q.partial_fraction_decomposition(); parts # optional - sage.libs.pari + sage: whole, parts = q.partial_fraction_decomposition(); parts [3/(t - 3), 1/(t + 1), 2/(t + 2)] - sage: sum(parts) == q # optional - sage.libs.pari + sage: sum(parts) == q True - sage: q = 1/(t^3+1) + 2/(t^2+2) + 3/(t-3)^5 # optional - sage.libs.pari - sage: whole, parts = q.partial_fraction_decomposition(); parts # optional - sage.libs.pari + sage: q = 1/(t^3+1) + 2/(t^2+2) + 3/(t-3)^5 + sage: whole, parts = q.partial_fraction_decomposition(); parts [1/3/(t + 1), 3/(t^5 - 15*t^4 + 90*t^3 - 270*t^2 + 405*t - 243), (-1/3*t + 2/3)/(t^2 - t + 1), 2/(t^2 + 2)] - sage: sum(parts) == q # optional - sage.libs.pari + sage: sum(parts) == q True - sage: q = 2*t / (t + 3)^2 # optional - sage.libs.pari - sage: q.partial_fraction_decomposition() # optional - sage.libs.pari + sage: q = 2*t / (t + 3)^2 + sage: q.partial_fraction_decomposition() (0, [2/(t + 3), -6/(t^2 + 6*t + 9)]) - sage: for p in q.partial_fraction_decomposition()[1]: # optional - sage.libs.pari + sage: for p in q.partial_fraction_decomposition()[1]: ....: print(p.factor()) (2) * (t + 3)^-1 (-6) * (t + 3)^-2 - sage: q.partial_fraction_decomposition(decompose_powers=False) # optional - sage.libs.pari + sage: q.partial_fraction_decomposition(decompose_powers=False) (0, [2*t/(t^2 + 6*t + 9)]) We can decompose over a given algebraic extension:: - sage: R. = QQ[sqrt(2)][] # optional - sage.rings.number_field sage.symbolic - sage: r = 1/(x^4+1) # optional - sage.rings.number_field sage.symbolic - sage: r.partial_fraction_decomposition() # optional - sage.rings.number_field sage.symbolic + sage: R. = QQ[sqrt(2)][] # needs sage.rings.number_field sage.symbolic + sage: r = 1/(x^4+1) # needs sage.rings.number_field sage.symbolic + sage: r.partial_fraction_decomposition() # needs sage.rings.number_field sage.symbolic (0, [(-1/4*sqrt2*x + 1/2)/(x^2 - sqrt2*x + 1), (1/4*sqrt2*x + 1/2)/(x^2 + sqrt2*x + 1)]) - sage: R. = QQ[I][] # of QQ[sqrt(-1)] # optional - sage.rings.number_field - sage: r = 1/(x^4+1) # optional - sage.rings.number_field - sage: r.partial_fraction_decomposition() # optional - sage.rings.number_field + sage: R. = QQ[I][] # of QQ[sqrt(-1)] # needs sage.rings.number_field sage.symbolic + sage: r = 1/(x^4+1) # needs sage.rings.number_field sage.symbolic + sage: r.partial_fraction_decomposition() # needs sage.rings.number_field sage.symbolic (0, [(-1/2*I)/(x^2 - I), 1/2*I/(x^2 + I)]) We can also ask Sage to find the least extension where the denominator factors in linear terms:: + sage: # needs sage.rings.number_field sage: R. = QQ[] sage: r = 1/(x^4+2) - sage: N = r.denominator().splitting_field('a'); N # optional - sage.rings.number_field + sage: N = r.denominator().splitting_field('a'); N Number Field in a with defining polynomial x^8 - 8*x^6 + 28*x^4 + 16*x^2 + 36 - sage: R1. = N[] # optional - sage.rings.number_field - sage: r1 = 1/(x1^4+2) # optional - sage.rings.number_field - sage: r1.partial_fraction_decomposition() # optional - sage.rings.number_field + sage: R1. = N[] + sage: r1 = 1/(x1^4+2) + sage: r1.partial_fraction_decomposition() (0, [(-1/224*a^6 + 13/448*a^4 - 5/56*a^2 - 25/224)/(x1 - 1/28*a^6 + 13/56*a^4 - 5/7*a^2 - 25/28), (1/224*a^6 - 13/448*a^4 + 5/56*a^2 + 25/224)/(x1 + 1/28*a^6 - 13/56*a^4 + 5/7*a^2 + 25/28), @@ -438,9 +444,9 @@ def partial_fraction_decomposition(self, decompose_powers=True): Or we may work directly over an algebraically closed field:: - sage: R. = QQbar[] # optional - sage.rings.number_field - sage: r = 1/(x^4+1) # optional - sage.rings.number_field - sage: r.partial_fraction_decomposition() # optional - sage.rings.number_field + sage: R. = QQbar[] # needs sage.rings.number_field + sage: r = 1/(x^4+1) # needs sage.rings.number_field + sage: r.partial_fraction_decomposition() # needs sage.rings.number_field (0, [(-0.1767766952966369? - 0.1767766952966369?*I)/(x - 0.7071067811865475? - 0.7071067811865475?*I), (-0.1767766952966369? + 0.1767766952966369?*I)/(x - 0.7071067811865475? + 0.7071067811865475?*I), @@ -449,14 +455,15 @@ def partial_fraction_decomposition(self, decompose_powers=True): We do the best we can over inexact fields:: + sage: # needs sage.rings.number_field sage.rings.real_mpfr sage: R. = RealField(20)[] sage: q = 1/(x^2 + x + 2)^2 + 1/(x-1); q (x^4 + 2.0000*x^3 + 5.0000*x^2 + 5.0000*x + 3.0000)/(x^5 + x^4 + 3.0000*x^3 - x^2 - 4.0000) - sage: whole, parts = q.partial_fraction_decomposition(); parts # optional - sage.rings.number_field + sage: whole, parts = q.partial_fraction_decomposition(); parts [1.0000/(x - 1.0000), 1.0000/(x^4 + 2.0000*x^3 + 5.0000*x^2 + 4.0000*x + 4.0000)] - sage: sum(parts) # optional - sage.rings.number_field + sage: sum(parts) (x^4 + 2.0000*x^3 + 5.0000*x^2 + 5.0000*x + 3.0000)/(x^5 + x^4 + 3.0000*x^3 - x^2 - 4.0000) @@ -466,23 +473,23 @@ def partial_fraction_decomposition(self, decompose_powers=True): sage: R. = ZZ[] sage: q = x^2/(x-1) - sage: q.partial_fraction_decomposition() # optional - sage.libs.pari + sage: q.partial_fraction_decomposition() # needs sage.libs.pari (x + 1, [1/(x - 1)]) sage: q = x^10/(x-1)^5 - sage: whole, parts = q.partial_fraction_decomposition() # optional - sage.libs.pari - sage: whole + sum(parts) == q # optional - sage.libs.pari + sage: whole, parts = q.partial_fraction_decomposition() # needs sage.libs.pari + sage: whole + sum(parts) == q # needs sage.libs.pari True And also over finite fields (see :trac:`6052`, :trac:`9945`):: - sage: R. = GF(2)[] # optional - sage.rings.finite_rings - sage: q = (x+1)/(x^3+x+1) # optional - sage.rings.finite_rings - sage: q.partial_fraction_decomposition() # optional - sage.rings.finite_rings + sage: R. = GF(2)[] + sage: q = (x+1)/(x^3+x+1) + sage: q.partial_fraction_decomposition() # needs sage.libs.pari (0, [(x + 1)/(x^3 + x + 1)]) - sage: R. = GF(11)[] # optional - sage.rings.finite_rings - sage: q = x + 1 + 1/(x+1) + x^2/(x^3 + 2*x + 9) # optional - sage.rings.finite_rings - sage: q.partial_fraction_decomposition() # optional - sage.rings.finite_rings + sage: R. = GF(11)[] + sage: q = x + 1 + 1/(x+1) + x^2/(x^3 + 2*x + 9) + sage: q.partial_fraction_decomposition() # needs sage.libs.pari (x + 1, [1/(x + 1), x^2/(x^3 + 2*x + 9)]) And even the rationals:: @@ -496,7 +503,7 @@ def partial_fraction_decomposition(self, decompose_powers=True): sage: S. = QQ[] sage: r = t / (t^3+1)^5 - sage: r.partial_fraction_decomposition() # optional - sage.libs.pari + sage: r.partial_fraction_decomposition() # needs sage.libs.pari (0, [-35/729/(t + 1), -35/729/(t^2 + 2*t + 1), @@ -508,37 +515,38 @@ def partial_fraction_decomposition(self, decompose_powers=True): (-1/81*t + 5/81)/(t^6 - 3*t^5 + 6*t^4 - 7*t^3 + 6*t^2 - 3*t + 1), (-2/27*t + 1/9)/(t^8 - 4*t^7 + 10*t^6 - 16*t^5 + 19*t^4 - 16*t^3 + 10*t^2 - 4*t + 1), (-2/27*t + 1/27)/(t^10 - 5*t^9 + 15*t^8 - 30*t^7 + 45*t^6 - 51*t^5 + 45*t^4 - 30*t^3 + 15*t^2 - 5*t + 1)]) - sage: sum(r.partial_fraction_decomposition()[1]) == r # optional - sage.libs.pari + sage: sum(r.partial_fraction_decomposition()[1]) == r # needs sage.libs.pari True Some special cases:: sage: R = Frac(QQ['x']); x = R.gen() - sage: x.partial_fraction_decomposition() # optional - sage.libs.pari + sage: x.partial_fraction_decomposition() (x, []) - sage: R(0).partial_fraction_decomposition() # optional - sage.libs.pari + sage: R(0).partial_fraction_decomposition() (0, []) - sage: R(1).partial_fraction_decomposition() # optional - sage.libs.pari + sage: R(1).partial_fraction_decomposition() (1, []) - sage: (1/x).partial_fraction_decomposition() # optional - sage.libs.pari + sage: (1/x).partial_fraction_decomposition() # needs sage.libs.pari (0, [1/x]) - sage: (1/x+1/x^3).partial_fraction_decomposition() # optional - sage.libs.pari + sage: (1/x+1/x^3).partial_fraction_decomposition() # needs sage.libs.pari (0, [1/x, 1/x^3]) This was fixed in :trac:`16240`:: + sage: # needs sage.libs.pari sage: R. = QQ['x'] sage: p = 1/(-x + 1) - sage: whole,parts = p.partial_fraction_decomposition() # optional - sage.libs.pari - sage: p == sum(parts) # optional - sage.libs.pari + sage: whole, parts = p.partial_fraction_decomposition() + sage: p == sum(parts) True sage: p = 3/(-x^4 + 1) - sage: whole,parts = p.partial_fraction_decomposition() # optional - sage.libs.pari - sage: p == sum(parts) # optional - sage.libs.pari + sage: whole, parts = p.partial_fraction_decomposition() + sage: p == sum(parts) True sage: p = (6*x^2 - 9*x + 5)/(-x^3 + 3*x^2 - 3*x + 1) - sage: whole,parts = p.partial_fraction_decomposition() # optional - sage.libs.pari - sage: p == sum(parts) # optional - sage.libs.pari + sage: whole, parts = p.partial_fraction_decomposition() + sage: p == sum(parts) True """ denom = self.denominator() diff --git a/src/sage/categories/realizations.py b/src/sage/categories/realizations.py index 0207b66a4be..1c40e597676 100644 --- a/src/sage/categories/realizations.py +++ b/src/sage/categories/realizations.py @@ -71,9 +71,9 @@ def Realizations(self): The category of realizations of a given algebra:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.Realizations() # optional - sage.combinat sage.modules + sage: A.Realizations() # needs sage.modules Category of realizations of The subset algebra of {1, 2, 3} over Rational Field @@ -102,6 +102,7 @@ def Realizations(self): else: return getattr(self.__class__, "Realizations")(self) + Category.Realizations = Realizations class Category_realization_of_parent(Category_over_base, BindableClass): @@ -116,7 +117,7 @@ class Category_realization_of_parent(Category_over_base, BindableClass): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field The role of this base class is to implement some technical goodies, like @@ -124,7 +125,7 @@ class Category_realization_of_parent(Category_over_base, BindableClass): implemented as a nested class in ``A`` (see the :mod:`code of the example `):: - sage: C = A.Realizations(); C # optional - sage.combinat sage.modules + sage: C = A.Realizations(); C # needs sage.modules Category of realizations of The subset algebra of {1, 2, 3} over Rational Field @@ -134,17 +135,18 @@ def __init__(self, parent_with_realization): """ TESTS:: + sage: # needs sage.combinat sage.modules sage: from sage.categories.realizations import Category_realization_of_parent - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A The subset algebra of {1, 2, 3} over Rational Field - sage: C = A.Realizations(); C # optional - sage.combinat sage.modules + sage: C = A.Realizations(); C Category of realizations of The subset algebra of {1, 2, 3} over Rational Field - sage: isinstance(C, Category_realization_of_parent) # optional - sage.combinat sage.modules + sage: isinstance(C, Category_realization_of_parent) True - sage: C.parent_with_realization # optional - sage.combinat sage.modules + sage: C.parent_with_realization The subset algebra of {1, 2, 3} over Rational Field - sage: TestSuite(C).run(skip=["_test_category_over_bases"]) # optional - sage.combinat sage.modules + sage: TestSuite(C).run(skip=["_test_category_over_bases"]) .. TODO:: @@ -167,8 +169,8 @@ def _get_name(self): sage: from sage.categories.realizations import Category_realization_of_parent sage: class MultiplicativeBasesOnPrimitiveElements(Category_realization_of_parent): ....: def super_categories(self): return [Objects()] - sage: Sym = SymmetricFunctions(QQ); Sym.rename("Sym") # optional - sage.combinat - sage: MultiplicativeBasesOnPrimitiveElements(Sym)._get_name() # optional - sage.combinat + sage: Sym = SymmetricFunctions(QQ); Sym.rename("Sym") # needs sage.combinat sage.modules + sage: MultiplicativeBasesOnPrimitiveElements(Sym)._get_name() # needs sage.combinat sage.modules 'multiplicative bases on primitive elements' """ import re @@ -185,10 +187,10 @@ def _repr_object_names(self): sage: from sage.categories.realizations import Category_realization_of_parent sage: class MultiplicativeBasesOnPrimitiveElements(Category_realization_of_parent): ....: def super_categories(self): return [Objects()] - sage: Sym = SymmetricFunctions(QQ); Sym.rename("Sym") # optional - sage.combinat - sage: C = MultiplicativeBasesOnPrimitiveElements(Sym); C # optional - sage.combinat + sage: Sym = SymmetricFunctions(QQ); Sym.rename("Sym") # needs sage.combinat sage.modules + sage: C = MultiplicativeBasesOnPrimitiveElements(Sym); C # needs sage.combinat sage.modules Category of multiplicative bases on primitive elements of Sym - sage: C._repr_object_names() # optional - sage.combinat + sage: C._repr_object_names() # needs sage.combinat sage.modules 'multiplicative bases on primitive elements of Sym' """ return "{} of {}".format(self._get_name(), self.base()) diff --git a/src/sage/categories/regular_crystals.py b/src/sage/categories/regular_crystals.py index afad9e78c22..297420e5083 100644 --- a/src/sage/categories/regular_crystals.py +++ b/src/sage/categories/regular_crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.graphs +# sage.doctest: needs sage.combinat sage.graphs r""" Regular Crystals """ @@ -310,7 +310,7 @@ def _test_stembridge_local_axioms(self, index_set=None, verbose=False, complete= AssertionError: None """ tester = self._tester(**options) - goodness=True + goodness = True i = 0 for x in self: goodness = x._test_stembridge_local_axioms(index_set, verbose) @@ -715,10 +715,10 @@ def stembridgeTriple(self,i,j): """ if self.e(i) is None: return None - b=self.stembridgeDelta_depth(i,j) - c=self.stembridgeDelta_rise(i,j) - dd=self.cartan_type().dynkin_diagram() - a=dd[j,i] + b = self.stembridgeDelta_depth(i,j) + c = self.stembridgeDelta_rise(i,j) + dd = self.cartan_type().dynkin_diagram() + a = dd[j,i] return (a, b, c) def _test_stembridge_local_axioms(self, index_set=None, verbose=False, **options): @@ -754,38 +754,38 @@ def _test_stembridge_local_axioms(self, index_set=None, verbose=False, **options tester = self._tester(**options) goodness = True if index_set is None: - index_set=self.index_set() + index_set = self.index_set() from sage.combinat.subset import Subsets for (i,j) in Subsets(index_set, 2): if self.e(i) is not None and self.e(j) is not None: - triple=self.stembridgeTriple(i,j) + triple = self.stembridgeTriple(i,j) #Test axioms P3 and P4. - if not triple[0]==triple[1]+triple[2] or triple[1]>0 or triple[2]>0: + if not triple[0] == triple[1]+triple[2] or triple[1] > 0 or triple[2] > 0: if verbose: print('Warning: Failed axiom P3 or P4 at vector ', self, 'i,j=', i, j, 'Stembridge triple:', self.stembridgeTriple(i, j)) - goodness=False + goodness = False else: tester.fail() - if self.stembridgeDelta_depth(i,j)==0: + if self.stembridgeDelta_depth(i,j) == 0: #check E_i E_j(x)= E_j E_i(x) - if self.e(i).e(j)!=self.e(j).e(i) or self.e(i).e(j).stembridgeDel_rise(j, i)!=0: + if self.e(i).e(j) != self.e(j).e(i) or self.e(i).e(j).stembridgeDel_rise(j, i) != 0: if verbose: print('Warning: Failed axiom P5 at: vector ', self, 'i,j=', i, j, 'Stembridge triple:', self.stembridgeTriple(i, j)) - goodness=False + goodness = False else: tester.fail() - if self.stembridgeDelta_depth(i,j)==-1 and self.stembridgeDelta_depth(j,i)==-1: + if self.stembridgeDelta_depth(i,j) == -1 and self.stembridgeDelta_depth(j,i) == -1: #check E_i E_j^2 E_i (x)= E_j E_i^2 E_j (x) - y1=self.e(j).e(i).e(i).e(j) - y2=self.e(j).e(i).e(i).e(j) - a=y1.stembridgeDel_rise(j, i) - b=y2.stembridgeDel_rise(i, j) - if y1!=y2 or a!=-1 or b!=-1: + y1 = self.e(j).e(i).e(i).e(j) + y2 = self.e(j).e(i).e(i).e(j) + a = y1.stembridgeDel_rise(j, i) + b = y2.stembridgeDel_rise(i, j) + if y1 != y2 or a != -1 or b != -1: if verbose: print('Warning: Failed axiom P6 at: vector ', self, 'i,j=', i, j, 'Stembridge triple:', self.stembridgeTriple(i, j)) - goodness=False + goodness = False else: tester.fail() tester.assertTrue(goodness) diff --git a/src/sage/categories/regular_supercrystals.py b/src/sage/categories/regular_supercrystals.py index 9fd6f5c8a83..044f556a1f7 100644 --- a/src/sage/categories/regular_supercrystals.py +++ b/src/sage/categories/regular_supercrystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.graphs +# sage.doctest: needs sage.combinat sage.graphs r""" Regular Supercrystals """ diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index 1449333d973..60ca92f971b 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -66,17 +66,18 @@ def is_injective(self) -> bool: EXAMPLES:: + sage: # needs sage.libs.singular sage: R. = QQ[] - sage: R.hom([x, y^2], R).is_injective() # optional - sage.libs.singular + sage: R.hom([x, y^2], R).is_injective() True - sage: R.hom([x, x^2], R).is_injective() # optional - sage.libs.singular + sage: R.hom([x, x^2], R).is_injective() False - sage: S. = R.quotient(x^3*y) # optional - sage.libs.singular - sage: R.hom([v, u], S).is_injective() # optional - sage.libs.singular + sage: S. = R.quotient(x^3*y) + sage: R.hom([v, u], S).is_injective() False - sage: S.hom([-u, v], S).is_injective() # optional - sage.libs.singular + sage: S.hom([-u, v], S).is_injective() True - sage: S.cover().is_injective() # optional - sage.libs.singular + sage: S.cover().is_injective() False If the domain is a field, the homomorphism is injective:: @@ -102,12 +103,12 @@ def is_injective(self) -> bool: characteristic can not be injective:: sage: R. = ZZ[] - sage: f = R.hom([GF(3)(1)]); f # optional - sage.rings.finite_rings + sage: f = R.hom([GF(3)(1)]); f Ring morphism: From: Univariate Polynomial Ring in x over Integer Ring To: Finite Field of size 3 Defn: x |--> 1 - sage: f.is_injective() # optional - sage.rings.finite_rings + sage: f.is_injective() False A morphism whose domain is an order in a number field is injective if @@ -132,8 +133,8 @@ def is_injective(self) -> bool: A coercion to the fraction field is injective:: - sage: R = ZpFM(3) # optional - sage.rings.padics - sage: R.fraction_field().coerce_map_from(R).is_injective() # optional - sage.rings.padics + sage: R = ZpFM(3) # needs sage.rings.padics + sage: R.fraction_field().coerce_map_from(R).is_injective() True """ @@ -218,20 +219,20 @@ def extend_to_fraction_field(self): Ring endomorphism of Univariate Polynomial Ring in x over Rational Field Defn: x |--> x + 1 - sage: g = f.extend_to_fraction_field(); g # optional - sage.libs.singular + sage: g = f.extend_to_fraction_field(); g # needs sage.libs.singular Ring endomorphism of Fraction Field of Univariate Polynomial Ring in x over Rational Field Defn: x |--> x + 1 - sage: g(x) # optional - sage.libs.singular + sage: g(x) # needs sage.libs.singular x + 1 - sage: g(1/x) # optional - sage.libs.singular + sage: g(1/x) # needs sage.libs.singular 1/(x + 1) If this morphism is not injective, it does not extend to the fraction field and an error is raised:: - sage: f = GF(5).coerce_map_from(ZZ) # optional - sage.rings.finite_rings - sage: f.extend_to_fraction_field() # optional - sage.rings.finite_rings + sage: f = GF(5).coerce_map_from(ZZ) + sage: f.extend_to_fraction_field() Traceback (most recent call last): ... ValueError: the morphism is not injective @@ -240,7 +241,7 @@ def extend_to_fraction_field(self): sage: A. = RR[] sage: phi = A.hom([x + 1]) - sage: phi.extend_to_fraction_field() # optional - sage.libs.singular + sage: phi.extend_to_fraction_field() # needs sage.libs.singular Ring endomorphism of Fraction Field of Univariate Polynomial Ring in x over Real Field with 53 bits of precision Defn: x |--> x + 1.00000000000000 @@ -336,10 +337,10 @@ def is_zero(self) -> bool: sage: R. = ZZ[] sage: R.quo(1).is_zero() True - sage: R. = GF(101)[] # optional - sage.rings.finite_rings - sage: R.quo(77).is_zero() # optional - sage.rings.finite_rings + sage: R. = GF(101)[] + sage: R.quo(77).is_zero() True - sage: R.quo(x^2 + 1).is_zero() # optional - sage.rings.finite_rings + sage: R.quo(x^2 + 1).is_zero() # needs sage.libs.pari False """ return self.one() == self.zero() @@ -354,19 +355,20 @@ def bracket(self, x, y): EXAMPLES:: - sage: F = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: F # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: F = AlgebrasWithBasis(QQ).example() + sage: F An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: a, b, c = F.algebra_generators() # optional - sage.combinat sage.modules - sage: F.bracket(a, b) # optional - sage.combinat sage.modules + sage: a, b, c = F.algebra_generators() + sage: F.bracket(a, b) B[word: ab] - B[word: ba] This measures the default of commutation between `x` and `y`. `F` endowed with the bracket operation is a Lie algebra; in particular, it satisfies Jacobi's identity:: - sage: (F.bracket(F.bracket(a,b), c) + F.bracket(F.bracket(b,c), a) # optional - sage.combinat sage.modules + sage: (F.bracket(F.bracket(a,b), c) + F.bracket(F.bracket(b,c), a) # needs sage.combinat sage.modules ....: + F.bracket(F.bracket(c,a), b)) 0 """ @@ -402,7 +404,7 @@ def _Hom_(self, Y, category): sage: Hom(QQ, QQ, category=Rings()).__class__ - sage: Hom(CyclotomicField(3), QQ, category=Rings()).__class__ # optional - sage.rings.number_field + sage: Hom(CyclotomicField(3), QQ, category=Rings()).__class__ # needs sage.rings.number_field sage: TestSuite(Hom(QQ, QQ, category=Rings())).run() # indirect doctest @@ -445,12 +447,13 @@ def _mul_(self, x, switch_sides=False): from the base class of rings. This is the case, e.g., for matrix algebras:: - sage: MS = MatrixSpace(QQ, 2, 2) # optional - sage.modules - sage: isinstance(MS, Ring) # optional - sage.modules + sage: # needs sage.modules + sage: MS = MatrixSpace(QQ, 2, 2) + sage: isinstance(MS, Ring) False - sage: MS in Rings() # optional - sage.modules + sage: MS in Rings() True - sage: MS * 2 # indirect doctest # optional - sage.modules + sage: MS * 2 # indirect doctest Left Ideal ( [2 0] @@ -461,7 +464,7 @@ def _mul_(self, x, switch_sides=False): In the next example, the ring and the other factor switch sides in the product:: - sage: [MS.2] * MS # optional - sage.modules + sage: [MS.2] * MS # needs sage.modules Right Ideal ( [0 0] @@ -507,12 +510,12 @@ def __pow__(self, n): EXAMPLES:: - sage: QQ^5 # optional - sage.modules + sage: QQ^5 # needs sage.modules Vector space of dimension 5 over Rational Field - sage: Integers(20)^1000 # optional - sage.modules + sage: Integers(20)^1000 # needs sage.modules Ambient free module of rank 1000 over Ring of integers modulo 20 - sage: QQ^(2, 3) # optional - sage.modules + sage: QQ^(2, 3) # needs sage.modules Full MatrixSpace of 2 by 3 dense matrices over Rational Field """ if isinstance(n, tuple): @@ -537,18 +540,19 @@ def ideal_monoid(self): EXAMPLES:: - sage: MS = MatrixSpace(QQ, 2, 2) # optional - sage.modules - sage: isinstance(MS, Ring) # optional - sage.modules + sage: # needs sage.modules + sage: MS = MatrixSpace(QQ, 2, 2) + sage: isinstance(MS, Ring) False - sage: MS in Rings() # optional - sage.modules + sage: MS in Rings() True - sage: MS.ideal_monoid() # optional - sage.modules + sage: MS.ideal_monoid() Monoid of ideals of Full MatrixSpace of 2 by 2 dense matrices over Rational Field Note that the monoid is cached:: - sage: MS.ideal_monoid() is MS.ideal_monoid() # optional - sage.modules + sage: MS.ideal_monoid() is MS.ideal_monoid() # needs sage.modules True """ try: @@ -566,11 +570,11 @@ def characteristic(self): sage: QQ.characteristic() 0 - sage: GF(19).characteristic() # optional - sage.rings.finite_rings + sage: GF(19).characteristic() 19 sage: Integers(8).characteristic() 8 - sage: Zp(5).characteristic() # optional - sage.rings.padics + sage: Zp(5).characteristic() # needs sage.rings.padics 0 """ from sage.rings.infinity import infinity @@ -625,19 +629,20 @@ def ideal(self, *args, **kwds): EXAMPLES:: - sage: MS = MatrixSpace(QQ, 2, 2) # optional - sage.modules - sage: isinstance(MS, Ring) # optional - sage.modules + sage: # needs sage.modules + sage: MS = MatrixSpace(QQ, 2, 2) + sage: isinstance(MS, Ring) False - sage: MS in Rings() # optional - sage.modules + sage: MS in Rings() True - sage: MS.ideal(2) # optional - sage.modules + sage: MS.ideal(2) Twosided Ideal ( [2 0] [0 2] ) of Full MatrixSpace of 2 by 2 dense matrices over Rational Field - sage: MS.ideal([MS.0, MS.1], side='right') # optional - sage.modules + sage: MS.ideal([MS.0, MS.1], side='right') Right Ideal ( [1 0] @@ -739,8 +744,8 @@ def _ideal_class_(self, n=0): EXAMPLES:: - sage: MS = MatrixSpace(QQ, 2, 2) # optional - sage.modules - sage: MS._ideal_class_() # optional - sage.modules + sage: MS = MatrixSpace(QQ, 2, 2) # needs sage.modules + sage: MS._ideal_class_() # needs sage.modules We do not know of a commutative ring in Sage that does not inherit @@ -788,10 +793,11 @@ def quotient(self, I, names=None, **kwds): So, we need a bit of effort to make the following example work with the category framework:: - sage: F. = FreeAlgebra(QQ) # optional - sage.combinat sage.modules - sage: from sage.rings.noncommutative_ideals import Ideal_nc # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: F. = FreeAlgebra(QQ) + sage: from sage.rings.noncommutative_ideals import Ideal_nc sage: from itertools import product - sage: class PowerIdeal(Ideal_nc): # optional - sage.combinat sage.modules + sage: class PowerIdeal(Ideal_nc): ....: def __init__(self, R, n): ....: self._power = n ....: Ideal_nc.__init__(self, R, [R.prod(m) @@ -800,22 +806,22 @@ def quotient(self, I, names=None, **kwds): ....: R = self.ring() ....: return add([c*R(m) for m, c in x ....: if len(m) < self._power], R(0)) - sage: I = PowerIdeal(F, 3) # optional - sage.combinat sage.modules - sage: Q = Rings().parent_class.quotient(F, I); Q # optional - sage.combinat sage.modules + sage: I = PowerIdeal(F, 3) + sage: Q = Rings().parent_class.quotient(F, I); Q Quotient of Free Algebra on 3 generators (x, y, z) over Rational Field by the ideal (x^3, x^2*y, x^2*z, x*y*x, x*y^2, x*y*z, x*z*x, x*z*y, x*z^2, y*x^2, y*x*y, y*x*z, y^2*x, y^3, y^2*z, y*z*x, y*z*y, y*z^2, z*x^2, z*x*y, z*x*z, z*y*x, z*y^2, z*y*z, z^2*x, z^2*y, z^3) - sage: Q.0 # optional - sage.combinat sage.modules + sage: Q.0 xbar - sage: Q.1 # optional - sage.combinat sage.modules + sage: Q.1 ybar - sage: Q.2 # optional - sage.combinat sage.modules + sage: Q.2 zbar - sage: Q.0*Q.1 # optional - sage.combinat sage.modules + sage: Q.0*Q.1 xbar*ybar - sage: Q.0*Q.1*Q.0 # optional - sage.combinat sage.modules + sage: Q.0*Q.1*Q.0 0 An example with polynomial rings:: @@ -826,14 +832,15 @@ def quotient(self, I, names=None, **kwds): sage: S.gens() (a,) + sage: # needs sage.libs.singular sage: R. = PolynomialRing(QQ, 2) - sage: S. = R.quotient((x^2, y)) # optional - sage.libs.singular - sage: S # optional - sage.libs.singular + sage: S. = R.quotient((x^2, y)) + sage: S Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2, y) - sage: S.gens() # optional - sage.libs.singular + sage: S.gens() (a, 0) - sage: a == b # optional - sage.libs.singular + sage: a == b False """ from sage.rings.quotient_ring import QuotientRing @@ -849,8 +856,8 @@ def quo(self, I, names=None, **kwds): EXAMPLES:: - sage: MS = MatrixSpace(QQ, 2) # optional - sage.modules - sage: I = MS * MS.gens() * MS # optional - sage.modules + sage: MS = MatrixSpace(QQ, 2) # needs sage.modules + sage: I = MS * MS.gens() * MS # needs sage.modules ``MS`` is not an instance of :class:`~sage.rings.ring.Ring`. @@ -858,11 +865,11 @@ def quo(self, I, names=None, **kwds): category of rings. The quotient method is inherited from there:: - sage: isinstance(MS, sage.rings.ring.Ring) # optional - sage.modules + sage: isinstance(MS, sage.rings.ring.Ring) # needs sage.modules False - sage: isinstance(MS, Rings().parent_class) # optional - sage.modules + sage: isinstance(MS, Rings().parent_class) # needs sage.modules True - sage: MS.quo(I, names=['a','b','c','d']) # optional - sage.modules + sage: MS.quo(I, names=['a','b','c','d']) # needs sage.modules Quotient of Full MatrixSpace of 2 by 2 dense matrices over Rational Field by the ideal ( @@ -881,14 +888,15 @@ def quo(self, I, names=None, **kwds): A test with a subclass of :class:`~sage.rings.ring.Ring`:: - sage: R. = PolynomialRing(QQ, 2) # optional - sage.libs.singular - sage: S. = R.quo((x^2, y)) # optional - sage.libs.singular - sage: S # optional - sage.libs.singular + sage: # needs sage.libs.singular + sage: R. = PolynomialRing(QQ, 2) + sage: S. = R.quo((x^2, y)) + sage: S Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2, y) - sage: S.gens() # optional - sage.libs.singular + sage: S.gens() (a, 0) - sage: a == b # optional - sage.libs.singular + sage: a == b False """ return self.quotient(I, names=names, **kwds) @@ -918,18 +926,18 @@ def quotient_ring(self, I, names=None, **kwds): EXAMPLES:: - sage: MS = MatrixSpace(QQ, 2) # optional - sage.modules - sage: I = MS * MS.gens() * MS # optional - sage.modules + sage: MS = MatrixSpace(QQ, 2) # needs sage.modules + sage: I = MS * MS.gens() * MS # needs sage.modules ``MS`` is not an instance of :class:`~sage.rings.ring.Ring`, but it is an instance of the parent class of the category of rings. The quotient method is inherited from there:: - sage: isinstance(MS, sage.rings.ring.Ring) # optional - sage.modules + sage: isinstance(MS, sage.rings.ring.Ring) # needs sage.modules False - sage: isinstance(MS, Rings().parent_class) # optional - sage.modules + sage: isinstance(MS, Rings().parent_class) # needs sage.modules True - sage: MS.quotient_ring(I, names=['a','b','c','d']) # optional - sage.modules + sage: MS.quotient_ring(I, names=['a','b','c','d']) # needs sage.modules Quotient of Full MatrixSpace of 2 by 2 dense matrices over Rational Field by the ideal ( @@ -954,14 +962,15 @@ def quotient_ring(self, I, names=None, **kwds): sage: S.gens() (a,) - sage: R. = PolynomialRing(QQ,2) # optional - sage.libs.singular - sage: S. = R.quotient_ring((x^2, y)) # optional - sage.libs.singular - sage: S # optional - sage.libs.singular + sage: # needs sage.libs.singular + sage: R. = PolynomialRing(QQ,2) + sage: S. = R.quotient_ring((x^2, y)) + sage: S Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2, y) - sage: S.gens() # optional - sage.libs.singular + sage: S.gens() (a, 0) - sage: a == b # optional - sage.libs.singular + sage: a == b False """ return self.quotient(I, names=names, **kwds) @@ -974,9 +983,9 @@ def __truediv__(self, I): EXAMPLES:: - sage: MS = MatrixSpace(QQ, 2) # optional - sage.modules - sage: I = MS * MS.gens() * MS # optional - sage.modules - sage: MS/I # optional - sage.modules + sage: MS = MatrixSpace(QQ, 2) # needs sage.modules + sage: I = MS * MS.gens() * MS # needs sage.modules + sage: MS/I # needs sage.modules Traceback (most recent call last): ... TypeError: use self.quotient(I) to construct the quotient ring @@ -1013,25 +1022,25 @@ def __getitem__(self, arg): Univariate Polynomial Ring in x over Integer Ring sage: QQ['x'] Univariate Polynomial Ring in x over Rational Field - sage: GF(17)['abc'] # optional - sage.rings.finite_rings + sage: GF(17)['abc'] Univariate Polynomial Ring in abc over Finite Field of size 17 - sage: GF(17)['a,b,c'] # optional - sage.rings.finite_rings + sage: GF(17)['a,b,c'] Multivariate Polynomial Ring in a, b, c over Finite Field of size 17 - sage: GF(17)['a']['b'] # optional - sage.rings.finite_rings + sage: GF(17)['a']['b'] Univariate Polynomial Ring in b over Univariate Polynomial Ring in a over Finite Field of size 17 We can create Ore polynomial rings:: - sage: k. = GF(5^3) # optional - sage.rings.finite_rings - sage: Frob = k.frobenius_endomorphism() # optional - sage.rings.finite_rings - sage: k['x', Frob] # optional - sage.rings.finite_rings + sage: k. = GF(5^3) # needs sage.rings.finite_rings + sage: Frob = k.frobenius_endomorphism() # needs sage.rings.finite_rings + sage: k['x', Frob] # needs sage.rings.finite_rings Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5 sage: R. = QQ[] - sage: der = R.derivation() # optional - sage.modules - sage: R['d', der] # optional - sage.modules + sage: der = R.derivation() # needs sage.modules + sage: R['d', der] # needs sage.modules Ore Polynomial Ring in d over Univariate Polynomial Ring in t over Rational Field twisted by d/dt @@ -1061,9 +1070,9 @@ def __getitem__(self, arg): Note that the same syntax can be used to create number fields:: - sage: QQ[I] + sage: QQ[I] # needs sage.rings.number_field sage.symbolic Number Field in I with defining polynomial x^2 + 1 with I = 1*I - sage: QQ[I].coerce_embedding() + sage: QQ[I].coerce_embedding() # needs sage.rings.number_field sage.symbolic Generic morphism: From: Number Field in I with defining polynomial x^2 + 1 with I = 1*I To: Complex Lazy Field @@ -1071,10 +1080,10 @@ def __getitem__(self, arg): :: - sage: QQ[sqrt(2)] # optional - sage.symbolic sage.rings.number_field + sage: QQ[sqrt(2)] # needs sage.rings.number_field sage.symbolic Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? - sage: QQ[sqrt(2)].coerce_embedding() # optional - sage.symbolic sage.rings.number_field + sage: QQ[sqrt(2)].coerce_embedding() # needs sage.rings.number_field sage.symbolic Generic morphism: From: Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? @@ -1083,26 +1092,26 @@ def __getitem__(self, arg): :: - sage: QQ[sqrt(2), sqrt(3)] # optional - sage.symbolic sage.rings.number_field + sage: QQ[sqrt(2), sqrt(3)] # needs sage.rings.number_field sage.symbolic Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field and orders in number fields:: - sage: ZZ[I] # optional - sage.symbolic sage.rings.number_field + sage: ZZ[I] # needs sage.rings.number_field sage.symbolic Order in Number Field in I0 with defining polynomial x^2 + 1 with I0 = 1*I - sage: ZZ[sqrt(5)] # optional - sage.symbolic sage.rings.number_field + sage: ZZ[sqrt(5)] # needs sage.rings.number_field sage.symbolic Order in Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: ZZ[sqrt(2) + sqrt(3)] # optional - sage.symbolic sage.rings.number_field + sage: ZZ[sqrt(2) + sqrt(3)] # needs sage.rings.number_field sage.symbolic Order in Number Field in a with defining polynomial x^4 - 10*x^2 + 1 with a = 3.146264369941973? Embeddings are found for simple extensions (when that makes sense):: - sage: QQi. = QuadraticField(-1, 'i') # optional - sage.symbolic sage.rings.number_field - sage: QQ[i].coerce_embedding() # optional - sage.symbolic sage.rings.number_field + sage: QQi. = QuadraticField(-1, 'i') # needs sage.rings.number_field sage.symbolic + sage: QQ[i].coerce_embedding() # needs sage.rings.number_field sage.symbolic Generic morphism: From: Number Field in i with defining polynomial x^2 + 1 with i = 1*I To: Complex Lazy Field @@ -1138,25 +1147,27 @@ def __getitem__(self, arg): Extension towers are built as follows and use distinct generator names:: - sage: K = QQ[2^(1/3), 2^(1/2), 3^(1/3)] # optional - sage.symbolic sage.rings.number_field - sage: K # optional - sage.symbolic sage.rings.number_field + sage: # needs sage.rings.number_field sage.symbolic + sage: K = QQ[2^(1/3), 2^(1/2), 3^(1/3)] + sage: K Number Field in a with defining polynomial x^3 - 2 over its base field - sage: K.base_field() # optional - sage.symbolic sage.rings.number_field + sage: K.base_field() Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field - sage: K.base_field().base_field() # optional - sage.symbolic sage.rings.number_field + sage: K.base_field().base_field() Number Field in b with defining polynomial x^3 - 3 Embeddings:: - sage: a = 10^100; expr = (2*a + sqrt(2))/(2*a^2-1) # optional - sage.symbolic sage.rings.number_field - sage: QQ[expr].coerce_embedding() is None # optional - sage.symbolic sage.rings.number_field + sage: # needs sage.rings.number_field sage.symbolic + sage: a = 10^100; expr = (2*a + sqrt(2))/(2*a^2-1) + sage: QQ[expr].coerce_embedding() is None False - sage: QQ[sqrt(5)].gen() > 0 # optional - sage.symbolic sage.rings.number_field + sage: QQ[sqrt(5)].gen() > 0 True - sage: expr = sqrt(2) + I*(cos(pi/4, hold=True) - sqrt(2)/2) # optional - sage.symbolic sage.rings.number_field - sage: QQ[expr].coerce_embedding() # optional - sage.symbolic sage.rings.number_field + sage: expr = sqrt(2) + I*(cos(pi/4, hold=True) - sqrt(2)/2) + sage: QQ[expr].coerce_embedding() Generic morphism: From: Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? @@ -1280,18 +1291,19 @@ def free_module(self, base=None, basis=None, map=True): EXAMPLES:: + sage: # needs sage.modules sage: R. = QQ[[]] - sage: V, from_V, to_V = R.free_module(R) # optional - sage.modules - sage: v = to_V(1 + x); v # optional - sage.modules + sage: V, from_V, to_V = R.free_module(R) + sage: v = to_V(1 + x); v (1 + x) - sage: from_V(v) # optional - sage.modules + sage: from_V(v) 1 + x - sage: W, from_W, to_W = R.free_module(R, basis=(1 - x)) # optional - sage.modules - sage: W is V # optional - sage.modules + sage: W, from_W, to_W = R.free_module(R, basis=(1 - x)) + sage: W is V True - sage: w = to_W(1 + x); w # optional - sage.modules + sage: w = to_W(1 + x); w (1 - x^2) - sage: from_W(w) # optional - sage.modules + sage: from_W(w) 1 + x + O(x^20) """ if base is None: @@ -1333,12 +1345,13 @@ def is_unit(self) -> bool: EXAMPLES:: - sage: MS = MatrixSpace(ZZ, 2) # optional - sage.modules - sage: MS.one().is_unit() # optional - sage.modules + sage: # needs sage.modules + sage: MS = MatrixSpace(ZZ, 2) + sage: MS.one().is_unit() True - sage: MS.zero().is_unit() # optional - sage.modules + sage: MS.zero().is_unit() False - sage: MS([1,2,3,4]).is_unit() # optional - sage.modules + sage: MS([1,2,3,4]).is_unit() False """ if self.is_one() or (-self).is_one(): @@ -1358,8 +1371,8 @@ def inverse_of_unit(self): EXAMPLES:: sage: R. = ZZ[] - sage: S = R.quo(x^2 + x + 1) # optional - sage.libs.pari - sage: S(1).inverse_of_unit() # optional - sage.libs.pari + sage: S = R.quo(x^2 + x + 1) # needs sage.libs.pari + sage: S(1).inverse_of_unit() # needs sage.libs.pari 1 This method fails when the element is not a unit:: @@ -1430,10 +1443,11 @@ def _gen_names(elts): EXAMPLES:: + sage: # needs sage.combinat sage: from sage.categories.rings import _gen_names - sage: list(_gen_names([sqrt(5)])) # optional - sage.symbolic + sage: list(_gen_names([sqrt(5)])) # needs sage.symbolic ['sqrt5'] - sage: list(_gen_names([sqrt(-17), 2^(1/3)])) # optional - sage.symbolic + sage: list(_gen_names([sqrt(-17), 2^(1/3)])) # needs sage.symbolic ['a', 'b'] sage: list(_gen_names((1..27)))[-1] 'aa' diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index aad5a48b7e9..d27ac1fafd7 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -148,7 +148,7 @@ def _call_(self, x): A = Spec(x.codomain()) return A.hom(x) else: - raise TypeError("No way to create an object or morphism in %s from %s"%(self, x)) + raise TypeError("No way to create an object or morphism in %s from %s" % (self, x)) ############################################################# diff --git a/src/sage/categories/semigroups.py b/src/sage/categories/semigroups.py index 45bf6ed7305..4b85a255568 100644 --- a/src/sage/categories/semigroups.py +++ b/src/sage/categories/semigroups.py @@ -196,37 +196,40 @@ def cayley_graph(self, side="right", simple=False, elements=None, We start with the (right) Cayley graphs of some classical groups:: - sage: D4 = DihedralGroup(4); D4 # optional - sage.groups + sage: # needs sage.graphs sage.groups + sage: D4 = DihedralGroup(4); D4 Dihedral group of order 8 as a permutation group - sage: G = D4.cayley_graph() # optional - sage.groups sage.graphs - sage: show(G, color_by_label=True, edge_labels=True) # optional - sage.groups sage.graphs sage.plot - sage: A5 = AlternatingGroup(5); A5 # optional - sage.groups + sage: G = D4.cayley_graph() + sage: show(G, color_by_label=True, edge_labels=True) # needs sage.plot + sage: A5 = AlternatingGroup(5); A5 Alternating group of order 5!/2 as a permutation group - sage: G = A5.cayley_graph() # optional - sage.groups sage.graphs - sage: G.show3d(color_by_label=True, edge_size=0.01, # optional - sage.groups sage.graphs sage.plot + sage: G = A5.cayley_graph() + sage: G.show3d(color_by_label=True, edge_size=0.01, # needs sage.plot ....: edge_size2=0.02, vertex_size=0.03) - sage: G.show3d(vertex_size=0.03, # long time (less than a minute) # optional - sage.groups sage.graphs sage.plot + sage: G.show3d(vertex_size=0.03, # long time (less than a minute), needs sage.plot ....: edge_size=0.01, edge_size2=0.02, ....: vertex_colors={(1,1,1): G.vertices(sort=True)}, ....: bgcolor=(0,0,0), color_by_label=True, ....: xres=700, yres=700, iterations=200) - sage: G.num_edges() # optional - sage.groups sage.graphs + sage: G.num_edges() 120 - sage: w = WeylGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: d = w.cayley_graph(); d # optional - sage.combinat sage.groups sage.graphs + sage: # needs sage.combinat sage.graphs sage.groups + sage: w = WeylGroup(['A', 3]) + sage: d = w.cayley_graph(); d Digraph on 24 vertices - sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03) # optional - sage.combinat sage.groups sage.graphs sage.plot + sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03) # needs sage.plot Alternative generators may be specified:: - sage: G = A5.cayley_graph(generators=[A5.gens()[0]]) # optional - sage.groups sage.graphs - sage: G.num_edges() # optional - sage.groups sage.graphs + sage: # needs sage.graphs sage.groups + sage: G = A5.cayley_graph(generators=[A5.gens()[0]]) + sage: G.num_edges() 60 - sage: g = PermutationGroup([(i + 1, j + 1) # optional - sage.groups sage.graphs + sage: g = PermutationGroup([(i + 1, j + 1) ....: for i in range(5) ....: for j in range(5) if j != i]) - sage: g.cayley_graph(generators=[(1,2), (2,3)]) # optional - sage.groups sage.graphs + sage: g.cayley_graph(generators=[(1,2), (2,3)]) Digraph on 120 vertices If ``elements`` is specified, then only the subgraph @@ -234,62 +237,63 @@ def cayley_graph(self, side="right", simple=False, elements=None, display the Cayley graph of the free monoid truncated on the elements of length at most 3:: + sage: # needs sage.combinat sage.graphs sage: M = Monoids().example(); M An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd') - sage: elements = [M.prod(w) # optional - sage.combinat + sage: elements = [M.prod(w) ....: for w in sum((list(Words(M.semigroup_generators(), k)) ....: for k in range(4)), [])] - sage: G = M.cayley_graph(elements=elements) # optional - sage.combinat sage.graphs - sage: G.num_verts(), G.num_edges() # optional - sage.combinat sage.graphs + sage: G = M.cayley_graph(elements=elements) + sage: G.num_verts(), G.num_edges() (85, 84) - sage: G.show3d(color_by_label=True, edge_size=0.001, vertex_size=0.01) # optional - sage.combinat sage.graphs sage.plot + sage: G.show3d(color_by_label=True, edge_size=0.001, vertex_size=0.01) # needs sage.plot We now illustrate the ``side`` and ``simple`` options on a semigroup:: sage: S = FiniteSemigroups().example(alphabet=('a', 'b')) - sage: g = S.cayley_graph(simple=True) # optional - sage.graphs - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g = S.cayley_graph(simple=True) # needs sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs ['a', 'ab', 'b', 'ba'] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [('a', 'ab', None), ('b', 'ba', None)] :: - sage: g = S.cayley_graph(side="left", simple=True) # optional - sage.graphs - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g = S.cayley_graph(side="left", simple=True) # needs sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs ['a', 'ab', 'b', 'ba'] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [('a', 'ba', None), ('ab', 'ba', None), ('b', 'ab', None), ('ba', 'ab', None)] :: - sage: g = S.cayley_graph(side="twosided", simple=True) # optional - sage.graphs - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g = S.cayley_graph(side="twosided", simple=True) # needs sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs ['a', 'ab', 'b', 'ba'] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [('a', 'ab', None), ('a', 'ba', None), ('ab', 'ba', None), ('b', 'ab', None), ('b', 'ba', None), ('ba', 'ab', None)] :: - sage: g = S.cayley_graph(side="twosided") # optional - sage.graphs - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g = S.cayley_graph(side="twosided") # needs sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs ['a', 'ab', 'b', 'ba'] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [('a', 'a', (0, 'left')), ('a', 'a', (0, 'right')), ('a', 'ab', (1, 'right')), ('a', 'ba', (1, 'left')), ('ab', 'ab', (0, 'left')), ('ab', 'ab', (0, 'right')), ('ab', 'ab', (1, 'right')), ('ab', 'ba', (1, 'left')), ('b', 'ab', (0, 'left')), ('b', 'b', (1, 'left')), ('b', 'b', (1, 'right')), ('b', 'ba', (0, 'right')), ('ba', 'ab', (0, 'left')), ('ba', 'ba', (0, 'right')), ('ba', 'ba', (1, 'left')), ('ba', 'ba', (1, 'right'))] :: - sage: s1 = SymmetricGroup(1); s = s1.cayley_graph() # optional - sage.groups sage.graphs - sage: s.vertices(sort=False) # optional - sage.groups sage.graphs + sage: s1 = SymmetricGroup(1); s = s1.cayley_graph() # needs sage.graphs sage.groups + sage: s.vertices(sort=False) # needs sage.graphs sage.groups [()] TESTS:: - sage: SymmetricGroup(2).cayley_graph(side="both") # optional - sage.groups sage.graphs + sage: SymmetricGroup(2).cayley_graph(side="both") # needs sage.graphs sage.groups Traceback (most recent call last): ... ValueError: option 'side' must be 'left', 'right' or 'twosided' @@ -386,52 +390,53 @@ def subsemigroup(self, generators, one=None, category=None): EXAMPLES:: sage: R = IntegerModRing(15) - sage: M = R.subsemigroup([R(3), R(5)]); M # optional - sage.groups + sage: M = R.subsemigroup([R(3), R(5)]); M # needs sage.combinat A subsemigroup of (Ring of integers modulo 15) with 2 generators - sage: M.list() # optional - sage.groups + sage: M.list() # needs sage.combinat [3, 5, 9, 0, 10, 12, 6] By default, `M` is just in the category of subsemigroups:: - sage: M in Semigroups().Subobjects() # optional - sage.groups + sage: M in Semigroups().Subobjects() # needs sage.combinat True In the following example, we specify that `M` is a submonoid of the finite monoid `R` (it shares the same unit), and a group by itself:: - sage: M = R.subsemigroup([R(-1)], # optional - sage.groups + sage: M = R.subsemigroup([R(-1)], # needs sage.combinat ....: category=Monoids().Finite().Subobjects() & Groups()); M A submonoid of (Ring of integers modulo 15) with 1 generators - sage: M.list() # optional - sage.groups + sage: M.list() # needs sage.combinat [1, 14] - sage: M.one() # optional - sage.groups + sage: M.one() # needs sage.combinat 1 In the following example, `M` is a group; however, its unit does not coincide with that of `R`, so `M` is only a subsemigroup, and we need to specify its unit explicitly:: - sage: M = R.subsemigroup([R(5)], # optional - sage.groups + sage: M = R.subsemigroup([R(5)], # needs sage.combinat ....: category=Semigroups().Finite().Subobjects() & Groups()); M Traceback (most recent call last): ... ValueError: For a monoid which is just a subsemigroup, the unit should be specified - sage: M = R.subsemigroup([R(5)], one=R(10), # optional - sage.groups + sage: # needs sage.groups + sage: M = R.subsemigroup([R(5)], one=R(10), ....: category=Semigroups().Finite().Subobjects() & Groups()); M A subsemigroup of (Ring of integers modulo 15) with 1 generators - sage: M in Groups() # optional - sage.groups + sage: M in Groups() True - sage: M.list() # optional - sage.groups + sage: M.list() [10, 5] - sage: M.one() # optional - sage.groups + sage: M.one() 10 TESTS:: - sage: TestSuite(M).run() # optional - sage.groups + sage: TestSuite(M).run() # needs sage.combinat Failure in _test_inverse: Traceback (most recent call last): ... @@ -461,8 +466,8 @@ def trivial_representation(self, base_ring=None, side="twosided"): EXAMPLES:: - sage: G = groups.permutation.Dihedral(4) # optional - sage.groups - sage: G.trivial_representation() # optional - sage.groups + sage: G = groups.permutation.Dihedral(4) # needs sage.groups + sage: G.trivial_representation() # needs sage.groups Trivial representation of Dihedral group of order 8 as a permutation group over Integer Ring """ @@ -481,8 +486,8 @@ def regular_representation(self, base_ring=None, side="left"): EXAMPLES:: - sage: G = groups.permutation.Dihedral(4) # optional - sage.groups - sage: G.regular_representation() # optional - sage.groups + sage: G = groups.permutation.Dihedral(4) # needs sage.groups + sage: G.regular_representation() # needs sage.groups Left Regular Representation of Dihedral group of order 8 as a permutation group over Integer Ring """ @@ -892,7 +897,7 @@ def algebra_generators(self): the left regular band generated by ('a', 'b', 'c', 'd') sage: M.semigroup_generators() Family ('a', 'b', 'c', 'd') - sage: M.algebra(ZZ).algebra_generators() # optional - sage.modules + sage: M.algebra(ZZ).algebra_generators() # needs sage.modules Family (B['a'], B['b'], B['c'], B['d']) """ return self.basis().keys().semigroup_generators().map(self.monomial) @@ -907,12 +912,12 @@ def gens(self): EXAMPLES:: - sage: a, b = SL2Z.algebra(ZZ).gens(); a, b # optional - sage.groups sage.modules + sage: a, b = SL2Z.algebra(ZZ).gens(); a, b # needs sage.groups sage.modules ([ 0 -1] [ 1 0], [1 1] [0 1]) - sage: 2*a + b # optional - sage.groups sage.modules + sage: 2*a + b # needs sage.groups sage.modules 2*[ 0 -1] [ 1 0] + @@ -927,9 +932,9 @@ def ngens(self): EXAMPLES:: - sage: SL2Z.algebra(ZZ).ngens() # optional - sage.groups sage.modules + sage: SL2Z.algebra(ZZ).ngens() # needs sage.groups sage.modules 2 - sage: DihedralGroup(4).algebra(RR).ngens() # optional - sage.groups sage.modules + sage: DihedralGroup(4).algebra(RR).ngens() # needs sage.groups sage.modules 2 """ return self.basis().keys().ngens() @@ -940,8 +945,8 @@ def gen(self, i=0): EXAMPLES:: - sage: A = GL(3, GF(7)).algebra(ZZ) # optional - sage.groups sage.libs.pari sage.modules - sage: A.gen(0) # optional - sage.groups sage.libs.pari sage.modules + sage: A = GL(3, GF(7)).algebra(ZZ) # needs sage.modules + sage: A.gen(0) # needs sage.groups sage.libs.pari sage.modules [3 0 0] [0 1 0] [0 0 1] @@ -962,9 +967,9 @@ def product_on_basis(self, g1, g2): sage: S = FiniteSemigroups().example(); S An example of a finite semigroup: the left regular band generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(QQ) # optional - sage.modules - sage: a, b, c, d = A.algebra_generators() # optional - sage.modules - sage: a * b + b * d * c * d # optional - sage.modules + sage: A = S.algebra(QQ) # needs sage.modules + sage: a, b, c, d = A.algebra_generators() # needs sage.modules + sage: a * b + b * d * c * d # needs sage.modules B['ab'] + B['bdc'] """ return self.monomial(g1 * g2) @@ -979,10 +984,11 @@ def trivial_representation(self, side="twosided"): EXAMPLES:: - sage: G = groups.permutation.Dihedral(4) # optional - sage.groups - sage: A = G.algebra(QQ) # optional - sage.groups sage.modules - sage: V = A.trivial_representation() # optional - sage.groups sage.modules - sage: V == G.trivial_representation(QQ) # optional - sage.groups sage.modules + sage: # needs sage.groups + sage: G = groups.permutation.Dihedral(4) + sage: A = G.algebra(QQ) # needs sage.modules + sage: V = A.trivial_representation() # needs sage.modules + sage: V == G.trivial_representation(QQ) # needs sage.modules True """ S = self.basis().keys() @@ -999,10 +1005,11 @@ def regular_representation(self, side="left"): EXAMPLES:: - sage: G = groups.permutation.Dihedral(4) # optional - sage.groups - sage: A = G.algebra(QQ) # optional - sage.groups sage.modules - sage: V = A.regular_representation() # optional - sage.groups sage.modules - sage: V == G.regular_representation(QQ) # optional - sage.groups sage.modules + sage: # needs sage.groups + sage: G = groups.permutation.Dihedral(4) + sage: A = G.algebra(QQ) # needs sage.modules + sage: V = A.regular_representation() # needs sage.modules + sage: V == G.regular_representation(QQ) # needs sage.modules True """ S = self.basis().keys() diff --git a/src/sage/categories/semisimple_algebras.py b/src/sage/categories/semisimple_algebras.py index 9be6bb8d571..9a310614290 100644 --- a/src/sage/categories/semisimple_algebras.py +++ b/src/sage/categories/semisimple_algebras.py @@ -37,15 +37,15 @@ class SemisimpleAlgebras(Category_over_base_ring): Typically, finite group algebras are semisimple:: - sage: DihedralGroup(5).algebra(QQ) in SemisimpleAlgebras # optional - sage.groups + sage: DihedralGroup(5).algebra(QQ) in SemisimpleAlgebras # needs sage.groups True Unless the characteristic of the field divides the order of the group:: - sage: DihedralGroup(5).algebra(IntegerModRing(5)) in SemisimpleAlgebras # optional - sage.groups + sage: DihedralGroup(5).algebra(IntegerModRing(5)) in SemisimpleAlgebras # needs sage.groups False - sage: DihedralGroup(5).algebra(IntegerModRing(7)) in SemisimpleAlgebras # optional - sage.groups + sage: DihedralGroup(5).algebra(IntegerModRing(7)) in SemisimpleAlgebras # needs sage.groups True .. SEEALSO:: :wikipedia:`Semisimple_algebra` @@ -96,13 +96,13 @@ def radical_basis(self, **keywords): EXAMPLES:: - sage: A = SymmetricGroup(4).algebra(QQ) # optional - sage.groups - sage: A.radical_basis() # optional - sage.groups + sage: A = SymmetricGroup(4).algebra(QQ) # needs sage.groups + sage: A.radical_basis() # needs sage.groups () TESTS:: - sage: A.radical_basis.__module__ # optional - sage.groups + sage: A.radical_basis.__module__ # needs sage.groups 'sage.categories.finite_dimensional_semisimple_algebras_with_basis' """ return () diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index c2d87e43b0c..16c117b286e 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -147,7 +147,7 @@ class Sets(Category_singleton): We run some generic checks on P:: - sage: TestSuite(P).run(verbose=True) # optional - sage.libs.pari + sage: TestSuite(P).run(verbose=True) # needs sage.libs.pari running ._test_an_element() . . . pass running ._test_cardinality() . . . pass running ._test_category() . . . pass @@ -867,11 +867,11 @@ def Facade(self): 1. as plain integers:: - sage: P = Poset((divisors(12), attrcall("divides")), facade=True) # optional - sage.graphs sage.combinat + sage: P = Poset((divisors(12), attrcall("divides")), facade=True) # needs sage.graphs 2. as integers, modified to be aware that their parent is `P`:: - sage: Q = Poset((divisors(12), attrcall("divides")), facade=False) # optional - sage.graphs sage.combinat + sage: Q = Poset((divisors(12), attrcall("divides")), facade=False) # needs sage.graphs The advantage of option 1. is that one needs not do conversions back and forth between `P` and `\ZZ`. The @@ -885,23 +885,23 @@ def Facade(self): To raise this ambiguity, one needs to explicitly specify the underlying poset as in `2 <_P 3`:: - sage: P = Posets().example("facade") # optional - sage.graphs sage.combinat - sage: P.lt(2,3) # optional - sage.graphs sage.combinat + sage: P = Posets().example("facade") + sage: P.lt(2,3) False On the other hand, with option 2. and once constructed, the elements know unambiguously how to compare themselves:: - sage: Q(2) < Q(3) # optional - sage.graphs sage.combinat + sage: Q(2) < Q(3) # needs sage.graphs False - sage: Q(2) < Q(6) # optional - sage.graphs sage.combinat + sage: Q(2) < Q(6) # needs sage.graphs True Beware that ``P(2)`` is still the integer `2`. Therefore ``P(2) < P(3)`` still compares `2` and `3` as integers!:: - sage: P(2) < P(3) # optional - sage.graphs sage.combinat + sage: P(2) < P(3) True In short `P` being a facade parent is one of the programmatic @@ -970,17 +970,17 @@ def _element_constructor_(self): sage: S(17) # indirect doctest 17 - sage: A = FreeModule(QQ, 3) # optional - sage.modules - sage: A.element_class # optional - sage.modules + sage: A = FreeModule(QQ, 3) # needs sage.modules + sage: A.element_class # needs sage.modules - sage: A._element_constructor_ # optional - sage.modules + sage: A._element_constructor_ # needs sage.modules - sage: B = SymmetricGroup(3).algebra(ZZ) # optional - sage.groups sage.modules - sage: B.element_class # optional - sage.groups sage.modules + sage: B = SymmetricGroup(3).algebra(ZZ) # needs sage.groups sage.modules + sage: B.element_class # needs sage.groups sage.modules <...SymmetricGroupAlgebra_n_with_category.element_class'> - sage: B._element_constructor_ # optional - sage.groups sage.modules + sage: B._element_constructor_ # needs sage.groups sage.modules """ @@ -1070,7 +1070,7 @@ def an_element(self): EXAMPLES:: - sage: CDF.an_element() + sage: CDF.an_element() # needs sage.rings.complex_double 1.0*I sage: ZZ[['t']].an_element() t @@ -1192,12 +1192,12 @@ def _test_elements_eq_reflexive(self, **options): We try a non-reflexive equality:: sage: P = Sets().example("wrapper") - sage: P._test_elements_eq_reflexive() # optional - sage.libs.pari + sage: P._test_elements_eq_reflexive() # needs sage.libs.pari sage: eq = P.element_class.__eq__ sage: P.element_class.__eq__ = (lambda x, y: ....: False if eq(x, P(47)) and eq(y, P(47)) else eq(x, y)) - sage: P._test_elements_eq_reflexive() # optional - sage.libs.pari + sage: P._test_elements_eq_reflexive() # needs sage.libs.pari Traceback (most recent call last): ... AssertionError: 47 != 47 @@ -1228,7 +1228,7 @@ def _test_elements_eq_symmetric(self, **options): We test a non symmetric equality:: sage: P = Sets().example("wrapper") - sage: P._test_elements_eq_symmetric() # optional - sage.libs.pari + sage: P._test_elements_eq_symmetric() # needs sage.libs.pari sage: eq = P.element_class.__eq__ sage: def non_sym_eq(x, y): @@ -1236,7 +1236,7 @@ def _test_elements_eq_symmetric(self, **options): ....: elif eq(x, P(47)) and eq(y, P(53)): return True ....: else: return eq(x, y) sage: P.element_class.__eq__ = non_sym_eq - sage: P._test_elements_eq_symmetric() # optional - sage.libs.pari + sage: P._test_elements_eq_symmetric() # needs sage.libs.pari Traceback (most recent call last): ... AssertionError: non symmetric equality: 47 == 53 but 53 != 47 @@ -1250,7 +1250,7 @@ def _test_elements_eq_symmetric(self, **options): S = list(tester.some_elements()) + [None, 0] from sage.misc.misc import some_tuples for x, y in some_tuples(S, 2, tester._max_runs): - tester.assertEqual(x==y, y==x, + tester.assertEqual(x == y, y == x, LazyFormat("non symmetric equality: %s but %s") % ( print_compare(x, y), print_compare(y, x))) @@ -1269,9 +1269,9 @@ def _test_elements_eq_transitive(self, **options): We test a non transitive equality:: - sage: R = Zp(3) # optional - sage.rings.padics - sage: test = raw_getattr(Sets().ParentMethods, "_test_elements_eq_transitive") # optional - sage.rings.padics - sage: test(R, elements=[R(3,2), R(3,1), R(0)]) # optional - sage.rings.padics + sage: R = Zp(3) # needs sage.rings.padics + sage: test = raw_getattr(Sets().ParentMethods, "_test_elements_eq_transitive") + sage: test(R, elements=[R(3,2), R(3,1), R(0)]) # needs sage.rings.padics Traceback (most recent call last): ... AssertionError: non transitive equality: @@ -1297,7 +1297,7 @@ def _test_elements_eq_transitive(self, **options): continue tester.assertEqual(x, z, LazyFormat("non transitive equality:\n" - "%s and %s but %s")%( + "%s and %s but %s") % ( print_compare(x, y), print_compare(y, z), print_compare(x, z))) @@ -1318,12 +1318,12 @@ def _test_elements_neq(self, **options): We try a broken inequality:: sage: P = Sets().example("wrapper") - sage: P._test_elements_neq() # optional - sage.libs.pari + sage: P._test_elements_neq() # needs sage.libs.pari sage: ne = P.element_class.__ne__ sage: eq = P.element_class.__eq__ sage: P.element_class.__ne__ = lambda x, y: False - sage: P._test_elements_neq() # optional - sage.libs.pari + sage: P._test_elements_neq() # needs sage.libs.pari Traceback (most recent call last): ... AssertionError: __eq__ and __ne__ inconsistency: @@ -1343,7 +1343,7 @@ def _test_elements_neq(self, **options): for x,y in some_tuples(S, 2, tester._max_runs): tester.assertNotEqual(x == y, x != y, LazyFormat("__eq__ and __ne__ inconsistency:\n" - " %s == %s returns %s but %s != %s returns %s")%( + " %s == %s returns %s but %s != %s returns %s") % ( x, y, (x == y), x, y, (x != y))) def some_elements(self): @@ -1404,7 +1404,7 @@ def _test_some_elements(self, **options): # "self.some_elements() should return an iterable, not an iterator") for x in elements: tester.assertIn(x, self, LazyFormat( - "the object %s in self.some_elements() is not in self")%(x,)) + "the object %s in self.some_elements() is not in self") % (x,)) #Note: the four methods 'cardinality', 'is_finite_, 'is_empty' and # 'random_element' might or might not be implemented in the parent @@ -1562,21 +1562,21 @@ def cartesian_product(*parents, **kwargs): EXAMPLES:: sage: C = AlgebrasWithBasis(QQ) - sage: A = C.example(); A.rename("A") # optional - sage.combinat sage.modules - sage: A.cartesian_product(A, A) # optional - sage.combinat sage.modules + sage: A = C.example(); A.rename("A") # needs sage.combinat sage.modules + sage: A.cartesian_product(A, A) # needs sage.combinat sage.modules A (+) A (+) A - sage: ZZ.cartesian_product(GF(2), FiniteEnumeratedSet([1,2,3])) # optional - sage.rings.finite_rings + sage: ZZ.cartesian_product(GF(2), FiniteEnumeratedSet([1,2,3])) The Cartesian product of (Integer Ring, Finite Field of size 2, {1, 2, 3}) - sage: C = ZZ.cartesian_product(A); C # optional - sage.combinat sage.modules + sage: C = ZZ.cartesian_product(A); C # needs sage.combinat sage.modules The Cartesian product of (Integer Ring, A) TESTS:: - sage: type(C) # optional - sage.combinat sage.modules + sage: type(C) # needs sage.combinat sage.modules - sage: C.category() # optional - sage.combinat sage.modules + sage: C.category() # needs sage.combinat sage.modules Join of Category of rings and ... and Category of Cartesian products of commutative additive groups @@ -1629,21 +1629,22 @@ def algebra(self, base_ring, category=None, **kwds): If `S` is a :class:`group `, the result is its group algebra `KS`:: - sage: S = DihedralGroup(4); S # optional - sage.groups + sage: # needs sage.groups sage.modules + sage: S = DihedralGroup(4); S Dihedral group of order 8 as a permutation group - sage: A = S.algebra(QQ); A # optional - sage.groups sage.modules + sage: A = S.algebra(QQ); A Algebra of Dihedral group of order 8 as a permutation group over Rational Field - sage: A.category() # optional - sage.groups sage.modules + sage: A.category() Category of finite group algebras over Rational Field - sage: a = A.an_element(); a # optional - sage.groups sage.modules + sage: a = A.an_element(); a () + (1,3) + 2*(1,3)(2,4) + 3*(1,4,3,2) This space is endowed with an algebra structure, obtained by extending by bilinearity the multiplication of `G` to a multiplication on `RG`:: - sage: a * a # optional - sage.groups sage.modules + sage: a * a # needs sage.groups sage.modules 6*() + 4*(2,4) + 3*(1,2)(3,4) + 12*(1,2,3,4) + 2*(1,3) + 13*(1,3)(2,4) + 6*(1,4,3,2) + 3*(1,4)(2,3) @@ -1653,11 +1654,11 @@ def algebra(self, base_ring, category=None, **kwds): sage: S = Monoids().example(); S An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd') - sage: A = S.algebra(QQ); A # optional - sage.modules + sage: A = S.algebra(QQ); A # needs sage.modules Algebra of An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd') over Rational Field - sage: A.category() # optional - sage.modules + sage: A.category() # needs sage.modules Category of monoid algebras over Rational Field Similarly, we can construct algebras for additive magmas, @@ -1666,18 +1667,18 @@ def algebra(self, base_ring, category=None, **kwds): One may specify for which category one takes the algebra; here we build the algebra of the additive group `GF_3`:: + sage: # needs sage.modules sage: from sage.categories.additive_groups import AdditiveGroups - sage: S = GF(7) # optional - sage.rings.finite_rings - sage: A = S.algebra(QQ, category=AdditiveGroups()); A # optional - sage.rings.finite_rings sage.modules + sage: S = GF(7) + sage: A = S.algebra(QQ, category=AdditiveGroups()); A Algebra of Finite Field of size 7 over Rational Field - sage: A.category() # optional - sage.rings.finite_rings sage.modules + sage: A.category() Category of finite dimensional additive group algebras over Rational Field - - sage: a = A(S(1)) # optional - sage.rings.finite_rings sage.modules - sage: a # optional - sage.rings.finite_rings sage.modules + sage: a = A(S(1)) + sage: a 1 - sage: 1 + a * a * a # optional - sage.rings.finite_rings sage.modules + sage: 1 + a * a * a 0 + 3 Note that the ``category`` keyword needs to be fed with @@ -1720,31 +1721,32 @@ def _sympy_(self): EXAMPLES:: + sage: # needs sympy sage: F = FiniteEnumeratedSets().example(); F An example of a finite enumerated set: {1,2,3} - sage: sF = F._sympy_(); sF # optional - sympy + sage: sF = F._sympy_(); sF SageSet(An example of a finite enumerated set: {1,2,3}) - sage: sF.is_finite_set # optional - sympy + sage: sF.is_finite_set True - sage: bool(sF) # optional - sympy + sage: bool(sF) True - sage: len(sF) # optional - sympy + sage: len(sF) 3 - sage: list(sF) # optional - sympy + sage: list(sF) [1, 2, 3] - sage: from sympy import FiniteSet # optional - sympy - sage: FiniteSet.fromiter(sF) # random - this output is sympy >= 1.9 # optional - sympy + sage: from sympy import FiniteSet + sage: FiniteSet.fromiter(sF) # random - this output is sympy >= 1.9 FiniteSet(1, 2, 3) - sage: RR._sympy_().is_finite_set # optional - sympy + sage: RR._sympy_().is_finite_set # needs sympy False sage: F = Family([1, 2]) sage: F is Family([1, 2]) False - sage: sF = F._sympy_(); sF # optional - sympy + sage: sF = F._sympy_(); sF # needs sympy SageSet(Family (1, 2)) - sage: sF._sage_() is F # optional - sympy + sage: sF._sage_() is F # needs sympy True """ from sage.interfaces.sympy_wrapper import SageSet @@ -1769,9 +1771,9 @@ def cartesian_product(*elements): EXAMPLES:: sage: C = AlgebrasWithBasis(QQ) - sage: A = C.example() # optional - sage.combinat sage.modules - sage: a, b, c = A.algebra_generators() # optional - sage.combinat sage.modules - sage: a.cartesian_product(b, c) # optional - sage.combinat sage.modules + sage: A = C.example() # needs sage.combinat sage.modules + sage: a, b, c = A.algebra_generators() # needs sage.combinat sage.modules + sage: a.cartesian_product(b, c) # needs sage.combinat sage.modules B[(0, word: a)] + B[(1, word: b)] + B[(2, word: c)] FIXME: is this a policy that we want to enforce on all parents? @@ -1805,22 +1807,22 @@ def __invert__(self): We now try to inverse a couple of morphisms defined by a matrix:: - sage: H = End(QQ^2) # optional - sage.modules - sage: phi = H(matrix([[1,1], [0,1]])); phi # optional - sage.modules + sage: H = End(QQ^2) # needs sage.modules + sage: phi = H(matrix([[1,1], [0,1]])); phi # needs sage.modules Vector space morphism represented by the matrix: [1 1] [0 1] Domain: Vector space of dimension 2 over Rational Field Codomain: Vector space of dimension 2 over Rational Field - sage: ~phi # optional - sage.modules + sage: ~phi # needs sage.modules Vector space morphism represented by the matrix: [ 1 -1] [ 0 1] Domain: Vector space of dimension 2 over Rational Field Codomain: Vector space of dimension 2 over Rational Field - sage: phi = H(matrix([[1,1], [1,1]])) # optional - sage.modules - sage: ~phi # optional - sage.modules + sage: phi = H(matrix([[1,1], [1,1]])) # needs sage.modules + sage: ~phi # needs sage.modules Traceback (most recent call last): ... ZeroDivisionError: matrix morphism not invertible @@ -1837,11 +1839,11 @@ def is_injective(self): EXAMPLES:: - sage: f = ZZ.hom(GF(3)); f # optional - sage.rings.finite_rings + sage: f = ZZ.hom(GF(3)); f Natural morphism: From: Integer Ring To: Finite Field of size 3 - sage: f.is_injective() # optional - sage.rings.finite_rings + sage: f.is_injective() False """ if self.domain().cardinality() <= 1: @@ -1856,11 +1858,12 @@ def image(self, domain_subset=None): EXAMPLES:: - sage: P = Partitions(6) # optional - sage.combinat - sage: H = Hom(P, ZZ) # optional - sage.combinat - sage: f = H(ZZ.sum) # optional - sage.combinat - sage: X = f.image() # optional - sage.combinat - sage: list(X) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = Partitions(6) + sage: H = Hom(P, ZZ) + sage: f = H(ZZ.sum) + sage: X = f.image() # needs sage.libs.flint + sage: list(X) # needs sage.libs.flint [6] """ D = self.domain() @@ -1969,7 +1972,7 @@ def _repr_(self): sage: S._repr_() 'A subquotient of An example of a semigroup: the left zero semigroup' """ - return "A subquotient of %s"%(self.ambient()) + return "A subquotient of %s" % (self.ambient()) @abstract_method def ambient(self): @@ -2173,7 +2176,7 @@ def _repr_(self): sage: S._repr_() 'The image by some isomorphism of An example of a finite enumerated set: {1,2,3}' """ - return "The image by some isomorphism of %s"%(self.ambient()) + return "The image by some isomorphism of %s" % (self.ambient()) class CartesianProducts(CartesianProductsCategory): """ @@ -2259,18 +2262,19 @@ def __iter__(self): sage: C.__iter__.__module__ 'sage.categories.sets_cat' - sage: F22 = GF(2).cartesian_product(GF(2)) # optional - sage.rings.finite_rings - sage: list(F22) # optional - sage.rings.finite_rings + sage: F22 = GF(2).cartesian_product(GF(2)) + sage: list(F22) [(0, 0), (0, 1), (1, 0), (1, 1)] - sage: C = cartesian_product([Permutations(10)]*4) # optional - sage.combinat - sage: it = iter(C) # optional - sage.combinat - sage: next(it) # optional - sage.combinat + sage: # needs sage.combinat + sage: C = cartesian_product([Permutations(10)]*4) + sage: it = iter(C) + sage: next(it) ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) - sage: next(it) # optional - sage.combinat + sage: next(it) ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], @@ -2279,8 +2283,8 @@ def __iter__(self): When all factors (except possibly the first factor) are known to be finite, it uses the lexicographic order:: - sage: it = iter(cartesian_product([ZZ, GF(2)])) # optional - sage.rings.finite_rings - sage: [next(it) for _ in range(10)] # optional - sage.rings.finite_rings + sage: it = iter(cartesian_product([ZZ, GF(2)])) + sage: [next(it) for _ in range(10)] [(0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (-1, 1), @@ -2300,8 +2304,8 @@ def __iter__(self): An example with the first factor finite, the second infinite:: - sage: it = iter(cartesian_product([GF(2), ZZ])) # optional - sage.rings.finite_rings - sage: [next(it) for _ in range(11)] # optional - sage.rings.finite_rings + sage: it = iter(cartesian_product([GF(2), ZZ])) + sage: [next(it) for _ in range(11)] [(0, 0), (1, 0), (0, 1), (1, 1), (0, -1), @@ -2386,8 +2390,8 @@ def is_finite(self): EXAMPLES:: sage: E = FiniteEnumeratedSet([1,2,3]) - sage: C = cartesian_product([E, SymmetricGroup(4)]) # optional - sage.groups - sage: C.is_finite() # optional - sage.groups + sage: C = cartesian_product([E, SymmetricGroup(4)]) # needs sage.groups + sage: C.is_finite() # needs sage.groups True sage: cartesian_product([ZZ,ZZ]).is_finite() @@ -2414,8 +2418,8 @@ def cardinality(self): EXAMPLES:: sage: E = FiniteEnumeratedSet([1,2,3]) - sage: C = cartesian_product([E, SymmetricGroup(4)]) # optional - sage.groups - sage: C.cardinality() # optional - sage.groups + sage: C = cartesian_product([E, SymmetricGroup(4)]) # needs sage.groups + sage: C.cardinality() # needs sage.groups 72 sage: E = FiniteEnumeratedSet([]) @@ -2427,9 +2431,9 @@ def cardinality(self): sage: C.cardinality() +Infinity - sage: cartesian_product([GF(5), Permutations(10)]).cardinality() # optional - sage.rings.finite_rings sage.combinat + sage: cartesian_product([GF(5), Permutations(10)]).cardinality() 18144000 - sage: cartesian_product([GF(71)]*20).cardinality() == 71**20 # optional - sage.rings.finite_rings + sage: cartesian_product([GF(71)]*20).cardinality() == 71**20 True """ f = self.cartesian_factors() @@ -2460,8 +2464,8 @@ def random_element(self, *args): EXAMPLES:: - sage: C = cartesian_product([Permutations(10)]*5) # optional - sage.combinat - sage: C.random_element() # random # optional - sage.combinat + sage: C = cartesian_product([Permutations(10)]*5) + sage: C.random_element() # random ([2, 9, 4, 7, 1, 8, 6, 10, 5, 3], [8, 6, 5, 7, 1, 4, 9, 3, 10, 2], [5, 10, 3, 8, 2, 9, 1, 4, 7, 6], @@ -2570,9 +2574,9 @@ def _sympy_(self): EXAMPLES:: sage: ZZ3 = cartesian_product([ZZ, ZZ, ZZ]) - sage: sZZ3 = ZZ3._sympy_(); sZZ3 # optional - sympy + sage: sZZ3 = ZZ3._sympy_(); sZZ3 # needs sympy ProductSet(Integers, Integers, Integers) - sage: (1, 2, 3) in sZZ3 # optional - sympy + sage: (1, 2, 3) in sZZ3 # needs sympy True """ from sympy import ProductSet @@ -2593,14 +2597,15 @@ def cartesian_projection(self, i): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") # optional - sage.modules - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") # optional - sage.modules - sage: S = cartesian_product([F, G]) # optional - sage.modules - sage: x = (S.monomial((0,4)) + 2 * S.monomial((0,5)) # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") + sage: S = cartesian_product([F, G]) + sage: x = (S.monomial((0,4)) + 2 * S.monomial((0,5)) ....: + 3 * S.monomial((1,6))) - sage: x.cartesian_projection(0) # optional - sage.modules + sage: x.cartesian_projection(0) B[4] + 2*B[5] - sage: x.cartesian_projection(1) # optional - sage.modules + sage: x.cartesian_projection(1) 3*B[6] """ return self.parent().cartesian_projection(i)(self) @@ -2611,20 +2616,21 @@ def cartesian_factors(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") # optional - sage.modules - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") # optional - sage.modules - sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.rename("H") # optional - sage.modules - sage: S = cartesian_product([F, G, H]) # optional - sage.modules - sage: x = (S.monomial((0,4)) + 2 * S.monomial((0,5)) # optional - sage.modules + sage: # needs sage.modules + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") + sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.rename("H") + sage: S = cartesian_product([F, G, H]) + sage: x = (S.monomial((0,4)) + 2 * S.monomial((0,5)) ....: + 3 * S.monomial((1,6)) + 4 * S.monomial((2,4)) ....: + 5 * S.monomial((2,7))) - sage: x.cartesian_factors() # optional - sage.modules + sage: x.cartesian_factors() (B[4] + 2*B[5], 3*B[6], 4*B[4] + 5*B[7]) - sage: [s.parent() for s in x.cartesian_factors()] # optional - sage.modules + sage: [s.parent() for s in x.cartesian_factors()] [F, G, H] - sage: S.zero().cartesian_factors() # optional - sage.modules + sage: S.zero().cartesian_factors() (0, 0, 0) - sage: [s.parent() for s in S.zero().cartesian_factors()] # optional - sage.modules + sage: [s.parent() for s in S.zero().cartesian_factors()] [F, G, H] """ # TODO: optimize @@ -2644,7 +2650,7 @@ def extra_super_categories(self): sage: Sets().Algebras(QQ).extra_super_categories() [Category of vector spaces with basis over Rational Field] - sage: Sets().example().algebra(ZZ).categories() # optional - sage.groups sage.modules + sage: Sets().example().algebra(ZZ).categories() # needs sage.modules [Category of set algebras over Integer Ring, Category of modules with basis over Integer Ring, ... @@ -2661,20 +2667,20 @@ def construction(self): EXAMPLES:: - sage: A = GroupAlgebra(KleinFourGroup(), QQ) # optional - sage.groups sage.modules - sage: F, arg = A.construction(); F, arg # optional - sage.groups sage.modules + sage: A = GroupAlgebra(KleinFourGroup(), QQ) # needs sage.groups sage.modules + sage: F, arg = A.construction(); F, arg # needs sage.groups sage.modules (GroupAlgebraFunctor, Rational Field) - sage: F(arg) is A # optional - sage.groups sage.modules + sage: F(arg) is A # needs sage.groups sage.modules True This also works for structures such as monoid algebras (see :trac:`27937`):: - sage: A = FreeAbelianMonoid('x,y').algebra(QQ) # optional - sage.groups sage.modules - sage: F, arg = A.construction(); F, arg # optional - sage.groups sage.modules + sage: A = FreeAbelianMonoid('x,y').algebra(QQ) # needs sage.groups sage.modules + sage: F, arg = A.construction(); F, arg # needs sage.groups sage.modules (The algebra functorial construction, Free abelian monoid on 2 generators (x, y)) - sage: F(arg) is A # optional - sage.groups sage.modules + sage: F(arg) is A # needs sage.groups sage.modules True """ from sage.categories.algebra_functor import ( @@ -2692,14 +2698,15 @@ def _repr_(self): EXAMPLES:: - sage: A = Groups().example().algebra(QQ); A # optional - sage.groups sage.modules + sage: # needs sage.groups sage.modules + sage: A = Groups().example().algebra(QQ); A Algebra of General Linear Group of degree 4 over Rational Field over Rational Field - sage: A._name = "foo" # optional - sage.groups sage.modules - sage: A # optional - sage.groups sage.modules + sage: A._name = "foo" + sage: A foo over Rational Field - sage: A = KleinFourGroup().algebra(ZZ) # optional - sage.groups sage.modules - sage: A # optional - sage.groups sage.modules + sage: A = KleinFourGroup().algebra(ZZ) + sage: A Algebra of The Klein 4 group of order 4, as a permutation group over Integer Ring """ @@ -2731,10 +2738,10 @@ def example(self, base_ring=None, set=None): EXAMPLES:: - sage: Sets().WithRealizations().example() # optional - sage.combinat sage.modules + sage: Sets().WithRealizations().example() # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: Sets().WithRealizations().example(ZZ, Set([1,2])) # optional - sage.combinat sage.modules + sage: Sets().WithRealizations().example(ZZ, Set([1,2])) # needs sage.modules The subset algebra of {1, 2} over Integer Ring """ from sage.rings.rational_field import QQ @@ -2760,8 +2767,8 @@ def _test_with_realizations(self, **options): EXAMPLES:: - sage: A = Sets().WithRealizations().example() # optional - sage.combinat sage.modules - sage: A._test_with_realizations() # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example() # needs sage.modules + sage: A._test_with_realizations() # needs sage.modules See the documentation for :class:`TestSuite` for more information. @@ -2791,15 +2798,16 @@ def _register_realization(self, realization): """ EXAMPLES:: - sage: A = Sets().WithRealizations().example(QQ['x']); A # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(QQ['x']); A The subset algebra of {1, 2, 3} over Univariate Polynomial Ring in x over Rational Field - sage: class ANewRealizationOfA(CombinatorialFreeModule): # optional - sage.combinat sage.modules + sage: class ANewRealizationOfA(CombinatorialFreeModule): ....: pass - sage: category = A.Realizations() & Algebras(QQ['x']).WithBasis() # optional - sage.combinat sage.modules - sage: R = ANewRealizationOfA(A.base_ring(), A.F().basis().keys(), # optional - sage.combinat sage.modules + sage: category = A.Realizations() & Algebras(QQ['x']).WithBasis() + sage: R = ANewRealizationOfA(A.base_ring(), A.F().basis().keys(), ....: category=category) - sage: R in A.realizations() # indirect doctest # optional - sage.combinat sage.modules + sage: R in A.realizations() # indirect doctest True Note: the test above uses ``QQ[x]`` to not interfer @@ -2827,16 +2835,17 @@ def inject_shorthands(self, shorthands=None, verbose=True): it is convenient to define shorthands for the various realizations, but cumbersome to do it by hand:: - sage: S = SymmetricFunctions(ZZ); S # optional - sage.combinat + sage: S = SymmetricFunctions(ZZ); S # needs sage.combinat sage.modules Symmetric Functions over Integer Ring - sage: s = S.s(); s # optional - sage.combinat + sage: s = S.s(); s # needs sage.combinat sage.modules Symmetric Functions over Integer Ring in the Schur basis - sage: e = S.e(); e # optional - sage.combinat + sage: e = S.e(); e # needs sage.combinat sage.modules Symmetric Functions over Integer Ring in the elementary basis This method automates the process:: - sage: S.inject_shorthands() # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: S.inject_shorthands() Defining e as shorthand for Symmetric Functions over Integer Ring in the elementary basis Defining f as shorthand for @@ -2849,22 +2858,21 @@ def inject_shorthands(self, shorthands=None, verbose=True): Symmetric Functions over Integer Ring in the powersum basis Defining s as shorthand for Symmetric Functions over Integer Ring in the Schur basis - sage: s[1] + e[2] * p[1,1] + 2*h[3] + m[2,1] # optional - sage.combinat + sage: s[1] + e[2] * p[1,1] + 2*h[3] + m[2,1] s[1] - 2*s[1, 1, 1] + s[1, 1, 1, 1] + s[2, 1] + 2*s[2, 1, 1] + s[2, 2] + 2*s[3] + s[3, 1] - - sage: e # optional - sage.combinat + sage: e Symmetric Functions over Integer Ring in the elementary basis - sage: p # optional - sage.combinat + sage: p Symmetric Functions over Integer Ring in the powersum basis - sage: s # optional - sage.combinat + sage: s Symmetric Functions over Integer Ring in the Schur basis Sometimes, like for symmetric functions, one can request for all shorthands to be defined, including less common ones:: - sage: S.inject_shorthands("all") # optional - sage.combinat + sage: S.inject_shorthands("all") # needs sage.combinat sage.modules Defining e as shorthand for Symmetric Functions over Integer Ring in the elementary basis Defining f as shorthand for @@ -2892,37 +2900,37 @@ def inject_shorthands(self, shorthands=None, verbose=True): The messages can be silenced by setting ``verbose=False``:: - sage: Q = QuasiSymmetricFunctions(ZZ) # optional - sage.combinat - sage: Q.inject_shorthands(verbose=False) # optional - sage.combinat - - sage: F[1,2,1] + 5*M[1,3] + F[2]^2 # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: Q = QuasiSymmetricFunctions(ZZ) + sage: Q.inject_shorthands(verbose=False) + sage: F[1,2,1] + 5*M[1,3] + F[2]^2 5*F[1, 1, 1, 1] - 5*F[1, 1, 2] - 3*F[1, 2, 1] + 6*F[1, 3] + 2*F[2, 2] + F[3, 1] + F[4] - - sage: F # optional - sage.combinat + sage: F Quasisymmetric functions over the Integer Ring in the Fundamental basis - sage: M # optional - sage.combinat + sage: M Quasisymmetric functions over the Integer Ring in the Monomial basis One can also just import a subset of the shorthands:: - sage: SQ = SymmetricFunctions(QQ) # optional - sage.combinat - sage: SQ.inject_shorthands(['p', 's'], verbose=False) # optional - sage.combinat - sage: p # optional - sage.combinat + sage: # needs sage.combinat sage.modules + sage: SQ = SymmetricFunctions(QQ) + sage: SQ.inject_shorthands(['p', 's'], verbose=False) + sage: p Symmetric Functions over Rational Field in the powersum basis - sage: s # optional - sage.combinat + sage: s Symmetric Functions over Rational Field in the Schur basis Note that ``e`` is left unchanged:: - sage: e # optional - sage.combinat + sage: e # needs sage.combinat sage.modules Symmetric Functions over Integer Ring in the elementary basis TESTS:: - sage: e == S.e(), h == S.h(), m == S.m(), p == SQ.p(), s == SQ.s() # optional - sage.combinat + sage: e == S.e(), h == S.h(), m == S.m(), p == SQ.p(), s == SQ.s() # needs sage.combinat sage.modules (True, True, True, True, True) """ from sage.misc.misc import inject_variable @@ -2945,9 +2953,9 @@ def a_realization(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.a_realization() # optional - sage.combinat sage.modules + sage: A.a_realization() # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis """ @@ -2959,9 +2967,9 @@ def realizations(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.realizations() # optional - sage.combinat sage.modules + sage: A.realizations() # needs sage.modules [The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis, The subset algebra of {1, 2, 3} over Rational Field in the In basis, The subset algebra of {1, 2, 3} over Rational Field in the Out basis] @@ -2981,22 +2989,23 @@ def facade_for(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.facade_for() # optional - sage.combinat sage.modules + sage: A.facade_for() # needs sage.modules [The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis, The subset algebra of {1, 2, 3} over Rational Field in the In basis, The subset algebra of {1, 2, 3} over Rational Field in the Out basis] - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A The subset algebra of {1, 2, 3} over Rational Field - sage: f = A.F().an_element(); f # optional - sage.combinat sage.modules + sage: f = A.F().an_element(); f F[{}] + 2*F[{1}] + 3*F[{2}] + F[{1, 2}] - sage: i = A.In().an_element(); i # optional - sage.combinat sage.modules + sage: i = A.In().an_element(); i In[{}] + 2*In[{1}] + 3*In[{2}] + In[{1, 2}] - sage: o = A.Out().an_element(); o # optional - sage.combinat sage.modules + sage: o = A.Out().an_element(); o Out[{}] + 2*Out[{1}] + 3*Out[{2}] + Out[{1, 2}] - sage: f in A, i in A, o in A # optional - sage.combinat sage.modules + sage: f in A, i in A, o in A (True, True, True) """ return self.realizations() @@ -3008,9 +3017,9 @@ def super_categories(self): """ EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.Realizations().super_categories() # optional - sage.combinat sage.modules + sage: A.Realizations().super_categories() # needs sage.modules [Category of realizations of sets] """ return [Sets().Realizations()] @@ -3021,9 +3030,9 @@ def _an_element_(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: A.an_element() # indirect doctest # optional - sage.combinat sage.modules + sage: A.an_element() # indirect doctest # needs sage.modules F[{}] + 2*F[{1}] + 3*F[{2}] + F[{1, 2}] TESTS: @@ -3031,9 +3040,9 @@ def _an_element_(self): Check that we are consistent no matter which basis is created first:: - sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) # optional - sage.combinat sage.graphs sage.modules - sage: I = M.I() # optional - sage.combinat sage.graphs sage.modules - sage: M._an_element_() # optional - sage.combinat sage.graphs sage.modules + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) # needs sage.combinat sage.graphs sage.modules + sage: I = M.I() # needs sage.combinat sage.graphs sage.modules + sage: M._an_element_() # needs sage.combinat sage.graphs sage.modules 2*E[0] + 2*E[1] + 3*E[2] """ return self.a_realization().an_element() @@ -3046,19 +3055,20 @@ def __contains__(self, x): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A The subset algebra of {1, 2, 3} over Rational Field - sage: A.an_element() in A # optional - sage.combinat sage.modules + sage: A.an_element() in A True - sage: A.In().an_element() in A # optional - sage.combinat sage.modules + sage: A.In().an_element() in A True - sage: A.F().an_element() in A # optional - sage.combinat sage.modules + sage: A.F().an_element() in A True - sage: A.Out().an_element() in A # optional - sage.combinat sage.modules + sage: A.Out().an_element() in A True - sage: 1 in A # optional - sage.combinat sage.modules + sage: 1 in A True - sage: QQ['x'].an_element() in A # optional - sage.combinat sage.modules + sage: QQ['x'].an_element() in A False """ return any(x in realization for realization in self.realizations()) @@ -3073,8 +3083,8 @@ def __init_extra__(self): TESTS:: - sage: A = Sets().WithRealizations().example() # optional - sage.combinat sage.modules - sage: A.realizations() # indirect doctest # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example() # needs sage.modules + sage: A.realizations() # indirect doctest # needs sage.modules [The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis, The subset algebra of {1, 2, 3} over Rational Field in the In basis, The subset algebra of {1, 2, 3} over Rational Field in the Out basis] @@ -3088,11 +3098,11 @@ def realization_of(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: In = A.In(); In # optional - sage.combinat sage.modules + sage: In = A.In(); In # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field in the In basis - sage: In.realization_of() # optional - sage.combinat sage.modules + sage: In.realization_of() # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field """ for category in self.categories(): @@ -3108,11 +3118,11 @@ def _realization_name(self): EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: In = A.In(); In # optional - sage.combinat sage.modules + sage: In = A.In(); In # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field in the In basis - sage: In._realization_name() # optional - sage.combinat sage.modules + sage: In._realization_name() # needs sage.modules 'In' """ # The __base__ gets rid of the with_category @@ -3123,9 +3133,9 @@ def _repr_(self): """ EXAMPLES:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field - sage: In = A.In(); In # optional - sage.combinat sage.modules + sage: In = A.In(); In # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field in the In basis In the example above, :meth:`repr` was overridden by @@ -3137,12 +3147,13 @@ def _repr_(self): sage: from sage.categories.realizations import Realizations sage: class Blah(Parent): ....: pass - sage: C = Sets.WithRealizations.ParentMethods.Realizations(A) # optional - sage.combinat sage.modules - sage: P = Blah(category=C) # optional - sage.combinat sage.modules - sage: P # indirect doctest # optional - sage.combinat sage.modules + sage: C = Sets.WithRealizations.ParentMethods.Realizations(A) # needs sage.modules + sage: P = Blah(category=C) # needs sage.modules + sage: P # indirect doctest # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field in the realization Blah """ return "{} in the realization {}".format(self.realization_of(), self._realization_name()) + # Moved from sage.categories.cartesian_product to avoid circular import errors cartesian_product = CartesianProductFunctor() diff --git a/src/sage/categories/sets_with_grading.py b/src/sage/categories/sets_with_grading.py index a9cc219e06e..b1e321f67f2 100644 --- a/src/sage/categories/sets_with_grading.py +++ b/src/sage/categories/sets_with_grading.py @@ -161,9 +161,9 @@ def subset(self, *args, **options): EXAMPLES:: - sage: W = WeightedIntegerVectors([3,2,1]); W # optional - sage.combinat + sage: W = WeightedIntegerVectors([3,2,1]); W # needs sage.combinat Integer vectors weighted by [3, 2, 1] - sage: W.subset(4) # optional - sage.combinat + sage: W.subset(4) # needs sage.combinat Integer vectors of 4 weighted by [3, 2, 1] """ @@ -213,7 +213,7 @@ def generating_series(self): sage: N.generating_series() 1/(-z + 1) - sage: Permutations().generating_series() # optional - sage.combinat + sage: Permutations().generating_series() # needs sage.combinat 1 + z + 2*z^2 + 6*z^3 + 24*z^4 + 120*z^5 + 720*z^6 + O(z^7) .. TODO:: diff --git a/src/sage/categories/simplicial_complexes.py b/src/sage/categories/simplicial_complexes.py index 87c266858d8..9750dcab686 100644 --- a/src/sage/categories/simplicial_complexes.py +++ b/src/sage/categories/simplicial_complexes.py @@ -67,8 +67,8 @@ def dimension(self): EXAMPLES:: - sage: S = SimplicialComplex([[1,3,4], [1,2],[2,5],[4,5]]) # optional - sage.graphs - sage: S.dimension() # optional - sage.graphs + sage: S = SimplicialComplex([[1,3,4], [1,2],[2,5],[4,5]]) # needs sage.graphs + sage: S.dimension() # needs sage.graphs 2 """ return max(c.dimension() for c in self.facets()) @@ -81,8 +81,8 @@ def facets(self): EXAMPLES:: - sage: S = SimplicialComplex([[1,3,4], [1,2],[2,5],[4,5]]) # optional - sage.graphs - sage: sorted(S.facets()) # optional - sage.graphs + sage: S = SimplicialComplex([[1,3,4], [1,2],[2,5],[4,5]]) # needs sage.graphs + sage: sorted(S.facets()) # needs sage.graphs [(1, 2), (1, 3, 4), (2, 5), (4, 5)] """ @@ -93,8 +93,8 @@ def faces(self): EXAMPLES:: - sage: S = SimplicialComplex([[1,3,4], [1,2],[2,5],[4,5]]) # optional - sage.graphs - sage: S.faces() # optional - sage.graphs + sage: S = SimplicialComplex([[1,3,4], [1,2],[2,5],[4,5]]) # needs sage.graphs + sage: S.faces() # needs sage.graphs {-1: {()}, 0: {(1,), (2,), (3,), (4,), (5,)}, 1: {(1, 2), (1, 3), (1, 4), (2, 5), (3, 4), (4, 5)}, diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index 4558f139874..c07871402fd 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -71,10 +71,10 @@ def is_finite(self): EXAMPLES:: - sage: simplicial_sets.Torus().is_finite() # optional - sage.graphs + sage: simplicial_sets.Torus().is_finite() # needs sage.graphs True - sage: C5 = groups.misc.MultiplicativeAbelian([5]) # optional - sage.graphs sage.groups - sage: simplicial_sets.ClassifyingSpace(C5).is_finite() # optional - sage.graphs sage.groups + sage: C5 = groups.misc.MultiplicativeAbelian([5]) # needs sage.graphs sage.groups + sage: simplicial_sets.ClassifyingSpace(C5).is_finite() # needs sage.graphs sage.groups False """ return SimplicialSets.Finite() in self.categories() @@ -86,15 +86,16 @@ def is_pointed(self): EXAMPLES:: - sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet # optional - sage.graphs - sage: v = AbstractSimplex(0) # optional - sage.graphs - sage: w = AbstractSimplex(0) # optional - sage.graphs - sage: e = AbstractSimplex(1) # optional - sage.graphs - sage: X = SimplicialSet({e: (v, w)}) # optional - sage.graphs - sage: Y = SimplicialSet({e: (v, w)}, base_point=w) # optional - sage.graphs - sage: X.is_pointed() # optional - sage.graphs + sage: # needs sage.graphs + sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet + sage: v = AbstractSimplex(0) + sage: w = AbstractSimplex(0) + sage: e = AbstractSimplex(1) + sage: X = SimplicialSet({e: (v, w)}) + sage: Y = SimplicialSet({e: (v, w)}, base_point=w) + sage: X.is_pointed() False - sage: Y.is_pointed() # optional - sage.graphs + sage: Y.is_pointed() True """ return SimplicialSets.Pointed() in self.categories() @@ -110,29 +111,30 @@ def set_base_point(self, point): EXAMPLES:: - sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet # optional - sage.graphs - sage: v = AbstractSimplex(0, name='v_0') # optional - sage.graphs - sage: w = AbstractSimplex(0, name='w_0') # optional - sage.graphs - sage: e = AbstractSimplex(1) # optional - sage.graphs - sage: X = SimplicialSet({e: (v, w)}) # optional - sage.graphs - sage: Y = SimplicialSet({e: (v, w)}, base_point=w) # optional - sage.graphs - sage: Y.base_point() # optional - sage.graphs + sage: # needs sage.graphs + sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet + sage: v = AbstractSimplex(0, name='v_0') + sage: w = AbstractSimplex(0, name='w_0') + sage: e = AbstractSimplex(1) + sage: X = SimplicialSet({e: (v, w)}) + sage: Y = SimplicialSet({e: (v, w)}, base_point=w) + sage: Y.base_point() w_0 - sage: X_star = X.set_base_point(w) # optional - sage.graphs - sage: X_star.base_point() # optional - sage.graphs + sage: X_star = X.set_base_point(w) + sage: X_star.base_point() w_0 - sage: Y_star = Y.set_base_point(v) # optional - sage.graphs - sage: Y_star.base_point() # optional - sage.graphs + sage: Y_star = Y.set_base_point(v) + sage: Y_star.base_point() v_0 TESTS:: - sage: X.set_base_point(e) # optional - sage.graphs + sage: X.set_base_point(e) # needs sage.graphs Traceback (most recent call last): ... ValueError: the "point" is not a zero-simplex - sage: pt = AbstractSimplex(0) # optional - sage.graphs - sage: X.set_base_point(pt) # optional - sage.graphs + sage: pt = AbstractSimplex(0) # needs sage.graphs + sage: X.set_base_point(pt) # needs sage.graphs Traceback (most recent call last): ... ValueError: the point is not a simplex in this simplicial set @@ -154,8 +156,8 @@ def one(self): EXAMPLES:: - sage: T = simplicial_sets.Torus() # optional - sage.graphs - sage: Hom(T, T).identity() # optional - sage.graphs + sage: T = simplicial_sets.Torus() # needs sage.graphs + sage: Hom(T, T).identity() # needs sage.graphs Simplicial set endomorphism of Torus Defn: Identity map """ @@ -197,13 +199,14 @@ def base_point(self): EXAMPLES:: - sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet # optional - sage.graphs - sage: v = AbstractSimplex(0, name='*') # optional - sage.graphs - sage: e = AbstractSimplex(1) # optional - sage.graphs - sage: S1 = SimplicialSet({e: (v, v)}, base_point=v) # optional - sage.graphs - sage: S1.is_pointed() # optional - sage.graphs + sage: # needs sage.graphs + sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet + sage: v = AbstractSimplex(0, name='*') + sage: e = AbstractSimplex(1) + sage: S1 = SimplicialSet({e: (v, v)}, base_point=v) + sage: S1.is_pointed() True - sage: S1.base_point() # optional - sage.graphs + sage: S1.base_point() * """ return self._basepoint @@ -226,26 +229,27 @@ def base_point_map(self, domain=None): EXAMPLES:: - sage: T = simplicial_sets.Torus() # optional - sage.graphs - sage: f = T.base_point_map(); f # optional - sage.graphs + sage: # needs sage.graphs + sage: T = simplicial_sets.Torus() + sage: f = T.base_point_map(); f Simplicial set morphism: From: Point To: Torus Defn: Constant map at (v_0, v_0) - sage: S3 = simplicial_sets.Sphere(3) # optional - sage.graphs - sage: g = S3.base_point_map() # optional - sage.graphs - sage: f.domain() == g.domain() # optional - sage.graphs + sage: S3 = simplicial_sets.Sphere(3) + sage: g = S3.base_point_map() + sage: f.domain() == g.domain() True - sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # optional - sage.graphs sage.groups - sage: temp = simplicial_sets.Simplex(0) # optional - sage.graphs sage.groups - sage: pt = temp.set_base_point(temp.n_cells(0)[0]) # optional - sage.graphs sage.groups - sage: h = RP3.base_point_map(domain=pt) # optional - sage.graphs sage.groups - sage: f.domain() == h.domain() # optional - sage.graphs sage.groups + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # needs sage.groups + sage: temp = simplicial_sets.Simplex(0) + sage: pt = temp.set_base_point(temp.n_cells(0)[0]) + sage: h = RP3.base_point_map(domain=pt) # needs sage.groups + sage: f.domain() == h.domain() # needs sage.groups False - sage: C5 = groups.misc.MultiplicativeAbelian([5]) # optional - sage.graphs sage.groups - sage: BC5 = simplicial_sets.ClassifyingSpace(C5) # optional - sage.graphs sage.groups - sage: BC5.base_point_map() # optional - sage.graphs sage.groups + sage: C5 = groups.misc.MultiplicativeAbelian([5]) # needs sage.graphs sage.groups + sage: BC5 = simplicial_sets.ClassifyingSpace(C5) # needs sage.graphs sage.groups + sage: BC5.base_point_map() # needs sage.graphs sage.groups Simplicial set morphism: From: Point To: Classifying space of Multiplicative Abelian group isomorphic to C5 @@ -285,49 +289,51 @@ def fundamental_group(self, simplify=True): EXAMPLES:: - sage: S1 = simplicial_sets.Sphere(1) # optional - sage.graphs - sage: eight = S1.wedge(S1) # optional - sage.graphs - sage: eight.fundamental_group() # free group on 2 generators # optional - sage.graphs sage.groups + sage: S1 = simplicial_sets.Sphere(1) # needs sage.graphs + sage: eight = S1.wedge(S1) # needs sage.graphs + sage: eight.fundamental_group() # free group on 2 generators # needs sage.graphs sage.groups Finitely presented group < e0, e1 | > The fundamental group of a disjoint union of course depends on the choice of base point:: - sage: T = simplicial_sets.Torus() # optional - sage.graphs - sage: K = simplicial_sets.KleinBottle() # optional - sage.graphs - sage: X = T.disjoint_union(K) # optional - sage.graphs + sage: T = simplicial_sets.Torus() # needs sage.graphs + sage: K = simplicial_sets.KleinBottle() # needs sage.graphs + sage: X = T.disjoint_union(K) # needs sage.graphs - sage: X_0 = X.set_base_point(X.n_cells(0)[0]) # optional - sage.graphs - sage: X_0.fundamental_group().is_abelian() # optional - sage.graphs sage.groups + sage: # needs sage.graphs + sage: X_0 = X.set_base_point(X.n_cells(0)[0]) + sage: X_0.fundamental_group().is_abelian() # needs sage.groups True - sage: X_1 = X.set_base_point(X.n_cells(0)[1]) # optional - sage.graphs - sage: X_1.fundamental_group().is_abelian() # optional - sage.graphs sage.groups + sage: X_1 = X.set_base_point(X.n_cells(0)[1]) + sage: X_1.fundamental_group().is_abelian() # needs sage.groups False - sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # optional - sage.graphs sage.groups - sage: RP3.fundamental_group() # optional - sage.graphs sage.groups + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # needs sage.graphs sage.groups + sage: RP3.fundamental_group() # needs sage.graphs sage.groups Finitely presented group < e | e^2 > Compute the fundamental group of some classifying spaces:: - sage: C5 = groups.misc.MultiplicativeAbelian([5]) # optional - sage.graphs sage.groups - sage: BC5 = C5.nerve() # optional - sage.graphs sage.groups - sage: BC5.fundamental_group() # optional - sage.graphs sage.groups + sage: C5 = groups.misc.MultiplicativeAbelian([5]) # needs sage.graphs sage.groups + sage: BC5 = C5.nerve() # needs sage.graphs sage.groups + sage: BC5.fundamental_group() # needs sage.graphs sage.groups Finitely presented group < e0 | e0^5 > - sage: Sigma3 = groups.permutation.Symmetric(3) # optional - sage.graphs sage.groups - sage: BSigma3 = Sigma3.nerve() # optional - sage.graphs sage.groups - sage: pi = BSigma3.fundamental_group(); pi # optional - sage.graphs sage.groups + sage: # needs sage.graphs sage.groups + sage: Sigma3 = groups.permutation.Symmetric(3) + sage: BSigma3 = Sigma3.nerve() + sage: pi = BSigma3.fundamental_group(); pi Finitely presented group < e1, e2 | e2^2, e1^3, (e2*e1)^2 > - sage: pi.order() # optional - sage.graphs sage.groups + sage: pi.order() 6 - sage: pi.is_abelian() # optional - sage.graphs sage.groups + sage: pi.is_abelian() False The sphere has a trivial fundamental group:: - sage: S2 = simplicial_sets.Sphere(2) # optional - sage.graphs - sage: S2.fundamental_group() # optional - sage.graphs sage.groups + sage: S2 = simplicial_sets.Sphere(2) # needs sage.graphs + sage: S2.fundamental_group() # needs sage.graphs sage.groups Finitely presented group < | > """ # Import this here to prevent importing libgap upon startup. @@ -347,10 +353,10 @@ def _universal_cover_dict(self): TESTS:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.groups - sage: RP2._universal_cover_dict() # optional - sage.groups + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # needs sage.groups + sage: RP2._universal_cover_dict() # needs sage.groups (Finitely presented group < e | e^2 >, {f: e}) - sage: RP2.nondegenerate_simplices() # optional - sage.groups + sage: RP2.nondegenerate_simplices() # needs sage.groups [1, f, f * f] """ from sage.groups.free_group import FreeGroup @@ -393,14 +399,14 @@ def universal_cover_map(self): EXAMPLES:: - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.groups - sage: phi = RP2.universal_cover_map(); phi # optional - sage.groups + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # needs sage.groups + sage: phi = RP2.universal_cover_map(); phi # needs sage.groups Simplicial set morphism: From: Simplicial set with 6 non-degenerate simplices To: RP^2 Defn: [(1, 1), (1, e), (f, 1), (f, e), (f * f, 1), (f * f, e)] --> [1, 1, f, f, f * f, f * f] - sage: phi.domain().face_data() # optional - sage.groups + sage: phi.domain().face_data() # needs sage.groups {(1, 1): None, (1, e): None, (f, 1): ((1, e), (1, 1)), @@ -431,11 +437,12 @@ def covering_map(self, character): EXAMPLES:: - sage: S1 = simplicial_sets.Sphere(1) # optional - sage.graphs - sage: W = S1.wedge(S1) # optional - sage.graphs - sage: G = CyclicPermutationGroup(3) # optional - sage.groups - sage: a, b = W.n_cells(1) # optional - sage.graphs - sage: C = W.covering_map({a : G.gen(0), b : G.one()}); C # optional - sage.graphs sage.groups + sage: # needs sage.graphs sage.groups + sage: S1 = simplicial_sets.Sphere(1) + sage: W = S1.wedge(S1) + sage: G = CyclicPermutationGroup(3) + sage: a, b = W.n_cells(1) + sage: C = W.covering_map({a : G.gen(0), b : G.one()}); C Simplicial set morphism: From: Simplicial set with 9 non-degenerate simplices To: Wedge: (S^1 v S^1) @@ -443,9 +450,9 @@ def covering_map(self, character): (sigma_1, ()), (sigma_1, (1,2,3)), (sigma_1, (1,2,3)), (sigma_1, (1,3,2)), (sigma_1, (1,3,2))] --> [*, *, *, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1] - sage: C.domain() # optional - sage.graphs sage.groups + sage: C.domain() Simplicial set with 9 non-degenerate simplices - sage: C.domain().face_data() # optional - sage.graphs sage.groups + sage: C.domain().face_data() {(*, ()): None, (*, (1,2,3)): None, (*, (1,3,2)): None, @@ -518,12 +525,13 @@ def cover(self, character): EXAMPLES:: - sage: S1 = simplicial_sets.Sphere(1) # optional - sage.graphs - sage: W = S1.wedge(S1) # optional - sage.graphs - sage: G = CyclicPermutationGroup(3) # optional - sage.groups - sage: (a, b) = W.n_cells(1) # optional - sage.graphs - sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2}) # optional - sage.graphs sage.groups - sage: C.face_data() # optional - sage.graphs sage.groups + sage: # needs sage.graphs sage.groups + sage: S1 = simplicial_sets.Sphere(1) + sage: W = S1.wedge(S1) + sage: G = CyclicPermutationGroup(3) + sage: (a, b) = W.n_cells(1) + sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2}) + sage: C.face_data() {(*, ()): None, (*, (1,2,3)): None, (*, (1,3,2)): None, @@ -533,9 +541,9 @@ def cover(self, character): (sigma_1, (1,2,3)): ((*, ()), (*, (1,2,3))), (sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))), (sigma_1, (1,3,2)): ((*, (1,2,3)), (*, (1,3,2)))} - sage: C.homology(1) # optional - sage.graphs sage.groups sage.modules + sage: C.homology(1) # needs sage.modules Z x Z x Z x Z - sage: C.fundamental_group() # optional - sage.graphs sage.groups + sage: C.fundamental_group() Finitely presented group < e0, e1, e2, e3 | > """ return self.covering_map(character).domain() @@ -548,10 +556,11 @@ def universal_cover(self): EXAMPLES:: - sage: RP3 = simplicial_sets.RealProjectiveSpace(3) # optional - sage.groups - sage: C = RP3.universal_cover(); C # optional - sage.groups + sage: # needs sage.groups + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) + sage: C = RP3.universal_cover(); C Simplicial set with 8 non-degenerate simplices - sage: C.face_data() # optional - sage.groups + sage: C.face_data() {(1, 1): None, (1, e): None, (f, 1): ((1, e), (1, 1)), @@ -560,7 +569,7 @@ def universal_cover(self): (f * f, e): ((f, 1), s_0 (1, e), (f, e)), (f * f * f, 1): ((f * f, e), s_0 (f, 1), s_1 (f, 1), (f * f, 1)), (f * f * f, e): ((f * f, 1), s_0 (f, e), s_1 (f, e), (f * f, e))} - sage: C.fundamental_group() # optional - sage.groups + sage: C.fundamental_group() Finitely presented group < | > """ return self.universal_cover_map().domain() @@ -579,26 +588,28 @@ def is_simply_connected(self): EXAMPLES:: - sage: T = simplicial_sets.Torus() # optional - sage.graphs - sage: T.is_simply_connected() # optional - sage.graphs sage.groups + sage: # needs sage.graphs sage.groups + sage: T = simplicial_sets.Torus() + sage: T.is_simply_connected() False - sage: T.suspension().is_simply_connected() # optional - sage.graphs sage.groups + sage: T.suspension().is_simply_connected() True - sage: simplicial_sets.KleinBottle().is_simply_connected() # optional - sage.graphs sage.groups + sage: simplicial_sets.KleinBottle().is_simply_connected() False - sage: S2 = simplicial_sets.Sphere(2) # optional - sage.graphs - sage: S3 = simplicial_sets.Sphere(3) # optional - sage.graphs - sage: (S2.wedge(S3)).is_simply_connected() # optional - sage.graphs sage.groups + sage: # needs sage.graphs + sage: S2 = simplicial_sets.Sphere(2) + sage: S3 = simplicial_sets.Sphere(3) + sage: (S2.wedge(S3)).is_simply_connected() # needs sage.groups True - sage: X = S2.disjoint_union(S3) # optional - sage.graphs - sage: X = X.set_base_point(X.n_cells(0)[0]) # optional - sage.graphs - sage: X.is_simply_connected() # optional - sage.graphs sage.groups + sage: X = S2.disjoint_union(S3) + sage: X = X.set_base_point(X.n_cells(0)[0]) + sage: X.is_simply_connected() False - sage: C3 = groups.misc.MultiplicativeAbelian([3]) # optional - sage.graphs sage.groups - sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # optional - sage.graphs sage.groups - sage: BC3.is_simply_connected() # optional - sage.graphs sage.groups + sage: C3 = groups.misc.MultiplicativeAbelian([3]) # needs sage.graphs sage.groups + sage: BC3 = simplicial_sets.ClassifyingSpace(C3) # needs sage.graphs sage.groups + sage: BC3.is_simply_connected() # needs sage.graphs sage.groups False """ if not self.is_connected(): @@ -642,21 +653,22 @@ def connectivity(self, max_dim=None): EXAMPLES:: - sage: simplicial_sets.Sphere(3).connectivity() # optional - sage.graphs sage.groups + sage: # needs sage.graphs sage.groups + sage: simplicial_sets.Sphere(3).connectivity() 2 - sage: simplicial_sets.Sphere(0).connectivity() # optional - sage.graphs sage.groups + sage: simplicial_sets.Sphere(0).connectivity() -1 - sage: K = simplicial_sets.Simplex(4) # optional - sage.graphs - sage: K = K.set_base_point(K.n_cells(0)[0]) # optional - sage.graphs - sage: K.connectivity() # optional - sage.graphs sage.groups + sage: K = simplicial_sets.Simplex(4) + sage: K = K.set_base_point(K.n_cells(0)[0]) + sage: K.connectivity() +Infinity - sage: X = simplicial_sets.Torus().suspension(2) # optional - sage.graphs - sage: X.connectivity() # optional - sage.graphs sage.groups + sage: X = simplicial_sets.Torus().suspension(2) + sage: X.connectivity() 2 - sage: C2 = groups.misc.MultiplicativeAbelian([2]) # optional - sage.graphs sage.groups - sage: BC2 = simplicial_sets.ClassifyingSpace(C2) # optional - sage.graphs sage.groups - sage: BC2.connectivity() # optional - sage.graphs sage.groups + sage: C2 = groups.misc.MultiplicativeAbelian([2]) # needs sage.graphs sage.groups + sage: BC2 = simplicial_sets.ClassifyingSpace(C2) # needs sage.graphs sage.groups + sage: BC2.connectivity() # needs sage.graphs sage.groups 0 """ if not self.is_connected(): @@ -690,17 +702,18 @@ def unset_base_point(self): EXAMPLES:: - sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet # optional - sage.graphs - sage: v = AbstractSimplex(0, name='v_0') # optional - sage.graphs - sage: w = AbstractSimplex(0, name='w_0') # optional - sage.graphs - sage: e = AbstractSimplex(1) # optional - sage.graphs - sage: Y = SimplicialSet({e: (v, w)}, base_point=w) # optional - sage.graphs - sage: Y.is_pointed() # optional - sage.graphs + sage: # needs sage.graphs + sage: from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet + sage: v = AbstractSimplex(0, name='v_0') + sage: w = AbstractSimplex(0, name='w_0') + sage: e = AbstractSimplex(1) + sage: Y = SimplicialSet({e: (v, w)}, base_point=w) + sage: Y.is_pointed() True - sage: Y.base_point() # optional - sage.graphs + sage: Y.base_point() w_0 - sage: Z = Y.unset_base_point() # optional - sage.graphs - sage: Z.is_pointed() # optional - sage.graphs + sage: Z = Y.unset_base_point() + sage: Z.is_pointed() False """ from sage.topology.simplicial_set import SimplicialSet @@ -719,14 +732,15 @@ def fat_wedge(self, n): EXAMPLES:: - sage: S1 = simplicial_sets.Sphere(1) # optional - sage.graphs - sage: S1.fat_wedge(0) # optional - sage.graphs + sage: # needs sage.graphs + sage: S1 = simplicial_sets.Sphere(1) + sage: S1.fat_wedge(0) Point - sage: S1.fat_wedge(1) # optional - sage.graphs + sage: S1.fat_wedge(1) S^1 - sage: S1.fat_wedge(2).fundamental_group() # optional - sage.graphs sage.groups + sage: S1.fat_wedge(2).fundamental_group() # needs sage.groups Finitely presented group < e0, e1 | > - sage: S1.fat_wedge(4).homology() # optional - sage.graphs sage.modules + sage: S1.fat_wedge(4).homology() # needs sage.modules {0: 0, 1: Z x Z x Z x Z, 2: Z^6, 3: Z x Z x Z x Z} """ from sage.topology.simplicial_set_examples import Point @@ -746,18 +760,19 @@ def smash_product(self, *others): EXAMPLES:: - sage: S1 = simplicial_sets.Sphere(1) # optional - sage.graphs - sage: RP2 = simplicial_sets.RealProjectiveSpace(2) # optional - sage.graphs sage.groups - sage: X = S1.smash_product(RP2) # optional - sage.graphs sage.groups - sage: X.homology(base_ring=GF(2)) # optional - sage.graphs sage.groups sage.modules sage.rings.finite_rings + sage: # needs sage.graphs sage.groups + sage: S1 = simplicial_sets.Sphere(1) + sage: RP2 = simplicial_sets.RealProjectiveSpace(2) + sage: X = S1.smash_product(RP2) + sage: X.homology(base_ring=GF(2)) # needs sage.modules {0: Vector space of dimension 0 over Finite Field of size 2, 1: Vector space of dimension 0 over Finite Field of size 2, 2: Vector space of dimension 1 over Finite Field of size 2, 3: Vector space of dimension 1 over Finite Field of size 2} - sage: T = S1.product(S1) # optional - sage.graphs - sage: X = T.smash_product(S1) # optional - sage.graphs - sage: X.homology(reduced=False) # optional - sage.graphs sage.modules + sage: T = S1.product(S1) # needs sage.graphs sage.groups + sage: X = T.smash_product(S1) # needs sage.graphs sage.groups + sage: X.homology(reduced=False) # needs sage.graphs sage.groups sage.modules {0: Z, 1: 0, 2: Z x Z, 3: Z} """ from sage.topology.simplicial_set_constructions import SmashProductOfSimplicialSets_finite diff --git a/src/sage/categories/super_algebras.py b/src/sage/categories/super_algebras.py index cad158f689a..d63b2cc6da5 100644 --- a/src/sage/categories/super_algebras.py +++ b/src/sage/categories/super_algebras.py @@ -76,22 +76,24 @@ def tensor(*parents, **kwargs): EXAMPLES:: - sage: A. = ExteriorAlgebra(ZZ); A.rename("A") # optional - sage.combinat sage.modules - sage: T = A.tensor(A,A); T # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A. = ExteriorAlgebra(ZZ); A.rename("A") + sage: T = A.tensor(A,A); T A # A # A - sage: T in Algebras(ZZ).Graded().SignedTensorProducts() # optional - sage.combinat sage.modules + sage: T in Algebras(ZZ).Graded().SignedTensorProducts() True - sage: T in Algebras(ZZ).Graded().TensorProducts() # optional - sage.combinat sage.modules + sage: T in Algebras(ZZ).Graded().TensorProducts() False - sage: A.rename(None) # optional - sage.combinat sage.modules + sage: A.rename(None) This also works when the other elements do not have a signed tensor product (:trac:`31266`):: - sage: a = SteenrodAlgebra(3).an_element() # optional - sage.modules - sage: M = CombinatorialFreeModule(GF(3), ['s', 't', 'u']) # optional - sage.modules sage.rings.finite_rings - sage: s = M.basis()['s'] # optional - sage.modules sage.rings.finite_rings - sage: tensor([a, s]) # optional - sage.modules sage.rings.finite_rings + sage: # needs sage.combinat sage.modules + sage: a = SteenrodAlgebra(3).an_element() + sage: M = CombinatorialFreeModule(GF(3), ['s', 't', 'u']) + sage: s = M.basis()['s'] + sage: tensor([a, s]) # needs sage.rings.finite_rings 2*Q_1 Q_3 P(2,1) # B['s'] """ constructor = kwargs.pop('constructor', tensor_signed) diff --git a/src/sage/categories/super_algebras_with_basis.py b/src/sage/categories/super_algebras_with_basis.py index affa3386377..014fe6e563e 100644 --- a/src/sage/categories/super_algebras_with_basis.py +++ b/src/sage/categories/super_algebras_with_basis.py @@ -52,8 +52,8 @@ def graded_algebra(self): EXAMPLES:: - sage: W. = algebras.DifferentialWeyl(QQ) # optional - sage.combinat sage.modules - sage: W.graded_algebra() # optional - sage.combinat sage.modules + sage: W. = algebras.DifferentialWeyl(QQ) # needs sage.modules + sage: W.graded_algebra() # needs sage.combinat sage.modules Graded Algebra of Differential Weyl algebra of polynomials in x, y over Rational Field """ @@ -76,27 +76,29 @@ def supercommutator(self, x): EXAMPLES:: - sage: Q = QuadraticForm(ZZ, 3, [1,2,3,4,5,6]) # optional - sage.modules - sage: Cl. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: a = x*y - z # optional - sage.combinat sage.modules - sage: b = x - y + y*z # optional - sage.combinat sage.modules - sage: a.supercommutator(b) # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(ZZ, 3, [1,2,3,4,5,6]) + sage: Cl. = CliffordAlgebra(Q) + sage: a = x*y - z + sage: b = x - y + y*z + sage: a.supercommutator(b) -5*x*y + 8*x*z - 2*y*z - 6*x + 12*y - 5*z - sage: a.supercommutator(Cl.one()) # optional - sage.combinat sage.modules + sage: a.supercommutator(Cl.one()) 0 - sage: Cl.one().supercommutator(a) # optional - sage.combinat sage.modules + sage: Cl.one().supercommutator(a) 0 - sage: Cl.zero().supercommutator(a) # optional - sage.combinat sage.modules + sage: Cl.zero().supercommutator(a) 0 - sage: a.supercommutator(Cl.zero()) # optional - sage.combinat sage.modules + sage: a.supercommutator(Cl.zero()) 0 - sage: Q = QuadraticForm(ZZ, 2, [-1,1,-3]) # optional - sage.modules - sage: Cl. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: [a.supercommutator(b) for a in Cl.basis() for b in Cl.basis()] # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(ZZ, 2, [-1,1,-3]) + sage: Cl. = CliffordAlgebra(Q) + sage: [a.supercommutator(b) for a in Cl.basis() for b in Cl.basis()] [0, 0, 0, 0, 0, -2, 1, -x - 2*y, 0, 1, -6, 6*x + y, 0, x + 2*y, -6*x - y, 0] - sage: [a*b-b*a for a in Cl.basis() for b in Cl.basis()] # optional - sage.combinat sage.modules + sage: [a*b-b*a for a in Cl.basis() for b in Cl.basis()] [0, 0, 0, 0, 0, 0, 2*x*y - 1, -x - 2*y, 0, -2*x*y + 1, 0, 6*x + y, 0, x + 2*y, -6*x - y, 0] @@ -104,8 +106,8 @@ def supercommutator(self, x): supercommutators work as well. We verify the exterior algebra is supercommutative:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: all(b1.supercommutator(b2) == 0 # optional - sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: all(b1.supercommutator(b2) == 0 # needs sage.modules ....: for b1 in E.basis() for b2 in E.basis()) True """ diff --git a/src/sage/categories/super_hopf_algebras_with_basis.py b/src/sage/categories/super_hopf_algebras_with_basis.py index e8974390ba5..afaafc2b8f7 100644 --- a/src/sage/categories/super_hopf_algebras_with_basis.py +++ b/src/sage/categories/super_hopf_algebras_with_basis.py @@ -42,15 +42,15 @@ def antipode(self): EXAMPLES:: - sage: A = SteenrodAlgebra(7) # optional - sage.combinat sage.modules - sage: a = A.an_element() # optional - sage.combinat sage.modules - sage: a, A.antipode(a) # optional - sage.combinat sage.modules + sage: A = SteenrodAlgebra(7) # needs sage.combinat sage.modules + sage: a = A.an_element() # needs sage.combinat sage.modules + sage: a, A.antipode(a) # needs sage.combinat sage.modules (6 Q_1 Q_3 P(2,1), Q_1 Q_3 P(2,1)) TESTS:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: [b.antipode() for b in E.basis()] # optional - sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: [b.antipode() for b in E.basis()] # needs sage.modules [1, -x, -y, x*y] """ if self.antipode_on_basis is not NotImplemented: @@ -88,8 +88,8 @@ def _test_antipode(self, **options): TESTS:: - sage: A = SteenrodAlgebra(7) # optional - sage.combinat sage.modules - sage: A._test_antipode() # long time # optional - sage.combinat sage.modules + sage: A = SteenrodAlgebra(7) # needs sage.combinat sage.modules + sage: A._test_antipode() # long time # needs sage.combinat sage.modules """ tester = self._tester(**options) diff --git a/src/sage/categories/super_lie_conformal_algebras.py b/src/sage/categories/super_lie_conformal_algebras.py index 82a11f5f2cc..9e38c4aa3e1 100644 --- a/src/sage/categories/super_lie_conformal_algebras.py +++ b/src/sage/categories/super_lie_conformal_algebras.py @@ -27,16 +27,16 @@ class SuperLieConformalAlgebras(SuperModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(AA).Super() # optional - sage.rings.number_field + sage: LieConformalAlgebras(AA).Super() # needs sage.rings.number_field Category of super Lie conformal algebras over Algebraic Real Field Notice that we can force to have a *purely even* super Lie conformal algebra:: sage: bosondict = {('a','a'): {1:{('K',0):1}}} - sage: R = LieConformalAlgebra(QQ, bosondict, names=('a',), # optional - sage.combinat sage.modules + sage: R = LieConformalAlgebra(QQ, bosondict, names=('a',), # needs sage.combinat sage.modules ....: central_elements=('K',), super=True) - sage: [g.is_even_odd() for g in R.gens()] # optional - sage.combinat sage.modules + sage: [g.is_even_odd() for g in R.gens()] # needs sage.combinat sage.modules [0, 0] """ def extra_super_categories(self): @@ -57,7 +57,7 @@ def example(self): EXAMPLES:: - sage: LieConformalAlgebras(QQ).Super().example() # optional - sage.combinat sage.modules + sage: LieConformalAlgebras(QQ).Super().example() # needs sage.combinat sage.modules The Neveu-Schwarz super Lie conformal algebra over Rational Field """ from sage.algebras.lie_conformal_algebras.neveu_schwarz_lie_conformal_algebra\ @@ -79,30 +79,30 @@ def _test_jacobi(self, **options): By default, this method tests only the elements returned by ``self.some_elements()``:: - sage: V = lie_conformal_algebras.Affine(QQ, 'B2') # optional - sage.combinat sage.modules - sage: V._test_jacobi() # long time (6 seconds) # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'B2') # needs sage.combinat sage.modules + sage: V._test_jacobi() # long time (6 seconds) # needs sage.combinat sage.modules It works for super Lie conformal algebras too:: - sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # optional - sage.combinat sage.modules - sage: V._test_jacobi() # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) # needs sage.combinat sage.modules + sage: V._test_jacobi() # needs sage.combinat sage.modules We can use specific elements by passing the ``elements`` keyword argument:: - sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # optional - sage.combinat sage.modules + sage: V = lie_conformal_algebras.Affine(QQ, 'A1', # needs sage.combinat sage.modules ....: names=('e', 'h', 'f')) - sage: V.inject_variables() # optional - sage.combinat sage.modules + sage: V.inject_variables() # needs sage.combinat sage.modules Defining e, h, f, K - sage: V._test_jacobi(elements=(e, 2*f + h, 3*h)) # optional - sage.combinat sage.modules + sage: V._test_jacobi(elements=(e, 2*f + h, 3*h)) # needs sage.combinat sage.modules TESTS:: sage: wrongdict = {('a', 'a'): {0: {('b', 0): 1}}, ....: ('b', 'a'): {0: {('a', 0): 1}}} - sage: V = LieConformalAlgebra(QQ, wrongdict, # optional - sage.combinat sage.modules + sage: V = LieConformalAlgebra(QQ, wrongdict, # needs sage.combinat sage.modules ....: names=('a', 'b'), parity=(1, 0)) - sage: V._test_jacobi() # optional - sage.combinat sage.modules + sage: V._test_jacobi() # needs sage.combinat sage.modules Traceback (most recent call last): ... AssertionError: {(0, 0): -3*a} != {} - {(0, 0): -3*a} + {} @@ -163,10 +163,10 @@ def is_even_odd(self): EXAMPLES:: - sage: R = lie_conformal_algebras.NeveuSchwarz(QQ) # optional - sage.combinat sage.modules - sage: R.inject_variables() # optional - sage.combinat sage.modules + sage: R = lie_conformal_algebras.NeveuSchwarz(QQ) # needs sage.combinat sage.modules + sage: R.inject_variables() # needs sage.combinat sage.modules Defining L, G, C - sage: G.is_even_odd() # optional - sage.combinat sage.modules + sage: G.is_even_odd() # needs sage.combinat sage.modules 1 """ @@ -176,7 +176,7 @@ class Graded(GradedModulesCategory): EXAMPLES:: - sage: LieConformalAlgebras(AA).Super().Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(AA).Super().Graded() # needs sage.rings.number_field Category of H-graded super Lie conformal algebras over Algebraic Real Field """ def _repr_object_names(self): @@ -185,7 +185,7 @@ def _repr_object_names(self): EXAMPLES:: - sage: LieConformalAlgebras(QQbar).Graded() # optional - sage.rings.number_field + sage: LieConformalAlgebras(QQbar).Graded() # needs sage.rings.number_field Category of H-graded Lie conformal algebras over Algebraic Field """ return "H-graded {}".format(self.base_category()._repr_object_names()) diff --git a/src/sage/categories/super_modules.py b/src/sage/categories/super_modules.py index 2efd5f6e7e2..0fbd94fbf31 100644 --- a/src/sage/categories/super_modules.py +++ b/src/sage/categories/super_modules.py @@ -182,12 +182,13 @@ def is_even_odd(self): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: cat = Algebras(QQ).WithBasis().Super() - sage: C = CombinatorialFreeModule(QQ, Partitions(), category=cat) # optional - sage.combinat sage.modules - sage: C.degree_on_basis = sum # optional - sage.combinat sage.modules - sage: C.basis()[2,2,1].is_even_odd() # optional - sage.combinat sage.modules + sage: C = CombinatorialFreeModule(QQ, Partitions(), category=cat) + sage: C.degree_on_basis = sum + sage: C.basis()[2,2,1].is_even_odd() 1 - sage: C.basis()[2,2].is_even_odd() # optional - sage.combinat sage.modules + sage: C.basis()[2,2].is_even_odd() 0 """ return self.degree() % 2 @@ -198,12 +199,13 @@ def is_even(self): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: cat = Algebras(QQ).WithBasis().Super() - sage: C = CombinatorialFreeModule(QQ, Partitions(), category=cat) # optional - sage.combinat sage.modules - sage: C.degree_on_basis = sum # optional - sage.combinat sage.modules - sage: C.basis()[2,2,1].is_even() # optional - sage.combinat sage.modules + sage: C = CombinatorialFreeModule(QQ, Partitions(), category=cat) + sage: C.degree_on_basis = sum + sage: C.basis()[2,2,1].is_even() False - sage: C.basis()[2,2].is_even() # optional - sage.combinat sage.modules + sage: C.basis()[2,2].is_even() True """ return self.is_even_odd() == 0 @@ -214,12 +216,13 @@ def is_odd(self): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: cat = Algebras(QQ).WithBasis().Super() - sage: C = CombinatorialFreeModule(QQ, Partitions(), category=cat) # optional - sage.combinat sage.modules - sage: C.degree_on_basis = sum # optional - sage.combinat sage.modules - sage: C.basis()[2,2,1].is_odd() # optional - sage.combinat sage.modules + sage: C = CombinatorialFreeModule(QQ, Partitions(), category=cat) + sage: C.degree_on_basis = sum + sage: C.basis()[2,2,1].is_odd() True - sage: C.basis()[2,2].is_odd() # optional - sage.combinat sage.modules + sage: C.basis()[2,2].is_odd() False """ return self.is_even_odd() == 1 diff --git a/src/sage/categories/super_modules_with_basis.py b/src/sage/categories/super_modules_with_basis.py index dff6b54fbe2..ef4bbc048e8 100644 --- a/src/sage/categories/super_modules_with_basis.py +++ b/src/sage/categories/super_modules_with_basis.py @@ -53,11 +53,12 @@ def _even_odd_on_basis(self, m): EXAMPLES:: - sage: Q = QuadraticForm(QQ, 2, [1,2,3]) # optional - sage.modules - sage: C. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: C._even_odd_on_basis((0,)) # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(QQ, 2, [1,2,3]) + sage: C. = CliffordAlgebra(Q) + sage: C._even_odd_on_basis((0,)) 1 - sage: C._even_odd_on_basis((0,1)) # optional - sage.combinat sage.modules + sage: C._even_odd_on_basis((0,1)) 0 """ return self.degree_on_basis(m) % 2 @@ -70,27 +71,29 @@ def is_super_homogeneous(self): EXAMPLES:: - sage: Q = QuadraticForm(QQ, 2, [1,2,3]) # optional - sage.modules - sage: C. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: a = x + y # optional - sage.combinat sage.modules - sage: a.is_super_homogeneous() # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(QQ, 2, [1,2,3]) + sage: C. = CliffordAlgebra(Q) + sage: a = x + y + sage: a.is_super_homogeneous() True - sage: a = x*y + 4 # optional - sage.combinat sage.modules - sage: a.is_super_homogeneous() # optional - sage.combinat sage.modules + sage: a = x*y + 4 + sage: a.is_super_homogeneous() True - sage: a = x*y + x - 3*y + 4 # optional - sage.combinat sage.modules - sage: a.is_super_homogeneous() # optional - sage.combinat sage.modules + sage: a = x*y + x - 3*y + 4 + sage: a.is_super_homogeneous() False The exterior algebra has a `\ZZ` grading, which induces the `\ZZ / 2\ZZ` grading. However the definition of homogeneous elements differs because of the different gradings:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: a = x*y + 4 # optional - sage.combinat sage.modules - sage: a.is_super_homogeneous() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) + sage: a = x*y + 4 + sage: a.is_super_homogeneous() True - sage: a.is_homogeneous() # optional - sage.combinat sage.modules + sage: a.is_homogeneous() False """ even_odd = self.parent()._even_odd_on_basis @@ -110,22 +113,23 @@ def is_even_odd(self): EXAMPLES:: - sage: Q = QuadraticForm(QQ, 2, [1,2,3]) # optional - sage.modules - sage: C. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: a = x + y # optional - sage.combinat sage.modules - sage: a.is_even_odd() # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(QQ, 2, [1,2,3]) + sage: C. = CliffordAlgebra(Q) + sage: a = x + y + sage: a.is_even_odd() 1 - sage: a = x*y + 4 # optional - sage.combinat sage.modules - sage: a.is_even_odd() # optional - sage.combinat sage.modules + sage: a = x*y + 4 + sage: a.is_even_odd() 0 - sage: a = x + 4 # optional - sage.combinat sage.modules - sage: a.is_even_odd() # optional - sage.combinat sage.modules + sage: a = x + 4 + sage: a.is_even_odd() Traceback (most recent call last): ... ValueError: element is not homogeneous - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: (x*y).is_even_odd() # optional - sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: (x*y).is_even_odd() # needs sage.modules 0 """ if not self.support(): @@ -140,18 +144,19 @@ def even_component(self): EXAMPLES:: - sage: Q = QuadraticForm(QQ, 2, [1,2,3]) # optional - sage.modules - sage: C. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: a = x*y + x - 3*y + 4 # optional - sage.combinat sage.modules - sage: a.even_component() # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(QQ, 2, [1,2,3]) + sage: C. = CliffordAlgebra(Q) + sage: a = x*y + x - 3*y + 4 + sage: a.even_component() x*y + 4 TESTS: Check that this really return ``A.zero()`` and not a plain ``0``:: - sage: a = x + y # optional - sage.combinat sage.modules - sage: a.even_component().parent() is C # optional - sage.combinat sage.modules + sage: a = x + y # needs sage.modules + sage: a.even_component().parent() is C # needs sage.modules True """ even_odd = self.parent()._even_odd_on_basis @@ -165,18 +170,19 @@ def odd_component(self): EXAMPLES:: - sage: Q = QuadraticForm(QQ, 2, [1,2,3]) # optional - sage.modules - sage: C. = CliffordAlgebra(Q) # optional - sage.combinat sage.modules - sage: a = x*y + x - 3*y + 4 # optional - sage.combinat sage.modules - sage: a.odd_component() # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: Q = QuadraticForm(QQ, 2, [1,2,3]) + sage: C. = CliffordAlgebra(Q) + sage: a = x*y + x - 3*y + 4 + sage: a.odd_component() x - 3*y TESTS: Check that this really return ``A.zero()`` and not a plain ``0``:: - sage: a = x*y # optional - sage.combinat sage.modules - sage: a.odd_component().parent() is C # optional - sage.combinat sage.modules + sage: a = x*y # needs sage.modules + sage: a.odd_component().parent() is C # needs sage.modules True """ even_odd = self.parent()._even_odd_on_basis diff --git a/src/sage/categories/supercommutative_algebras.py b/src/sage/categories/supercommutative_algebras.py index 9cb2f609a8c..1928c7057dc 100644 --- a/src/sage/categories/supercommutative_algebras.py +++ b/src/sage/categories/supercommutative_algebras.py @@ -73,15 +73,15 @@ def _test_supercommutativity(self, **options): By default, this method tests only the elements returned by ``self.some_elements()``:: - sage: E. = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules - sage: E._test_supercommutativity() # optional - sage.combinat sage.modules + sage: E. = ExteriorAlgebra(QQ) # needs sage.modules + sage: E._test_supercommutativity() # needs sage.modules However, the elements tested can be customized with the ``elements`` keyword argument, but the elements must be homogeneous:: - sage: E._test_supercommutativity(elements=[x+y, x*y-3*y*z, x*y*z]) # optional - sage.combinat sage.modules - sage: E._test_supercommutativity(elements=[x+x*y]) # optional - sage.combinat sage.modules + sage: E._test_supercommutativity(elements=[x+y, x*y-3*y*z, x*y*z]) # needs sage.modules + sage: E._test_supercommutativity(elements=[x+x*y]) # needs sage.modules Traceback (most recent call last): ... ValueError: element is not homogeneous diff --git a/src/sage/categories/supercrystals.py b/src/sage/categories/supercrystals.py index a68c1d7c591..239aa8c0a86 100644 --- a/src/sage/categories/supercrystals.py +++ b/src/sage/categories/supercrystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.graphs sage.combinat +# sage.doctest: needs sage.graphs sage.combinat r""" Supercrystals """ diff --git a/src/sage/categories/triangular_kac_moody_algebras.py b/src/sage/categories/triangular_kac_moody_algebras.py index 434ff22c1c7..e9c3f1ad167 100644 --- a/src/sage/categories/triangular_kac_moody_algebras.py +++ b/src/sage/categories/triangular_kac_moody_algebras.py @@ -60,10 +60,10 @@ def _part_on_basis(self, m): EXAMPLES:: - sage: L = lie_algebras.so(QQ, 5) # optional - sage.combinat sage.modules - sage: L.f() # optional - sage.combinat sage.modules + sage: L = lie_algebras.so(QQ, 5) # needs sage.combinat sage.modules + sage: L.f() # needs sage.combinat sage.modules Finite family {1: E[-alpha[1]], 2: E[-alpha[2]]} - sage: L.f(1) # optional - sage.combinat sage.modules + sage: L.f(1) # needs sage.combinat sage.modules E[-alpha[1]] """ deg = self.degree_on_basis(m) @@ -100,8 +100,8 @@ def _part_generators(self, positive=False): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['E', 6]) # optional - sage.combinat sage.modules - sage: list(L._part_generators(False)) # optional - sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type=['E', 6]) # needs sage.combinat sage.modules + sage: list(L._part_generators(False)) # needs sage.combinat sage.modules [E[-alpha[1]], E[-alpha[2]], E[-alpha[3]], E[-alpha[4]], E[-alpha[5]], E[-alpha[6]]] """ @@ -128,10 +128,10 @@ def e(self, i=None): EXAMPLES:: - sage: L = lie_algebras.so(QQ, 5) # optional - sage.combinat sage.modules - sage: L.e() # optional - sage.combinat sage.modules + sage: L = lie_algebras.so(QQ, 5) # needs sage.combinat sage.modules + sage: L.e() # needs sage.combinat sage.modules Finite family {1: E[alpha[1]], 2: E[alpha[2]]} - sage: L.e(1) # optional - sage.combinat sage.modules + sage: L.e(1) # needs sage.combinat sage.modules E[alpha[1]] """ E = self._part_generators(True) @@ -150,10 +150,10 @@ def f(self, i=None): EXAMPLES:: - sage: L = lie_algebras.so(QQ, 5) # optional - sage.combinat sage.modules - sage: L.f() # optional - sage.combinat sage.modules + sage: L = lie_algebras.so(QQ, 5) # needs sage.combinat sage.modules + sage: L.f() # needs sage.combinat sage.modules Finite family {1: E[-alpha[1]], 2: E[-alpha[2]]} - sage: L.f(1) # optional - sage.combinat sage.modules + sage: L.f(1) # needs sage.combinat sage.modules E[-alpha[1]] """ F = self._part_generators(False) @@ -168,8 +168,8 @@ def _negative_half_index_set(self): EXAMPLES:: - sage: L = lie_algebras.so(QQ, 5) # optional - sage.combinat sage.modules - sage: L._negative_half_index_set() # optional - sage.combinat sage.modules + sage: L = lie_algebras.so(QQ, 5) # needs sage.combinat sage.modules + sage: L._negative_half_index_set() # needs sage.combinat sage.modules [-alpha[2], -alpha[1], -alpha[1] - alpha[2], -alpha[1] - 2*alpha[2]] """ @@ -186,15 +186,16 @@ def _weight_action(self, m, wt): EXAMPLES:: - sage: L = lie_algebras.sp(QQ, 6) # optional - sage.combinat sage.modules - sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() # optional - sage.combinat sage.modules - sage: mu = La[1] - 3/5*La[2] # optional - sage.combinat sage.modules - sage: ac = L.cartan_type().root_system().coroot_lattice().simple_roots() # optional - sage.combinat sage.modules - sage: L._weight_action(ac[1], mu) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.sp(QQ, 6) + sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() + sage: mu = La[1] - 3/5*La[2] + sage: ac = L.cartan_type().root_system().coroot_lattice().simple_roots() + sage: L._weight_action(ac[1], mu) 1 - sage: L._weight_action(ac[2], mu) # optional - sage.combinat sage.modules + sage: L._weight_action(ac[2], mu) -3/5 - sage: L._weight_action(ac[3], mu) # optional - sage.combinat sage.modules + sage: L._weight_action(ac[3], mu) 0 """ @@ -210,11 +211,12 @@ def verma_module(self, la, basis_key=None, **kwds): EXAMPLES:: - sage: L = lie_algebras.sl(QQ, 3) # optional - sage.combinat sage.modules - sage: P = L.cartan_type().root_system().weight_lattice() # optional - sage.combinat sage.modules - sage: La = P.fundamental_weights() # optional - sage.combinat sage.modules - sage: M = L.verma_module(La[1] + La[2]) # optional - sage.combinat sage.modules - sage: M # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.sl(QQ, 3) + sage: P = L.cartan_type().root_system().weight_lattice() + sage: La = P.fundamental_weights() + sage: M = L.verma_module(La[1] + La[2]) + sage: M Verma module with highest weight Lambda[1] + Lambda[2] of Lie algebra of ['A', 2] in the Chevalley basis """ @@ -234,18 +236,19 @@ def part(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type="F4") # optional - sage.combinat sage.modules - sage: L.inject_variables() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = LieAlgebra(QQ, cartan_type="F4") + sage: L.inject_variables() Defining e1, e2, e3, e4, f1, f2, f3, f4, h1, h2, h3, h4 - sage: e1.part() # optional - sage.combinat sage.modules + sage: e1.part() 1 - sage: f4.part() # optional - sage.combinat sage.modules + sage: f4.part() -1 - sage: (h2 + h3).part() # optional - sage.combinat sage.modules + sage: (h2 + h3).part() 0 - sage: (f1.bracket(f2) + 4*f4).part() # optional - sage.combinat sage.modules + sage: (f1.bracket(f2) + 4*f4).part() -1 - sage: (e1 + f1).part() # optional - sage.combinat sage.modules + sage: (e1 + f1).part() Traceback (most recent call last): ... ValueError: element is not in one part diff --git a/src/sage/categories/unique_factorization_domains.py b/src/sage/categories/unique_factorization_domains.py index f3d6b565316..851bfe80175 100644 --- a/src/sage/categories/unique_factorization_domains.py +++ b/src/sage/categories/unique_factorization_domains.py @@ -65,7 +65,7 @@ def __contains__(self, x): """ EXAMPLES:: - sage: GF(4, "a") in UniqueFactorizationDomains() # optional - sage.rings.finite_rings + sage: GF(4, "a") in UniqueFactorizationDomains() # needs sage.rings.finite_rings True sage: QQ in UniqueFactorizationDomains() True @@ -162,10 +162,11 @@ def _gcd_univariate_polynomial(self, f, g): Check that :trac:`23620` has been resolved:: - sage: R. = ZpFM(2)[] # optional - sage.rings.padics - sage: f = 2*x + 2 # optional - sage.rings.padics - sage: g = 4*x + 2 # optional - sage.rings.padics - sage: f.gcd(g).parent() is R # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: R. = ZpFM(2)[] + sage: f = 2*x + 2 + sage: g = 4*x + 2 + sage: f.gcd(g).parent() is R True """ @@ -295,4 +296,4 @@ def squarefree_part(self): """ decomp = self.squarefree_decomposition() - return prod(fac for fac, mult in decomp if mult%2 == 1) + return prod(fac for fac, mult in decomp if mult % 2 == 1) diff --git a/src/sage/categories/unital_algebras.py b/src/sage/categories/unital_algebras.py index 388a6e940a7..8e58f12e167 100644 --- a/src/sage/categories/unital_algebras.py +++ b/src/sage/categories/unital_algebras.py @@ -18,6 +18,7 @@ from sage.categories.homset import Hom from sage.categories.rings import Rings from sage.categories.magmatic_algebras import MagmaticAlgebras +from sage.categories.cartesian_product import CartesianProductsCategory class UnitalAlgebras(CategoryWithAxiom_over_base_ring): @@ -25,7 +26,7 @@ class UnitalAlgebras(CategoryWithAxiom_over_base_ring): The category of non-associative algebras over a given base ring. A non-associative algebra over a ring `R` is a module over `R` - which s also a unital magma. + which is also a unital magma. .. WARNING:: @@ -61,10 +62,10 @@ def from_base_ring(self, r): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field - sage: A.from_base_ring(1) # optional - sage.combinat sage.modules + sage: A.from_base_ring(1) # needs sage.combinat sage.modules B[word: ] """ return self.one()._lmul_(r) @@ -76,18 +77,18 @@ def __init_extra__(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example(); A # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example(); A # needs sage.combinat sage.modules An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field sage: coercion_model = sage.structure.element.get_coercion_model() - sage: coercion_model.discover_coercion(QQ, A) # optional - sage.combinat sage.modules + sage: coercion_model.discover_coercion(QQ, A) # needs sage.combinat sage.modules ((map internal to coercion system -- copy before use) Generic morphism: From: Rational Field To: An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field, None) - sage: A(1) # indirect doctest # optional - sage.combinat sage.modules + sage: A(1) # indirect doctest # needs sage.combinat sage.modules B[word: ] TESTS: @@ -95,15 +96,16 @@ def __init_extra__(self): Ensure that :trac:`28328` is fixed and that non-associative algebras are supported:: - sage: class Foo(CombinatorialFreeModule): # optional - sage.modules + sage: # needs sage.modules + sage: class Foo(CombinatorialFreeModule): ....: def one(self): ....: return self.monomial(0) sage: from sage.categories.magmatic_algebras import MagmaticAlgebras sage: C = MagmaticAlgebras(QQ).WithBasis().Unital() - sage: F = Foo(QQ, (1,), category=C) # optional - sage.modules - sage: F(0) # optional - sage.modules + sage: F = Foo(QQ, (1,), category=C) + sage: F(0) 0 - sage: F(3) # optional - sage.modules + sage: F(3) 3*B[0] sage: class Bar(Parent): @@ -185,8 +187,8 @@ def _coerce_map_from_base_ring(self): Check that :trac:`29312` is fixed:: - sage: F. = FreeAlgebra(QQ, implementation='letterplace') # optional - sage.combinat sage.modules - sage: F._coerce_map_from_base_ring() # optional - sage.combinat sage.modules + sage: F. = FreeAlgebra(QQ, implementation='letterplace') # needs sage.combinat sage.modules + sage: F._coerce_map_from_base_ring() # needs sage.combinat sage.modules Generic morphism: From: Rational Field To: Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field @@ -276,12 +278,13 @@ def one_basis(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: A.one_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() + sage: A.one_basis() word: - sage: A.one() # optional - sage.combinat sage.modules + sage: A.one() B[word: ] - sage: A.from_base_ring(4) # optional - sage.combinat sage.modules + sage: A.from_base_ring(4) 4*B[word: ] """ @@ -297,33 +300,35 @@ def one_from_one_basis(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: A.one_basis() # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() + sage: A.one_basis() word: - sage: A.one_from_one_basis() # optional - sage.combinat sage.modules + sage: A.one_from_one_basis() B[word: ] - sage: A.one() # optional - sage.combinat sage.modules + sage: A.one() B[word: ] TESTS: Try to check that :trac:`5843` Heisenbug is fixed:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: B = AlgebrasWithBasis(QQ).example(('a', 'c')) # optional - sage.combinat sage.modules - sage: A == B # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() + sage: B = AlgebrasWithBasis(QQ).example(('a', 'c')) + sage: A == B False - sage: Aone = A.one_from_one_basis # optional - sage.combinat sage.modules - sage: Bone = B.one_from_one_basis # optional - sage.combinat sage.modules - sage: Aone is Bone # optional - sage.combinat sage.modules + sage: Aone = A.one_from_one_basis + sage: Bone = B.one_from_one_basis + sage: Aone is Bone False Even if called in the wrong order, they should returns their respective one:: - sage: Bone().parent() is B # optional - sage.combinat sage.modules + sage: Bone().parent() is B # needs sage.combinat sage.modules True - sage: Aone().parent() is A # optional - sage.combinat sage.modules + sage: Aone().parent() is A # needs sage.combinat sage.modules True """ return self.monomial(self.one_basis()) #. @@ -335,10 +340,10 @@ def one(self): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: A.one_basis() # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() # needs sage.combinat sage.modules + sage: A.one_basis() # needs sage.combinat sage.modules word: - sage: A.one() # optional - sage.combinat sage.modules + sage: A.one() # needs sage.combinat sage.modules B[word: ] """ if self.one_basis is NotImplemented: @@ -350,8 +355,8 @@ def from_base_ring(self): """ TESTS:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: A.from_base_ring(3) # optional - sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() # needs sage.combinat sage.modules + sage: A.from_base_ring(3) # needs sage.combinat sage.modules 3*B[word: ] """ if self.one_basis is NotImplemented: @@ -368,12 +373,65 @@ def from_base_ring_from_one_basis(self, r): EXAMPLES:: - sage: A = AlgebrasWithBasis(QQ).example() # optional - sage.combinat sage.modules - sage: A.from_base_ring_from_one_basis(3) # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: A = AlgebrasWithBasis(QQ).example() + sage: A.from_base_ring_from_one_basis(3) 3*B[word: ] - sage: A.from_base_ring(3) # optional - sage.combinat sage.modules + sage: A.from_base_ring(3) 3*B[word: ] - sage: A(3) # optional - sage.combinat sage.modules + sage: A(3) 3*B[word: ] """ return self.term(self.one_basis(), r) + + class CartesianProducts(CartesianProductsCategory): + r""" + The category of unital algebras constructed as Cartesian products + of unital algebras. + + This construction gives the direct product of algebras. See + discussion on: + + - http://groups.google.fr/group/sage-devel/browse_thread/thread/35a72b1d0a2fc77a/348f42ae77a66d16#348f42ae77a66d16 + - :wikipedia:`Direct_product` + """ + def extra_super_categories(self): + """ + A Cartesian product of algebras is endowed with a natural + unital algebra structure. + + EXAMPLES:: + + sage: from sage.categories.unital_algebras import UnitalAlgebras + sage: C = UnitalAlgebras(QQ).CartesianProducts() + sage: C.extra_super_categories() + [Category of unital algebras over Rational Field] + sage: sorted(C.super_categories(), key=str) + [Category of Cartesian products of distributive magmas and additive magmas, + Category of Cartesian products of unital magmas, + Category of Cartesian products of vector spaces over Rational Field, + Category of unital algebras over Rational Field] + """ + return [self.base_category()] + + class ParentMethods: + @cached_method + def one(self): + r""" + Return the multiplicative unit element. + + EXAMPLES:: + + sage: S2 = simplicial_complexes.Sphere(2) + sage: H = S2.cohomology_ring(QQ) + sage: C = cartesian_product([H, H]) + sage: one = C.one() + sage: one + B[(0, (0, 0))] + B[(1, (0, 0))] + sage: one == one * one + True + sage: all(b == b * one for b in C.basis()) + True + """ + data = enumerate(self.cartesian_factors()) + return self._cartesian_product_of_elements([C.one() for i, C in data]) diff --git a/src/sage/categories/vector_bundles.py b/src/sage/categories/vector_bundles.py index d5388e381c1..3f3bed1f2d0 100644 --- a/src/sage/categories/vector_bundles.py +++ b/src/sage/categories/vector_bundles.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.symbolic +# sage.doctest: needs sage.symbolic r""" Vector Bundles """ @@ -97,7 +97,7 @@ def _repr_object_names(self): """ base_space = self._base_space return Category_over_base_ring._repr_object_names(self) + \ - " with base space %s"%base_space + " with base space %s" % base_space class SubcategoryMethods: @cached_method diff --git a/src/sage/categories/vector_spaces.py b/src/sage/categories/vector_spaces.py index 508b0fc1f61..9497c143862 100644 --- a/src/sage/categories/vector_spaces.py +++ b/src/sage/categories/vector_spaces.py @@ -82,8 +82,8 @@ def __init__(self, K): TESTS:: - sage: C = QQ^10 # vector space # optional - sage.modules - sage: TestSuite(C).run() # optional - sage.modules + sage: C = QQ^10 # vector space # needs sage.modules + sage: TestSuite(C).run() # needs sage.modules sage: TestSuite(VectorSpaces(QQ)).run() """ Category_module.__init__(self, K) @@ -94,15 +94,15 @@ def _call_(self, x): EXAMPLES:: - sage: VectorSpaces(QQ)(ZZ^3) # optional - sage.modules + sage: VectorSpaces(QQ)(ZZ^3) # needs sage.modules Vector space of dimension 3 over Rational Field TESTS: Check whether :trac:`30174` is fixed:: - sage: Q3 = FiniteRankFreeModule(QQ, 3) # optional - sage.modules - sage: Modules(QQ)(Q3) is Q3 # optional - sage.modules + sage: Q3 = FiniteRankFreeModule(QQ, 3) # needs sage.modules + sage: Modules(QQ)(Q3) is Q3 # needs sage.modules True """ @@ -111,7 +111,7 @@ def _call_(self, x): if V.base_field() != self.base_field(): V = V.change_ring(self.base_field()) 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 V def base_field(self): @@ -162,15 +162,15 @@ def dimension(self): EXAMPLES:: - sage: M = FreeModule(FiniteField(19), 100) # optional - sage.modules sage.rings.finite_rings - sage: W = M.submodule([M.gen(50)]) # optional - sage.modules sage.rings.finite_rings - sage: W.dimension() # optional - sage.modules sage.rings.finite_rings + sage: M = FreeModule(FiniteField(19), 100) # needs sage.modules + sage: W = M.submodule([M.gen(50)]) # needs sage.modules + sage: W.dimension() # needs sage.modules 1 - sage: M = FiniteRankFreeModule(QQ, 3) # optional - sage.modules - sage: M.dimension() # optional - sage.modules + sage: M = FiniteRankFreeModule(QQ, 3) # needs sage.modules + sage: M.dimension() # needs sage.modules 3 - sage: M.tensor_module(1, 2).dimension() # optional - sage.modules + sage: M.tensor_module(1, 2).dimension() # needs sage.modules 27 """ @@ -253,7 +253,7 @@ def example(self, base_ring=None): EXAMPLES:: - sage: Modules(QQ).WithBasis().Graded().example() # optional - sage.combinat sage.modules + sage: Modules(QQ).WithBasis().Graded().example() # needs sage.combinat sage.modules An example of a graded module with basis: the free module on partitions over Rational Field """ @@ -274,7 +274,7 @@ def example(self, base_ring=None): EXAMPLES:: - sage: Modules(QQ).WithBasis().Graded().example() # optional - sage.combinat sage.modules + sage: Modules(QQ).WithBasis().Graded().example() # needs sage.combinat sage.modules An example of a graded module with basis: the free module on partitions over Rational Field """ diff --git a/src/sage/categories/weyl_groups.py b/src/sage/categories/weyl_groups.py index 70f8879353e..1322ecd8499 100644 --- a/src/sage/categories/weyl_groups.py +++ b/src/sage/categories/weyl_groups.py @@ -1,13 +1,13 @@ -# sage.doctest: optional - sage.combinat sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Weyl Groups """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2009 Nicolas M. Thiery # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -#****************************************************************************** +# https://www.gnu.org/licenses/ +# ***************************************************************************** from sage.misc.cachefunc import cached_method, cached_in_parent_method from sage.misc.lazy_import import LazyImport @@ -315,7 +315,7 @@ def length(x): from sage.graphs.digraph import DiGraph return DiGraph(visited, - name="Parabolic Quantum Bruhat Graph of %s for nodes %s"%(self, index_set), + name="Parabolic Quantum Bruhat Graph of %s for nodes %s" % (self, index_set), format="dict_of_dicts", data_structure="static_sparse") @@ -493,13 +493,13 @@ def stanley_symmetric_function_as_polynomial(self, max_length=None): W = self.parent() pieri_factors = W.pieri_factors() from sage.rings.rational_field import QQ - R = QQ[','.join('x%s'%l for l in range(1,pieri_factors.max_length()+1))] + R = QQ[','.join('x%s' % l for l in range(1, pieri_factors.max_length()+1))] x = R.gens() if self.is_one(): return R.one() return R(sum(2**(pieri_factors.stanley_symm_poly_weight(u))*x[u.length()-1] * v.stanley_symmetric_function_as_polynomial(max_length=u.length()) - for (u,v) in self.left_pieri_factorizations(max_length) + for (u, v) in self.left_pieri_factorizations(max_length) if u != W.one())) def stanley_symmetric_function(self): @@ -747,7 +747,7 @@ def bruhat_lower_covers_coroots(self): [(s1*s2*s1, alphacheck[1] + alphacheck[2] + alphacheck[3]), (s3*s2*s1, alphacheck[2]), (s3*s1*s2, alphacheck[1])] """ - return [(x[0],x[1].reflection_to_coroot()) + return [(x[0], x[1].reflection_to_coroot()) for x in self.bruhat_lower_covers_reflections()] def bruhat_upper_covers_coroots(self): @@ -770,7 +770,7 @@ def bruhat_upper_covers_coroots(self): (s3*s4*s1*s2*s1, alphacheck[4]), (s4*s3*s1*s2*s1, alphacheck[1] + alphacheck[2] + alphacheck[3] + alphacheck[4])] """ - return [(x[0],x[1].reflection_to_coroot()) + return [(x[0], x[1].reflection_to_coroot()) for x in self.bruhat_upper_covers_reflections()] def quantum_bruhat_successors(self, index_set=None, roots=False, quantum_only=False): @@ -840,12 +840,12 @@ def quantum_bruhat_successors(self, index_set=None, roots=False, quantum_only=Fa wrc = wr.coset_representative(index_set) if wrc == wr and wr.length() == w_length_plus_one and not quantum_only: if roots: - successors.append((wr,alpha)) + successors.append((wr, alpha)) else: successors.append(wr) elif alpha.quantum_root() and wrc.length() == w_length_plus_one - lattice.nonparabolic_positive_root_sum(index_set).scalar(alpha.associated_coroot()): if roots: - successors.append((wrc,alpha)) + successors.append((wrc, alpha)) else: successors.append(wrc) return successors diff --git a/src/sage/categories/with_realizations.py b/src/sage/categories/with_realizations.py index dd463186a2a..d0dc8d148bd 100644 --- a/src/sage/categories/with_realizations.py +++ b/src/sage/categories/with_realizations.py @@ -69,46 +69,47 @@ def WithRealizations(self): represented. Consider for example an algebra `A` which admits several natural bases:: - sage: A = Sets().WithRealizations().example(); A # optional - sage.combinat sage.modules + sage: A = Sets().WithRealizations().example(); A # needs sage.modules The subset algebra of {1, 2, 3} over Rational Field For each such basis `B` one implements a parent `P_B` which realizes `A` with its elements represented by expanding them on the basis `B`:: - sage: A.F() # optional - sage.combinat sage.modules + sage: # needs sage.modules + sage: A.F() The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis - sage: A.Out() # optional - sage.combinat sage.modules + sage: A.Out() The subset algebra of {1, 2, 3} over Rational Field in the Out basis - sage: A.In() # optional - sage.combinat sage.modules + sage: A.In() The subset algebra of {1, 2, 3} over Rational Field in the In basis - - sage: A.an_element() # optional - sage.combinat sage.modules + sage: A.an_element() F[{}] + 2*F[{1}] + 3*F[{2}] + F[{1, 2}] If `B` and `B'` are two bases, then the change of basis from `B` to `B'` is implemented by a canonical coercion between `P_B` and `P_{B'}`:: - sage: F = A.F(); In = A.In(); Out = A.Out() # optional - sage.combinat sage.modules - sage: i = In.an_element(); i # optional - sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: F = A.F(); In = A.In(); Out = A.Out() + sage: i = In.an_element(); i In[{}] + 2*In[{1}] + 3*In[{2}] + In[{1, 2}] - sage: F(i) # optional - sage.combinat sage.modules + sage: F(i) 7*F[{}] + 3*F[{1}] + 4*F[{2}] + F[{1, 2}] - sage: F.coerce_map_from(Out) # optional - sage.combinat sage.modules + sage: F.coerce_map_from(Out) Generic morphism: From: The subset algebra of {1, 2, 3} over Rational Field in the Out basis To: The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis allowing for mixed arithmetic:: - sage: (1 + Out.from_set(1)) * In.from_set(2,3) # optional - sage.combinat sage.modules + sage: (1 + Out.from_set(1)) * In.from_set(2,3) # needs sage.combinat sage.modules Out[{}] + 2*Out[{1}] + 2*Out[{2}] + 2*Out[{3}] + 2*Out[{1, 2}] + 2*Out[{1, 3}] + 4*Out[{2, 3}] + 4*Out[{1, 2, 3}] In our example, there are three realizations:: - sage: A.realizations() # optional - sage.combinat sage.modules + sage: A.realizations() # needs sage.modules [The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis, The subset algebra of {1, 2, 3} over Rational Field in the In basis, The subset algebra of {1, 2, 3} over Rational Field in the Out basis] @@ -116,7 +117,7 @@ def WithRealizations(self): Instead of manually defining the shorthands ``F``, ``In``, and ``Out``, as above one can just do:: - sage: A.inject_shorthands() # optional - sage.combinat sage.modules + sage: A.inject_shorthands() # needs sage.combinat sage.modules Defining F as shorthand for The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis Defining In as shorthand for @@ -142,25 +143,25 @@ def WithRealizations(self): We now illustrate this second point by defining the polynomial ring with coefficients in `A`:: - sage: P = A['x']; P # optional - sage.combinat sage.modules + sage: P = A['x']; P # needs sage.modules Univariate Polynomial Ring in x over The subset algebra of {1, 2, 3} over Rational Field - sage: x = P.gen() # optional - sage.combinat sage.modules + sage: x = P.gen() # needs sage.modules In the following examples, the coefficients turn out to be all represented in the `F` basis:: - sage: P.one() # optional - sage.combinat sage.modules + sage: P.one() # needs sage.modules F[{}] - sage: (P.an_element() + 1)^2 # optional - sage.combinat sage.modules + sage: (P.an_element() + 1)^2 # needs sage.modules F[{}]*x^2 + 2*F[{}]*x + F[{}] However we can create a polynomial with mixed coefficients, and compute with it:: - sage: p = P([1, In[{1}], Out[{2}] ]); p # optional - sage.combinat sage.modules + sage: p = P([1, In[{1}], Out[{2}] ]); p # needs sage.combinat sage.modules Out[{2}]*x^2 + In[{1}]*x + F[{}] - sage: p^2 # optional - sage.combinat sage.modules + sage: p^2 # needs sage.combinat sage.modules Out[{2}]*x^4 + (-8*In[{}] + 4*In[{1}] + 8*In[{2}] + 4*In[{3}] - 4*In[{1, 2}] - 2*In[{1, 3}] - 4*In[{2, 3}] + 2*In[{1, 2, 3}])*x^3 @@ -175,7 +176,7 @@ def WithRealizations(self): One can easily coerce all coefficient to a given basis with:: - sage: p.map_coefficients(In) # optional - sage.combinat sage.modules + sage: p.map_coefficients(In) # needs sage.combinat sage.modules (-4*In[{}] + 2*In[{1}] + 4*In[{2}] + 2*In[{3}] - 2*In[{1, 2}] - In[{1, 3}] - 2*In[{2, 3}] + In[{1, 2, 3}])*x^2 + In[{1}]*x + In[{}] @@ -183,7 +184,7 @@ def WithRealizations(self): Alas, the natural notation for constructing such polynomials does not yet work:: - sage: In[{1}] * x # optional - sage.combinat sage.modules + sage: In[{1}] * x # needs sage.combinat sage.modules Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: @@ -197,18 +198,18 @@ def WithRealizations(self): is a category (whose class inherits from :class:`~sage.categories.realizations.Category_realization_of_parent`):: - sage: A.Realizations() # optional - sage.combinat sage.modules + sage: A.Realizations() # needs sage.modules Category of realizations of The subset algebra of {1, 2, 3} over Rational Field The various parent realizing `A` belong to this category:: - sage: A.F() in A.Realizations() # optional - sage.combinat sage.modules + sage: A.F() in A.Realizations() # needs sage.modules True `A` itself is in the category of algebras with realizations:: - sage: A in Algebras(QQ).WithRealizations() # optional - sage.combinat sage.modules + sage: A in Algebras(QQ).WithRealizations() # needs sage.modules True The (mostly technical) ``WithRealizations`` categories are the @@ -228,12 +229,12 @@ def WithRealizations(self): On our example, this simply means that `A` is automatically in the category of rings with realizations (covariance):: - sage: A in Rings().WithRealizations() # optional - sage.combinat sage.modules + sage: A in Rings().WithRealizations() # needs sage.modules True and in the category of algebras (regressiveness):: - sage: A in Algebras(QQ) # optional - sage.combinat sage.modules + sage: A in Algebras(QQ) # needs sage.modules True .. NOTE:: @@ -279,6 +280,7 @@ def WithRealizations(self): """ return WithRealizationsCategory.category_of(self) + Category.WithRealizations = WithRealizations class WithRealizationsCategory(RegressiveCovariantConstructionCategory): diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index e0c8b6e4068..7839cd8c693 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -309,6 +309,7 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, if out_test(N): yield N + # Import the following function so that it is available as # sage.codes.databases.self_dual_binary_codes sage.codes.databases functions # somewhat like a catalog in this respect. diff --git a/src/sage/coding/goppa_code.py b/src/sage/coding/goppa_code.py index cc9fdb4791b..2a974cf1ef2 100644 --- a/src/sage/coding/goppa_code.py +++ b/src/sage/coding/goppa_code.py @@ -436,4 +436,5 @@ def generator_matrix(self): aux = codes.from_parity_check_matrix(pmat) return aux.generator_matrix() + GoppaCode._registered_encoders["GoppaEncoder"] = GoppaCodeEncoder diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index 2b687775102..babb22ff1ce 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -891,7 +891,8 @@ def decoding_radius(self): sage: D.decoding_radius() 1 """ - return (self.code().minimum_distance()-1) // 2 + return (self.code().minimum_distance() - 1) // 2 + ####################### registration ############################### diff --git a/src/sage/coding/parity_check_code.py b/src/sage/coding/parity_check_code.py index 03f23bcc17f..d131ecaf80a 100644 --- a/src/sage/coding/parity_check_code.py +++ b/src/sage/coding/parity_check_code.py @@ -349,6 +349,7 @@ def message_space(self): """ return VectorSpace(self.code().base_field(), self.code().dimension()) + ####################### registration ############################### ParityCheckCode._registered_encoders["ParityCheckCodeGeneratorMatrixEncoder"] = ParityCheckCodeGeneratorMatrixEncoder diff --git a/src/sage/coding/punctured_code.py b/src/sage/coding/punctured_code.py index df57fb90e54..7aafa4f3f27 100644 --- a/src/sage/coding/punctured_code.py +++ b/src/sage/coding/punctured_code.py @@ -709,6 +709,7 @@ def decoding_radius(self, number_erasures=None): elif "error-erasure" in D.decoder_type() and number_erasures is None: raise ValueError("You must provide the number of erasures") + ####################### registration ############################### PuncturedCode._registered_encoders["PuncturedMatrix"] = PuncturedCodePuncturedMatrixEncoder diff --git a/src/sage/coding/subfield_subcode.py b/src/sage/coding/subfield_subcode.py index 2783c66ec4a..9ec9650c43a 100644 --- a/src/sage/coding/subfield_subcode.py +++ b/src/sage/coding/subfield_subcode.py @@ -419,6 +419,7 @@ def decoding_radius(self, **kwargs): """ return self.original_decoder().decoding_radius(**kwargs) + ####################### registration ############################### SubfieldSubcode._registered_decoders["OriginalCode"] = SubfieldSubcodeOriginalCodeDecoder diff --git a/src/sage/combinat/affine_permutation.py b/src/sage/combinat/affine_permutation.py index cbe4ea6fcd0..13144414cb9 100644 --- a/src/sage/combinat/affine_permutation.py +++ b/src/sage/combinat/affine_permutation.py @@ -706,7 +706,7 @@ def maximal_cyclic_factor(self, typ='decreasing', side='right', verbose=False): y = self.clone().apply_simple_reflection(i,side) T = [i] j = i - for count in range(1, self.k): + for _ in range(1, self.k): if (typ[0],side[0]) == ('d', 'r'): j=(j+1)%(k+1) if (typ[0],side[0]) == ('i', 'r'): @@ -917,10 +917,10 @@ def to_bounded_partition(self, typ='decreasing', side='right'): INPUT: - - ``typ`` -- 'increasing' or 'decreasing' (default: 'decreasing'.) + - ``typ`` -- ``'increasing'`` or ``'decreasing'`` (default: ``'decreasing'``.) Chooses whether to find increasing or decreasing sets. - - ``side`` -- 'right' or 'left' (default: 'right'.) Chooses whether to + - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``.) Chooses whether to find maximal sets starting from the left or the right. EXAMPLES:: @@ -941,9 +941,9 @@ def to_core(self, typ='decreasing', side='right'): INPUT: - - ``typ`` -- 'increasing' or 'decreasing' (default: 'decreasing'.) + - ``typ`` -- ``'increasing'`` or ``'decreasing'`` (default: ``'decreasing'``.) - - ``side`` -- 'right' or 'left' (default: 'right'.) Chooses whether to + - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``.) Chooses whether to find maximal sets starting from the left or the right. EXAMPLES:: diff --git a/src/sage/combinat/bijectionist.py b/src/sage/combinat/bijectionist.py index 0c7d50a7659..68d1f322e9f 100644 --- a/src/sage/combinat/bijectionist.py +++ b/src/sage/combinat/bijectionist.py @@ -2174,7 +2174,7 @@ def _preprocess_intertwining_relations(self): A = self._A P = self._P images = defaultdict(set) # A^k -> A, a_1,...,a_k +-> {pi(a_1,...,a_k) for all pi} - for composition_index, pi_rho in enumerate(self._pi_rho): + for pi_rho in self._pi_rho: for a_tuple in itertools.product(*([A]*pi_rho.numargs)): if pi_rho.domain is not None and not pi_rho.domain(*a_tuple): continue diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index 49ddfe13fc0..9527c512360 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -126,9 +126,9 @@ def __init__(self, b, c, u0=0, u1=1): self.c = c self.u0 = u0 self.u1 = u1 - self._period_dict = {} #dictionary to cache the period of a sequence for future lookup - self._PGoodness = {} #dictionary to cache primes that are "good" by some prime power - self._ell = 1 #variable that keeps track of the last prime power to be used as a goodness + self._period_dict = {} # dictionary to cache the period of a sequence for future lookup + self._PGoodness = {} # dictionary to cache primes that are "good" by some prime power + self._ell = 1 # variable that keeps track of the last prime power to be used as a goodness def __repr__(self): """ @@ -468,7 +468,7 @@ def period(self, m): #expand the list of prime factors so every factor is with multiplicity 1 for i0, i1 in Mfac: - for j in range(i1): + for _ in range(i1): C.append(i0) Mfac = C @@ -519,7 +519,9 @@ def pthpowers(self, p, Bound): OUTPUT: - - A list of the indices of all ``p`` th powers less bounded by ``Bound``. If the sequence is degenerate and there are many ``p`` th powers, raises ``ValueError``. + - A list of the indices of all ``p`` th powers less bounded by + ``Bound``. If the sequence is degenerate and there are many + ``p`` th powers, raises :class:`ValueError`. EXAMPLES:: @@ -646,10 +648,10 @@ def pthpowers(self, p, Bound): F = GF(ell) a0 = F(self.u0) - a1 = F(self.u1) #a0 and a1 are variables for terms in sequence + a1 = F(self.u1) # a0 and a1 are variables for terms in sequence bf, cf = F(self.b), F(self.c) - for n in range(Bound): # n is the index of the a0 + for n in range(Bound): # n is the index of the a0 #Check whether a0 is a perfect power mod ell if _is_p_power_mod(a0, p, ell): diff --git a/src/sage/combinat/cluster_complex.py b/src/sage/combinat/cluster_complex.py index edc4f235aeb..e263d983887 100644 --- a/src/sage/combinat/cluster_complex.py +++ b/src/sage/combinat/cluster_complex.py @@ -222,10 +222,6 @@ def __init__(self, W, k, coxeter_element, algorithm): self._W = W self._w0 = w self._k = k - if k == 1: - self.__custom_name = 'Cluster complex' - else: - self.__custom_name = 'Multi-cluster complex' self.set_immutable() @@ -271,7 +267,10 @@ def _repr_(self): sage: ClusterComplex(['A', 2])._repr_() "Cluster complex of type ['A', 2] with 5 vertices and 5 facets" """ - name = self.__custom_name + if self._k == 1: + name = 'Cluster complex' + else: + name = 'Multi-cluster complex' name += (' of type %s with %s vertices and %s facets' % (self.cartan_type(), len(self.vertices()), len(self._facets))) diff --git a/src/sage/combinat/colored_permutations.py b/src/sage/combinat/colored_permutations.py index c7f134efbe0..d97624a218d 100644 --- a/src/sage/combinat/colored_permutations.py +++ b/src/sage/combinat/colored_permutations.py @@ -7,6 +7,7 @@ generalized to `G \wr S_n` """ import itertools +from random import choice from sage.structure.element import MultiplicativeGroupElement from sage.structure.parent import Parent @@ -313,13 +314,13 @@ def has_left_descent(self, i): [False, True, False, True] """ if self.parent()._m == 1: - return self._perm[i-1] > self._perm[i] + return self._perm[i - 1] > self._perm[i] if i == self.parent()._n: return self._colors[-1] != 0 - if self._colors[i-1] != 0: - return self._colors[i] == 0 or self._perm[i-1] < self._perm[i] - return self._colors[i] == 0 and self._perm[i-1] > self._perm[i] + if self._colors[i - 1] != 0: + return self._colors[i] == 0 or self._perm[i - 1] < self._perm[i] + return self._colors[i] == 0 and self._perm[i - 1] > self._perm[i] def reduced_word(self): r""" @@ -563,7 +564,7 @@ def coxeter_matrix(self): """ from sage.combinat.root_system.cartan_type import CartanType if self._m == 1: - return CartanType(['A', self._n-1]).coxeter_matrix() + return CartanType(['A', self._n - 1]).coxeter_matrix() return CartanType(['B', self._n]).coxeter_matrix() @cached_method @@ -580,6 +581,23 @@ def one(self): return self.element_class(self, [self._C.zero()] * self._n, self._P.identity()) + def random_element(self): + """ + Return an element drawn uniformly at random. + + EXAMPLES:: + + sage: C = ColoredPermutations(4, 3) + sage: s = C.random_element(); s # random + [[0, 2, 1], [2, 1, 3]] + sage: s in C + True + """ + return self.element_class(self, + [self._C.random_element() + for _ in range(self._n)], + self._P.random_element()) + def simple_reflection(self, i): r""" Return the ``i``-th simple reflection of ``self``. @@ -883,7 +901,7 @@ def codegrees(self): True """ # Special case for the usual symmetric group - last = self._n-1 if self._m == 1 else self._n + last = self._n - 1 if self._m == 1 else self._n return tuple(self._m * i for i in reversed(range(last))) def number_of_reflection_hyperplanes(self): @@ -979,8 +997,9 @@ def is_well_generated(self): Element = ColoredPermutation + ##################################################################### -## Signed permutations +# Signed permutations class SignedPermutation(ColoredPermutation, @@ -1122,11 +1141,11 @@ def __call__(self, i): if i in ZZ and 1 <= abs(i) <= len(self): i = ZZ(i) if i < 0: - return -self._colors[-i-1] * self._perm[-i-1] - return self._colors[i-1] * self._perm[i-1] - else: - raise TypeError("i (= %s) must equal +/- an integer between %s and %s" - % (i,1,len(self))) + return -self._colors[-i - 1] * self._perm[-i - 1] + return self._colors[i - 1] * self._perm[i - 1] + + raise TypeError("i (= %s) must equal +/- an integer between %s and %s" + % (i, 1, len(self))) def to_matrix(self): """ @@ -1170,14 +1189,13 @@ def has_left_descent(self, i): return self._colors[i] == 1 or self._perm[i - 1] < self._perm[i] return self._colors[i] == 1 and self._perm[i - 1] > self._perm[i] - def to_cycles(self, singletons=True, use_min=True, negative_singletons=True): - """ + def to_cycles(self, singletons=True, use_min=True, negative_cycles=True): + r""" Return the signed permutation ``self`` as a list of disjoint cycles. The cycles are returned in the order of increasing smallest elements, and each cycle is returned as a tuple which starts - with its smallest positive element. We do not include the - corresponding negative cycles. + with its smallest positive element. INPUT: @@ -1186,18 +1204,30 @@ def to_cycles(self, singletons=True, use_min=True, negative_singletons=True): - ``use_min`` -- (default: ``True``) if ``False``, the cycles are returned in the order of increasing *largest* (not smallest) elements, and each cycle starts with its largest element + - ``negative_cycles`` -- (default: ``True``) if ``False``, for any + two cycles `C^{\pm} = \{\pm c_1, \ldots, \pm c_k\}` such that + `C^+ \neq C^-`, this does not include the cycle `C^-` + + .. WARNING:: + + The arugment ``negative_cycles`` does not refer to the usual + definition of a negative cycle; see :meth:`cycle_type`. EXAMPLES:: sage: pi = SignedPermutations(7)([2,-1,4,-6,-5,-3,7]) sage: pi.to_cycles() - [(1, 2, -1, -2), (3, 4, -6), (5, -5), (7,)] + [(1, 2, -1, -2), (3, 4, -6), (-3, -4, 6), (5, -5), (7,), (-7,)] sage: pi.to_cycles(singletons=False) + [(1, 2, -1, -2), (3, 4, -6), (-3, -4, 6), (5, -5)] + sage: pi.to_cycles(negative_cycles=False) + [(1, 2, -1, -2), (3, 4, -6), (5, -5), (7,)] + sage: pi.to_cycles(singletons=False, negative_cycles=False) [(1, 2, -1, -2), (3, 4, -6), (5, -5)] sage: pi.to_cycles(use_min=False) - [(7,), (6, -3, -4), (5, -5), (2, -1, -2, 1)] + [(7,), (-7,), (6, -3, -4), (-6, 3, 4), (5, -5), (2, -1, -2, 1)] sage: pi.to_cycles(singletons=False, use_min=False) - [(6, -3, -4), (5, -5), (2, -1, -2, 1)] + [(6, -3, -4), (-6, 3, 4), (5, -5), (2, -1, -2, 1)] """ cycles = [] @@ -1216,19 +1246,70 @@ def to_cycles(self, singletons=True, use_min=True, negative_singletons=True): cycle = [cycle_first] l[i], next_val = False, l[i] s = self._colors[i] + add_neg = True while next_val != cycle_first: cycle.append(s * next_val) - s *= self._colors[next_val-1] - l[next_val-1], next_val = False, l[next_val-1] + s *= self._colors[next_val - 1] + l[next_val - 1], next_val = False, l[next_val - 1] if s != 1: cycle.extend([-e for e in cycle]) + add_neg = False # Add the cycle to the list of cycles if singletons or len(cycle) > 1: cycles.append(tuple(cycle)) + if negative_cycles and add_neg: + cycles.append(tuple([-e for e in cycle])) return cycles + def cycle_type(self): + r""" + Return a pair of partitions of ``len(self)`` corresponding to the + signed cycle type of ``self``. + + A *cycle* is a tuple `C = (c_0, \ldots, c_{k-1})` with + `\pi(c_i) = c_{i+1}` for `0 \leq i < k` and `\pi(c_{k-1}) = c_0`. + If `C` is a cycle, `\overline{C} = (-c_0, \ldots, -c_{k-1})` is + also a cycle. A cycle is *negative*, if `C = \overline{C}` up + to cyclic reordering. In this case, `k` is necessarily even + and the length of `C` is `k/2`. A *positive cycle* is a pair + `C \overline{C}`, its length is `k`. + + Let `\alpha` be the partition whose parts are the lengths of the + positive cycles and let `\beta` be the partition whose parts are + the lengths of the negative cycles. Then `(\alpha, \beta)` is + the cycle type of `\pi`. + + EXAMPLES:: + + sage: G = SignedPermutations(7) + sage: pi = G([2, -1, 4, -6, -5, -3, 7]) + sage: pi.cycle_type() + ([3, 1], [2, 1]) + + sage: G = SignedPermutations(5) + sage: all(pi.cycle_type().size() == 5 for pi in G) + True + sage: set(pi.cycle_type() for pi in G) == set(PartitionTuples(2, 5)) + True + """ + cycles = self.to_cycles(negative_cycles=False) + pos_cycles = [] + neg_cycles = [] + for C in cycles: + if (not len(C) % 2) and C[0] == -C[len(C)//2]: + neg_cycles.append(C) + else: + pos_cycles.append(C) + pos_type = [len(C) for C in pos_cycles] + pos_type.sort(reverse=True) + neg_type = [len(C) // 2 for C in neg_cycles] + neg_type.sort(reverse=True) + from sage.combinat.partition_tuple import PartitionTuples + PT = PartitionTuples(2, self.parent()._n) + return PT([pos_type, neg_type]) + def order(self): """ Return the multiplicative order of the signed permutation. @@ -1237,11 +1318,11 @@ def order(self): sage: pi = SignedPermutations(7)([2,-1,4,-6,-5,-3,7]) sage: pi.to_cycles(singletons=False) - [(1, 2, -1, -2), (3, 4, -6), (5, -5)] + [(1, 2, -1, -2), (3, 4, -6), (-3, -4, 6), (5, -5)] sage: pi.order() 12 """ - return lcm(len(c) for c in self.to_cycles(singletons=False)) + return lcm(len(c) for c in self.to_cycles(singletons=False, negative_cycles=False)) class SignedPermutations(ColoredPermutations): @@ -1299,7 +1380,6 @@ class SignedPermutations(ColoredPermutations): - :wikipedia:`Hyperoctahedral_group` """ - def __init__(self, n): """ Initialize ``self``. @@ -1336,6 +1416,23 @@ def one(self): return self.element_class(self, [ZZ.one()] * self._n, self._P.identity()) + def random_element(self): + """ + Return an element drawn uniformly at random. + + EXAMPLES:: + + sage: C = SignedPermutations(7) + sage: s = C.random_element(); s # random + [7, 6, -4, -5, 2, 3, -1] + sage: s in C + True + """ + return self.element_class(self, + [choice([ZZ.one(), -ZZ.one()]) + for _ in range(self._n)], + self._P.random_element()) + def simple_reflection(self, i): r""" Return the ``i``-th simple reflection of ``self``. @@ -1454,7 +1551,7 @@ def _coerce_map_from_(self, C): False """ if isinstance(C, Permutations) and C.n == self._n: - return lambda P, x: P.element_class(P, [1]*P._n, x) + return lambda P, x: P.element_class(P, [1] * P._n, x) if isinstance(C, ColoredPermutations) and C._n == self._n and C._m == 2: return lambda P, x: P.element_class(P, [1 if v == 0 else -1 @@ -1493,10 +1590,73 @@ def long_element(self, index_set=None): return super(SignedPermutations, self).long_element() return self.element_class(self, [-ZZ.one()] * self._n, self._P.one()) + def conjugacy_class_representative(self, nu): + r""" + Return a permutation with (signed) cycle type ``nu``. + + EXAMPLES:: + + sage: G = SignedPermutations(4) + sage: for nu in PartitionTuples(2, 4): + ....: print(nu, G.conjugacy_class_representative(nu)) + ....: assert nu == G.conjugacy_class_representative(nu).cycle_type(), nu + ([4], []) [2, 3, 4, 1] + ([3, 1], []) [2, 3, 1, 4] + ([2, 2], []) [2, 1, 4, 3] + ([2, 1, 1], []) [2, 1, 3, 4] + ([1, 1, 1, 1], []) [1, 2, 3, 4] + ([3], [1]) [2, 3, 1, -4] + ([2, 1], [1]) [2, 1, 3, -4] + ([1, 1, 1], [1]) [1, 2, 3, -4] + ([2], [2]) [2, 1, 4, -3] + ([2], [1, 1]) [2, 1, -3, -4] + ([1, 1], [2]) [1, 2, 4, -3] + ([1, 1], [1, 1]) [1, 2, -3, -4] + ([1], [3]) [1, 3, 4, -2] + ([1], [2, 1]) [1, 3, -2, -4] + ([1], [1, 1, 1]) [1, -2, -3, -4] + ([], [4]) [2, 3, 4, -1] + ([], [3, 1]) [2, 3, -1, -4] + ([], [2, 2]) [2, -1, 4, -3] + ([], [2, 1, 1]) [2, -1, -3, -4] + ([], [1, 1, 1, 1]) [-1, -2, -3, -4] + + TESTS:: + + sage: all(nu == SignedPermutations(n).conjugacy_class_representative(nu).cycle_type() + ....: for n in range(1, 6) for nu in PartitionTuples(2, n)) + True + """ + from sage.combinat.partition_tuple import PartitionTuple + nu = PartitionTuple(nu) + if nu.size() != self._n: + raise ValueError("the size of the partition pair (=%s) must equal" + " the rank (=%s)" % (nu.size(), self._n)) + la, mu = nu + cyc = [] + cnt = 0 + + for i in la: + cyc += [tuple(range(cnt+1, cnt+i+1))] + [tuple(range(-cnt-1, -cnt-i-1, -1))] + cnt += i + for i in mu: + cyc += [tuple(range(cnt+1, cnt+i+1)) + tuple(range(-cnt-1, -cnt-i-1, -1))] + cnt += i + + p = [None] * self._n + for c in cyc: + for i in range(len(c)-1): + if c[i] > 0: + p[c[i]-1] = c[i+1] + if c[-1] > 0: + p[c[-1]-1] = c[0] + + return self(p) + Element = SignedPermutation # TODO: Make this a subgroup -#class EvenSignedPermutations(SignedPermutations): +# class EvenSignedPermutations(SignedPermutations): # """ # Group of even signed permutations. # """ diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index f34df107585..8945c697c1e 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -718,7 +718,7 @@ def one(self): def one_basis(self): """ The element `1` is not (generally) a basis vector in the `I` - basis, thus this returns a ``TypeError``. + basis, thus this raises a :class:`TypeError`. EXAMPLES:: diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index e484070c4e8..ed44883be25 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -1048,6 +1048,7 @@ def _PBD_4_5_8_9_12_closure(B): BB.append(X) return BB + table_7_1 = { 0:{'t':-4,'u':16,'s':2}, 1:{'t':-4,'u':17,'s':2}, @@ -1652,4 +1653,5 @@ def arc(self, s=2, solver=None, verbose=0, *, integrality_tolerance=1e-3): values = p.get_values(b, convert=bool, tolerance=integrality_tolerance) return [self._points[i] for (i,j) in values.items() if j] + BIBD = BalancedIncompleteBlockDesign diff --git a/src/sage/combinat/designs/covering_design.py b/src/sage/combinat/designs/covering_design.py index d87ddc6dfbd..fd7172ac876 100644 --- a/src/sage/combinat/designs/covering_design.py +++ b/src/sage/combinat/designs/covering_design.py @@ -518,7 +518,7 @@ def best_known_covering_design_www(v, k, t, verbose=False): 2 3 6 2 4 5 - A ValueError is raised if the ``(v, k, t)`` parameters are not + A :class:`ValueError` is raised if the ``(v, k, t)`` parameters are not found in the database. """ v = int(v) diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index ebefb6bc669..5302771756c 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -296,6 +296,7 @@ def MOLS_18_3(): # # This dictionary is used by designs.mutually_orthogonal_latin_squares(k,n). + MOLS_constructions = { 10 : (2, MOLS_10_2), 12 : (5, MOLS_12_5), @@ -2021,6 +2022,7 @@ def OA_10_1620(): # # This dictionary is used by designs.orthogonal_array(k,n). + OA_constructions = { 18 : (7 , OA_7_18), 40 : (9 , OA_9_40), @@ -2455,6 +2457,7 @@ def QDM_57_9_1_1_8(): # } # } + QDM: dict[tuple[int, int], dict] = {} for ((n,k,lmbda,mu,u),f) in [((19,6,1,1,1), QDM_19_6_1_1_1), ((21,5,1,1,1), QDM_21_5_1_1_1), @@ -4018,6 +4021,7 @@ def DM_993_32_1(): G = AdditiveCyclic(993) return G, M + DM = { (12 ,1) : (6 ,DM_12_6_1), (21 ,1) : (6 ,DM_21_6_1), @@ -4686,6 +4690,7 @@ def BIBD_56_11_2(): D = IncidenceStructure(libgap.Orbit(G, B, libgap.OnSets)) return D._blocks + # Index of the BIBD constructions # # Associates to triple (v,k,lambda) a function that return a diff --git a/src/sage/combinat/designs/difference_family.py b/src/sage/combinat/designs/difference_family.py index 382240627ab..6745985adec 100644 --- a/src/sage/combinat/designs/difference_family.py +++ b/src/sage/combinat/designs/difference_family.py @@ -3606,6 +3606,7 @@ def difference_family(v, k, l=1, existence=False, explain_construction=False, ch return G, D + from sage.misc.rest_index_of_methods import gen_rest_table_index import sys __doc__ = __doc__.format(INDEX_OF_FUNCTIONS=gen_rest_table_index(sys.modules[__name__])) diff --git a/src/sage/combinat/designs/ext_rep.py b/src/sage/combinat/designs/ext_rep.py index cc2f13687a0..0f5bdf339fa 100644 --- a/src/sage/combinat/designs/ext_rep.py +++ b/src/sage/combinat/designs/ext_rep.py @@ -565,6 +565,7 @@ def open_extrep_url(url): else: return f.read() + pattern_integer = re.compile(r'\d+$') pattern_decimal = re.compile(r'-?\d+\.\d+$') pattern_rational = re.compile(r'-?\d+/\d+$') diff --git a/src/sage/combinat/dyck_word.py b/src/sage/combinat/dyck_word.py index a6620735321..80911865d49 100644 --- a/src/sage/combinat/dyck_word.py +++ b/src/sage/combinat/dyck_word.py @@ -539,7 +539,7 @@ def _repr_lattice(self, type=None, labelling=None, underpath=True) -> str: final_fall = " " else: final_fall = " _" + "__" * (length_of_final_fall - 1) - row = " "*(n - alst[-1] - 1) + final_fall + "\n" + row = " " * (n - alst[-1] - 1) + final_fall + "\n" for i in range(n - 1): c = 0 row = row + " "*(n-i-2-alst[-i-2]) @@ -1982,23 +1982,30 @@ def number_of_parking_functions(self) -> int: from sage.arith.misc import multinomial return multinomial(self.rise_composition()) - def list_parking_functions(self): + def list_parking_functions(self) -> list: r""" Return all parking functions whose supporting Dyck path is ``self``. EXAMPLES:: sage: DyckWord([1,1,0,0,1,0]).list_parking_functions() - Permutations of the multi-set [1, 1, 3] - sage: DyckWord([1,1,1,0,0,0]).list_parking_functions() - Permutations of the multi-set [1, 1, 1] - sage: DyckWord([1,0,1,0,1,0]).list_parking_functions() - Standard permutations of 3 + [[1, 1, 3], [1, 3, 1], [3, 1, 1]] """ + return list(self.parking_functions()) + + def parking_functions(self): + r""" + Iterate over parking functions whose supporting Dyck path is ``self``. + + EXAMPLES:: + + sage: list(DyckWord([1,1,0,1,0,0]).parking_functions()) + [[1, 1, 2], [1, 2, 1], [2, 1, 1]] + """ + from sage.combinat.parking_functions import ParkingFunction alist = self._area_sequence_iter() - return Permutations([i - ai + 1 for i, ai in enumerate(alist)]) - # TODO: upon implementation of ParkingFunction class - # map(ParkingFunction, Permutations([i - alist[i]+1 for i in range(len(alist))])) + for pi in Permutations([i - ai + 1 for i, ai in enumerate(alist)]): + yield ParkingFunction(pi) def reading_permutation(self) -> Permutation: r""" diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index a688cc04c4a..cb6e5607931 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -1508,7 +1508,7 @@ def __call__(self, patch, iterations=1) -> Patch: raise ValueError("iterations (=%s) must be >= 0" % iterations) else: old_faces = patch - for i in range(iterations): + for _ in range(iterations): new_faces = [] for f in old_faces: new_faces.extend(self._call_on_face(f, color=f.color())) diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 35de4581bd0..494e8154c80 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -5754,7 +5754,7 @@ def is_deterministic(self): state.transitions, key=lambda t: t.word_in) - for key, transition_class in transition_classes_by_word_in: + for _, transition_class in transition_classes_by_word_in: if len(transition_class) > 1: return False return True @@ -6446,14 +6446,14 @@ def _iter_process_simple_(self, iterator): "'simple' iterator cannot be used " "here." % (len(current),)) - pos, states = next(iter(current.items())) + _, states = next(iter(current.items())) if len(states) > 1: raise RuntimeError("Process has branched " "(visiting %s states in branch). The " "'simple' iterator cannot be used " "here." % (len(states),)) - state, branch = next(iter(states.items())) + _, branch = next(iter(states.items())) if len(branch.outputs) > 1: raise RuntimeError("Process has branched. " "(%s different outputs in branch). The " @@ -8216,7 +8216,7 @@ def function(transition1, transition2): for state_result in result.iter_states(): state = state_result.label()[0] if state.is_final: - accept, state_to, output = self.process( + accept, _, output = self.process( state.final_word_out, initial_state=self.state(state_result.label()[1])) if not accept: @@ -11809,7 +11809,7 @@ def _process_convert_output_(self, output_data, **kwargs): if kwargs['always_include_output']: return super()._process_convert_output_( output_data, **kwargs) - accept_input, current_state, output = output_data + accept_input, current_state, _ = output_data if kwargs['full_output']: return (accept_input, current_state) else: @@ -13769,8 +13769,8 @@ def compare_to_tape(self, track_number, word): next(it_word) # check letters not already cached - for letter_in_word in it_word: - successful, letter_on_track = self.read(track_number) + for _ in it_word: + successful, _ = self.read(track_number) if not successful: return False return True diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 4887720d1c1..5c196c6cbf4 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -503,7 +503,7 @@ def change_ring(self, R): return self construction = self.construction() if construction is not None: - functor, arg = construction + functor, _ = construction from sage.categories.pushout import VectorFunctor if isinstance(functor, VectorFunctor): return functor(R) diff --git a/src/sage/combinat/fully_commutative_elements.py b/src/sage/combinat/fully_commutative_elements.py index 660e917884f..79237fefe42 100644 --- a/src/sage/combinat/fully_commutative_elements.py +++ b/src/sage/combinat/fully_commutative_elements.py @@ -607,13 +607,13 @@ def _still_reduced_fc_after_prepending(self, s): # Find the first letter in that doesn't commute with s. try: - (j, t) = next((i, x) for (i, x) in enumerate(self) if m[s, x] >= 3) + j, t = next((i, x) for i, x in enumerate(self) if m[s, x] >= 3) except StopIteration: return True u = self.clone() u._set_list(self[j:]) - x, y = u.coset_decomposition({s, t}) + x, _ = u.coset_decomposition({s, t}) return len(x) != m[s, t] - 1 ########################################################################### diff --git a/src/sage/combinat/integer_lists/base.pxd b/src/sage/combinat/integer_lists/base.pxd index ecb5550a9cf..3d373a64fe0 100644 --- a/src/sage/combinat/integer_lists/base.pxd +++ b/src/sage/combinat/integer_lists/base.pxd @@ -12,4 +12,4 @@ cdef class IntegerListsBackend(): cdef readonly min_part, max_part cdef readonly min_slope, max_slope cdef readonly Envelope floor, ceiling - cdef public dict __cached_methods # Support cached_method + cdef public dict _cached_methods # Support cached_method diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py index 7f118cc0775..3c8e85061f3 100644 --- a/src/sage/combinat/interval_posets.py +++ b/src/sage/combinat/interval_posets.py @@ -450,7 +450,7 @@ def plot(self, **kwds): c1 = 'red' # self.latex_options()["color_decreasing"] G = self.poset().hasse_diagram() G.set_pos(self._find_node_positions()) - for a, b, c in G.edges(sort=False): + for a, b in G.edges(sort=False, labels=False): if a < b: G.set_edge_label(a, b, 0) else: diff --git a/src/sage/combinat/knutson_tao_puzzles.py b/src/sage/combinat/knutson_tao_puzzles.py index 13df595dce4..72c3ea9c52e 100644 --- a/src/sage/combinat/knutson_tao_puzzles.py +++ b/src/sage/combinat/knutson_tao_puzzles.py @@ -1195,7 +1195,7 @@ def is_completed(self): sage: puzzle.is_completed() True """ - (i, j) = self.kink_coordinates() + i, _ = self.kink_coordinates() return i == self._n + 1 def south_labels(self): @@ -1225,7 +1225,7 @@ def add_piece(self, piece): sage: P.add_piece(piece); P {(1, 4): 1/0\0} """ - (i, j) = self.kink_coordinates() + i, j = self.kink_coordinates() self._squares[i, j] = piece if isinstance(piece, DeltaPiece): i += 1 @@ -1253,7 +1253,7 @@ def add_pieces(self, pieces): sage: P {(1, 4): 1/0\0, (2, 4): 1/0\0} """ - (i, j) = self.kink_coordinates() + i, j = self.kink_coordinates() for piece in pieces: self._squares[i, j] = piece if isinstance(piece, DeltaPiece): @@ -2178,7 +2178,7 @@ def _fill_puzzle_by_strips(self, lamda, mu): queue = [PuzzleFilling(lamda, mu)] while queue: PP = queue.pop() - (i, j) = PP.kink_coordinates() + i, _ = PP.kink_coordinates() # grab nw labels if i == 1: diff --git a/src/sage/combinat/parking_functions.py b/src/sage/combinat/parking_functions.py index bd67b573238..d356cedb2b7 100644 --- a/src/sage/combinat/parking_functions.py +++ b/src/sage/combinat/parking_functions.py @@ -222,11 +222,17 @@ def __init__(self, parent, lst): sage: type(b) + + Some checks for more general inputs:: + + sage: PF = ParkingFunction((1, 1, 2, 2, 5, 6)) + sage: PF = ParkingFunction(Permutation([4,2,3,1])) """ - if isinstance(lst, ParkingFunction): - lst = list(lst) if not isinstance(lst, list): - raise TypeError('input must be a list') + try: + lst = list(lst) + except TypeError: + raise TypeError('input must be convertible to a list') if parent is None: parent = ParkingFunctions_n(len(lst)) ClonableArray.__init__(self, parent, lst) diff --git a/src/sage/combinat/partition_kleshchev.py b/src/sage/combinat/partition_kleshchev.py index bc4963aa6cf..18db4ff3424 100644 --- a/src/sage/combinat/partition_kleshchev.py +++ b/src/sage/combinat/partition_kleshchev.py @@ -994,7 +994,7 @@ def e(self, i): cell = self.good_cells(i) if cell is None: return None - r,c = cell + r, _ = cell mu = list(self) mu[r] -= 1 return type(self)(P, mu) @@ -1055,7 +1055,7 @@ def e(self, i): cell = self.good_cells(i) if cell is None: return None - k,r,c = cell + k, r, _ = cell mu = self.to_list() mu[k][r] -= 1 return type(self)(P, mu) @@ -1938,7 +1938,7 @@ def _is_regular(kpt, multicharge, convention): convention = convention[0] + 'G' cell = _a_good_cell(kpt, multicharge, convention) while cell is not None: - k,r,c = cell + k, r, _ = cell if kpt[k][r] == 1: kpt[k].pop() else: @@ -1964,15 +1964,15 @@ def _is_restricted(kpt, multicharge, convention): sage: _is_restricted([[], []], [I3(0),I3(2)], 'RG') True """ - if all(part == [] for part in kpt): + if all(not part for part in kpt): return True convention = convention[0] + 'S' cell = _a_good_cell(kpt, multicharge, convention) while cell is not None: - k,r,c = cell + k, r, _ = cell if kpt[k][r] == 1: kpt[k].pop() else: kpt[k][r] -= 1 cell = _a_good_cell(kpt, multicharge, convention) - return all(part == [] for part in kpt) + return all(not part for part in kpt) diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index a216ad58029..459364f6121 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -7143,12 +7143,16 @@ def element_in_conjugacy_classes(self, nu): sage: PP = Permutations(5) sage: PP.element_in_conjugacy_classes([2,2]) # optional - sage.combinat [2, 1, 4, 3, 5] + sage: PP.element_in_conjugacy_classes([5, 5]) + Traceback (most recent call last): + ... + ValueError: the size of the partition (=10) should be at most the size of the permutations (=5) """ from sage.combinat.partition import Partition nu = Partition(nu) if nu.size() > self.n: - raise ValueError("The size of the partition (=%s) should be lower or equal" - " to the size of the permutations (=%s)"%(nu.size,self.n)) + raise ValueError("the size of the partition (=%s) should be at most" + " the size of the permutations (=%s)" % (nu.size(), self.n)) l = [] i = 0 for nui in nu: diff --git a/src/sage/combinat/plane_partition.py b/src/sage/combinat/plane_partition.py index e7cb63842b9..14d284b77c6 100644 --- a/src/sage/combinat/plane_partition.py +++ b/src/sage/combinat/plane_partition.py @@ -38,7 +38,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.rings.integer_ring import ZZ -from sage.arith.misc import Sigma, integer_floor as floor, integer_ceil as ceil, binomial, factorial +from sage.arith.misc import Sigma, binomial, factorial from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets from sage.sets.family import Family from sage.sets.non_negative_integers import NonNegativeIntegers @@ -74,6 +74,7 @@ class PlanePartition(ClonableArray, sage: PP = PlanePartition([[4,3,3,1],[2,1,1],[1,1]]) sage: TestSuite(PP).run() + sage: hash(PP) # random """ @staticmethod def __classcall_private__(cls, PP, box_size=None): @@ -118,13 +119,14 @@ def __init__(self, parent, pp, check=True): if isinstance(pp, PlanePartition): ClonableArray.__init__(self, parent, pp, check=False) else: - pp = [list(_) for _ in pp] + pp = [list(row) for row in pp] if pp: for i in reversed(range(len(pp))): while pp[i] and not pp[i][-1]: del pp[i][-1] if not pp[i]: pp.pop(i) + pp = [tuple(row) for row in pp] ClonableArray.__init__(self, parent, pp, check=check) if self.parent()._box is None: if pp: @@ -232,7 +234,7 @@ def _repr_(self) -> str: sage: PlanePartition([[4,3,3,1],[2,1,1],[1,1]]) Plane partition [[4, 3, 3, 1], [2, 1, 1], [1, 1]] """ - return "Plane partition {}".format(list(self)) + return "Plane partition {}".format([list(row) for row in self]) def to_tableau(self) -> Tableau: r""" @@ -667,7 +669,7 @@ def plot(self, show_box=False, colors=None): EXAMPLES:: sage: PP = PlanePartition([[4,3,3,1],[2,1,1],[1,1]]) - sage: PP.plot() # optional - sage.plot + sage: PP.plot() # optional - sage.plot Graphics object consisting of 27 graphics primitives """ from sage.functions.trig import cos, sin @@ -764,7 +766,7 @@ def plot3d(self, colors=None): EXAMPLES:: sage: PP = PlanePartition([[4,3,3,1],[2,1,1],[1,1]]) - sage: PP.plot3d() # optional - sage.plot + sage: PP.plot3d() # optional - sage.plot Graphics3d Object """ if colors is None: @@ -877,7 +879,14 @@ def is_SPP(self) -> bool: sage: PP = PlanePartition([[3,2],[2,0],[0,0]]) sage: PP.is_SPP() True + + TESTS:: + + sage: PlanePartition([]).is_SPP() + True """ + if not self: + return True Z = self.z_tableau() c1 = len(Z) c2 = len(Z[0]) @@ -905,6 +914,11 @@ def is_CSPP(self) -> bool: sage: PP = PlanePartition([[3,2,2],[3,1,0],[1,1,0]]) sage: PP.is_CSPP() True + + TESTS:: + + sage: PlanePartition([]).is_CSPP() + True """ if self.z_tableau() == self.y_tableau(): return True @@ -925,6 +939,11 @@ def is_TSPP(self) -> bool: sage: PP = PlanePartition([[3,3,3],[3,3,2],[3,2,1]]) sage: PP.is_TSPP() True + + TESTS:: + + sage: PlanePartition([]).is_TSPP() + True """ return self.is_CSPP() and self.is_SPP() @@ -948,6 +967,11 @@ def is_SCPP(self) -> bool: sage: PP = PlanePartitions([4,4,4])([[4,4,4,4],[4,4,2,0],[4,2,0,0],[0,0,0,0]]) sage: PP.is_SCPP() True + + TESTS:: + + sage: PlanePartition([]).is_SCPP() + True """ return self.z_tableau(tableau=False) == self.complement(tableau_only=True) @@ -963,6 +987,11 @@ def is_TCPP(self) -> bool: sage: PP = PlanePartition([[4,4,3,2],[4,4,2,1],[4,2,0,0],[2,0,0,0]]) sage: PP.is_TCPP() True + + TESTS:: + + sage: PlanePartition([]).is_TCPP() + True """ return self.transpose(True) == self.complement(True) @@ -988,6 +1017,11 @@ def is_SSCPP(self) -> bool: sage: PP = PlanePartition([[4,2,2,2],[2,2,2,2],[2,2,2,2],[2,2,2,0]]) sage: PP.is_SSCPP() True + + TESTS:: + + sage: PlanePartition([]).is_SSCPP() + True """ return self.is_SPP() and self.is_SCPP() @@ -1004,6 +1038,11 @@ def is_CSTCPP(self) -> bool: sage: PP = PlanePartition([[4,4,3,2],[4,3,2,1],[3,2,1,0],[2,1,0,0]]) sage: PP.is_CSTCPP() True + + TESTS:: + + sage: PlanePartition([]).is_CSTCPP() + True """ return self.is_CSPP() and self.is_TCPP() @@ -1020,6 +1059,11 @@ def is_CSSCPP(self) -> bool: sage: PP = PlanePartition([[4,4,4,1],[3,3,2,1],[3,2,1,1],[3,0,0,0]]) sage: PP.is_CSSCPP() True + + TESTS:: + + sage: PlanePartition([]).is_CSSCPP() + True """ return self.is_CSPP() and self.is_SCPP() @@ -1036,6 +1080,11 @@ def is_TSSCPP(self) -> bool: sage: PP = PlanePartition([[4,4,3,2],[4,3,2,1],[3,2,1,0],[2,1,0,0]]) sage: PP.is_TSSCPP() True + + TESTS:: + + sage: PlanePartition([]).is_TSSCPP() + True """ return self.is_TSPP() and self.is_SCPP() @@ -1089,7 +1138,7 @@ def maximal_boxes(self) -> list: for j, entry in enumerate(row): if (i == len(self)-1 or len(self[i+1])-1 < j or self[i+1][j] < entry) and (j == len(row)-1 or row[j+1] < entry): generate.append([i, j, entry-1]) - return(generate) + return generate def cyclically_rotate(self, preserve_parent=False) -> PP: r""" @@ -1300,6 +1349,10 @@ def __classcall_private__(cls, *args, **kwds): Plane partitions of size 3 sage: PlanePartitions([4,4,4], symmetry='TSSCPP') Totally symmetric self-complementary plane partitions inside a 4 x 4 x 4 box + sage: PlanePartitions(4, symmetry='TSSCPP') + Traceback (most recent call last): + ... + ValueError: the number of boxes may only be specified if no symmetry is required """ symmetry = kwds.get('symmetry', None) box_size = kwds.get('box_size', None) @@ -1310,8 +1363,10 @@ def __classcall_private__(cls, *args, **kwds): if args and box_size is None: # The first arg could be either a size or a box size if isinstance(args[0], (int, Integer)): - return PlanePartitions_n(args[0]) - + if symmetry is None: + return PlanePartitions_n(args[0]) + else: + raise ValueError("the number of boxes may only be specified if no symmetry is required") box_size = args[0] box_size = tuple(box_size) @@ -1436,7 +1491,7 @@ def __init__(self): sage: from sage.combinat.plane_partition import PlanePartitions_all sage: P = PlanePartitions_all() - sage: TestSuite(P).run() # long time + sage: TestSuite(P).run() """ # We manually set these here rather than invoking the super().__init__(). # This is so DisjointUnionEnumeratedSets can make the Parent.__init__() call. @@ -1445,8 +1500,10 @@ def __init__(self): # super(PlanePartitions_all, self).__init__(category=InfiniteEnumeratedSets()) DisjointUnionEnumeratedSets.__init__(self, - Family(NonNegativeIntegers(), PlanePartitions_n), - facade=True, keepkey=False) + Family(NonNegativeIntegers(), + PlanePartitions_n), + facade=True, + keepkey=False) def _repr_(self) -> str: """ @@ -1488,7 +1545,7 @@ def __init__(self, box_size): EXAMPLES:: sage: PP = PlanePartitions([4,3,2]) - sage: TestSuite(PP).run() + sage: TestSuite(PP).run() # long time """ super().__init__(box_size, category=FiniteEnumeratedSets()) @@ -1599,10 +1656,20 @@ def __iter__(self) -> Iterator: sage: list(PlanePartitions([1,2,1])) [Plane partition [], Plane partition [[1]], Plane partition [[1, 1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() + ....: for b in cartesian_product([range(4)]*3) + ....: if (PP := PlanePartitions(b))) + True """ A = self._box[0] B = self._box[1] C = self._box[2] + if not A: + yield self.element_class(self, [], check=False) + return from sage.combinat.tableau import SemistandardTableaux as SST for T in SST([B for i in range(A)], max_entry=C + A): # type:ignore PP = [[0 for _ in range(B)] for _ in range(A)] @@ -1632,7 +1699,11 @@ def cardinality(self) -> Integer: A = self._box[0] B = self._box[1] C = self._box[2] - return Integer(prod(Integer(i + j + k - 1) / Integer(i + j + k - 2) + return Integer(prod(i + j + k - 1 + for i in range(1, A + 1) + for j in range(1, B + 1) + for k in range(1, C + 1)) // + prod(i + j + k - 2 for i in range(1, A + 1) for j in range(1, B + 1) for k in range(1, C + 1))) @@ -1708,6 +1779,11 @@ def __iter__(self) -> Iterator: sage: list(PlanePartitions(2)) [Plane partition [[2]], Plane partition [[1, 1]], Plane partition [[1], [1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() for n in range(9) if (PP := PlanePartitions(n))) + True """ from sage.combinat.partition import Partitions @@ -1922,6 +1998,13 @@ def __iter__(self) -> Iterator: Plane partition [[1, 1], [1, 1]], Plane partition [[1, 1], [1]], Plane partition [[1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() + ....: for a, b in cartesian_product([range(4)]*2) + ....: if (PP := PlanePartitions([a, a, b], symmetry='SPP'))) + True """ for acl in self.to_poset().antichains_iterator(): yield self.from_antichain(acl) @@ -1946,11 +2029,15 @@ def cardinality(self) -> Integer: """ a = self._box[0] c = self._box[2] - left_prod = prod((2*i + c - 1) / (2*i - 1) for i in range(1, a+1)) - right_prod = prod((i + j + c - 1) / (i + j - 1) - for j in range(1, a+1) - for i in range(1, j)) - return Integer(left_prod * right_prod) + left_prod_num = prod(2*i + c - 1 for i in range(1, a+1)) + left_prod_den = prod(2*i - 1 for i in range(1, a+1)) + right_prod_num = prod(i + j + c - 1 + for j in range(1, a+1) + for i in range(1, j)) + right_prod_den = prod(i + j - 1 + for j in range(1, a+1) + for i in range(1, j)) + return Integer(left_prod_num * right_prod_num // left_prod_den // right_prod_den) def random_element(self) -> PP: r""" @@ -2143,6 +2230,11 @@ def __iter__(self) -> Iterator: Plane partition [[2, 2], [2, 1]], Plane partition [[2, 1], [1]], Plane partition [[1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() for n in range(5) if (PP := PlanePartitions([n]*3, symmetry='CSPP'))) + True """ for acl in self.to_poset().antichains_iterator(): yield self.from_antichain(acl) @@ -2166,13 +2258,13 @@ def cardinality(self) -> Integer: 132 """ a = self._box[0] - numerator = (prod(3*i - 1 for i in range(1, a+1)) - * prod(i + j + a - 1 for j in range(1, a+1) - for i in range(1, j+1))) - denominator = (prod(3*i - 2 for i in range(1, a+1)) - * prod(2*i + j - 1 for j in range(1, a+1) - for i in range(1, j+1))) - return Integer(numerator // denominator) + num = (prod(3*i - 1 for i in range(1, a + 1)) + * prod(i + j + a - 1 for j in range(1, a + 1) + for i in range(1, j + 1))) + den = (prod(3*i - 2 for i in range(1, a + 1)) + * prod(2*i + j - 1 for j in range(1, a + 1) + for i in range(1, j + 1))) + return Integer(num // den) # Class 4 @@ -2321,9 +2413,14 @@ def __iter__(self) -> Iterator: Plane partition [[2, 2], [2, 1]], Plane partition [[2, 1], [1]], Plane partition [[1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() for n in range(5) if (PP := PlanePartitions([n]*3, symmetry='TSPP'))) + True """ - for A in self.to_poset().antichains_iterator(): - yield self.from_antichain(A) + for acl in self.to_poset().antichains_iterator(): + yield self.from_antichain(acl) def cardinality(self) -> Integer: r""" @@ -2343,8 +2440,9 @@ def cardinality(self) -> Integer: 66 """ a = self._box[0] - return Integer(prod((i + j + a - 1) / (i + 2*j - 2) - for j in range(1, a+1) for i in range(1, j+1))) + num = prod(i + j + a - 1 for j in range(1, a + 1) for i in range(1, j + 1)) + den = prod(i + 2*j - 2 for j in range(1, a + 1) for i in range(1, j + 1)) + return Integer(num // den) # Class 5 @@ -2412,37 +2510,45 @@ def __iter__(self) -> Iterator: Plane partition [[2], [2], [2]], Plane partition [[2, 1], [2], [1]], Plane partition [[2, 2], [2]]] + + TESTS:: + + sage: PP = PlanePartitions([3,4,5], symmetry='SCPP') + sage: len(set(PP)) == PP.cardinality() + True + + sage: all(len(set(PP)) == PP.cardinality() + ....: for b in cartesian_product([range(4)]*3) + ....: if is_even(prod(b)) and (PP := PlanePartitions(b, symmetry='SCPP'))) + True """ b = self._box[0] a = self._box[1] c = self._box[2] def Partitions_inside_lambda(la): - "Iterate over all partitions contained in la with the same number of parts including 0s." - if not la: - yield [] - return - for mu_0 in range(la[0], 0, -1): - new_la = [min(mu_0, la[i]) for i in range(1, len(la))] - for mu in Partitions_inside_lambda(new_la): - yield [mu_0] + mu - yield [0] * len(la) - return + """ + Iterate over all partitions contained in la with the same number + of parts including 0s. + """ + from sage.combinat.partition import Partitions + for k in range(sum(la), -1, -1): + for mu in Partitions(k, outer=la): + yield mu + [0]*(len(la)-len(mu)) def Partitions_inside_lambda_with_smallest_at_least_k(la, k): - "Iterate over all partitions contained in la with the smallest entry at least k." - if not la: - yield [] - return - if la[-1] < k: - yield - return - for mu in Partitions_inside_lambda([val-k for val in la]): + """ + Iterate over all partitions contained in la with the smallest + entry at least k. + """ + for mu in Partitions_inside_lambda([val - k for val in la]): yield [mu[i] + k for i in range(len(la))] - return def possible_middle_row_for_b_odd(a, c): - "Iterate over all possible middle row for SCPP inside box(a,b,c) when b is odd." + """ + Iterate over all possible middle row for SCPP inside box(a,b,c) + when b is odd. + """ if a * c % 2 == 1: yield return @@ -2451,18 +2557,22 @@ def possible_middle_row_for_b_odd(a, c): if not a % 2: la = nu + mu else: - la = nu + [c//2] + mu + la = nu + [c // 2] + mu yield la - return def possible_middle_row_for_b_even(a, c): - "Iterate over all possible middle ((b/2)+1)st row for SCPP inside box(a,b,c) when b is even." + """ + Iterate over all possible middle ((b/2)+1)st row for SCPP inside + box(a,b,c) when b is even. + """ for mu in Partitions_inside_lambda([c // 2 for i in range((a+1) // 2)]): + if not mu: + yield [] + continue nu = [c - mu[len(mu)-1-i] for i in range(a // 2)] for tau in Partitions_inside_lambda_with_smallest_at_least_k(nu, mu[0]): la = tau + mu yield la - return def PPs_with_first_row_la_and_with_k_rows(la, k): "Iterate over PPs with first row la and with k rows in total." @@ -2475,7 +2585,6 @@ def PPs_with_first_row_la_and_with_k_rows(la, k): for mu in Partitions_inside_lambda(la): for PP in PPs_with_first_row_la_and_with_k_rows(mu, k-1): yield [la] + PP - return def complement(PP, c): "Return the complement of PP with respect to height c" @@ -2486,18 +2595,19 @@ def complement(PP, c): return [[c - PP[b-1-i][a-1-j] for j in range(a)] for i in range(b)] if b % 2 == 1: - for la in possible_middle_row_for_b_odd(a, c): # la is the middle row of SCPP + # la is the middle row of SCPP + for la in possible_middle_row_for_b_odd(a, c): for PP in PPs_with_first_row_la_and_with_k_rows(la, (b+1) // 2): PP_below = PP[1:] PP_above = complement(PP_below, c) yield self.element_class(self, PP_above + [la] + PP_below) else: - for la in possible_middle_row_for_b_even(a, c): # la is the middle ((a/2)+1)st row of SCPP + # la is the middle ((a/2)+1)st row of SCPP + for la in possible_middle_row_for_b_even(a, c): for PP in PPs_with_first_row_la_and_with_k_rows(la, b // 2): PP_below = PP PP_above = complement(PP_below, c) yield self.element_class(self, PP_above + PP_below) - return def cardinality(self) -> Integer: r""" @@ -2673,7 +2783,6 @@ def __iter__(self) -> Iterator: for p in PlanePartitions(self._box): if p.is_TCPP(): yield self.element_class(self, p) - return def cardinality(self) -> Integer: r""" @@ -2695,9 +2804,11 @@ def cardinality(self) -> Integer: """ a = self._box[0] c = self._box[2] - return Integer(binomial(c//2 + a - 1, a - 1) - * prod((c + i + j + 1) / (i + j + 1) - for j in range(1, 1+a-2) for i in range(1, 1+j))) + return Integer(binomial(c // 2 + a - 1, a - 1) + * prod(c + i + j + 1 + for j in range(1, a - 1) for i in range(1, 1 + j)) + // prod(i + j + 1 + for j in range(1, a - 1) for i in range(1, 1 + j))) # Class 7 @@ -2717,7 +2828,7 @@ def __init__(self, box_size): sage: TestSuite(PP).run() sage: PP = PlanePartitions([4, 4, 2], symmetry='SSCPP') - sage: TestSuite(PP).run() # long time + sage: TestSuite(PP).run() sage: PlanePartitions([4, 2, 2], symmetry='SSCPP') Traceback (most recent call last): @@ -2752,14 +2863,22 @@ def __iter__(self) -> Iterator: EXAMPLES:: sage: list(PlanePartitions([4,4,2], symmetry='SSCPP')) - [Plane partition [[2, 2, 2, 1], [2, 2, 1], [2, 1], [1]], + [Plane partition [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], Plane partition [[2, 2, 2, 1], [2, 1, 1], [2, 1, 1], [1]], Plane partition [[2, 2, 1, 1], [2, 2, 1, 1], [1, 1], [1, 1]], + Plane partition [[2, 2, 2, 1], [2, 2, 1], [2, 1], [1]], Plane partition [[2, 2, 1, 1], [2, 1, 1, 1], [1, 1, 1], [1, 1]], - Plane partition [[2, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1]], - Plane partition [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]] + Plane partition [[2, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() + ....: for a, b in cartesian_product([range(5), range(0, 5, 2)]) + ....: if (PP := PlanePartitions([a, a, b], symmetry='SSCPP'))) + True """ - for p in PlanePartitions(self._box): + # any SSCPP is a SPP + for p in PlanePartitions(self._box, symmetry='SPP'): if p.is_SSCPP(): yield self.element_class(self, p) @@ -2792,10 +2911,15 @@ def cardinality(self) -> Integer: """ a = self._box[0] c = self._box[2] - return Integer(prod(Integer(i + j + k - 1) / Integer(i + j + k - 2) - for i in range(1, 1+a//2) - for j in range(1, 1+ceil(a/2)) - for k in range(1, 1+c//2))) + num = prod(i + j + k - 1 + for i in range(1, 1 + a // 2) + for j in range(1, 1 + (a + 1) // 2) + for k in range(1, 1 + c // 2)) + den = prod(i + j + k - 2 + for i in range(1, 1 + a // 2) + for j in range(1, 1 + (a + 1) // 2) + for k in range(1, 1 + c // 2)) + return Integer(num // den) # Class 8 @@ -2846,8 +2970,16 @@ def __iter__(self) -> Iterator: sage: list(PlanePartitions([2,2,2], symmetry='CSTCPP')) [Plane partition [[2, 1], [1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() + ....: for n in range(0, 5, 2) + ....: if (PP := PlanePartitions([n]*3, symmetry='CSTCPP'))) + True """ - for p in PlanePartitions(self._box): + # any CSTCPP is a TSPP, a SSCPP and a CSSCPP + for p in PlanePartitions(self._box, symmetry='TSPP'): if p.is_CSTCPP(): yield self.element_class(self, p) @@ -2869,7 +3001,9 @@ def cardinality(self) -> Integer: 11 """ a = self._box[0] // 2 - return Integer(prod((3*i+1) * factorial(6*i) * factorial(2*i) / (factorial(4*i+1) * factorial(4*i)) for i in range(a))) + num = prod((3*i + 1) * factorial(6*i) * factorial(2*i) for i in range(a)) + den = prod((factorial(4*i + 1) * factorial(4*i)) for i in range(a)) + return Integer(num // den) # Class 9 @@ -2921,7 +3055,8 @@ def __iter__(self) -> Iterator: sage: list(PlanePartitions([2,2,2], symmetry='CSSCPP')) [Plane partition [[2, 1], [1]]] """ - for p in PlanePartitions(self._box): + # any CSSCPP is a SCPP and an CSPP, there are much fewer CSPP + for p in PlanePartitions(self._box, symmetry='CSPP'): if p.is_CSSCPP(): yield self.element_class(self, p) @@ -2943,7 +3078,9 @@ def cardinality(self) -> Integer: 49 """ a = self._box[0] // 2 - return Integer(prod(factorial(3*i+1)**2 / factorial(a+i)**2 for i in range(a))) + num = prod(factorial(3*i + 1)**2 for i in range(a)) + den = prod(factorial(a + i)**2 for i in range(a)) + return Integer(num // den) # Class 10 @@ -3037,9 +3174,9 @@ def from_antichain(self, acl) -> PP: height = N - 1 # generate inner triangle - # FIXME: Make this ierator more efficient + # FIXME: Make this iterator more efficient for i in range(width): - for j in range(min(height, i+1)): + for j in range(i, height): for ac in acl: if ac[0] == i and ac[1] == j: zVal = ac[2] @@ -3129,10 +3266,14 @@ def __iter__(self) -> Iterator: sage: list(PlanePartitions([4,4,4], symmetry='TSSCPP')) [Plane partition [[4, 4, 2, 2], [4, 4, 2, 2], [2, 2], [2, 2]], Plane partition [[4, 4, 3, 2], [4, 3, 2, 1], [3, 2, 1], [2, 1]]] + + TESTS:: + + sage: all(len(set(PP)) == PP.cardinality() for n in range(0,11,2) if (PP := PlanePartitions([n]*3, symmetry='TSSCPP'))) + True """ for acl in self.to_poset().antichains_iterator(): yield self.from_antichain(acl) - return def cardinality(self) -> Integer: r""" @@ -3152,4 +3293,6 @@ def cardinality(self) -> Integer: 7 """ a = self._box[0] // 2 - return Integer(prod(factorial(3*i+1) / factorial(a+i) for i in range(a))) + num = prod(factorial(3*i + 1) for i in range(a)) + den = prod(factorial(a + i) for i in range(a)) + return Integer(num // den) diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 80cff74eb5c..6bfe6eca61e 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -89,18 +89,20 @@ def _hooks(self): # Check if any of these make a longer double tailed diamond found_diamond = False - for (mn, mx) in [(i, j) for i in potential_min for j in potential_max]: - if len(H.neighbors_in(mx)) != 1: + for mx in potential_max: + if H.in_degree(mx) != 1: continue - if len(H.all_paths(mn, mx)) == 2: - # Success - min_elmt = mn - max_elmt = mx - - min_diamond[mx] = mn - max_diamond[mn] = mx - diamond_index[mx] = index - found_diamond = True + for mn in potential_min: + if len(H.all_paths(mn, mx)) == 2: + # Success + min_elmt = mn + max_elmt = mx + min_diamond[mx] = mn + max_diamond[mn] = mx + diamond_index[mx] = index + found_diamond = True + break + if found_diamond: break if not found_diamond: break diff --git a/src/sage/combinat/posets/elements.py b/src/sage/combinat/posets/elements.py index 4788246cd1d..4cfb0b28ae0 100644 --- a/src/sage/combinat/posets/elements.py +++ b/src/sage/combinat/posets/elements.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Elements of posets, lattices, semilattices, etc. """ @@ -78,13 +79,13 @@ def _latex_(self): EXAMPLES:: - sage: m = matrix(2, [1,2,3,4]) # optional - sage.modules - sage: m.set_immutable() # optional - sage.modules - sage: P = Poset(([m],[]), facade=False) # optional - sage.modules - sage: [e] = P # optional - sage.modules - sage: type(e) # optional - sage.modules + sage: m = matrix(2, [1,2,3,4]) + sage: m.set_immutable() + sage: P = Poset(([m],[]), facade=False) + sage: [e] = P + sage: type(e) - sage: latex(e) #indirect doctest # optional - sage.modules + sage: latex(e) #indirect doctest \left(\begin{array}{rr} 1 & 2 \\ 3 & 4 @@ -244,13 +245,13 @@ def __mul__(self, other): EXAMPLES:: sage: D = posets.DiamondPoset(5, facade=False) - sage: D(1) * D(2) # optional - sage.modules + sage: D(1) * D(2) 0 - sage: D(1) * D(1) # optional - sage.modules + sage: D(1) * D(1) 1 - sage: D(1) * D(0) # optional - sage.modules + sage: D(1) * D(0) 0 - sage: D(1) * D(4) # optional - sage.modules + sage: D(1) * D(4) 1 """ return self.parent().meet(self, other) @@ -264,13 +265,13 @@ def __add__(self, other): EXAMPLES:: sage: D = posets.DiamondPoset(5,facade=False) - sage: D(1) + D(2) # optional - sage.modules + sage: D(1) + D(2) 4 - sage: D(1) + D(1) # optional - sage.modules + sage: D(1) + D(1) 1 - sage: D(1) + D(4) # optional - sage.modules + sage: D(1) + D(4) 4 - sage: D(1) + D(0) # optional - sage.modules + sage: D(1) + D(0) 1 """ return self.parent().join(self, other) diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 969aedb770c..1c61cee4760 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -598,7 +598,7 @@ def _precompute_intervals(self): """ n = self.order() v_up = (frozenset(self.depth_first_search(v)) for v in range(n)) - v_down = [frozenset(self.depth_first_search(v, neighbors=self.neighbors_in)) + v_down = [frozenset(self.depth_first_search(v, neighbors=self.neighbor_in_iterator)) for v in range(n)] self._intervals = [[sorted(up.intersection(down)) for down in v_down] for up in v_up] @@ -1232,7 +1232,7 @@ def order_ideal(self, elements): [0, 1, 2, 3, 4, 5, 6, 7, 8, 10] """ return sorted(self.depth_first_search(elements, - neighbors=self.neighbors_in)) + neighbors=self.neighbor_in_iterator)) def order_ideal_cardinality(self, elements): r""" @@ -1256,7 +1256,7 @@ def order_ideal_cardinality(self, elements): continue size += 1 seen.add(v) - q.extend(self.neighbors_in(v)) + q.extend(self.neighbor_in_iterator(v)) return ZZ(size) @@ -2545,9 +2545,9 @@ def common_upper_covers(self, vertices): sage: H.common_upper_covers([4, 5]) # optional - sage.combinat [6] """ - covers = set(self.neighbors_out(vertices.pop())) + covers = set(self.neighbor_out_iterator(vertices.pop())) for v in vertices: - covers = covers.intersection(self.neighbors_out(v)) + covers = covers.intersection(self.neighbor_out_iterator(v)) return list(covers) def common_lower_covers(self, vertices): @@ -2566,9 +2566,9 @@ def common_lower_covers(self, vertices): sage: H.common_lower_covers([4, 5]) # optional - sage.combinat [3] """ - covers = set(self.neighbors_in(vertices.pop())) + covers = set(self.neighbor_in_iterator(vertices.pop())) for v in vertices: - covers = covers.intersection(self.neighbors_in(v)) + covers = covers.intersection(self.neighbor_in_iterator(v)) return list(covers) def _trivial_nonregular_congruence(self): @@ -2764,7 +2764,7 @@ def sublattice(elms, e): break # Special case to handle at last. - if len(self.neighbors_out(0)) == 1: + if self.out_degree(0) == 1: result.append(set(range(1, N))) return result @@ -2830,8 +2830,8 @@ def kappa_dual(self, a): uc = next(self.neighbor_out_iterator(a)) if self.in_degree(uc) == 1: return uc - lt_a = set(self.depth_first_search(a, neighbors=self.neighbors_in)) - tmp = list(self.depth_first_search(uc, neighbors=lambda v: [v_ for v_ in self.neighbor_in_iterator(v) if v_ not in lt_a])) + lt_a = set(self.depth_first_search(a, neighbors=self.neighbor_in_iterator)) + tmp = set(self.depth_first_search(uc, neighbors=lambda v: [v_ for v_ in self.neighbor_in_iterator(v) if v_ not in lt_a])) result = None for e in tmp: if all(x not in tmp for x in self.neighbor_in_iterator(e)): @@ -2990,7 +2990,7 @@ def neutral_elements(self): def is_neutral(a): noncomp = all_elements.difference(self.depth_first_search(a)) - noncomp.difference_update(self.depth_first_search(a, neighbors=self.neighbors_in)) + noncomp.difference_update(self.depth_first_search(a, neighbors=self.neighbor_in_iterator)) for x in noncomp.intersection(todo): meet_ax = mt[a, x] @@ -3071,7 +3071,7 @@ def kappa(self, a): if self.out_degree(lc) == 1: return lc gt_a = set(self.depth_first_search(a)) - tmp = list(self.depth_first_search(lc, neighbors=lambda v: [v_ for v_ in self.neighbor_out_iterator(v) if v_ not in gt_a])) + tmp = set(self.depth_first_search(lc, neighbors=lambda v: [v_ for v_ in self.neighbor_out_iterator(v) if v_ not in gt_a])) result = None for e in tmp: if all(x not in tmp for x in self.neighbor_out_iterator(e)): @@ -3346,9 +3346,9 @@ def find_nontrivial_congruence(self): join_irreducibles = [v for v in self if self.in_degree(v) == 1] meet_irreducibles = [v for v in self if self.out_degree(v) == 1] if len(join_irreducibles) < len(meet_irreducibles): - irr = [(v, self.neighbors_in(v)[0]) for v in join_irreducibles] + irr = [(v, next(self.neighbor_in_iterator(v))) for v in join_irreducibles] else: - irr = [(self.neighbors_out(v)[0], v) for v in meet_irreducibles] + irr = [(next(self.neighbor_out_iterator(v)), v) for v in meet_irreducibles] irr.sort(key=lambda x: x[0] - x[1]) tried = [] for pair in irr: diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index c6746f544a5..99e403765f8 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -1695,7 +1695,7 @@ def is_cosectionally_complemented(self, certificate=False): n = H.order() for e in range(n - 2, -1, -1): t = 0 - for uc in H.neighbors_out(e): + for uc in H.neighbor_out_iterator(e): t = jn[t, uc] if t == n - 1: break @@ -1805,13 +1805,13 @@ def is_relatively_complemented(self, certificate=False): return False for e1 in range(n - 1): - C = Counter(flatten([H.neighbors_out(e2) for e2 in H.neighbors_out(e1)])) + C = Counter(flatten([H.neighbors_out(e2) for e2 in H.neighbor_out_iterator(e1)])) for e3, c in C.items(): if c == 1 and len(H.closed_interval(e1, e3)) == 3: if not certificate: return False - for e2 in H.neighbors_in(e3): - if e2 in H.neighbors_out(e1): + for e2 in H.neighbor_in_iterator(e3): + if e2 in H.neighbor_out_iterator(e1): break return (False, (self._vertex_to_element(e1), self._vertex_to_element(e2), @@ -1885,7 +1885,7 @@ def is_sectionally_complemented(self, certificate=False): n = H.order() - 1 for e in range(2, n + 1): t = n - for lc in H.neighbors_in(e): + for lc in H.neighbor_in_iterator(e): t = mt[t, lc] if t == 0: break @@ -1988,7 +1988,7 @@ def join(L): # Get elements more than B levels below it. too_close = set(H.breadth_first_search(j, - neighbors=H.neighbors_in, + neighbors=H.neighbor_in_iterator, distance=B - 2)) elems = [e for e in H.order_ideal([j]) if e not in too_close] @@ -2378,7 +2378,7 @@ def is_atomic(self, certificate=False): if self.cardinality() < 3: return (True, None) H = self._hasse_diagram - atoms = set(H.neighbors_out(0)) + atoms = set(H.neighbor_out_iterator(0)) for v in H: if H.in_degree(v) == 1 and v not in atoms: return (False, self._vertex_to_element(v)) @@ -2436,7 +2436,7 @@ def is_coatomic(self, certificate=False): if self.cardinality() < 3: return (True, None) H = self._hasse_diagram - coatoms = set(H.neighbors_in(n - 1)) + coatoms = set(H.neighbor_in_iterator(n - 1)) for v in H: if H.out_degree(v) == 1 and v not in coatoms: return (False, self._vertex_to_element(v)) @@ -3782,8 +3782,8 @@ def is_dismantlable(self, certificate=False): if certificate: cert.append(e) if i == 1 and o == 1: # Remove inside the lattice - lower = H.neighbors_in(e)[0] - upper = H.neighbors_out(e)[0] + lower = next(H.neighbor_in_iterator(e)) + upper = next(H.neighbor_out_iterator(e)) H.delete_vertex(e) if upper not in H.depth_first_search(lower): H.add_edge(lower, upper) @@ -4125,11 +4125,11 @@ def canonical_meetands(self, e): H = self._hasse_diagram e = self._element_to_vertex(e) meetands = [] - for a in H.neighbors_out(e): - above_a = list(H.depth_first_search(a)) + for a in H.neighbor_out_iterator(e): + above_a = set(H.depth_first_search(a)) def go_up(v): - return [v_ for v_ in H.neighbors_out(v) if v_ not in above_a] + return [v_ for v_ in H.neighbor_out_iterator(v) if v_ not in above_a] result = None for v in H.depth_first_search(e, neighbors=go_up): @@ -4191,11 +4191,11 @@ def canonical_joinands(self, e): H = self._hasse_diagram e = self._element_to_vertex(e) joinands = [] - for a in H.neighbors_in(e): - below_a = list(H.depth_first_search(a, neighbors=H.neighbors_in)) + for a in H.neighbor_in_iterator(e): + below_a = set(H.depth_first_search(a, neighbors=H.neighbor_in_iterator)) def go_down(v): - return [v_ for v_ in H.neighbors_in(v) if v_ not in below_a] + return [v_ for v_ in H.neighbor_in_iterator(v) if v_ not in below_a] result = None for v in H.depth_first_search(e, neighbors=go_down): diff --git a/src/sage/combinat/posets/mobile.py b/src/sage/combinat/posets/mobile.py index f291400ce5f..321942a0fd7 100644 --- a/src/sage/combinat/posets/mobile.py +++ b/src/sage/combinat/posets/mobile.py @@ -112,13 +112,13 @@ def _is_valid_ribbon(self, ribbon): num_anchors = 0 for r in ribbon: - anchor_neighbors = set(G.neighbors_out(r)).difference(set(R.neighbors_out(r))) + anchor_neighbors = set(G.neighbor_out_iterator(r)).difference(set(R.neighbor_out_iterator(r))) if len(anchor_neighbors) == 1: num_anchors += 1 elif len(anchor_neighbors) > 1: return False - for lc in G.neighbors_in(r): + for lc in G.neighbor_in_iterator(r): if lc in ribbon: continue @@ -151,7 +151,7 @@ def _anchor(self): # Find the anchor vertex, if it exists, and return the edge for r in ribbon: - anchor_neighbors = set(H.neighbors_out(r)).difference(set(R.neighbors_out(r))) + anchor_neighbors = set(H.neighbor_out_iterator(r)).difference(set(R.neighbor_out_iterator(r))) if len(anchor_neighbors) == 1: anchor = (r, anchor_neighbors.pop()) break diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index f9a5d793dfa..f565c7f9903 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1,9 +1,10 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Catalog of posets and lattices Some common posets can be accessed through the ``posets.`` object:: - sage: posets.PentagonPoset() # optional - sage.modules + sage: posets.PentagonPoset() Finite lattice containing 5 elements Moreover, the set of all posets of order `n` is represented by ``Posets(n)``:: @@ -238,9 +239,9 @@ def BooleanLattice(n, facade=None, use_subsets=False): Check the corner cases:: - sage: list(posets.BooleanLattice(0, use_subsets=True)) # optional - sage.modules + sage: list(posets.BooleanLattice(0, use_subsets=True)) [{}] - sage: list(posets.BooleanLattice(1, use_subsets=True)) # optional - sage.modules + sage: list(posets.BooleanLattice(1, use_subsets=True)) [{}, {1}] """ n = check_int(n) @@ -382,22 +383,22 @@ def PentagonPoset(facade=None): EXAMPLES:: - sage: P = posets.PentagonPoset(); P # optional - sage.modules + sage: P = posets.PentagonPoset(); P Finite lattice containing 5 elements - sage: P.cover_relations() # optional - sage.modules + sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] TESTS: This is smallest lattice that is not modular:: - sage: P.is_modular() # optional - sage.modules + sage: P.is_modular() False This poset and the :meth:`DiamondPoset` are the two smallest lattices which are not distributive:: - sage: P.is_distributive() # optional - sage.modules + sage: P.is_distributive() False sage: posets.DiamondPoset(5).is_distributive() False @@ -535,9 +536,9 @@ def IntegerPartitions(n): EXAMPLES:: - sage: P = posets.IntegerPartitions(7); P # optional - sage.combinat + sage: P = posets.IntegerPartitions(7); P Finite poset containing 15 elements - sage: len(P.cover_relations()) # optional - sage.combinat + sage: len(P.cover_relations()) 28 """ def lower_covers(partition): @@ -573,9 +574,9 @@ def RestrictedIntegerPartitions(n): EXAMPLES:: - sage: P = posets.RestrictedIntegerPartitions(7); P # optional - sage.combinat + sage: P = posets.RestrictedIntegerPartitions(7); P Finite poset containing 15 elements - sage: len(P.cover_relations()) # optional - sage.combinat + sage: len(P.cover_relations()) 17 """ @@ -617,9 +618,9 @@ def IntegerPartitionsDominanceOrder(n): EXAMPLES:: - sage: P = posets.IntegerPartitionsDominanceOrder(6); P # optional - sage.combinat + sage: P = posets.IntegerPartitionsDominanceOrder(6); P Finite lattice containing 11 elements - sage: P.cover_relations() # optional - sage.combinat + sage: P.cover_relations() [[[1, 1, 1, 1, 1, 1], [2, 1, 1, 1, 1]], [[2, 1, 1, 1, 1], [2, 2, 1, 1]], [[2, 2, 1, 1], [2, 2, 2]], @@ -652,22 +653,22 @@ def PowerPoset(n): EXAMPLES:: - sage: P3 = posets.PowerPoset(3); P3 # optional - sage.modules + sage: P3 = posets.PowerPoset(3); P3 Finite meet-semilattice containing 19 elements - sage: all(P.is_chain() for P in P3.maximal_elements()) # optional - sage.modules + sage: all(P.is_chain() for P in P3.maximal_elements()) True TESTS:: - sage: P0 = posets.PowerPoset(0); P0 # optional - sage.modules + sage: P0 = posets.PowerPoset(0); P0 Finite meet-semilattice containing 1 elements - sage: P0[0] # optional - sage.modules + sage: P0[0] Finite poset containing 0 elements - sage: P1 = posets.PowerPoset(1); P1 # optional - sage.modules + sage: P1 = posets.PowerPoset(1); P1 Finite meet-semilattice containing 1 elements - sage: P1[0] # optional - sage.modules + sage: P1[0] Finite poset containing 1 elements - sage: P1[0][0] # optional - sage.modules + sage: P1[0][0] 0 """ # Todo: Make this faster. @@ -697,22 +698,22 @@ def ProductOfChains(chain_lengths, facade=None): EXAMPLES:: - sage: P = posets.ProductOfChains([2, 2]); P # optional - sage.modules + sage: P = posets.ProductOfChains([2, 2]); P Finite lattice containing 4 elements - sage: P.linear_extension() # optional - sage.modules + sage: P.linear_extension() [(0, 0), (0, 1), (1, 0), (1, 1)] - sage: P.upper_covers((0,0)) # optional - sage.modules + sage: P.upper_covers((0,0)) [(0, 1), (1, 0)] - sage: P.lower_covers((1,1)) # optional - sage.modules + sage: P.lower_covers((1,1)) [(0, 1), (1, 0)] TESTS:: - sage: P = posets.ProductOfChains([]); P # optional - sage.modules + sage: P = posets.ProductOfChains([]); P Finite lattice containing 0 elements - sage: P = posets.ProductOfChains([3, 0, 1]); P # optional - sage.modules + sage: P = posets.ProductOfChains([3, 0, 1]); P Finite lattice containing 0 elements - sage: P = posets.ProductOfChains([1,1,1,1]); P # optional - sage.modules + sage: P = posets.ProductOfChains([1,1,1,1]); P Finite lattice containing 1 elements """ try: @@ -831,12 +832,12 @@ def RandomLattice(n, p, properties=None): EXAMPLES:: sage: set_random_seed(0) # Results are reproducible - sage: L = posets.RandomLattice(8, 0.995); L # optional - sage.modules + sage: L = posets.RandomLattice(8, 0.995); L Finite lattice containing 8 elements - sage: L.cover_relations() # optional - sage.modules + sage: L.cover_relations() [[7, 6], [7, 3], [7, 1], ..., [5, 4], [2, 4], [1, 4], [0, 4]] - sage: L = posets.RandomLattice(10, 0, properties=['dismantlable']) # optional - sage.modules - sage: L.is_dismantlable() # optional - sage.modules + sage: L = posets.RandomLattice(10, 0, properties=['dismantlable']) + sage: L.is_dismantlable() True .. SEEALSO:: :meth:`RandomPoset` @@ -858,7 +859,7 @@ def RandomLattice(n, p, properties=None): ... ValueError: unknown value junk for 'properties' - sage: posets.RandomLattice(0, 0.5) # optional - sage.modules + sage: posets.RandomLattice(0, 0.5) Finite lattice containing 0 elements """ from copy import copy @@ -941,7 +942,7 @@ def SetPartitions(n): EXAMPLES:: - sage: posets.SetPartitions(4) # optional - sage.combinat + sage: posets.SetPartitions(4) Finite lattice containing 15 elements """ from sage.combinat.set_partition import SetPartitions @@ -981,19 +982,19 @@ def SSTPoset(s, f=None): EXAMPLES:: - sage: posets.SSTPoset([2,1]) # optional - sage.combinat + sage: posets.SSTPoset([2,1]) Finite lattice containing 8 elements - sage: posets.SSTPoset([2,1],4) # optional - sage.combinat + sage: posets.SSTPoset([2,1],4) Finite lattice containing 20 elements - sage: posets.SSTPoset([2,1],2).cover_relations() # optional - sage.combinat + sage: posets.SSTPoset([2,1],2).cover_relations() [[[[1, 1], [2]], [[1, 2], [2]]]] - sage: posets.SSTPoset([3,2]).bottom() # long time (6s on sage.math, 2012) # optional - sage.combinat + sage: posets.SSTPoset([3,2]).bottom() # long time (6s on sage.math, 2012) [[1, 1, 1], [2, 2]] - sage: posets.SSTPoset([3,2],4).maximal_elements() # optional - sage.combinat + sage: posets.SSTPoset([3,2],4).maximal_elements() [[[3, 3, 4], [4, 4]]] """ from sage.combinat.tableau import SemistandardTableaux @@ -1202,11 +1203,11 @@ def TetrahedralPoset(n, *colors, **labels): sage: posets.TetrahedralPoset(4,'green','red','yellow','silver','blue','orange', labels='integers') Finite poset containing 10 elements - sage: A = AlternatingSignMatrices(3) # optional - sage.combinat sage.modules - sage: p = A.lattice() # optional - sage.combinat sage.modules - sage: ji = p.join_irreducibles_poset() # optional - sage.combinat sage.modules - sage: tet = posets.TetrahedralPoset(3, 'green','yellow','blue','orange') # optional - sage.combinat sage.modules - sage: ji.is_isomorphic(tet) # optional - sage.combinat sage.modules + sage: A = AlternatingSignMatrices(3) + sage: p = A.lattice() + sage: ji = p.join_irreducibles_poset() + sage: tet = posets.TetrahedralPoset(3, 'green','yellow','blue','orange') + sage: ji.is_isomorphic(tet) True TESTS:: @@ -1276,12 +1277,12 @@ def CoxeterGroupAbsoluteOrderPoset(W, use_reduced_words=True): EXAMPLES:: - sage: W = CoxeterGroup(['B', 3]) # optional - sage.combinat sage.groups - sage: posets.CoxeterGroupAbsoluteOrderPoset(W) # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['B', 3]) # needs sage.groups + sage: posets.CoxeterGroupAbsoluteOrderPoset(W) # needs sage.groups Finite poset containing 48 elements - sage: W = WeylGroup(['B', 2], prefix='s') # optional - sage.combinat sage.groups - sage: posets.CoxeterGroupAbsoluteOrderPoset(W, False) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['B', 2], prefix='s') # needs sage.groups + sage: posets.CoxeterGroupAbsoluteOrderPoset(W, False) # needs sage.groups Finite poset containing 8 elements """ if use_reduced_words: @@ -1300,12 +1301,12 @@ def NoncrossingPartitions(W): EXAMPLES:: - sage: W = CoxeterGroup(['A', 3]) # optional - sage.combinat sage.groups - sage: posets.NoncrossingPartitions(W) # optional - sage.combinat sage.groups + sage: W = CoxeterGroup(['A', 3]) # needs sage.groups + sage: posets.NoncrossingPartitions(W) # needs sage.groups Finite lattice containing 14 elements - sage: W = WeylGroup(['B', 2], prefix='s') # optional - sage.combinat sage.groups - sage: posets.NoncrossingPartitions(W) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['B', 2], prefix='s') # needs sage.groups + sage: posets.NoncrossingPartitions(W) # needs sage.groups Finite lattice containing 6 elements """ return W.noncrossing_partition_lattice() @@ -1331,11 +1332,11 @@ def SymmetricGroupAbsoluteOrderPoset(n, labels="permutations"): EXAMPLES:: - sage: posets.SymmetricGroupAbsoluteOrderPoset(4) # optional - sage.groups + sage: posets.SymmetricGroupAbsoluteOrderPoset(4) # needs sage.groups Finite poset containing 24 elements - sage: posets.SymmetricGroupAbsoluteOrderPoset(3, labels="cycles") # optional - sage.groups + sage: posets.SymmetricGroupAbsoluteOrderPoset(3, labels="cycles") # needs sage.groups Finite poset containing 6 elements - sage: posets.SymmetricGroupAbsoluteOrderPoset(3, labels="reduced_words") # optional - sage.groups + sage: posets.SymmetricGroupAbsoluteOrderPoset(3, labels="reduced_words") # needs sage.groups Finite poset containing 6 elements """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -1380,7 +1381,7 @@ def UpDownPoset(n, m=1): Fibonacci numbers as the number of antichains of a poset:: - sage: [len(posets.UpDownPoset(n).antichains().list()) for n in range(6)] # optional - sage.combinat + sage: [len(posets.UpDownPoset(n).antichains().list()) for n in range(6)] [1, 2, 3, 5, 8, 13] TESTS:: @@ -1414,13 +1415,13 @@ def YoungDiagramPoset(lam, dual=False): EXAMPLES:: - sage: P = posets.YoungDiagramPoset(Partition([2, 2])); P # optional - sage.combinat + sage: P = posets.YoungDiagramPoset(Partition([2, 2])); P Finite meet-semilattice containing 4 elements - sage: sorted(P.cover_relations()) # optional - sage.combinat + sage: sorted(P.cover_relations()) [[(0, 0), (0, 1)], [(0, 0), (1, 0)], [(0, 1), (1, 1)], [(1, 0), (1, 1)]] - sage: posets.YoungDiagramPoset([3, 2], dual=True) # optional - sage.combinat + sage: posets.YoungDiagramPoset([3, 2], dual=True) Finite join-semilattice containing 5 elements """ from sage.combinat.partition import Partition @@ -1460,9 +1461,9 @@ def YoungsLattice(n): EXAMPLES:: - sage: P = posets.YoungsLattice(3); P # optional - sage.combinat + sage: P = posets.YoungsLattice(3); P Finite meet-semilattice containing 7 elements - sage: P.cover_relations() # optional - sage.combinat + sage: P.cover_relations() [[[], [1]], [[1], [1, 1]], [[1], [2]], @@ -1488,10 +1489,10 @@ def YoungsLatticePrincipalOrderIdeal(lam): EXAMPLES:: - sage: P = posets.YoungsLatticePrincipalOrderIdeal(Partition([2,2])) # optional - sage.combinat - sage: P # optional - sage.combinat + sage: P = posets.YoungsLatticePrincipalOrderIdeal(Partition([2,2])) + sage: P Finite lattice containing 6 elements - sage: P.cover_relations() # optional - sage.combinat + sage: P.cover_relations() [[[], [1]], [[1], [1, 1]], [[1], [2]], @@ -1527,16 +1528,16 @@ def YoungFibonacci(n): EXAMPLES:: - sage: Y5 = posets.YoungFibonacci(5); Y5 # optional - sage.combinat + sage: Y5 = posets.YoungFibonacci(5); Y5 Finite meet-semilattice containing 20 elements - sage: sorted(Y5.upper_covers(Word('211'))) # optional - sage.combinat + sage: sorted(Y5.upper_covers(Word('211'))) [word: 1211, word: 2111, word: 221] TESTS:: - sage: posets.YoungFibonacci(0) # optional - sage.combinat + sage: posets.YoungFibonacci(0) Finite meet-semilattice containing 1 elements - sage: posets.YoungFibonacci(1) # optional - sage.combinat + sage: posets.YoungFibonacci(1) Finite meet-semilattice containing 2 elements """ from sage.combinat.posets.lattices import FiniteMeetSemilattice @@ -1616,9 +1617,9 @@ def PermutationPattern(n): EXAMPLES:: - sage: P4 = posets.PermutationPattern(4); P4 # optional - sage.combinat + sage: P4 = posets.PermutationPattern(4); P4 Finite poset containing 33 elements - sage: sorted(P4.lower_covers(Permutation([2,4,1,3]))) # optional - sage.combinat + sage: sorted(P4.lower_covers(Permutation([2,4,1,3]))) [[1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2]] .. SEEALSO:: @@ -1627,9 +1628,9 @@ def PermutationPattern(n): TESTS:: - sage: posets.PermutationPattern(1) # optional - sage.combinat + sage: posets.PermutationPattern(1) Finite poset containing 1 elements - sage: posets.PermutationPattern(2) # optional - sage.combinat + sage: posets.PermutationPattern(2) Finite poset containing 3 elements """ n = check_int(n, 1) @@ -1660,9 +1661,9 @@ def PermutationPatternInterval(bottom, top): sage: t = Permutation([2,3,1]) sage: b = Permutation([4,6,2,3,5,1]) - sage: R = posets.PermutationPatternInterval(t, b); R # optional - sage.combinat + sage: R = posets.PermutationPatternInterval(t, b); R Finite poset containing 14 elements - sage: R.moebius_function(R.bottom(),R.top()) # optional - sage.combinat + sage: R.moebius_function(R.bottom(),R.top()) -4 .. SEEALSO:: @@ -1673,7 +1674,7 @@ def PermutationPatternInterval(bottom, top): TESTS:: sage: p = Permutation([1]) - sage: posets.PermutationPatternInterval(p, p) # optional - sage.combinat + sage: posets.PermutationPatternInterval(p, p) Finite poset containing 1 elements """ P = Permutations() @@ -1732,7 +1733,7 @@ def PermutationPatternOccurrenceInterval(bottom, top, pos): sage: t = Permutation([3,2,1]) sage: b = Permutation([6,3,4,5,2,1]) - sage: A = posets.PermutationPatternOccurrenceInterval(t, b, (0,2,4)); A # optional - sage.combinat + sage: A = posets.PermutationPatternOccurrenceInterval(t, b, (0,2,4)); A Finite poset containing 8 elements .. SEEALSO:: @@ -1818,11 +1819,11 @@ def MobilePoset(ribbon, hangers, anchor=None): sage: len(M.cover_relations()) 7 - sage: P = posets.MobilePoset(posets.RibbonPoset(7, [1,3]), # optional - sage.combinat + sage: P = posets.MobilePoset(posets.RibbonPoset(7, [1,3]), ....: {1: [posets.YoungDiagramPoset([3, 2], dual=True)], ....: 3: [posets.DoubleTailedDiamond(6)]}, ....: anchor=(4, 2, posets.ChainPoset(6))) - sage: len(P.cover_relations()) # optional - sage.combinat + sage: len(P.cover_relations()) 33 """ elements = [] @@ -2039,8 +2040,8 @@ def _random_distributive_lattice(n): EXAMPLES:: - sage: g = sage.combinat.posets.poset_examples._random_distributive_lattice(10) # optional - sage.modules - sage: Poset(g).order_ideals_lattice(as_ideals=False).cardinality() # optional - sage.modules + sage: g = sage.combinat.posets.poset_examples._random_distributive_lattice(10) + sage: Poset(g).order_ideals_lattice(as_ideals=False).cardinality() 10 ALGORITHM: @@ -2095,8 +2096,8 @@ def _random_stone_lattice(n): EXAMPLES:: - sage: g = sage.combinat.posets.poset_examples._random_stone_lattice(10) # optional - sage.combinat - sage: LatticePoset(g).is_stone() # optional - sage.combinat + sage: g = sage.combinat.posets.poset_examples._random_stone_lattice(10) + sage: LatticePoset(g).is_stone() True ALGORITHM: diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index c21bcc899e1..a832e6a673f 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# sage.doctest: needs sage.graphs sage.modules r""" Finite posets @@ -433,7 +434,8 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio With a function that identifies the cover relations: the set partitions of `\{1, 2, 3\}` ordered by refinement:: - sage: elms = SetPartitions(3) # optional - sage.combinat + sage: # needs sage.combinat + sage: elms = SetPartitions(3) sage: def fcn(A, B): ....: if len(A) != len(B)+1: ....: return False @@ -441,7 +443,7 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio ....: if not any(set(a).issubset(b) for b in B): ....: return False ....: return True - sage: Poset((elms, fcn), cover_relations=True) # optional - sage.combinat + sage: Poset((elms, fcn), cover_relations=True) Finite poset containing 5 elements 3. A dictionary of upper covers:: @@ -1350,7 +1352,7 @@ def hasse_diagram(self): [1, 3, 5, 15] sage: H.edges(sort=True) [(1, 3, None), (1, 5, None), (3, 15, None), (5, 15, None)] - sage: H.set_latex_options(format="dot2tex") # optional - sage.plot + sage: H.set_latex_options(format="dot2tex") sage: view(H) # optional - dot2tex, not tested (opens external window) """ G = DiGraph(self._hasse_diagram).relabel(self._list, inplace=False) @@ -1396,8 +1398,8 @@ def _repr_(self): sage: P5._repr_() 'Finite poset containing 7 elements' - sage: M = MeetSemilattice([[1,2],[3],[3]]) # optional - sage.modules - sage: M._repr_() # optional - sage.modules + sage: M = MeetSemilattice([[1,2],[3],[3]]) + sage: M._repr_() 'Finite meet-semilattice containing 3 elements' """ s = "%s containing %s elements" % (self._desc, self._hasse_diagram.order()) @@ -1499,14 +1501,14 @@ def sorted(self, l, allow_incomparable=True, remove_duplicates=False): TESTS:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.sorted([], allow_incomparable=True, remove_duplicates=True) # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.sorted([], allow_incomparable=True, remove_duplicates=True) [] - sage: P.sorted([], allow_incomparable=False, remove_duplicates=True) # optional - sage.modules + sage: P.sorted([], allow_incomparable=False, remove_duplicates=True) [] - sage: P.sorted([], allow_incomparable=True, remove_duplicates=False) # optional - sage.modules + sage: P.sorted([], allow_incomparable=True, remove_duplicates=False) [] - sage: P.sorted([], allow_incomparable=False, remove_duplicates=False) # optional - sage.modules + sage: P.sorted([], allow_incomparable=False, remove_duplicates=False) [] """ v = [self._element_to_vertex(x) for x in l] @@ -1616,7 +1618,7 @@ def linear_extensions(self, facade=False): [1, 2, 3, 4, 6, 12] sage: L.cardinality() 5 - sage: L.list() # optional - sage.modules sage.rings.finite_rings + sage: L.list() [[1, 2, 3, 4, 6, 12], [1, 2, 4, 3, 6, 12], [1, 3, 2, 4, 6, 12], @@ -1630,9 +1632,9 @@ def linear_extensions(self, facade=False): With ``facade=True``, the elements of ``L`` are plain lists instead:: - sage: L = P.linear_extensions(facade=True) # optional - sage.modules sage.rings.finite_rings - sage: l = L.an_element() # optional - sage.modules sage.rings.finite_rings - sage: type(l) # optional - sage.modules sage.rings.finite_rings + sage: L = P.linear_extensions(facade=True) + sage: l = L.an_element() + sage: type(l) .. WARNING:: @@ -1640,13 +1642,13 @@ def linear_extensions(self, facade=False): In Sage <= 4.8, this function used to return a plain list of lists. To recover the previous functionality, please use:: - sage: L = list(P.linear_extensions(facade=True)); L # optional - sage.modules sage.rings.finite_rings + sage: L = list(P.linear_extensions(facade=True)); L [[1, 2, 3, 4, 6, 12], [1, 2, 4, 3, 6, 12], [1, 3, 2, 4, 6, 12], [1, 3, 2, 6, 4, 12], [1, 2, 3, 6, 4, 12]] - sage: type(L[0]) # optional - sage.modules sage.rings.finite_rings + sage: type(L[0]) .. SEEALSO:: :meth:`linear_extension`, :meth:`is_linear_extension` @@ -1654,7 +1656,7 @@ def linear_extensions(self, facade=False): TESTS:: sage: D = Poset({ 0:[1,2], 1:[3], 2:[3,4] }) - sage: list(D.linear_extensions()) # optional - sage.modules sage.rings.finite_rings + sage: list(D.linear_extensions()) [[0, 1, 2, 3, 4], [0, 2, 1, 3, 4], [0, 2, 1, 4, 3], [0, 2, 4, 1, 3], [0, 1, 2, 4, 3]] """ return self._lin_ext_type(self, facade=facade) @@ -1678,19 +1680,19 @@ def spectrum(self, a): EXAMPLES:: sage: P = posets.ChainPoset(5) - sage: P.spectrum(2) # optional - sage.modules sage.rings.finite_rings + sage: P.spectrum(2) [0, 0, 1, 0, 0] sage: P = posets.BooleanLattice(3) - sage: P.spectrum(5) # optional - sage.modules sage.rings.finite_rings + sage: P.spectrum(5) [0, 0, 0, 4, 12, 16, 16, 0] - sage: P = posets.YoungDiagramPoset(Partition([3,2,1])) # optional - sage.combinat - sage: P.spectrum((0,1)) # optional - sage.combinat sage.modules sage.rings.finite_rings + sage: P = posets.YoungDiagramPoset(Partition([3,2,1])) # needs sage.combinat + sage: P.spectrum((0,1)) # needs sage.combinat [0, 8, 6, 2, 0, 0] sage: P = posets.AntichainPoset(4) - sage: P.spectrum(3) # optional - sage.modules sage.rings.finite_rings + sage: P.spectrum(3) [6, 6, 6, 6] TESTS:: @@ -1826,7 +1828,7 @@ def is_linear_extension(self, l) -> bool: [1, 2, 4, 3, 6, 12], [1, 3, 2, 4, 6, 12], [1, 3, 2, 6, 4, 12]] - sage: list(P.linear_extensions()) # optional - sage.modules sage.rings.finite_rings + sage: list(P.linear_extensions()) [[1, 2, 3, 4, 6, 12], [1, 2, 4, 3, 6, 12], [1, 3, 2, 4, 6, 12], @@ -1853,10 +1855,10 @@ def is_linear_extension(self, l) -> bool: sage: P.is_linear_extension(['David', 'McNeil', 'La', 'Lamentable', 'Aventure', 'de', 'Simon', 'Wiesenthal']) False """ - index = {x: i for (i, x) in enumerate(l)} + index = {x: i for i, x in enumerate(l)} return (len(l) == self.cardinality() and all(x in index for x in self) and - all(index[i] < index[j] for (i, j) in self.cover_relations())) + all(index[i] < index[j] for i, j in self.cover_relations())) def list(self): """ @@ -1931,37 +1933,41 @@ def plot(self, label_elements=True, element_labels=None, This function can be used without any parameters:: + sage: # needs sage.plot sage: D12 = posets.DivisorLattice(12) - sage: D12.plot() # optional - sage.plot + sage: D12.plot() Graphics object consisting of 14 graphics primitives Just the abstract form of the poset; examples of relabeling:: - sage: D12.plot(label_elements=False) # optional - sage.plot + sage: # needs sage.plot + sage: D12.plot(label_elements=False) Graphics object consisting of 8 graphics primitives sage: d = {1: 0, 2: 'a', 3: 'b', 4: 'c', 6: 'd', 12: 1} - sage: D12.plot(element_labels=d) # optional - sage.plot + sage: D12.plot(element_labels=d) Graphics object consisting of 14 graphics primitives sage: d = {i: str(factor(i)) for i in D12} - sage: D12.plot(element_labels=d) # optional - sage.plot + sage: D12.plot(element_labels=d) Graphics object consisting of 14 graphics primitives Some settings for coverings:: + sage: # needs sage.plot sage: d = {(a, b): b/a for a, b in D12.cover_relations()} - sage: D12.plot(cover_labels=d, cover_color='gray', cover_style='dotted') # optional - sage.plot + sage: D12.plot(cover_labels=d, cover_color='gray', cover_style='dotted') Graphics object consisting of 21 graphics primitives To emphasize some elements and show some options:: - sage: L = LatticePoset({0: [1, 2, 3, 4], 1: [12], 2: [6, 7], # optional - sage.modules + sage: # needs sage.plot + sage: L = LatticePoset({0: [1, 2, 3, 4], 1: [12], 2: [6, 7], ....: 3: [5, 9], 4: [5, 6, 10, 11], 5: [13], ....: 6: [12], 7: [12, 8, 9], 8: [13], 9: [13], ....: 10: [12], 11: [12], 12: [13]}) - sage: F = L.frattini_sublattice() # optional - sage.modules - sage: F_internal = [c for c in F.cover_relations() # optional - sage.modules + sage: F = L.frattini_sublattice() + sage: F_internal = [c for c in F.cover_relations() ....: if c in L.cover_relations()] - sage: L.plot(figsize=12, border=True, element_shape='s', # optional - sage.modules sage.plot + sage: L.plot(figsize=12, border=True, element_shape='s', ....: element_size=400, element_color='white', ....: element_colors={'blue': F, 'green': L.double_irreducibles()}, ....: cover_color='lightgray', cover_colors={'black': F_internal}, @@ -1972,51 +1978,56 @@ def plot(self, label_elements=True, element_labels=None, We check that ``label_elements`` and ``element_labels`` are honored:: + sage: # needs sage.plot sage: def get_plot_labels(P): ....: return sorted(t.string for t in P ....: if isinstance(t, sage.plot.text.Text)) sage: P1 = Poset({ 0:[1,2], 1:[3], 2:[3,4] }) sage: P2 = Poset({ 0:[1,2], 1:[3], 2:[3,4] }, facade=True) - sage: get_plot_labels(P1.plot(label_elements=False)) # optional - sage.plot + sage: get_plot_labels(P1.plot(label_elements=False)) [] - sage: get_plot_labels(P1.plot(label_elements=True)) # optional - sage.plot + sage: get_plot_labels(P1.plot(label_elements=True)) ['0', '1', '2', '3', '4'] sage: element_labels = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e'} - sage: get_plot_labels(P1.plot(element_labels=element_labels)) # optional - sage.plot + sage: get_plot_labels(P1.plot(element_labels=element_labels)) ['a', 'b', 'c', 'd', 'e'] - sage: get_plot_labels(P2.plot(element_labels=element_labels)) # optional - sage.plot + sage: get_plot_labels(P2.plot(element_labels=element_labels)) ['a', 'b', 'c', 'd', 'e'] The following checks that :trac:`18936` has been fixed and labels still work:: + sage: # needs sage.plot sage: P = Poset({0: [1,2], 1:[3]}) sage: heights = {1 : [0], 2 : [1], 3 : [2,3]} - sage: P.plot(heights=heights) # optional - sage.plot + sage: P.plot(heights=heights) Graphics object consisting of 8 graphics primitives sage: elem_labels = {0 : 'a', 1 : 'b', 2 : 'c', 3 : 'd'} - sage: P.plot(element_labels=elem_labels, heights=heights) # optional - sage.plot + sage: P.plot(element_labels=elem_labels, heights=heights) Graphics object consisting of 8 graphics primitives The following checks that equal labels are allowed (:trac:`15206`):: + sage: # needs sage.plot sage: P = Poset({1: [2,3]}) sage: labs = {i: P.rank(i) for i in range(1, 4)}; labs {1: 0, 2: 1, 3: 1} - sage: P.plot(element_labels=labs) # optional - sage.plot + sage: P.plot(element_labels=labs) Graphics object consisting of 6 graphics primitives The following checks that non-hashable labels are allowed (:trac:`15206`):: + sage: # needs sage.plot sage: P = Poset({1: [2,3]}) sage: labs = {1: [2, 3], 2: [], 3: []}; labs {1: [2, 3], 2: [], 3: []} - sage: P.plot(element_labels=labs) # optional - sage.plot + sage: P.plot(element_labels=labs) Graphics object consisting of 6 graphics primitives Plot of the empty poset:: + sage: # needs sage.plot sage: P = Poset({}) - sage: P.plot() # optional - sage.plot + sage: P.plot() Graphics object consisting of 0 graphics primitives """ graph = self.hasse_diagram() @@ -2046,7 +2057,7 @@ def plot(self, label_elements=True, element_labels=None, if label_elements and element_labels is not None: from sage.misc.element_with_label import ElementWithLabel relabeling = {self(element): ElementWithLabel(self(element), label) - for (element, label) in element_labels.items()} + for element, label in element_labels.items()} graph = graph.relabel(relabeling, inplace=False) if heights is not None: for key in heights: @@ -2054,14 +2065,14 @@ def plot(self, label_elements=True, element_labels=None, if cover_labels is not None: if callable(cover_labels): - for (v, w) in graph.edges(sort=True, labels=False): + for v, w in graph.edges(sort=False, labels=False): graph.set_edge_label(v, w, cover_labels(v, w)) elif isinstance(cover_labels, dict): - for (v, w) in cover_labels: + for v, w in cover_labels: graph.set_edge_label(self(v), self(w), cover_labels[(v, w)]) else: - for (v, w, l) in cover_labels: + for v, w, l in cover_labels: graph.set_edge_label(self(v), self(w), l) cover_labels = True else: @@ -2102,18 +2113,19 @@ def show(self, label_elements=True, element_labels=None, EXAMPLES:: + sage: # needs sage.plot sage: D = Poset({ 0:[1,2], 1:[3], 2:[3,4] }) - sage: D.plot(label_elements=False) # optional - sage.plot + sage: D.plot(label_elements=False) Graphics object consisting of 6 graphics primitives - sage: D.show() # optional - sage.plot + sage: D.show() sage: elm_labs = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e'} - sage: D.show(element_labels=elm_labs) # optional - sage.plot + sage: D.show(element_labels=elm_labs) One more example with cover labels:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.show(cover_labels=lambda a, b: a - b) # optional - sage.modules sage.plot - + sage: # needs sage.plot + sage: P = posets.PentagonPoset() + sage: P.show(cover_labels=lambda a, b: a - b) """ # We split the arguments into those meant for plot() and those meant for show() # @@ -2287,8 +2299,8 @@ def diamonds(self): sage: P.diamonds() ([(0, 1, 2, 3)], True) - sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) # optional - sage.combinat - sage: P.diamonds() # optional - sage.combinat + sage: P = posets.YoungDiagramPoset(Partition([3, 2, 2])) # needs sage.combinat + sage: P.diamonds() # needs sage.combinat ([((0, 0), (0, 1), (1, 0), (1, 1)), ((1, 0), (1, 1), (2, 0), (2, 1))], False) """ diamonds, all_diamonds_completed = self._hasse_diagram.diamonds() @@ -2328,23 +2340,23 @@ def meet(self, x, y): EXAMPLES:: sage: D = Poset({1:[2,3], 2:[4], 3:[4]}) - sage: D.meet(2, 3) # optional - sage.modules + sage: D.meet(2, 3) 1 sage: P = Poset({'a':['b', 'c'], 'b':['e', 'f'], 'c':['f', 'g'], ....: 'd':['f', 'g']}) - sage: P.meet('a', 'b') # optional - sage.modules + sage: P.meet('a', 'b') 'a' - sage: P.meet('e', 'a') # optional - sage.modules + sage: P.meet('e', 'a') 'a' - sage: P.meet('c', 'b') # optional - sage.modules + sage: P.meet('c', 'b') 'a' - sage: P.meet('e', 'f') # optional - sage.modules + sage: P.meet('e', 'f') 'b' - sage: P.meet('e', 'g') # optional - sage.modules + sage: P.meet('e', 'g') 'a' - sage: P.meet('c', 'd') is None # optional - sage.modules + sage: P.meet('c', 'd') is None True - sage: P.meet('g', 'f') is None # optional - sage.modules + sage: P.meet('g', 'f') is None True """ i, j = map(self._element_to_vertex, (x, y)) @@ -2362,23 +2374,23 @@ def join(self, x, y): EXAMPLES:: sage: D = Poset({1:[2,3], 2:[4], 3:[4]}) - sage: D.join(2, 3) # optional - sage.modules + sage: D.join(2, 3) 4 sage: P = Poset({'e':['b'], 'f':['b', 'c', 'd'], 'g':['c', 'd'], ....: 'b':['a'], 'c':['a']}) - sage: P.join('a', 'b') # optional - sage.modules + sage: P.join('a', 'b') 'a' - sage: P.join('e', 'a') # optional - sage.modules + sage: P.join('e', 'a') 'a' - sage: P.join('c', 'b') # optional - sage.modules + sage: P.join('c', 'b') 'a' - sage: P.join('e', 'f') # optional - sage.modules + sage: P.join('e', 'f') 'b' - sage: P.join('e', 'g') # optional - sage.modules + sage: P.join('e', 'g') 'a' - sage: P.join('c', 'd') is None # optional - sage.modules + sage: P.join('c', 'd') is None True - sage: P.join('g', 'f') is None # optional - sage.modules + sage: P.join('g', 'f') is None True """ i, j = map(self._element_to_vertex, (x, y)) @@ -2416,8 +2428,8 @@ def is_d_complete(self) -> bool: sage: D.is_d_complete() False - sage: P = Posets.YoungDiagramPoset(Partition([3, 2, 2]), dual=True) # optional - sage.combinat - sage: P.is_d_complete() # optional - sage.combinat + sage: P = Posets.YoungDiagramPoset(Partition([3, 2, 2]), dual=True) # needs sage.combinat + sage: P.is_d_complete() # needs sage.combinat True """ min_diamond = {} # Maps max of double-tailed diamond to min of double-tailed diamond @@ -2441,7 +2453,7 @@ def is_d_complete(self) -> bool: min_elmt = d[0] max_elmt = d[3] - if len(H.neighbors_in(max_elmt)) != 2: + if H.in_degree(max_elmt) != 2: # Top of a diamond cannot cover anything but the two side elements return False @@ -2457,7 +2469,7 @@ def is_d_complete(self) -> bool: continue for mx in potential_max: if len(H.all_paths(mn, mx)) == 2: - if len(H.neighbors_in(mx)) != 1: + if H.in_degree(mx) != 1: # Max element covers something outside of double tailed diamond return False # Success @@ -2535,8 +2547,8 @@ def intervals_poset(self): sage: P.intervals_poset() Finite poset containing 3 elements - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.intervals_poset() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.intervals_poset() Finite lattice containing 13 elements TESTS:: @@ -2563,7 +2575,7 @@ def intervals_poset(self): ints = [tuple(u) for u in self.relations()] covers = [] - for (a, b) in ints: + for a, b in ints: covers.extend([[(a, b), (a, bb)] for bb in self.upper_covers(b)]) if a != b: covers.extend([[(a, b), (aa, b)] for aa in self.upper_covers(a) @@ -2599,8 +2611,8 @@ def relations_iterator(self, strict=False): sage: next(it), next(it) ([1, 1], [1, 2]) - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: list(P.relations_iterator(strict=True)) # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: list(P.relations_iterator(strict=True)) [[0, 1], [0, 2], [0, 4], [0, 3], [1, 4], [2, 3], [2, 4], [3, 4]] .. SEEALSO:: @@ -2635,8 +2647,8 @@ def relations_number(self): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.relations_number() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.relations_number() 13 sage: posets.TamariLattice(4).relations_number() @@ -2668,8 +2680,8 @@ def linear_intervals_count(self) -> List[int]: EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.linear_intervals_count() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.linear_intervals_count() [5, 5, 2] sage: P = posets.TamariLattice(4) sage: P.linear_intervals_count() @@ -2714,12 +2726,12 @@ def is_linear_interval(self, x, y) -> bool: EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.is_linear_interval(0, 4) # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.is_linear_interval(0, 4) False - sage: P.is_linear_interval(0, 3) # optional - sage.modules + sage: P.is_linear_interval(0, 3) True - sage: P.is_linear_interval(1, 3) # optional - sage.modules + sage: P.is_linear_interval(1, 3) False """ a = self._element_to_vertex(x) @@ -2749,44 +2761,44 @@ def is_incomparable_chain_free(self, m, n=None) -> bool: EXAMPLES:: sage: B3 = posets.BooleanLattice(3) - sage: B3.is_incomparable_chain_free(1, 3) # optional - sage.modules + sage: B3.is_incomparable_chain_free(1, 3) True - sage: B3.is_incomparable_chain_free(2, 2) # optional - sage.modules + sage: B3.is_incomparable_chain_free(2, 2) False - sage: IP6 = posets.IntegerPartitions(6) # optional - sage.combinat - sage: IP6.is_incomparable_chain_free(1, 3) # optional - sage.combinat sage.modules + sage: IP6 = posets.IntegerPartitions(6) # needs sage.combinat + sage: IP6.is_incomparable_chain_free(1, 3) # needs sage.combinat False - sage: IP6.is_incomparable_chain_free(2, 2) # optional - sage.combinat sage.modules + sage: IP6.is_incomparable_chain_free(2, 2) # needs sage.combinat True A list of pairs as an argument:: - sage: B3.is_incomparable_chain_free([[1, 3], [2, 2]]) # optional - sage.modules + sage: B3.is_incomparable_chain_free([[1, 3], [2, 2]]) False We show how to get an incomparable chain pair:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: chains_1_2 = Poset({0:[], 1:[2]}) # optional - sage.modules - sage: incomps = P.isomorphic_subposets(chains_1_2)[0] # optional - sage.modules - sage: sorted(incomps.list()), incomps.cover_relations() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: chains_1_2 = Poset({0:[], 1:[2]}) + sage: incomps = P.isomorphic_subposets(chains_1_2)[0] + sage: sorted(incomps.list()), incomps.cover_relations() ([1, 2, 3], [[2, 3]]) TESTS:: - sage: Poset().is_incomparable_chain_free(1,1) # Test empty poset # optional - sage.modules + sage: Poset().is_incomparable_chain_free(1,1) # Test empty poset True - sage: [len([p for p in Posets(n) # long time # optional - sage.modules + sage: [len([p for p in Posets(n) # long time ....: if p.is_incomparable_chain_free(((3, 1), (2, 2)))]) ....: for n in range(6)] [1, 1, 2, 5, 14, 42] sage: Q = Poset({0:[2], 1:[2], 2:[3], 3:[4], 4:[]}) - sage: Q.is_incomparable_chain_free(2, 20/10) # optional - sage.modules + sage: Q.is_incomparable_chain_free(2, 20/10) True - sage: Q.is_incomparable_chain_free(2, pi) # optional - sage.symbolic + sage: Q.is_incomparable_chain_free(2, pi) # needs sage.symbolic Traceback (most recent call last): ... TypeError: 2 and pi must be integers @@ -2803,9 +2815,9 @@ def is_incomparable_chain_free(self, m, n=None) -> bool: Traceback (most recent call last): ... TypeError: [3, 1] and [2, 2] must be integers - sage: P.is_incomparable_chain_free([[3, 1], [2, 2]]) # optional - sage.modules + sage: P.is_incomparable_chain_free([[3, 1], [2, 2]]) True - sage: P.is_incomparable_chain_free(([3, 1], [2, 2])) # optional - sage.modules + sage: P.is_incomparable_chain_free(([3, 1], [2, 2])) True sage: P.is_incomparable_chain_free([3, 1], 2) Traceback (most recent call last): @@ -3140,7 +3152,7 @@ def height(self, certificate=False): sage: P = Poset({0: [1], 2: [3, 4], 4: [5, 6]}) sage: P.height() 3 - sage: posets.PentagonPoset().height(certificate=True) # optional - sage.modules + sage: posets.PentagonPoset().height(certificate=True) (4, [0, 2, 3, 4]) TESTS:: @@ -3186,14 +3198,14 @@ def has_isomorphic_subposet(self, other): sage: D = Poset({1:[2,3], 2:[4], 3:[4]}) sage: T = Poset({1:[2,3], 2:[4,5], 3:[6,7]}) - sage: N5 = posets.PentagonPoset() # optional - sage.modules + sage: N5 = posets.PentagonPoset() - sage: N5.has_isomorphic_subposet(T) # optional - sage.modules + sage: N5.has_isomorphic_subposet(T) False - sage: N5.has_isomorphic_subposet(D) # optional - sage.modules + sage: N5.has_isomorphic_subposet(D) True - sage: len([P for P in Posets(5) if P.has_isomorphic_subposet(D)]) # optional - sage.modules + sage: len([P for P in Posets(5) if P.has_isomorphic_subposet(D)]) 11 """ @@ -3341,17 +3353,17 @@ def is_antichain_of_poset(self, elms): TESTS:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.is_antichain_of_poset([]) # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.is_antichain_of_poset([]) True - sage: P.is_antichain_of_poset([0]) # optional - sage.modules + sage: P.is_antichain_of_poset([0]) True - sage: P.is_antichain_of_poset([1, 2, 1]) # optional - sage.modules + sage: P.is_antichain_of_poset([1, 2, 1]) True Check :trac:`19078`:: - sage: P.is_antichain_of_poset([0, 1, 'junk']) # optional - sage.modules + sage: P.is_antichain_of_poset([0, 1, 'junk']) Traceback (most recent call last): ... ValueError: element (=junk) not in poset @@ -3620,7 +3632,7 @@ def dimension(self, certificate=False, *, solver=None, integrality_tolerance=1e- P = Poset(self._hasse_diagram) # work on an int-labelled poset hasse_diagram = P.hasse_diagram() inc_graph = P.incomparability_graph() - inc_P = inc_graph.edges(sort=True, labels=False) + inc_P = inc_graph.edges(sort=False, labels=False) # cycles is the list of all cycles found during the execution of the # algorithm @@ -3704,37 +3716,39 @@ def magnitude(self) -> Integer: EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.magnitude() # optional - sage.libs.flint sage.modules + sage: # needs sage.groups sage.libs.flint + sage: P = posets.PentagonPoset() + sage: P.magnitude() 1 - sage: W = SymmetricGroup(4) # optional - sage.groups - sage: P = W.noncrossing_partition_lattice().without_bounds() # optional - sage.groups - sage: P.magnitude() # optional - sage.groups sage.libs.flint sage.modules + sage: W = SymmetricGroup(4) + sage: P = W.noncrossing_partition_lattice().without_bounds() + sage: P.magnitude() -4 sage: P = posets.TamariLattice(4).without_bounds() - sage: P.magnitude() # optional - sage.libs.flint sage.modules + sage: P.magnitude() 0 .. SEEALSO:: :meth:`order_complex` TESTS:: + sage: # needs sage.groups sage.libs.flint sage: P1 = posets.RandomPoset(20, 0.05) sage: P2 = posets.RandomPoset(20, 0.05) - sage: m1 = P1.magnitude() # optional - sage.libs.flint sage.modules - sage: m2 = P2.magnitude() # optional - sage.libs.flint sage.modules + sage: m1 = P1.magnitude() + sage: m2 = P2.magnitude() sage: U = P1.disjoint_union(P2) sage: P = P1.product(P2) - sage: U.magnitude() == m1 + m2 # optional - sage.libs.flint sage.modules + sage: U.magnitude() == m1 + m2 True - sage: P.magnitude() == m1*m2 # optional - sage.libs.flint sage.modules + sage: P.magnitude() == m1*m2 True - sage: Poset({}).magnitude() # optional - sage.libs.flint sage.modules + sage: Poset({}).magnitude() 0 - sage: Poset({1:[]}).magnitude() # optional - sage.libs.flint sage.modules + sage: Poset({1:[]}).magnitude() 1 """ H = self._hasse_diagram @@ -3865,10 +3879,10 @@ def is_jump_critical(self, certificate=False): sage: P.is_jump_critical() True - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.is_jump_critical() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.is_jump_critical() False - sage: P.is_jump_critical(certificate=True) # optional - sage.modules + sage: P.is_jump_critical(certificate=True) (False, 3) .. SEEALSO:: :meth:`jump_number` @@ -4027,8 +4041,8 @@ def is_graded(self) -> bool: EXAMPLES:: - sage: P = posets.PentagonPoset() # Not even ranked # optional - sage.modules - sage: P.is_graded() # optional - sage.modules + sage: P = posets.PentagonPoset() # Not even ranked + sage: P.is_graded() False sage: P = Poset({1:[2, 3], 3:[4]}) # Ranked, but not graded @@ -4217,20 +4231,20 @@ def moebius_function_matrix(self, ring=ZZ, sparse=False): sage: x,y = (P.linear_extension()[0],P.linear_extension()[1]) sage: P.moebius_function(x,y) -1 - sage: M = P.moebius_function_matrix(); M # optional - sage.libs.flint sage.modules + sage: M = P.moebius_function_matrix(); M # needs sage.libs.flint [ 1 -1 -1 -1 2] [ 0 1 0 0 -1] [ 0 0 1 0 -1] [ 0 0 0 1 -1] [ 0 0 0 0 1] - sage: M[0,4] # optional - sage.libs.flint sage.modules + sage: M[0,4] # needs sage.libs.flint 2 - sage: M[0,1] # optional - sage.libs.flint sage.modules + sage: M[0,1] # needs sage.libs.flint -1 We now demonstrate the usage of the optional parameters:: - sage: P.moebius_function_matrix(ring=QQ, sparse=False).parent() # optional - sage.libs.flint sage.modules + sage: P.moebius_function_matrix(ring=QQ, sparse=False).parent() # needs sage.libs.flint Full MatrixSpace of 5 by 5 dense matrices over Rational Field """ M = self._hasse_diagram.moebius_function_matrix() @@ -4255,7 +4269,7 @@ def lequal_matrix(self, ring=ZZ, sparse=False): EXAMPLES:: sage: P = Poset([[1,3,2],[4],[4,5,6],[6],[7],[7],[7],[]], facade=False) - sage: LEQM = P.lequal_matrix(); LEQM # optional - sage.modules + sage: LEQM = P.lequal_matrix(); LEQM [1 1 1 1 1 1 1 1] [0 1 0 1 0 0 0 1] [0 0 1 1 1 0 1 1] @@ -4264,18 +4278,18 @@ def lequal_matrix(self, ring=ZZ, sparse=False): [0 0 0 0 0 1 1 1] [0 0 0 0 0 0 1 1] [0 0 0 0 0 0 0 1] - sage: LEQM[1,3] # optional - sage.modules + sage: LEQM[1,3] 1 sage: P.linear_extension()[1] < P.linear_extension()[3] True - sage: LEQM[2,5] # optional - sage.modules + sage: LEQM[2,5] 0 sage: P.linear_extension()[2] < P.linear_extension()[5] False We now demonstrate the usage of the optional parameters:: - sage: P.lequal_matrix(ring=QQ, sparse=False).parent() # optional - sage.libs.flint sage.modules + sage: P.lequal_matrix(ring=QQ, sparse=False).parent() # needs sage.libs.flint Full MatrixSpace of 8 by 8 dense matrices over Rational Field """ M = self._hasse_diagram.lequal_matrix(boolean=False) @@ -4301,7 +4315,7 @@ def coxeter_transformation(self): EXAMPLES:: - sage: posets.PentagonPoset().coxeter_transformation() # optional - sage.modules + sage: posets.PentagonPoset().coxeter_transformation() [ 0 0 0 0 -1] [ 0 0 0 1 -1] [ 0 1 0 0 -1] @@ -4314,8 +4328,8 @@ def coxeter_transformation(self): TESTS:: - sage: M = posets.PentagonPoset().coxeter_transformation() # optional - sage.modules - sage: M ** 8 == 1 # optional - sage.modules + sage: M = posets.PentagonPoset().coxeter_transformation() + sage: M ** 8 == 1 True """ return self._hasse_diagram.coxeter_transformation() @@ -4334,12 +4348,12 @@ def coxeter_polynomial(self): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.coxeter_polynomial() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.coxeter_polynomial() x^5 + x^4 + x + 1 - sage: p = posets.SymmetricGroupWeakOrderPoset(3) # optional - sage.groups - sage: p.coxeter_polynomial() # optional - sage.groups sage.modules + sage: p = posets.SymmetricGroupWeakOrderPoset(3) # needs sage.groups + sage: p.coxeter_polynomial() # needs sage.groups x^6 + x^5 - x^3 + x + 1 .. SEEALSO:: @@ -4374,28 +4388,28 @@ def coxeter_smith_form(self, algorithm='singular'): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.coxeter_smith_form() # optional - sage.modules sage.libs.singular + sage: P = posets.PentagonPoset() + sage: P.coxeter_smith_form() # needs sage.libs.singular [1, 1, 1, 1, x^5 + x^4 + x + 1] sage: P = posets.DiamondPoset(7) - sage: prod(P.coxeter_smith_form()) == P.coxeter_polynomial() # optional - sage.modules sage.libs.singular + sage: prod(P.coxeter_smith_form()) == P.coxeter_polynomial() # needs sage.libs.singular True TESTS:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.coxeter_smith_form(algorithm='sage') # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.coxeter_smith_form(algorithm='sage') [1, 1, 1, 1, x^5 + x^4 + x + 1] - sage: P.coxeter_smith_form(algorithm='gap') # optional - sage.libs.gap sage.modules + sage: P.coxeter_smith_form(algorithm='gap') # needs sage.libs.gap [1, 1, 1, 1, x^5 + x^4 + x + 1] - sage: P.coxeter_smith_form(algorithm='pari') # optional - sage.libs.pari sage.modules + sage: P.coxeter_smith_form(algorithm='pari') # needs sage.libs.pari [1, 1, 1, 1, x^5 + x^4 + x + 1] - sage: P.coxeter_smith_form(algorithm='fricas') # optional - fricas # optional - sage.modules + sage: P.coxeter_smith_form(algorithm='fricas') # optional - fricas [1, 1, 1, 1, x^5 + x^4 + x + 1] - sage: P.coxeter_smith_form(algorithm='maple') # optional - maple # optional - sage.modules + sage: P.coxeter_smith_form(algorithm='maple') # optional - maple [1, 1, 1, 1, x^5 + x^4 + x + 1] - sage: P.coxeter_smith_form(algorithm='magma') # optional - magma # optional - sage.modules + sage: P.coxeter_smith_form(algorithm='magma') # optional - magma [1, 1, 1, 1, x^5 + x^4 + x + 1] .. SEEALSO:: @@ -4471,15 +4485,15 @@ def is_meet_semilattice(self, certificate=False): EXAMPLES:: sage: P = Poset({1:[2, 3, 4], 2:[5, 6], 3:[6], 4:[6, 7]}) - sage: P.is_meet_semilattice() # optional - sage.modules + sage: P.is_meet_semilattice() True sage: Q = P.dual() - sage: Q.is_meet_semilattice() # optional - sage.modules + sage: Q.is_meet_semilattice() False - sage: V = posets.IntegerPartitions(5) # optional - sage.combinat - sage: V.is_meet_semilattice(certificate=True) # optional - sage.combinat sage.modules + sage: V = posets.IntegerPartitions(5) # needs sage.combinat + sage: V.is_meet_semilattice(certificate=True) # needs sage.combinat (False, ((2, 2, 1), (3, 1, 1))) .. SEEALSO:: @@ -4489,13 +4503,13 @@ def is_meet_semilattice(self, certificate=False): TESTS:: - sage: Poset().is_meet_semilattice() # Test empty lattice # optional - sage.modules + sage: Poset().is_meet_semilattice() # Test empty lattice True - sage: len([P for P in Posets(4) if P.is_meet_semilattice()]) # optional - sage.modules + sage: len([P for P in Posets(4) if P.is_meet_semilattice()]) 5 sage: P = Poset({1: [2], 3: []}) - sage: P.is_meet_semilattice(certificate=True) # optional - sage.modules + sage: P.is_meet_semilattice(certificate=True) (False, (3, 1)) """ from sage.combinat.posets.hasse_diagram import LatticeError @@ -4544,13 +4558,13 @@ def is_join_semilattice(self, certificate=False): EXAMPLES:: sage: P = Poset([[1,3,2], [4], [4,5,6], [6], [7], [7], [7], []]) - sage: P.is_join_semilattice() # optional - sage.modules + sage: P.is_join_semilattice() True sage: P = Poset({1:[3, 4], 2:[3, 4], 3:[5], 4:[5]}) - sage: P.is_join_semilattice() # optional - sage.modules + sage: P.is_join_semilattice() False - sage: P.is_join_semilattice(certificate=True) # optional - sage.modules + sage: P.is_join_semilattice(certificate=True) (False, (2, 1)) .. SEEALSO:: @@ -4560,13 +4574,13 @@ def is_join_semilattice(self, certificate=False): TESTS:: - sage: Poset().is_join_semilattice() # Test empty lattice # optional - sage.modules + sage: Poset().is_join_semilattice() # Test empty lattice True - sage: len([P for P in Posets(4) if P.is_join_semilattice()]) # optional - sage.modules + sage: len([P for P in Posets(4) if P.is_join_semilattice()]) 5 sage: X = Poset({1: [3], 2: [3], 3: [4, 5]}) - sage: X.is_join_semilattice(certificate=True) # optional - sage.modules + sage: X.is_join_semilattice(certificate=True) (False, (5, 4)) """ from sage.combinat.posets.hasse_diagram import LatticeError @@ -4634,8 +4648,8 @@ def isomorphic_subposets_iterator(self, other): EXAMPLES:: sage: D = Poset({1:[2,3], 2:[4], 3:[4]}) - sage: N5 = posets.PentagonPoset() # optional - sage.modules - sage: for P in N5.isomorphic_subposets_iterator(D): # optional - sage.modules + sage: N5 = posets.PentagonPoset() + sage: for P in N5.isomorphic_subposets_iterator(D): ....: print(P.cover_relations()) [[0, 1], [0, 2], [1, 4], [2, 4]] [[0, 1], [0, 3], [1, 4], [3, 4]] @@ -4674,15 +4688,15 @@ def isomorphic_subposets(self, other): sage: C2 = Poset({0:[1]}) sage: C3 = Poset({'a':['b'], 'b':['c']}) - sage: L = sorted(x.cover_relations() for x in C3.isomorphic_subposets(C2)) # optional - sage.modules - sage: for x in L: print(x) # optional - sage.modules + sage: L = sorted(x.cover_relations() for x in C3.isomorphic_subposets(C2)) + sage: for x in L: print(x) [['a', 'b']] [['a', 'c']] [['b', 'c']] sage: D = Poset({1:[2,3], 2:[4], 3:[4]}) - sage: N5 = posets.PentagonPoset() # optional - sage.modules - sage: len(N5.isomorphic_subposets(D)) # optional - sage.modules + sage: N5 = posets.PentagonPoset() + sage: len(N5.isomorphic_subposets(D)) 2 .. NOTE:: @@ -4719,19 +4733,19 @@ def antichains(self, element_constructor=type([])): EXAMPLES:: - sage: A = posets.PentagonPoset().antichains(); A # optional - sage.modules + sage: A = posets.PentagonPoset().antichains(); A Set of antichains of Finite lattice containing 5 elements - sage: list(A) # optional - sage.modules + sage: list(A) [[], [0], [1], [1, 2], [1, 3], [2], [3], [4]] - sage: A.cardinality() # optional - sage.modules + sage: A.cardinality() 8 - sage: A[3] # optional - sage.modules + sage: A[3] [1, 2] To get the antichains as, say, sets, one may use the ``element_constructor`` option:: - sage: list(posets.ChainPoset(3).antichains(element_constructor=set)) # optional - sage.modules + sage: list(posets.ChainPoset(3).antichains(element_constructor=set)) [set(), {0}, {1}, {2}] To get the antichains of a given size one can currently use:: @@ -4774,9 +4788,9 @@ def antichains_iterator(self): EXAMPLES:: - sage: it = posets.PentagonPoset().antichains_iterator(); it # optional - sage.modules + sage: it = posets.PentagonPoset().antichains_iterator(); it - sage: next(it), next(it) # optional - sage.modules + sage: next(it), next(it) ([], [4]) .. SEEALSO:: :meth:`antichains` @@ -4928,9 +4942,9 @@ def chains(self, element_constructor=type([]), exclude=None): EXAMPLES:: - sage: C = posets.PentagonPoset().chains(); C # optional - sage.modules + sage: C = posets.PentagonPoset().chains(); C Set of chains of Finite lattice containing 5 elements - sage: list(C) # optional - sage.modules + sage: list(C) [[], [0], [0, 1], [0, 1, 4], [0, 2], [0, 2, 3], [0, 2, 3, 4], [0, 2, 4], [0, 3], [0, 3, 4], [0, 4], [1], [1, 4], [2], [2, 3], [2, 3, 4], [2, 4], [3], [3, 4], [4]] @@ -4943,12 +4957,12 @@ def chains(self, element_constructor=type([]), exclude=None): To get the chains of a given size one can currently use:: - sage: list(C.elements_of_depth_iterator(2)) # optional - sage.modules + sage: list(C.elements_of_depth_iterator(2)) [[0, 1], [0, 2], [0, 3], [0, 4], [1, 4], [2, 3], [2, 4], [3, 4]] Eventually the following syntax will be accepted:: - sage: C.subset(size = 2) # todo: not implemented # optional - sage.modules + sage: C.subset(size = 2) # not implemented .. SEEALSO:: :meth:`maximal_chains`, :meth:`antichains` """ @@ -5112,23 +5126,23 @@ def product(self, other): sage: P = posets.ChainPoset(3) sage: Q = posets.ChainPoset(4) - sage: PQ = P.product(Q) ; PQ # optional - sage.modules + sage: PQ = P.product(Q) ; PQ Finite lattice containing 12 elements - sage: len(PQ.cover_relations()) # optional - sage.modules + sage: len(PQ.cover_relations()) 17 - sage: Q.product(P).is_isomorphic(PQ) # optional - sage.modules + sage: Q.product(P).is_isomorphic(PQ) True sage: P = posets.BooleanLattice(2) - sage: Q = P.product(P) # optional - sage.modules - sage: Q.is_isomorphic(posets.BooleanLattice(4)) # optional - sage.modules + sage: Q = P.product(P) + sage: Q.is_isomorphic(posets.BooleanLattice(4)) True One can also simply use `*`:: sage: P = posets.ChainPoset(2) sage: Q = posets.ChainPoset(3) - sage: P*Q # optional - sage.modules + sage: P*Q Finite lattice containing 6 elements .. SEEALSO:: @@ -5137,15 +5151,15 @@ def product(self, other): TESTS:: - sage: Poset({0: [1]}).product(Poset()) # Product with empty poset # optional - sage.modules + sage: Poset({0: [1]}).product(Poset()) # Product with empty poset Finite poset containing 0 elements - sage: Poset().product(Poset()) # Product of two empty poset # optional - sage.modules + sage: Poset().product(Poset()) # Product of two empty poset Finite poset containing 0 elements We check that :trac:`19113` is fixed:: - sage: L = LatticePoset({1: []}) # optional - sage.modules - sage: type(L) == type(L.product(L)) # optional - sage.modules + sage: L = LatticePoset({1: []}) + sage: type(L) == type(L.product(L)) True """ from sage.combinat.posets.lattices import LatticePoset, \ @@ -5235,9 +5249,9 @@ def factor(self): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: Q = P*P # optional - sage.modules - sage: Q.factor() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: Q = P*P + sage: Q.factor() [Finite poset containing 5 elements, Finite poset containing 5 elements] @@ -5245,12 +5259,12 @@ def factor(self): sage: P2 = posets.ChainPoset(7) sage: P1.factor() [Finite lattice containing 3 elements] - sage: (P1 * P2).factor() # optional - sage.modules + sage: (P1 * P2).factor() [Finite poset containing 7 elements, Finite poset containing 3 elements] sage: P = posets.TamariLattice(4) - sage: (P*P).factor() # optional - sage.modules + sage: (P*P).factor() [Finite poset containing 14 elements, Finite poset containing 14 elements] @@ -5309,9 +5323,9 @@ def edge_color(va, vb): for i0, i1 in Subsets(factors_range, 2): for x in prod_dg: - neigh0 = [y for y in prod_dg.neighbors(x) + neigh0 = [y for y in prod_dg.neighbor_iterator(x) if edge_color(x, y) == i0] - neigh1 = [z for z in prod_dg.neighbors(x) + neigh1 = [z for z in prod_dg.neighbor_iterator(x) if edge_color(x, z) == i1] for x0, x1 in cartesian_product_iterator([neigh0, neigh1]): x2 = list(x0) @@ -5372,9 +5386,9 @@ def disjoint_union(self, other, labels='pairs'): sage: P.cover_relations() [[2, 3], [0, 1]] - sage: N5 = posets.PentagonPoset(); N5 # optional - sage.modules + sage: N5 = posets.PentagonPoset(); N5 Finite lattice containing 5 elements - sage: N5.disjoint_union(N5) # Union of lattices is not a lattice # optional - sage.modules + sage: N5.disjoint_union(N5) # Union of lattices is not a lattice Finite poset containing 10 elements We show how to get literally direct sum with elements untouched:: @@ -5387,9 +5401,9 @@ def disjoint_union(self, other, labels='pairs'): TESTS:: - sage: N5 = posets.PentagonPoset() # optional - sage.modules + sage: N5 = posets.PentagonPoset() sage: P0 = Poset() - sage: N5.disjoint_union(P0).is_isomorphic(N5) # optional - sage.modules + sage: N5.disjoint_union(P0).is_isomorphic(N5) True sage: P0.disjoint_union(P0) Finite poset containing 0 elements @@ -5451,11 +5465,11 @@ def ordinal_product(self, other, labels='pairs'): ... ValueError: labels must be either 'pairs' or 'integers' - sage: N5 = posets.PentagonPoset() # optional - sage.modules + sage: N5 = posets.PentagonPoset() sage: P0 = Poset() - sage: N5.ordinal_product(P0) == P0 # optional - sage.modules + sage: N5.ordinal_product(P0) == P0 True - sage: P0.ordinal_product(N5) == P0 # optional - sage.modules + sage: P0.ordinal_product(N5) == P0 True sage: P0.ordinal_product(P0) == P0 True @@ -5469,7 +5483,7 @@ def ordinal_product(self, other, labels='pairs'): sage: C3 = posets.ChainPoset(3) sage: C4 = posets.ChainPoset(4) sage: C12 = posets.ChainPoset(12) - sage: C3.ordinal_product(C4).is_isomorphic(C12) # optional - sage.modules + sage: C3.ordinal_product(C4).is_isomorphic(C12) True """ from sage.combinat.posets.lattices import LatticePoset, \ @@ -5546,15 +5560,15 @@ def ordinal_sum(self, other, labels='pairs'): sage: P = Poset({1:[2]}); P Finite poset containing 2 elements - sage: JL = JoinSemilattice({1:[2]}); JL # optional - sage.modules + sage: JL = JoinSemilattice({1:[2]}); JL Finite join-semilattice containing 2 elements - sage: L = LatticePoset({1:[2]}); L # optional - sage.modules + sage: L = LatticePoset({1:[2]}); L Finite lattice containing 2 elements - sage: P.ordinal_sum(L) # optional - sage.modules + sage: P.ordinal_sum(L) Finite poset containing 4 elements - sage: L.ordinal_sum(JL) # optional - sage.modules + sage: L.ordinal_sum(JL) Finite join-semilattice containing 4 elements - sage: L.ordinal_sum(L) # optional - sage.modules + sage: L.ordinal_sum(L) Finite lattice containing 4 elements .. SEEALSO:: @@ -5564,11 +5578,11 @@ def ordinal_sum(self, other, labels='pairs'): TESTS:: - sage: N5 = posets.PentagonPoset() # optional - sage.modules + sage: N5 = posets.PentagonPoset() sage: P0 = LatticePoset({}) - sage: N5.ordinal_sum(P0).is_isomorphic(N5) # optional - sage.modules + sage: N5.ordinal_sum(P0).is_isomorphic(N5) True - sage: P0.ordinal_sum(P0) # optional - sage.modules + sage: P0.ordinal_sum(P0) Finite lattice containing 0 elements """ from sage.combinat.posets.lattices import LatticePoset, \ @@ -5635,7 +5649,7 @@ def star_product(self, other, labels='pairs'): sage: B3 = posets.BooleanLattice(3) sage: P = B2.star_product(B3); P Finite poset containing 10 elements - sage: P.is_eulerian() # optional - sage.libs.flint sage.modules + sage: P.is_eulerian() # needs sage.libs.flint True We can get elements as pairs or as integers:: @@ -5726,11 +5740,11 @@ def lexicographic_sum(self, P): EXAMPLES:: sage: N = Poset({1: [3, 4], 2: [4]}) - sage: P = {1: posets.PentagonPoset(), 2: N, # optional - sage.modules + sage: P = {1: posets.PentagonPoset(), 2: N, ....: 3: posets.ChainPoset(3), 4: posets.AntichainPoset(4)} - sage: NP = N.lexicographic_sum(P); NP # optional - sage.modules + sage: NP = N.lexicographic_sum(P); NP Finite poset containing 16 elements - sage: sorted(NP.minimal_elements()) # optional - sage.modules + sage: sorted(NP.minimal_elements()) [(1, 0), (2, 1), (2, 2)] TESTS:: @@ -5813,10 +5827,10 @@ def dual(self): join-semilattice and vice versa. Also the dual of a (non-)facade poset is again (non-)facade:: - sage: V = MeetSemilattice({1: [2, 3]}, facade=False) # optional - sage.modules - sage: A = V.dual(); A # optional - sage.modules + sage: V = MeetSemilattice({1: [2, 3]}, facade=False) + sage: A = V.dual(); A Finite join-semilattice containing 3 elements - sage: A(2) < A(1) # optional - sage.modules + sage: A(2) < A(1) True .. SEEALSO:: :meth:`~sage.categories.finite_posets.FinitePosets.ParentMethods.is_self_dual` @@ -5869,12 +5883,12 @@ def with_bounds(self, labels=('bottom', 'top')): sage: Y.cover_relations() [[-1, 0], [0, 1], [0, 2]] - sage: P = posets.PentagonPoset() # A lattice # optional - sage.modules - sage: P.with_bounds() # optional - sage.modules + sage: P = posets.PentagonPoset() # A lattice + sage: P.with_bounds() Finite lattice containing 7 elements - sage: P = posets.PentagonPoset(facade=False) # optional - sage.modules - sage: P.with_bounds() # optional - sage.modules + sage: P = posets.PentagonPoset(facade=False) + sage: P.with_bounds() Finite lattice containing 7 elements .. SEEALSO:: @@ -5887,58 +5901,58 @@ def with_bounds(self, labels=('bottom', 'top')): sage: P.cover_relations() [['bottom', 'top']] - sage: L = LatticePoset({}).with_bounds(); L # optional - sage.modules + sage: L = LatticePoset({}).with_bounds(); L Finite lattice containing 2 elements - sage: L.meet_irreducibles() # Issue 21543 # optional - sage.modules + sage: L.meet_irreducibles() # Issue 21543 ['bottom'] sage: Poset().with_bounds((None, 1)) Finite poset containing 1 elements - sage: LatticePoset().with_bounds((None, 1)) # optional - sage.modules + sage: LatticePoset().with_bounds((None, 1)) Finite lattice containing 1 elements - sage: MeetSemilattice().with_bounds((None, 1)) # optional - sage.modules + sage: MeetSemilattice().with_bounds((None, 1)) Finite lattice containing 1 elements - sage: JoinSemilattice().with_bounds((None, 1)) # optional - sage.modules + sage: JoinSemilattice().with_bounds((None, 1)) Finite join-semilattice containing 1 elements sage: Poset().with_bounds((1, None)) Finite poset containing 1 elements - sage: LatticePoset().with_bounds((1, None)) # optional - sage.modules + sage: LatticePoset().with_bounds((1, None)) Finite lattice containing 1 elements - sage: MeetSemilattice().with_bounds((1, None)) # optional - sage.modules + sage: MeetSemilattice().with_bounds((1, None)) Finite meet-semilattice containing 1 elements - sage: JoinSemilattice().with_bounds((1, None)) # optional - sage.modules + sage: JoinSemilattice().with_bounds((1, None)) Finite lattice containing 1 elements sage: P = Poset({0: []}) - sage: L = LatticePoset({0: []}) # optional - sage.modules - sage: ML = MeetSemilattice({0: []}) # optional - sage.modules - sage: JL = JoinSemilattice({0: []}) # optional - sage.modules + sage: L = LatticePoset({0: []}) + sage: ML = MeetSemilattice({0: []}) + sage: JL = JoinSemilattice({0: []}) sage: P.with_bounds((None, None)) Finite poset containing 1 elements - sage: L.with_bounds((None, None)) # optional - sage.modules + sage: L.with_bounds((None, None)) Finite lattice containing 1 elements - sage: ML.with_bounds((None, None)) # optional - sage.modules + sage: ML.with_bounds((None, None)) Finite meet-semilattice containing 1 elements - sage: JL.with_bounds((None, None)) # optional - sage.modules + sage: JL.with_bounds((None, None)) Finite join-semilattice containing 1 elements sage: P.with_bounds((1, None)) Finite poset containing 2 elements - sage: L.with_bounds((1, None)) # optional - sage.modules + sage: L.with_bounds((1, None)) Finite lattice containing 2 elements - sage: ML.with_bounds((1, None)) # optional - sage.modules + sage: ML.with_bounds((1, None)) Finite meet-semilattice containing 2 elements - sage: JL.with_bounds((1, None)) # optional - sage.modules + sage: JL.with_bounds((1, None)) Finite lattice containing 2 elements sage: P.with_bounds((None, 1)) Finite poset containing 2 elements - sage: L.with_bounds((None, 1)) # optional - sage.modules + sage: L.with_bounds((None, 1)) Finite lattice containing 2 elements - sage: ML.with_bounds((None, 1)) # optional - sage.modules + sage: ML.with_bounds((None, 1)) Finite lattice containing 2 elements - sage: JL.with_bounds((None, 1)) # optional - sage.modules + sage: JL.with_bounds((None, 1)) Finite join-semilattice containing 2 elements - sage: posets.PentagonPoset().with_bounds(labels=(4, 5)) # optional - sage.modules + sage: posets.PentagonPoset().with_bounds(labels=(4, 5)) Traceback (most recent call last): ... ValueError: the poset already has element 4 @@ -5993,14 +6007,14 @@ def without_bounds(self): This is useful as an input for the method :meth:`order_complex`. If there is either no top or no bottom element, this - raises a ``TypeError``. + raises a :class:`TypeError`. EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: Q = P.without_bounds(); Q # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: Q = P.without_bounds(); Q Finite poset containing 3 elements - sage: Q.cover_relations() # optional - sage.modules + sage: Q.cover_relations() [[2, 3]] sage: P = posets.DiamondPoset(5) @@ -6092,27 +6106,27 @@ def relabel(self, relabeling=None): Relabeling using a list:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: list(P) # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: list(P) [0, 1, 2, 3, 4] - sage: P.cover_relations() # optional - sage.modules + sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] - sage: Q = P.relabel(list('abcde')) # optional - sage.modules - sage: Q.cover_relations() # optional - sage.modules + sage: Q = P.relabel(list('abcde')) + sage: Q.cover_relations() [['a', 'b'], ['a', 'c'], ['b', 'e'], ['c', 'd'], ['d', 'e']] Default behaviour is increasing relabeling:: sage: a2 = posets.ChainPoset(2) - sage: P = a2 * a2 # optional - sage.modules - sage: Q = P.relabel() # optional - sage.modules - sage: Q.cover_relations() # optional - sage.modules + sage: P = a2 * a2 + sage: Q = P.relabel() + sage: Q.cover_relations() [[0, 1], [0, 2], [1, 3], [2, 3]] Relabeling a (semi)lattice gives a (semi)lattice:: - sage: P = JoinSemilattice({0: [1]}) # optional - sage.modules - sage: P.relabel(lambda n: n+1) # optional - sage.modules + sage: P = JoinSemilattice({0: [1]}) + sage: P.relabel(lambda n: n+1) Finite join-semilattice containing 2 elements .. NOTE:: @@ -6213,10 +6227,10 @@ def canonical_label(self, algorithm=None): sage: D = DiGraph({'a':['b','c']}) sage: P = Poset(D) - sage: ML = MeetSemilattice(D) # optional - sage.modules + sage: ML = MeetSemilattice(D) sage: P.canonical_label() Finite poset containing 3 elements - sage: ML.canonical_label() # optional - sage.modules + sage: ML.canonical_label() Finite meet-semilattice containing 3 elements .. SEEALSO:: @@ -6293,8 +6307,8 @@ def with_linear_extension(self, linear_extension): (Semi)lattice remains (semi)lattice with new linear extension:: - sage: L = LatticePoset(P) # optional - sage.modules - sage: Q = L.with_linear_extension([1,3,2,6,4,12]); Q # optional - sage.modules + sage: L = LatticePoset(P) + sage: Q = L.with_linear_extension([1,3,2,6,4,12]); Q Finite lattice containing 6 elements with distinguished linear extension .. NOTE:: @@ -6354,9 +6368,9 @@ def subposet(self, elements): A subposet of a non-facade poset is again a non-facade poset:: - sage: P = posets.PentagonPoset(facade=False) # optional - sage.modules - sage: Q = P.subposet([0, 1, 2, 4]) # optional - sage.modules - sage: Q(1) < Q(2) # optional - sage.modules + sage: P = posets.PentagonPoset(facade=False) + sage: Q = P.subposet([0, 1, 2, 4]) + sage: Q(1) < Q(2) False TESTS:: @@ -6413,8 +6427,8 @@ def random_subposet(self, p): TESTS:: - sage: P = posets.IntegerPartitions(4) # optional - sage.combinat - sage: P.random_subposet(1) == P # optional - sage.combinat + sage: P = posets.IntegerPartitions(4) # needs sage.combinat + sage: P.random_subposet(1) == P # needs sage.combinat True """ from sage.misc.randstate import current_randstate @@ -6709,17 +6723,19 @@ def order_ideal_plot(self, elements): EXAMPLES:: + sage: # needs sage.plot sage: P = Poset((divisors(1000), attrcall("divides"))) - sage: P.order_ideal_plot([20, 25]) # optional - sage.plot + sage: P.order_ideal_plot([20, 25]) Graphics object consisting of 41 graphics primitives TESTS:: + sage: # needs sage.plot sage: P = Poset() # Test empty poset - sage: P.order_ideal_plot([]) # optional - sage.plot + sage: P.order_ideal_plot([]) Graphics object consisting of 0 graphics primitives sage: C = posets.ChainPoset(5) - sage: C.order_ideal_plot([]) # optional - sage.plot + sage: C.order_ideal_plot([]) Graphics object consisting of 10 graphics primitives """ order_ideal = self.order_ideal(elements) @@ -6905,25 +6921,25 @@ def linear_extensions_graph(self): EXAMPLES:: sage: N = Poset({1: [3, 4], 2: [4]}) - sage: G = N.linear_extensions_graph(); G # optional - sage.modules + sage: G = N.linear_extensions_graph(); G Graph on 5 vertices - sage: G.neighbors(N.linear_extension([1,2,3,4])) # optional - sage.modules + sage: G.neighbors(N.linear_extension([1,2,3,4])) [[2, 1, 3, 4], [1, 3, 2, 4], [1, 2, 4, 3]] sage: chevron = Poset({1: [2, 6], 2: [3], 4: [3, 5], 6: [5]}) - sage: G = chevron.linear_extensions_graph(); G # optional - sage.modules + sage: G = chevron.linear_extensions_graph(); G Graph on 22 vertices - sage: G.size() # optional - sage.modules + sage: G.size() 36 TESTS:: - sage: Poset().linear_extensions_graph() # optional - sage.modules + sage: Poset().linear_extensions_graph() Graph on 1 vertex sage: A4 = posets.AntichainPoset(4) - sage: G = A4.linear_extensions_graph() # optional - sage.modules - sage: G.is_regular() # optional - sage.modules + sage: G = A4.linear_extensions_graph() + sage: G.is_regular() True """ from sage.graphs.graph import Graph @@ -6952,7 +6968,7 @@ def maximal_antichains(self): sage: [sorted(anti) for anti in P.maximal_antichains()] [['a'], ['b', 'c'], ['c', 'd', 'e']] - sage: posets.PentagonPoset().maximal_antichains() # optional - sage.modules + sage: posets.PentagonPoset().maximal_antichains() [[0], [1, 2], [1, 3], [4]] .. SEEALSO:: :meth:`antichains`, :meth:`maximal_chains` @@ -7087,10 +7103,10 @@ def order_complex(self, on_ints=False): Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6, 7) and 6 facets sage: S.f_vector() [1, 8, 19, 18, 6] - sage: S.homology() # S is contractible # optional - sage.modules + sage: S.homology() # S is contractible {0: 0, 1: 0, 2: 0, 3: 0} sage: Q = P.subposet([1,2,3,4,5,6]) - sage: Q.order_complex().homology() # a circle # optional - sage.modules + sage: Q.order_complex().homology() # a circle {0: 0, 1: Z} sage: P = Poset((divisors(15), attrcall("divides")), facade = True) @@ -7144,22 +7160,22 @@ def order_polytope(self): EXAMPLES:: sage: P = posets.AntichainPoset(3) - sage: Q = P.order_polytope(); Q # optional - sage.geometry.polyhedron + sage: Q = P.order_polytope(); Q # needs sage.geometry.polyhedron A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: Q = P.order_polytope(); Q # optional - sage.modules sage.geometry.polyhedron + sage: P = posets.PentagonPoset() + sage: Q = P.order_polytope(); Q # needs sage.geometry.polyhedron A 5-dimensional polyhedron in ZZ^5 defined as the convex hull of 8 vertices sage: P = Poset([[1,2,3],[[1,2],[1,3]]]) - sage: Q = P.order_polytope() # optional - sage.geometry.polyhedron - sage: Q.contains((1,0,0)) # optional - sage.geometry.polyhedron + sage: Q = P.order_polytope() # needs sage.geometry.polyhedron + sage: Q.contains((1,0,0)) # needs sage.geometry.polyhedron False - sage: Q.contains((0,1,1)) # optional - sage.geometry.polyhedron + sage: Q.contains((0,1,1)) # needs sage.geometry.polyhedron True """ from sage.geometry.polyhedron.constructor import Polyhedron ineqs = [[0] + [ZZ(j == v) - ZZ(j == u) for j in self] - for u, v, w in self.hasse_diagram().edges(sort=True)] + for u, v in self.hasse_diagram().edges(sort=False, labels=False)] for i in self.maximal_elements(): ineqs += [[1] + [-ZZ(j == i) for j in self]] for i in self.minimal_elements(): @@ -7190,10 +7206,10 @@ def chain_polytope(self): EXAMPLES:: sage: P = posets.AntichainPoset(3) - sage: Q = P.chain_polytope();Q # optional - sage.geometry.polyhedron + sage: Q = P.chain_polytope();Q # needs sage.geometry.polyhedron A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: Q = P.chain_polytope();Q # optional - sage.modules sage.geometry.polyhedron + sage: P = posets.PentagonPoset() + sage: Q = P.chain_polytope();Q # needs sage.geometry.polyhedron A 5-dimensional polyhedron in ZZ^5 defined as the convex hull of 8 vertices """ from sage.geometry.polyhedron.constructor import Polyhedron @@ -7234,8 +7250,8 @@ def zeta_polynomial(self): sage: posets.ChainPoset(3).zeta_polynomial() 1/2*q^2 + 1/2*q - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.zeta_polynomial() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.zeta_polynomial() 1/6*q^3 + q^2 - 1/6*q sage: P = posets.DiamondPoset(5) @@ -7286,13 +7302,13 @@ def M_triangle(self): EXAMPLES:: sage: P = posets.DiamondPoset(5) - sage: P.M_triangle() # optional - sage.combinat + sage: P.M_triangle() # needs sage.combinat M: x^2*y^2 - 3*x*y^2 + 3*x*y + 2*y^2 - 3*y + 1 TESTS:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.M_triangle() # optional - sage.combinat sage.modules + sage: P = posets.PentagonPoset() + sage: P.M_triangle() # needs sage.combinat Traceback (most recent call last): ... ValueError: the poset is not graded @@ -7398,8 +7414,8 @@ def h_polynomial(self): EXAMPLES:: - sage: P = posets.AntichainPoset(3).order_ideals_lattice() # optional - sage.modules - sage: P.h_polynomial() # optional - sage.modules + sage: P = posets.AntichainPoset(3).order_ideals_lattice() + sage: P.h_polynomial() q^3 + 4*q^2 + q sage: P = posets.DiamondPoset(5) sage: P.h_polynomial() @@ -7699,13 +7715,13 @@ def order_polynomial(self): EXAMPLES:: sage: P = posets.AntichainPoset(3) - sage: P.order_polynomial() # optional - sage.modules sage.rings.finite_rings + sage: P.order_polynomial() q^3 sage: P = posets.ChainPoset(3) - sage: f = P.order_polynomial(); f # optional - sage.modules sage.rings.finite_rings + sage: f = P.order_polynomial(); f 1/6*q^3 + 1/2*q^2 + 1/3*q - sage: [f(i) for i in range(4)] # optional - sage.modules sage.rings.finite_rings + sage: [f(i) for i in range(4)] [0, 1, 4, 10] .. SEEALSO:: :meth:`order_polytope` @@ -7731,8 +7747,8 @@ def degree_polynomial(self): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.degree_polynomial() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.degree_polynomial() x^2 + 3*x*y + y^2 sage: P = posets.BooleanLattice(4) @@ -7974,17 +7990,18 @@ def is_slender(self, certificate=False): sage: P.is_slender() False - sage: W = WeylGroup(['A', 2]) # optional - sage.groups - sage: G = W.bruhat_poset() # optional - sage.groups - sage: G.is_slender() # optional - sage.groups + sage: # needs sage.groups + sage: W = WeylGroup(['A', 2]) + sage: G = W.bruhat_poset() + sage: G.is_slender() True - sage: W = WeylGroup(['A', 3]) # optional - sage.groups - sage: G = W.bruhat_poset() # optional - sage.groups - sage: G.is_slender() # optional - sage.groups + sage: W = WeylGroup(['A', 3]) + sage: G = W.bruhat_poset() + sage: G.is_slender() True - sage: P = posets.IntegerPartitions(6) # optional - sage.combinat - sage: P.is_slender(certificate=True) # optional - sage.combinat + sage: P = posets.IntegerPartitions(6) # needs sage.combinat + sage: P.is_slender(certificate=True) # needs sage.combinat (False, ((6,), (3, 2, 1))) TESTS:: @@ -8028,7 +8045,7 @@ def is_sperner(self): EXAMPLES:: - sage: posets.SetPartitions(3).is_sperner() # optional - sage.combinat + sage: posets.SetPartitions(3).is_sperner() # needs sage.combinat True sage: P = Poset({0:[3,4,5],1:[5],2:[5]}) @@ -8037,7 +8054,7 @@ def is_sperner(self): TESTS:: - sage: posets.PentagonPoset().is_sperner() # optional - sage.modules + sage: posets.PentagonPoset().is_sperner() Traceback (most recent call last): ... ValueError: the poset is not ranked @@ -8084,33 +8101,33 @@ def is_eulerian(self, k=None, certificate=False): sage: P = Poset({0: [1, 2, 3], 1: [4, 5], 2: [4, 6], 3: [5, 6], ....: 4: [7, 8], 5: [7, 8], 6: [7, 8], 7: [9], 8: [9]}) - sage: P.is_eulerian() # optional - sage.modules sage.rings.finite_rings + sage: P.is_eulerian() True sage: P = Poset({0: [1, 2, 3], 1: [4, 5, 6], 2: [4, 6], 3: [5,6], ....: 4: [7], 5:[7], 6:[7]}) - sage: P.is_eulerian() # optional - sage.modules sage.rings.finite_rings + sage: P.is_eulerian() False Canonical examples of Eulerian posets are the face lattices of convex polytopes:: - sage: P = polytopes.cube().face_lattice() # optional - sage.geometry.polyhedron - sage: P.is_eulerian() # optional - sage.geometry.polyhedron sage.rings.finite_rings + sage: P = polytopes.cube().face_lattice() # needs sage.geometry.polyhedron + sage: P.is_eulerian() # needs sage.geometry.polyhedron True A poset that is 3- but not 4-eulerian:: sage: P = Poset(DiGraph('MWW@_?W?@_?W??@??O@_?W?@_?W?@??O??')); P Finite poset containing 14 elements - sage: P.is_eulerian(k=3) # optional - sage.modules + sage: P.is_eulerian(k=3) True - sage: P.is_eulerian(k=4) # optional - sage.modules + sage: P.is_eulerian(k=4) False Getting an interval that is not Eulerian:: sage: P = posets.DivisorLattice(12) - sage: P.is_eulerian(certificate=True) # optional - sage.modules + sage: P.is_eulerian(certificate=True) (False, (1, 4)) TESTS:: @@ -8120,15 +8137,15 @@ def is_eulerian(self, k=None, certificate=False): ... ValueError: the poset is not bounded - sage: Poset({1: []}).is_eulerian() # optional - sage.modules + sage: Poset({1: []}).is_eulerian() True - sage: posets.PentagonPoset().is_eulerian() # optional - sage.modules + sage: posets.PentagonPoset().is_eulerian() Traceback (most recent call last): ... ValueError: the poset is not graded - sage: posets.BooleanLattice(3).is_eulerian(k=123, certificate=True) # optional - sage.modules + sage: posets.BooleanLattice(3).is_eulerian(k=123, certificate=True) (True, None) """ if k is not None: @@ -8346,14 +8363,13 @@ def frank_network(self): - Darij Grinberg (2013-05-09) """ - from sage.graphs.digraph import DiGraph P0 = [(0, i) for i in self] pdict = {(-1, 0): P0, (2, 0): []} for i in self: pdict[(0, i)] = [(1, j) for j in self if self.ge(i, j)] pdict[(1, i)] = [(2, 0)] G = DiGraph(pdict, format="dict_of_lists") - a = {(u, v): 0 for (u, v, l) in G.edge_iterator()} + a = {e: 0 for e in G.edge_iterator(labels=False)} for i in self: a[((0, i), (1, i))] = 1 return (G, a) @@ -8374,18 +8390,19 @@ def greene_shape(self): EXAMPLES:: + sage: # needs sage.combinat sage: P = Poset([[3,2,1], [[3,1],[2,1]]]) - sage: P.greene_shape() # optional - sage.combinat + sage: P.greene_shape() [2, 1] sage: P = Poset([[1,2,3,4], [[1,4],[2,4],[4,3]]]) - sage: P.greene_shape() # optional - sage.combinat + sage: P.greene_shape() [3, 1] sage: P = Poset([[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22], ....: [[1,4],[2,4],[4,3]]]) - sage: P.greene_shape() # optional - sage.combinat + sage: P.greene_shape() [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] sage: P = Poset([[],[]]) - sage: P.greene_shape() # optional - sage.combinat + sage: P.greene_shape() [] AUTHOR: @@ -8393,15 +8410,15 @@ def greene_shape(self): - Darij Grinberg (2013-05-09) """ from sage.combinat.partition import Partition - (G, a) = self.frank_network() + G, a = self.frank_network() n = len(self) chron = _ford_fulkerson_chronicle(G, (-1, 0), (2, 0), a) size = 0 ps = [] part = 0 - (pold, vold) = (0, 0) + pold, vold = (0, 0) while size != n: - (p, v) = next(chron) + p, v = next(chron) if v > vold: size += p if part > 0: @@ -8468,41 +8485,41 @@ def p_partition_enumerator(self, tup, R, weights=None, check=False): EXAMPLES:: sage: P = Poset([[1,2,3,4],[[1,4],[2,4],[4,3]]]) - sage: FP = P.p_partition_enumerator((3,1,2,4), QQ, check=True); FP # optional - sage.combinat + sage: FP = P.p_partition_enumerator((3,1,2,4), QQ, check=True); FP # needs sage.combinat 2*M[1, 1, 1, 1] + 2*M[1, 2, 1] + M[2, 1, 1] + M[3, 1] - sage: expansion = FP.expand(5) # optional - sage.combinat - sage: xs = expansion.parent().gens() # optional - sage.combinat - sage: expansion == sum(xs[a]*xs[b]*xs[c]*xs[d] # optional - sage.combinat + sage: expansion = FP.expand(5) # needs sage.combinat + sage: xs = expansion.parent().gens() # needs sage.combinat + sage: expansion == sum(xs[a]*xs[b]*xs[c]*xs[d] # needs sage.combinat ....: for a in range(5) for b in range(5) ....: for c in range(5) for d in range(5) ....: if a <= b and c <= b and b < d) True sage: P = Poset([[],[]]) - sage: FP = P.p_partition_enumerator((), QQ, check=True); FP # optional - sage.combinat + sage: FP = P.p_partition_enumerator((), QQ, check=True); FP # needs sage.combinat M[] With the ``weights`` parameter:: sage: P = Poset([[1,2,3,4],[[1,4],[2,4],[4,3]]]) - sage: FP = P.p_partition_enumerator((3,1,2,4), QQ, # optional - sage.combinat + sage: FP = P.p_partition_enumerator((3,1,2,4), QQ, # needs sage.combinat ....: weights={1: 1, 2: 2, 3: 1, 4: 1}, check=True); FP M[1, 2, 1, 1] + M[1, 3, 1] + M[2, 1, 1, 1] + M[2, 2, 1] + M[3, 1, 1] + M[4, 1] - sage: FP = P.p_partition_enumerator((3,1,2,4), QQ, # optional - sage.combinat + sage: FP = P.p_partition_enumerator((3,1,2,4), QQ, # needs sage.combinat ....: weights={2: 2}, check=True); FP M[1, 2, 1, 1] + M[1, 3, 1] + M[2, 1, 1, 1] + M[2, 2, 1] + M[3, 1, 1] + M[4, 1] sage: P = Poset([['a','b','c'], [['a','b'], ['a','c']]]) - sage: FP = P.p_partition_enumerator(('b','c','a'), QQ, # optional - sage.combinat + sage: FP = P.p_partition_enumerator(('b','c','a'), QQ, # needs sage.combinat ....: weights={'a': 3, 'b': 5, 'c': 7}, check=True); FP M[3, 5, 7] + M[3, 7, 5] + M[3, 12] sage: P = Poset([['a','b','c'], [['a','c'], ['b','c']]]) - sage: FP = P.p_partition_enumerator(('b','c','a'), QQ, # optional - sage.combinat + sage: FP = P.p_partition_enumerator(('b','c','a'), QQ, # needs sage.combinat ....: weights={'a': 3, 'b': 5, 'c': 7}, check=True); FP M[3, 5, 7] + M[3, 12] + M[5, 3, 7] + M[8, 7] - sage: FP = P.p_partition_enumerator(('a','b','c'), QQ, # optional - sage.combinat + sage: FP = P.p_partition_enumerator(('a','b','c'), QQ, # needs sage.combinat ....: weights={'a': 3, 'b': 5, 'c': 7}, check=True); FP M[3, 5, 7] + M[3, 12] + M[5, 3, 7] + M[5, 10] + M[8, 7] + M[15] """ @@ -8585,18 +8602,18 @@ def completion_by_cuts(self): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P.completion_by_cuts().is_isomorphic(P) # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P.completion_by_cuts().is_isomorphic(P) True sage: Y = Poset({1: [2], 2: [3, 4]}) - sage: trafficsign = LatticePoset({1: [2], 2: [3, 4], 3: [5], 4: [5]}) # optional - sage.modules - sage: L = Y.completion_by_cuts() # optional - sage.modules - sage: L.is_isomorphic(trafficsign) # optional - sage.modules + sage: trafficsign = LatticePoset({1: [2], 2: [3, 4], 3: [5], 4: [5]}) + sage: L = Y.completion_by_cuts() + sage: L.is_isomorphic(trafficsign) True sage: P = posets.SymmetricGroupBruhatOrderPoset(3) - sage: Q = P.completion_by_cuts(); Q # optional - sage.modules + sage: Q = P.completion_by_cuts(); Q Finite lattice containing 7 elements .. SEEALSO:: @@ -8625,7 +8642,7 @@ def incidence_algebra(self, R, prefix='I'): EXAMPLES:: sage: P = posets.BooleanLattice(4) - sage: P.incidence_algebra(QQ) # optional - sage.modules + sage: P.incidence_algebra(QQ) Incidence algebra of Finite lattice containing 16 elements over Rational Field """ @@ -8747,7 +8764,7 @@ def kazhdan_lusztig_polynomial(self, x=None, y=None, q=None, canonical_labels=No sage: y = '3421' sage: L.kazhdan_lusztig_polynomial(x, y) -q + 1 - sage: L.kazhdan_lusztig_polynomial(x, y, var('t')) # optional - sage.symbolic + sage: L.kazhdan_lusztig_polynomial(x, y, var('t')) # needs sage.symbolic -t + 1 AUTHORS: @@ -8849,8 +8866,8 @@ def _macaulay2_init_(self, macaulay2=None): EXAMPLES:: - sage: P = posets.PentagonPoset() # optional - sage.modules - sage: P._macaulay2_init_() # optional - sage.modules + sage: P = posets.PentagonPoset() + sage: P._macaulay2_init_() 'needsPackage "Posets";poset({0,1,2,3,4},{{0,1},{0,2},{1,4},{2,3},{3,4}})' sage: P = Poset({1:[2],2:[]}) @@ -8919,9 +8936,9 @@ def __contains__(self, P): """ EXAMPLES:: - sage: posets.PentagonPoset() in Posets(5) # optional - sage.modules + sage: posets.PentagonPoset() in Posets(5) True - sage: posets.PentagonPoset() in Posets(3) # optional - sage.modules + sage: posets.PentagonPoset() in Posets(3) False sage: 1 in Posets(3) False @@ -9090,22 +9107,20 @@ def _ford_fulkerson_chronicle(G, s, t, a): sage: next(ffc) (11, 2) """ - from sage.graphs.digraph import DiGraph - # pi: potential function as a dictionary. - pi = {v: 0 for v in G.vertex_iterator()} + pi = {v: 0 for v in G} # p: value of the potential pi. p = 0 # f: flow function as a dictionary. - f = {(u, v): 0 for (u, v, l) in G.edge_iterator()} + f = {edge: 0 for edge in G.edge_iterator(labels=False)} # val: value of the flow f. (Cannot call it v due to Python's asinine # handling of for loops.) val = 0 # capacity: capacity function as a dictionary. Here, just the # indicator function of the set of arcs of G. - capacity = {(u, v): 1 for (u, v, l) in G.edge_iterator()} + capacity = {edge: 1 for edge in G.edge_iterator(labels=False)} while True: @@ -9113,30 +9128,29 @@ def _ford_fulkerson_chronicle(G, s, t, a): # Gprime: directed graph G' from Britz-Fomin, Section 7. Gprime = DiGraph() - Gprime.add_vertices(G.vertices(sort=False)) - for (u, v, l) in G.edge_iterator(): + Gprime.add_vertices(G) + for u, v in G.edge_iterator(labels=False): if pi[v] - pi[u] == a[(u, v)]: if f[(u, v)] < capacity[(u, v)]: Gprime.add_edge(u, v) elif f[(u, v)] > 0: Gprime.add_edge(v, u) - # X: list of vertices of G' reachable from s, along with - # the shortest paths from s to them. - X = Gprime.shortest_paths(s) + # X: list of vertices of G' reachable from s + X = set(Gprime.depth_first_search(s)) if t in X: # Step MC2a in Britz-Fomin, Algorithm 7.2. - shortest_path = X[t] + shortest_path = Gprime.shortest_path(s, t, by_weight=False) shortest_path_in_edges = zip(shortest_path[:-1], shortest_path[1:]) - for (u, v) in shortest_path_in_edges: - if v in G.neighbors_out(u): + for u, v in shortest_path_in_edges: + if v in G.neighbor_out_iterator(u): f[(u, v)] += 1 else: f[(v, u)] -= 1 val += 1 else: # Step MC2b in Britz-Fomin, Algorithm 7.2. - for v in G.vertex_iterator(): + for v in G: if v not in X: pi[v] += 1 p += 1 diff --git a/src/sage/combinat/ribbon_tableau.py b/src/sage/combinat/ribbon_tableau.py index 65b9b7079cd..843626c4752 100644 --- a/src/sage/combinat/ribbon_tableau.py +++ b/src/sage/combinat/ribbon_tableau.py @@ -1083,7 +1083,9 @@ def __contains__(self, x): return all(xi.is_semistandard() for xi in x) def __iter__(self): - """ + r""" + Iterate over ``self``. + EXAMPLES:: sage: sp = SkewPartitions(3).list() @@ -1098,6 +1100,21 @@ def __iter__(self): 34 sage: RibbonTableaux(a,weight,k).cardinality() 34 + + TESTS: + + Check that :issue:`36196` is fixed:: + + sage: shapes = [[[1], [0]], [[1], [0]], [[1], [0]]] + sage: weight = [1, 1, 1] + sage: SMST = SemistandardMultiSkewTableaux(shapes, weight) + sage: list(SMST) + [[[[1]], [[2]], [[3]]], + [[[2]], [[1]], [[3]]], + [[[1]], [[3]], [[2]]], + [[[2]], [[3]], [[1]]], + [[[3]], [[1]], [[2]]], + [[[3]], [[2]], [[1]]]] """ parts = self._shape mu = self._weight @@ -1122,9 +1139,12 @@ def __iter__(self): S = SkewTableaux() for lk in l: pos = 0 # Double check this - restmp = [S.from_shape_and_word(parts[0], [lk[j] for j in range(s[0])])] + lk = list(lk) + w = lk[:s[0]] + restmp = [S.from_shape_and_word(parts[0], w)] for i in range(1, len(parts)): - w = [lk[j] for j in range(pos + s[i - 1], pos + s[i - 1] + s[i])] + pos += s[i-1] + w = lk[pos: pos + s[i]] restmp.append(S.from_shape_and_word(parts[i], w)) yield self.element_class(self, restmp) diff --git a/src/sage/combinat/root_system/ambient_space.py b/src/sage/combinat/root_system/ambient_space.py index 7c7159a444c..c9696b98fdb 100644 --- a/src/sage/combinat/root_system/ambient_space.py +++ b/src/sage/combinat/root_system/ambient_space.py @@ -117,9 +117,13 @@ def _test_norm_of_simple_roots(self, **options): """ tester = self._tester(**options) T = self.cartan_type() - D = T.symmetrizer() - alpha = self.simple_roots() - for C in T.dynkin_diagram().connected_components(sort=False): + try: + D = T.symmetrizer() + alpha = self.simple_roots() + DD = T.dynkin_diagram() + except ImportError: # Dynkin diagrams need sage.graphs + return + for C in DD.connected_components(sort=False): tester.assertEqual(len( set( alpha[i].scalar(alpha[i]) / D[i] for i in C ) ), 1) # FIXME: attribute or method? diff --git a/src/sage/combinat/root_system/associahedron.py b/src/sage/combinat/root_system/associahedron.py index 578007985fd..b0739695810 100644 --- a/src/sage/combinat/root_system/associahedron.py +++ b/src/sage/combinat/root_system/associahedron.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.geometry.polyhedron r""" Associahedron diff --git a/src/sage/combinat/root_system/braid_move_calculator.py b/src/sage/combinat/root_system/braid_move_calculator.py index 10991bf2504..e932662bd5d 100644 --- a/src/sage/combinat/root_system/braid_move_calculator.py +++ b/src/sage/combinat/root_system/braid_move_calculator.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap """ Braid Move Calculator diff --git a/src/sage/combinat/root_system/branching_rules.py b/src/sage/combinat/root_system/branching_rules.py index 9c8967331b8..d92d08a8eed 100644 --- a/src/sage/combinat/root_system/branching_rules.py +++ b/src/sage/combinat/root_system/branching_rules.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap """ Branching Rules """ @@ -54,7 +55,7 @@ def branch_weyl_character(chi, R, S, rule="default"): * ``"triality"`` * ``"miscellaneous"`` - The ``BranchingRule`` class is a wrapper for functions + The :class:`BranchingRule` class is a wrapper for functions from the weight lattice of `G` to the weight lattice of `H`. An instance of this class encodes an embedding of `H` into `G`. The usual way to specify an embedding is to supply a diff --git a/src/sage/combinat/root_system/cartan_matrix.py b/src/sage/combinat/root_system/cartan_matrix.py index 77f175f0364..c1ce04fba38 100644 --- a/src/sage/combinat/root_system/cartan_matrix.py +++ b/src/sage/combinat/root_system/cartan_matrix.py @@ -28,21 +28,29 @@ from sage.misc.cachefunc import cached_method from sage.matrix.constructor import matrix +from sage.misc.lazy_import import lazy_import from sage.structure.element import is_Matrix from sage.matrix.matrix_space import MatrixSpace from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass from sage.misc.classcall_metaclass import typecall from sage.combinat.subset import powerset -from sage.matrix.matrix_integer_sparse import Matrix_integer_sparse from sage.rings.integer_ring import ZZ from sage.combinat.root_system.cartan_type import CartanType, CartanType_abstract from sage.combinat.root_system.root_system import RootSystem from sage.sets.family import Family -from sage.graphs.digraph import DiGraph +lazy_import('sage.graphs.digraph', 'DiGraph') +lazy_import('sage.combinat.root_system.dynkin_diagram', 'DynkinDiagram_class') -class CartanMatrix(Matrix_integer_sparse, CartanType_abstract, - metaclass=InheritComparisonClasscallMetaclass): + +try: + from sage.matrix.matrix_integer_sparse import Matrix_integer_sparse as Base +except ImportError: + from sage.matrix.matrix_generic_sparse import Matrix_generic_sparse as Base + + +class CartanMatrix(Base, CartanType_abstract, + metaclass=InheritComparisonClasscallMetaclass): r""" A (generalized) Cartan matrix. @@ -81,6 +89,7 @@ class CartanMatrix(Matrix_integer_sparse, CartanType_abstract, EXAMPLES:: + sage: # needs sage.graphs sage: CartanMatrix(['A', 4]) [ 2 -1 0 0] [-1 2 -1 0] @@ -140,6 +149,7 @@ class CartanMatrix(Matrix_integer_sparse, CartanType_abstract, :: + sage: # needs sage.graphs sage: CartanMatrix(['G', 2]) [ 2 -3] [-1 2] @@ -207,10 +217,10 @@ class CartanMatrix(Matrix_integer_sparse, CartanType_abstract, Examples of Borcherds-Cartan matrices:: - sage: CartanMatrix([[2,-1],[-1,-2]], borcherds=True) + sage: CartanMatrix([[2,-1],[-1,-2]], borcherds=True) # needs sage.graphs [ 2 -1] [-1 -2] - sage: CartanMatrix('B3', borcherds=[-4,-6,2]) + sage: CartanMatrix('B3', borcherds=[-4,-6,2]) # needs sage.graphs [-4 -1 0] [-1 -6 -1] [ 0 -2 2] @@ -237,6 +247,7 @@ def __classcall_private__(cls, data=None, index_set=None, EXAMPLES:: + sage: # needs sage.graphs sage: C = CartanMatrix(['A',1,1]) sage: C2 = CartanMatrix([[2, -2], [-2, 2]]) sage: C3 = CartanMatrix(matrix([[2, -2], [-2, 2]]), [0, 1]) @@ -247,6 +258,7 @@ def __classcall_private__(cls, data=None, index_set=None, Check that :trac:`15740` is fixed:: + sage: # needs sage.graphs sage: d = DynkinDiagram() sage: d.add_edge('a', 'b', 2) sage: d.index_set() @@ -274,7 +286,6 @@ def __classcall_private__(cls, data=None, index_set=None, dynkin_diagram = None subdivisions = None - from sage.combinat.root_system.dynkin_diagram import DynkinDiagram_class if isinstance(data, DynkinDiagram_class): dynkin_diagram = data cartan_type = data._cartan_type @@ -346,6 +357,7 @@ def matrix_space(self, nrows=None, ncols=None, sparse=None): EXAMPLES:: + sage: # needs sage.graphs sage: cm = CartanMatrix(['A', 3]) sage: cm.matrix_space() Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring @@ -374,8 +386,8 @@ def _CM_init(self, cartan_type, index_set, cartan_type_check): TESTS:: - sage: C = CartanMatrix(['A',1,1]) # indirect doctest - sage: TestSuite(C).run(skip=["_test_category", "_test_change_ring"]) + sage: C = CartanMatrix(['A',1,1]) # indirect doctest # needs sage.graphs + sage: TestSuite(C).run(skip=["_test_category", "_test_change_ring"]) # needs sage.graphs """ self._index_set = index_set self.set_immutable() @@ -398,9 +410,9 @@ def __reduce__(self): TESTS:: - sage: CM = CartanMatrix(['A',4]) - sage: x = loads(dumps(CM)) - sage: x._index_set + sage: CM = CartanMatrix(['A',4]) # needs sage.graphs + sage: x = loads(dumps(CM)) # needs sage.graphs + sage: x._index_set # needs sage.graphs (1, 2, 3, 4) """ if self._cartan_type: @@ -413,8 +425,8 @@ def root_system(self): EXAMPLES:: - sage: C = CartanMatrix(['A',3]) - sage: C.root_system() + sage: C = CartanMatrix(['A',3]) # needs sage.graphs + sage: C.root_system() # needs sage.graphs Root system of type ['A', 3] """ if self._cartan_type is not None: @@ -427,8 +439,8 @@ def root_space(self): EXAMPLES:: - sage: C = CartanMatrix(['A',3]) - sage: C.root_space() + sage: C = CartanMatrix(['A',3]) # needs sage.graphs + sage: C.root_space() # needs sage.graphs Root space over the Rational Field of the Root system of type ['A', 3] """ return self.root_system().root_space() @@ -439,8 +451,8 @@ def reflection_group(self, type="matrix"): EXAMPLES:: - sage: C = CartanMatrix(['A',3]) - sage: C.reflection_group() + sage: C = CartanMatrix(['A',3]) # needs sage.graphs + sage: C.reflection_group() # needs sage.graphs Weyl Group of type ['A', 3] (as a matrix group acting on the root space) """ RS = self.root_space() @@ -468,8 +480,8 @@ def symmetrizer(self): EXAMPLES:: - sage: cm = CartanMatrix([[2,-5],[-2,2]]) - sage: cm.symmetrizer() + sage: cm = CartanMatrix([[2,-5],[-2,2]]) # needs sage.graphs + sage: cm.symmetrizer() # needs sage.graphs Finite family {0: 2, 1: 5} TESTS: @@ -478,9 +490,9 @@ def symmetrizer(self): with the values given by the Cartan type:: sage: ct = CartanType(['B',4,1]) - sage: ct.symmetrizer() + sage: ct.symmetrizer() # needs sage.graphs Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1} - sage: ct.cartan_matrix().symmetrizer() + sage: ct.cartan_matrix().symmetrizer() # needs sage.graphs Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1} """ sym = self.is_symmetrizable(True) @@ -501,8 +513,8 @@ def symmetrized_matrix(self): EXAMPLES:: - sage: cm = CartanMatrix(['B',4,1]) - sage: cm.symmetrized_matrix() + sage: cm = CartanMatrix(['B',4,1]) # needs sage.graphs + sage: cm.symmetrized_matrix() # needs sage.graphs [ 4 0 -2 0 0] [ 0 4 -2 0 0] [-2 -2 4 -2 0] @@ -522,6 +534,7 @@ def index_set(self): EXAMPLES:: + sage: # needs sage.graphs sage: C = CartanMatrix(['A',1,1]) sage: C.index_set() (0, 1) @@ -537,14 +550,14 @@ def cartan_type(self): EXAMPLES:: - sage: C = CartanMatrix(['A',4,1]) - sage: C.cartan_type() + sage: C = CartanMatrix(['A',4,1]) # needs sage.graphs + sage: C.cartan_type() # needs sage.graphs ['A', 4, 1] If the Cartan type is unknown:: - sage: C = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]]) - sage: C.cartan_type() + sage: C = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]]) # needs sage.graphs + sage: C.cartan_type() # needs sage.graphs [ 2 -1 -2] [-1 2 -1] [-2 -1 2] @@ -564,6 +577,7 @@ def subtype(self, index_set): EXAMPLES:: + sage: # needs sage.graphs sage: C = CartanMatrix(['F',4]) sage: S = C.subtype([1,2,3]) sage: S @@ -583,9 +597,9 @@ def rank(self): EXAMPLES:: - sage: CartanMatrix(['C',3]).rank() + sage: CartanMatrix(['C',3]).rank() # needs sage.graphs 3 - sage: CartanMatrix(["A2","B2","F4"]).rank() + sage: CartanMatrix(["A2","B2","F4"]).rank() # needs sage.graphs 8 """ return self.ncols() @@ -596,6 +610,7 @@ def relabel(self, relabelling): EXAMPLES:: + sage: # needs sage.graphs sage: CM = CartanMatrix(['C',3]) sage: R = CM.relabel({1:0, 2:4, 3:1}); R [ 2 0 -1] @@ -617,6 +632,7 @@ def dynkin_diagram(self): EXAMPLES:: + sage: # needs sage.graphs sage: C = CartanMatrix(['A',2]) sage: C.dynkin_diagram() O---O @@ -642,7 +658,7 @@ def cartan_matrix(self): EXAMPLES:: - sage: CartanMatrix(['C',3]).cartan_matrix() + sage: CartanMatrix(['C',3]).cartan_matrix() # needs sage.graphs [ 2 -1 0] [-1 2 -2] [ 0 -1 2] @@ -656,6 +672,7 @@ def dual(self): EXAMPLES:: + sage: # needs sage.graphs sage: ct = CartanType(['C',3]) sage: M = CartanMatrix(ct); M [ 2 -1 0] @@ -672,6 +689,7 @@ def dual(self): An example with arbitrary Cartan matrices:: + sage: # needs sage.graphs sage: cm = CartanMatrix([[2,-5], [-2, 2]]); cm [ 2 -5] [-2 2] @@ -696,8 +714,9 @@ def is_simply_laced(self): EXAMPLES:: - sage: cm = CartanMatrix([[2, -1, -1, -1], [-1, 2, -1, -1], [-1, -1, 2, -1], [-1, -1, -1, 2]]) - sage: cm.is_simply_laced() + sage: cm = CartanMatrix([[2, -1, -1, -1], [-1, 2, -1, -1], # needs sage.graphs + ....: [-1, -1, 2, -1], [-1, -1, -1, 2]]) + sage: cm.is_simply_laced() # needs sage.graphs True """ for i in range(self.nrows()): @@ -714,7 +733,7 @@ def is_crystallographic(self): EXAMPLES:: - sage: CartanMatrix(['F',4]).is_crystallographic() + sage: CartanMatrix(['F',4]).is_crystallographic() # needs sage.graphs True """ return self.is_symmetrizable() @@ -726,8 +745,8 @@ def column_with_indices(self, j): EXAMPLES:: - sage: M = CartanMatrix(['B',4]) - sage: [ (i,a) for (i,a) in M.column_with_indices(3) ] + sage: M = CartanMatrix(['B',4]) # needs sage.graphs + sage: [ (i,a) for (i,a) in M.column_with_indices(3) ] # needs sage.graphs [(3, 2), (2, -1), (4, -2)] """ return self.dynkin_diagram().column(j) @@ -739,8 +758,8 @@ def row_with_indices(self, i): EXAMPLES:: - sage: M = CartanMatrix(['C',4]) - sage: [ (i,a) for (i,a) in M.row_with_indices(3) ] + sage: M = CartanMatrix(['C',4]) # needs sage.graphs + sage: [ (i,a) for (i,a) in M.row_with_indices(3) ] # needs sage.graphs [(3, 2), (2, -1), (4, -2)] """ return self.dynkin_diagram().row(i) @@ -758,6 +777,7 @@ def is_finite(self): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix(['C',4]) sage: M.is_finite() True @@ -785,6 +805,7 @@ def is_affine(self): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix(['C',4]) sage: M.is_affine() False @@ -822,6 +843,7 @@ def is_hyperbolic(self, compact=False): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix([[2,-2,0],[-2,2,-1],[0,-1,2]]) sage: M.is_hyperbolic() True @@ -858,6 +880,7 @@ def is_lorentzian(self): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix([[2,-3],[-3,2]]) sage: M.is_lorentzian() True @@ -876,6 +899,7 @@ def is_indefinite(self): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix([[2,-3],[-3,2]]) sage: M.is_indefinite() True @@ -892,6 +916,7 @@ def is_indecomposable(self): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix(['A',5]) sage: M.is_indecomposable() True @@ -912,6 +937,7 @@ def coxeter_matrix(self): EXAMPLES:: + sage: # needs sage.graphs sage: cm = CartanMatrix([[2,-5,0],[-2,2,-1],[0,-1,2]]) sage: cm.coxeter_matrix() [ 1 -1 2] @@ -949,6 +975,7 @@ def coxeter_diagram(self): EXAMPLES:: + sage: # needs sage.graphs sage: cm = CartanMatrix([[2,-5,0],[-2,2,-1],[0,-1,2]]) sage: G = cm.coxeter_diagram(); G Graph on 3 vertices @@ -972,13 +999,13 @@ def principal_submatrices(self, proper=False): EXAMPLES:: - sage: M = CartanMatrix(['A',2]) - sage: M.principal_submatrices() + sage: M = CartanMatrix(['A',2]) # needs sage.graphs + sage: M.principal_submatrices() # needs sage.graphs [ [ 2 -1] [], [2], [2], [-1 2] ] - sage: M.principal_submatrices(proper=True) + sage: M.principal_submatrices(proper=True) # needs sage.graphs [[], [2], [2]] """ @@ -996,6 +1023,7 @@ def indecomposable_blocks(self): EXAMPLES:: + sage: # needs sage.graphs sage: M = CartanMatrix(['A',2]) sage: M.indecomposable_blocks() ( @@ -1097,6 +1125,7 @@ def find_cartan_type_from_matrix(CM): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.combinat.root_system.cartan_matrix import find_cartan_type_from_matrix sage: CM = CartanMatrix([[2,-1,-1], [-1,2,-1], [-1,-1,2]]) sage: find_cartan_type_from_matrix(CM) diff --git a/src/sage/combinat/root_system/cartan_type.py b/src/sage/combinat/root_system/cartan_type.py index 013ceca8a02..a2e831bf1f3 100644 --- a/src/sage/combinat/root_system/cartan_type.py +++ b/src/sage/combinat/root_system/cartan_type.py @@ -16,13 +16,12 @@ Let us consider, for example, the Cartan type `A_4`:: - sage: T = CartanType(['A', 4]) - sage: T + sage: T = CartanType(['A', 4]); T ['A', 4] It is the name of the following Dynkin diagram:: - sage: DynkinDiagram(T) + sage: DynkinDiagram(T) # needs sage.graphs O---O---O---O 1 2 3 4 A4 @@ -31,15 +30,15 @@ For convenience, the following shortcuts are available:: - sage: DynkinDiagram(['A',4]) + sage: DynkinDiagram(['A',4]) # needs sage.graphs O---O---O---O 1 2 3 4 A4 - sage: DynkinDiagram('A4') + sage: DynkinDiagram('A4') # needs sage.graphs O---O---O---O 1 2 3 4 A4 - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O---O 1 2 3 4 A4 @@ -55,10 +54,9 @@ The associated Weyl group of `A_n` is the symmetric group `S_{n+1}`:: - sage: W = WeylGroup(T) - sage: W + sage: W = WeylGroup(T); W # needs sage.libs.gap Weyl Group of type ['A', 4] (as a matrix group acting on the ambient space) - sage: W.cardinality() + sage: W.cardinality() # needs sage.libs.gap 120 while the Lie algebra is `sl_{n+1}`, and the Lie group `SL_{n+1}` @@ -67,22 +65,20 @@ One may also construct crystals associated to various Dynkin diagrams. For example:: - sage: C = crystals.Letters(T) - sage: C + sage: C = crystals.Letters(T); C # needs sage.combinat The crystal of letters for type ['A', 4] - sage: C.list() + sage: C.list() # needs sage.combinat [1, 2, 3, 4, 5] - sage: C = crystals.Tableaux(T, shape=[2]) - sage: C + sage: C = crystals.Tableaux(T, shape=[2]); C # needs sage.combinat The crystal of tableaux of type ['A', 4] and shape(s) [[2]] - sage: C.cardinality() + sage: C.cardinality() # needs sage.combinat 15 Here is a sample of all the finite irreducible crystallographic Cartan types:: - sage: CartanType.samples(finite = True, crystallographic = True) + sage: CartanType.samples(finite=True, crystallographic=True) [['A', 1], ['A', 5], ['B', 1], ['B', 5], ['C', 1], ['C', 5], ['D', 2], ['D', 3], ['D', 5], ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2]] @@ -92,15 +88,17 @@ sage: [latex(ct) for ct in CartanType.samples(crystallographic=True)] [A_{1}, A_{5}, B_{1}, B_{5}, C_{1}, C_{5}, D_{2}, D_{3}, D_{5}, E_6, E_7, E_8, F_4, G_2, - A_{1}^{(1)}, A_{5}^{(1)}, B_{1}^{(1)}, B_{5}^{(1)}, C_{1}^{(1)}, C_{5}^{(1)}, D_{3}^{(1)}, D_{5}^{(1)}, + A_{1}^{(1)}, A_{5}^{(1)}, B_{1}^{(1)}, B_{5}^{(1)}, + C_{1}^{(1)}, C_{5}^{(1)}, D_{3}^{(1)}, D_{5}^{(1)}, E_6^{(1)}, E_7^{(1)}, E_8^{(1)}, F_4^{(1)}, G_2^{(1)}, BC_{1}^{(2)}, BC_{5}^{(2)}, - B_{5}^{(1)\vee}, C_{4}^{(1)\vee}, F_4^{(1)\vee}, G_2^{(1)\vee}, BC_{1}^{(2)\vee}, BC_{5}^{(2)\vee}] + B_{5}^{(1)\vee}, C_{4}^{(1)\vee}, F_4^{(1)\vee}, + G_2^{(1)\vee}, BC_{1}^{(2)\vee}, BC_{5}^{(2)\vee}] sage: view([DynkinDiagram(ct) for ct in CartanType.samples(crystallographic=True)]) # not tested Non-crystallographic Cartan types are also partially supported:: - sage: CartanType.samples(finite = True, crystallographic = False) + sage: CartanType.samples(finite=True, crystallographic=False) [['I', 5], ['H', 3], ['H', 4]] In Sage, a Cartan type is used as a database of type-specific @@ -118,7 +116,7 @@ Elements of Mathematics, Springer (2002). ISBN 978-3540426509. For example:: sage: T = CartanType(['D', 4]) - sage: DynkinDiagram(T) + sage: DynkinDiagram(T) # needs sage.graphs O 4 | | @@ -127,7 +125,7 @@ D4 sage: E6 = CartanType(['E',6]) - sage: DynkinDiagram(E6) + sage: DynkinDiagram(E6) # needs sage.graphs O 2 | | @@ -142,11 +140,11 @@ For example, in type `C_2`, we have:: - sage: C2 = DynkinDiagram(['C',2]); C2 + sage: C2 = DynkinDiagram(['C',2]); C2 # needs sage.graphs O=<=O 1 2 C2 - sage: C2.cartan_matrix() + sage: C2.cartan_matrix() # needs sage.graphs [ 2 -2] [-1 2] @@ -162,7 +160,7 @@ If desired, other node labelling conventions can be achieved. For example the Kac labelling for type `E_6` can be obtained via:: - sage: E6.relabel({1:1,2:6,3:2,4:3,5:4,6:5}).dynkin_diagram() + sage: E6.relabel({1:1,2:6,3:2,4:3,5:4,6:5}).dynkin_diagram() # needs sage.graphs O 6 | | @@ -183,25 +181,25 @@ Kac, Infinite Dimensional Lie Algebras. We start with an empty Dynkin diagram, and add a couple nodes:: - sage: g = DynkinDiagram() - sage: g.add_vertices([1,2,3]) + sage: g = DynkinDiagram() # needs sage.graphs + sage: g.add_vertices([1,2,3]) # needs sage.graphs Note that the diagonal of the Cartan matrix is already initialized:: - sage: g.cartan_matrix() + sage: g.cartan_matrix() # needs sage.graphs [2 0 0] [0 2 0] [0 0 2] Then we add a couple edges:: - sage: g.add_edge(1,2,2) - sage: g.add_edge(1,3) - sage: g.add_edge(2,3) + sage: g.add_edge(1,2,2) # needs sage.graphs + sage: g.add_edge(1,3) # needs sage.graphs + sage: g.add_edge(2,3) # needs sage.graphs and we get the desired Cartan matrix:: - sage: g.cartan_matrix() + sage: g.cartan_matrix() # needs sage.graphs [2 0 0] [0 2 0] [0 0 2] @@ -216,18 +214,18 @@ Here, we can work around this by clearing the cache:: - sage: delattr(g, 'cartan_matrix') + sage: delattr(g, 'cartan_matrix') # needs sage.graphs Now we get the desired Cartan matrix:: - sage: g.cartan_matrix() + sage: g.cartan_matrix() # needs sage.graphs [ 2 -1 -1] [-2 2 -1] [-1 -1 2] Note that backward edges have been automatically added:: - sage: g.edges(sort=True) + sage: g.edges(sort=True) # needs sage.graphs [(1, 2, 2), (1, 3, 1), (2, 1, 1), (2, 3, 1), (3, 1, 1), (3, 2, 1)] .. rubric:: Reducible Cartan types @@ -284,7 +282,7 @@ groups: each affine type is either untwisted (that is arise from the natural affinisation of a finite Cartan type):: - sage: CartanType(["A", 4, 1]).dynkin_diagram() + sage: CartanType(["A", 4, 1]).dynkin_diagram() # needs sage.graphs 0 O-----------+ | | @@ -292,7 +290,7 @@ O---O---O---O 1 2 3 4 A4~ - sage: CartanType(["B", 4, 1]).dynkin_diagram() + sage: CartanType(["B", 4, 1]).dynkin_diagram() # needs sage.graphs O 0 | | @@ -302,7 +300,7 @@ or dual thereof:: - sage: CartanType(["B", 4, 1]).dual().dynkin_diagram() + sage: CartanType(["B", 4, 1]).dual().dynkin_diagram() # needs sage.graphs O 0 | | @@ -313,18 +311,18 @@ or is of type `\widetilde{BC}_n` (which yields an irreducible, but nonreduced root system):: - sage: CartanType(["BC", 4, 2]).dynkin_diagram() + sage: CartanType(["BC", 4, 2]).dynkin_diagram() # needs sage.graphs O=<=O---O---O=<=O 0 1 2 3 4 BC4~ This includes the two degenerate cases:: - sage: CartanType(["A", 1, 1]).dynkin_diagram() + sage: CartanType(["A", 1, 1]).dynkin_diagram() # needs sage.graphs O<=>O 0 1 A1~ - sage: CartanType(["BC", 1, 2]).dynkin_diagram() + sage: CartanType(["BC", 1, 2]).dynkin_diagram() # needs sage.graphs 4 O=<=O 0 1 @@ -333,6 +331,7 @@ For the user convenience, Kac's notations for twisted affine types are automatically translated into the previous ones:: + sage: # needs sage.graphs sage: CartanType(["A", 9, 2]) ['B', 5, 1]^* sage: CartanType(["A", 9, 2]).dynkin_diagram() @@ -362,6 +361,7 @@ Additionally one can set the notation option to use Kac's notation:: + sage: # needs sage.graphs sage: CartanType.options['notation'] = 'Kac' sage: CartanType(["A", 9, 2]) ['A', 9, 2] @@ -546,7 +546,7 @@ def __call__(self, *args): sage: CT = CartanType([['A',2]]) sage: CT.is_irreducible() True - sage: CT.cartan_matrix() + sage: CT.cartan_matrix() # needs sage.graphs [ 2 -1] [-1 2] sage: CT = CartanType(['A2']) @@ -898,7 +898,7 @@ class options(GlobalOptions): sage: ct = CartanType(['D',5,2]); ct ['C', 4, 1]^* - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs O=<=O---O---O=>=O 0 1 2 3 4 C4~* @@ -907,7 +907,7 @@ class options(GlobalOptions): sage: CartanType.options(dual_str='#', dual_latex='\\ast',) sage: ct ['C', 4, 1]^# - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs O=<=O---O---O=>=O 0 1 2 3 4 C4~# @@ -916,7 +916,7 @@ class options(GlobalOptions): sage: CartanType.options(notation='kac', mark_special_node='both') sage: ct ['D', 5, 2] - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs @=<=O---O---O=>=O 0 1 2 3 4 D5^2 @@ -930,7 +930,7 @@ class options(GlobalOptions): ['A', 8, 2]^+ sage: latex(dct) A_{8}^{(2)\dagger} - sage: dct.dynkin_diagram() + sage: dct.dynkin_diagram() # needs sage.graphs @=>=O---O---O=>=O 0 1 2 3 4 A8^2+ @@ -1149,6 +1149,7 @@ def coxeter_diagram(self): EXAMPLES:: + sage: # needs sage.graphs sage: CartanType(['B',3]).coxeter_diagram() Graph on 3 vertices sage: CartanType(['A',3]).coxeter_diagram().edges(sort=True) @@ -1168,7 +1169,7 @@ def coxeter_matrix(self): EXAMPLES:: - sage: CartanType(['A', 4]).coxeter_matrix() + sage: CartanType(['A', 4]).coxeter_matrix() # needs sage.graphs [1 3 2 2] [3 1 3 2] [2 3 1 3] @@ -1228,7 +1229,7 @@ def relabel(self, relabelling): EXAMPLES:: - sage: CartanType(['F',4]).relabel({ 1:4, 2:3, 3:2, 4:1 }).dynkin_diagram() + sage: CartanType(['F',4]).relabel({ 1:4, 2:3, 3:2, 4:1 }).dynkin_diagram() # needs sage.graphs O---O=>=O---O 4 3 2 1 F4 relabelled by {1: 4, 2: 3, 3: 2, 4: 1} @@ -1246,11 +1247,11 @@ def subtype(self, index_set): EXAMPLES:: sage: ct = CartanType(['A',6,2]) - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs O=<=O---O=<=O 0 1 2 3 BC3~ - sage: ct.subtype([1,2,3]) + sage: ct.subtype([1,2,3]) # needs sage.graphs ['C', 3] """ return self.cartan_matrix().subtype(index_set).cartan_type() @@ -1265,7 +1266,7 @@ def marked_nodes(self, marked_nodes): EXAMPLES:: - sage: CartanType(['F',4]).marked_nodes([1, 3]).dynkin_diagram() + sage: CartanType(['F',4]).marked_nodes([1, 3]).dynkin_diagram() # needs sage.graphs X---O=>=X---O 1 2 3 4 F4 with nodes (1, 3) marked @@ -1416,7 +1417,8 @@ def is_simply_laced(self): [['C', 1], True], [['C', 5], False], [['D', 2], True], [['D', 3], True], [['D', 5], True], [['E', 6], True], [['E', 7], True], [['E', 8], True], - [['F', 4], False], [['G', 2], False], [['I', 5], False], [['H', 3], False], [['H', 4], False], + [['F', 4], False], [['G', 2], False], [['I', 5], False], + [['H', 3], False], [['H', 4], False], [['A', 1, 1], False], [['A', 5, 1], True], [['B', 1, 1], False], [['B', 5, 1], False], [['C', 1, 1], False], [['C', 5, 1], False], @@ -1424,7 +1426,8 @@ def is_simply_laced(self): [['E', 6, 1], True], [['E', 7, 1], True], [['E', 8, 1], True], [['F', 4, 1], False], [['G', 2, 1], False], [['BC', 1, 2], False], [['BC', 5, 2], False], - [['B', 5, 1]^*, False], [['C', 4, 1]^*, False], [['F', 4, 1]^*, False], [['G', 2, 1]^*, False], + [['B', 5, 1]^*, False], [['C', 4, 1]^*, False], + [['F', 4, 1]^*, False], [['G', 2, 1]^*, False], [['BC', 1, 2]^*, False], [['BC', 5, 2]^*, False]] """ return False @@ -1516,8 +1519,8 @@ def _default_folded_cartan_type(self): EXAMPLES:: - sage: D = CartanMatrix([[2, -3], [-2, 2]]).dynkin_diagram() - sage: D._default_folded_cartan_type() + sage: D = CartanMatrix([[2, -3], [-2, 2]]).dynkin_diagram() # needs sage.graphs + sage: D._default_folded_cartan_type() # needs sage.graphs Dynkin diagram of rank 2 as a folding of Dynkin diagram of rank 2 """ from sage.combinat.root_system.type_folded import CartanTypeFolded @@ -1558,9 +1561,9 @@ def ascii_art(self, label='lambda x: x', node=None): The label option is useful to visualize various statistics on the nodes of the Dynkin diagram:: - sage: a = cartan_type.col_annihilator(); a + sage: a = cartan_type.col_annihilator(); a # needs sage.graphs Finite family {0: 1, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2} - sage: print(CartanType(['B',5,1]).ascii_art(label=a.__getitem__)) + sage: print(CartanType(['B',5,1]).ascii_art(label=a.__getitem__)) # needs sage.graphs O 1 | | @@ -1588,7 +1591,7 @@ def _latex_dynkin_diagram(self, label='lambda i: i', EXAMPLES:: - sage: latex(CartanType(['A',4]).dynkin_diagram()) # indirect doctest + sage: latex(CartanType(['A',4]).dynkin_diagram()) # indirect doctest # needs sage.graphs \begin{tikzpicture}[scale=0.5] \draw (-1,0) node[anchor=east] {$A_{4}$}; \draw (0 cm,0) -- (6 cm,0); @@ -1606,7 +1609,7 @@ def dynkin_diagram(self): EXAMPLES:: - sage: CartanType(['A',4]).dynkin_diagram() + sage: CartanType(['A',4]).dynkin_diagram() # needs sage.graphs O---O---O---O 1 2 3 4 A4 @@ -1624,7 +1627,7 @@ def cartan_matrix(self): EXAMPLES:: - sage: CartanType(['A',4]).cartan_matrix() + sage: CartanType(['A',4]).cartan_matrix() # needs sage.graphs [ 2 -1 0 0] [-1 2 -1 0] [ 0 -1 2 -1] @@ -1643,6 +1646,7 @@ def coxeter_diagram(self): EXAMPLES:: + sage: # needs sage.graphs sage: CartanType(['A',3]).coxeter_diagram() Graph on 3 vertices sage: CartanType(['A',3]).coxeter_diagram().edges(sort=True) @@ -1689,30 +1693,30 @@ def symmetrizer(self): EXAMPLES:: - sage: CartanType(["B",5]).symmetrizer() + sage: CartanType(["B",5]).symmetrizer() # needs sage.graphs Finite family {1: 2, 2: 2, 3: 2, 4: 2, 5: 1} Here is a neat trick to visualize it better:: sage: T = CartanType(["B",5]) - sage: print(T.ascii_art(T.symmetrizer().__getitem__)) + sage: print(T.ascii_art(T.symmetrizer().__getitem__)) # needs sage.graphs O---O---O---O=>=O 2 2 2 2 1 sage: T = CartanType(["BC",5, 2]) - sage: print(T.ascii_art(T.symmetrizer().__getitem__)) + sage: print(T.ascii_art(T.symmetrizer().__getitem__)) # needs sage.graphs O=<=O---O---O---O=<=O 1 2 2 2 2 4 Here is the symmetrizer of some reducible Cartan types:: sage: T = CartanType(["D", 2]) - sage: print(T.ascii_art(T.symmetrizer().__getitem__)) + sage: print(T.ascii_art(T.symmetrizer().__getitem__)) # needs sage.graphs O O 1 1 sage: T = CartanType(["B",5],["BC",5, 2]) - sage: print(T.ascii_art(T.symmetrizer().__getitem__)) + sage: print(T.ascii_art(T.symmetrizer().__getitem__)) # needs sage.graphs O---O---O---O=>=O 2 2 2 2 1 O=<=O---O---O---O=<=O @@ -1722,7 +1726,7 @@ def symmetrizer(self): of the simple roots in the ambient space:: sage: T = CartanType(["C",5]) - sage: print(T.ascii_art(T.symmetrizer().__getitem__)) + sage: print(T.ascii_art(T.symmetrizer().__getitem__)) # needs sage.graphs O---O---O---O=<=O 1 1 1 1 2 @@ -1766,10 +1770,10 @@ def index_set_bipartition(self): EXAMPLES:: - sage: CartanType(['A',5]).index_set_bipartition() + sage: CartanType(['A',5]).index_set_bipartition() # needs sage.graphs ({1, 3, 5}, {2, 4}) - sage: CartanType(['A',2,1]).index_set_bipartition() + sage: CartanType(['A',2,1]).index_set_bipartition() # needs sage.graphs Traceback (most recent call last): ... ValueError: the Dynkin diagram must be bipartite @@ -1937,7 +1941,7 @@ def is_untwisted_affine(self): sage: CartanType(['A', 3, 1]).is_untwisted_affine() True - sage: CartanType(['A', 3, 1]).dual().is_untwisted_affine() # this one is self dual! + sage: CartanType(['A', 3, 1]).dual().is_untwisted_affine() # this one is self dual! True sage: CartanType(['B', 3, 1]).dual().is_untwisted_affine() False @@ -1979,6 +1983,7 @@ def special_nodes(self): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage: CartanType(['A',3,1]).special_nodes() (0, 1, 2, 3) sage: CartanType(['C',2,1]).special_nodes() @@ -2036,7 +2041,7 @@ def classical(self): :meth:`sage.combinat.root_system.cartan_type.CartanType_crystallographic.dynkin_diagram`, and :meth:`special_node` are consistent:: - sage: for ct in CartanType.samples(affine = True): + sage: for ct in CartanType.samples(affine=True): # needs sage.graphs ....: g1 = ct.classical().dynkin_diagram() ....: g2 = ct.dynkin_diagram() ....: g2.delete_vertex(ct.special_node()) @@ -2096,6 +2101,7 @@ def row_annihilator(self, m=None): EXAMPLES:: + sage: # needs sage.graphs sage: RootSystem(['C',2,1]).cartan_type().acheck() Finite family {0: 1, 1: 1, 2: 1} sage: RootSystem(['D',4,1]).cartan_type().acheck() @@ -2107,7 +2113,7 @@ def row_annihilator(self, m=None): ``acheck`` is a shortcut for row_annihilator:: - sage: RootSystem(['BC',4,2]).cartan_type().row_annihilator() + sage: RootSystem(['BC',4,2]).cartan_type().row_annihilator() # needs sage.graphs Finite family {0: 1, 1: 2, 2: 2, 3: 2, 4: 2} FIXME: @@ -2145,6 +2151,7 @@ def col_annihilator(self): EXAMPLES:: + sage: # needs sage.graphs sage: RootSystem(['C',2,1]).cartan_type().a() Finite family {0: 1, 1: 2, 2: 1} sage: RootSystem(['D',4,1]).cartan_type().a() @@ -2156,7 +2163,7 @@ def col_annihilator(self): ``a`` is a shortcut for col_annihilator:: - sage: RootSystem(['BC',4,2]).cartan_type().col_annihilator() + sage: RootSystem(['BC',4,2]).cartan_type().col_annihilator() # needs sage.graphs Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1} """ return self.row_annihilator(self.cartan_matrix().transpose()) @@ -2174,6 +2181,7 @@ def c(self): EXAMPLES:: + sage: # needs sage.graphs sage: RootSystem(['C',2,1]).cartan_type().c() Finite family {0: 1, 1: 2, 2: 1} sage: RootSystem(['D',4,1]).cartan_type().c() @@ -2185,7 +2193,7 @@ def c(self): TESTS:: - sage: CartanType(["B", 3, 1]).c().map(parent) + sage: CartanType(["B", 3, 1]).c().map(parent) # needs sage.graphs Finite family {0: Integer Ring, 1: Integer Ring, 2: Integer Ring, 3: Integer Ring} REFERENCES: @@ -2230,6 +2238,7 @@ def translation_factors(self): EXAMPLES:: + sage: # needs sage.graphs sage: CartanType(['C',2,1]).translation_factors() Finite family {0: 1, 1: 2, 2: 1} sage: CartanType(['C',2,1]).dual().translation_factors() @@ -2244,6 +2253,7 @@ def translation_factors(self): We proceed with systematic tests taken from MuPAD-Combinat's testsuite:: + sage: # needs sage.graphs sage: list(CartanType(["A", 1, 1]).translation_factors()) [1, 1] sage: list(CartanType(["A", 5, 1]).translation_factors()) @@ -2288,37 +2298,37 @@ def translation_factors(self): along `\Lambda_0`:: sage: R = RootSystem(["BC",2,2]) - sage: alpha = R.weight_space().simple_roots() + sage: alpha = R.weight_space().simple_roots() # needs sage.graphs sage: alphacheck = R.coroot_space().simple_roots() sage: Lambda = R.weight_space().fundamental_weights() Here are the levels of the fundamental weights:: - sage: Lambda[0].level(), Lambda[1].level(), Lambda[2].level() + sage: Lambda[0].level(), Lambda[1].level(), Lambda[2].level() # needs sage.graphs (1, 2, 2) So the "center" of the fundamental polygon at level `1` is:: sage: O = Lambda[0] - sage: O.level() + sage: O.level() # needs sage.graphs 1 We take the projection `\omega_1` at level `0` of `\Lambda_1` as unit vector on the `x`-axis, and the projection `\omega_2` at level 0 of `\Lambda_2` as unit vector of the `y`-axis:: - sage: omega1 = Lambda[1]-2*Lambda[0] - sage: omega2 = Lambda[2]-2*Lambda[0] - sage: omega1.level(), omega2.level() + sage: omega1 = Lambda[1] - 2*Lambda[0] + sage: omega2 = Lambda[2] - 2*Lambda[0] + sage: omega1.level(), omega2.level() # needs sage.graphs (0, 0) The projections of the simple roots can be read off:: - sage: alpha[0] + sage: alpha[0] # needs sage.graphs 2*Lambda[0] - Lambda[1] - sage: alpha[1] + sage: alpha[1] # needs sage.graphs -2*Lambda[0] + 2*Lambda[1] - Lambda[2] - sage: alpha[2] + sage: alpha[2] # needs sage.graphs -2*Lambda[1] + 2*Lambda[2] Namely `\alpha_0 = -\omega_1`, `\alpha_1 = 2\omega_1 - @@ -2350,14 +2360,14 @@ def translation_factors(self): smallest with this property. Hence, the translation factors for affine type `BC` are `t_0=1, t_1=1, t_2=1/2`:: - sage: CartanType(['BC',2,2]).translation_factors() + sage: CartanType(['BC',2,2]).translation_factors() # needs sage.graphs Finite family {0: 1, 1: 1, 2: 1/2} TESTS:: - sage: CartanType(["B", 3, 1]).translation_factors().map(parent) + sage: CartanType(["B", 3, 1]).translation_factors().map(parent) # needs sage.graphs Finite family {0: Integer Ring, 1: Integer Ring, 2: Integer Ring, 3: Integer Ring} - sage: CartanType(["BC", 3, 2]).translation_factors().map(parent) + sage: CartanType(["BC", 3, 2]).translation_factors().map(parent) # needs sage.graphs Finite family {0: Integer Ring, 1: Integer Ring, 2: Integer Ring, 3: Rational Field} REFERENCES: @@ -2625,7 +2635,7 @@ def dual_coxeter_number(self): def type(self): """ - Returns the type of ``self``. + Return the type of ``self``. EXAMPLES:: @@ -2639,7 +2649,7 @@ def type(self): @cached_method def opposition_automorphism(self): r""" - Returns the opposition automorphism + Return the opposition automorphism The *opposition automorphism* is the automorphism `i \mapsto i^*` of the vertices Dynkin diagram such that, @@ -2651,19 +2661,19 @@ def opposition_automorphism(self): EXAMPLES:: sage: ct = CartanType(['A', 5]) - sage: ct.opposition_automorphism() + sage: ct.opposition_automorphism() # needs sage.libs.gap Finite family {1: 5, 2: 4, 3: 3, 4: 2, 5: 1} sage: ct = CartanType(['D', 4]) - sage: ct.opposition_automorphism() + sage: ct.opposition_automorphism() # needs sage.libs.gap Finite family {1: 1, 2: 2, 3: 3, 4: 4} sage: ct = CartanType(['D', 5]) - sage: ct.opposition_automorphism() + sage: ct.opposition_automorphism() # needs sage.libs.gap Finite family {1: 1, 2: 2, 3: 3, 4: 5, 5: 4} sage: ct = CartanType(['C', 4]) - sage: ct.opposition_automorphism() + sage: ct.opposition_automorphism() # needs sage.libs.gap Finite family {1: 1, 2: 2, 3: 3, 4: 4} """ Q = self.root_system().root_lattice() @@ -3083,7 +3093,7 @@ def __setstate__(self, dict): sage: si1 ['A', 4] - sage: si1.dynkin_diagram() + sage: si1.dynkin_diagram() # needs sage.graphs O---O---O---O 1 2 3 4 A4 diff --git a/src/sage/combinat/root_system/coxeter_group.py b/src/sage/combinat/root_system/coxeter_group.py index 8c7e6306508..f33003b35f6 100644 --- a/src/sage/combinat/root_system/coxeter_group.py +++ b/src/sage/combinat/root_system/coxeter_group.py @@ -9,9 +9,11 @@ # https://www.gnu.org/licenses/ # *************************************************************************** -from sage.combinat.root_system.weyl_group import WeylGroup -from sage.combinat.root_system.reflection_group_real import ReflectionGroup from sage.combinat.root_system.cartan_type import CartanType +from sage.misc.lazy_import import lazy_import + +lazy_import('from sage.combinat.root_system.reflection_group_real', 'ReflectionGroup') +lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup') def CoxeterGroup(data, implementation="reflection", base_ring=None, index_set=None): @@ -46,78 +48,75 @@ def CoxeterGroup(data, implementation="reflection", base_ring=None, index_set=No ``implementation`` is not specified, the reflection representation is returned:: - sage: W = CoxeterGroup(["A",2]) - sage: W + sage: W = CoxeterGroup(["A",2]); W # needs sage.libs.gap Finite Coxeter group over Integer Ring with Coxeter matrix: [1 3] [3 1] - sage: W = CoxeterGroup(["A",3,1]); W + sage: W = CoxeterGroup(["A",3,1]); W # needs sage.libs.gap Coxeter group over Integer Ring with Coxeter matrix: [1 3 2 3] [3 1 3 2] [2 3 1 3] [3 2 3 1] - sage: W = CoxeterGroup(['H',3]); W - Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? with Coxeter matrix: + sage: W = CoxeterGroup(['H',3]); W # needs sage.libs.gap + Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 + with a = 2.236067977499790? with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] We now use the ``implementation`` option:: - sage: W = CoxeterGroup(["A",2], implementation = "permutation") # optional - gap3 - sage: W # optional - gap3 + sage: W = CoxeterGroup(["A",2], implementation="permutation"); W # optional - gap3 Permutation Group with generators [(1,4)(2,3)(5,6), (1,3)(2,5)(4,6)] - sage: W.category() # optional - gap3 + sage: W.category() # optional - gap3 Join of Category of finite enumerated permutation groups - and Category of finite weyl groups - and Category of well generated finite irreducible complex reflection groups + and Category of finite weyl groups + and Category of well generated finite irreducible complex reflection groups - sage: W = CoxeterGroup(["A",2], implementation="matrix") - sage: W + sage: W = CoxeterGroup(["A",2], implementation="matrix"); W # needs sage.libs.gap Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) - sage: W = CoxeterGroup(["H",3], implementation="matrix") - sage: W - Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? with Coxeter matrix: + sage: W = CoxeterGroup(["H",3], implementation="matrix"); W # needs sage.libs.gap sage.rings.number_field + Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 + with a = 2.236067977499790? with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] - sage: W = CoxeterGroup(["H",3], implementation="reflection") - sage: W - Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? with Coxeter matrix: + sage: W = CoxeterGroup(["H",3], implementation="reflection"); W # needs sage.rings.number_field + Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 + with a = 2.236067977499790? with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] - sage: W = CoxeterGroup(["A",4,1], implementation="permutation") + sage: W = CoxeterGroup(["A",4,1], implementation="permutation") # needs sage.libs.gap Traceback (most recent call last): ... ValueError: the type must be finite - sage: W = CoxeterGroup(["A",4], implementation="chevie"); W # optional - gap3 + sage: W = CoxeterGroup(["A",4], implementation="chevie"); W # optional - gap3 Irreducible real reflection group of rank 4 and type A4 We use the different options for the "reflection" implementation:: - sage: W = CoxeterGroup(["H",3], implementation="reflection", base_ring=RR) - sage: W + sage: W = CoxeterGroup(["H",3], implementation="reflection", base_ring=RR); W # needs sage.libs.gap Finite Coxeter group over Real Field with 53 bits of precision with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] - sage: W = CoxeterGroup([[1,10],[10,1]], implementation="reflection", index_set=['a','b'], base_ring=SR) - sage: W + sage: W = CoxeterGroup([[1,10],[10,1]], implementation="reflection", # needs sage.symbolics + ....: index_set=['a','b'], base_ring=SR); W Finite Coxeter group over Symbolic Ring with Coxeter matrix: [ 1 10] [10 1] TESTS:: - sage: W = groups.misc.CoxeterGroup(["H",3]) + sage: W = groups.misc.CoxeterGroup(["H",3]) # needs sage.groups """ if implementation not in ["permutation", "matrix", "coxeter3", "reflection", "chevie", None]: raise ValueError("invalid type implementation") diff --git a/src/sage/combinat/root_system/coxeter_matrix.py b/src/sage/combinat/root_system/coxeter_matrix.py index 9ae647552e2..719d23c3409 100644 --- a/src/sage/combinat/root_system/coxeter_matrix.py +++ b/src/sage/combinat/root_system/coxeter_matrix.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs """ Coxeter Matrices """ @@ -22,8 +23,8 @@ from sage.matrix.constructor import matrix from sage.matrix.matrix_space import MatrixSpace from sage.misc.classcall_metaclass import ClasscallMetaclass, typecall +from sage.misc.lazy_import import lazy_import from sage.matrix.matrix_generic_dense import Matrix_generic_dense -from sage.graphs.graph import Graph from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RR @@ -31,6 +32,8 @@ from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.coxeter_type import CoxeterType +lazy_import('sage.graphs.graph', 'Graph') + class CoxeterMatrix(CoxeterType, metaclass=ClasscallMetaclass): r""" diff --git a/src/sage/combinat/root_system/coxeter_type.py b/src/sage/combinat/root_system/coxeter_type.py index cad3482bb17..ef1d4beb922 100644 --- a/src/sage/combinat/root_system/coxeter_type.py +++ b/src/sage/combinat/root_system/coxeter_type.py @@ -245,11 +245,11 @@ def coxeter_matrix(self): EXAMPLES:: - sage: CoxeterType(['A', 3]).coxeter_matrix() + sage: CoxeterType(['A', 3]).coxeter_matrix() # needs sage.graphs [1 3 2] [3 1 3] [2 3 1] - sage: CoxeterType(['A', 3, 1]).coxeter_matrix() + sage: CoxeterType(['A', 3, 1]).coxeter_matrix() # needs sage.graphs [1 3 2 3] [3 1 3 2] [2 3 1 3] @@ -263,9 +263,9 @@ def coxeter_graph(self): EXAMPLES:: - sage: CoxeterType(['A', 3]).coxeter_graph() + sage: CoxeterType(['A', 3]).coxeter_graph() # needs sage.graphs Graph on 3 vertices - sage: CoxeterType(['A', 3, 1]).coxeter_graph() + sage: CoxeterType(['A', 3, 1]).coxeter_graph() # needs sage.graphs Graph on 4 vertices """ @@ -357,6 +357,7 @@ def bilinear_form(self, R=None): EXAMPLES:: + sage: # needs sage.graphs sage.rings.number_field sage: CoxeterType(['A', 2, 1]).bilinear_form() [ 1 -1/2 -1/2] [-1/2 1 -1/2] @@ -479,7 +480,7 @@ def coxeter_matrix(self): EXAMPLES:: sage: C = CoxeterType(['H',3]) - sage: C.coxeter_matrix() + sage: C.coxeter_matrix() # needs sage.graphs [1 3 2] [3 1 5] [2 5 1] @@ -493,7 +494,7 @@ def coxeter_graph(self): EXAMPLES:: sage: C = CoxeterType(['H',3]) - sage: C.coxeter_graph().edges(sort=True) + sage: C.coxeter_graph().edges(sort=True) # needs sage.graphs [(1, 2, 3), (2, 3, 5)] """ return self._cartan_type.coxeter_diagram() diff --git a/src/sage/combinat/root_system/dynkin_diagram.py b/src/sage/combinat/root_system/dynkin_diagram.py index 89826d15d12..7f100b10efc 100644 --- a/src/sage/combinat/root_system/dynkin_diagram.py +++ b/src/sage/combinat/root_system/dynkin_diagram.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs """ Dynkin diagrams @@ -28,10 +29,12 @@ # https://www.gnu.org/licenses/ # **************************************************************************** from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.structure.element import is_Matrix from sage.graphs.digraph import DiGraph from sage.combinat.root_system.cartan_type import CartanType, CartanType_abstract -from sage.combinat.root_system.cartan_matrix import CartanMatrix + +lazy_import('sage.combinat.root_system.cartan_matrix', 'CartanMatrix') def DynkinDiagram(*args, **kwds): diff --git a/src/sage/combinat/root_system/extended_affine_weyl_group.py b/src/sage/combinat/root_system/extended_affine_weyl_group.py index 1fcd553da5a..5594b2d538a 100644 --- a/src/sage/combinat/root_system/extended_affine_weyl_group.py +++ b/src/sage/combinat/root_system/extended_affine_weyl_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap r""" Extended Affine Weyl Groups @@ -55,7 +56,7 @@ def ExtendedAffineWeylGroup(cartan_type, general_linear=None, **print_options): - ``cartan_type`` -- An affine or finite Cartan type (a finite Cartan type is an abbreviation for its untwisted affinization) - - ``general_linear`` -- (default: None) If True and ``cartan_type`` indicates + - ``general_linear`` -- (default: ``None``) If ``True`` and ``cartan_type`` indicates untwisted type A, returns the universal central extension - ``print_options`` -- Special instructions for printing elements (see below) @@ -75,8 +76,8 @@ def ExtendedAffineWeylGroup(cartan_type, general_linear=None, **print_options): Recognized arguments for ``print_options`` are: - - ``print_tuple`` -- True or False (default: False) If True, elements are printed - `(a,b)`, otherwise as `a * b` + - ``print_tuple`` -- ``True`` or ``False`` (default: ``False``) + If ``True``, elements are printed `(a,b)`, otherwise as `a * b` - ``affine`` -- Prefix for simple reflections in the affine Weyl group - ``classical`` -- Prefix for simple reflections in the classical Weyl group - ``translation`` -- Prefix for the translation elements @@ -203,23 +204,37 @@ def ExtendedAffineWeylGroup(cartan_type, general_linear=None, **print_options): sage: type(E) - sage: PW0=E.PW0(); PW0 - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Coweight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + sage: PW0 = E.PW0(); PW0 + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Multiplicative form of Coweight lattice of the Root system of type ['A', 2] + acted upon by Weyl Group of type ['A', 2] + (as a matrix group acting on the coweight lattice) sage: W0P = E.W0P(); W0P - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) acting on Multiplicative form of Coweight lattice of the Root system of type ['A', 2] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + acting on Multiplicative form of Coweight lattice of the Root system of type ['A', 2] sage: PvW0 = E.PvW0(); PvW0 - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Weight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Multiplicative form of Weight lattice of the Root system of type ['A', 2] + acted upon by Weyl Group of type ['A', 2] + (as a matrix group acting on the weight lattice) sage: W0Pv = E.W0Pv(); W0Pv - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) acting on Multiplicative form of Weight lattice of the Root system of type ['A', 2] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) + acting on Multiplicative form of Weight lattice of the Root system of type ['A', 2] sage: WF = E.WF(); WF - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) acted upon by Fundamental group of type ['A', 2, 1] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + acted upon by Fundamental group of type ['A', 2, 1] sage: FW = E.FW(); FW - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Fundamental group of type ['A', 2, 1] acting on Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Fundamental group of type ['A', 2, 1] acting on Weyl Group of type ['A', 2, 1] + (as a matrix group acting on the root lattice) When the realizations are constructed from each other as above, there are built-in coercions between them. :: @@ -330,10 +345,10 @@ def ExtendedAffineWeylGroup(cartan_type, general_linear=None, **print_options): Here is a demonstration of the printing options:: - sage: E = ExtendedAffineWeylGroup(["A",2,1], affine="sx", classical="Sx",translation="x",fundamental="pix") + sage: E = ExtendedAffineWeylGroup(["A",2,1], affine="sx", classical="Sx", + ....: translation="x", fundamental="pix") sage: PW0 = E.PW0() - sage: y = PW0(E.lattice_basis()[1]) - sage: y + sage: y = PW0(E.lattice_basis()[1]); y x[Lambdacheck[1]] sage: FW = E.FW() sage: FW(y) @@ -376,7 +391,9 @@ def ExtendedAffineWeylGroup(cartan_type, general_linear=None, **print_options): of `GL_n`, which is usually identified with the lattice `\ZZ^n` of `n`-tuples of integers:: sage: PW0 = E.PW0(); PW0 - Extended affine Weyl group of GL(3) realized by Semidirect product of Multiplicative form of Ambient space of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) + Extended affine Weyl group of GL(3) realized by Semidirect product of + Multiplicative form of Ambient space of the Root system of type ['A', 2] acted upon + by Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) sage: PW0.an_element() t[(2, 2, 3)] * s1*s2 @@ -395,7 +412,9 @@ def ExtendedAffineWeylGroup(cartan_type, general_linear=None, **print_options): and the indices of the simple reflections are taken modulo `n`:: sage: FW = E.FW(); FW - Extended affine Weyl group of GL(3) realized by Semidirect product of Fundamental group of GL(3) acting on Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + Extended affine Weyl group of GL(3) realized by + Semidirect product of Fundamental group of GL(3) acting on + Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) sage: FW.an_element() pi[5] * S0*S1*S2 @@ -672,7 +691,10 @@ def PW0(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).PW0() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Coweight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by + Semidirect product of Multiplicative form of + Coweight lattice of the Root system of type ['A', 2] acted upon by + Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) """ return self.ExtendedAffineWeylGroupPW0() @@ -683,7 +705,9 @@ def W0P(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).W0P() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) acting on Multiplicative form of Coweight lattice of the Root system of type ['A', 2] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + acting on Multiplicative form of Coweight lattice of the Root system of type ['A', 2] """ return self.ExtendedAffineWeylGroupW0P() @@ -694,7 +718,9 @@ def WF(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).WF() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) acted upon by Fundamental group of type ['A', 2, 1] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + acted upon by Fundamental group of type ['A', 2, 1] """ return self.ExtendedAffineWeylGroupWF() @@ -705,7 +731,9 @@ def FW(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).FW() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Fundamental group of type ['A', 2, 1] acting on Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Fundamental group of type ['A', 2, 1] acting on + Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) """ return self.ExtendedAffineWeylGroupFW() @@ -716,7 +744,9 @@ def PvW0(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).PvW0() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Weight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Multiplicative form of Weight lattice of the Root system of type ['A', 2] + acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) """ return self.ExtendedAffineWeylGroupPvW0() @@ -727,7 +757,9 @@ def W0Pv(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).W0Pv() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) acting on Multiplicative form of Weight lattice of the Root system of type ['A', 2] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) + acting on Multiplicative form of Weight lattice of the Root system of type ['A', 2] """ return self.ExtendedAffineWeylGroupW0Pv() @@ -782,7 +814,8 @@ def lattice(self): Weight lattice of the Root system of type ['C', 2] sage: ExtendedAffineWeylGroup(CartanType(['A',4,2]).dual()).lattice() Coweight lattice of the Root system of type ['B', 2] - sage: ExtendedAffineWeylGroup(CartanType(['A',2,1]), general_linear=True).lattice() + sage: ExtendedAffineWeylGroup(CartanType(['A',2,1]), + ....: general_linear=True).lattice() Ambient space of the Root system of type ['A', 2] """ @@ -938,7 +971,9 @@ def a_realization(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).a_realization() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Coweight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Multiplicative form of Coweight lattice of the Root system of type ['A', 2] + acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) """ return self.PW0() @@ -1058,9 +1093,15 @@ def from_fundamental(self, x): sage: F = E.fundamental_group() sage: Is = F.special_nodes() sage: [(i, PW0.from_fundamental(F(i))) for i in Is] - [(0, 1), (1, t[Lambdacheck[1]] * s1*s2*s3), (2, t[Lambdacheck[2]] * s2*s3*s1*s2), (3, t[Lambdacheck[3]] * s3*s2*s1)] + [(0, 1), + (1, t[Lambdacheck[1]] * s1*s2*s3), + (2, t[Lambdacheck[2]] * s2*s3*s1*s2), + (3, t[Lambdacheck[3]] * s3*s2*s1)] sage: [(i, E.W0P().from_fundamental((F(i)))) for i in Is] - [(0, 1), (1, s1*s2*s3 * t[-Lambdacheck[3]]), (2, s2*s3*s1*s2 * t[-Lambdacheck[2]]), (3, s3*s2*s1 * t[-Lambdacheck[1]])] + [(0, 1), + (1, s1*s2*s3 * t[-Lambdacheck[3]]), + (2, s2*s3*s1*s2 * t[-Lambdacheck[2]]), + (3, s3*s2*s1 * t[-Lambdacheck[1]])] sage: [(i, E.WF().from_fundamental(F(i))) for i in Is] [(0, 1), (1, pi[1]), (2, pi[2]), (3, pi[3])] @@ -1085,13 +1126,13 @@ def from_translation(self, la): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',2,1]); PW0 = E.PW0() sage: b = E.lattice_basis(); b Finite family {1: Lambdacheck[1], 2: Lambdacheck[2]} - sage: x = PW0.from_translation(2*b[1]-b[2]); x + sage: x = PW0.from_translation(2*b[1] - b[2]); x t[2*Lambdacheck[1] - Lambdacheck[2]] sage: FW = E.FW() - sage: y = FW.from_translation(2*b[1]-b[2]); y + sage: y = FW.from_translation(2*b[1] - b[2]); y S0*S2*S0*S1 sage: FW(x) == y True @@ -1118,10 +1159,10 @@ def from_dual_translation(self, la): sage: E = ExtendedAffineWeylGroup(['A',2,1]); PvW0 = E.PvW0() sage: bv = E.dual_lattice_basis(); bv Finite family {1: Lambda[1], 2: Lambda[2]} - sage: x = PvW0.from_dual_translation(2*bv[1]-bv[2]); x + sage: x = PvW0.from_dual_translation(2*bv[1] - bv[2]); x t[2*Lambda[1] - Lambda[2]] sage: FW = E.FW() - sage: y = FW.from_dual_translation(2*bv[1]-bv[2]); y + sage: y = FW.from_dual_translation(2*bv[1] - bv[2]); y S0*S2*S0*S1 sage: FW(x) == y True @@ -1137,15 +1178,22 @@ def simple_reflections(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',3,1]).W0P().simple_reflections() - Finite family {0: s1*s2*s3*s2*s1 * t[-Lambdacheck[1] - Lambdacheck[3]], 1: s1, 2: s2, 3: s3} + Finite family {0: s1*s2*s3*s2*s1 * t[-Lambdacheck[1] - Lambdacheck[3]], + 1: s1, 2: s2, 3: s3} sage: ExtendedAffineWeylGroup(['A',3,1]).WF().simple_reflections() Finite family {0: S0, 1: S1, 2: S2, 3: S3} - sage: ExtendedAffineWeylGroup(['A',3,1], print_tuple=True).FW().simple_reflections() - Finite family {0: (pi[0], S0), 1: (pi[0], S1), 2: (pi[0], S2), 3: (pi[0], S3)} - sage: ExtendedAffineWeylGroup(['A',3,1],fundamental="f",print_tuple=True).FW().simple_reflections() - Finite family {0: (f[0], S0), 1: (f[0], S1), 2: (f[0], S2), 3: (f[0], S3)} + sage: ExtendedAffineWeylGroup(['A',3,1], + ....: print_tuple=True).FW().simple_reflections() + Finite family {0: (pi[0], S0), 1: (pi[0], S1), + 2: (pi[0], S2), 3: (pi[0], S3)} + sage: ExtendedAffineWeylGroup(['A',3,1], + ....: fundamental="f", + ....: print_tuple=True).FW().simple_reflections() + Finite family {0: (f[0], S0), 1: (f[0], S1), + 2: (f[0], S2), 3: (f[0], S3)} sage: ExtendedAffineWeylGroup(['A',3,1]).PvW0().simple_reflections() - Finite family {0: t[Lambda[1] + Lambda[3]] * s1*s2*s3*s2*s1, 1: s1, 2: s2, 3: s3} + Finite family {0: t[Lambda[1] + Lambda[3]] * s1*s2*s3*s2*s1, + 1: s1, 2: s2, 3: s3} """ def simple_reflection(self, i): @@ -1155,7 +1203,7 @@ def simple_reflection(self, i): INPUT: - ``self`` -- a realization of the extended affine Weyl group - - `i` -- An affine Dynkin node + - ``i`` -- An affine Dynkin node EXAMPLES:: @@ -1240,7 +1288,7 @@ def from_affine_weyl(self, w): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0 = E.PW0() sage: W = E.affine_weyl() sage: w = W.from_reduced_word([2,1,3,0]) sage: x = PW0.from_affine_weyl(w); x @@ -1284,15 +1332,15 @@ def has_descent(self, i, side='right', positive=False): OPTIONAL: - - ``side`` -- 'right' or 'left' (default: 'right') - - ``positive`` -- True or False (default: False) + - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) - If ``side``='left' then the reflection acts - on the left. If ``positive`` = True then the inequality is reversed. + If ``side='left'``, then the reflection acts + on the left. If ``positive=True``, then the inequality is reversed. EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',3,1]); WF=E.WF() + sage: E = ExtendedAffineWeylGroup(['A',3,1]); WF = E.WF() sage: F = E.fundamental_group() sage: x = WF.an_element(); x S0*S1*S2*S3 * pi[3] @@ -1316,11 +1364,11 @@ def first_descent(self, side='right', positive=False, index_set=None): INPUT: - - ``side`` -- 'left' or 'right' (default: 'right') - - ``positive`` -- True or False (default: False) + - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) - ``index_set`` -- an optional subset of Dynkin nodes - If ``index_set`` is not None, then the descent must be in the ``index_set``. + If ``index_set`` is not ``None``, then the descent must be in the ``index_set``. EXAMPLES:: @@ -1370,8 +1418,11 @@ def apply_simple_projection(self, i, side='right', length_increasing=True): - ``self`` -- an element of the extended affine Weyl group - `i` -- a Dynkin node (index of a simple reflection `s_i`) - - ``side`` -- 'right' or 'left' (default: 'right') according to which side of ``self`` the reflection `s_i` should be multiplied - - ``length_increasing`` -- True or False (default True). If False do the above with the word "greater" replaced by "less". + - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``) + according to which side of ``self`` the reflection `s_i` + should be multiplied + - ``length_increasing`` -- ``True`` or ``False`` (default ``True``). + If ``False``, do the above with the word "greater" replaced by "less". EXAMPLES:: @@ -1447,8 +1498,10 @@ def to_affine_weyl_left(self): sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0 = E.PW0() sage: b = E.lattice_basis() - sage: [(x,PW0.from_translation(x).to_affine_weyl_left()) for x in b] - [(Lambdacheck[1], S0*S3*S2), (Lambdacheck[2], S0*S3*S1*S0), (Lambdacheck[3], S0*S1*S2)] + sage: [(x, PW0.from_translation(x).to_affine_weyl_left()) for x in b] + [(Lambdacheck[1], S0*S3*S2), + (Lambdacheck[2], S0*S3*S1*S0), + (Lambdacheck[3], S0*S1*S2)] .. WARNING:: @@ -1464,10 +1517,12 @@ def to_affine_weyl_right(self): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0 = E.PW0() sage: b = E.lattice_basis() - sage: [(x,PW0.from_translation(x).to_affine_weyl_right()) for x in b] - [(Lambdacheck[1], S3*S2*S1), (Lambdacheck[2], S2*S3*S1*S2), (Lambdacheck[3], S1*S2*S3)] + sage: [(x, PW0.from_translation(x).to_affine_weyl_right()) for x in b] + [(Lambdacheck[1], S3*S2*S1), + (Lambdacheck[2], S2*S3*S1*S2), + (Lambdacheck[3], S1*S2*S3)] .. WARNING:: @@ -1550,7 +1605,7 @@ def length(self): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0 = E.PW0() sage: I0 = E.cartan_type().classical().index_set() sage: [PW0.from_translation(E.lattice_basis()[i]).length() for i in I0] [3, 4, 3] @@ -1566,7 +1621,8 @@ def coset_representative(self, index_set, side='right'): - ``self`` -- an element of the extended affine Weyl group - ``index_set`` -- a subset of the set of Dynkin nodes - - ``side`` -- 'right' or 'left' (default: 'right') the side on which the subgroup acts + - ``side`` -- ``'right'`` or ``'left'`` (default: ``'right'``) + the side on which the subgroup acts EXAMPLES:: @@ -1589,7 +1645,7 @@ def is_grassmannian(self, index_set, side='right'): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',3,1]); PW0 = E.PW0() sage: x = PW0.from_translation(E.lattice_basis()[1]); x t[Lambdacheck[1]] sage: I = E.cartan_type().index_set() @@ -1609,7 +1665,8 @@ def to_affine_grassmannian(self): sage: elts = ExtendedAffineWeylGroup(['A',2,1]).PW0().some_elements() sage: [(x, x.to_affine_grassmannian()) for x in elts] - [(t[2*Lambdacheck[1] + 2*Lambdacheck[2]] * s1*s2, t[2*Lambdacheck[1] + 2*Lambdacheck[2]] * s1*s2*s1)] + [(t[2*Lambdacheck[1] + 2*Lambdacheck[2]] * s1*s2, + t[2*Lambdacheck[1] + 2*Lambdacheck[2]] * s1*s2*s1)] """ return self.coset_representative(index_set=self.parent().realization_of().cartan_type().classical().index_set()) @@ -1620,7 +1677,7 @@ def is_affine_grassmannian(self): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',2,1]); PW0 = E.PW0() sage: F = E.fundamental_group() sage: [(x,PW0.from_fundamental(x).is_affine_grassmannian()) for x in F] [(pi[0], True), (pi[1], True), (pi[2], True)] @@ -1642,7 +1699,7 @@ def bruhat_le(self, x): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],print_tuple=True); WF=E.WF() + sage: E = ExtendedAffineWeylGroup(['A',2,1], print_tuple=True); WF = E.WF() sage: W = E.affine_weyl() sage: v = W.from_reduced_word([2,1,0]) sage: w = W.from_reduced_word([2,0,1,0]) @@ -1674,7 +1731,7 @@ def is_translation(self): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1]); FW=E.FW() + sage: E = ExtendedAffineWeylGroup(['A',2,1]); FW = E.FW() sage: F = E.fundamental_group() sage: FW.from_affine_weyl(E.affine_weyl().from_reduced_word([1,2,1,0])).is_translation() True @@ -1693,18 +1750,20 @@ def action(self, la): INPUT: - ``self`` -- an element of the extended affine Weyl group - - ``la`` -- an element of the translation lattice of the extended affine Weyl group, the lattice denoted by the mnemonic "P" in the documentation for :meth:`ExtendedAffineWeylGroup`. + - ``la`` -- an element of the translation lattice of the extended + affine Weyl group, the lattice denoted by the mnemonic "P" in the + documentation for :meth:`ExtendedAffineWeylGroup`. EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],affine="s") + sage: E = ExtendedAffineWeylGroup(['A',2,1], affine="s") sage: x = E.FW().an_element(); x pi[2] * s0*s1*s2 sage: la = E.lattice().an_element(); la 2*Lambdacheck[1] + 2*Lambdacheck[2] sage: x.action(la) 5*Lambdacheck[1] - 3*Lambdacheck[2] - sage: E = ExtendedAffineWeylGroup(['C',2,1],affine="s") + sage: E = ExtendedAffineWeylGroup(['C',2,1], affine="s") sage: x = E.PW0().from_translation(E.lattice_basis()[1]) sage: x.action(E.lattice_basis()[2]) Lambdacheck[1] + Lambdacheck[2] @@ -1723,18 +1782,20 @@ def dual_action(self, la): INPUT: - ``self`` -- an element of the extended affine Weyl group - - ``la`` -- an element of the dual translation lattice of the extended affine Weyl group, the lattice denoted by the mnemonic "Pv" in the documentation for :meth:`ExtendedAffineWeylGroup`. + - ``la`` -- an element of the dual translation lattice of the extended + affine Weyl group, the lattice denoted by the mnemonic "Pv" in + the documentation for :meth:`ExtendedAffineWeylGroup`. EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],affine="s") + sage: E = ExtendedAffineWeylGroup(['A',2,1], affine="s") sage: x = E.FW().an_element(); x pi[2] * s0*s1*s2 sage: la = E.dual_lattice().an_element(); la 2*Lambda[1] + 2*Lambda[2] sage: x.dual_action(la) 5*Lambda[1] - 3*Lambda[2] - sage: E = ExtendedAffineWeylGroup(['C',2,1],affine="s") + sage: E = ExtendedAffineWeylGroup(['C',2,1], affine="s") sage: x = E.PvW0().from_dual_translation(E.dual_lattice_basis()[1]) sage: x.dual_action(E.dual_lattice_basis()[2]) Lambda[1] + Lambda[2] @@ -1775,7 +1836,7 @@ def face_data(self, i): INPUT: - ``self`` -- An element of the extended affine Weyl group - - `i` -- an affine Dynkin node + - ``i`` -- an affine Dynkin node OUTPUT: @@ -1863,12 +1924,12 @@ def has_descent(self, i, side='right', positive=False): INPUT: - - `i` -- an affine Dynkin node + - ``i`` -- an affine Dynkin node OPTIONAL: - - ``side`` -- 'left' or 'right' (default: 'right') - - ``positive`` -- True or False (default: False) + - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) EXAMPLES:: @@ -1905,7 +1966,7 @@ def action(self, la): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1]); PW0=E.PW0() + sage: E = ExtendedAffineWeylGroup(['A',2,1]); PW0 = E.PW0() sage: x = PW0.an_element(); x t[2*Lambdacheck[1] + 2*Lambdacheck[2]] * s1*s2 sage: la = E.lattice().an_element(); la @@ -1952,12 +2013,15 @@ class ExtendedAffineWeylGroupPW0(GroupSemidirectProduct, BindableClass): INPUT: - - `E` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` + - ``E`` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).PW0() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Coweight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Multiplicative form of Coweight lattice of the Root system of type ['A', 2] + acted upon by Weyl Group of type ['A', 2] + (as a matrix group acting on the coweight lattice) """ def __init__(self, E): @@ -1994,7 +2058,8 @@ def from_translation(self, la): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1], translation="tau", print_tuple = True) + sage: E = ExtendedAffineWeylGroup(['A',2,1], translation="tau", + ....: print_tuple=True) sage: la = E.lattice().an_element(); la 2*Lambdacheck[1] + 2*Lambdacheck[2] sage: E.PW0().from_translation(la) @@ -2041,7 +2106,8 @@ def simple_reflections(self): EXAMPLES:: sage: ExtendedAffineWeylGroup("A3").PW0().simple_reflections() - Finite family {0: t[Lambdacheck[1] + Lambdacheck[3]] * s1*s2*s3*s2*s1, 1: s1, 2: s2, 3: s3} + Finite family {0: t[Lambdacheck[1] + Lambdacheck[3]] * s1*s2*s3*s2*s1, + 1: s1, 2: s2, 3: s3} """ return Family(self.realization_of().cartan_type().index_set(), self.simple_reflection) @@ -2068,12 +2134,12 @@ def has_descent(self, i, side='right', positive=False): INPUT: - - `i` - an index. + - ``i`` -- an index. OPTIONAL: - - ``side`` - 'left' or 'right' (default: 'right') - - ``positive`` - True or False (default: False) + - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) EXAMPLES:: @@ -2137,12 +2203,14 @@ class ExtendedAffineWeylGroupW0P(GroupSemidirectProduct, BindableClass): INPUT: - - `E` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` + - ``E`` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).W0P() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) acting on Multiplicative form of Coweight lattice of the Root system of type ['A', 2] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2] (as a matrix group acting on the coweight lattice) + acting on Multiplicative form of Coweight lattice of the Root system of type ['A', 2] """ def __init__(self, E): @@ -2189,7 +2257,8 @@ def simple_reflection(self, i): sage: E = ExtendedAffineWeylGroup(['A',3,1]); W0P = E.W0P() sage: [(i, W0P.simple_reflection(i)) for i in E.cartan_type().index_set()] - [(0, s1*s2*s3*s2*s1 * t[-Lambdacheck[1] - Lambdacheck[3]]), (1, s1), (2, s2), (3, s3)] + [(0, s1*s2*s3*s2*s1 * t[-Lambdacheck[1] - Lambdacheck[3]]), + (1, s1), (2, s2), (3, s3)] """ if i == 0: return self.S0() @@ -2204,7 +2273,8 @@ def simple_reflections(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(["A",3,1]).W0P().simple_reflections() - Finite family {0: s1*s2*s3*s2*s1 * t[-Lambdacheck[1] - Lambdacheck[3]], 1: s1, 2: s2, 3: s3} + Finite family {0: s1*s2*s3*s2*s1 * t[-Lambdacheck[1] - Lambdacheck[3]], + 1: s1, 2: s2, 3: s3} """ return Family(self.realization_of().cartan_type().index_set(), self.simple_reflection) @@ -2243,12 +2313,12 @@ def has_descent(self, i, side='right', positive=False): INPUT: - - `i` -- an affine Dynkin index + - ``i`` -- an affine Dynkin index OPTIONAL: - - ``side`` -- 'left' or 'right' (default: 'right') - - ``positive`` -- True or False (default: False) + - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) EXAMPLES:: @@ -2298,7 +2368,8 @@ def bruhat_le(self, x): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],affine="s", print_tuple=True); WF=E.WF() + sage: E = ExtendedAffineWeylGroup(['A',2,1], affine="s", + ....: print_tuple=True); WF = E.WF() sage: r = E.affine_weyl().from_reduced_word sage: v = r([1,0]) sage: w = r([1,2,0]) @@ -2330,12 +2401,14 @@ class ExtendedAffineWeylGroupWF(GroupSemidirectProduct, BindableClass): INPUT: - - `E` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` + - ``E`` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).WF() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) acted upon by Fundamental group of type ['A', 2, 1] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + acted upon by Fundamental group of type ['A', 2, 1] """ def __init__(self, E): @@ -2368,7 +2441,7 @@ def from_affine_weyl(self, w): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['C',2,1],print_tuple=True) + sage: E = ExtendedAffineWeylGroup(['C',2,1], print_tuple=True) sage: E.WF().from_affine_weyl(E.affine_weyl().from_reduced_word([1,2,1,0])) (S1*S2*S1*S0, pi[0]) """ @@ -2381,7 +2454,7 @@ def simple_reflections(self): EXAMPLES:: - sage: ExtendedAffineWeylGroup(["A",3,1],affine="r").WF().simple_reflections() + sage: ExtendedAffineWeylGroup(["A",3,1], affine="r").WF().simple_reflections() Finite family {0: r0, 1: r1, 2: r2, 3: r3} """ E = self.realization_of() @@ -2396,8 +2469,9 @@ def from_fundamental(self, f): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['E',6,1],print_tuple=True); WF = E.WF(); F = E.fundamental_group() - sage: [(x,WF.from_fundamental(x)) for x in F] + sage: E = ExtendedAffineWeylGroup(['E',6,1], print_tuple=True); WF = E.WF() + sage: F = E.fundamental_group() + sage: [(x, WF.from_fundamental(x)) for x in F] [(pi[0], (1, pi[0])), (pi[1], (1, pi[1])), (pi[6], (1, pi[6]))] """ return self((self.cartesian_factors()[0].one(),f)) @@ -2417,8 +2491,8 @@ def has_descent(self, i, side='right', positive=False): OPTIONAL: - - ``side`` -- 'left' or 'right' (default: 'right') - - ``positive`` -- True or False (default: False) + - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) EXAMPLES:: @@ -2468,7 +2542,7 @@ def action_on_affine_roots(self, beta): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],affine="s") + sage: E = ExtendedAffineWeylGroup(['A',2,1], affine="s") sage: x = E.FW().an_element(); x pi[2] * s0*s1*s2 sage: v = RootSystem(['A',2,1]).root_lattice().an_element(); v @@ -2487,12 +2561,14 @@ class ExtendedAffineWeylGroupFW(GroupSemidirectProduct, BindableClass): INPUT: - - `E` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` + - ``E`` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).FW() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Fundamental group of type ['A', 2, 1] acting on Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Fundamental group of type ['A', 2, 1] acting on Weyl Group of type ['A', 2, 1] + (as a matrix group acting on the root lattice) """ def __init__(self, E): @@ -2541,7 +2617,7 @@ def from_affine_weyl(self, w): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],print_tuple=True) + sage: E = ExtendedAffineWeylGroup(['A',2,1], print_tuple=True) sage: E.FW().from_affine_weyl(E.affine_weyl().from_reduced_word([0,2,1])) (pi[0], S0*S2*S1) """ @@ -2554,7 +2630,7 @@ def from_fundamental(self, f): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1],print_tuple=True) + sage: E = ExtendedAffineWeylGroup(['A',2,1], print_tuple=True) sage: E.FW().from_fundamental(E.fundamental_group()(2)) (pi[2], 1) """ @@ -2571,12 +2647,12 @@ def has_descent(self, i, side='right', positive=False): INPUT: - - `i` - an affine Dynkin index + - ``i`` - an affine Dynkin index OPTIONAL: - - ``side`` -- 'left' or 'right' (default: 'right') - - ``positive`` -- True or False (default: False) + - ``side`` -- ``'left'`` or ``'right'`` (default: ``'right'``) + - ``positive`` -- ``True`` or ``False`` (default: ``False``) EXAMPLES:: @@ -2657,12 +2733,14 @@ class ExtendedAffineWeylGroupPvW0(GroupSemidirectProduct, BindableClass): INPUT: - - `E` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` + - ``E`` -- A parent with realization in :class:`ExtendedAffineWeylGroup_Class` EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).PvW0() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Multiplicative form of Weight lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Multiplicative form of Weight lattice of the Root system of type ['A', 2] acted + upon by Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) """ def __init__(self, E): @@ -2698,7 +2776,8 @@ def from_dual_translation(self, la): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1], translation="tau", print_tuple = True) + sage: E = ExtendedAffineWeylGroup(['A',2,1], translation="tau", + ....: print_tuple=True) sage: la = E.dual_lattice().an_element(); la 2*Lambda[1] + 2*Lambda[2] sage: E.PvW0().from_dual_translation(la) @@ -2715,7 +2794,8 @@ def simple_reflections(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',3,1]).PvW0().simple_reflections() - Finite family {0: t[Lambda[1] + Lambda[3]] * s1*s2*s3*s2*s1, 1: s1, 2: s2, 3: s3} + Finite family {0: t[Lambda[1] + Lambda[3]] * s1*s2*s3*s2*s1, + 1: s1, 2: s2, 3: s3} """ E = self.realization_of() return Family(E.cartan_type().index_set(), lambda i: self(E.PW0().simple_reflection(i))) @@ -2726,8 +2806,9 @@ def from_dual_classical_weyl(self, w): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',3,1],print_tuple=True) - sage: E.PvW0().from_dual_classical_weyl(E.dual_classical_weyl().from_reduced_word([1,2])) + sage: E = ExtendedAffineWeylGroup(['A',3,1], print_tuple=True) + sage: E.PvW0().from_dual_classical_weyl( + ....: E.dual_classical_weyl().from_reduced_word([1,2])) (t[0], s1*s2) """ return self((self.cartesian_factors()[0].one(),w)) @@ -2829,7 +2910,9 @@ class ExtendedAffineWeylGroupW0Pv(GroupSemidirectProduct, BindableClass): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',2,1]).W0Pv() - Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) acting on Multiplicative form of Weight lattice of the Root system of type ['A', 2] + Extended affine Weyl group of type ['A', 2, 1] realized by Semidirect product of + Weyl Group of type ['A', 2] (as a matrix group acting on the weight lattice) + acting on Multiplicative form of Weight lattice of the Root system of type ['A', 2] """ def __init__(self, E): @@ -2864,7 +2947,8 @@ def from_dual_translation(self, la): EXAMPLES:: - sage: E = ExtendedAffineWeylGroup(['A',2,1], translation="tau", print_tuple = True) + sage: E = ExtendedAffineWeylGroup(['A',2,1], translation="tau", + ....: print_tuple=True) sage: la = E.dual_lattice().an_element(); la 2*Lambda[1] + 2*Lambda[2] sage: E.W0Pv().from_dual_translation(la) @@ -2881,7 +2965,8 @@ def simple_reflections(self): EXAMPLES:: sage: ExtendedAffineWeylGroup(['A',3,1]).W0Pv().simple_reflections() - Finite family {0: s1*s2*s3*s2*s1 * t[-Lambda[1] - Lambda[3]], 1: s1, 2: s2, 3: s3} + Finite family {0: s1*s2*s3*s2*s1 * t[-Lambda[1] - Lambda[3]], + 1: s1, 2: s2, 3: s3} """ E = self.realization_of() return Family(E.cartan_type().index_set(), lambda i: self(E.PW0().simple_reflection(i))) diff --git a/src/sage/combinat/root_system/fundamental_group.py b/src/sage/combinat/root_system/fundamental_group.py index f42acd0a44a..65426b786e3 100644 --- a/src/sage/combinat/root_system/fundamental_group.py +++ b/src/sage/combinat/root_system/fundamental_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs r""" Fundamental Group of an Extended Affine Weyl Group @@ -324,6 +325,21 @@ def act_on_affine_lattice(self, wt): """ return wt.map_support(self.parent().action(self.value())) + def __hash__(self): + r""" + Return the hash of ``self``. + + TESTS: + + Check that :issue:`36121` is fixed:: + + sage: W = ExtendedAffineWeylGroup('A4') + sage: fun = W.fundamental_group().an_element() + sage: hash(fun) == hash(fun.value()) + True + """ + return hash(self.value()) + class FundamentalGroupOfExtendedAffineWeylGroup_Class(UniqueRepresentation, Parent): diff --git a/src/sage/combinat/root_system/hecke_algebra_representation.py b/src/sage/combinat/root_system/hecke_algebra_representation.py index 8de4bce6107..d3fd598e0d6 100644 --- a/src/sage/combinat/root_system/hecke_algebra_representation.py +++ b/src/sage/combinat/root_system/hecke_algebra_representation.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap sage.groups r""" Hecke algebra representations """ @@ -167,7 +168,8 @@ def domain(self): sage: H = WeylGroup(["A",3]).algebra(QQ).demazure_lusztig_operators(-1,1) sage: H.domain() - Algebra of Weyl Group of type ['A', 3] (as a matrix group acting on the ambient space) over Rational Field + Algebra of Weyl Group of type ['A', 3] (as a matrix group + acting on the ambient space) over Rational Field """ return self._domain @@ -428,7 +430,8 @@ def Tw_inverse(self, word): sage: x = KW.monomial(W.an_element()); x 123 sage: rho.Tw_inverse(word)(x) - 1/q2^2*12321 + ((-q1-q2)/(q1*q2^2))*1231 + ((-q1-q2)/(q1*q2^2))*1232 + ((q1^2+2*q1*q2+q2^2)/(q1^2*q2^2))*123 + 1/q2^2*12321 + ((-q1-q2)/(q1*q2^2))*1231 + ((-q1-q2)/(q1*q2^2))*1232 + + ((q1^2+2*q1*q2+q2^2)/(q1^2*q2^2))*123 sage: rho.Tw(word)(_) 123 """ @@ -464,26 +467,30 @@ def _test_relations(self, **options): def Ti(x,i,c): return T[i](x)+c*x - # Check the quadratic relation - for i in cartan_type.index_set(): - for x in elements: - tester.assertTrue(Ti(Ti(x,i,-q2),i,-q1).is_zero()) - G = cartan_type.coxeter_diagram() - # Check the braid relation - for (i, j) in Subsets(cartan_type.index_set(), 2): - if G.has_edge(i,j): - o = G.edge_label(i,j) - else: - o = 2 - if o == infinity: - continue - for x in elements: - y = x - for k in range(o): - x = T[i](x) - y = T[j](y) - y,x = x,y - tester.assertEqual(x, y) + + try: + # Check the quadratic relation + for i in cartan_type.index_set(): + for x in elements: + tester.assertTrue(Ti(Ti(x,i,-q2),i,-q1).is_zero()) + G = cartan_type.coxeter_diagram() + # Check the braid relation + for (i, j) in Subsets(cartan_type.index_set(), 2): + if G.has_edge(i,j): + o = G.edge_label(i,j) + else: + o = 2 + if o == infinity: + continue + for x in elements: + y = x + for k in range(o): + x = T[i](x) + y = T[j](y) + y,x = x,y + tester.assertEqual(x, y) + except ImportError: + pass def _test_inverse(self, **options): r""" @@ -502,14 +509,17 @@ def _test_inverse(self, **options): elements = self.domain().some_elements() q1 = self._q1 q2 = self._q2 - if q1.is_unit() and q2.is_unit(): - I = self.cartan_type().index_set() - for w in [[i] for i in I] + [tuple(I)]: - Tw = self.Tw(w) - Tw_inverse = self.Tw_inverse(w) - for x in elements: - tester.assertEqual(Tw_inverse(Tw(x)), x) - tester.assertEqual(Tw(Tw_inverse(x)), x) + try: + if q1.is_unit() and q2.is_unit(): + I = self.cartan_type().index_set() + for w in [[i] for i in I] + [tuple(I)]: + Tw = self.Tw(w) + Tw_inverse = self.Tw_inverse(w) + for x in elements: + tester.assertEqual(Tw_inverse(Tw(x)), x) + tester.assertEqual(Tw(Tw_inverse(x)), x) + except ImportError: + pass def Y_lambdacheck(self, lambdacheck): r""" @@ -540,9 +550,12 @@ def Y_lambdacheck(self, lambdacheck): sage: x = KW.monomial(W.an_element()); x 12 sage: Y1(x) - ((-q1^2-2*q1*q2-q2^2)/(-q2^2))*2121 + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1*q2^2))*121 + ((q1^2+q1*q2)/(-q2^2))*212 + ((-q1^2)/(-q2^2))*12 + ((-q1^2-2*q1*q2-q2^2)/(-q2^2))*2121 + + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1*q2^2))*121 + + ((q1^2+q1*q2)/(-q2^2))*212 + ((-q1^2)/(-q2^2))*12 sage: Y2(x) - ((-q1^4-q1^3*q2-q1*q2^3-q2^4)/(-q1^3*q2))*2121 + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1^2*q2))*121 + (q2^3/(-q1^3))*12 + ((-q1^4-q1^3*q2-q1*q2^3-q2^4)/(-q1^3*q2))*2121 + + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1^2*q2))*121 + (q2^3/(-q1^3))*12 sage: Y1(Y2(x)) ((q1*q2+q2^2)/q1^2)*212 + ((-q2)/q1)*12 sage: Y2(Y1(x)) @@ -742,9 +755,11 @@ def Y_eigenvectors(self): sage: [E[w] for w in W] [2121 - 121 - 212 + 12 + 21 - 1 - 2 + , -2121 + 212, - (q2/(q1-q2))*2121 + (q2/(-q1+q2))*121 + (q2/(-q1+q2))*212 - 12 + ((-q2)/(-q1+q2))*21 + 2, + (q2/(q1-q2))*2121 + (q2/(-q1+q2))*121 + + (q2/(-q1+q2))*212 - 12 + ((-q2)/(-q1+q2))*21 + 2, ((-q2^2)/(-q1^2+q1*q2-q2^2))*2121 - 121 + (q2^2/(-q1^2+q1*q2-q2^2))*212 + 21, - ((-q1^2-q2^2)/(q1^2-q1*q2+q2^2))*2121 + ((-q1^2-q2^2)/(-q1^2+q1*q2-q2^2))*121 + ((-q2^2)/(-q1^2+q1*q2-q2^2))*212 + (q2^2/(-q1^2+q1*q2-q2^2))*12 - 21 + 1, + ((-q1^2-q2^2)/(q1^2-q1*q2+q2^2))*2121 + ((-q1^2-q2^2)/(-q1^2+q1*q2-q2^2))*121 + + ((-q2^2)/(-q1^2+q1*q2-q2^2))*212 + (q2^2/(-q1^2+q1*q2-q2^2))*12 - 21 + 1, 2121, (q2/(-q1+q2))*2121 + ((-q2)/(-q1+q2))*121 - 212 + 12, -2121 + 121] @@ -830,7 +845,8 @@ def __init__(self, T, T_Y=None, normalized=True): sage: E.keys() Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space) sage: E.domain() - Algebra of Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space) over Fraction Field of Multivariate Polynomial Ring in q1, q2 over Rational Field + Algebra of Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space) + over Fraction Field of Multivariate Polynomial Ring in q1, q2 over Rational Field sage: E._T == E._T_Y True """ @@ -855,7 +871,7 @@ def cartan_type(self): sage: E.cartan_type() ['B', 3, 1] - sage: NonSymmetricMacdonaldPolynomials(["B", 2, 1]).cartan_type() + sage: NonSymmetricMacdonaldPolynomials(["B", 2, 1]).cartan_type() # needs sage.graphs ['B', 2, 1] """ return self._T_Y.cartan_type() @@ -872,7 +888,9 @@ def domain(self): sage: KW = W.algebra(K) sage: E = KW.demazure_lusztig_eigenvectors(q1, q2) sage: E.domain() - Algebra of Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space) over Multivariate Polynomial Ring in q1, q2 over Rational Field + Algebra of Weyl Group of type ['B', 3] + (as a matrix group acting on the ambient space) + over Multivariate Polynomial Ring in q1, q2 over Rational Field """ return self._T.domain() diff --git a/src/sage/combinat/root_system/integrable_representations.py b/src/sage/combinat/root_system/integrable_representations.py index 687a3b7abf7..0278617a2e5 100644 --- a/src/sage/combinat/root_system/integrable_representations.py +++ b/src/sage/combinat/root_system/integrable_representations.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs sage.modules """ Integrable Representations of Affine Lie Algebras """ diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py index a7cad09cdb5..a29b26fdde3 100644 --- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs r""" Nonsymmetric Macdonald polynomials @@ -72,7 +73,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): `[2,0,1]`:: sage: E[L0([2,0,1])] - ((-q*q1-q*q2)/(-q*q1-q2))*B[(1, 1, 1)] + ((-q1-q2)/(-q*q1-q2))*B[(2, 1, 0)] + B[(2, 0, 1)] + ((-q*q1-q*q2)/(-q*q1-q2))*B[(1, 1, 1)] + + ((-q1-q2)/(-q*q1-q2))*B[(2, 1, 0)] + B[(2, 0, 1)] It can be seen as a polynomial (or in general a Laurent polynomial) by interpreting each term as an exponent vector. The @@ -93,8 +95,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E[L0([2,0,1])].expand(vars) (t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2 - sage: from sage.combinat.sf.ns_macdonald import E - sage: E([2,0,1]) + sage: from sage.combinat.sf.ns_macdonald import E # needs sage.combinat + sage: E([2,0,1]) # needs sage.combinat sage.groups (t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2 Here is a type `G_2^{(1)}` nonsymmetric Macdonald polynomial:: @@ -103,7 +105,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: L0 = E.keys() sage: omega = L0.fundamental_weights() sage: E[ omega[2]-omega[1] ] - ((-q*q1^3*q2-q*q1^2*q2^2)/(q*q1^4-q2^4))*B[(0, 0, 0)] + B[(1, -1, 0)] + ((-q1*q2^3-q2^4)/(q*q1^4-q2^4))*B[(1, 0, -1)] + ((-q*q1^3*q2-q*q1^2*q2^2)/(q*q1^4-q2^4))*B[(0, 0, 0)] + + B[(1, -1, 0)] + ((-q1*q2^3-q2^4)/(q*q1^4-q2^4))*B[(1, 0, -1)] Many more examples are given after the background section. @@ -119,9 +122,9 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): The nonsymmetric Macdonald polynomials are a distinguished basis of the "polynomial" module of the affine Hecke algebra. Given:: - - a ground ring `K`, which contains the input parameters `q, q_1, q_2` - - an affine root system, specified by a Cartan type `C` - - a realization `L` of the weight lattice of type `C` + - a ground ring `K`, which contains the input parameters `q, q_1, q_2` + - an affine root system, specified by a Cartan type `C` + - a realization `L` of the weight lattice of type `C` the polynomial module is the group algebra `K[L_0]` of the classical weight lattice `L_0` with coefficients in `K`. It is isomorphic to the @@ -139,7 +142,9 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: L.simple_roots() Finite family {0: -2*e[0] + e['delta'], 1: e[0] - e[1], 2: 2*e[1]} sage: omega = L.fundamental_weights(); omega - Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'], 2: e[0] + e[1] + e['deltacheck']} + Finite family {0: e['deltacheck'], + 1: e[0] + e['deltacheck'], + 2: e[0] + e[1] + e['deltacheck']} sage: L0 = L.classical(); L0 Ambient space of the Root system of type ['C', 2] @@ -194,7 +199,9 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): defined by the action of their `T`-generators.:: sage: T - A representation of the (q1, q2)-Hecke algebra of type ['C', 2, 1] on Algebra of the Ambient space of the Root system of type ['C', 2, 1] over Fraction Field of Multivariate Polynomial Ring in q, q1, q2 over Rational Field + A representation of the (q1, q2)-Hecke algebra of type ['C', 2, 1] on + Algebra of the Ambient space of the Root system of type ['C', 2, 1] over + Fraction Field of Multivariate Polynomial Ring in q, q1, q2 over Rational Field sage: type(T) sage: T._test_relations() # long time (1.3s) @@ -283,7 +290,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): having `\mu` as leading term:: sage: E = NonSymmetricMacdonaldPolynomials(KL, q, q1, q2); E - The family of the Macdonald polynomials of type ['C', 2, 1] with parameters q, q1, q2 + The family of the Macdonald polynomials of type ['C', 2, 1] + with parameters q, q1, q2 Or for short:: @@ -368,7 +376,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(['D',3,1], q, u, -1/u) sage: omega = E.keys().fundamental_weights() sage: E[omega[1]+omega[3]] - ((-q*u^2+q)/(-q*u^4+1))*B[(1/2, -1/2, 1/2)] + ((-q*u^2+q)/(-q*u^4+1))*B[(1/2, 1/2, -1/2)] + B[(3/2, 1/2, 1/2)] + ((-q*u^2+q)/(-q*u^4+1))*B[(1/2, -1/2, 1/2)] + + ((-q*u^2+q)/(-q*u^4+1))*B[(1/2, 1/2, -1/2)] + B[(3/2, 1/2, 1/2)] sage: KL = RootSystem(["D",3,1]).ambient_space().algebra(K) sage: P = NonSymmetricMacdonaldPolynomials(KL, q, u, -1/u) @@ -393,6 +402,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(KL,q, q1, q2) sage: omega = E.keys().fundamental_weights() sage: w = omega[1] + + sage: # needs sage.combinat sage.groups sage: import sage.combinat.sf.ns_macdonald as NS sage: p = NS.E([1,0,0]); p x0 @@ -402,6 +413,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: def eig(l): return E.eigenvalues(KL0.from_polynomial(NS.E(l))) + sage: # needs sage.combinat sage.groups sage: eig([1,0,0]) [t, (-1)/(-q*t^2), t] sage: eig([2,0,0]) @@ -421,53 +433,57 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: KL0 = KL.classical() sage: P = K['x0,x1'] sage: def EE(weight): return E[L0(weight)].expand(P.gens()) + + sage: # needs sage.combinat sage: import sage.combinat.sf.ns_macdonald as NS sage: EE([0,0]) 1 - sage: NS.E([0,0]) + sage: NS.E([0,0]) # needs sage.groups 1 sage: EE([1,0]) x0 - sage: NS.E([1,0]) + sage: NS.E([1,0]) # needs sage.groups x0 sage: EE([0,1]) (t - 1)/(q*t - 1)*x0 + x1 - sage: NS.E([0,1]) + sage: NS.E([0,1]) # needs sage.groups (t - 1)/(q*t - 1)*x0 + x1 - - sage: NS.E([2,0]) - x0^2 + (q*t - q)/(q*t - 1)*x0*x1 sage: EE([2,0]) x0^2 + (q*t - q)/(q*t - 1)*x0*x1 + sage: NS.E([2,0]) # needs sage.groups + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 The same, directly in the ambient lattice with several shifts:: - sage: E[L0([2,0])] + sage: E[L0([2,0])] # needs sage.combinat ((-q*t+q)/(-q*t+1))*B[(1, 1)] + B[(2, 0)] - sage: E[L0([1,-1])] + sage: E[L0([1,-1])] # needs sage.combinat ((-q*t+q)/(-q*t+1))*B[(0, 0)] + B[(1, -1)] - sage: E[L0([0,-2])] + sage: E[L0([0,-2])] # needs sage.combinat ((-q*t+q)/(-q*t+1))*B[(-1, -1)] + B[(0, -2)] Systematic checks with Sage's implementation of [HHL06]_:: - sage: assert all(EE([x,y]) == NS.E([x,y]) for d in range(5) for x,y in IntegerVectors(d,2)) + sage: assert all(EE([x,y]) == NS.E([x,y]) # needs sage.combinat + ....: for d in range(5) for x,y in IntegerVectors(d,2)) With the current implementation, we can compute nonsymmetric Macdonald polynomials for any type, for example for type `E_6^{(1)}`:: - sage: K=QQ['q,u'].fraction_field() + sage: K = QQ['q,u'].fraction_field() sage: q, u = K.gens() sage: KL = RootSystem(["E",6,1]).weight_space(extended=True).algebra(K) sage: E = NonSymmetricMacdonaldPolynomials(KL,q,u,-1/u) sage: L0 = E.keys() sage: E[L0.fundamental_weight(1).weyl_action([2,4,3,2,1])] - ((-u^2+1)/(-q*u^16+1))*B[-Lambda[1] + Lambda[3]] + ((-u^2+1)/(-q*u^16+1))*B[Lambda[1]] - + B[-Lambda[2] + Lambda[5]] + ((-u^2+1)/(-q*u^16+1))*B[Lambda[2] - Lambda[4] + Lambda[5]] + ((-u^2+1)/(-q*u^16+1))*B[-Lambda[1] + Lambda[3]] + + ((-u^2+1)/(-q*u^16+1))*B[Lambda[1]] + + B[-Lambda[2] + Lambda[5]] + + ((-u^2+1)/(-q*u^16+1))*B[Lambda[2] - Lambda[4] + Lambda[5]] + ((-u^2+1)/(-q*u^16+1))*B[-Lambda[3] + Lambda[4]] - sage: E[L0.fundamental_weight(2).weyl_action([2,5,3,4,2])] # long time (6s) + sage: E[L0.fundamental_weight(2).weyl_action([2,5,3,4,2])] # long time (6s) ((-q^2*u^20+q^2*u^18+q*u^2-q)/(-q^2*u^32+2*q*u^16-1))*B[0] + B[Lambda[1] - Lambda[3] + Lambda[4] - Lambda[5] + Lambda[6]] + ((-u^2+1)/(-q*u^16+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] @@ -475,45 +491,50 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): + ((-q*u^20+q*u^18+u^2-1)/(-q^2*u^32+2*q*u^16-1))*B[Lambda[2]] + ((u^4-2*u^2+1)/(q^2*u^32-2*q*u^16+1))*B[Lambda[3] - Lambda[4] + Lambda[5]] + ((-u^2+1)/(-q*u^16+1))*B[Lambda[3] - Lambda[5] + Lambda[6]] - - sage: E[L0.fundamental_weight(1)+L0.fundamental_weight(6)] # long time (13s) + sage: E[L0.fundamental_weight(1)+L0.fundamental_weight(6)] # long time (13s) ((q^2*u^10-q^2*u^8-q^2*u^2+q^2)/(q^2*u^26-q*u^16-q*u^10+1))*B[0] + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[2] + Lambda[6]] + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] + Lambda[2] - Lambda[4] + Lambda[6]] + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[4] - Lambda[5] + Lambda[6]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] + B[Lambda[1] + Lambda[6]] - + ((-q*u^2+q)/(-q*u^10+1))*B[-Lambda[2] + Lambda[4]] + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[2]] + + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] + + B[Lambda[1] + Lambda[6]] + + ((-q*u^2+q)/(-q*u^10+1))*B[-Lambda[2] + Lambda[4]] + + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[2]] + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[3] - Lambda[4] + Lambda[5]] + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[3] - Lambda[5] + Lambda[6]] We test various other types:: - sage: K=QQ['q,u'].fraction_field() + sage: K = QQ['q,u'].fraction_field() sage: q, u = K.gens() sage: KL = RootSystem(["A",5,2]).ambient_space().algebra(K) sage: E = NonSymmetricMacdonaldPolynomials(KL, q, u, -1/u) sage: L0 = E.keys() sage: E[L0.fundamental_weight(2)] ((-q*u^2+q)/(-q*u^8+1))*B[(0, 0, 0)] + B[(1, 1, 0)] - sage: E[L0((0,-1,1))] # long time (1.5s) + sage: E[L0((0,-1,1))] # long time (1.5s) ((-q^2*u^10+q^2*u^8-q*u^6+q*u^4+q*u^2+u^2-q-1)/(-q^3*u^12+q^2*u^8+q*u^4-1))*B[(0, 0, 0)] + ((-u^2+1)/(-q*u^4+1))*B[(1, -1, 0)] + ((u^6-u^4-u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 1, 0)] + ((u^4-2*u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 0, -1)] - + ((q^2*u^12-q^2*u^10-u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 0, 1)] + B[(0, -1, 1)] + + ((q^2*u^12-q^2*u^10-u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 0, 1)] + + B[(0, -1, 1)] + ((-u^2+1)/(-q^2*u^8+1))*B[(0, 1, -1)] + ((-u^2+1)/(-q^2*u^8+1))*B[(0, 1, 1)] - - sage: K=QQ['q,u'].fraction_field() + sage: K = QQ['q,u'].fraction_field() sage: q, u = K.gens() sage: KL = RootSystem(["E",6,2]).ambient_space().algebra(K) sage: E = NonSymmetricMacdonaldPolynomials(KL,q,u,-1/u) sage: L0 = E.keys() - sage: E[L0.fundamental_weight(4)] # long time (5s) + sage: E[L0.fundamental_weight(4)] # long time (5s) ((-q^3*u^20+q^3*u^18+q^2*u^2-q^2)/(-q^3*u^28+q^2*u^22+q*u^6-1))*B[(0, 0, 0, 0)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, -1/2)] + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, 1/2)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, -1/2)] + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, 1/2)] - + ((q*u^2-q)/(q*u^6-1))*B[(1, 0, 0, 0)] + B[(1, 1, 0, 0)] + ((-q*u^2+q)/(-q*u^6+1))*B[(0, 1, 0, 0)] - sage: E[L0((1,-1,0,0))] # long time (23s) + + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, -1/2)] + + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, 1/2)] + + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, -1/2)] + + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, 1/2)] + + ((q*u^2-q)/(q*u^6-1))*B[(1, 0, 0, 0)] + + B[(1, 1, 0, 0)] + + ((-q*u^2+q)/(-q*u^6+1))*B[(0, 1, 0, 0)] + sage: E[L0((1,-1,0,0))] # long time (23s) ((q^3*u^18-q^3*u^16+q*u^4-q^2*u^2-2*q*u^2+q^2+q)/(q^3*u^18-q^2*u^12-q*u^6+1))*B[(0, 0, 0, 0)] + ((-q^3*u^18+q^3*u^16+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, -1/2, -1/2, -1/2)] + ((-q^3*u^18+q^3*u^16+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, -1/2, -1/2, 1/2)] @@ -524,9 +545,12 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): + ((-q*u^8+q*u^6+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, 1/2, 1/2, -1/2)] + ((-q*u^8+q*u^6+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, 1/2, 1/2, 1/2)] + ((-q^2*u^18+q^2*u^16-q*u^8+q*u^6+q*u^2+u^2-q-1)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1, 0, 0, 0)] - + B[(1, -1, 0, 0)] + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 1, 0, 0)] + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, -1, 0)] - + ((u^2-1)/(q^2*u^12-1))*B[(1, 0, 1, 0)] + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, 0, -1)] - + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, 0, 1)] + ((-q*u^2+q)/(-q*u^6+1))*B[(0, -1, 0, 0)] + + B[(1, -1, 0, 0)] + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 1, 0, 0)] + + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, -1, 0)] + + ((u^2-1)/(q^2*u^12-1))*B[(1, 0, 1, 0)] + + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, 0, -1)] + + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, 0, 1)] + + ((-q*u^2+q)/(-q*u^6+1))*B[(0, -1, 0, 0)] + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 1, 0, 0)] + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, -1, 0)] + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 1, 0)] @@ -543,29 +567,50 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): B[(1, 0, 0)] sage: E[-omega[1]] - B[(-1, 0, 0)] + ((q*q1^6+q*q1^5*q2+q1*q2^5+q2^6)/(q^3*q1^6+q^2*q1^5*q2+q*q1*q2^5+q2^6))*B[(1, 0, 0)] + ((q1+q2)/(q*q1+q2))*B[(0, -1, 0)] + ((q1+q2)/(q*q1+q2))*B[(0, 1, 0)] + ((q1+q2)/(q*q1+q2))*B[(0, 0, -1)] + ((q1+q2)/(q*q1+q2))*B[(0, 0, 1)] + B[(-1, 0, 0)] + + ((q*q1^6+q*q1^5*q2+q1*q2^5+q2^6)/(q^3*q1^6+q^2*q1^5*q2+q*q1*q2^5+q2^6))*B[(1, 0, 0)] + + ((q1+q2)/(q*q1+q2))*B[(0, -1, 0)] + ((q1+q2)/(q*q1+q2))*B[(0, 1, 0)] + + ((q1+q2)/(q*q1+q2))*B[(0, 0, -1)] + ((q1+q2)/(q*q1+q2))*B[(0, 0, 1)] sage: E[omega[2]] ((-q1*q2^3-q2^4)/(q*q1^4-q2^4))*B[(1, 0, 0)] + B[(0, 1, 0)] sage: E[-omega[2]] - ((q^2*q1^7+q^2*q1^6*q2-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(1, 0, 0)] + B[(0, -1, 0)] + ((q^2*q1^7+q^2*q1^6*q2-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(1, 0, 0)] + + B[(0, -1, 0)] + ((q*q1^5*q2^2+q*q1^4*q2^3-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(0, 1, 0)] - + ((-q1*q2-q2^2)/(q*q1^2-q2^2))*B[(0, 0, -1)] + ((q1*q2+q2^2)/(-q*q1^2+q2^2))*B[(0, 0, 1)] + + ((-q1*q2-q2^2)/(q*q1^2-q2^2))*B[(0, 0, -1)] + + ((q1*q2+q2^2)/(-q*q1^2+q2^2))*B[(0, 0, 1)] sage: E[-omega[1]-omega[2]] - ((q^3*q1^6+q^3*q1^5*q2+2*q^2*q1^6+3*q^2*q1^5*q2-q^2*q1^4*q2^2-2*q^2*q1^3*q2^3-q*q1^5*q2-2*q*q1^4*q2^2+q*q1^3*q2^3+2*q*q1^2*q2^4-q*q1*q2^5-q*q2^6+q1^3*q2^3+q1^2*q2^4-2*q1*q2^5-2*q2^6)/(q^4*q1^6+q^3*q1^5*q2-q^3*q1^4*q2^2+q*q1^2*q2^4-q*q1*q2^5-q2^6))*B[(0, 0, 0)] + B[(-1, -1, 0)] + ((q*q1^4+q*q1^3*q2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(-1, 1, 0)] + ((q1+q2)/(q*q1+q2))*B[(-1, 0, -1)] + ((-q1-q2)/(-q*q1-q2))*B[(-1, 0, 1)] + ((q*q1^4+q*q1^3*q2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, -1, 0)] + ((q^2*q1^6+q^2*q1^5*q2+q*q1^5*q2-q*q1^3*q2^3-q1^5*q2-q1^4*q2^2+q1^3*q2^3+q1^2*q2^4-q1*q2^5-q2^6)/(q^4*q1^6+q^3*q1^5*q2-q^3*q1^4*q2^2+q*q1^2*q2^4-q*q1*q2^5-q2^6))*B[(1, 1, 0)] + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, 0, -1)] + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, 0, 1)] + ((q1+q2)/(q*q1+q2))*B[(0, -1, -1)] + ((q1+q2)/(q*q1+q2))*B[(0, -1, 1)] + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(0, 1, -1)] + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(0, 1, 1)] + ((q^3*q1^6+q^3*q1^5*q2+2*q^2*q1^6+3*q^2*q1^5*q2-q^2*q1^4*q2^2-2*q^2*q1^3*q2^3-q*q1^5*q2-2*q*q1^4*q2^2+q*q1^3*q2^3+2*q*q1^2*q2^4-q*q1*q2^5-q*q2^6+q1^3*q2^3+q1^2*q2^4-2*q1*q2^5-2*q2^6)/(q^4*q1^6+q^3*q1^5*q2-q^3*q1^4*q2^2+q*q1^2*q2^4-q*q1*q2^5-q2^6))*B[(0, 0, 0)] + + B[(-1, -1, 0)] + + ((q*q1^4+q*q1^3*q2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(-1, 1, 0)] + + ((q1+q2)/(q*q1+q2))*B[(-1, 0, -1)] + + ((-q1-q2)/(-q*q1-q2))*B[(-1, 0, 1)] + + ((q*q1^4+q*q1^3*q2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, -1, 0)] + + ((q^2*q1^6+q^2*q1^5*q2+q*q1^5*q2-q*q1^3*q2^3-q1^5*q2-q1^4*q2^2+q1^3*q2^3+q1^2*q2^4-q1*q2^5-q2^6)/(q^4*q1^6+q^3*q1^5*q2-q^3*q1^4*q2^2+q*q1^2*q2^4-q*q1*q2^5-q2^6))*B[(1, 1, 0)] + + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, 0, -1)] + + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, 0, 1)] + + ((q1+q2)/(q*q1+q2))*B[(0, -1, -1)] + + ((q1+q2)/(q*q1+q2))*B[(0, -1, 1)] + + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(0, 1, -1)] + + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(0, 1, 1)] sage: E[omega[1]-omega[2]] - ((q^3*q1^7+q^3*q1^6*q2-q*q1*q2^6-q*q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(0, 0, 0)] + B[(1, -1, 0)] - + ((q*q1^5*q2^2+q*q1^4*q2^3-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(1, 1, 0)] + ((-q1*q2-q2^2)/(q*q1^2-q2^2))*B[(1, 0, -1)] + ((q^3*q1^7+q^3*q1^6*q2-q*q1*q2^6-q*q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(0, 0, 0)] + + B[(1, -1, 0)] + + ((q*q1^5*q2^2+q*q1^4*q2^3-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(1, 1, 0)] + + ((-q1*q2-q2^2)/(q*q1^2-q2^2))*B[(1, 0, -1)] + ((q1*q2+q2^2)/(-q*q1^2+q2^2))*B[(1, 0, 1)] sage: E[omega[3]] - ((-q1*q2^2-q2^3)/(-q*q1^3-q2^3))*B[(1, 0, 0)] + ((-q1*q2^2-q2^3)/(-q*q1^3-q2^3))*B[(0, 1, 0)] + B[(0, 0, 1)] + ((-q1*q2^2-q2^3)/(-q*q1^3-q2^3))*B[(1, 0, 0)] + + ((-q1*q2^2-q2^3)/(-q*q1^3-q2^3))*B[(0, 1, 0)] + B[(0, 0, 1)] sage: E[-omega[3]] - ((q*q1^4*q2+q*q1^3*q2^2-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(1, 0, 0)] + ((q*q1^4*q2+q*q1^3*q2^2-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(0, 1, 0)] + ((q*q1^4*q2+q*q1^3*q2^2-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(1, 0, 0)] + + ((q*q1^4*q2+q*q1^3*q2^2-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(0, 1, 0)] + B[(0, 0, -1)] + ((-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(0, 0, 1)] .. RUBRIC:: Comparison with the energy function of crystals @@ -580,19 +625,20 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: KL = RootSystem(["A",5,2]).ambient_space().algebra(K) sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() - sage: E[-omega[1]].map_coefficients(lambda x:x.subs(t=0)) - B[(-1, 0, 0)] + B[(1, 0, 0)] + B[(0, -1, 0)] + B[(0, 1, 0)] + B[(0, 0, -1)] + B[(0, 0, 1)] - sage: E[-omega[2]].map_coefficients(lambda x:x.subs(t=0)) # long time (3s) + sage: E[-omega[1]].map_coefficients(lambda x: x.subs(t=0)) + B[(-1, 0, 0)] + B[(1, 0, 0)] + B[(0, -1, 0)] + B[(0, 1, 0)] + + B[(0, 0, -1)] + B[(0, 0, 1)] + sage: E[-omega[2]].map_coefficients(lambda x: x.subs(t=0)) # long time (3s) (q+2)*B[(0, 0, 0)] + B[(-1, -1, 0)] + B[(-1, 1, 0)] + B[(-1, 0, -1)] - + B[(-1, 0, 1)] + B[(1, -1, 0)] + B[(1, 1, 0)] + B[(1, 0, -1)] + B[(1, 0, 1)] - + B[(0, -1, -1)] + B[(0, -1, 1)] + B[(0, 1, -1)] + B[(0, 1, 1)] + + B[(-1, 0, 1)] + B[(1, -1, 0)] + B[(1, 1, 0)] + B[(1, 0, -1)] + B[(1, 0, 1)] + + B[(0, -1, -1)] + B[(0, -1, 1)] + B[(0, 1, -1)] + B[(0, 1, 1)] :: sage: KL = RootSystem(["C",3,1]).ambient_space().algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() - sage: E[-omega[2]].map_coefficients(lambda x:x.subs(t=0)) # long time (5s) + sage: E[-omega[2]].map_coefficients(lambda x: x.subs(t=0)) # long time (5s) 2*B[(0, 0, 0)] + B[(-1, -1, 0)] + B[(-1, 1, 0)] + B[(-1, 0, -1)] + B[(-1, 0, 1)] + B[(1, -1, 0)] + B[(1, 1, 0)] + B[(1, 0, -1)] + B[(1, 0, 1)] + B[(0, -1, -1)] + B[(0, -1, 1)] + B[(0, 1, -1)] + B[(0, 1, 1)] @@ -601,69 +647,79 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: R = RootSystem(['C',3,1]) sage: KL = R.weight_lattice(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) - sage: E[-2*omega[1]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # long time (15s) + sage: (E[-2*omega[1]].map_coefficients(lambda x: x.subs(t=0)) # long time (15s) + ....: == LS.one_dimensional_configuration_sum(q)) True - sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1]+La[2]) - sage: E[-omega[1]-omega[2]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # long time (45s) + sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1] + La[2]) + sage: (E[-omega[1] - omega[2]].map_coefficients(lambda x: x.subs(t=0)) # long time (45s) + ....: == LS.one_dimensional_configuration_sum(q)) True :: sage: R = RootSystem(['C',2,1]) sage: KL = R.weight_lattice(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() - sage: for d in range(1,3): # long time (10s) + sage: for d in range(1,3): # long time (45s) ....: for x,y in IntegerVectors(d,2): ....: weight = x*La[1]+y*La[2] ....: weight0 = -x*omega[1]-y*omega[2] ....: LS = crystals.ProjectedLevelZeroLSPaths(weight) - ....: assert E[weight0].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) + ....: assert (E[weight0].map_coefficients(lambda x:x.subs(t=0)) + ....: == LS.one_dimensional_configuration_sum(q)) :: sage: R = RootSystem(['B',3,1]) sage: KL = R.weight_lattice(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() + + sage: # needs sage.combinat sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) - sage: E[-2*omega[1]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # long time (23s) + sage: (E[-2*omega[1]].map_coefficients(lambda x: x.subs(t=0)) # long time (23s) + ....: == LS.one_dimensional_configuration_sum(q)) True sage: B = crystals.KirillovReshetikhin(['B',3,1],1,1) sage: T = crystals.TensorProduct(B,B) - sage: T.one_dimensional_configuration_sum(q) == LS.one_dimensional_configuration_sum(q) # long time (2s) + sage: (T.one_dimensional_configuration_sum(q) # long time (2s) + ....: == LS.one_dimensional_configuration_sum(q)) True :: sage: R = RootSystem(['BC',3,2]) sage: KL = R.weight_lattice(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() - sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) - sage: E[-2*omega[1]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # long time (21s) + sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) # needs sage.combinat + sage: (E[-2*omega[1]].map_coefficients(lambda x: x.subs(t=0)) # long time (21s), needs sage.combinat + ....: == LS.one_dimensional_configuration_sum(q)) True :: sage: R = RootSystem(CartanType(['BC',3,2]).dual()) sage: KL = R.weight_space(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() + + sage: # long time, needs sage.combinat sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) - sage: g = E[-2*omega[1]].map_coefficients(lambda x:x.subs(t=0)) # long time (30s) - sage: f = LS.one_dimensional_configuration_sum(q) # long time (1.5s) - sage: P = g.support()[0].parent() # long time - sage: B = P.algebra(q.parent()) # long time - sage: sum(p[1]*B(P(p[0])) for p in f) == g # long time + sage: g = E[-2*omega[1]].map_coefficients(lambda x: x.subs(t=0)) # 30s + sage: f = LS.one_dimensional_configuration_sum(q) # 1.5s + sage: P = g.support()[0].parent() + sage: B = P.algebra(q.parent()) + sage: sum(p[1]*B(P(p[0])) for p in f) == g True :: @@ -673,41 +729,47 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: K = QQ['q,t'].fraction_field() sage: q,t = K.gens() sage: KL = R.weight_lattice(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() + + sage: # needs sage.combinat sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) - sage: E[-2*omega[1]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # not tested, long time (20s) + sage: (E[-2*omega[1]].map_coefficients(lambda x: x.subs(t=0)) # long time (20s), not tested + ....: == LS.one_dimensional_configuration_sum(q) True - sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1]+La[2]) - sage: E[-omega[1]-omega[2]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # not tested, long time (23s) + sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1] + La[2]) + sage: (E[-omega[1]-omega[2]].map_coefficients(lambda x: x.subs(t=0)) # long time (23s), not tested + ....: == LS.one_dimensional_configuration_sum(q)) True The next test breaks if the energy is not scaled by the translation factor for dual type `G_2^{(1)}`:: - sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]+La[2]) - sage: E[-2*omega[1]-omega[2]].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) # not tested, very long time (100s) + sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]+La[2]) # needs sage.combinat + sage: (E[-2*omega[1]-omega[2]].map_coefficients(lambda x: x.subs(t=0)) # long time (100s), not tested, needs sage.combinat + ....: == LS.one_dimensional_configuration_sum(q) True sage: R = RootSystem(['D',4,1]) sage: KL = R.weight_lattice(extended=True).algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t,-1) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, t, -1) sage: omega = E.keys().fundamental_weights() sage: La = R.weight_space().basis() - sage: for d in range(1,2): # long time (41s) + sage: for d in range(1,2): # long time (41s) ....: for a,b,c,d in IntegerVectors(d,4): - ....: weight = a*La[1]+b*La[2]+c*La[3]+d*La[4] - ....: weight0 = -a*omega[1]-b*omega[2]-c*omega[3]-d*omega[4] + ....: weight = a*La[1] + b*La[2] + c*La[3] + d*La[4] + ....: weight0 = -a*omega[1] - b*omega[2] - c*omega[3] - d*omega[4] ....: LS = crystals.ProjectedLevelZeroLSPaths(weight) - ....: assert E[weight0].map_coefficients(lambda x:x.subs(t=0)) == LS.one_dimensional_configuration_sum(q) + ....: assert (E[weight0].map_coefficients(lambda x: x.subs(t=0)) + ....: == LS.one_dimensional_configuration_sum(q)) TESTS: Calculations checked with Bogdan Ion 2013/04/18:: sage: K = QQ['q,t'].fraction_field() - sage: q,t=K.gens() + sage: q,t = K.gens() sage: E = NonSymmetricMacdonaldPolynomials(["B",2,1], q=q,q1=t,q2=-1/t) sage: L0 = E.keys() sage: omega = L0.fundamental_weights() @@ -717,16 +779,20 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E[omega[2]] B[(1/2, 1/2)] sage: E[-omega[1]] - ((-q^2*t^8+q^2*t^6-q*t^6+2*q*t^4-q*t^2+t^2-1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(0, 0)] + B[(-1, 0)] + ((-q*t^8+q*t^6+t^2-1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(1, 0)] + ((-t^2+1)/(-q*t^2+1))*B[(0, -1)] + ((t^2-1)/(q*t^2-1))*B[(0, 1)] + ((-q^2*t^8+q^2*t^6-q*t^6+2*q*t^4-q*t^2+t^2-1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(0, 0)] + + B[(-1, 0)] + ((-q*t^8+q*t^6+t^2-1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(1, 0)] + + ((-t^2+1)/(-q*t^2+1))*B[(0, -1)] + ((t^2-1)/(q*t^2-1))*B[(0, 1)] sage: E[L0([0,1])] ((-q*t^4+q*t^2)/(-q*t^4+1))*B[(0, 0)] + ((-t^2+1)/(-q*t^4+1))*B[(1, 0)] + B[(0, 1)] sage: E[L0([1,1])] - ((q*t^2-q)/(q*t^2-1))*B[(0, 0)] + ((-q*t^2+q)/(-q*t^2+1))*B[(1, 0)] + B[(1, 1)] + ((-q*t^2+q)/(-q*t^2+1))*B[(0, 1)] + ((q*t^2-q)/(q*t^2-1))*B[(0, 0)] + ((-q*t^2+q)/(-q*t^2+1))*B[(1, 0)] + + B[(1, 1)] + ((-q*t^2+q)/(-q*t^2+1))*B[(0, 1)] sage: E = NonSymmetricMacdonaldPolynomials(["A",2,1], q=q,q1=t,q2=-1/t) sage: L0 = E.keys() sage: factor(E[L0([-1,0,1])][L0.zero()]) - (t - 1) * (t + 1) * (q*t^2 - 1)^-3 * (q*t^2 + 1)^-1 * (q^3*t^6 + 2*q^2*t^6 - 3*q^2*t^4 - 2*q*t^2 - t^2 + q + 2) + (t - 1) * (t + 1) * (q*t^2 - 1)^-3 * (q*t^2 + 1)^-1 + * (q^3*t^6 + 2*q^2*t^6 - 3*q^2*t^4 - 2*q*t^2 - t^2 + q + 2) Checking step by step calculations in type `BC` with Bogdan Ion 2013/04/18:: @@ -791,8 +857,22 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E[omega[1]] ((-q*q1*q2^3-q*q2^4)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] - sage: E[2*omega[2]] # long time # not checked against Bogdan's notes, but a good self-consistency test - ((-q^12*q1^6-q^12*q1^5*q2+2*q^10*q1^5*q2+5*q^10*q1^4*q2^2+3*q^10*q1^3*q2^3+2*q^8*q1^5*q2+4*q^8*q1^4*q2^2+q^8*q1^3*q2^3-q^8*q1^2*q2^4+q^8*q1*q2^5+q^8*q2^6-q^6*q1^3*q2^3+q^6*q1^2*q2^4+4*q^6*q1*q2^5+2*q^6*q2^6+q^4*q1^3*q2^3+3*q^4*q1^2*q2^4+4*q^4*q1*q2^5+2*q^4*q2^6)/(-q^12*q1^6-q^10*q1^5*q2-q^8*q1^3*q2^3+q^6*q1^4*q2^2-q^6*q1^2*q2^4+q^4*q1^3*q2^3+q^2*q1*q2^5+q2^6))*B[(0, 0)] + ((q^7*q1^2*q2+2*q^7*q1*q2^2+q^7*q2^3+q^5*q1^2*q2+2*q^5*q1*q2^2+q^5*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(-1, 0)] + ((-q^6*q1*q2-q^6*q2^2)/(q^6*q1^2-q2^2))*B[(-1, -1)] + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(-1, 1)] + ((-q^3*q1*q2-q^3*q2^2)/(q^6*q1^2-q2^2))*B[(-1, 2)] + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 0)] + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(1, -1)] + ((q^8*q1^3+q^8*q1^2*q2+q^6*q1^3+q^6*q1^2*q2-q^6*q1*q2^2-q^6*q2^3-2*q^4*q1^2*q2-4*q^4*q1*q2^2-2*q^4*q2^3-q^2*q1^2*q2-3*q^2*q1*q2^2-2*q^2*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 1)] + ((q^5*q1^2+q^5*q1*q2-q^3*q1*q2-q^3*q2^2-q*q1*q2-q*q2^2)/(q^6*q1^2-q2^2))*B[(1, 2)] + ((-q^6*q1^2-q^6*q1*q2+q^4*q1*q2+q^4*q2^2+q^2*q1*q2+q^2*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 0)] + ((-q^3*q1*q2-q^3*q2^2)/(q^6*q1^2-q2^2))*B[(2, -1)] + ((-q^5*q1^2-q^5*q1*q2+q^3*q1*q2+q^3*q2^2+q*q1*q2+q*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 1)] + B[(2, 2)] + ((q^7*q1^2*q2+2*q^7*q1*q2^2+q^7*q2^3+q^5*q1^2*q2+2*q^5*q1*q2^2+q^5*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(0, -1)] + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(0, 1)] + ((q^6*q1^2+q^6*q1*q2-q^4*q1*q2-q^4*q2^2-q^2*q1*q2-q^2*q2^2)/(q^6*q1^2-q2^2))*B[(0, 2)] + sage: E[2*omega[2]] # not checked against Bogdan's notes, but a good self-consistency test # long time + ((-q^12*q1^6-q^12*q1^5*q2+2*q^10*q1^5*q2+5*q^10*q1^4*q2^2+3*q^10*q1^3*q2^3+2*q^8*q1^5*q2+4*q^8*q1^4*q2^2+q^8*q1^3*q2^3-q^8*q1^2*q2^4+q^8*q1*q2^5+q^8*q2^6-q^6*q1^3*q2^3+q^6*q1^2*q2^4+4*q^6*q1*q2^5+2*q^6*q2^6+q^4*q1^3*q2^3+3*q^4*q1^2*q2^4+4*q^4*q1*q2^5+2*q^4*q2^6)/(-q^12*q1^6-q^10*q1^5*q2-q^8*q1^3*q2^3+q^6*q1^4*q2^2-q^6*q1^2*q2^4+q^4*q1^3*q2^3+q^2*q1*q2^5+q2^6))*B[(0, 0)] + + ((q^7*q1^2*q2+2*q^7*q1*q2^2+q^7*q2^3+q^5*q1^2*q2+2*q^5*q1*q2^2+q^5*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(-1, 0)] + + ((-q^6*q1*q2-q^6*q2^2)/(q^6*q1^2-q2^2))*B[(-1, -1)] + + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(-1, 1)] + + ((-q^3*q1*q2-q^3*q2^2)/(q^6*q1^2-q2^2))*B[(-1, 2)] + + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 0)] + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(1, -1)] + + ((q^8*q1^3+q^8*q1^2*q2+q^6*q1^3+q^6*q1^2*q2-q^6*q1*q2^2-q^6*q2^3-2*q^4*q1^2*q2-4*q^4*q1*q2^2-2*q^4*q2^3-q^2*q1^2*q2-3*q^2*q1*q2^2-2*q^2*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 1)] + + ((q^5*q1^2+q^5*q1*q2-q^3*q1*q2-q^3*q2^2-q*q1*q2-q*q2^2)/(q^6*q1^2-q2^2))*B[(1, 2)] + + ((-q^6*q1^2-q^6*q1*q2+q^4*q1*q2+q^4*q2^2+q^2*q1*q2+q^2*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 0)] + + ((-q^3*q1*q2-q^3*q2^2)/(q^6*q1^2-q2^2))*B[(2, -1)] + + ((-q^5*q1^2-q^5*q1*q2+q^3*q1*q2+q^3*q2^2+q*q1*q2+q*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 1)] + + B[(2, 2)] + + ((q^7*q1^2*q2+2*q^7*q1*q2^2+q^7*q2^3+q^5*q1^2*q2+2*q^5*q1*q2^2+q^5*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(0, -1)] + + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(0, 1)] + + ((q^6*q1^2+q^6*q1*q2-q^4*q1*q2-q^4*q2^2-q^2*q1*q2-q^2*q2^2)/(q^6*q1^2-q2^2))*B[(0, 2)] sage: E.recursion(2*omega[2]) [0, 1, 0, 2, 1, 0, 2, 1, 0] @@ -800,17 +880,17 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): defining the `Y` s in terms of them:: sage: T = E._T_Y - sage: Ye1 = T.Tw((1,2,1,0), scalar = (-1/(q1*q2))^2) - sage: Ye2 = T.Tw((2,1,0,1), signs = (1,1,1,-1), scalar = (-1/(q1*q2))) - sage: Yalpha0 = T.Tw((0,1,2,1), signs = (-1,-1,-1,-1), scalar = q^-1*(-q1*q2)^2) - sage: Yalpha1 = T.Tw((1,2,0,1,2,0), signs=(1,1,-1,1,-1,1), scalar = -1/(q1*q2)) - sage: Yalpha2 = T.Tw((2,1,0,1,2,1,0,1), signs = (1,1,1,-1,1,1,1,-1), scalar = (1/(q1*q2))^2) + sage: Ye1 = T.Tw((1,2,1,0), scalar=(-1/(q1*q2))^2) + sage: Ye2 = T.Tw((2,1,0,1), signs=(1,1,1,-1), scalar=(-1/(q1*q2))) + sage: Yalpha0 = T.Tw((0,1,2,1), signs=(-1,-1,-1,-1), scalar=q^-1*(-q1*q2)^2) + sage: Yalpha1 = T.Tw((1,2,0,1,2,0), signs=(1,1,-1,1,-1,1), scalar=-1/(q1*q2)) + sage: Yalpha2 = T.Tw((2,1,0,1,2,1,0,1), signs=(1,1,1,-1,1,1,1,-1), + ....: scalar=(1/(q1*q2))^2) sage: Ye1(KL0.one()) q1^2/q2^2*B[(0, 0)] sage: Ye2(KL0.one()) ((-q1)/q2)*B[(0, 0)] - sage: Yalpha0(KL0.one()) q2^2/(q*q1^2)*B[(0, 0)] sage: Yalpha1(KL0.one()) @@ -830,12 +910,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): e[0] - e[1] sage: L(alpha[2]) e[1] - sage: Y[alpha[0]].word (0, 1, 2, 1) sage: Y[alpha[0]].signs (-1, -1, -1, -1) - sage: Y[alpha[0]].scalar # mind that Sage's q is the usual q^{1/2} + sage: Y[alpha[0]].scalar # mind that Sage's q is the usual q^{1/2} q1^2*q2^2/q sage: Y[alpha[0]](KL0.one()) q2^2/(q*q1^2)*B[(0, 0)] @@ -847,7 +926,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: Y[alpha[1]].scalar 1/(-q1*q2) - sage: Y[alpha[2]].word # Bogdan says it should be the square of that; do we need to take translation factors into account or not? + sage: Y[alpha[2]].word # Bogdan says it should be the square of that; do we need to take translation factors into account or not? (2, 1, 0, 1) sage: Y[alpha[2]].signs (1, 1, 1, -1) @@ -865,11 +944,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): Checking T0check:: sage: T0check_on_basis = KL.T0_check_on_basis(q1,q2, convention="dominant") - sage: T0check_on_basis.phi # note: this is in fact a0 phi + sage: T0check_on_basis.phi # note: this is in fact a0 phi (2, 0) - sage: T0check_on_basis.v # what to match it with? + sage: T0check_on_basis.v # what to match it with? (1,) - sage: T0check_on_basis.j # what to match it with? + sage: T0check_on_basis.j # what to match it with? 2 sage: T0check_on_basis(KL0.basis().keys().zero()) ((-q1^2)/q2)*B[(1, 0)] @@ -898,7 +977,6 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: x.parent() Algebra of the Weight lattice of the Root system of type ['A', 1] over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field - sage: E[omega[1]] B[Lambda[1]] sage: E.eigenvalues(_) @@ -908,15 +986,24 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E.eigenvalues(_) [q*t, 1/(q^2*t)] sage: E[3*omega[1]] - ((-q^2*t+q^2)/(-q^2*t+1))*B[-Lambda[1]] + ((-q^2*t+q^2-q*t+q)/(-q^2*t+1))*B[Lambda[1]] + B[3*Lambda[1]] + ((-q^2*t+q^2)/(-q^2*t+1))*B[-Lambda[1]] + + ((-q^2*t+q^2-q*t+q)/(-q^2*t+1))*B[Lambda[1]] + B[3*Lambda[1]] sage: E.eigenvalues(_) [q^2*t, 1/(q^3*t)] sage: E[4*omega[1]] - ((q^5*t^2-q^5*t+q^4*t^2-2*q^4*t+q^3*t^2+q^4-2*q^3*t+q^3-q^2*t+q^2)/(q^5*t^2-q^3*t-q^2*t+1))*B[0] + ((-q^3*t+q^3)/(-q^3*t+1))*B[-2*Lambda[1]] + ((-q^3*t+q^3-q^2*t+q^2-q*t+q)/(-q^3*t+1))*B[2*Lambda[1]] + B[4*Lambda[1]] + ((q^5*t^2-q^5*t+q^4*t^2-2*q^4*t+q^3*t^2+q^4-2*q^3*t+q^3-q^2*t+q^2)/(q^5*t^2-q^3*t-q^2*t+1))*B[0] + + ((-q^3*t+q^3)/(-q^3*t+1))*B[-2*Lambda[1]] + + ((-q^3*t+q^3-q^2*t+q^2-q*t+q)/(-q^3*t+1))*B[2*Lambda[1]] + + B[4*Lambda[1]] sage: E.eigenvalues(_) [q^3*t, 1/(q^4*t)] sage: E[6*omega[1]] - ((-q^12*t^3+q^12*t^2-q^11*t^3+2*q^11*t^2-2*q^10*t^3-q^11*t+4*q^10*t^2-2*q^9*t^3-2*q^10*t+5*q^9*t^2-2*q^8*t^3-4*q^9*t+6*q^8*t^2-q^7*t^3+q^9-5*q^8*t+5*q^7*t^2-q^6*t^3+q^8-6*q^7*t+4*q^6*t^2+2*q^7-5*q^6*t+2*q^5*t^2+2*q^6-4*q^5*t+q^4*t^2+2*q^5-2*q^4*t+q^4-q^3*t+q^3)/(-q^12*t^3+q^9*t^2+q^8*t^2+q^7*t^2-q^5*t-q^4*t-q^3*t+1))*B[0] + ((-q^5*t+q^5)/(-q^5*t+1))*B[-4*Lambda[1]] + ((q^9*t^2-q^9*t+q^8*t^2-2*q^8*t+q^7*t^2+q^8-2*q^7*t+q^6*t^2+q^7-2*q^6*t+q^5*t^2+q^6-2*q^5*t+q^5-q^4*t+q^4)/(q^9*t^2-q^5*t-q^4*t+1))*B[-2*Lambda[1]] + ((q^9*t^2-q^9*t+q^8*t^2-2*q^8*t+2*q^7*t^2+q^8-3*q^7*t+2*q^6*t^2+q^7-4*q^6*t+2*q^5*t^2+2*q^6-4*q^5*t+q^4*t^2+2*q^5-3*q^4*t+q^3*t^2+2*q^4-2*q^3*t+q^3-q^2*t+q^2)/(q^9*t^2-q^5*t-q^4*t+1))*B[2*Lambda[1]] + ((q^5*t-q^5+q^4*t-q^4+q^3*t-q^3+q^2*t-q^2+q*t-q)/(q^5*t-1))*B[4*Lambda[1]] + B[6*Lambda[1]] + ((-q^12*t^3+q^12*t^2-q^11*t^3+2*q^11*t^2-2*q^10*t^3-q^11*t+4*q^10*t^2-2*q^9*t^3-2*q^10*t+5*q^9*t^2-2*q^8*t^3-4*q^9*t+6*q^8*t^2-q^7*t^3+q^9-5*q^8*t+5*q^7*t^2-q^6*t^3+q^8-6*q^7*t+4*q^6*t^2+2*q^7-5*q^6*t+2*q^5*t^2+2*q^6-4*q^5*t+q^4*t^2+2*q^5-2*q^4*t+q^4-q^3*t+q^3)/(-q^12*t^3+q^9*t^2+q^8*t^2+q^7*t^2-q^5*t-q^4*t-q^3*t+1))*B[0] + + ((-q^5*t+q^5)/(-q^5*t+1))*B[-4*Lambda[1]] + + ((q^9*t^2-q^9*t+q^8*t^2-2*q^8*t+q^7*t^2+q^8-2*q^7*t+q^6*t^2+q^7-2*q^6*t+q^5*t^2+q^6-2*q^5*t+q^5-q^4*t+q^4)/(q^9*t^2-q^5*t-q^4*t+1))*B[-2*Lambda[1]] + + ((q^9*t^2-q^9*t+q^8*t^2-2*q^8*t+2*q^7*t^2+q^8-3*q^7*t+2*q^6*t^2+q^7-4*q^6*t+2*q^5*t^2+2*q^6-4*q^5*t+q^4*t^2+2*q^5-3*q^4*t+q^3*t^2+2*q^4-2*q^3*t+q^3-q^2*t+q^2)/(q^9*t^2-q^5*t-q^4*t+1))*B[2*Lambda[1]] + + ((q^5*t-q^5+q^4*t-q^4+q^3*t-q^3+q^2*t-q^2+q*t-q)/(q^5*t-1))*B[4*Lambda[1]] + + B[6*Lambda[1]] sage: E.eigenvalues(_) [q^5*t, 1/(q^6*t)] sage: E[-omega[1]] @@ -961,24 +1048,29 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): x0^2 + (q*t - q)/(q*t - 1)*x0*x1 + (q*t - q)/(q*t - 1)*x0*x2 sage: EE([0,2,0]) - (t - 1)/(q^2*t^2 - 1)*x0^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x1 + x1^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x2 + (q*t - q)/(q*t - 1)*x1*x2 + (t - 1)/(q^2*t^2 - 1)*x0^2 + + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x1 + + x1^2 + + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x2 + + (q*t - q)/(q*t - 1)*x1*x2 Systematic checks with Sage's implementation of [HHL06]_:: - sage: import sage.combinat.sf.ns_macdonald as NS - sage: assert all(EE([x,y,z]) == NS.E([x,y,z]) for d in range(5) for x,y,z in IntegerVectors(d,3)) # long time (9s) + sage: import sage.combinat.sf.ns_macdonald as NS # needs sage.combinat + sage: assert all(EE([x,y,z]) == NS.E([x,y,z]) for d in range(5) # long time (9s), needs sage.combinat + ....: for x,y,z in IntegerVectors(d,3)) We check that we get eigenvectors for generic `q_1`, `q_2`:: sage: K = QQ['q,q1,q2'].fraction_field() sage: q,q1,q2 = K.gens() sage: KL = RootSystem(["A",2,1]).ambient_space().algebra(K) - sage: E = NonSymmetricMacdonaldPolynomials(KL,q, q1, q2) + sage: E = NonSymmetricMacdonaldPolynomials(KL, q, q1, q2) sage: L0 = E.keys() sage: omega = L0.fundamental_weights() sage: E[2*omega[2]] ((-q*q1-q*q2)/(-q*q1-q2))*B[(1, 2, 1)] + ((-q*q1-q*q2)/(-q*q1-q2))*B[(2, 1, 1)] + B[(2, 2, 0)] - sage: for d in range(4): # long time (9s) + sage: for d in range(4): # long time (9s) ....: for weight in IntegerVectors(d,3).map(list).map(L0): ....: eigenvalues = E.eigenvalues(E[L0(weight)]) @@ -999,28 +1091,36 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E.eigenvalues(_) # not checked [t, 1/(q*t^3), t] - sage: E[-omega[1]] # consistent with before refactoring - B[(-1, 0)] + ((-t+1)/(-q*t+1))*B[(1, 0)] + ((-t+1)/(-q*t+1))*B[(0, -1)] + ((t-1)/(q*t-1))*B[(0, 1)] + sage: E[-omega[1]] # consistent with before refactoring + B[(-1, 0)] + ((-t+1)/(-q*t+1))*B[(1, 0)] + + ((-t+1)/(-q*t+1))*B[(0, -1)] + ((t-1)/(q*t-1))*B[(0, 1)] sage: E.eigenvalues(_) # not checked [(-1)/(-q^2*t^3), q*t, t] - sage: E[-omega[1]+omega[2]] # consistent with before refactoring + sage: E[-omega[1]+omega[2]] # consistent with before refactoring ((-t+1)/(-q*t^3+1))*B[(1, 0)] + B[(0, 1)] sage: E.eigenvalues(_) # not checked [t, q*t^3, (-1)/(-q*t^2)] - sage: E[omega[1]-omega[2]] # consistent with before refactoring + sage: E[omega[1]-omega[2]] # consistent with before refactoring ((-t+1)/(-q*t^2+1))*B[(1, 0)] + B[(0, -1)] + ((-t+1)/(-q*t^2+1))*B[(0, 1)] sage: E.eigenvalues(_) # not checked [1/(q^2*t^3), 1/(q*t), q*t^2] sage: E[-omega[2]] - ((-q^2*t^4+q^2*t^3-q*t^3+2*q*t^2-q*t+t-1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(0, 0)] + B[(-1, -1)] + ((-t+1)/(-q*t+1))*B[(-1, 1)] + ((t-1)/(q*t-1))*B[(1, -1)] + ((-q*t^4+q*t^3+t-1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(1, 1)] - sage: E.eigenvalues(_) # not checked # long time (1s) + ((-q^2*t^4+q^2*t^3-q*t^3+2*q*t^2-q*t+t-1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(0, 0)] + + B[(-1, -1)] + ((-t+1)/(-q*t+1))*B[(-1, 1)] + ((t-1)/(q*t-1))*B[(1, -1)] + + ((-q*t^4+q*t^3+t-1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(1, 1)] + sage: E.eigenvalues(_) # not checked # long time (1s) [1/(q^3*t^3), t, q*t] sage: E[-omega[2]].map_coefficients(lambda c: c.subs(t=0)) # checking against crystals B[(0, 0)] + B[(-1, -1)] + B[(-1, 1)] + B[(1, -1)] + B[(1, 1)] sage: E[2*omega[2]] - ((-q^6*t^7+q^6*t^6-q^5*t^6+2*q^5*t^5-q^4*t^5-q^5*t^3+3*q^4*t^4-3*q^4*t^3+q^3*t^4+q^4*t^2-2*q^3*t^2+q^3*t-q^2*t+q^2)/(-q^6*t^7+q^5*t^6+q^4*t^4+q^3*t^4-q^3*t^3-q^2*t^3-q*t+1))*B[(0, 0)] + ((-q^3*t^2+q^3*t)/(-q^3*t^3+1))*B[(-1, -1)] + ((-q^3*t^3+2*q^3*t^2-q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(-1, 1)] + ((-q^3*t^3+2*q^3*t^2-q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, -1)] + ((-q^4*t^4+q^4*t^3-q^3*t^3+2*q^3*t^2-q^2*t^3-q^3*t+2*q^2*t^2-q^2*t+q*t-q)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, 1)] + ((q*t-q)/(q*t-1))*B[(2, 0)] + B[(2, 2)] + ((-q*t+q)/(-q*t+1))*B[(0, 2)] + ((-q^6*t^7+q^6*t^6-q^5*t^6+2*q^5*t^5-q^4*t^5-q^5*t^3+3*q^4*t^4-3*q^4*t^3+q^3*t^4+q^4*t^2-2*q^3*t^2+q^3*t-q^2*t+q^2)/(-q^6*t^7+q^5*t^6+q^4*t^4+q^3*t^4-q^3*t^3-q^2*t^3-q*t+1))*B[(0, 0)] + + ((-q^3*t^2+q^3*t)/(-q^3*t^3+1))*B[(-1, -1)] + + ((-q^3*t^3+2*q^3*t^2-q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(-1, 1)] + + ((-q^3*t^3+2*q^3*t^2-q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, -1)] + + ((-q^4*t^4+q^4*t^3-q^3*t^3+2*q^3*t^2-q^2*t^3-q^3*t+2*q^2*t^2-q^2*t+q*t-q)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, 1)] + + ((q*t-q)/(q*t-1))*B[(2, 0)] + B[(2, 2)] + ((-q*t+q)/(-q*t+1))*B[(0, 2)] sage: E.eigenvalues(_) # not checked [q^3*t^3, t, (-1)/(-q^2*t^2)] @@ -1033,7 +1133,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E.eigenvalues(E11) [q*t^3, t, (-1)/(-q*t^2)] - sage: E1m1 = KL0.sum_of_terms([[L0([1,-1]), 1], [L0([1,1]), (1-t)/(1-q*t^2)], [L0([0,0]), q*t*(1-t)/(1-q*t^2)] ]) + sage: E1m1 = KL0.sum_of_terms([[L0([1,-1]), 1], [L0([1,1]), (1-t)/(1-q*t^2)], + ....: [L0([0,0]), q*t*(1-t)/(1-q*t^2)]]) sage: E1m1 == E[2*omega[1]-omega[2]] True sage: E.eigenvalues(E1m1) @@ -1057,11 +1158,13 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): [q*t^2, 1/(q^2*t^3), t] sage: E[-omega[1]] - ((-q*t+q-t+1)/(-q^2*t+1))*B[(0, 0)] + B[(-1, 0)] + ((-t+1)/(-q^2*t+1))*B[(1, 0)] + ((-t+1)/(-q^2*t+1))*B[(0, -1)] + ((t-1)/(q^2*t-1))*B[(0, 1)] + ((-q*t+q-t+1)/(-q^2*t+1))*B[(0, 0)] + B[(-1, 0)] + ((-t+1)/(-q^2*t+1))*B[(1, 0)] + + ((-t+1)/(-q^2*t+1))*B[(0, -1)] + ((t-1)/(q^2*t-1))*B[(0, 1)] sage: E.eigenvalues(_) [(-1)/(-q^3*t^2), q^2*t, t] sage: E[-omega[1]+omega[2]] - B[(-1/2, 1/2)] + ((-t+1)/(-q^2*t^3+1))*B[(1/2, -1/2)] + ((-q*t^3+q*t^2-t+1)/(-q^2*t^3+1))*B[(1/2, 1/2)] + B[(-1/2, 1/2)] + ((-t+1)/(-q^2*t^3+1))*B[(1/2, -1/2)] + + ((-q*t^3+q*t^2-t+1)/(-q^2*t^3+1))*B[(1/2, 1/2)] sage: E.eigenvalues(_) [(-1)/(-q^2*t^2), q^2*t^3, (-1)/(-q*t)] sage: E[omega[1]-omega[2]] @@ -1073,30 +1176,33 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: K = QQ['q','t'].fraction_field() sage: q,t = K.gens() - sage: def to_SR(x): return x.expand([SR.var('x%s'%i) for i in range(1,x.parent().basis().keys().dimension()+1)]).subs(q=SR.var('q'), t=SR.var('t')) - sage: var('x1,x2,x3') # optional - sage.symbolic + sage: def to_SR(x): + ....: dim = x.parent().basis().keys().dimension() + ....: x_expanded = x.expand([SR.var('x%s'%i) for i in range(1, dim + 1)]) + ....: return x_expanded.subs(q=SR.var('q'), t=SR.var('t')) + sage: var('x1,x2,x3') # needs sage.symbolic (x1, x2, x3) - sage: E = NonSymmetricMacdonaldPolynomials(["BC",2,2], q=q, q1=t^2,q2=-1) + sage: E = NonSymmetricMacdonaldPolynomials(["BC",2,2], q=q, q1=t^2, q2=-1) sage: omega = E.keys().fundamental_weights() - sage: expected = (t-1)*(t+1)*(2+q^4+2*q^2-2*t^2-2*q^2*t^2-t^4*q^2-q^4*t^4+t^4-3*q^6*t^6-2*q^4*t^6+2*q^6*t^8+2*q^4*t^8+t^10*q^8)*q^4/((q^2*t^3-1)*(q^2*t^3+1)*(t*q-1)*(t*q+1)*(t^2*q^3+1)*(t^2*q^3-1))+(t-1)^2*(t+1)^2*(2*q^2+q^4+2+q^4*t^2)*q^3*x1/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1))+(t-1)^2*(t+1)^2*(q^2+1)*q^5/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(q^2+1)*q^4*x2/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(2*q^2+q^4+2+q^4*t^2)*q^3*x2/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1))+(t-1)^2*(t+1)^2*(q^2+1)*q^5/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x2)+x1^2*x2^2+(t-1)*(t+1)*(-2*q^2-q^4-2+2*q^2*t^2+t^2+q^6*t^4+q^4*t^4)*q^2*x2*x1/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1))+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q*x2^2*x1/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*q^3*x1^2/((t^2*q^3-1)*(t^2*q^3+1)*x2)+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q*x2*x1^2/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*q^6/((t^2*q^3+1)*(t^2*q^3-1)*x1*x2)+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q^2*x1^2/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q^2*x2^2/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*q^3*x2^2/((t^2*q^3-1)*(t^2*q^3+1)*x1)+(t-1)^2*(t+1)^2*(q^2+1)*q^4*x1/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x2) # optional - sage.symbolic - sage: to_SR(E[2*omega[2]]) - expected # long time (3.5s) # optional - sage.symbolic + sage: expected = (t-1)*(t+1)*(2+q^4+2*q^2-2*t^2-2*q^2*t^2-t^4*q^2-q^4*t^4+t^4-3*q^6*t^6-2*q^4*t^6+2*q^6*t^8+2*q^4*t^8+t^10*q^8)*q^4/((q^2*t^3-1)*(q^2*t^3+1)*(t*q-1)*(t*q+1)*(t^2*q^3+1)*(t^2*q^3-1))+(t-1)^2*(t+1)^2*(2*q^2+q^4+2+q^4*t^2)*q^3*x1/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1))+(t-1)^2*(t+1)^2*(q^2+1)*q^5/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(q^2+1)*q^4*x2/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(2*q^2+q^4+2+q^4*t^2)*q^3*x2/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1))+(t-1)^2*(t+1)^2*(q^2+1)*q^5/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x2)+x1^2*x2^2+(t-1)*(t+1)*(-2*q^2-q^4-2+2*q^2*t^2+t^2+q^6*t^4+q^4*t^4)*q^2*x2*x1/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1))+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q*x2^2*x1/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*q^3*x1^2/((t^2*q^3-1)*(t^2*q^3+1)*x2)+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q*x2*x1^2/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*q^6/((t^2*q^3+1)*(t^2*q^3-1)*x1*x2)+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q^2*x1^2/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*(q^2+1+q^4*t^2)*q^2*x2^2/((t^2*q^3-1)*(t^2*q^3+1))+(t-1)*(t+1)*q^3*x2^2/((t^2*q^3-1)*(t^2*q^3+1)*x1)+(t-1)^2*(t+1)^2*(q^2+1)*q^4*x1/((t^2*q^3+1)*(t^2*q^3-1)*(t*q-1)*(t*q+1)*x2) # needs sage.symbolic + sage: to_SR(E[2*omega[2]]) - expected # long time (3.5s) # needs sage.symbolic 0 sage: E = NonSymmetricMacdonaldPolynomials(["BC",3,2], q=q, q1=t^2, q2=-1) sage: omega=E.keys().fundamental_weights() sage: mu = -3*omega[1] + 3*omega[2] - omega[3]; mu (-1, 2, -1) - sage: expected = (t-1)^2*(t+1)^2*(3*q^2+q^4+1+t^2*q^4+q^2*t^2-3*t^4*q^2-5*t^6*q^4+2*t^8*q^4-4*t^8*q^6-q^8*t^10+2*t^10*q^6-2*q^8*t^12+t^14*q^8-t^14*q^10+q^10*t^16+q^8*t^16+q^10*t^18+t^18*q^12)*x2*x1/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(q^2*t^6+2*t^6*q^4-q^4*t^4+t^4*q^2-q^2*t^2+t^2-2-q^2)*q^2*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*(-q^2-1+t^4*q^2-q^4*t^4+2*t^6*q^4)*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t+1)*(t-1)*x2^2*x3/((t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(3*q^2+q^4+2+t^2*q^4+2*q^2*t^2-4*t^4*q^2+q^4*t^4-6*t^6*q^4+t^8*q^4-4*t^8*q^6-q^8*t^10+t^10*q^6-3*q^8*t^12-2*t^14*q^10+2*t^14*q^8+2*q^10*t^16+q^8*t^16+t^18*q^12+2*q^10*t^18)*q*x2/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(1+q^4+2*q^2+t^2*q^4-3*t^4*q^2+q^2*t^6-5*t^6*q^4+3*t^8*q^4-4*t^8*q^6+2*t^10*q^6-q^8*t^12-t^14*q^10+t^14*q^8+q^10*t^16+t^18*q^12)*x3*x1/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(2*q^2+1+q^4+t^2*q^4-t^2+q^2*t^2-4*t^4*q^2+q^4*t^4+q^2*t^6-5*t^6*q^4+3*t^8*q^4-4*t^8*q^6+2*t^10*q^6+q^6*t^12-2*q^8*t^12-2*t^14*q^10+2*t^14*q^8+q^10*t^16+t^18*q^12)*q*x3/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(1+t^2+t^4*q^2)*q*x3*x2^2/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)^2*(t+1)^2*(-q^2-2-q^2*t^2+t^4-q^4*t^4-t^4*q^2+3*q^2*t^6-t^6*q^4-t^8*q^6+t^8*q^4+t^10*q^4+2*q^6*t^12-q^8*t^12+t^14*q^8)*q*x3*x2*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)*(t+1)*x1^2/((q^3*t^5-1)*(q^3*t^5+1)*x3*x2)+(t-1)*(t+1)*(-q^2-1+t^4*q^2-q^4*t^4+2*t^6*q^4)*x2^2/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)*(t+1)*(t^3*q-1)*(t^3*q+1)*x3*x2^2*x1/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)^2*(t+1)^2*(q^2+1)*q*x1/((t*q+1)*(t*q-1)*(q^3*t^5+1)*(q^3*t^5-1)*x3*x2)+(t-1)^2*(t+1)^2*(t^3*q-1)*(t^3*q+1)*x3*x2*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)^2*(t+1)^2*q^3*x3/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1*x2)+(t-1)*(t+1)*(-1-q^2+q^2*t^2+t^10*q^6)*q*x2/((t*q+1)*(t*q-1)*(q^3*t^5+1)*(q^3*t^5-1)*x3*x1)+x2^2/(x1*x3)+(t-1)*(t+1)*q*x2^2/((t*q-1)*(t*q+1)*x3)+(t-1)^3*(t+1)^3*(1+t^2+t^4*q^2)*q*x2*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)^2*(t+1)^2*q*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(q^2*t^6+2*t^6*q^4-q^4*t^4+t^4*q^2-q^2*t^2+t^2-2-q^2)*q^3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)*(t+1)*(q^2+2-t^2+q^4*t^4-t^4*q^2-3*t^6*q^4+t^8*q^4-2*t^10*q^6-q^8*t^12+q^6*t^12+q^8*t^16+q^10*t^16)*q^2*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1)+(t-1)^2*(t+1)^2*(q^2+1)*q^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3*x2)+(t-1)*(t+1)*(1+q^4+2*q^2-2*q^2*t^2+t^4*q^6-q^4*t^4-3*q^6*t^6-t^6*q^4+2*t^8*q^6-t^10*q^6-q^8*t^10-t^14*q^10+t^14*q^8+2*q^10*t^16)*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(-q^2-2-q^2*t^2-q^4*t^4+2*t^6*q^4+t^10*q^6+q^8*t^12+t^14*q^8)*q^3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1)+(t-1)^2*(t+1)^2*(-1-q^2-q^2*t^2+t^2+t^4*q^2-q^4*t^4+2*t^6*q^4)*q^2*x3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)*(t+1)*q*x2^2/((t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(1+t^2+t^4*q^2)*q*x2^2*x1/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)^2*(t+1)^2*q*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*(-1-q^4-2*q^2-t^2*q^4-q^2*t^2+t^4*q^2-t^4*q^6-2*q^4*t^4+3*t^6*q^4-q^6*t^6-t^8*q^8+t^8*q^6+2*t^10*q^6-q^10*t^12+3*q^8*t^12+2*t^14*q^10)*x3*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)*(t+1)*(q^2+1-t^2+q^4*t^4-t^4*q^2+q^2*t^6-3*t^6*q^4+t^8*q^4-t^10*q^6+q^6*t^12-q^8*t^12+q^10*t^16)*q^2*x3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1)+(t-1)*(t+1)*(-1-q^2+q^2*t^2+t^10*q^6)*q^2/((t*q-1)*(t*q+1)*(q^3*t^5+1)*(q^3*t^5-1)*x1*x3)+(t-1)*(t+1)*(1+q^4+2*q^2-3*q^2*t^2+t^4*q^6-q^4*t^4-3*q^6*t^6-t^6*q^4+t^8*q^4+2*t^8*q^6-t^10*q^6+t^14*q^8-t^14*q^10+q^10*t^16)*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(3*q^2+q^4+2+q^2*t^2-t^2+t^2*q^4-6*t^4*q^2+q^4*t^4-7*t^6*q^4+q^2*t^6+3*t^8*q^4-4*t^8*q^6+t^10*q^4+3*t^10*q^6-q^8*t^12-t^14*q^10+t^14*q^8+q^8*t^16+q^10*t^18)*q*x1/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(-q^2-2-q^2*t^2-q^4*t^4+2*t^6*q^4+t^10*q^6+q^6*t^12+t^14*q^8)*q*x2*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t+1)*(t-1)*x2^2*x1/((t*q-1)*(t*q+1)*x3)+(t-1)^3*(t+1)^3*(1+t^2+t^4*q^2)*q*x3*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)*(t+1)*q^3/((q^3*t^5+1)*(q^3*t^5-1)*x1*x2*x3)+(t-1)^2*(t+1)^2*(3+3*q^2+q^4+2*q^2*t^2-t^2+t^2*q^4-6*t^4*q^2+q^4*t^4-8*t^6*q^4+q^2*t^6+2*t^8*q^4-4*t^8*q^6+t^10*q^4+2*t^10*q^6-2*q^8*t^12-t^14*q^10+t^14*q^8+q^8*t^16+q^10*t^16+2*q^10*t^18)*q^2/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(-q^4-2*q^2-1-t^2*q^4-t^4*q^6+2*q^6*t^6+t^6*q^4+t^10*q^6+q^8*t^12+t^14*q^10)*q/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(-1-q^2-q^2*t^2+t^2+t^4*q^2-q^4*t^4+2*t^6*q^4)*q*x3*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*x2*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*x3*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*q^4/((t*q+1)*(t*q-1)*(q^3*t^5+1)*(q^3*t^5-1)*x1*x2)+(t-1)^2*(t+1)^2*(-q^2-1-q^2*t^2-q^4*t^4+t^6*q^4+t^10*q^6+q^8*t^12+t^14*q^10)*q*x3*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1) # optional - sage.symbolic - sage: to_SR(E[mu]) - expected # long time (20s) # optional - sage.symbolic + sage: expected = (t-1)^2*(t+1)^2*(3*q^2+q^4+1+t^2*q^4+q^2*t^2-3*t^4*q^2-5*t^6*q^4+2*t^8*q^4-4*t^8*q^6-q^8*t^10+2*t^10*q^6-2*q^8*t^12+t^14*q^8-t^14*q^10+q^10*t^16+q^8*t^16+q^10*t^18+t^18*q^12)*x2*x1/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(q^2*t^6+2*t^6*q^4-q^4*t^4+t^4*q^2-q^2*t^2+t^2-2-q^2)*q^2*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*(-q^2-1+t^4*q^2-q^4*t^4+2*t^6*q^4)*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t+1)*(t-1)*x2^2*x3/((t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(3*q^2+q^4+2+t^2*q^4+2*q^2*t^2-4*t^4*q^2+q^4*t^4-6*t^6*q^4+t^8*q^4-4*t^8*q^6-q^8*t^10+t^10*q^6-3*q^8*t^12-2*t^14*q^10+2*t^14*q^8+2*q^10*t^16+q^8*t^16+t^18*q^12+2*q^10*t^18)*q*x2/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(1+q^4+2*q^2+t^2*q^4-3*t^4*q^2+q^2*t^6-5*t^6*q^4+3*t^8*q^4-4*t^8*q^6+2*t^10*q^6-q^8*t^12-t^14*q^10+t^14*q^8+q^10*t^16+t^18*q^12)*x3*x1/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(2*q^2+1+q^4+t^2*q^4-t^2+q^2*t^2-4*t^4*q^2+q^4*t^4+q^2*t^6-5*t^6*q^4+3*t^8*q^4-4*t^8*q^6+2*t^10*q^6+q^6*t^12-2*q^8*t^12-2*t^14*q^10+2*t^14*q^8+q^10*t^16+t^18*q^12)*q*x3/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(1+t^2+t^4*q^2)*q*x3*x2^2/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)^2*(t+1)^2*(-q^2-2-q^2*t^2+t^4-q^4*t^4-t^4*q^2+3*q^2*t^6-t^6*q^4-t^8*q^6+t^8*q^4+t^10*q^4+2*q^6*t^12-q^8*t^12+t^14*q^8)*q*x3*x2*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)*(t+1)*x1^2/((q^3*t^5-1)*(q^3*t^5+1)*x3*x2)+(t-1)*(t+1)*(-q^2-1+t^4*q^2-q^4*t^4+2*t^6*q^4)*x2^2/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)*(t+1)*(t^3*q-1)*(t^3*q+1)*x3*x2^2*x1/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)^2*(t+1)^2*(q^2+1)*q*x1/((t*q+1)*(t*q-1)*(q^3*t^5+1)*(q^3*t^5-1)*x3*x2)+(t-1)^2*(t+1)^2*(t^3*q-1)*(t^3*q+1)*x3*x2*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)^2*(t+1)^2*q^3*x3/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1*x2)+(t-1)*(t+1)*(-1-q^2+q^2*t^2+t^10*q^6)*q*x2/((t*q+1)*(t*q-1)*(q^3*t^5+1)*(q^3*t^5-1)*x3*x1)+x2^2/(x1*x3)+(t-1)*(t+1)*q*x2^2/((t*q-1)*(t*q+1)*x3)+(t-1)^3*(t+1)^3*(1+t^2+t^4*q^2)*q*x2*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)^2*(t+1)^2*q*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(q^2*t^6+2*t^6*q^4-q^4*t^4+t^4*q^2-q^2*t^2+t^2-2-q^2)*q^3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)*(t+1)*(q^2+2-t^2+q^4*t^4-t^4*q^2-3*t^6*q^4+t^8*q^4-2*t^10*q^6-q^8*t^12+q^6*t^12+q^8*t^16+q^10*t^16)*q^2*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1)+(t-1)^2*(t+1)^2*(q^2+1)*q^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3*x2)+(t-1)*(t+1)*(1+q^4+2*q^2-2*q^2*t^2+t^4*q^6-q^4*t^4-3*q^6*t^6-t^6*q^4+2*t^8*q^6-t^10*q^6-q^8*t^10-t^14*q^10+t^14*q^8+2*q^10*t^16)*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(-q^2-2-q^2*t^2-q^4*t^4+2*t^6*q^4+t^10*q^6+q^8*t^12+t^14*q^8)*q^3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1)+(t-1)^2*(t+1)^2*(-1-q^2-q^2*t^2+t^2+t^4*q^2-q^4*t^4+2*t^6*q^4)*q^2*x3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)*(t+1)*q*x2^2/((t*q-1)*(t*q+1)*x1)+(t-1)^2*(t+1)^2*(1+t^2+t^4*q^2)*q*x2^2*x1/((t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1))+(t-1)^2*(t+1)^2*q*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*(-1-q^4-2*q^2-t^2*q^4-q^2*t^2+t^4*q^2-t^4*q^6-2*q^4*t^4+3*t^6*q^4-q^6*t^6-t^8*q^8+t^8*q^6+2*t^10*q^6-q^10*t^12+3*q^8*t^12+2*t^14*q^10)*x3*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)*(t+1)*(q^2+1-t^2+q^4*t^4-t^4*q^2+q^2*t^6-3*t^6*q^4+t^8*q^4-t^10*q^6+q^6*t^12-q^8*t^12+q^10*t^16)*q^2*x3/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1)+(t-1)*(t+1)*(-1-q^2+q^2*t^2+t^10*q^6)*q^2/((t*q-1)*(t*q+1)*(q^3*t^5+1)*(q^3*t^5-1)*x1*x3)+(t-1)*(t+1)*(1+q^4+2*q^2-3*q^2*t^2+t^4*q^6-q^4*t^4-3*q^6*t^6-t^6*q^4+t^8*q^4+2*t^8*q^6-t^10*q^6+t^14*q^8-t^14*q^10+q^10*t^16)*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(3*q^2+q^4+2+q^2*t^2-t^2+t^2*q^4-6*t^4*q^2+q^4*t^4-7*t^6*q^4+q^2*t^6+3*t^8*q^4-4*t^8*q^6+t^10*q^4+3*t^10*q^6-q^8*t^12-t^14*q^10+t^14*q^8+q^8*t^16+q^10*t^18)*q*x1/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(-q^2-2-q^2*t^2-q^4*t^4+2*t^6*q^4+t^10*q^6+q^6*t^12+t^14*q^8)*q*x2*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t+1)*(t-1)*x2^2*x1/((t*q-1)*(t*q+1)*x3)+(t-1)^3*(t+1)^3*(1+t^2+t^4*q^2)*q*x3*x1^2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1))+(t-1)*(t+1)*q^3/((q^3*t^5+1)*(q^3*t^5-1)*x1*x2*x3)+(t-1)^2*(t+1)^2*(3+3*q^2+q^4+2*q^2*t^2-t^2+t^2*q^4-6*t^4*q^2+q^4*t^4-8*t^6*q^4+q^2*t^6+2*t^8*q^4-4*t^8*q^6+t^10*q^4+2*t^10*q^6-2*q^8*t^12-t^14*q^10+t^14*q^8+q^8*t^16+q^10*t^16+2*q^10*t^18)*q^2/((q^3*t^5+1)*(q^3*t^5-1)*(t*q-1)*(t*q+1)*(t^3*q^2+1)*(t^3*q^2-1)*(t^2*q-1)*(t^2*q+1))+(t-1)^2*(t+1)^2*(-q^4-2*q^2-1-t^2*q^4-t^4*q^6+2*q^6*t^6+t^6*q^4+t^10*q^6+q^8*t^12+t^14*q^10)*q/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*(-1-q^2-q^2*t^2+t^2+t^4*q^2-q^4*t^4+2*t^6*q^4)*q*x3*x1/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*x2*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x3)+(t-1)^2*(t+1)^2*x3*x1^2/((t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x2)+(t-1)^2*(t+1)^2*q^4/((t*q+1)*(t*q-1)*(q^3*t^5+1)*(q^3*t^5-1)*x1*x2)+(t-1)^2*(t+1)^2*(-q^2-1-q^2*t^2-q^4*t^4+t^6*q^4+t^10*q^6+q^8*t^12+t^14*q^10)*q*x3*x2/((t^3*q^2-1)*(t^3*q^2+1)*(t*q+1)*(t*q-1)*(q^3*t^5-1)*(q^3*t^5+1)*x1) # needs sage.symbolic + sage: to_SR(E[mu]) - expected # long time (20s) # needs sage.symbolic 0 - sage: E = NonSymmetricMacdonaldPolynomials(["BC",1,2], q=q, q1=t^2,q2=-1) - sage: omega=E.keys().fundamental_weights() + sage: E = NonSymmetricMacdonaldPolynomials(["BC",1,2], q=q, q1=t^2, q2=-1) + sage: omega = E.keys().fundamental_weights() sage: mu = -4*omega[1]; mu (-4) - sage: expected = (t-1)*(t+1)*(-1+q^2*t^2-q^2-3*q^10-7*q^26*t^8+5*t^2*q^6-q^16-3*q^4+4*t^10*q^30-4*t^6*q^22-10*q^20*t^6+2*q^32*t^10-3*q^6-4*q^8+q^34*t^10-4*t^8*q^24-2*q^12-q^14+2*q^22*t^10+4*q^26*t^10+4*q^28*t^10+t^6*q^30-2*q^32*t^8-2*t^8*q^22+2*q^24*t^10-q^20*t^2-2*t^6*q^12+t^8*q^14+2*t^4*q^24-4*t^8*q^30+2*t^8*q^20-9*t^6*q^16+3*q^26*t^6+q^28*t^6+3*t^2*q^4+2*q^18*t^8-6*t^6*q^14+4*t^4*q^22-2*q^24*t^6+3*t^2*q^12+7*t^4*q^20-t^2*q^16+11*q^18*t^4-2*t^2*q^18+9*q^16*t^4-t^4*q^6+6*q^8*t^2+5*q^10*t^2-6*q^28*t^8+q^12*t^4+8*t^4*q^14-10*t^6*q^18-q^4*t^4+q^16*t^8-2*t^4*q^8)/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1)*(q^5*t^2+1)*(q^5*t^2-1))+(q^2+1)*(q^4+1)*(t-1)*(t+1)*(-1+q^2*t^2-q^2+t^2*q^6-q^4+t^6*q^22+3*q^10*t^4+t^2-q^8-2*t^8*q^24+q^22*t^10+q^26*t^10-2*t^8*q^22+q^24*t^10-4*t^6*q^12-2*t^8*q^20-3*t^6*q^16+2*t^2*q^4-t^6*q^10-2*t^6*q^14+t^8*q^12-t^2*q^12+2*q^16*t^4+q^8*t^2-q^10*t^2+3*q^12*t^4+2*t^4*q^14+t^6*q^18-2*q^4*t^4+q^16*t^8+q^20*t^10)*q*x1/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1)*(q^5*t^2+1)*(q^5*t^2-1))+(q^2+1)*(q^4+1)*(t-1)*(t+1)*(1+q^8+q^4+q^2-q^8*t^2-2*t^2*q^4-t^2*q^6+t^2*q^12-t^2+t^4*q^6-2*q^16*t^4-t^4*q^14-2*q^12*t^4+t^6*q^12+t^6*q^16+t^6*q^18+t^6*q^14)*q/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1)*x1)+(t-1)*(t+1)*(-1-q^2-q^6-q^4-q^8+t^2*q^4-t^2*q^14+t^2*q^6-q^10*t^2+q^8*t^2-t^2*q^12+q^12*t^4+q^10*t^4+q^16*t^4+2*t^4*q^14)*(q^4+1)/((q^7*t^2+1)*(q^7*t^2-1)*(t*q^4-1)*(t*q^4+1)*x1^2)+(t-1)*(t+1)*(q^4+1)*(q^2+1)*q/((t*q^4-1)*(t*q^4+1)*x1^3)+(q^4+1)*(t-1)*(t+1)*(1+q^6+q^8+q^2+q^4-q^2*t^2-3*t^2*q^4+q^10*t^2+t^2*q^12-2*t^2*q^6-q^8*t^2-2*q^16*t^4+q^4*t^4+t^4*q^6-q^10*t^4-2*q^12*t^4-2*t^4*q^14+t^6*q^12+t^6*q^18+2*t^6*q^16+t^6*q^14)*x1^2/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1))+(t-1)*(t+1)*(-1-t^2*q^6+t^2+t^4*q^8)*(q^4+1)*(q^2+1)*q*x1^3/((q^7*t^2+1)*(q^7*t^2-1)*(t*q^4-1)*(t*q^4+1))+1/x1^4+(t-1)*(t+1)*x1^4/((t*q^4-1)*(t*q^4+1)) # optional - sage.symbolic - sage: to_SR(E[mu]) - expected # optional - sage.symbolic + sage: expected = (t-1)*(t+1)*(-1+q^2*t^2-q^2-3*q^10-7*q^26*t^8+5*t^2*q^6-q^16-3*q^4+4*t^10*q^30-4*t^6*q^22-10*q^20*t^6+2*q^32*t^10-3*q^6-4*q^8+q^34*t^10-4*t^8*q^24-2*q^12-q^14+2*q^22*t^10+4*q^26*t^10+4*q^28*t^10+t^6*q^30-2*q^32*t^8-2*t^8*q^22+2*q^24*t^10-q^20*t^2-2*t^6*q^12+t^8*q^14+2*t^4*q^24-4*t^8*q^30+2*t^8*q^20-9*t^6*q^16+3*q^26*t^6+q^28*t^6+3*t^2*q^4+2*q^18*t^8-6*t^6*q^14+4*t^4*q^22-2*q^24*t^6+3*t^2*q^12+7*t^4*q^20-t^2*q^16+11*q^18*t^4-2*t^2*q^18+9*q^16*t^4-t^4*q^6+6*q^8*t^2+5*q^10*t^2-6*q^28*t^8+q^12*t^4+8*t^4*q^14-10*t^6*q^18-q^4*t^4+q^16*t^8-2*t^4*q^8)/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1)*(q^5*t^2+1)*(q^5*t^2-1))+(q^2+1)*(q^4+1)*(t-1)*(t+1)*(-1+q^2*t^2-q^2+t^2*q^6-q^4+t^6*q^22+3*q^10*t^4+t^2-q^8-2*t^8*q^24+q^22*t^10+q^26*t^10-2*t^8*q^22+q^24*t^10-4*t^6*q^12-2*t^8*q^20-3*t^6*q^16+2*t^2*q^4-t^6*q^10-2*t^6*q^14+t^8*q^12-t^2*q^12+2*q^16*t^4+q^8*t^2-q^10*t^2+3*q^12*t^4+2*t^4*q^14+t^6*q^18-2*q^4*t^4+q^16*t^8+q^20*t^10)*q*x1/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1)*(q^5*t^2+1)*(q^5*t^2-1))+(q^2+1)*(q^4+1)*(t-1)*(t+1)*(1+q^8+q^4+q^2-q^8*t^2-2*t^2*q^4-t^2*q^6+t^2*q^12-t^2+t^4*q^6-2*q^16*t^4-t^4*q^14-2*q^12*t^4+t^6*q^12+t^6*q^16+t^6*q^18+t^6*q^14)*q/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1)*x1)+(t-1)*(t+1)*(-1-q^2-q^6-q^4-q^8+t^2*q^4-t^2*q^14+t^2*q^6-q^10*t^2+q^8*t^2-t^2*q^12+q^12*t^4+q^10*t^4+q^16*t^4+2*t^4*q^14)*(q^4+1)/((q^7*t^2+1)*(q^7*t^2-1)*(t*q^4-1)*(t*q^4+1)*x1^2)+(t-1)*(t+1)*(q^4+1)*(q^2+1)*q/((t*q^4-1)*(t*q^4+1)*x1^3)+(q^4+1)*(t-1)*(t+1)*(1+q^6+q^8+q^2+q^4-q^2*t^2-3*t^2*q^4+q^10*t^2+t^2*q^12-2*t^2*q^6-q^8*t^2-2*q^16*t^4+q^4*t^4+t^4*q^6-q^10*t^4-2*q^12*t^4-2*t^4*q^14+t^6*q^12+t^6*q^18+2*t^6*q^16+t^6*q^14)*x1^2/((t*q^4-1)*(t*q^4+1)*(q^7*t^2-1)*(q^7*t^2+1)*(t*q^3-1)*(t*q^3+1))+(t-1)*(t+1)*(-1-t^2*q^6+t^2+t^4*q^8)*(q^4+1)*(q^2+1)*q*x1^3/((q^7*t^2+1)*(q^7*t^2-1)*(t*q^4-1)*(t*q^4+1))+1/x1^4+(t-1)*(t+1)*x1^4/((t*q^4-1)*(t*q^4+1)) # needs sage.symbolic + sage: to_SR(E[mu]) - expected # needs sage.symbolic 0 Type `BC` dual, comparison with hand calculations by Bogdan Ion:: @@ -1128,7 +1234,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): B[(0, 0)] sage: E[omega[1]] ((-q^2*q1^3*q2-q^2*q1^2*q2^2)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] - sage: Eomega1 = KL.one() * (q^2*(-q1/q2)^2*(1-(-q1/q2))) / (1-q^2*(-q1/q2)^4) + KL.monomial(omega[1]) + sage: Eomega1 = (KL.one() * (q^2*(-q1/q2)^2*(1-(-q1/q2))) / (1-q^2*(-q1/q2)^4) + ....: + KL.monomial(omega[1])) sage: E[omega[1]] == Eomega1 True @@ -1419,6 +1526,7 @@ def Q_to_Qcheck(self): alphacheck[1] + 2*alphacheck[2] sage: _.parent() Coroot lattice of the Root system of type ['C', 2, 1] + """ #assert self.cartan_type().is_untwisted_affine() Qcheck = self._T_Y.Y().keys() @@ -1436,12 +1544,10 @@ def Y(self): Lazy family ((i))_{i in Root lattice of the Root system of type ['B', 2, 1]} sage: _.keys().classical() Root lattice of the Root system of type ['B', 2] - sage: NonSymmetricMacdonaldPolynomials("C2~*").Y() Lazy family (<...Y_lambdacheck...>(i))_{i in Coroot lattice of the Root system of type ['C', 2, 1]^*} sage: _.keys().classical() Root lattice of the Root system of type ['C', 2] - sage: NonSymmetricMacdonaldPolynomials(["BC", 3, 2]).Y() Lazy family (<...Y_lambdacheck...>(i))_{i in Coroot lattice of the Root system of type ['BC', 3, 2]} sage: _.keys().classical() @@ -1505,8 +1611,10 @@ def twist(self, mu, i): EXAMPLES:: + sage: # needs sage.libs.gap sage: W = WeylGroup(["B",3]) - sage: W.element_class._repr_=lambda x: "".join(str(i) for i in x.reduced_word()) + sage: W.element_class._repr_ = lambda x: "".join(str(i) + ....: for i in x.reduced_word()) sage: K = QQ['q1,q2'] sage: q1, q2 = K.gens() sage: KW = W.algebra(K) @@ -1574,9 +1682,12 @@ def __getitem__(self, mu): sage: E[omega[2]] Traceback (most recent call last): ... - ValueError: 1/2*e[0] + 1/2*e[1] does not lift to a level 0 element of the affine weight lattice + ValueError: 1/2*e[0] + 1/2*e[1] does not lift to a level 0 element + of the affine weight lattice sage: E[2*omega[2]] - ((q^2*q1^2+q^2*q1*q2)/(q^2*q1^2-q2^2))*B[(0, 0)] + ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(1, 0)] + B[(1, 1)] + ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(0, 1)] + ((q^2*q1^2+q^2*q1*q2)/(q^2*q1^2-q2^2))*B[(0, 0)] + + ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(1, 0)] + B[(1, 1)] + + ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(0, 1)] """ muaff = self._L.embed_at_level(mu, 0) if not all(muaff.scalar(coroot) in ZZ for coroot in self._L.simple_coroots()): @@ -1594,14 +1705,14 @@ def rho_prime(self): # Should be rho_prime_check Untwisted case:: - sage: NonSymmetricMacdonaldPolynomials("B2~").rho_prime() # CHECKME + sage: NonSymmetricMacdonaldPolynomials("B2~").rho_prime() # CHECKME 3/2*e[0] + 1/2*e[1] sage: NonSymmetricMacdonaldPolynomials("B2~").rho_prime().parent() Coambient space of the Root system of type ['C', 2, 1] Twisted case:: - sage: NonSymmetricMacdonaldPolynomials("B2~*").rho_prime() # CHECKME + sage: NonSymmetricMacdonaldPolynomials("B2~*").rho_prime() # CHECKME 2*e[0] + e[1] sage: NonSymmetricMacdonaldPolynomials("B2~*").rho_prime().parent() Ambient space of the Root system of type ['B', 2, 1]^* @@ -1640,7 +1751,7 @@ def eigenvalue_experimental(self, mu, l): sage: KL = RootSystem(["A",1,1]).ambient_space().algebra(K) sage: E = NonSymmetricMacdonaldPolynomials(KL,q, q1, q2) sage: L0 = E.keys() - sage: E.eigenvalues(L0([0,0])) # Checked by hand by Mark and Arun + sage: E.eigenvalues(L0([0,0])) # Checked by hand by Mark and Arun [1/(q*t), t] sage: alpha = E.Y().keys().simple_roots() sage: E.eigenvalue_experimental(L0([0,0]), alpha[0]) # todo: not implemented @@ -1676,13 +1787,15 @@ def eigenvalue_experimental(self, mu, l): sage: E = NonSymmetricMacdonaldPolynomials(KL,q, q1, q2) sage: L0 = E.keys() sage: alpha = L.simple_coroots() - sage: E.eigenvalue(L0((0,0)), alpha[0]) # not checked # not tested + + sage: # not tested + sage: E.eigenvalue(L0((0,0)), alpha[0]) # not checked q/t - sage: E.eigenvalue(L0((1,0)), alpha[1]) # What Mark got by hand # not tested + sage: E.eigenvalue(L0((1,0)), alpha[1]) # What Mark got by hand q - sage: E.eigenvalue(L0((1,0)), alpha[2]) # not checked # not tested + sage: E.eigenvalue(L0((1,0)), alpha[2]) # not checked t - sage: E.eigenvalue(L0((1,0)), alpha[0]) # not checked # not tested + sage: E.eigenvalue(L0((1,0)), alpha[0]) # not checked 1 sage: L = RootSystem("B2~*").ambient_space() @@ -1770,18 +1883,26 @@ def symmetric_macdonald_polynomial(self, mu): sage: E.symmetric_macdonald_polynomial(om[2]) B[(1, 1, 0)] + B[(1, 0, 1)] + B[(0, 1, 1)] sage: E.symmetric_macdonald_polynomial(2*om[1]) - ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(1, 1, 0)] + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(1, 0, 1)] + B[(2, 0, 0)] + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(0, 1, 1)] + B[(0, 2, 0)] + B[(0, 0, 2)] + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(1, 1, 0)] + + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(1, 0, 1)] + B[(2, 0, 0)] + + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(0, 1, 1)] + B[(0, 2, 0)] + B[(0, 0, 2)] sage: f = E.symmetric_macdonald_polynomial(E.L0()((2,1,0))); f - ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, 1)] + B[(1, 2, 0)] + B[(1, 0, 2)] + B[(2, 1, 0)] + B[(2, 0, 1)] + B[(0, 1, 2)] + B[(0, 2, 1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, 1)] + B[(1, 2, 0)] + + B[(1, 0, 2)] + B[(2, 1, 0)] + B[(2, 0, 1)] + B[(0, 1, 2)] + B[(0, 2, 1)] We compare with the type `A` Macdonald polynomials coming from symmetric functions:: + sage: # needs sage.combinat sage: P = SymmetricFunctions(K).macdonald().P() sage: g = P[2,1].expand(3); g - x0^2*x1 + x0*x1^2 + x0^2*x2 + (2*q*t^2 - q*t - q + t^2 + t - 2)/(q*t^2 - 1)*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x0^2*x1 + x0*x1^2 + x0^2*x2 + + (2*q*t^2 - q*t - q + t^2 + t - 2)/(q*t^2 - 1)*x0*x1*x2 + + x1^2*x2 + x0*x2^2 + x1*x2^2 sage: fe = f.expand(g.parent().gens()); fe - x0^2*x1 + x0*x1^2 + x0^2*x2 + (2*q*v^4 - q*v^2 - q + v^4 + v^2 - 2)/(q*v^4 - 1)*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x0^2*x1 + x0*x1^2 + x0^2*x2 + + (2*q*v^4 - q*v^2 - q + v^4 + v^2 - 2)/(q*v^4 - 1)*x0*x1*x2 + + x1^2*x2 + x0*x2^2 + x1*x2^2 sage: g.map_coefficients(lambda x: x.subs(t=v*v)) == fe True diff --git a/src/sage/combinat/root_system/pieri_factors.py b/src/sage/combinat/root_system/pieri_factors.py index e0e3053d8e3..ee06d692b31 100644 --- a/src/sage/combinat/root_system/pieri_factors.py +++ b/src/sage/combinat/root_system/pieri_factors.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap r""" Pieri Factors """ @@ -13,6 +14,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.constant_function import ConstantFunction from sage.misc.call import attrcall +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.structure.parent import Parent @@ -24,9 +26,10 @@ import sage.combinat.ranker from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet from sage.combinat.root_system.root_system import RootSystem -from sage.combinat.root_system.dynkin_diagram import DynkinDiagram from sage.combinat.root_system.weyl_group import WeylGroup -from sage.graphs.digraph import DiGraph + +lazy_import('sage.graphs.digraph', 'DiGraph') +lazy_import('sage.combinat.root_system.dynkin_diagram', 'DynkinDiagram') class PieriFactors(UniqueRepresentation, Parent): diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py index 74aa2bf1390..c10879e2381 100644 --- a/src/sage/combinat/root_system/plot.py +++ b/src/sage/combinat/root_system/plot.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.geometry.polyhedron sage.plot sage.symbolic r""" Tutorial: visualizing root systems @@ -5,7 +6,7 @@ space, and form the fundamental combinatorial data underlying Coxeter and Weyl groups, Lie algebras and groups, etc. The theory can be a bit intimidating at first because of the many technical gadgets (roots, -coroots, weights, ...). Vizualizing them goes a long way toward +coroots, weights, ...). Visualizing them goes a long way toward building a geometric intuition. This tutorial starts from simple plots and guides you all the way to @@ -29,7 +30,7 @@ angle:: sage: L = RootSystem(["A",2]).ambient_space() - sage: L.plot() # optional - sage.plot sage.symbolic + sage: L.plot() Graphics object consisting of 13 graphics primitives .. PLOT:: @@ -56,7 +57,7 @@ full picture in 3D:: sage: L = RootSystem(["A",2]).ambient_space() - sage: L.plot(projection=False) # optional - sage.plot sage.symbolic + sage: L.plot(projection=False) Graphics3d Object .. PLOT:: @@ -72,7 +73,7 @@ `G_2`:: sage: L = RootSystem(["G",2]).ambient_space() - sage: L.plot(reflection_hyperplanes="all") # optional - sage.plot sage.symbolic + sage: L.plot(reflection_hyperplanes="all") Graphics object consisting of 21 graphics primitives .. PLOT:: @@ -107,7 +108,7 @@ its corresponding reflection hyperplane:: sage: L = RootSystem(["A",2]).weight_space() - sage: L.plot(roots="all", reflection_hyperplanes="all").show(figsize=15) # optional - sage.plot sage.symbolic + sage: L.plot(roots="all", reflection_hyperplanes="all").show(figsize=15) .. NOTE:: @@ -128,7 +129,7 @@ sage: Q = RootSystem(["G",2]).root_space() sage: L = RootSystem(["G",2]).ambient_space() - sage: L.plot(roots=list(Q.positive_roots()), fundamental_weights=False) # optional - sage.plot sage.symbolic + sage: L.plot(roots=list(Q.positive_roots()), fundamental_weights=False) Graphics object consisting of 17 graphics primitives .. PLOT:: @@ -149,7 +150,7 @@ sage: L = RootSystem(["E",8]).ambient_space() sage: L.dimension() 8 - sage: L.plot(roots="all", reflection_hyperplanes=False, # long time # optional - sage.plot sage.symbolic + sage: L.plot(roots="all", reflection_hyperplanes=False, # long time ....: projection=lambda v: M*vector(v), labels=False) Graphics3d Object @@ -185,7 +186,7 @@ elements of the Weyl group. We enlarge a bit the bounding box to make sure everything fits in the picture:: - sage: RootSystem(["G",2]).ambient_space().plot(alcoves=True, # optional - sage.plot sage.symbolic + sage: RootSystem(["G",2]).ambient_space().plot(alcoves=True, ....: alcove_labels=True, bounding_box=5) Graphics object consisting of 37 graphics primitives @@ -196,7 +197,7 @@ The same picture in 3D, for type `B_3`:: - sage: RootSystem(["B",3]).ambient_space().plot(alcoves=True, alcove_labels=True) # optional - sage.plot sage.symbolic + sage: RootSystem(["B",3]).ambient_space().plot(alcoves=True, alcove_labels=True) Graphics3d Object .. PLOT:: @@ -215,7 +216,7 @@ We now draw the usual alcove picture for affine type `A_2^{(1)}`:: sage: L = RootSystem(["A",2,1]).ambient_space() - sage: L.plot() # long time # optional - sage.plot sage.symbolic + sage: L.plot() # long time Graphics object consisting of 160 graphics primitives .. PLOT:: @@ -233,7 +234,7 @@ we are visualizing here what's happening at level `1`. Here is the full picture in 3D:: - sage: L.plot(bounding_box=[[-3,3],[-3,3],[-1,1]], affine=False) # long time # optional - sage.plot sage.symbolic + sage: L.plot(bounding_box=[[-3,3],[-3,3],[-1,1]], affine=False) # long time Graphics3d Object .. PLOT:: @@ -248,7 +249,7 @@ It's usually more readable to only draw the intersection of the reflection hyperplanes with the level `1` hyperplane:: - sage: L.plot(affine=False, level=1) # long time # optional - sage.plot sage.symbolic + sage: L.plot(affine=False, level=1) # long time Graphics3d Object .. PLOT:: @@ -261,7 +262,7 @@ level 1:: sage: L = RootSystem(["G",2,1]).ambient_space() - sage: L.plot(affine=False, level=1) # optional - sage.plot sage.symbolic + sage: L.plot(affine=False, level=1) Graphics3d Object .. PLOT:: @@ -276,8 +277,8 @@ options of the :meth:`~sage.plot.plot3d.base.Graphics3d.show` method:: - sage: p = L.plot(affine=False, level=1) # optional - sage.plot sage.symbolic - sage: p.show(aspect_ratio=[1,1,2], frame=False) # optional - sage.plot sage.symbolic + sage: p = L.plot(affine=False, level=1) + sage: p.show(aspect_ratio=[1,1,2], frame=False) .. TOPIC:: Exercise @@ -291,7 +292,7 @@ `u = vs_i`; the color of that wall is given by `i`:: sage: L = RootSystem(["C",2,1]).ambient_space() - sage: L.plot(coroots="simple", alcove_labels=True) # long time # optional - sage.plot sage.symbolic + sage: L.plot(coroots="simple", alcove_labels=True) # long time Graphics object consisting of 216 graphics primitives .. PLOT:: @@ -310,7 +311,7 @@ sage: positive_roots = RecursivelyEnumeratedSet(seed, succ, structure='graded') sage: it = iter(positive_roots) sage: first_positive_roots = [next(it) for i in range(10)] - sage: L.plot(roots=first_positive_roots, affine=False, alcoves=False) # optional - sage.plot sage.symbolic + sage: L.plot(roots=first_positive_roots, affine=False, alcoves=False) Graphics object consisting of 24 graphics primitives .. PLOT:: @@ -348,12 +349,12 @@ sage: positive_coroots = RecursivelyEnumeratedSet(seed, succ, structure='graded') sage: it = iter(positive_coroots) sage: first_positive_coroots = [next(it) for i in range(20)] - sage: p = L.plot(fundamental_chamber=True, # optional - sage.plot sage.symbolic + sage: p = L.plot(fundamental_chamber=True, ....: reflection_hyperplanes=first_positive_coroots, ....: affine=False, alcove_labels=1, ....: bounding_box=[[-9,9],[-1,2]], ....: projection=lambda x: matrix([[1,-1],[1,1]])*vector(x)) - sage: p.show(figsize=20) # long time # optional - sage.plot sage.symbolic + sage: p.show(figsize=20) # long time Higher dimension affine pictures @@ -363,7 +364,7 @@ tiled by the alcoves, each of which is a 3D simplex:: sage: L = RootSystem(["A",3,1]).ambient_space() - sage: L.plot(reflection_hyperplanes=False, bounding_box=85/100) # long time # optional - sage.plot sage.symbolic + sage: L.plot(reflection_hyperplanes=False, bounding_box=85/100) # long time Graphics3d Object .. PLOT:: @@ -379,7 +380,7 @@ the Weyl group:: sage: W = L.weyl_group() - sage: L.plot(reflection_hyperplanes=False, alcoves=[W.one()], bounding_box=2) # optional - sage.plot sage.symbolic + sage: L.plot(reflection_hyperplanes=False, alcoves=[W.one()], bounding_box=2) Graphics3d Object .. PLOT:: @@ -393,7 +394,7 @@ center in the root lattice:: sage: W = L.weyl_group() - sage: L.plot(reflection_hyperplanes=False, alcoves=[[0,0]], bounding_box=2) # optional - sage.plot sage.symbolic + sage: L.plot(reflection_hyperplanes=False, alcoves=[[0,0]], bounding_box=2) Graphics3d Object .. PLOT:: @@ -414,10 +415,10 @@ sage: W = L.weyl_group() sage: alcoves = [~w for d in range(12) ....: for w in W.affine_grassmannian_elements_of_given_length(d)] - sage: p = L.plot_fundamental_chamber("classical") # optional - sage.plot sage.symbolic - sage: p += L.plot_alcoves(alcoves=alcoves, wireframe=True) # optional - sage.plot sage.symbolic - sage: p += L.plot_fundamental_weights() # optional - sage.plot sage.symbolic - sage: p.show(frame=False) # optional - sage.plot sage.symbolic + sage: p = L.plot_fundamental_chamber("classical") + sage: p += L.plot_alcoves(alcoves=alcoves, wireframe=True) + sage: p += L.plot_fundamental_weights() + sage: p.show(frame=False) .. PLOT:: :width: 300 px @@ -452,7 +453,7 @@ sage: L = RootSystem(["A",2,1]).ambient_space() sage: w1 = [0,2,1,2,0,2,1,0,2,1,2,1,2,0,2,0,1,2,0] - sage: L.plot(alcove_walk=w1, bounding_box=6) # long time # optional - sage.plot sage.symbolic + sage: L.plot(alcove_walk=w1, bounding_box=6) # long time Graphics object consisting of 535 graphics primitives .. PLOT:: @@ -467,7 +468,7 @@ instead, it is actually built on top of many methods (see the list below) that can be called independently and combined at will:: - sage: L.plot_roots() + L.plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: L.plot_roots() + L.plot_reflection_hyperplanes() Graphics object consisting of 12 graphics primitives .. PLOT:: @@ -483,9 +484,9 @@ tend to pollute the picture. Annoyingly they come back when combining them. Here is a workaround:: - sage: p = L.plot_roots() + L.plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic - sage: p.axes(False) # optional - sage.plot sage.symbolic - sage: p # optional - sage.plot sage.symbolic + sage: p = L.plot_roots() + L.plot_reflection_hyperplanes() + sage: p.axes(False) + sage: p Graphics object consisting of 12 graphics primitives .. PLOT:: @@ -502,14 +503,15 @@ :meth:`~sage.combinat.root_system.root_lattice_realizations.RootLatticeRealizations.ParentMethods.plot_parse_options`, and pass it down to each piece. We use this to plot our two walks:: + sage: # long time sage: plot_options = L.plot_parse_options(bounding_box=[[-2,5],[-2,6]]) sage: w2 = [2,1,2,0,2,0,2,1,2,0,1,2,1,2,1,0,1,2,0,2,0,1,2,0,2] - sage: p = L.plot_alcoves(plot_options=plot_options) # long time # optional - sage.plot sage.symbolic - sage: p += L.plot_alcove_walk(w1, color="green", # long time # optional - sage.plot sage.symbolic + sage: p = L.plot_alcoves(plot_options=plot_options) + sage: p += L.plot_alcove_walk(w1, color="green", ....: plot_options=plot_options) - sage: p += L.plot_alcove_walk(w2, color="orange", # long time # optional - sage.plot sage.symbolic + sage: p += L.plot_alcove_walk(w2, color="orange", ....: plot_options=plot_options) - sage: p # long time # optional - sage.plot sage.symbolic + sage: p Graphics object consisting of ... graphics primitives .. PLOT:: @@ -525,12 +527,12 @@ And another with some foldings:: - sage: p += L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # optional - sage.plot sage.symbolic + sage: p += L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], ....: foldings=[False, False, True, False, False, ....: False, True, False, True, False], ....: color="purple") - sage: p.axes(False) # optional - sage.plot sage.symbolic - sage: p.show(figsize=20) # optional - sage.plot sage.symbolic + sage: p.axes(False) + sage: p.show(figsize=20) .. PLOT:: :width: 300 px @@ -551,19 +553,20 @@ Here we show a weight at level `0` and the reduced word implementing the translation by this weight:: + sage: # long time sage: L = RootSystem(["A",2,1]).ambient_space() sage: P = RootSystem(["A",2,1]).weight_space(extended=True) sage: Lambda = P.fundamental_weights() sage: t = 6*Lambda[1] - 2*Lambda[2] - 4*Lambda[0] sage: walk = L.reduced_word_of_translation(L(t)) sage: plot_options = L.plot_parse_options(bounding_box=[[-2,5],[-2,5]]) - sage: p = L.plot(plot_options=plot_options) # long time # optional - sage.plot sage.symbolic - sage: p += L.plot_alcove_walk(walk, color="green", # long time # optional - sage.plot sage.symbolic + sage: p = L.plot(plot_options=plot_options) + sage: p += L.plot_alcove_walk(walk, color="green", ....: plot_options=plot_options) - sage: p += plot_options.family_of_vectors({t: L(t)}) # long time # optional - sage.plot sage.symbolic - sage: plot_options.finalize(p) # long time # optional - sage.plot sage.symbolic + sage: p += plot_options.family_of_vectors({t: L(t)}) + sage: plot_options.finalize(p) Graphics object consisting of ... graphics primitives - sage: p # long time # optional - sage.plot sage.symbolic + sage: p Graphics object consisting of ... graphics primitives .. PLOT:: @@ -591,7 +594,7 @@ sage: L = RootSystem(["B",3,1]).ambient_space() sage: w3 = [0,2,1,3,2,0,2,1,0,2,3,1,2,1,3,2,0,2,0,1,2,0] - sage: (L.plot_fundamental_weights() # optional - sage.plot sage.symbolic + sage: (L.plot_fundamental_weights() ....: + L.plot_reflection_hyperplanes(bounding_box=2) + L.plot_alcove_walk(w3)) Graphics3d Object @@ -619,7 +622,7 @@ sage: L = RootSystem(["A",3,1]).ambient_space() sage: alcoves = cartesian_product([[0,1],[0,1],[0,1]]) sage: color = lambda i: "black" if i==0 else None - sage: L.plot_alcoves(alcoves=alcoves, color=color, # long time # optional - sage.plot sage.symbolic + sage: L.plot_alcoves(alcoves=alcoves, color=color, # long time ....: bounding_box=10, wireframe=True).show(frame=False) .. PLOT:: @@ -645,9 +648,9 @@ Now you can create your own customized color Coxeter graph paper:: sage: L = RootSystem(["C",2,1]).ambient_space() - sage: p = L.plot(bounding_box=[[-8,9],[-5,7]], # long time (10 s) # optional - sage.plot sage.symbolic + sage: p = L.plot(bounding_box=[[-8,9],[-5,7]], # long time (10 s) ....: coroots="simple") - sage: p # long time # optional - sage.plot sage.symbolic + sage: p # long time Graphics object consisting of ... graphics primitives .. PLOT:: @@ -660,7 +663,7 @@ if printed on paper. Instead, we recommend saving the picture in postscript or svg before printing it:: - sage: p.save("C21paper.eps") # not tested # optional - sage.plot sage.symbolic + sage: p.save("C21paper.eps") # not tested .. NOTE:: @@ -687,11 +690,11 @@ sage: W = L.weyl_group() sage: g = W.cayley_graph(side="right") sage: positions = {w: plot_options.projection(w.action(rho)) for w in W} - sage: p = L.plot_alcoves() # optional - sage.plot sage.symbolic - sage: p += g.plot(pos=positions, vertex_size=0, # optional - sage.plot sage.symbolic + sage: p = L.plot_alcoves() + sage: p += g.plot(pos=positions, vertex_size=0, ....: color_by_label=plot_options.color) - sage: p.axes(False) # optional - sage.plot sage.symbolic - sage: p # optional - sage.plot sage.symbolic + sage: p.axes(False) + sage: p Graphics object consisting of 30 graphics primitives .. PLOT:: @@ -718,9 +721,9 @@ sage: W = L.weyl_group() sage: g = W.cayley_graph(side="right") sage: positions = {w: plot_options.projection(w.action(rho)) for w in W} - sage: p = L.plot_roots() # optional - sage.plot sage.symbolic - sage: p += g.plot3d(pos3d=positions, color_by_label=plot_options.color) # optional - sage.plot sage.symbolic - sage: p # optional - sage.plot sage.symbolic + sage: p = L.plot_roots() + sage: p += g.plot3d(pos3d=positions, color_by_label=plot_options.color) + sage: p Graphics3d Object .. PLOT:: @@ -754,15 +757,15 @@ sage: C = crystals.Tableaux(["A",2], shape=[4,2]) sage: L = C.weight_lattice_realization() - sage: plot_options = L.plot_parse_options() # optional - sage.plot sage.symbolic + sage: plot_options = L.plot_parse_options() sage: g = C.digraph() - sage: positions = {x: plot_options.projection(x.weight()) for x in C} # optional - sage.plot sage.symbolic - sage: p = L.plot() # optional - sage.plot sage.symbolic - sage: p += g.plot(pos=positions, # optional - sage.plot sage.symbolic + sage: positions = {x: plot_options.projection(x.weight()) for x in C} + sage: p = L.plot() + sage: p += g.plot(pos=positions, ....: color_by_label=plot_options.color, vertex_size=0) - sage: p.axes(False) # optional - sage.plot sage.symbolic - sage: p.show(figsize=15) # optional - sage.plot sage.symbolic + sage: p.axes(False) + sage: p.show(figsize=15) .. PLOT:: :width: 300 px @@ -792,11 +795,11 @@ sage: L = C.weight_lattice_realization() sage: plot_options = L.plot_parse_options() sage: g = C.digraph() - sage: positions = {x: plot_options.projection(x.weight()) for x in C} # optional - sage.plot sage.symbolic - sage: p = L.plot(reflection_hyperplanes=False, fundamental_weights=False) # optional - sage.plot sage.symbolic - sage: p += g.plot3d(pos3d=positions, vertex_labels=True, # optional - sage.plot sage.symbolic + sage: positions = {x: plot_options.projection(x.weight()) for x in C} + sage: p = L.plot(reflection_hyperplanes=False, fundamental_weights=False) + sage: p += g.plot3d(pos3d=positions, vertex_labels=True, ....: color_by_label=plot_options.color, edge_labels=True) - sage: p # optional - sage.plot sage.symbolic + sage: p Graphics3d Object .. TOPIC:: Exercise @@ -858,7 +861,8 @@ def __init__(self, space, 2 sage: options._projections [Weight space over the Rational Field of the Root system of type ['B', 2], - ] + ] sage: L = RootSystem(['B',2,1]).ambient_space() sage: options = L.plot_parse_options() @@ -866,24 +870,29 @@ def __init__(self, space, 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], - ] + ] sage: options = L.plot_parse_options(affine=True) sage: options.dimension 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], - ] + ] sage: options = L.plot_parse_options(affine=False) sage: options._projections - [] + [] sage: options.dimension 3 - sage: options = L.plot_parse_options(affine=False, projection='barycentric') + sage: options = L.plot_parse_options(affine=False, + ....: projection='barycentric') sage: options._projections - [] + [] sage: options.dimension 3 """ @@ -986,7 +995,7 @@ def text(self, label, position, rgbcolor=(0,0,0)): sage: list(options.text(L.simple_root(2), [1,0], rgbcolor=(1,0.5,0))) [Text '$\alpha_{2}$' at the point (1.0,0.0)] - sage: options = RootSystem(["A",2]).root_lattice().plot_parse_options(labels=False) + sage: options = L.plot_parse_options(labels=False) sage: options.text("coucou", [0,1]) 0 @@ -1289,7 +1298,8 @@ def family_of_vectors(self, vectors): Handling of colors and labels:: - sage: color=lambda i: "purple" if i==1 else None + sage: def color(i): + ....: return "purple" if i==1 else None sage: options = L.plot_parse_options(labels=False, color=color) sage: p = options.family_of_vectors(alpha) sage: list(p) @@ -1362,26 +1372,30 @@ def cone(self, rays=[], lines=[], color="black", thickness=1, alpha=1, wireframe sage: L = RootSystem(["A",2]).root_lattice() sage: options = L.plot_parse_options() sage: alpha = L.simple_roots() - sage: p = options.cone(rays=[alpha[1]], lines=[alpha[2]], color='green', label=2) - sage: p + sage: p = options.cone(rays=[alpha[1]], lines=[alpha[2]], + ....: color='green', label=2); p Graphics object consisting of 2 graphics primitives sage: list(p) [Polygon defined by 4 points, Text '$2$' at the point (3.15...,3.15...)] - sage: options.cone(rays=[alpha[1]], lines=[alpha[2]], color='green', label=2, as_polyhedron=True) + sage: options.cone(rays=[alpha[1]], lines=[alpha[2]], + ....: color='green', label=2, as_polyhedron=True) A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line An empty result, being outside of the bounding box:: - sage: options = L.plot_parse_options(labels=True, bounding_box=[[-10,-9]]*2) - sage: options.cone(rays=[alpha[1]], lines=[alpha[2]], color='green', label=2) + sage: options = L.plot_parse_options(labels=True, + ....: bounding_box=[[-10,-9]]*2) + sage: options.cone(rays=[alpha[1]], lines=[alpha[2]], + ....: color='green', label=2) 0 Test that the options are properly passed down:: sage: L = RootSystem(["A",2]).root_lattice() sage: options = L.plot_parse_options() - sage: p = options.cone(rays=[alpha[1]+alpha[2]], color='green', label=2, thickness=4, alpha=.5) + sage: p = options.cone(rays=[alpha[1] + alpha[2]], + ....: color='green', label=2, thickness=4, alpha=.5) sage: list(p) [Line defined by 2 points, Text '$2$' at the point (3.15...,3.15...)] sage: sorted(p[0].options().items()) @@ -1463,7 +1477,8 @@ def reflection_hyperplane(self, coroot, as_polyhedron=False): sage: L = RootSystem(["A",3,1]).ambient_space() sage: alphacheck = L.simple_coroots() sage: options = L.plot_parse_options() - sage: H = options.reflection_hyperplane(alphacheck[1], as_polyhedron=True); H + sage: H = options.reflection_hyperplane(alphacheck[1], + ....: as_polyhedron=True); H A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 2 lines sage: H.lines() (A line in the direction (0, 0, 1), A line in the direction (0, 1, 0)) @@ -1541,25 +1556,25 @@ def barycentric_projection_matrix(n, angle=0): Three vectors in dimension 2:: - sage: barycentric_projection_matrix(2) # optional - sage.symbolic + sage: barycentric_projection_matrix(2) [ 1/2*sqrt(3) -1/2*sqrt(3) 0] [ 1/2 1/2 -1] Four vectors in dimension 3:: - sage: m = barycentric_projection_matrix(3); m # optional - sage.symbolic + sage: m = barycentric_projection_matrix(3); m [ 1/3*sqrt(3)*sqrt(2) -1/3*sqrt(3)*sqrt(2) 0 0] [ 1/3*sqrt(2) 1/3*sqrt(2) -2/3*sqrt(2) 0] [ 1/3 1/3 1/3 -1] The columns give four vectors that sum up to zero:: - sage: sum(m.columns()) # optional - sage.symbolic + sage: sum(m.columns()) (0, 0, 0) and have regular mutual angles:: - sage: m.transpose()*m # optional - sage.symbolic + sage: m.transpose()*m [ 1 -1/3 -1/3 -1/3] [-1/3 1 -1/3 -1/3] [-1/3 -1/3 1 -1/3] @@ -1567,19 +1582,19 @@ def barycentric_projection_matrix(n, angle=0): Here is a plot of them:: - sage: sum(arrow((0,0,0),x) for x in m.columns()) # optional - sage.plot sage.symbolic + sage: sum(arrow((0,0,0),x) for x in m.columns()) Graphics3d Object For 2D drawings of root systems, it is desirable to rotate the result to match with the usual conventions:: - sage: barycentric_projection_matrix(2, angle=2*pi/3) # optional - sage.symbolic + sage: barycentric_projection_matrix(2, angle=2*pi/3) [ 1/2 -1 1/2] [ 1/2*sqrt(3) 0 -1/2*sqrt(3)] TESTS:: - sage: for n in range(1, 7): # optional - sage.symbolic + sage: for n in range(1, 7): ....: m = barycentric_projection_matrix(n) ....: assert sum(m.columns()).is_zero() ....: assert matrix(QQ, n+1,n+1, lambda i,j: 1 if i==j else -1/n) == m.transpose()*m diff --git a/src/sage/combinat/root_system/reflection_group_c.pyx b/src/sage/combinat/root_system/reflection_group_c.pyx index d709a6dceec..247e9a62c02 100644 --- a/src/sage/combinat/root_system/reflection_group_c.pyx +++ b/src/sage/combinat/root_system/reflection_group_c.pyx @@ -150,18 +150,20 @@ cdef class Iterator(): """ EXAMPLES:: + sage: # optional - gap3 sage: from sage.combinat.root_system.reflection_group_c import Iterator - sage: W = ReflectionGroup(["B", 4]) # optional - gap3 - sage: N = W.number_of_reflections() # optional - gap3 - sage: I = Iterator(W, N) # optional - gap3 - sage: len(list(I)) == W.cardinality() # optional - gap3 + sage: W = ReflectionGroup(["B", 4]) + sage: N = W.number_of_reflections() + sage: I = Iterator(W, N) + sage: len(list(I)) == W.cardinality() True - sage: I = Iterator(W, N, "breadth", False) # optional - gap3 - sage: len(list(I)) == W.cardinality() # optional - gap3 + sage: # optional - gap3 + sage: I = Iterator(W, N, "breadth", False) + sage: len(list(I)) == W.cardinality() True - sage: I = Iterator(W, N, "parabolic") # optional - gap3 - sage: len(list(I)) == W.cardinality() # optional - gap3 + sage: I = Iterator(W, N, "parabolic") + sage: len(list(I)) == W.cardinality() True """ # the breadth search iterator is ~2x slower as it diff --git a/src/sage/combinat/root_system/reflection_group_complex.py b/src/sage/combinat/root_system/reflection_group_complex.py index 3adeea5d5c7..f0cd54d009a 100644 --- a/src/sage/combinat/root_system/reflection_group_complex.py +++ b/src/sage/combinat/root_system/reflection_group_complex.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap r""" Finite complex reflection groups ---------------------------------- @@ -21,17 +22,18 @@ or with Shephard-Todd types:: - sage: ReflectionGroup((1,1,3)) # optional - gap3 + sage: # optional - gap3 + sage: ReflectionGroup((1,1,3)) Irreducible real reflection group of rank 2 and type A2 - sage: ReflectionGroup((2,1,3)) # optional - gap3 + sage: ReflectionGroup((2,1,3)) Irreducible real reflection group of rank 3 and type B3 - sage: ReflectionGroup((3,1,3)) # optional - gap3 + sage: ReflectionGroup((3,1,3)) Irreducible complex reflection group of rank 3 and type G(3,1,3) - sage: ReflectionGroup((4,2,3)) # optional - gap3 + sage: ReflectionGroup((4,2,3)) Irreducible complex reflection group of rank 3 and type G(4,2,3) - sage: ReflectionGroup(4) # optional - gap3 + sage: ReflectionGroup(4) Irreducible complex reflection group of rank 2 and type ST4 - sage: ReflectionGroup(31) # optional - gap3 + sage: ReflectionGroup(31) Irreducible complex reflection group of rank 4 and type ST31 Also reducible types are allowed using concatenation:: @@ -398,14 +400,15 @@ def index_set(self): EXAMPLES:: - sage: W = ReflectionGroup((1,1,4)) # optional - gap3 - sage: W.index_set() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,4)) + sage: W.index_set() (1, 2, 3) - sage: W = ReflectionGroup((1,1,4), index_set=[1,3,'asdf']) # optional - gap3 - sage: W.index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), index_set=[1,3,'asdf']) + sage: W.index_set() (1, 3, 'asdf') - sage: W = ReflectionGroup((1,1,4), index_set=('a', 'b', 'c')) # optional - gap3 - sage: W.index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), index_set=('a', 'b', 'c')) + sage: W.index_set() ('a', 'b', 'c') """ return self._index_set @@ -450,14 +453,15 @@ def hyperplane_index_set(self): EXAMPLES:: - sage: W = ReflectionGroup((1,1,4)) # optional - gap3 - sage: W.hyperplane_index_set() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,4)) + sage: W.hyperplane_index_set() (1, 2, 3, 4, 5, 6) - sage: W = ReflectionGroup((1,1,4), hyperplane_index_set=[1,3,'asdf',7,9,11]) # optional - gap3 - sage: W.hyperplane_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), hyperplane_index_set=[1,3,'asdf',7,9,11]) + sage: W.hyperplane_index_set() (1, 3, 'asdf', 7, 9, 11) - sage: W = ReflectionGroup((1,1,4),hyperplane_index_set=('a','b','c','d','e','f')) # optional - gap3 - sage: W.hyperplane_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4),hyperplane_index_set=('a','b','c','d','e','f')) + sage: W.hyperplane_index_set() ('a', 'b', 'c', 'd', 'e', 'f') """ return self._hyperplane_index_set @@ -518,12 +522,13 @@ def distinguished_reflection(self, i): EXAMPLES:: - sage: W = ReflectionGroup((1,1,3)) # optional - gap3 - sage: W.distinguished_reflection(1) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,3)) + sage: W.distinguished_reflection(1) (1,4)(2,3)(5,6) - sage: W.distinguished_reflection(2) # optional - gap3 + sage: W.distinguished_reflection(2) (1,3)(2,5)(4,6) - sage: W.distinguished_reflection(3) # optional - gap3 + sage: W.distinguished_reflection(3) (1,5)(2,4)(3,6) sage: W = ReflectionGroup((3,1,1),hyperplane_index_set=['a']) # optional - gap3 @@ -651,14 +656,15 @@ def reflection_index_set(self): EXAMPLES:: - sage: W = ReflectionGroup((1,1,4)) # optional - gap3 - sage: W.reflection_index_set() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,4)) + sage: W.reflection_index_set() (1, 2, 3, 4, 5, 6) - sage: W = ReflectionGroup((1,1,4), reflection_index_set=[1,3,'asdf',7,9,11]) # optional - gap3 - sage: W.reflection_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), reflection_index_set=[1,3,'asdf',7,9,11]) + sage: W.reflection_index_set() (1, 3, 'asdf', 7, 9, 11) - sage: W = ReflectionGroup((1,1,4), reflection_index_set=('a','b','c','d','e','f')) # optional - gap3 - sage: W.reflection_index_set() # optional - gap3 + sage: W = ReflectionGroup((1,1,4), reflection_index_set=('a','b','c','d','e','f')) + sage: W.reflection_index_set() ('a', 'b', 'c', 'd', 'e', 'f') """ return self._reflection_index_set @@ -708,12 +714,13 @@ def reflection(self,i): EXAMPLES:: - sage: W = ReflectionGroup((1,1,3)) # optional - gap3 - sage: W.reflection(1) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,3)) + sage: W.reflection(1) (1,4)(2,3)(5,6) - sage: W.reflection(2) # optional - gap3 + sage: W.reflection(2) (1,3)(2,5)(4,6) - sage: W.reflection(3) # optional - gap3 + sage: W.reflection(3) (1,5)(2,4)(3,6) sage: W = ReflectionGroup((3,1,1),reflection_index_set=['a','b']) # optional - gap3 @@ -1007,17 +1014,18 @@ def rank(self): EXAMPLES:: - sage: W = ReflectionGroup((1,1,3)) # optional - gap3 - sage: W.rank() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((1,1,3)) + sage: W.rank() 2 - sage: W = ReflectionGroup((2,1,3)) # optional - gap3 - sage: W.rank() # optional - gap3 + sage: W = ReflectionGroup((2,1,3)) + sage: W.rank() 3 - sage: W = ReflectionGroup((4,1,3)) # optional - gap3 - sage: W.rank() # optional - gap3 + sage: W = ReflectionGroup((4,1,3)) + sage: W.rank() 3 - sage: W = ReflectionGroup((4,2,3)) # optional - gap3 - sage: W.rank() # optional - gap3 + sage: W = ReflectionGroup((4,2,3)) + sage: W.rank() 3 """ return self._rank @@ -1227,12 +1235,13 @@ def simple_root(self, i): EXAMPLES:: - sage: W = ReflectionGroup(['A',3]) # optional - gap3 - sage: W.simple_root(1) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',3]) + sage: W.simple_root(1) (1, 0, 0) - sage: W.simple_root(2) # optional - gap3 + sage: W.simple_root(2) (0, 1, 0) - sage: W.simple_root(3) # optional - gap3 + sage: W.simple_root(3) (0, 0, 1) TESTS:: @@ -1585,13 +1594,14 @@ def invariant_form(self, brute_force=False): sage: all( F == S[i].matrix()*F*S[i].matrix().transpose() for i in W.index_set() ) # optional - gap3 True - sage: W = ReflectionGroup(['B',3]) # optional - gap3 - sage: F = W.invariant_form(); F # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['B',3]) + sage: F = W.invariant_form(); F [ 1 -1 0] [-1 2 -1] [ 0 -1 2] - sage: w = W.an_element().to_matrix() # optional - gap3 - sage: w * F * w.transpose().conjugate() == F # optional - gap3 + sage: w = W.an_element().to_matrix() + sage: w * F * w.transpose().conjugate() == F True sage: S = W.simple_reflections() # optional - gap3 @@ -1764,20 +1774,22 @@ def invariant_form_standardization(self): EXAMPLES:: - sage: W = ReflectionGroup((4,2,5)) # optional - gap3 - sage: I = W.invariant_form() # optional - gap3 - sage: A = W.invariant_form_standardization() # optional - gap3 - sage: A^2 == I # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup((4,2,5)) + sage: I = W.invariant_form() + sage: A = W.invariant_form_standardization() + sage: A^2 == I True TESTS:: - sage: W = ReflectionGroup(9) # optional - gap3 - sage: A = W.invariant_form_standardization() # optional - gap3 - sage: S = W.simple_reflections() # optional - gap3 - sage: Ainv = A.inverse() # optional - gap3 - sage: T = {i: Ainv * S[i] * A for i in W.index_set()} # optional - gap3 - sage: all(T[i] * T[i].conjugate_transpose() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(9) + sage: A = W.invariant_form_standardization() + sage: S = W.simple_reflections() + sage: Ainv = A.inverse() + sage: T = {i: Ainv * S[i] * A for i in W.index_set()} + sage: all(T[i] * T[i].conjugate_transpose() ....: == 1 for i in W.index_set() ) True """ @@ -1906,14 +1918,15 @@ def coxeter_number(self, chi=None): EXAMPLES:: - sage: W = ReflectionGroup(["H",4]) # optional - gap3 - sage: W.coxeter_number() # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(["H",4]) + sage: W.coxeter_number() 30 - sage: all(W.coxeter_number(chi).is_integer() # optional - gap3 + sage: all(W.coxeter_number(chi).is_integer() ....: for chi in W.irreducible_characters()) True - sage: W = ReflectionGroup(14) # optional - gap3 - sage: W.coxeter_number() # optional - gap3 + sage: W = ReflectionGroup(14) + sage: W.coxeter_number() 24 """ if chi is None: @@ -2186,12 +2199,13 @@ def is_regular(self, h, is_class_representative=False): Check that :trac:`25478` is fixed:: - sage: W = ReflectionGroup(["A",5]) # optional - gap3 - sage: w = W.from_reduced_word([1,2,3,5]) # optional - gap3 - sage: w.is_regular(4) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(["A",5]) + sage: w = W.from_reduced_word([1,2,3,5]) + sage: w.is_regular(4) False - sage: W = ReflectionGroup(["A",3]) # optional - gap3 - sage: len([w for w in W if w.is_regular(w.order())]) # optional - gap3 + sage: W = ReflectionGroup(["A",3]) + sage: len([w for w in W if w.is_regular(w.order())]) 18 """ from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField, E diff --git a/src/sage/combinat/root_system/reflection_group_element.pyx b/src/sage/combinat/root_system/reflection_group_element.pyx index b790438854a..8f5a61ff0a2 100644 --- a/src/sage/combinat/root_system/reflection_group_element.pyx +++ b/src/sage/combinat/root_system/reflection_group_element.pyx @@ -27,7 +27,6 @@ from sage.misc.misc_c import prod from sage.arith.functions import lcm from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.interfaces.gap3 import gap3 from sage.combinat.root_system.reflection_group_c import reduced_word_c, reduce_in_coset from sage.matrix.constructor import Matrix from sage.matrix.special import identity_matrix @@ -71,15 +70,16 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): Check that :trac:`34912` is fixed:: - sage: G4 = ReflectionGroup(4) # optional - gap3 - sage: g0, g1 = G4.gens() # optional - gap3 - sage: elt = g0^2 * g1 * g0^2 * g1 # optional - gap3 - sage: elt # optional - gap3 + sage: # optional - gap3 + sage: G4 = ReflectionGroup(4) + sage: g0, g1 = G4.gens() + sage: elt = g0^2 * g1 * g0^2 * g1 + sage: elt (1,12)(2,24)(3,19)(4,22)(5,17)(6,20)(7,23)(8,9)(10,21)(11,13)(14,18)(15,16) - sage: y = (elt * G4.gen(1)) * G4.gen(1) * G4.gen(1) # optional - gap3 - sage: elt == y # optional - gap3 + sage: y = (elt * G4.gen(1)) * G4.gen(1) * G4.gen(1) + sage: elt == y True - sage: hash(elt) == hash(y) # optional - gap3 + sage: hash(elt) == hash(y) True """ return hash(self._parent) | super().__hash__() @@ -406,16 +406,18 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): EXAMPLES:: - sage: W = ReflectionGroup(['A',3]) # optional - gap3 - sage: w = W.w0 # optional - gap3 - sage: N = len(W.roots()) # optional - gap3 - sage: [w.action_on_root_indices(i) for i in range(N)] # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',3]) + sage: w = W.w0 + sage: N = len(W.roots()) + sage: [w.action_on_root_indices(i) for i in range(N)] [8, 7, 6, 10, 9, 11, 2, 1, 0, 4, 3, 5] - sage: W = ReflectionGroup(['A',2], reflection_index_set=['A','B','C']) # optional - gap3 - sage: w = W.w0 # optional - gap3 - sage: N = len(W.roots()) # optional - gap3 - sage: [w.action_on_root_indices(i) for i in range(N)] # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',2], reflection_index_set=['A','B','C']) + sage: w = W.w0 + sage: N = len(W.roots()) + sage: [w.action_on_root_indices(i) for i in range(N)] [4, 3, 5, 1, 0, 2] TESTS:: @@ -770,11 +772,12 @@ cdef class RealReflectionGroupElement(ComplexReflectionGroupElement): EXAMPLES:: - sage: W = ReflectionGroup(["A",3]) # optional - gap3 - sage: s = W.simple_reflections() # optional - gap3 - sage: (s[1]*s[2]).has_left_descent(1) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(["A",3]) + sage: s = W.simple_reflections() + sage: (s[1]*s[2]).has_left_descent(1) True - sage: (s[1]*s[2]).has_left_descent(2) # optional - gap3 + sage: (s[1]*s[2]).has_left_descent(2) False """ W = self._parent @@ -796,11 +799,12 @@ cdef class RealReflectionGroupElement(ComplexReflectionGroupElement): EXAMPLES:: - sage: W = ReflectionGroup(["A",3]) # optional - gap3 - sage: s = W.simple_reflections() # optional - gap3 - sage: (s[1]*s[2]).has_descent(1) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(["A",3]) + sage: s = W.simple_reflections() + sage: (s[1]*s[2]).has_descent(1) True - sage: (s[1]*s[2]).has_descent(2) # optional - gap3 + sage: (s[1]*s[2]).has_descent(2) False """ if not isinstance(positive, bool): @@ -1062,16 +1066,18 @@ cdef class RealReflectionGroupElement(ComplexReflectionGroupElement): EXAMPLES:: - sage: W = ReflectionGroup(['A',3]) # optional - gap3 - sage: w = W.w0 # optional - gap3 - sage: N = len(W.roots()) # optional - gap3 - sage: [w.action_on_root_indices(i,side="left") for i in range(N)] # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',3]) + sage: w = W.w0 + sage: N = len(W.roots()) + sage: [w.action_on_root_indices(i,side="left") for i in range(N)] [8, 7, 6, 10, 9, 11, 2, 1, 0, 4, 3, 5] - sage: W = ReflectionGroup(['A',2], reflection_index_set=['A','B','C']) # optional - gap3 - sage: w = W.w0 # optional - gap3 - sage: N = len(W.roots()) # optional - gap3 - sage: [w.action_on_root_indices(i,side="left") for i in range(N)] # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',2], reflection_index_set=['A','B','C']) + sage: w = W.w0 + sage: N = len(W.roots()) + sage: [w.action_on_root_indices(i,side="left") for i in range(N)] [4, 3, 5, 1, 0, 2] """ cdef RealReflectionGroupElement w @@ -1169,6 +1175,8 @@ def _gap_factorization(w, gens): sage: [_gap_factorization(w,gens) for w in W] # optional - gap3 [[], [1], [0], [0, 1], [1, 0], [0, 1, 0]] """ + from sage.interfaces.gap3 import gap3 + gap3.execute('W := GroupWithGenerators(%s)'%str(gens)) gap3.execute(_gap_factorization_code) fac = gap3('MinimalWord(W,%s)'%str(w)).sage() diff --git a/src/sage/combinat/root_system/reflection_group_real.py b/src/sage/combinat/root_system/reflection_group_real.py index 885e0ee549e..aee6b1d9bd9 100644 --- a/src/sage/combinat/root_system/reflection_group_real.py +++ b/src/sage/combinat/root_system/reflection_group_real.py @@ -47,7 +47,6 @@ from sage.misc.cachefunc import cached_function, cached_method, cached_in_parent_method from sage.combinat.root_system.cartan_type import CartanType, CartanType_abstract from sage.rings.integer_ring import ZZ -from sage.interfaces.gap3 import gap3 from sage.combinat.root_system.reflection_group_complex import ComplexReflectionGroup, IrreducibleComplexReflectionGroup from sage.misc.sage_eval import sage_eval from sage.combinat.root_system.reflection_group_element import RealReflectionGroupElement @@ -124,6 +123,8 @@ def ReflectionGroup(*args,**kwds): """ if not is_chevie_available(): raise ImportError("the GAP3 package 'chevie' is needed to work with (complex) reflection groups") + + from sage.interfaces.gap3 import gap3 gap3.load_package("chevie") error_msg = "the input data (%s) is not valid for reflection groups" @@ -223,6 +224,7 @@ def is_chevie_available(): EXAMPLES:: + sage: # needs sage.groups sage: from sage.combinat.root_system.reflection_group_real import is_chevie_available sage: is_chevie_available() # random False @@ -563,10 +565,11 @@ def fundamental_weights(self): sage: W.fundamental_weights() # optional - gap3 Finite family {1: (3/4, 1/2, 1/4), 2: (1/2, 1, 1/2), 3: (1/4, 1/2, 3/4)} - sage: W = ReflectionGroup(['A',3]) # optional - gap3 - sage: S = W.simple_reflections() # optional - gap3 - sage: N = W.fundamental_weights() # optional - gap3 - sage: for i in W.index_set(): # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',3]) + sage: S = W.simple_reflections() + sage: N = W.fundamental_weights() + sage: for i in W.index_set(): ....: for j in W.index_set(): ....: print("{} {} {} {}".format(i, j, N[i], N[i]*S[j].to_matrix())) 1 1 (3/4, 1/2, 1/4) (-1/4, 1/2, 1/4) @@ -733,24 +736,27 @@ def bruhat_cone(self, x, y, side='upper', backend='cdd'): EXAMPLES:: - sage: W = ReflectionGroup(['A',2]) # optional - gap3 - sage: x = W.from_reduced_word([1]) # optional - gap3 - sage: y = W.w0 # optional - gap3 - sage: W.bruhat_cone(x, y) # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',2]) + sage: x = W.from_reduced_word([1]) + sage: y = W.w0 + sage: W.bruhat_cone(x, y) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays - sage: W = ReflectionGroup(['E',6]) # optional - gap3 - sage: x = W.one() # optional - gap3 - sage: y = W.w0 # optional - gap3 - sage: W.bruhat_cone(x, y, side='lower') # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['E',6]) + sage: x = W.one() + sage: y = W.w0 + sage: W.bruhat_cone(x, y, side='lower') A 6-dimensional polyhedron in QQ^6 defined as the convex hull of 1 vertex and 6 rays TESTS:: - sage: W = ReflectionGroup(['A',2]) # optional - gap3 - sage: x = W.one() # optional - gap3 - sage: y = W.w0 # optional - gap3 - sage: W.bruhat_cone(x, y, side='nonsense') # optional - gap3 + sage: # optional - gap3 + sage: W = ReflectionGroup(['A',2]) + sage: x = W.one() + sage: y = W.w0 + sage: W.bruhat_cone(x, y, side='nonsense') Traceback (most recent call last): ... ValueError: side must be either 'upper' or 'lower' diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index dcc3fa99d29..62bfff6060a 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -52,21 +52,25 @@ def some_elements(self): sage: A = RootSystem(["A",2,1]).ambient_space().algebra(QQ) sage: A.some_elements() + [B[2*e[0] + 2*e[1] + 3*e[2]]...] + sage: A.some_elements() # needs sage.graphs [B[2*e[0] + 2*e[1] + 3*e[2]], - B[-e[0] + e[2] + e['delta']], - B[e[0] - e[1]], - B[e[1] - e[2]], - B[e['deltacheck']], - B[e[0] + e['deltacheck']], - B[e[0] + e[1] + e['deltacheck']]] + B[-e[0] + e[2] + e['delta']], + B[e[0] - e[1]], + B[e[1] - e[2]], + B[e['deltacheck']], + B[e[0] + e['deltacheck']], + B[e[0] + e[1] + e['deltacheck']]] sage: A = RootSystem(["B",2]).weight_space().algebra(QQ) sage: A.some_elements() + [B[2*Lambda[1] + 2*Lambda[2]], ... B[Lambda[1]], B[Lambda[2]]] + sage: A.some_elements() # needs sage.graphs [B[2*Lambda[1] + 2*Lambda[2]], - B[2*Lambda[1] - 2*Lambda[2]], - B[-Lambda[1] + 2*Lambda[2]], - B[Lambda[1]], - B[Lambda[2]]] + B[2*Lambda[1] - 2*Lambda[2]], + B[-Lambda[1] + 2*Lambda[2]], + B[Lambda[1]], + B[Lambda[2]]] """ return [self.monomial(weight) for weight in self.basis().keys().some_elements()] @@ -238,32 +242,34 @@ def demazure_operators(self): sage: L = RootSystem(["A",2]).ambient_lattice() sage: KL = L.algebra(QQ) - sage: w0 = tuple(L.weyl_group().long_element().reduced_word()) + sage: w0 = tuple(L.weyl_group().long_element().reduced_word()) # needs sage.libs.gap sage: pi = KL.demazure_operators() - sage: pi0 = pi[w0] - sage: pi0(KL.monomial(L((2,1)))) - 2*B[(1, 1, 1)] + B[(1, 2, 0)] + B[(1, 0, 2)] + B[(2, 1, 0)] + B[(2, 0, 1)] + B[(0, 1, 2)] + B[(0, 2, 1)] + sage: pi0 = pi[w0] # needs sage.libs.gap + sage: pi0(KL.monomial(L((2,1)))) # needs sage.libs.gap + 2*B[(1, 1, 1)] + B[(1, 2, 0)] + B[(1, 0, 2)] + B[(2, 1, 0)] + + B[(2, 0, 1)] + B[(0, 1, 2)] + B[(0, 2, 1)] Let us make the result into an actual polynomial:: sage: P = QQ['x,y,z'] - sage: pi0(KL.monomial(L((2,1)))).expand(P.gens()) + sage: pi0(KL.monomial(L((2,1)))).expand(P.gens()) # needs sage.libs.gap x^2*y + x*y^2 + x^2*z + 2*x*y*z + y^2*z + x*z^2 + y*z^2 This is indeed a Schur function:: - sage: s = SymmetricFunctions(QQ).s() - sage: s[2,1].expand(3, P.variable_names()) + sage: s = SymmetricFunctions(QQ).s() # needs sage.combinat + sage: s[2,1].expand(3, P.variable_names()) # needs sage.combinat x^2*y + x*y^2 + x^2*z + 2*x*y*z + y^2*z + x*z^2 + y*z^2 Let us check this systematically on Schur functions of degree 6:: - sage: for p in Partitions(6, max_length=3).list(): - ....: assert s.monomial(p).expand(3, P.variable_names()) == pi0(KL.monomial(L(tuple(p)))).expand(P.gens()) + sage: for p in Partitions(6, max_length=3).list(): # needs sage.combinat sage.libs.gap + ....: assert (s.monomial(p).expand(3, P.variable_names()) + ....: == pi0(KL.monomial(L(tuple(p)))).expand(P.gens())) We check systematically that these operators satisfy the Iwahori-Hecke algebra relations:: - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time 12s + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).weight_lattice() ....: KL = L.algebra(QQ) ....: T = KL.demazure_operators() @@ -300,21 +306,24 @@ def _test_demazure_operators(self, **options): sage: RootSystem(["A",2]).root_lattice().algebra(QQ)._test_demazure_operators() """ tester = self._tester(**options) - pi = self.demazure_operators() - L = self.basis().keys() - alpha = L.simple_roots() - alphacheck = L.simple_coroots() - s = L.simple_reflections() - for i in self.cartan_type().index_set(): - emalphai = self.monomial(-alpha[i]) # X^{-\alpha_i} - for weight in L.some_elements(): - if not weight.scalar(alphacheck[i]) in ZZ: - # Demazure operators are not defined in this case - continue - x = self.monomial(weight) - result = pi[i](x) - tester.assertEqual(result * (self.one()-emalphai), - x - emalphai * x.map_support(s[i])) + try: + pi = self.demazure_operators() + L = self.basis().keys() + alpha = L.simple_roots() + alphacheck = L.simple_coroots() + s = L.simple_reflections() + for i in self.cartan_type().index_set(): + emalphai = self.monomial(-alpha[i]) # X^{-\alpha_i} + for weight in L.some_elements(): + if not weight.scalar(alphacheck[i]) in ZZ: + # Demazure operators are not defined in this case + continue + x = self.monomial(weight) + result = pi[i](x) + tester.assertEqual(result * (self.one()-emalphai), + x - emalphai * x.map_support(s[i])) + except ImportError: + pass def demazure_lusztig_operator_on_basis(self, weight, i, q1, q2, convention="antidominant"): r""" @@ -324,8 +333,8 @@ def demazure_lusztig_operator_on_basis(self, weight, i, q1, q2, convention="anti - ``weight`` -- an element `\lambda` of the weight lattice - ``i`` -- an element of the index set - - ``q1,q2`` -- two elements of the ground ring - - ``convention`` -- "antidominant", "bar", or "dominant" (default: "antidominant") + - ``q1``, ``q2`` -- two elements of the ground ring + - ``convention`` -- ``"antidominant"``, ``"bar"``, or ``"dominant"`` (default: ``"antidominant"``) See :meth:`demazure_lusztig_operators` for the details. @@ -440,7 +449,8 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: KL = L.algebra(K) sage: T = KL.demazure_lusztig_operators(q1, q2) sage: Tbar = KL.demazure_lusztig_operators(q1, q2, convention="bar") - sage: Tdominant = KL.demazure_lusztig_operators(q1, q2, convention="dominant") + sage: Tdominant = KL.demazure_lusztig_operators(q1, q2, + ....: convention="dominant") sage: x = KL.monomial(L((3,0))) sage: T[1](x) (q1+q2)*B[(1, 2)] + (q1+q2)*B[(2, 1)] + (q1+q2)*B[(3, 0)] + q1*B[(0, 3)] @@ -462,13 +472,16 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: KL = L.algebra(K) sage: T = KL.demazure_lusztig_operators(q1, q2) sage: Tbar = KL.demazure_lusztig_operators(q1, q2, convention="bar") - sage: Tdominant = KL.demazure_lusztig_operators(q1, q2, convention="dominant") + sage: Tdominant = KL.demazure_lusztig_operators(q1, q2, + ....: convention="dominant") sage: e = L.basis() sage: x = KL.monomial(3*e[0]) sage: T[1](x) - (q1+q2)*B[e[0] + 2*e[1]] + (q1+q2)*B[2*e[0] + e[1]] + (q1+q2)*B[3*e[0]] + q1*B[3*e[1]] + (q1+q2)*B[e[0] + 2*e[1]] + (q1+q2)*B[2*e[0] + e[1]] + + (q1+q2)*B[3*e[0]] + q1*B[3*e[1]] sage: Tbar[1](x) - (-q1-q2)*B[e[0] + 2*e[1]] + (-q1-q2)*B[2*e[0] + e[1]] + (-q1-2*q2)*B[3*e[1]] + (-q1-q2)*B[e[0] + 2*e[1]] + (-q1-q2)*B[2*e[0] + e[1]] + + (-q1-2*q2)*B[3*e[1]] sage: Tbar[1](x) + T[1](x) (q1+q2)*B[3*e[0]] + (-2*q2)*B[3*e[1]] sage: Tdominant[1](x) @@ -501,31 +514,33 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): And the `\bar{T}` are basically the inverses of the `T` s:: - sage: Tinv = KL.demazure_lusztig_operators(2/q1+1/q2,-1/q1,convention="bar") - sage: [Tinv[1](T[1](x))-x for x in KL.some_elements()] + sage: Tinv = KL.demazure_lusztig_operators(2/q1 + 1/q2, -1/q1, + ....: convention="bar") + sage: [Tinv[1](T[1](x)) - x for x in KL.some_elements()] # needs sage.graphs [0, 0, 0, 0, 0, 0, 0] We check that `\Lambda_1-\Lambda_0` is an eigenvector for the `Y` s in affine type:: sage: K = QQ['q,q1,q2'].fraction_field() - sage: q,q1,q2=K.gens() + sage: q,q1,q2 = K.gens() sage: L = RootSystem(["A",2,1]).ambient_space() sage: L0 = L.classical() - sage: Lambda = L.fundamental_weights() + sage: Lambda = L.fundamental_weights() # needs sage.graphs sage: alphacheck = L0.simple_coroots() sage: KL = L.algebra(K) sage: T = KL.demazure_lusztig_operators(q1, q2, convention="dominant") sage: Y = T.Y() - sage: alphacheck = Y.keys().alpha() # alpha of coroot lattice is alphacheck + sage: alphacheck = Y.keys().alpha() # alpha of coroot lattice is alphacheck sage: alphacheck Finite family {0: alphacheck[0], 1: alphacheck[1], 2: alphacheck[2]} - sage: x = KL.monomial(Lambda[1]-Lambda[0]); x + sage: x = KL.monomial(Lambda[1] - Lambda[0]); x # needs sage.graphs B[e[0]] In fact it is not exactly an eigenvector, but the extra '\delta` term is to be interpreted as a `q` parameter:: + sage: # needs sage.graphs sage: Y[alphacheck[0]](KL.one()) q2^2/q1^2*B[0] sage: Y[alphacheck[1]](x) @@ -535,6 +550,7 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: KL.q_project(Y[alphacheck[1]](x),q) ((-q2^2)/(-q*q1^2))*B[(1, 0, 0)] + sage: # needs sage.graphs sage: KL.q_project(x, q) B[(1, 0, 0)] sage: KL.q_project(Y[alphacheck[0]](x),q) @@ -589,7 +605,7 @@ def demazure_lusztig_operator_on_classical_on_basis(self, weight, i, q, q1, q2, - ``weight`` -- a classical weight `\lambda` - ``i`` -- an element of the index set - ``q1,q2`` -- two elements of the ground ring - - ``convention`` -- "antidominant", "bar", or "dominant" (default: "antidominant") + - ``convention`` -- ``"antidominant"``, ``"bar"``, or ``"dominant"`` (default: ``"antidominant"``) See :meth:`demazure_lusztig_operators` for the details. @@ -611,21 +627,25 @@ def demazure_lusztig_operator_on_classical_on_basis(self, weight, i, q, q1, q2, These operators coincide with the usual Demazure-Lusztig operators:: - sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((2,2)), 1, q, q1, q2) + sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((2,2)), # needs sage.graphs + ....: 1, q, q1, q2) q1*B[(2, 2)] sage: KL0.demazure_lusztig_operator_on_basis(L0((2,2)), 1, q1, q2) q1*B[(2, 2)] - sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((3,0)), 1, q, q1, q2) + sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((3,0)), # needs sage.graphs + ....: 1, q, q1, q2) (q1+q2)*B[(1, 2)] + (q1+q2)*B[(2, 1)] + (q1+q2)*B[(3, 0)] + q1*B[(0, 3)] sage: KL0.demazure_lusztig_operator_on_basis(L0((3,0)), 1, q1, q2) (q1+q2)*B[(1, 2)] + (q1+q2)*B[(2, 1)] + (q1+q2)*B[(3, 0)] + q1*B[(0, 3)] except that we now have an action of `T_0`, which introduces some `q` s:: - sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((2,2)), 0, q, q1, q2) + sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((2,2)), # needs sage.graphs + ....: 0, q, q1, q2) q1*B[(2, 2)] - sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((3,0)), 0, q, q1, q2) + sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((3,0)), # needs sage.graphs + ....: 0, q, q1, q2) (-q^2*q1-q^2*q2)*B[(1, 2)] + (-q*q1-q*q2)*B[(2, 1)] + (-q^3*q2)*B[(0, 3)] """ L = self.basis().keys() @@ -639,7 +659,7 @@ def demazure_lusztig_operators_on_classical(self, q, q1, q2, convention="antidom INPUT: - ``q,q1,q2`` -- three elements of the ground ring - - ``convention`` -- "antidominant", "bar", or "dominant" (default: "antidominant") + - ``convention`` -- ``"antidominant"``, ``"bar"``, or ``"dominant"`` (default: ``"antidominant"``) Let `KL` be the group algebra of an affine weight lattice realization `L`. The Demazure-Lusztig operators for `KL` @@ -661,32 +681,32 @@ def demazure_lusztig_operators_on_classical(self, q, q1, q2, convention="antidom sage: KL = L.algebra(K) sage: KL0 = KL.classical() sage: L0 = KL0.basis().keys() - sage: T = KL.demazure_lusztig_operators_on_classical(q, q1, q2) + sage: T = KL.demazure_lusztig_operators_on_classical(q, q1, q2) # needs sage.graphs sage: x = KL0.monomial(L0((3,0))); x B[(3, 0)] For `T_1,\dots` we recover the usual Demazure-Lusztig operators:: - sage: T[1](x) + sage: T[1](x) # needs sage.graphs (q1+q2)*B[(1, 2)] + (q1+q2)*B[(2, 1)] + (q1+q2)*B[(3, 0)] + q1*B[(0, 3)] For `T_0`, we can note that, in the projection, `\delta` is mapped to `q`:: - sage: T[0](x) + sage: T[0](x) # needs sage.graphs (-q^2*q1-q^2*q2)*B[(1, 2)] + (-q*q1-q*q2)*B[(2, 1)] + (-q^3*q2)*B[(0, 3)] Note that there is no translation part, and in particular 1 is an eigenvector for all `T_i`'s:: + sage: # needs sage.graphs sage: T[0](KL0.one()) q1*B[(0, 0)] sage: T[1](KL0.one()) q1*B[(0, 0)] - sage: Y = T.Y() - sage: alphacheck=Y.keys().simple_roots() + sage: alphacheck = Y.keys().simple_roots() sage: Y[alphacheck[0]](KL0.one()) ((-q2)/(q*q1))*B[(0, 0)] @@ -699,30 +719,30 @@ def demazure_lusztig_operators_on_classical(self, q, q1, q2, convention="antidom sage: KL0 = KL.classical() sage: L0 = KL0.basis().keys() sage: omega = L0.fundamental_weights() - sage: T = KL.demazure_lusztig_operators_on_classical(q, u, -1/u, convention="dominant") + + sage: # needs sage.graphs + sage: T = KL.demazure_lusztig_operators_on_classical(q, u, -1/u, + ....: convention="dominant") sage: Y = T.Y() sage: alphacheck = Y.keys().simple_roots() - sage: Ydelta = Y[Y.keys().null_root()] sage: Ydelta.word, Ydelta.signs, Ydelta.scalar ((), (), 1/q) - sage: Y1 = Y[alphacheck[1]] - sage: Y1.word, Y1.signs, Y1.scalar # This is T_0 T_1 (T_1 acts first, then T_0); Ion gets T_1 T_0 + sage: Y1.word, Y1.signs, Y1.scalar # This is T_0 T_1 (T_1 acts first, then T_0); Ion gets T_1 T_0 ((1, 0), (1, 1), 1) - sage: Y0 = Y[alphacheck[0]] - sage: Y0.word, Y0.signs, Y0.scalar # This is 1/q T_1^-1 T_0^-1 + sage: Y0.word, Y0.signs, Y0.scalar # This is 1/q T_1^-1 T_0^-1 ((0, 1), (-1, -1), 1/q) Note that the following computations use the "dominant" convention:: + sage: # needs sage.graphs sage: T0 = T.Tw(0) sage: T0(KL0.monomial(omega[1])) q*u*B[-Lambda[1]] + ((u^2-1)/u)*B[Lambda[1]] sage: T0(KL0.monomial(2*omega[1])) ((q*u^2-q)/u)*B[0] + q^2*u*B[-2*Lambda[1]] + ((u^2-1)/u)*B[2*Lambda[1]] - sage: T0(KL0.monomial(-omega[1])) 1/(q*u)*B[Lambda[1]] sage: T0(KL0.monomial(-2*omega[1])) @@ -766,22 +786,22 @@ def T0_check_on_basis(self, q1, q2, convention="antidominant"): sage: L = RootSystem(["A",1,1]).ambient_space() sage: L0 = L.classical() sage: KL = L.algebra(K) - sage: some_weights = L.fundamental_weights() - sage: f = KL.T0_check_on_basis(q1,q2, convention="dominant") - sage: f(L0.zero()) + sage: some_weights = L.fundamental_weights() # needs sage.graphs + sage: f = KL.T0_check_on_basis(q1,q2, convention="dominant") # needs sage.graphs + sage: f(L0.zero()) # needs sage.graphs (q1+q2)*B[(0, 0)] + q1*B[(1, -1)] sage: L = RootSystem(["A",3,1]).ambient_space() sage: L0 = L.classical() sage: KL = L.algebra(K) sage: some_weights = L0.fundamental_weights() - sage: f = KL.T0_check_on_basis(q1,q2, convention="dominant") - sage: f(L0.zero()) # not checked + sage: f = KL.T0_check_on_basis(q1,q2, convention="dominant") # needs sage.graphs + sage: f(L0.zero()) # not checked # needs sage.graphs (q1+q2)*B[(0, 0, 0, 0)] + q1^3/q2^2*B[(1, 0, 0, -1)] The following results have not been checked:: - sage: for x in some_weights: + sage: for x in some_weights: # needs sage.graphs ....: print("{} : {}".format(x, f(x))) (1, 0, 0, 0) : q1*B[(1, 0, 0, 0)] (1, 1, 0, 0) : q1*B[(1, 1, 0, 0)] @@ -798,14 +818,14 @@ def T0_check_on_basis(self, q1, q2, convention="antidominant"): sage: q2 = -1/u sage: KL = L.algebra(K) sage: KL0 = KL.classical() - sage: f = KL.T0_check_on_basis(q1,q2, convention="dominant") + sage: f = KL.T0_check_on_basis(q1,q2, convention="dominant") # needs sage.graphs sage: T = KL.twisted_demazure_lusztig_operators(q1,q2, convention="dominant") Direct calculation:: - sage: T.Tw(0)(KL0.monomial(L0([0,0]))) + sage: T.Tw(0)(KL0.monomial(L0([0,0]))) # needs sage.graphs ((u^2-1)/u)*B[(0, 0)] + u^3*B[(1, 1)] - sage: KL.T0_check_on_basis(q1,q2, convention="dominant")(L0([0,0])) + sage: KL.T0_check_on_basis(q1,q2, convention="dominant")(L0([0,0])) # needs sage.graphs ((u^2-1)/u)*B[(0, 0)] + u^3*B[(1, 1)] Step by step calculation, comparing by hand with Mark Shimozono:: @@ -888,7 +908,8 @@ def q_project_on_basis(self, l, q): sage: KL = RootSystem(["A",2,1]).ambient_space().algebra(K) sage: L = KL.basis().keys() sage: e = L.basis() - sage: KL.q_project_on_basis( 4*e[1] + 3*e[2] + e['deltacheck'] - 2*e['delta'], q) + sage: KL.q_project_on_basis(4*e[1] + 3*e[2] + ....: + e['deltacheck'] - 2*e['delta'], q) 1/q^2*B[(0, 4, 3)] """ KL0 = self.classical() @@ -915,16 +936,22 @@ def q_project(self, x, q): sage: KL = RootSystem(["A",2,1]).ambient_space().algebra(K) sage: L = KL.basis().keys() sage: e = L.basis() - sage: x = KL.an_element() + KL.monomial(4*e[1] + 3*e[2] + e['deltacheck'] - 2*e['delta']); x - B[2*e[0] + 2*e[1] + 3*e[2]] + B[4*e[1] + 3*e[2] - 2*e['delta'] + e['deltacheck']] + sage: x = (KL.an_element() + ....: + KL.monomial(4*e[1] + 3*e[2] + ....: + e['deltacheck'] - 2*e['delta'])); x + B[2*e[0] + 2*e[1] + 3*e[2]] + + B[4*e[1] + 3*e[2] - 2*e['delta'] + e['deltacheck']] sage: KL.q_project(x, q) B[(2, 2, 3)] + 1/q^2*B[(0, 4, 3)] sage: KL = RootSystem(["BC",3,2]).ambient_space().algebra(K) sage: L = KL.basis().keys() sage: e = L.basis() - sage: x = KL.an_element() + KL.monomial(4*e[1] + 3*e[2] + e['deltacheck'] - 2*e['delta']); x - B[2*e[0] + 2*e[1] + 3*e[2]] + B[4*e[1] + 3*e[2] - 2*e['delta'] + e['deltacheck']] + sage: x = (KL.an_element() + ....: + KL.monomial(4*e[1] + 3*e[2] + ....: + e['deltacheck'] - 2*e['delta'])); x + B[2*e[0] + 2*e[1] + 3*e[2]] + + B[4*e[1] + 3*e[2] - 2*e['delta'] + e['deltacheck']] sage: KL.q_project(x, q) B[(2, 2, 3)] + 1/q^2*B[(0, 4, 3)] @@ -937,7 +964,7 @@ def q_project(self, x, q): denoted `q` is in fact ``q^a[0]`` in Sage's notations, to avoid manipulating square roots:: - sage: KL.q_project(KL.monomial(L.null_root()),q) + sage: KL.q_project(KL.monomial(L.null_root()),q) # needs sage.graphs q^2*B[(0, 0, 0)] """ L0 = self.classical() @@ -952,7 +979,7 @@ def twisted_demazure_lusztig_operator_on_basis(self, weight, i, q1, q2, conventi - ``weight`` -- an element `\lambda` of the weight lattice - ``i`` -- an element of the index set - ``q1,q2`` -- two elements of the ground ring - - ``convention`` -- "antidominant", "bar", or "dominant" (default: "antidominant") + - ``convention`` -- ``"antidominant"``, ``"bar"``, or ``"dominant"`` (default: ``"antidominant"``) .. SEEALSO:: :meth:`twisted_demazure_lusztig_operators` @@ -964,16 +991,23 @@ def twisted_demazure_lusztig_operator_on_basis(self, weight, i, q1, q2, conventi sage: q1, q2 = K.gens() sage: KL = L.algebra(K) sage: Lambda = L.classical().fundamental_weights() - sage: KL.twisted_demazure_lusztig_operator_on_basis(Lambda[1]+2*Lambda[2], 1, q1, q2, convention="dominant") + sage: KL.twisted_demazure_lusztig_operator_on_basis( + ....: Lambda[1] + 2*Lambda[2], 1, q1, q2, convention="dominant") (-q2)*B[(2, 3, 0, 0)] - sage: KL.twisted_demazure_lusztig_operator_on_basis(Lambda[1]+2*Lambda[2], 2, q1, q2, convention="dominant") + sage: KL.twisted_demazure_lusztig_operator_on_basis( + ....: Lambda[1] + 2*Lambda[2], 2, q1, q2, convention="dominant") (-q1-q2)*B[(3, 1, 1, 0)] + (-q2)*B[(3, 0, 2, 0)] - sage: KL.twisted_demazure_lusztig_operator_on_basis(Lambda[1]+2*Lambda[2], 3, q1, q2, convention="dominant") + sage: KL.twisted_demazure_lusztig_operator_on_basis( + ....: Lambda[1] + 2*Lambda[2], 3, q1, q2, convention="dominant") q1*B[(3, 2, 0, 0)] - sage: KL.twisted_demazure_lusztig_operator_on_basis(Lambda[1]+2*Lambda[2], 0, q1, q2, convention="dominant") - ((q1*q2+q2^2)/q1)*B[(1, 2, 1, 1)] + ((q1*q2+q2^2)/q1)*B[(1, 2, 2, 0)] + q2^2/q1*B[(1, 2, 0, 2)] - + ((q1^2+2*q1*q2+q2^2)/q1)*B[(2, 1, 1, 1)] + ((q1^2+2*q1*q2+q2^2)/q1)*B[(2, 1, 2, 0)] - + ((q1*q2+q2^2)/q1)*B[(2, 1, 0, 2)] + ((q1^2+2*q1*q2+q2^2)/q1)*B[(2, 2, 1, 0)] + ((q1*q2+q2^2)/q1)*B[(2, 2, 0, 1)] + sage: KL.twisted_demazure_lusztig_operator_on_basis( # needs sage.graphs + ....: Lambda[1]+2*Lambda[2], 0, q1, q2, convention="dominant") + ((q1*q2+q2^2)/q1)*B[(1, 2, 1, 1)] + ((q1*q2+q2^2)/q1)*B[(1, 2, 2, 0)] + + q2^2/q1*B[(1, 2, 0, 2)] + ((q1^2+2*q1*q2+q2^2)/q1)*B[(2, 1, 1, 1)] + + ((q1^2+2*q1*q2+q2^2)/q1)*B[(2, 1, 2, 0)] + + ((q1*q2+q2^2)/q1)*B[(2, 1, 0, 2)] + + ((q1^2+2*q1*q2+q2^2)/q1)*B[(2, 2, 1, 0)] + + ((q1*q2+q2^2)/q1)*B[(2, 2, 0, 1)] """ if i == 0: # should use the special node if convention != "dominant": @@ -990,12 +1024,12 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention="antidominant"): INPUT: - ``q1,q2`` -- two elements of the ground ring - - ``convention`` -- "antidominant", "bar", or "dominant" (default: "antidominant") + - ``convention`` -- ``"antidominant"``, ``"bar"``, or ``"dominant"`` (default: ``"antidominant"``) .. WARNING:: - the code is currently only tested for `q_1q_2=-1` - - only the "dominant" convention is functional for `i=0` + - only the ``"dominant"`` convention is functional for `i=0` For `T_1,\ldots,T_n`, these operators are the usual Demazure-Lusztig operators. On the other hand, the @@ -1030,7 +1064,7 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention="antidominant"): (-q1-q2)*B[(0, 0)] + (-q2)*B[(-1, 1)] sage: T.Ti_inverse_on_basis(alpha[1], 1) ((q1+q2)/(q1*q2))*B[(0, 0)] + 1/q1*B[(-1, 1)] + ((q1+q2)/(q1*q2))*B[(1, -1)] - sage: T.Ti_on_basis(L0.zero(), 0) + sage: T.Ti_on_basis(L0.zero(), 0) # needs sage.graphs (q1+q2)*B[(0, 0)] + q1*B[(1, -1)] The next computations were checked with Mark Shimozono for type `A_2^{(1)}`:: @@ -1086,7 +1120,7 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: cartan_type = CartanType(["BC",1,2]) sage: KL = RootSystem(cartan_type).weight_lattice().algebra(K) sage: T = KL.twisted_demazure_lusztig_operators(q1,q2, convention="dominant") - sage: T._test_relations() + sage: T._test_relations() # needs sage.graphs Traceback (most recent call last): ... tester.assertTrue(Ti(Ti(x,i,-q2),i,-q1).is_zero()) ... AssertionError: False is not true @@ -1103,12 +1137,13 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: L0 = L.classical() sage: T = KL.demazure_lusztig_operators(q1,q2, convention="dominant") sage: def T0(*l0): return KL.q_project(T[0].on_basis()(L.embed_at_level(L0(l0), 1)), q) - sage: T0_check_on_basis = KL.T0_check_on_basis(q1, q2, convention="dominant") + sage: T0_check_on_basis = KL.T0_check_on_basis(q1, q2, # needs sage.graphs + ....: convention="dominant") sage: def T0c(*l0): return T0_check_on_basis(L0(l0)) - sage: T0(0,0,1) # not double checked + sage: T0(0,0,1) # not double checked # needs sage.graphs ((-t+1)/q)*B[(1, 0, 0)] + 1/q^2*B[(2, 0, -1)] - sage: T0c(0,0,1) + sage: T0c(0,0,1) # needs sage.graphs (t^2-t)*B[(1, 0, 0)] + (t^2-t)*B[(1, 1, -1)] + t^2*B[(2, 0, -1)] + (t-1)*B[(0, 0, 1)] """ T_on_basis = functools.partial(self.twisted_demazure_lusztig_operator_on_basis, @@ -1132,15 +1167,15 @@ def acted_upon(self, w): EXAMPLES:: sage: L = RootSystem(["A",3]).ambient_space() - sage: W = L.weyl_group() + sage: W = L.weyl_group() # needs sage.libs.gap sage: M = L.algebra(QQ['q','t']) sage: m = M.an_element(); m # TODO: investigate why we don't get something more interesting B[(2, 2, 3, 0)] sage: m = (m+1)^2; m B[(0, 0, 0, 0)] + 2*B[(2, 2, 3, 0)] + B[(4, 4, 6, 0)] - sage: w = W.an_element(); w.reduced_word() + sage: w = W.an_element(); w.reduced_word() # needs sage.libs.gap [1, 2, 3] - sage: m.acted_upon(w) + sage: m.acted_upon(w) # needs sage.libs.gap B[(0, 0, 0, 0)] + 2*B[(0, 2, 2, 3)] + B[(0, 4, 4, 6)] """ return self.map_support(w.action) diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 4cc293dbf85..349bd9976bb 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -80,7 +80,7 @@ class RootLatticeRealizations(Category_over_base_ring): alpha[2] + 2*alpha[5] sage: L = R.weight_lattice() - sage: L(x) + sage: L(x) # needs sage.graphs -Lambda[1] + 2*Lambda[2] - Lambda[3] - 2*Lambda[4] + 4*Lambda[5] - 2*Lambda[6] sage: L = R.ambient_space() @@ -94,7 +94,7 @@ class RootLatticeRealizations(Category_over_base_ring): sage: x = alpha[2] + 1/2 * alpha[5] sage: L = R.weight_space() - sage: L(x) + sage: L(x) # needs sage.graphs -Lambda[1] + 2*Lambda[2] - Lambda[3] - 1/2*Lambda[4] + Lambda[5] - 1/2*Lambda[6] sage: L = R.ambient_space() @@ -119,7 +119,7 @@ class RootLatticeRealizations(Category_over_base_ring): sage: L = R.weight_space(K2) sage: alpha = R.root_space(K2).simple_roots() - sage: L(alpha[1]) + sage: L(alpha[1]) # needs sage.graphs 2*Lambda[1] - Lambda[2] sage: alpha = R.root_space(K1).simple_roots() @@ -136,14 +136,14 @@ class RootLatticeRealizations(Category_over_base_ring): lattice:: sage: R = RootSystem(["A", 3, 1]) - sage: delta = R.root_lattice().null_root() + sage: delta = R.root_lattice().null_root() # needs sage.graphs sage: L = R.weight_lattice() - sage: L(delta) + sage: L(delta) # needs sage.graphs 0 TESTS:: - sage: TestSuite(L).run() + sage: TestSuite(L).run() # needs sage.graphs """ @cached_method @@ -176,7 +176,7 @@ def __init_extra__(self): sage: R = RootSystem(["A",3]) sage: alpha = R.root_lattice().simple_roots() sage: L = R.weight_lattice() - sage: L(alpha[2]) + sage: L(alpha[2]) # needs sage.graphs -Lambda[1] + 2*Lambda[2] - Lambda[3] .. NOTE:: @@ -228,7 +228,7 @@ def dynkin_diagram(self): EXAMPLES:: sage: r = RootSystem(['A',4]).root_space() - sage: r.dynkin_diagram() + sage: r.dynkin_diagram() # needs sage.graphs O---O---O---O 1 2 3 4 A4 @@ -285,15 +285,22 @@ def some_elements(self): EXAMPLES:: sage: L = RootSystem(["A",2]).weight_lattice() - sage: L.some_elements() - [2*Lambda[1] + 2*Lambda[2], 2*Lambda[1] - Lambda[2], -Lambda[1] + 2*Lambda[2], Lambda[1], Lambda[2]] + sage: L.some_elements() # needs sage.graphs + [2*Lambda[1] + 2*Lambda[2], 2*Lambda[1] - Lambda[2], + -Lambda[1] + 2*Lambda[2], Lambda[1], Lambda[2]] sage: L = RootSystem(["A",2]).root_lattice() sage: L.some_elements() [2*alpha[1] + 2*alpha[2], alpha[1], alpha[2]] """ - result = [self.an_element()]+list(self.simple_roots()) - if hasattr(self, "fundamental_weights"): - result += list(self.fundamental_weights()) + result = [self.an_element()] + try: + result.extend(self.simple_roots()) + except ImportError: + pass + try: + result.extend(self.fundamental_weights()) + except (AttributeError, ImportError): + pass return result ########################################################################## @@ -316,8 +323,11 @@ def _test_root_lattice_realization(self, **options): sage: RootSystem(['A',3]).root_lattice()._test_root_lattice_realization() """ tester = self._tester(**options) - alpha = self.simple_roots() - alphacheck = self.simple_coroots() + try: + alpha = self.simple_roots() + alphacheck = self.simple_coroots() + except ImportError: + return R = self.base_ring() tester.assertEqual(alpha .keys(), self.index_set()) tester.assertEqual(alphacheck.keys(), self.index_set()) @@ -337,7 +347,10 @@ def _test_root_lattice_realization(self, **options): tester.assertEqual(self(root_space .simple_root(i)), alpha[i]) # Check that the scalar products match with the Dynkin diagram - dynkin_diagram = self.dynkin_diagram() + try: + dynkin_diagram = self.dynkin_diagram() + except ImportError: + return for i in self.index_set(): for j in self.index_set(): tester.assertEqual(alpha[j].scalar(alphacheck[i]), R(dynkin_diagram[i,j])) @@ -379,7 +392,7 @@ def highest_root(self): sage: RootSystem(['A',4]).ambient_space().highest_root() (1, 0, 0, 0, -1) - sage: RootSystem(['E',6]).weight_space().highest_root() + sage: RootSystem(['E',6]).weight_space().highest_root() # needs sage.graphs Lambda[2] """ @@ -410,10 +423,10 @@ def a_long_simple_root(self): TESTS:: sage: X = RootSystem(['A',1]).weight_space() - sage: X.a_long_simple_root() + sage: X.a_long_simple_root() # needs sage.graphs 2*Lambda[1] sage: X = RootSystem(['A',5]).weight_space() - sage: X.a_long_simple_root() + sage: X.a_long_simple_root() # needs sage.graphs 2*Lambda[1] - Lambda[2] """ if self.dynkin_diagram().rank() == 1: @@ -480,7 +493,7 @@ def alpha(self): sage: alpha = RootSystem(["A",2]).root_lattice().alpha() sage: alpha[1] alpha[1] - sage: alpha[0] + sage: alpha[0] # needs sage.graphs -alpha[1] - alpha[2] """ if self.root_system.is_finite() and self.root_system.is_irreducible(): @@ -504,10 +517,11 @@ def basic_imaginary_roots(self): sage: RootSystem(['A', 2]).root_lattice().basic_imaginary_roots() () sage: Q = RootSystem(['A', 2, 1]).root_lattice() - sage: Q.basic_imaginary_roots() + sage: Q.basic_imaginary_roots() # needs sage.graphs (alpha[0] + alpha[1] + alpha[2],) - sage: delta = Q.basic_imaginary_roots()[0] - sage: all(delta.scalar(Q.simple_coroot(i)) <= 0 for i in Q.index_set()) + sage: delta = Q.basic_imaginary_roots()[0] # needs sage.graphs + sage: all(delta.scalar(Q.simple_coroot(i)) <= 0 # needs sage.graphs + ....: for i in Q.index_set()) True """ if self.cartan_type().is_finite(): @@ -540,15 +554,19 @@ def simple_roots_tilde(self): In simply laced cases, this is boring:: - sage: RootSystem(["A",3, 1]).root_lattice().simple_roots_tilde() + sage: RootSystem(["A",3, 1]).root_lattice().simple_roots_tilde() # needs sage.graphs Finite family {0: alpha[0], 1: alpha[1], 2: alpha[2], 3: alpha[3]} This was checked by hand:: - sage: RootSystem(["C",2,1]).coroot_lattice().simple_roots_tilde() - Finite family {0: alphacheck[0] - alphacheck[2], 1: alphacheck[1], 2: alphacheck[2]} - sage: RootSystem(["B",2,1]).coroot_lattice().simple_roots_tilde() - Finite family {0: alphacheck[0] - alphacheck[1], 1: alphacheck[1], 2: alphacheck[2]} + sage: RootSystem(["C",2,1]).coroot_lattice().simple_roots_tilde() # needs sage.graphs + Finite family {0: alphacheck[0] - alphacheck[2], + 1: alphacheck[1], + 2: alphacheck[2]} + sage: RootSystem(["B",2,1]).coroot_lattice().simple_roots_tilde() # needs sage.graphs + Finite family {0: alphacheck[0] - alphacheck[1], + 1: alphacheck[1], + 2: alphacheck[2]} What about type BC? """ @@ -576,7 +594,7 @@ def roots(self): This matches with :wikipedia:`Root_systems`:: - sage: for T in CartanType.samples(finite = True, crystallographic = True): + sage: for T in CartanType.samples(finite=True, crystallographic=True): # needs sage.graphs ....: print("%s %3s %3s"%(T, len(RootSystem(T).root_lattice().roots()), ....: len(RootSystem(T).weight_lattice().roots()))) ['A', 1] 2 2 @@ -616,7 +634,7 @@ def short_roots(self): EXAMPLES:: sage: L = RootSystem(['B',3]).root_lattice() - sage: sorted(L.short_roots()) + sage: sorted(L.short_roots()) # needs sage.graphs [-alpha[1] - alpha[2] - alpha[3], alpha[1] + alpha[2] + alpha[3], -alpha[2] - alpha[3], @@ -635,7 +653,7 @@ def long_roots(self): EXAMPLES:: sage: L = RootSystem(['B',3]).root_lattice() - sage: sorted(L.long_roots()) + sage: sorted(L.long_roots()) # needs sage.graphs [-alpha[1], -alpha[1] - 2*alpha[2] - 2*alpha[3], -alpha[1] - alpha[2], -alpha[1] - alpha[2] - 2*alpha[3], alpha[1], alpha[1] + alpha[2], @@ -661,20 +679,20 @@ def positive_roots(self, index_set=None): EXAMPLES:: sage: L = RootSystem(['A',3]).root_lattice() - sage: sorted(L.positive_roots()) + sage: sorted(L.positive_roots()) # needs sage.graphs [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], alpha[2], alpha[2] + alpha[3], alpha[3]] - sage: sorted(L.positive_roots((1,2))) + sage: sorted(L.positive_roots((1,2))) # needs sage.graphs [alpha[1], alpha[1] + alpha[2], alpha[2]] - sage: sorted(L.positive_roots(())) + sage: sorted(L.positive_roots(())) # needs sage.graphs [] sage: L = RootSystem(['A',3,1]).root_lattice() - sage: PR = L.positive_roots(); PR + sage: PR = L.positive_roots(); PR # needs sage.graphs Disjoint union of Family (Positive real roots of type ['A', 3, 1], Positive imaginary roots of type ['A', 3, 1]) - sage: [PR.unrank(i) for i in range(10)] + sage: [PR.unrank(i) for i in range(10)] # needs sage.graphs [alpha[1], alpha[2], alpha[3], @@ -714,11 +732,11 @@ def nonparabolic_positive_roots(self, index_set=None): EXAMPLES:: sage: L = RootSystem(['A',3]).root_lattice() - sage: L.nonparabolic_positive_roots() + sage: L.nonparabolic_positive_roots() # needs sage.graphs [] - sage: sorted(L.nonparabolic_positive_roots((1,2))) + sage: sorted(L.nonparabolic_positive_roots((1,2))) # needs sage.graphs [alpha[1] + alpha[2] + alpha[3], alpha[2] + alpha[3], alpha[3]] - sage: sorted(L.nonparabolic_positive_roots(())) + sage: sorted(L.nonparabolic_positive_roots(())) # needs sage.graphs [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], alpha[2], alpha[2] + alpha[3], alpha[3]] @@ -741,11 +759,11 @@ def nonparabolic_positive_root_sum(self, index_set=None): EXAMPLES:: sage: Q = RootSystem(['A',3]).root_lattice() - sage: Q.nonparabolic_positive_root_sum((1,2)) + sage: Q.nonparabolic_positive_root_sum((1,2)) # needs sage.graphs alpha[1] + 2*alpha[2] + 3*alpha[3] - sage: Q.nonparabolic_positive_root_sum() + sage: Q.nonparabolic_positive_root_sum() # needs sage.graphs 0 - sage: Q.nonparabolic_positive_root_sum(()) + sage: Q.nonparabolic_positive_root_sum(()) # needs sage.graphs 3*alpha[1] + 4*alpha[2] + 3*alpha[3] """ @@ -758,14 +776,14 @@ def positive_real_roots(self): EXAMPLES:: sage: L = RootSystem(['A',3]).root_lattice() - sage: sorted(L.positive_real_roots()) + sage: sorted(L.positive_real_roots()) # needs sage.graphs [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], alpha[2], alpha[2] + alpha[3], alpha[3]] sage: L = RootSystem(['A',3,1]).root_lattice() - sage: PRR = L.positive_real_roots(); PRR + sage: PRR = L.positive_real_roots(); PRR # needs sage.graphs Positive real roots of type ['A', 3, 1] - sage: [PRR.unrank(i) for i in range(10)] + sage: [PRR.unrank(i) for i in range(10)] # needs sage.graphs [alpha[1], alpha[2], alpha[3], @@ -778,8 +796,8 @@ def positive_real_roots(self): alpha[0] + 2*alpha[1] + 2*alpha[2] + alpha[3]] sage: Q = RootSystem(['A',4,2]).root_lattice() - sage: PR = Q.positive_roots() - sage: [PR.unrank(i) for i in range(5)] + sage: PR = Q.positive_roots() # needs sage.graphs + sage: [PR.unrank(i) for i in range(5)] # needs sage.graphs [alpha[1], alpha[2], alpha[1] + alpha[2], @@ -787,8 +805,8 @@ def positive_real_roots(self): alpha[0] + alpha[1] + alpha[2]] sage: Q = RootSystem(['D',3,2]).root_lattice() - sage: PR = Q.positive_roots() - sage: [PR.unrank(i) for i in range(5)] + sage: PR = Q.positive_roots() # needs sage.graphs + sage: [PR.unrank(i) for i in range(5)] # needs sage.graphs [alpha[1], alpha[2], alpha[1] + 2*alpha[2], @@ -858,9 +876,9 @@ def positive_imaginary_roots(self): () sage: L = RootSystem(['A',3,1]).root_lattice() - sage: PIR = L.positive_imaginary_roots(); PIR + sage: PIR = L.positive_imaginary_roots(); PIR # needs sage.graphs Positive imaginary roots of type ['A', 3, 1] - sage: [PIR.unrank(i) for i in range(5)] + sage: [PIR.unrank(i) for i in range(5)] # needs sage.graphs [alpha[0] + alpha[1] + alpha[2] + alpha[3], 2*alpha[0] + 2*alpha[1] + 2*alpha[2] + 2*alpha[3], 3*alpha[0] + 3*alpha[1] + 3*alpha[2] + 3*alpha[3], @@ -891,13 +909,13 @@ def positive_roots_by_height(self, increasing=True): EXAMPLES:: sage: L = RootSystem(['C',2]).root_lattice() - sage: L.positive_roots_by_height() + sage: L.positive_roots_by_height() # needs sage.graphs [alpha[2], alpha[1], alpha[1] + alpha[2], 2*alpha[1] + alpha[2]] - sage: L.positive_roots_by_height(increasing = False) + sage: L.positive_roots_by_height(increasing=False) # needs sage.graphs [2*alpha[1] + alpha[2], alpha[1] + alpha[2], alpha[2], alpha[1]] sage: L = RootSystem(['A',2,1]).root_lattice() - sage: L.positive_roots_by_height() + sage: L.positive_roots_by_height() # needs sage.graphs Traceback (most recent call last): ... NotImplementedError: Only implemented for finite Cartan type @@ -927,12 +945,12 @@ def positive_roots_parabolic(self, index_set=None): EXAMPLES:: - sage: lattice = RootSystem(['A',3]).root_lattice() - sage: sorted(lattice.positive_roots_parabolic((1,3)), key=str) + sage: lattice = RootSystem(['A',3]).root_lattice() + sage: sorted(lattice.positive_roots_parabolic((1,3)), key=str) # needs sage.graphs [alpha[1], alpha[3]] - sage: sorted(lattice.positive_roots_parabolic((2,3)), key=str) + sage: sorted(lattice.positive_roots_parabolic((2,3)), key=str) # needs sage.graphs [alpha[2], alpha[2] + alpha[3], alpha[3]] - sage: sorted(lattice.positive_roots_parabolic(), key=str) + sage: sorted(lattice.positive_roots_parabolic(), key=str) # needs sage.graphs [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], alpha[2], alpha[2] + alpha[3], alpha[3]] @@ -965,9 +983,11 @@ def positive_roots_nonparabolic(self, index_set=None): EXAMPLES:: + sage: # needs sage.graphs sage: lattice = RootSystem(['A',3]).root_lattice() sage: sorted(lattice.positive_roots_nonparabolic((1,3)), key=str) - [alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], alpha[2], alpha[2] + alpha[3]] + [alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], + alpha[2], alpha[2] + alpha[3]] sage: sorted(lattice.positive_roots_nonparabolic((2,3)), key=str) [alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]] sage: lattice.positive_roots_nonparabolic() @@ -999,7 +1019,8 @@ def positive_roots_nonparabolic_sum(self, index_set=None): EXAMPLES:: - sage: lattice = RootSystem(['A',3]).root_lattice() + sage: # needs sage.graphs + sage: lattice = RootSystem(['A',3]).root_lattice() sage: lattice.positive_roots_nonparabolic_sum((1,3)) 2*alpha[1] + 4*alpha[2] + 2*alpha[3] sage: lattice.positive_roots_nonparabolic_sum((2,3)) @@ -1037,26 +1058,23 @@ def root_poset(self, restricted=False, facade=False): EXAMPLES:: - sage: Phi = RootSystem(['A',1]).root_poset(); Phi # optional - sage.graphs + sage: # needs sage.graphs + sage: Phi = RootSystem(['A',1]).root_poset(); Phi Finite poset containing 1 elements - sage: Phi.cover_relations() # optional - sage.graphs + sage: Phi.cover_relations() [] - - sage: Phi = RootSystem(['A',2]).root_poset(); Phi # optional - sage.graphs + sage: Phi = RootSystem(['A',2]).root_poset(); Phi Finite poset containing 3 elements - - sage: sorted(Phi.cover_relations(), key=str) # optional - sage.graphs + sage: sorted(Phi.cover_relations(), key=str) [[alpha[1], alpha[1] + alpha[2]], [alpha[2], alpha[1] + alpha[2]]] - - sage: Phi = RootSystem(['A',3]).root_poset(restricted=True); Phi # optional - sage.graphs + sage: Phi = RootSystem(['A',3]).root_poset(restricted=True); Phi Finite poset containing 3 elements - sage: sorted(Phi.cover_relations(), key=str) # optional - sage.graphs + sage: sorted(Phi.cover_relations(), key=str) [[alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]], [alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]] - - sage: Phi = RootSystem(['B',2]).root_poset(); Phi # optional - sage.graphs + sage: Phi = RootSystem(['B',2]).root_poset(); Phi Finite poset containing 4 elements - sage: sorted(Phi.cover_relations(), key=str) # optional - sage.graphs + sage: sorted(Phi.cover_relations(), key=str) [[alpha[1] + alpha[2], alpha[1] + 2*alpha[2]], [alpha[1], alpha[1] + alpha[2]], [alpha[2], alpha[1] + alpha[2]]] @@ -1065,7 +1083,7 @@ def root_poset(self, restricted=False, facade=False): Check that :trac:`17982` is fixed:: - sage: RootSystem(['A', 2]).ambient_space().root_poset() # optional - sage.graphs + sage: RootSystem(['A', 2]).ambient_space().root_poset() # needs sage.graphs Finite poset containing 3 elements """ from sage.combinat.posets.posets import Poset @@ -1097,16 +1115,17 @@ def nonnesting_partition_lattice(self, facade=False): sage: R = RootSystem(['A', 3]) sage: RS = R.root_lattice() - sage: P = RS.nonnesting_partition_lattice(); P # optional - sage.graphs + sage: P = RS.nonnesting_partition_lattice(); P # needs sage.graphs Finite lattice containing 14 elements - sage: P.coxeter_transformation()**10 == 1 # optional - sage.graphs + sage: P.coxeter_transformation()**10 == 1 # needs sage.graphs True - sage: R = RootSystem(['B', 3]) # optional - sage.graphs - sage: RS = R.root_lattice() # optional - sage.graphs - sage: P = RS.nonnesting_partition_lattice(); P # optional - sage.graphs + sage: # needs sage.graphs + sage: R = RootSystem(['B', 3]) + sage: RS = R.root_lattice() + sage: P = RS.nonnesting_partition_lattice(); P Finite lattice containing 20 elements - sage: P.coxeter_transformation()**7 == 1 # optional - sage.graphs + sage: P.coxeter_transformation()**7 == 1 True REFERENCES: @@ -1136,9 +1155,9 @@ def generalized_nonnesting_partition_lattice(self, m, facade=False): sage: R = RootSystem(['A', 2]) sage: RS = R.root_lattice() - sage: P = RS.generalized_nonnesting_partition_lattice(2); P # optional - sage.graphs + sage: P = RS.generalized_nonnesting_partition_lattice(2); P # needs sage.graphs Finite lattice containing 12 elements - sage: P.coxeter_transformation()**20 == 1 # optional - sage.graphs + sage: P.coxeter_transformation()**20 == 1 # needs sage.graphs True """ Phi_plus = self.positive_roots() @@ -1189,7 +1208,7 @@ def almost_positive_roots(self): EXAMPLES:: sage: L = RootSystem(['A',2]).root_lattice() - sage: L.almost_positive_roots() + sage: L.almost_positive_roots() # needs sage.graphs [-alpha[1], alpha[1], alpha[1] + alpha[2], -alpha[2], alpha[2]] """ if not self.cartan_type().is_finite(): @@ -1203,7 +1222,7 @@ def negative_roots(self): EXAMPLES:: sage: L = RootSystem(['A', 2]).weight_lattice() - sage: sorted(L.negative_roots()) + sage: sorted(L.negative_roots()) # needs sage.graphs [-2*Lambda[1] + Lambda[2], -Lambda[1] - Lambda[2], Lambda[1] - 2*Lambda[2]] Algorithm: negate the positive roots @@ -1344,11 +1363,11 @@ def null_root(self): EXAMPLES:: - sage: RootSystem(['C',2,1]).root_lattice().null_root() + sage: RootSystem(['C',2,1]).root_lattice().null_root() # needs sage.graphs alpha[0] + 2*alpha[1] + alpha[2] - sage: RootSystem(['D',4,1]).root_lattice().null_root() + sage: RootSystem(['D',4,1]).root_lattice().null_root() # needs sage.graphs alpha[0] + alpha[1] + 2*alpha[2] + alpha[3] + alpha[4] - sage: RootSystem(['F',4,1]).root_lattice().null_root() + sage: RootSystem(['F',4,1]).root_lattice().null_root() # needs sage.graphs alpha[0] + 2*alpha[1] + 3*alpha[2] + 4*alpha[3] + 2*alpha[4] """ if self.cartan_type().is_affine(): @@ -1370,12 +1389,12 @@ def null_coroot(self): EXAMPLES:: - sage: RootSystem(['C',2,1]).root_lattice().null_coroot() + sage: RootSystem(['C',2,1]).root_lattice().null_coroot() # needs sage.graphs alphacheck[0] + alphacheck[1] + alphacheck[2] - sage: RootSystem(['D',4,1]).root_lattice().null_coroot() + sage: RootSystem(['D',4,1]).root_lattice().null_coroot() # needs sage.graphs alphacheck[0] + alphacheck[1] + 2*alphacheck[2] + alphacheck[3] + alphacheck[4] - sage: RootSystem(['F',4,1]).root_lattice().null_coroot() + sage: RootSystem(['F',4,1]).root_lattice().null_coroot() # needs sage.graphs alphacheck[0] + 2*alphacheck[1] + 3*alphacheck[2] + 2*alphacheck[3] + alphacheck[4] """ @@ -1402,11 +1421,11 @@ def fundamental_weights_from_simple_roots(self): In the root space, we retrieve the inverse of the Cartan matrix:: sage: L = RootSystem(["B",3]).root_space() - sage: L.fundamental_weights_from_simple_roots() + sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs Finite family {1: alpha[1] + alpha[2] + alpha[3], 2: alpha[1] + 2*alpha[2] + 2*alpha[3], 3: 1/2*alpha[1] + alpha[2] + 3/2*alpha[3]} - sage: ~L.cartan_type().cartan_matrix() + sage: ~L.cartan_type().cartan_matrix() # needs sage.graphs [ 1 1 1/2] [ 1 2 1] [ 1 2 3/2] @@ -1415,20 +1434,20 @@ def fundamental_weights_from_simple_roots(self): the fundamental weights:: sage: L = RootSystem(["B",3]).weight_lattice() - sage: L.fundamental_weights_from_simple_roots() + sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs Finite family {1: Lambda[1], 2: Lambda[2], 3: Lambda[3]} sage: L = RootSystem(["B",3]).ambient_space() sage: L.fundamental_weights() Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)} - sage: L.fundamental_weights_from_simple_roots() + sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)} However the fundamental weights do not belong to the root lattice:: sage: L = RootSystem(["B",3]).root_lattice() - sage: L.fundamental_weights_from_simple_roots() + sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs Traceback (most recent call last): ... ValueError: The fundamental weights do not live in this realization @@ -1439,13 +1458,13 @@ def fundamental_weights_from_simple_roots(self): sage: L = RootSystem(["A",3]).ambient_space() sage: L.fundamental_weights() Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)} - sage: L.fundamental_weights_from_simple_roots() + sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs Finite family {1: (3/4, -1/4, -1/4, -1/4), 2: (1/2, 1/2, -1/2, -1/2), 3: (1/4, 1/4, 1/4, -3/4)} sage: L = RootSystem(["A",3]).ambient_lattice() - sage: L.fundamental_weights_from_simple_roots() + sage: L.fundamental_weights_from_simple_roots() # needs sage.graphs Traceback (most recent call last): ... ValueError: The fundamental weights do not live in this realization @@ -1479,6 +1498,7 @@ def reflection(self, root, coroot=None): EXAMPLES:: + sage: # needs sage.graphs sage: space = RootSystem(['A',2]).weight_lattice() sage: x = space.simple_roots()[1] sage: y = space.simple_coroots()[1] @@ -1508,8 +1528,7 @@ def simple_reflection(self, i): sage: space = RootSystem(['A',2]).ambient_lattice() sage: s = space.simple_reflection(1) - sage: x = space.simple_roots()[1] - sage: x + sage: x = space.simple_roots()[1]; x (1, -1, 0) sage: s(x) (-1, 1, 0) @@ -1526,7 +1545,7 @@ def simple_reflections(self): sage: r = RootSystem(["A", 2]).root_lattice() sage: s = r.simple_reflections() - sage: s[1]( r.simple_root(1) ) + sage: s[1]( r.simple_root(1) ) # needs sage.graphs -alpha[1] TESTS:: @@ -1559,6 +1578,7 @@ def projection(self, root, coroot=None, to_negative=True): EXAMPLES:: + sage: # needs sage.graphs sage: space = RootSystem(['A',2]).weight_lattice() sage: x = space.simple_roots()[1] sage: y = space.simple_coroots()[1] @@ -1591,6 +1611,7 @@ def simple_projection(self, i, to_negative=True): EXAMPLES:: + sage: # needs sage.graphs sage: space = RootSystem(['A',2]).weight_lattice() sage: x = space.simple_roots()[1] sage: pi = space.simple_projection(1) @@ -1615,14 +1636,14 @@ def simple_projections(self, to_negative=True): EXAMPLES:: sage: space = RootSystem(['A',2]).weight_lattice() - sage: pi = space.simple_projections() - sage: x = space.simple_roots() - sage: pi[1](x[2]) + sage: pi = space.simple_projections() # needs sage.graphs + sage: x = space.simple_roots() # needs sage.graphs + sage: pi[1](x[2]) # needs sage.graphs -Lambda[1] + 2*Lambda[2] TESTS:: - sage: pi + sage: pi # needs sage.graphs pi """ if to_negative is not True: @@ -1642,9 +1663,9 @@ def weyl_group(self, prefix=None): EXAMPLES:: - sage: RootSystem(['F',4]).ambient_space().weyl_group() + sage: RootSystem(['F',4]).ambient_space().weyl_group() # needs sage.libs.gap Weyl Group of type ['F', 4] (as a matrix group acting on the ambient space) - sage: RootSystem(['F',4]).root_space().weyl_group() + sage: RootSystem(['F',4]).root_space().weyl_group() # needs sage.libs.gap Weyl Group of type ['F', 4] (as a matrix group acting on the root space) """ @@ -1677,22 +1698,22 @@ def tau_epsilon_operator_on_almost_positive_roots(self, J): EXAMPLES:: sage: L = RootSystem(['A',4]).root_lattice() - sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3]) - sage: alpha = L.simple_roots() + sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3]) # needs sage.libs.gap + sage: alpha = L.simple_roots() # needs sage.graphs The action on a negative simple root not in `J`:: - sage: tau(-alpha[2]) + sage: tau(-alpha[2]) # needs sage.graphs sage.libs.gap -alpha[2] The action on a negative simple root in `J`:: - sage: tau(-alpha[1]) + sage: tau(-alpha[1]) # needs sage.graphs sage.libs.gap alpha[1] The action on all almost positive roots:: - sage: for root in L.almost_positive_roots(): + sage: for root in L.almost_positive_roots(): # needs sage.graphs sage.libs.gap ....: print('tau({:<41}) = {}'.format(str(root), tau(root))) tau(-alpha[1] ) = alpha[1] tau(alpha[1] ) = -alpha[1] @@ -1712,8 +1733,8 @@ def tau_epsilon_operator_on_almost_positive_roots(self, J): This method works on any root lattice realization:: sage: L = RootSystem(['B',3]).ambient_space() - sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3]) - sage: for root in L.almost_positive_roots(): + sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3]) # needs sage.libs.gap + sage: for root in L.almost_positive_roots(): # needs sage.graphs sage.libs.gap ....: print('tau({:<41}) = {}'.format(str(root), tau(root))) tau((-1, 1, 0) ) = (1, -1, 0) tau((1, 0, 0) ) = (0, 1, 0) @@ -1768,8 +1789,8 @@ def tau_plus_minus(self): We explore the example of [CFZ2002]_ Eq.(1.3):: sage: S = RootSystem(['A',2]).root_lattice() - sage: taup, taum = S.tau_plus_minus() - sage: for beta in S.almost_positive_roots(): + sage: taup, taum = S.tau_plus_minus() # needs sage.graphs + sage: for beta in S.almost_positive_roots(): # needs sage.graphs ....: print("{} , {} , {}".format(beta, taup(beta), taum(beta))) -alpha[1] , alpha[1] , -alpha[1] alpha[1] , -alpha[1] , alpha[1] + alpha[2] @@ -1796,14 +1817,14 @@ def almost_positive_roots_decomposition(self): EXAMPLES:: - sage: RootSystem(['A',2]).root_lattice().almost_positive_roots_decomposition() + sage: RootSystem(['A',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs [[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2], -alpha[2]]] - sage: RootSystem(['B',2]).root_lattice().almost_positive_roots_decomposition() + sage: RootSystem(['B',2]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs [[-alpha[1], alpha[1], alpha[1] + 2*alpha[2]], [-alpha[2], alpha[2], alpha[1] + alpha[2]]] - sage: RootSystem(['D',4]).root_lattice().almost_positive_roots_decomposition() + sage: RootSystem(['D',4]).root_lattice().almost_positive_roots_decomposition() # needs sage.graphs [[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2] + alpha[3] + alpha[4]], [-alpha[2], alpha[2], alpha[1] + alpha[2] + alpha[3] + alpha[4], alpha[1] + 2*alpha[2] + alpha[3] + alpha[4]], @@ -1914,19 +1935,19 @@ def _classical_alpha_0(self): This is the opposite of the highest root in the untwisted case:: sage: L = RootSystem(["B",3,1]).root_space() - sage: L._classical_alpha_0() + sage: L._classical_alpha_0() # needs sage.graphs -alpha[1] - 2*alpha[2] - 2*alpha[3] - sage: L._to_classical_on_basis(0) + sage: L._to_classical_on_basis(0) # needs sage.graphs -alpha[1] - 2*alpha[2] - 2*alpha[3] - sage: L.classical().highest_root() + sage: L.classical().highest_root() # needs sage.graphs alpha[1] + 2*alpha[2] + 2*alpha[3] But not in the other cases:: sage: L = RootSystem(CartanType(["B",3,1]).dual()).root_space() - sage: L._to_classical_on_basis(0) + sage: L._to_classical_on_basis(0) # needs sage.graphs -alpha[1] - 2*alpha[2] - alpha[3] - sage: L.classical().highest_root() + sage: L.classical().highest_root() # needs sage.graphs 2*alpha[1] + 2*alpha[2] + alpha[3] """ cartan_type = self.cartan_type() @@ -2059,7 +2080,7 @@ def plot(self, EXAMPLES:: - sage: L = RootSystem(["A",2,1]).ambient_space().plot() # long time # optional - sage.plot sage.symbolic + sage: L = RootSystem(["A",2,1]).ambient_space().plot() # long time, needs sage.plot sage.symbolic .. SEEALSO:: @@ -2124,7 +2145,7 @@ def plot_parse_options(self, **args): EXAMPLES:: sage: L = RootSystem(["A",2,1]).ambient_space() - sage: options = L.plot_parse_options(); options # optional - sage.symbolic + sage: options = L.plot_parse_options(); options # needs sage.symbolic .. SEEALSO:: @@ -2149,7 +2170,7 @@ def _plot_projection(self, x): sage: L = RootSystem(["B",3]).root_lattice() sage: l = L.an_element(); l 2*alpha[1] + 2*alpha[2] + 3*alpha[3] - sage: L._plot_projection(l) # optional - sage.symbolic + sage: L._plot_projection(l) # needs sage.symbolic 2*alpha[1] + 2*alpha[2] + 3*alpha[3] In the ambient space of type `A_2`, this is the @@ -2183,22 +2204,23 @@ def _plot_projection_barycentric_matrix(self): EXAMPLES:: - sage: RootSystem(["A",0]).ambient_space()._plot_projection_barycentric_matrix() # optional - sage.symbolic + sage: # needs sage.symbolic + sage: RootSystem(["A",0]).ambient_space()._plot_projection_barycentric_matrix() [] - sage: m = RootSystem(["A",1]).ambient_space()._plot_projection_barycentric_matrix(); m # optional - sage.symbolic + sage: m = RootSystem(["A",1]).ambient_space()._plot_projection_barycentric_matrix(); m [ 1 -1] - sage: sum(m.columns()) # optional - sage.symbolic + sage: sum(m.columns()) (0) - sage: m = RootSystem(["A",2]).ambient_space()._plot_projection_barycentric_matrix(); m # optional - sage.symbolic + sage: m = RootSystem(["A",2]).ambient_space()._plot_projection_barycentric_matrix(); m [ 1/2 -1 1/2] [ 989/1142 0 -989/1142] - sage: sum(m.columns()) # optional - sage.symbolic + sage: sum(m.columns()) (0, 0) - sage: m = RootSystem(["A",3]).ambient_space()._plot_projection_barycentric_matrix(); m # optional - sage.symbolic + sage: m = RootSystem(["A",3]).ambient_space()._plot_projection_barycentric_matrix(); m [ 1277/1564 -1277/1564 0 0] [1009460/2141389 849/1801 -1121/1189 0] [ 1/3 1/3 1/3 -1] - sage: sum(m.columns()) # optional - sage.symbolic + sage: sum(m.columns()) (0, 0, 0) """ @@ -2226,11 +2248,11 @@ def _plot_projection_barycentric(self, x): sage: L = RootSystem(["A",2]).ambient_space() sage: e = L.basis() - sage: L._plot_projection_barycentric(e[0]) # optional - sage.symbolic + sage: L._plot_projection_barycentric(e[0]) # needs sage.symbolic (1/2, 989/1142) - sage: L._plot_projection_barycentric(e[1]) # optional - sage.symbolic + sage: L._plot_projection_barycentric(e[1]) # needs sage.symbolic (-1, 0) - sage: L._plot_projection_barycentric(e[2]) # optional - sage.symbolic + sage: L._plot_projection_barycentric(e[2]) # needs sage.symbolic (1/2, -989/1142) .. SEEALSO:: @@ -2264,36 +2286,36 @@ def plot_roots(self, collection="simple", **options): EXAMPLES:: - sage: RootSystem(["B",3]).ambient_space().plot_roots() # optional - sage.plot + sage: RootSystem(["B",3]).ambient_space().plot_roots() # needs sage.plot Graphics3d Object - sage: RootSystem(["B",3]).ambient_space().plot_roots("all") # optional - sage.plot + sage: RootSystem(["B",3]).ambient_space().plot_roots("all") # needs sage.plot Graphics3d Object TESTS:: - sage: list(RootSystem(["A",2]).root_lattice().plot_roots()) # optional - sage.plot sage.symbolic + sage: list(RootSystem(["A",2]).root_lattice().plot_roots()) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (1.0,0.0), Text '$\alpha_{1}$' at the point (1.05,0.0), Arrow from (0.0,0.0) to (0.0,1.0), Text '$\alpha_{2}$' at the point (0.0,1.05)] - sage: list(RootSystem(["A",2]).weight_lattice().plot_roots(labels=False)) # optional - sage.plot sage.symbolic + sage: list(RootSystem(["A",2]).weight_lattice().plot_roots(labels=False)) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (2.0,-1.0), Arrow from (0.0,0.0) to (-1.0,2.0)] - sage: list(RootSystem(["A",2]).ambient_lattice().plot_roots()) # optional - sage.plot sage.symbolic + sage: list(RootSystem(["A",2]).ambient_lattice().plot_roots()) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (1.5,0.86...), Text '$\alpha_{1}$' at the point (1.575...,0.90...), Arrow from (0.0,0.0) to (-1.5,0.86...), Text '$\alpha_{2}$' at the point (-1.575...,0.90...)] - sage: list(RootSystem(["B",2]).ambient_space().plot_roots()) # optional - sage.plot sage.symbolic + sage: list(RootSystem(["B",2]).ambient_space().plot_roots()) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (1.0,-1.0), Text '$\alpha_{1}$' at the point (1.05,-1.05), Arrow from (0.0,0.0) to (0.0,1.0), Text '$\alpha_{2}$' at the point (0.0,1.05)] - sage: list(RootSystem(["A",2]).root_lattice().plot_roots("all")) # optional - sage.plot sage.symbolic + sage: list(RootSystem(["A",2]).root_lattice().plot_roots("all")) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (1.0,0.0), Text '$\alpha_{1}$' at the point (1.05,0.0), Arrow from (0.0,0.0) to (0.0,1.0), @@ -2349,12 +2371,12 @@ def plot_coroots(self, collection="simple", **options): EXAMPLES:: - sage: RootSystem(["B",3]).ambient_space().plot_coroots() # optional - sage.plot sage.symbolic + sage: RootSystem(["B",3]).ambient_space().plot_coroots() # needs sage.plot sage.symbolic Graphics3d Object TESTS:: - sage: list(RootSystem(["B",2]).ambient_space().plot_coroots()) # optional - sage.plot sage.symbolic + sage: list(RootSystem(["B",2]).ambient_space().plot_coroots()) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (1.0,-1.0), Text '$\alpha^\vee_{1}$' at the point (1.05,-1.05), Arrow from (0.0,0.0) to (0.0,2.0), @@ -2399,18 +2421,18 @@ def plot_fundamental_weights(self, **options): EXAMPLES:: - sage: RootSystem(["B",3]).ambient_space().plot_fundamental_weights() # optional - sage.plot + sage: RootSystem(["B",3]).ambient_space().plot_fundamental_weights() # needs sage.plot Graphics3d Object TESTS:: - sage: sorted(RootSystem(["A",2]).weight_lattice().plot_fundamental_weights(), key=str) # optional - sage.plot sage.symbolic + sage: sorted(RootSystem(["A",2]).weight_lattice().plot_fundamental_weights(), key=str) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (0.0,1.0), Arrow from (0.0,0.0) to (1.0,0.0), Text '$\Lambda_{1}$' at the point (1.05,0.0), Text '$\Lambda_{2}$' at the point (0.0,1.05)] - sage: sorted(RootSystem(["A",2]).ambient_lattice().plot_fundamental_weights(), key=str) # optional - sage.plot sage.symbolic + sage: sorted(RootSystem(["A",2]).ambient_lattice().plot_fundamental_weights(), key=str) # needs sage.plot sage.symbolic [Arrow from (0.0,0.0) to (-0.5,0.86602451838...), Arrow from (0.0,0.0) to (0.5,0.86602451838...), Text '$\Lambda_{1}$' at the point (0.525,0.909325744308...), @@ -2452,33 +2474,34 @@ def plot_reflection_hyperplanes(self, collection="simple", **options): EXAMPLES:: - sage: RootSystem(["A",2,1]).ambient_space().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: # needs sage.plot sage.symbolic + sage: RootSystem(["A",2,1]).ambient_space().plot_reflection_hyperplanes() Graphics object consisting of 6 graphics primitives - sage: RootSystem(["G",2,1]).ambient_space().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: RootSystem(["G",2,1]).ambient_space().plot_reflection_hyperplanes() Graphics object consisting of 6 graphics primitives - sage: RootSystem(["A",3]).weight_space().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: RootSystem(["A",3]).weight_space().plot_reflection_hyperplanes() Graphics3d Object - sage: RootSystem(["B",3]).ambient_space().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: RootSystem(["B",3]).ambient_space().plot_reflection_hyperplanes() Graphics3d Object - sage: RootSystem(["A",3,1]).weight_space().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: RootSystem(["A",3,1]).weight_space().plot_reflection_hyperplanes() Graphics3d Object - sage: RootSystem(["B",3,1]).ambient_space().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: RootSystem(["B",3,1]).ambient_space().plot_reflection_hyperplanes() Graphics3d Object - sage: RootSystem(["A",2,1]).weight_space().plot_reflection_hyperplanes(affine=False, level=1) # optional - sage.plot sage.symbolic + sage: RootSystem(["A",2,1]).weight_space().plot_reflection_hyperplanes(affine=False, level=1) Graphics3d Object - sage: RootSystem(["A",2]).root_lattice().plot_reflection_hyperplanes() # optional - sage.plot sage.symbolic + sage: RootSystem(["A",2]).root_lattice().plot_reflection_hyperplanes() Graphics object consisting of 4 graphics primitives TESTS:: sage: L = RootSystem(["A",2]).ambient_space() - sage: print(L.plot_reflection_hyperplanes().description()) # optional - sage.plot sage.symbolic + sage: print(L.plot_reflection_hyperplanes().description()) # needs sage.plot sage.symbolic Text '$H_{\alpha^\vee_{1}}$' at the point (-1.81...,3.15...) Text '$H_{\alpha^\vee_{2}}$' at the point (1.81...,3.15...) Line defined by 2 points: [(-1.73..., 3.0), (1.73..., -3.0)] Line defined by 2 points: [(1.73..., 3.0), (-1.73..., -3.0)] - sage: print(L.plot_reflection_hyperplanes("all").description()) # optional - sage.plot sage.symbolic + sage: print(L.plot_reflection_hyperplanes("all").description()) # needs sage.plot sage.symbolic Text '$H_{\alpha^\vee_{1} + \alpha^\vee_{2}}$' at the point (3.15...,0.0) Text '$H_{\alpha^\vee_{1}}$' at the point (-1.81...,3.15...) Text '$H_{\alpha^\vee_{2}}$' at the point (1.81...,3.15...) @@ -2487,7 +2510,7 @@ def plot_reflection_hyperplanes(self, collection="simple", **options): Line defined by 2 points: [(3.0, 0.0), (-3.0, 0.0)] sage: L = RootSystem(["A",2,1]).ambient_space() - sage: print(L.plot_reflection_hyperplanes().description()) # optional - sage.plot sage.symbolic + sage: print(L.plot_reflection_hyperplanes().description()) # needs sage.plot sage.symbolic Text '$H_{\alpha^\vee_{0}}$' at the point (3.15...,0.90...) Text '$H_{\alpha^\vee_{1}}$' at the point (-1.81...,3.15...) Text '$H_{\alpha^\vee_{2}}$' at the point (1.81...,3.15...) @@ -2536,27 +2559,28 @@ def plot_hedron(self, **options): EXAMPLES:: - sage: RootSystem(["A",2]).ambient_space().plot_hedron() # optional - sage.plot sage.symbolic + sage: # needs sage.plot sage.symbolic + sage: RootSystem(["A",2]).ambient_space().plot_hedron() Graphics object consisting of 8 graphics primitives - sage: RootSystem(["A",3]).ambient_space().plot_hedron() # optional - sage.plot sage.symbolic + sage: RootSystem(["A",3]).ambient_space().plot_hedron() Graphics3d Object - sage: RootSystem(["B",3]).ambient_space().plot_hedron() # optional - sage.plot sage.symbolic + sage: RootSystem(["B",3]).ambient_space().plot_hedron() Graphics3d Object - sage: RootSystem(["C",3]).ambient_space().plot_hedron() # optional - sage.plot sage.symbolic + sage: RootSystem(["C",3]).ambient_space().plot_hedron() Graphics3d Object - sage: RootSystem(["D",3]).ambient_space().plot_hedron() # optional - sage.plot sage.symbolic + sage: RootSystem(["D",3]).ambient_space().plot_hedron() Graphics3d Object Surprise: polyhedra of large dimension know how to project themselves nicely:: - sage: RootSystem(["F",4]).ambient_space().plot_hedron() # long time # optional - sage.plot sage.symbolic + sage: RootSystem(["F",4]).ambient_space().plot_hedron() # long time, needs sage.plot sage.symbolic Graphics3d Object TESTS:: sage: L = RootSystem(["B",2]).ambient_space() - sage: print(L.plot_hedron().description()) # optional - sage.plot sage.symbolic + sage: print(L.plot_hedron().description()) # needs sage.plot sage.symbolic Polygon defined by 8 points: [(1.5, 0.5), (0.5, 1.5), (-0.5, 1.5), (-1.5, 0.5), (-1.5, -0.5), (-0.5, -1.5), (0.5, -1.5), (1.5, -0.5)] Line defined by 2 points: [(-0.5, -1.5), (0.5, -1.5)] Line defined by 2 points: [(-0.5, 1.5), (0.5, 1.5)] @@ -2596,23 +2620,23 @@ def plot_fundamental_chamber(self, style="normal", **options): 2D plots:: - sage: RootSystem(["B",2]).ambient_space().plot_fundamental_chamber() # optional - sage.plot + sage: RootSystem(["B",2]).ambient_space().plot_fundamental_chamber() # needs sage.plot Graphics object consisting of 1 graphics primitive - sage: RootSystem(["B",2,1]).ambient_space().plot_fundamental_chamber() # optional - sage.plot + sage: RootSystem(["B",2,1]).ambient_space().plot_fundamental_chamber() # needs sage.plot Graphics object consisting of 1 graphics primitive - sage: RootSystem(["B",2,1]).ambient_space().plot_fundamental_chamber("classical") # optional - sage.plot + sage: RootSystem(["B",2,1]).ambient_space().plot_fundamental_chamber("classical") # needs sage.plot Graphics object consisting of 1 graphics primitive 3D plots:: - sage: RootSystem(["A",3,1]).weight_space() .plot_fundamental_chamber() # optional - sage.plot + sage: RootSystem(["A",3,1]).weight_space() .plot_fundamental_chamber() # needs sage.plot Graphics3d Object - sage: RootSystem(["B",3,1]).ambient_space().plot_fundamental_chamber() # optional - sage.plot + sage: RootSystem(["B",3,1]).ambient_space().plot_fundamental_chamber() # needs sage.plot Graphics3d Object This feature is currently not available in the root lattice/space:: - sage: list(RootSystem(["A",2]).root_lattice().plot_fundamental_chamber()) + sage: list(RootSystem(["A",2]).root_lattice().plot_fundamental_chamber()) # needs sage.plot Traceback (most recent call last): ... TypeError: classical fundamental chamber not yet available in the root lattice @@ -2620,10 +2644,10 @@ def plot_fundamental_chamber(self, style="normal", **options): TESTS:: sage: L = RootSystem(["B",2,1]).ambient_space() - sage: print(L.plot_fundamental_chamber().description()) # optional - sage.plot + sage: print(L.plot_fundamental_chamber().description()) # needs sage.plot Polygon defined by 3 points: [(0.5, 0.5), (1.0, 0.0), (0.0, 0.0)] - sage: print(L.plot_fundamental_chamber(style="classical").description()) # optional - sage.plot + sage: print(L.plot_fundamental_chamber(style="classical").description()) # needs sage.plot Polygon defined by 3 points: [(0.0, 0.0), (3.0, 3.0), (3.0, 0.0)] """ plot_options = self.plot_parse_options(**options) @@ -2668,28 +2692,28 @@ def plot_alcoves(self, alcoves=True, alcove_labels=False, wireframe=False, **opt 2D plots:: - sage: RootSystem(["B",2,1]).ambient_space().plot_alcoves() # long time (3s) # optional - sage.plot sage.symbolic + sage: RootSystem(["B",2,1]).ambient_space().plot_alcoves() # long time (3s), needs sage.plot sage.symbolic Graphics object consisting of 228 graphics primitives 3D plots:: - sage: RootSystem(["A",2,1]).weight_space() .plot_alcoves(affine=False) # long time (3s) # optional - sage.plot sage.symbolic + sage: RootSystem(["A",2,1]).weight_space() .plot_alcoves(affine=False) # long time (3s), needs sage.plot sage.symbolic Graphics3d Object - sage: RootSystem(["G",2,1]).ambient_space().plot_alcoves(affine=False, level=1) # long time (3s) # optional - sage.plot sage.symbolic + sage: RootSystem(["G",2,1]).ambient_space().plot_alcoves(affine=False, level=1) # long time (3s), needs sage.plot sage.symbolic Graphics3d Object Here we plot a single alcove:: sage: L = RootSystem(["A",3,1]).ambient_space() - sage: W = L.weyl_group() - sage: L.plot(alcoves=[W.one()], reflection_hyperplanes=False, bounding_box=2) # optional - sage.plot sage.symbolic + sage: W = L.weyl_group() # needs sage.libs.gap + sage: L.plot(alcoves=[W.one()], reflection_hyperplanes=False, bounding_box=2) # needs sage.libs.gap sage.plot sage.symbolic Graphics3d Object TESTS:: sage: L = RootSystem(["A",2,1]).weight_space() - sage: p = L.plot_alcoves(alcoves=[[0,0]]) # optional - sage.plot sage.symbolic - sage: print(p.description()) # optional - sage.plot sage.symbolic + sage: p = L.plot_alcoves(alcoves=[[0,0]]) # needs sage.plot sage.symbolic + sage: print(p.description()) # needs sage.plot sage.symbolic Line defined by 2 points: [(-1.0, 0.0), (0.0, -1.0)] Line defined by 2 points: [(-1.0, 1.0), (-1.0, 0.0)] Line defined by 2 points: [(-1.0, 1.0), (0.0, 0.0)] @@ -2702,7 +2726,7 @@ def plot_alcoves(self, alcoves=True, alcove_labels=False, wireframe=False, **opt Line defined by 2 points: [(1.0, -1.0), (0.0, -1.0)] Line defined by 2 points: [(1.0, 0.0), (0.0, 0.0)] Line defined by 2 points: [(1.0, 0.0), (1.0, -1.0)] - sage: sorted((line.options()['rgbcolor'], line.options()['thickness']) for line in p) # optional - sage.plot sage.symbolic + sage: sorted((line.options()['rgbcolor'], line.options()['thickness']) for line in p) # needs sage.plot sage.symbolic [('black', 2), ('black', 2), ('black', 2), ('black', 2), ('black', 2), ('black', 2), ('blue', 1), ('blue', 1), ('blue', 1), @@ -2862,12 +2886,12 @@ def plot_bounding_box(self, **options): EXAMPLES:: sage: L = RootSystem(["A",2,1]).ambient_space() - sage: L.plot_bounding_box() # optional - sage.plot sage.symbolic + sage: L.plot_bounding_box() # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive TESTS:: - sage: list(L.plot_bounding_box()) # optional - sage.plot sage.symbolic + sage: list(L.plot_bounding_box()) # needs sage.plot sage.symbolic [Polygon defined by 4 points] """ plot_options = self.plot_parse_options(**options) @@ -2896,20 +2920,20 @@ def plot_alcove_walk(self, word, start=None, foldings=None, color="orange", **op sage: L = RootSystem(["A",2,1]).ambient_space() sage: w1 = [0,2,1,2,0,2,1,0,2,1,2,1,2,0,2,0,1,2,0] - sage: p = L.plot_alcoves(bounding_box=5) # long time (5s) # optional - sage.plot sage.symbolic - sage: p += L.plot_alcove_walk(w1) # long time # optional - sage.plot sage.symbolic - sage: p # long time # optional - sage.plot sage.symbolic + sage: p = L.plot_alcoves(bounding_box=5) # long time (5s) # needs sage.plot sage.symbolic + sage: p += L.plot_alcove_walk(w1) # long time # needs sage.plot sage.symbolic + sage: p # long time # needs sage.plot sage.symbolic Graphics object consisting of 375 graphics primitives The same plot with another alcove walk:: sage: w2 = [2,1,2,0,2,0,2,1,2,0,1,2,1,2,1,0,1,2,0,2,0,1,2,0,2] - sage: p += L.plot_alcove_walk(w2, color="orange") # long time # optional - sage.plot sage.symbolic + sage: p += L.plot_alcove_walk(w2, color="orange") # long time, needs sage.plot sage.symbolic And another with some foldings:: - sage: pic = L.plot_alcoves(bounding_box=3) # long time # optional - sage.plot sage.symbolic - sage: pic += L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # long time (3s), optional - sage.plot sage.symbolic + sage: pic = L.plot_alcoves(bounding_box=3) # long time, needs sage.plot sage.symbolic + sage: pic += L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # long time (3s), needs sage.plot sage.symbolic ....: foldings=[False, False, True, False, False, ....: False, True, False, True, False], ....: color="green"); pic @@ -2918,12 +2942,12 @@ def plot_alcove_walk(self, word, start=None, foldings=None, color="orange", **op TESTS:: sage: L = RootSystem(["A",2,1]).weight_space() - sage: p = L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # optional - sage.plot sage.symbolic + sage: p = L.plot_alcove_walk([0,1,2,0,2,0,1,2,0,1], # needs sage.plot sage.symbolic ....: foldings=[False, False, True, False, False, ....: False, True, False, True, False], ....: color="green", ....: start=L.rho()) - sage: print(p.description()) # optional - sage.plot sage.symbolic + sage: print(p.description()) # needs sage.plot sage.symbolic Line defined by 2 points: [(-1.0, 8.0), (-1.5, 9.0)] Line defined by 2 points: [(1.0, 4.0), (1.5, 4.5)] Line defined by 2 points: [(1.0, 7.0), (1.5, 6.0)] @@ -3011,16 +3035,16 @@ def plot_ls_paths(self, paths, plot_labels=None, colored_labels=True, **options) EXAMPLES:: - sage: B = crystals.LSPaths(['A',2], [1,1]) + sage: B = crystals.LSPaths(['A',2], [1,1]) # needs sage.combinat sage: L = RootSystem(['A',2]).ambient_space() - sage: L.plot_fundamental_weights() + L.plot_ls_paths(B) # optional - sage.plot sage.symbolic + sage: L.plot_fundamental_weights() + L.plot_ls_paths(B) # needs sage.combinat sage.plot sage.symbolic Graphics object consisting of 14 graphics primitives This also works in 3 dimensions:: - sage: B = crystals.LSPaths(['B',3], [2,0,0]) + sage: B = crystals.LSPaths(['B',3], [2,0,0]) # needs sage.combinat sage: L = RootSystem(['B',3]).ambient_space() - sage: L.plot_ls_paths(B) # optional - sage.plot sage.symbolic + sage: L.plot_ls_paths(B) # needs sage.combinat sage.plot sage.symbolic Graphics3d Object """ if not isinstance(paths, (list, tuple, set)): @@ -3078,18 +3102,18 @@ def plot_mv_polytope(self, mv_polytope, mark_endpoints=True, EXAMPLES:: - sage: B = crystals.infinity.MVPolytopes(['C',2]) + sage: B = crystals.infinity.MVPolytopes(['C',2]) # needs sage.combinat sage: L = RootSystem(['C',2]).ambient_space() - sage: p = B.highest_weight_vector().f_string([1,2,1,2]) - sage: L.plot_fundamental_weights() + L.plot_mv_polytope(p) # optional - sage.geometry.polyhedron sage.plot sage.symbolic + sage: p = B.highest_weight_vector().f_string([1,2,1,2]) # needs sage.combinat + sage: L.plot_fundamental_weights() + L.plot_mv_polytope(p) # needs sage.combinat sage.geometry.polyhedron sage.plot sage.symbolic Graphics object consisting of 14 graphics primitives This also works in 3 dimensions:: - sage: B = crystals.infinity.MVPolytopes(['A',3]) + sage: B = crystals.infinity.MVPolytopes(['A',3]) # needs sage.combinat sage: L = RootSystem(['A',3]).ambient_space() - sage: p = B.highest_weight_vector().f_string([2,1,3,2]) - sage: L.plot_mv_polytope(p) # optional - sage.geometry.polyhedron sage.plot sage.symbolic + sage: p = B.highest_weight_vector().f_string([2,1,3,2]) # needs sage.combinat + sage: L.plot_mv_polytope(p) # needs sage.combinat sage.geometry.polyhedron sage.plot sage.symbolic Graphics3d Object """ from sage.geometry.polyhedron.constructor import Polyhedron @@ -3157,19 +3181,20 @@ def plot_crystal(self, crystal, EXAMPLES:: + sage: # needs sage.combinat sage.plot sage.symbolic sage: L = RootSystem(['A',2]).ambient_space() sage: C = crystals.Tableaux(['A',2], shape=[2,1]) - sage: L.plot_crystal(C, plot_labels='multiplicities') # optional - sage.plot sage.symbolic + sage: L.plot_crystal(C, plot_labels='multiplicities') Graphics object consisting of 15 graphics primitives sage: C = crystals.Tableaux(['A',2], shape=[8,4]) - sage: p = L.plot_crystal(C, plot_labels='circles') # optional - sage.plot sage.symbolic - sage: p.show(figsize=15) # optional - sage.plot sage.symbolic + sage: p = L.plot_crystal(C, plot_labels='circles') + sage: p.show(figsize=15) A 3-dimensional example:: sage: L = RootSystem(['B',3]).ambient_space() - sage: C = crystals.Tableaux(['B',3], shape=[2,1]) - sage: L.plot_crystal(C, plot_labels='circles', # long time # optional - sage.plot sage.symbolic + sage: C = crystals.Tableaux(['B',3], shape=[2,1]) # needs sage.combinat + sage: L.plot_crystal(C, plot_labels='circles', # long time # needs sage.combinat sage.plot sage.symbolic ....: edge_labels=True) Graphics3d Object @@ -3177,9 +3202,9 @@ def plot_crystal(self, crystal, Check that :trac:`29548` is fixed:: - sage: LS = crystals.LSPaths(['A',2], [1,1]) + sage: LS = crystals.LSPaths(['A',2], [1,1]) # needs sage.combinat sage: L = RootSystem(['A',2]).ambient_space() - sage: L.plot_crystal(LS) # optional - sage.plot sage.symbolic + sage: L.plot_crystal(LS) # needs sage.combinat sage.plot sage.symbolic Graphics object consisting of 16 graphics primitives """ from sage.plot.arrow import arrow @@ -3327,11 +3352,11 @@ def scalar(self, lambdacheck): sage: L = RootSystem(['A',4]).root_lattice() sage: alpha = L.simple_roots() sage: alphacheck = L.simple_coroots() - sage: alpha[1].scalar(alphacheck[1]) + sage: alpha[1].scalar(alphacheck[1]) # needs sage.graphs 2 - sage: alpha[1].scalar(alphacheck[2]) + sage: alpha[1].scalar(alphacheck[2]) # needs sage.graphs -1 - sage: matrix([ [ alpha[i].scalar(alphacheck[j]) + sage: matrix([ [ alpha[i].scalar(alphacheck[j]) # needs sage.graphs ....: for i in L.index_set() ] ....: for j in L.index_set() ]) [ 2 -1 0 0] @@ -3363,6 +3388,7 @@ def symmetric_form(self, alpha): EXAMPLES:: + sage: # needs sage.graphs sage: Q = RootSystem(['B',2,1]).root_lattice() sage: alpha = Q.simple_roots() sage: alpha[1].symmetric_form(alpha[0]) @@ -3374,15 +3400,16 @@ def symmetric_form(self, alpha): -14 sage: elt.symmetric_form(alpha[0]+2*alpha[2]) 14 + sage: Q = RootSystem(CartanType(['A',4,2]).dual()).root_lattice() sage: Qc = RootSystem(['A',4,2]).coroot_lattice() sage: alpha = Q.simple_roots() sage: alphac = Qc.simple_roots() sage: elt = alpha[0] + 2*alpha[1] + 2*alpha[2] sage: eltc = alphac[0] + 2*alphac[1] + 2*alphac[2] - sage: elt.symmetric_form(alpha[1]) + sage: elt.symmetric_form(alpha[1]) # needs sage.graphs 0 - sage: eltc.symmetric_form(alphac[1]) + sage: eltc.symmetric_form(alphac[1]) # needs sage.graphs 0 """ cm = self.parent().dynkin_diagram().cartan_matrix() @@ -3398,6 +3425,7 @@ def norm_squared(self): EXAMPLES:: + sage: # needs sage.graphs sage: Q = RootSystem(['B',2,1]).root_lattice() sage: alpha = Q.simple_roots() sage: alpha[1].norm_squared() @@ -3410,15 +3438,16 @@ def norm_squared(self): sage: elt = alpha[0] + alpha[1] + 2*alpha[2] sage: elt.norm_squared() 0 + sage: Q = RootSystem(CartanType(['A',4,2]).dual()).root_lattice() sage: Qc = RootSystem(['A',4,2]).coroot_lattice() sage: alpha = Q.simple_roots() sage: alphac = Qc.simple_roots() sage: elt = alpha[0] + 2*alpha[1] + 2*alpha[2] sage: eltc = alphac[0] + 2*alphac[1] + 2*alphac[2] - sage: elt.norm_squared() + sage: elt.norm_squared() # needs sage.graphs 0 - sage: eltc.norm_squared() + sage: eltc.norm_squared() # needs sage.graphs 0 """ return self.symmetric_form(self) @@ -3434,13 +3463,13 @@ def simple_reflection(self, i): EXAMPLES:: sage: alpha = RootSystem(["A", 3]).root_lattice().alpha() - sage: alpha[1].simple_reflection(2) + sage: alpha[1].simple_reflection(2) # needs sage.graphs alpha[1] + alpha[2] sage: Q = RootSystem(['A', 3, 1]).weight_lattice(extended=True) sage: Lambda = Q.fundamental_weights() - sage: L = Lambda[0] + Q.null_root() - sage: L.simple_reflection(0) + sage: L = Lambda[0] + Q.null_root() # needs sage.graphs + sage: L.simple_reflection(0) # needs sage.graphs -Lambda[0] + Lambda[1] + Lambda[3] """ # Subclasses should optimize whenever possible! @@ -3453,7 +3482,7 @@ def simple_reflections(self): EXAMPLES:: sage: alpha = RootSystem(["A", 3]).root_lattice().alpha() - sage: alpha[1].simple_reflections() + sage: alpha[1].simple_reflections() # needs sage.graphs [-alpha[1], alpha[1] + alpha[2], alpha[1]] """ return [s(self) for s in self.parent().simple_reflections()] @@ -3491,11 +3520,11 @@ def orbit(self): (2, 0, 1), (0, 1, 2), (0, 2, 1)] sage: L = RootSystem(["A", 3]).weight_lattice() - sage: len(L.rho().orbit()) + sage: len(L.rho().orbit()) # needs sage.graphs 24 - sage: len(L.fundamental_weights()[1].orbit()) + sage: len(L.fundamental_weights()[1].orbit()) # needs sage.graphs 4 - sage: len(L.fundamental_weights()[2].orbit()) + sage: len(L.fundamental_weights()[2].orbit()) # needs sage.graphs 6 TESTS:: @@ -3544,12 +3573,12 @@ def dot_orbit(self): EXAMPLES:: sage: L = RootSystem(['A', 2]).ambient_lattice() - sage: sorted(L.rho().dot_orbit()) # the output order is not specified + sage: sorted(L.rho().dot_orbit()) # the output order is not specified # needs sage.graphs [(-2, 1, 4), (-2, 3, 2), (2, -1, 2), (2, 1, 0), (0, -1, 4), (0, 3, 0)] sage: L = RootSystem(['B',2]).weight_lattice() - sage: sorted(L.fundamental_weights()[1].dot_orbit()) # the output order is not specified + sage: sorted(L.fundamental_weights()[1].dot_orbit()) # the output order is not specified # needs sage.graphs [-4*Lambda[1], -4*Lambda[1] + 4*Lambda[2], -3*Lambda[1] - 2*Lambda[2], -3*Lambda[1] + 4*Lambda[2], Lambda[1], Lambda[1] - 6*Lambda[2], @@ -3557,6 +3586,7 @@ def dot_orbit(self): We compare the dot action orbit to the regular orbit:: + sage: # needs sage.graphs sage: L = RootSystem(['A', 3]).weight_lattice() sage: len(L.rho().dot_orbit()) 24 @@ -3592,7 +3622,7 @@ def associated_coroot(self): EXAMPLES:: sage: alpha = RootSystem(["A", 3]).root_space().simple_roots() - sage: alpha[1].associated_coroot() + sage: alpha[1].associated_coroot() # needs sage.graphs alphacheck[1] """ @@ -3609,11 +3639,11 @@ def reflection(self, root, use_coroot=False): sage: mu = weight_lattice.from_vector(vector([0,0,1,2])) sage: coroot_lattice = R.coroot_lattice() sage: alphavee = coroot_lattice.from_vector(vector([0,0,1,1])) - sage: mu.reflection(alphavee, use_coroot=True) + sage: mu.reflection(alphavee, use_coroot=True) # needs sage.graphs 6*Lambda[2] - 5*Lambda[3] + 2*Lambda[4] sage: root_lattice = R.root_lattice() sage: beta = root_lattice.from_vector(vector([0,1,1,0])) - sage: mu.reflection(beta) + sage: mu.reflection(beta) # needs sage.graphs Lambda[1] - Lambda[2] + 3*Lambda[4] """ if use_coroot: @@ -3636,6 +3666,7 @@ def has_descent(self, i, positive=False): EXAMPLES:: + sage: # needs sage.graphs sage: space = RootSystem(['A',5]).weight_space() sage: alpha = RootSystem(['A',5]).weight_space().simple_roots() sage: [alpha[i].has_descent(1) for i in space.index_set()] @@ -3668,6 +3699,7 @@ def first_descent(self, index_set=None, positive=False): EXAMPLES:: + sage: # needs sage.graphs sage: space = RootSystem(['A',5]).weight_space() sage: alpha = space.simple_roots() sage: (alpha[1]+alpha[2]+alpha[4]).first_descent() @@ -3690,9 +3722,9 @@ def descents(self, index_set=None, positive=False): EXAMPLES:: - sage: space = RootSystem(['A',5]).weight_space() - sage: alpha = space.simple_roots() - sage: (alpha[1]+alpha[2]+alpha[4]).descents() + sage: space=RootSystem(['A',5]).weight_space() + sage: alpha = space.simple_roots() # needs sage.graphs + sage: (alpha[1]+alpha[2]+alpha[4]).descents() # needs sage.graphs [3, 5] """ if index_set is None: @@ -3728,6 +3760,7 @@ def to_dominant_chamber(self, index_set=None, positive=True, reduced_word=False) EXAMPLES:: + sage: # needs sage.graphs sage: space = RootSystem(['A',5]).weight_space() sage: alpha = RootSystem(['A',5]).weight_space().simple_roots() sage: alpha[1].to_dominant_chamber() @@ -3739,6 +3772,7 @@ def to_dominant_chamber(self, index_set=None, positive=True, reduced_word=False) sage: mu.to_dominant_chamber(positive=False, reduced_word=True) (-Lambda[1] - Lambda[2] - delta, [0, 2]) + sage: # needs sage.graphs sage: R = RootSystem(['A',1,1]) sage: rl = R.root_lattice() sage: nu = rl.zero() @@ -3805,10 +3839,10 @@ def reduced_word(self, index_set=None, positive=True): EXAMPLES:: sage: space = RootSystem(['A',5]).weight_space() - sage: alpha = RootSystem(['A',5]).weight_space().simple_roots() - sage: alpha[1].reduced_word() + sage: alpha = RootSystem(['A',5]).weight_space().simple_roots() # needs sage.graphs + sage: alpha[1].reduced_word() # needs sage.graphs [2, 3, 4, 5] - sage: alpha[1].reduced_word([1,2]) + sage: alpha[1].reduced_word([1,2]) # needs sage.graphs [2] """ @@ -3895,6 +3929,7 @@ def succ(self, index_set=None): EXAMPLES:: + sage: # needs sage.graphs sage: L = RootSystem(['A',3]).weight_lattice() sage: Lambda = L.fundamental_weights() sage: Lambda[1].succ() @@ -3932,11 +3967,11 @@ def pred(self, index_set=None): [] sage: L.rho().pred() [] - sage: (-L.rho()).pred() + sage: (-L.rho()).pred() # needs sage.graphs [Lambda[1] - 2*Lambda[2] - Lambda[3], -2*Lambda[1] + Lambda[2] - 2*Lambda[3], -Lambda[1] - 2*Lambda[2] + Lambda[3]] - sage: (-L.rho()).pred(index_set=[1]) + sage: (-L.rho()).pred(index_set=[1]) # needs sage.graphs [Lambda[1] - 2*Lambda[2] - Lambda[3]] """ return [ self.simple_reflection(i) for i in self.descents(index_set) ] @@ -3997,7 +4032,7 @@ def extraspecial_pair(self): EXAMPLES:: sage: Q = RootSystem(['G', 2]).root_lattice() - sage: Q.highest_root().extraspecial_pair() + sage: Q.highest_root().extraspecial_pair() # needs sage.graphs (alpha[2], 3*alpha[1] + alpha[2]) """ if self.is_positive_root(): @@ -4023,7 +4058,7 @@ def height(self): EXAMPLES:: sage: Q = RootSystem(['G', 2]).root_lattice() - sage: Q.highest_root().height() + sage: Q.highest_root().height() # needs sage.graphs 5 """ return sum(self.coefficients()) @@ -4037,7 +4072,7 @@ def level(self): EXAMPLES:: sage: L = RootSystem(['A',2,1]).weight_lattice() - sage: L.rho().level() + sage: L.rho().level() # needs sage.graphs 3 """ if not self.parent().cartan_type().is_affine(): @@ -4065,7 +4100,7 @@ def to_simple_root(self, reduced_word=False): sage: L = RootSystem(["A",3]).root_lattice() sage: positive_roots = L.positive_roots() - sage: for alpha in sorted(positive_roots): + sage: for alpha in sorted(positive_roots): # needs sage.graphs ....: print("{} {}".format(alpha, alpha.to_simple_root())) alpha[1] 1 alpha[1] + alpha[2] 2 @@ -4073,7 +4108,7 @@ def to_simple_root(self, reduced_word=False): alpha[2] 2 alpha[2] + alpha[3] 3 alpha[3] 3 - sage: for alpha in sorted(positive_roots): + sage: for alpha in sorted(positive_roots): # needs sage.graphs ....: print("{} {}".format(alpha, alpha.to_simple_root(reduced_word=True))) alpha[1] (1, ()) alpha[1] + alpha[2] (2, (1,)) @@ -4101,8 +4136,8 @@ def to_simple_root(self, reduced_word=False): positive root. For a finite root system, this is currently caught (albeit with a not perfect message):: - sage: alpha = L.simple_roots() - sage: (2*alpha[1]).to_simple_root() + sage: alpha = L.simple_roots() # needs sage.graphs + sage: (2*alpha[1]).to_simple_root() # needs sage.graphs Traceback (most recent call last): ... ValueError: -2*alpha[1] - 2*alpha[2] - 2*alpha[3] is not a positive root @@ -4138,10 +4173,10 @@ def associated_reflection(self): EXAMPLES:: - sage: C3_rl = RootSystem(['C',3]).root_lattice() - sage: C3_rl.simple_root(3).weyl_action([1,2]).associated_reflection() + sage: C3_rl = RootSystem(['C',3]).root_lattice() # needs sage.graphs + sage: C3_rl.simple_root(3).weyl_action([1,2]).associated_reflection() # needs sage.graphs (1, 2, 3, 2, 1) - sage: C3_rl.simple_root(2).associated_reflection() + sage: C3_rl.simple_root(2).associated_reflection() # needs sage.graphs (2,) """ @@ -4160,33 +4195,33 @@ def translation(self, x): EXAMPLES:: sage: L = RootSystem(['A',2,1]).weight_lattice() - sage: alpha = L.simple_roots() - sage: Lambda = L.fundamental_weights() - sage: t = alpha[2] + sage: alpha = L.simple_roots() # needs sage.graphs + sage: Lambda = L.fundamental_weights() # needs sage.graphs + sage: t = alpha[2] # needs sage.graphs Let us look at the translation of an element of level `1`:: - sage: Lambda[1].level() + sage: Lambda[1].level() # needs sage.graphs 1 - sage: t.translation(Lambda[1]) + sage: t.translation(Lambda[1]) # needs sage.graphs -Lambda[0] + 2*Lambda[2] - sage: Lambda[1] + t + sage: Lambda[1] + t # needs sage.graphs -Lambda[0] + 2*Lambda[2] and of an element of level `0`:: - sage: alpha [1].level() + sage: alpha[1].level() # needs sage.graphs 0 - sage: t.translation(alpha [1]) + sage: t.translation(alpha [1]) # needs sage.graphs -Lambda[0] + 2*Lambda[1] - Lambda[2] - sage: alpha[1] + 0*t + sage: alpha[1] + 0*t # needs sage.graphs -Lambda[0] + 2*Lambda[1] - Lambda[2] The arguments are given in this seemingly unnatural order to make it easy to construct the translation function:: - sage: f = t.translation - sage: f(Lambda[1]) + sage: f = t.translation # needs sage.graphs + sage: f(Lambda[1]) # needs sage.graphs -Lambda[0] + 2*Lambda[2] """ if not self.level().is_zero(): @@ -4212,32 +4247,34 @@ def weyl_action(self, element, inverse=False): sage: mu = wl.from_vector(vector([1,0,-2])) sage: mu Lambda[1] - 2*Lambda[3] - sage: mudom, rw = mu.to_dominant_chamber(positive=False, reduced_word=True) - sage: mudom, rw + sage: mudom, rw = mu.to_dominant_chamber(positive=False, # needs sage.graphs + ....: reduced_word=True) + sage: mudom, rw # needs sage.graphs (-Lambda[2] - Lambda[3], [1, 2]) Acting by a (reduced) word:: - sage: mudom.weyl_action(rw) + sage: mudom.weyl_action(rw) # needs sage.graphs Lambda[1] - 2*Lambda[3] - sage: mu.weyl_action(rw, inverse = True) + sage: mu.weyl_action(rw, inverse=True) # needs sage.graphs -Lambda[2] - Lambda[3] Acting by an element of the Coxeter or Weyl group on a vector in its own lattice of definition (implemented by matrix multiplication on a vector):: - sage: w = wl.weyl_group().from_reduced_word([1, 2]) - sage: mudom.weyl_action(w) + sage: w = wl.weyl_group().from_reduced_word([1, 2]) # needs sage.graphs + sage: mudom.weyl_action(w) # needs sage.graphs Lambda[1] - 2*Lambda[3] Acting by an element of an isomorphic Coxeter or Weyl group (implemented by the action of a corresponding reduced word):: + sage: # needs sage.libs.gap sage: W = WeylGroup(['A',3], prefix="s") sage: w = W.from_reduced_word([1, 2]) sage: wl.weyl_group() == W False - sage: mudom.weyl_action(w) + sage: mudom.weyl_action(w) # needs sage.graphs Lambda[1] - 2*Lambda[3] """ # TODO, some day: accept an iterator @@ -4278,8 +4315,8 @@ def weyl_stabilizer(self, index_set=None): EXAMPLES:: sage: wl = RootSystem(['A',2,1]).weight_lattice(extended=True) - sage: al = wl.null_root() - sage: al.weyl_stabilizer() + sage: al = wl.null_root() # needs sage.graphs + sage: al.weyl_stabilizer() # needs sage.graphs [0, 1, 2] sage: wl = RootSystem(['A',4]).weight_lattice() sage: mu = wl.from_vector(vector([1,1,0,0])) @@ -4321,16 +4358,16 @@ def dot_action(self, w, inverse=False): sage: P = RootSystem(['B',3]).weight_lattice() sage: La = P.fundamental_weights() sage: mu = La[1] + 2*La[2] - 3*La[3] - sage: mu.dot_action([1]) + sage: mu.dot_action([1]) # needs sage.graphs -3*Lambda[1] + 4*Lambda[2] - 3*Lambda[3] - sage: mu.dot_action([3]) + sage: mu.dot_action([3]) # needs sage.graphs Lambda[1] + Lambda[3] - sage: mu.dot_action([1,2,3]) + sage: mu.dot_action([1,2,3]) # needs sage.graphs -4*Lambda[1] + Lambda[2] + 3*Lambda[3] We check that the origin of this action is at `-\rho`:: - sage: all((-P.rho()).dot_action([i]) == -P.rho() + sage: all((-P.rho()).dot_action([i]) == -P.rho() # needs sage.graphs ....: for i in P.index_set()) True @@ -4379,6 +4416,7 @@ def is_short_root(self): EXAMPLES:: + sage: # needs sage.graphs sage: Q = RootSystem(['C',2]).root_lattice() sage: al = Q.simple_root(1).weyl_action([1,2]); al alpha[1] + alpha[2] @@ -4393,6 +4431,7 @@ def is_short_root(self): An example in affine type:: + sage: # needs sage.graphs sage: Q = RootSystem(['B',2,1]).root_lattice() sage: alpha = Q.simple_roots() sage: alpha[0].is_short_root() @@ -4456,13 +4495,13 @@ def to_classical(self): sage: R = CartanType(['A',3,1]).root_system() sage: alpha = R.root_lattice().an_element(); alpha 2*alpha[0] + 2*alpha[1] + 3*alpha[2] - sage: alb = alpha.to_classical(); alb + sage: alb = alpha.to_classical(); alb # needs sage.graphs alpha[2] - 2*alpha[3] - sage: alb.parent() + sage: alb.parent() # needs sage.graphs Root lattice of the Root system of type ['A', 3] sage: v = R.ambient_space().an_element(); v 2*e[0] + 2*e[1] + 3*e[2] - sage: v.to_classical() + sage: v.to_classical() # needs sage.graphs (2, 2, 3, 0) """ @@ -4503,11 +4542,11 @@ def is_long_root(self): sage: Q = RootSystem(['B',2,1]).root_lattice() sage: alpha = Q.simple_roots() - sage: alpha[0].is_long_root() + sage: alpha[0].is_long_root() # needs sage.graphs True - sage: alpha[1].is_long_root() + sage: alpha[1].is_long_root() # needs sage.graphs True - sage: alpha[2].is_long_root() + sage: alpha[2].is_long_root() # needs sage.graphs False """ alpha = self.parent().simple_roots() @@ -4526,10 +4565,10 @@ def is_imaginary_root(self): sage: Q = RootSystem(['B',2,1]).root_lattice() sage: alpha = Q.simple_roots() - sage: alpha[0].is_imaginary_root() + sage: alpha[0].is_imaginary_root() # needs sage.graphs False sage: elt = alpha[0] + alpha[1] + 2*alpha[2] - sage: elt.is_imaginary_root() + sage: elt.is_imaginary_root() # needs sage.graphs True """ return self.norm_squared() <= 0 @@ -4545,10 +4584,10 @@ def is_real_root(self): sage: Q = RootSystem(['B',2,1]).root_lattice() sage: alpha = Q.simple_roots() - sage: alpha[0].is_real_root() + sage: alpha[0].is_real_root() # needs sage.graphs True sage: elt = alpha[0] + alpha[1] + 2*alpha[2] - sage: elt.is_real_root() + sage: elt.is_real_root() # needs sage.graphs False """ return self.norm_squared() > 0 diff --git a/src/sage/combinat/root_system/root_space.py b/src/sage/combinat/root_system/root_space.py index 790b45f9606..695a80b7e53 100644 --- a/src/sage/combinat/root_system/root_space.py +++ b/src/sage/combinat/root_system/root_space.py @@ -115,26 +115,26 @@ def to_coroot_space_morphism(self): sage: R = RootSystem(['A',3]).root_space() sage: alpha = R.simple_roots() - sage: f = R.to_coroot_space_morphism() - sage: f(alpha[1]) + sage: f = R.to_coroot_space_morphism() # needs sage.graphs + sage: f(alpha[1]) # needs sage.graphs alphacheck[1] - sage: f(alpha[1]+alpha[2]) + sage: f(alpha[1] + alpha[2]) # needs sage.graphs alphacheck[1] + alphacheck[2] sage: R = RootSystem(['A',3]).root_lattice() sage: alpha = R.simple_roots() - sage: f = R.to_coroot_space_morphism() - sage: f(alpha[1]) + sage: f = R.to_coroot_space_morphism() # needs sage.graphs + sage: f(alpha[1]) # needs sage.graphs alphacheck[1] - sage: f(alpha[1]+alpha[2]) + sage: f(alpha[1] + alpha[2]) # needs sage.graphs alphacheck[1] + alphacheck[2] sage: S = RootSystem(['G',2]).root_space() sage: alpha = S.simple_roots() - sage: f = S.to_coroot_space_morphism() - sage: f(alpha[1]) + sage: f = S.to_coroot_space_morphism() # needs sage.graphs + sage: f(alpha[1]) # needs sage.graphs alphacheck[1] - sage: f(alpha[1]+alpha[2]) + sage: f(alpha[1] + alpha[2]) # needs sage.graphs alphacheck[1] + 3*alphacheck[2] """ R = self.base_ring() @@ -194,7 +194,7 @@ def _to_classical_on_basis(self, i): EXAMPLES:: sage: L = RootSystem(["A",3,1]).root_space() - sage: L._to_classical_on_basis(0) + sage: L._to_classical_on_basis(0) # needs sage.graphs -alpha[1] - alpha[2] - alpha[3] sage: L._to_classical_on_basis(1) alpha[1] @@ -242,15 +242,15 @@ def scalar(self, lambdacheck): sage: L = RootSystem(['B',4]).root_lattice() sage: alpha = L.simple_roots() sage: alphacheck = L.simple_coroots() - sage: alpha[1].scalar(alphacheck[1]) + sage: alpha[1].scalar(alphacheck[1]) # needs sage.graphs 2 - sage: alpha[1].scalar(alphacheck[2]) + sage: alpha[1].scalar(alphacheck[2]) # needs sage.graphs -1 The scalar products between the roots and coroots are given by the Cartan matrix:: - sage: matrix([ [ alpha[i].scalar(alphacheck[j]) + sage: matrix([ [ alpha[i].scalar(alphacheck[j]) # needs sage.graphs ....: for i in L.index_set() ] ....: for j in L.index_set() ]) [ 2 -1 0 0] @@ -258,7 +258,7 @@ def scalar(self, lambdacheck): [ 0 -1 2 -1] [ 0 0 -2 2] - sage: L.cartan_type().cartan_matrix() + sage: L.cartan_type().cartan_matrix() # needs sage.graphs [ 2 -1 0 0] [-1 2 -1 0] [ 0 -1 2 -1] @@ -278,12 +278,12 @@ def is_positive_root(self): EXAMPLES:: - sage: R=RootSystem(['A',3,1]).root_space() - sage: B=R.basis() - sage: w=B[0]+B[3] + sage: R = RootSystem(['A',3,1]).root_space() + sage: B = R.basis() + sage: w = B[0] + B[3] sage: w.is_positive_root() True - sage: w=B[1]-B[2] + sage: w = B[1] - B[2] sage: w.is_positive_root() False """ @@ -304,20 +304,20 @@ def associated_coroot(self): sage: L = RootSystem(["B", 3]).root_space() sage: alpha = L.simple_roots() - sage: alpha[1].associated_coroot() + sage: alpha[1].associated_coroot() # needs sage.graphs alphacheck[1] - sage: alpha[1].associated_coroot().parent() + sage: alpha[1].associated_coroot().parent() # needs sage.graphs Coroot space over the Rational Field of the Root system of type ['B', 3] - sage: L.highest_root() + sage: L.highest_root() # needs sage.graphs alpha[1] + 2*alpha[2] + 2*alpha[3] - sage: L.highest_root().associated_coroot() + sage: L.highest_root().associated_coroot() # needs sage.graphs alphacheck[1] + 2*alphacheck[2] + alphacheck[3] sage: alpha = RootSystem(["B", 3]).root_lattice().simple_roots() - sage: alpha[1].associated_coroot() + sage: alpha[1].associated_coroot() # needs sage.graphs alphacheck[1] - sage: alpha[1].associated_coroot().parent() + sage: alpha[1].associated_coroot().parent() # needs sage.graphs Coroot lattice of the Root system of type ['B', 3] """ @@ -328,13 +328,15 @@ def associated_coroot(self): def quantum_root(self): r""" - Returns True if ``self`` is a quantum root and False otherwise. + Check whether ``self`` is a quantum root. INPUT: - ``self`` -- an element of the nonnegative integer span of simple roots. - A root `\alpha` is a quantum root if `\ell(s_\alpha) = \langle 2 \rho, \alpha^\vee \rangle - 1` where `\ell` is the length function, `s_\alpha` is the reflection across the hyperplane orthogonal to `\alpha`, and `2\rho` is the sum of positive roots. + A root `\alpha` is a quantum root if `\ell(s_\alpha) = \langle 2 \rho, \alpha^\vee \rangle - 1` + where `\ell` is the length function, `s_\alpha` is the reflection across the hyperplane + orthogonal to `\alpha`, and `2\rho` is the sum of positive roots. .. warning:: @@ -346,7 +348,7 @@ def quantum_root(self): sage: Q = RootSystem(['C',2]).root_lattice() sage: positive_roots = Q.positive_roots() - sage: for x in sorted(positive_roots): + sage: for x in sorted(positive_roots): # needs sage.graphs ....: print("{} {}".format(x, x.quantum_root())) alpha[1] True alpha[1] + alpha[2] False @@ -357,7 +359,7 @@ def quantum_root(self): def max_coroot_le(self): r""" - Returns the highest positive coroot whose associated root is less than or equal to ``self``. + Return the highest positive coroot whose associated root is less than or equal to ``self``. INPUT: @@ -374,6 +376,7 @@ def max_coroot_le(self): EXAMPLES:: + sage: # needs sage.graphs sage: root_lattice = RootSystem(['C',2]).root_lattice() sage: root_lattice.from_vector(vector([1,1])).max_coroot_le() alphacheck[1] + 2*alphacheck[2] @@ -385,14 +388,14 @@ def max_coroot_le(self): sage: root_lattice.from_vector(vector([1,2])).max_coroot_le() 2*alphacheck[1] + alphacheck[2] - sage: root_lattice.zero().max_coroot_le() is None + sage: root_lattice.zero().max_coroot_le() is None # needs sage.graphs True - sage: root_lattice.from_vector(vector([-1,0])).max_coroot_le() + sage: root_lattice.from_vector(vector([-1,0])).max_coroot_le() # needs sage.graphs Traceback (most recent call last): ... ValueError: -alpha[1] is not in the positive cone of roots sage: root_lattice = RootSystem(['A',2,1]).root_lattice() - sage: root_lattice.simple_root(1).max_coroot_le() + sage: root_lattice.simple_root(1).max_coroot_le() # needs sage.graphs Traceback (most recent call last): ... NotImplementedError: Only implemented for finite Cartan type @@ -411,7 +414,9 @@ def max_coroot_le(self): def max_quantum_element(self): r""" - Returns a reduced word for the longest element of the Weyl group whose shortest path in the quantum Bruhat graph to the identity, has sum of quantum coroots at most ``self``. + Return a reduced word for the longest element of the Weyl group + whose shortest path in the quantum Bruhat graph to the identity + has sum of quantum coroots at most ``self``. INPUT: @@ -426,11 +431,11 @@ def max_quantum_element(self): EXAMPLES:: sage: Qvee = RootSystem(['C',2]).coroot_lattice() - sage: Qvee.from_vector(vector([1,2])).max_quantum_element() + sage: Qvee.from_vector(vector([1,2])).max_quantum_element() # needs sage.graphs [2, 1, 2, 1] - sage: Qvee.from_vector(vector([1,1])).max_quantum_element() + sage: Qvee.from_vector(vector([1,1])).max_quantum_element() # needs sage.graphs [1, 2, 1] - sage: Qvee.from_vector(vector([0,2])).max_quantum_element() + sage: Qvee.from_vector(vector([0,2])).max_quantum_element() # needs sage.graphs [2] """ diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py index 7885023d33b..a26b9afa75c 100644 --- a/src/sage/combinat/root_system/root_system.py +++ b/src/sage/combinat/root_system/root_system.py @@ -33,15 +33,14 @@ class RootSystem(UniqueRepresentation, SageObject): We construct the root system for type `B_3`:: - sage: R=RootSystem(['B',3]); R + sage: R = RootSystem(['B',3]); R Root system of type ['B', 3] ``R`` models the root system abstractly. It comes equipped with various realizations of the root and weight lattices, where all computations take place. Let us play first with the root lattice:: - sage: space = R.root_lattice() - sage: space + sage: space = R.root_lattice(); space Root lattice of the Root system of type ['B', 3] This is the free `\ZZ`-module `\bigoplus_i \ZZ.\alpha_i` spanned @@ -77,8 +76,7 @@ class RootSystem(UniqueRepresentation, SageObject): `\bigoplus_i \ZZ.\Lambda_i`, the weight space `\bigoplus_i \QQ.\Lambda_i`. For example:: - sage: space = R.weight_space() - sage: space + sage: space = R.weight_space(); space Weight space over the Rational Field of the Root system of type ['B', 3] :: @@ -90,8 +88,8 @@ class RootSystem(UniqueRepresentation, SageObject): :: - sage: alpha = space.simple_roots() - sage: alpha[1] + alpha[2] + sage: alpha = space.simple_roots() # needs sage.graphs + sage: alpha[1] + alpha[2] # needs sage.graphs Lambda[1] + Lambda[2] - 2*Lambda[3] The fundamental weights are the dual basis of the coroots:: @@ -102,8 +100,8 @@ class RootSystem(UniqueRepresentation, SageObject): :: - sage: alphacheck = space.simple_coroots() - sage: list(alphacheck) + sage: alphacheck = space.simple_coroots() # needs sage.graphs + sage: list(alphacheck) # needs sage.graphs [alphacheck[1], alphacheck[2], alphacheck[3]] :: @@ -121,7 +119,7 @@ class RootSystem(UniqueRepresentation, SageObject): `\alpha_i`, where `c` is the coefficient of `i` in `x`:: - sage: s = space.simple_reflections() + sage: # needs sage.graphs sage: Lambda[1].simple_reflection(1) -Lambda[1] + Lambda[2] sage: Lambda[2].simple_reflection(1) @@ -134,6 +132,7 @@ class RootSystem(UniqueRepresentation, SageObject): It can be convenient to manipulate the simple reflections themselves:: + sage: # needs sage.graphs sage: s = space.simple_reflections() sage: s[1](Lambda[1]) -Lambda[1] + Lambda[2] @@ -159,7 +158,7 @@ class RootSystem(UniqueRepresentation, SageObject): In finite type `A`, we recover the natural representation of the symmetric group as group of permutation matrices:: - sage: RootSystem(["A",2]).ambient_space().weyl_group().simple_reflections() + sage: RootSystem(["A",2]).ambient_space().weyl_group().simple_reflections() # needs sage.libs.pari Finite family {1: [0 1 0] [1 0 0] [0 0 1], @@ -170,7 +169,7 @@ class RootSystem(UniqueRepresentation, SageObject): In type `B`, `C`, and `D`, we recover the natural representation of the Weyl group as groups of signed permutation matrices:: - sage: RootSystem(["B",3]).ambient_space().weyl_group().simple_reflections() + sage: RootSystem(["B",3]).ambient_space().weyl_group().simple_reflections() # needs sage.libs.pari Finite family {1: [0 1 0] [1 0 0] [0 0 1], @@ -190,35 +189,35 @@ class RootSystem(UniqueRepresentation, SageObject): Define the "identity" by an appropriate vector at level `-3`:: - sage: e = L.basis(); Lambda = L.fundamental_weights() - sage: id = e[0] + 2*e[1] + 3*e[2] - 3*Lambda[0] + sage: e = L.basis(); Lambda = L.fundamental_weights() # needs sage.graphs + sage: id = e[0] + 2*e[1] + 3*e[2] - 3*Lambda[0] # needs sage.graphs The corresponding permutation is obtained by projecting it onto the classical ambient space:: sage: L.classical() Ambient space of the Root system of type ['A', 2] - sage: L.classical()(id) + sage: L.classical()(id) # needs sage.graphs (1, 2, 3) Here is the orbit of the identity under the action of the finite group:: - sage: W = L.weyl_group() - sage: S3 = [ w.action(id) for w in W.classical() ] - sage: [L.classical()(x) for x in S3] + sage: W = L.weyl_group() # needs sage.libs.pari + sage: S3 = [ w.action(id) for w in W.classical() ] # needs sage.graphs sage.libs.pari + sage: [L.classical()(x) for x in S3] # needs sage.graphs sage.libs.pari [(1, 2, 3), (3, 1, 2), (2, 3, 1), (2, 1, 3), (1, 3, 2), (3, 2, 1)] And the action of `s_0` on these yields:: - sage: s = W.simple_reflections() - sage: [L.classical()(s[0].action(x)) for x in S3] + sage: s = W.simple_reflections() # needs sage.libs.pari + sage: [L.classical()(s[0].action(x)) for x in S3] # needs sage.graphs sage.libs.pari [(0, 2, 4), (-1, 1, 6), (-2, 3, 5), (0, 1, 5), (-1, 3, 4), (-2, 2, 6)] We can also plot various components of the ambient spaces:: sage: L = RootSystem(['A',2]).ambient_space() - sage: L.plot() # optional - sage.plot sage.symbolic + sage: L.plot() # needs sage.plot sage.symbolic Graphics object consisting of 13 graphics primitives For more on plotting, see :ref:`sage.combinat.root_system.plot`. @@ -266,11 +265,11 @@ class RootSystem(UniqueRepresentation, SageObject): TESTS:: sage: R = RootSystem(['C',3]) - sage: TestSuite(R).run() + sage: TestSuite(R).run() # needs sage.graphs sage: L = R.ambient_space() sage: s = L.simple_reflections() # this used to break the testsuite below due to caching an unpicklable method sage: s = L.simple_projections() # todo: not implemented - sage: TestSuite(L).run() + sage: TestSuite(L).run() # needs sage.graphs sage: L = R.root_space() sage: s = L.simple_reflections() sage: TestSuite(L).run() @@ -345,7 +344,7 @@ def _test_root_lattice_realizations(self, **options): EXAMPLES:: - sage: RootSystem(["A",3])._test_root_lattice_realizations() + sage: RootSystem(["A",3])._test_root_lattice_realizations() # needs sage.graphs .. SEEALSO:: :class:`TestSuite`. """ @@ -379,7 +378,7 @@ def _repr_(self): def cartan_type(self): """ - Returns the Cartan type of the root system. + Return the Cartan type of the root system. EXAMPLES:: @@ -392,12 +391,12 @@ def cartan_type(self): @cached_method def dynkin_diagram(self): """ - Returns the Dynkin diagram of the root system. + Return the Dynkin diagram of the root system. EXAMPLES:: sage: R = RootSystem(['A',3]) - sage: R.dynkin_diagram() + sage: R.dynkin_diagram() # needs sage.graphs O---O---O 1 2 3 A3 @@ -409,7 +408,7 @@ def cartan_matrix(self): """ EXAMPLES:: - sage: RootSystem(['A',3]).cartan_matrix() + sage: RootSystem(['A',3]).cartan_matrix() # needs sage.graphs [ 2 -1 0] [-1 2 -1] [ 0 -1 2] @@ -429,7 +428,7 @@ def index_set(self): @cached_method def is_finite(self): """ - Returns True if self is a finite root system. + Return ``True`` if ``self`` is a finite root system. EXAMPLES:: @@ -443,7 +442,7 @@ def is_finite(self): @cached_method def is_irreducible(self): """ - Returns True if self is an irreducible root system. + Return ``True`` if ``self`` is an irreducible root system. EXAMPLES:: @@ -456,7 +455,7 @@ def is_irreducible(self): def root_lattice(self): """ - Returns the root lattice associated to self. + Return the root lattice associated to ``self``. EXAMPLES:: @@ -468,7 +467,7 @@ def root_lattice(self): @cached_method def root_space(self, base_ring=QQ): """ - Returns the root space associated to self. + Return the root space associated to ``self``. EXAMPLES:: @@ -479,7 +478,7 @@ def root_space(self, base_ring=QQ): def root_poset(self, restricted=False, facade=False): r""" - Returns the (restricted) root poset associated to ``self``. + Return the (restricted) root poset associated to ``self``. The elements are given by the positive roots (resp. non-simple, positive roots), and `\alpha \leq \beta` iff `\beta - \alpha` is a non-negative linear combination of simple roots. @@ -491,26 +490,28 @@ def root_poset(self, restricted=False, facade=False): EXAMPLES:: - sage: Phi = RootSystem(['A',2]).root_poset(); Phi + sage: Phi = RootSystem(['A',2]).root_poset(); Phi # needs sage.graphs Finite poset containing 3 elements - sage: sorted(Phi.cover_relations(), key=str) + sage: sorted(Phi.cover_relations(), key=str) # needs sage.graphs [[alpha[1], alpha[1] + alpha[2]], [alpha[2], alpha[1] + alpha[2]]] - sage: Phi = RootSystem(['A',3]).root_poset(restricted=True); Phi + sage: Phi = RootSystem(['A',3]).root_poset(restricted=True); Phi # needs sage.graphs Finite poset containing 3 elements - sage: sorted(Phi.cover_relations(), key=str) - [[alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]], [alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]] + sage: sorted(Phi.cover_relations(), key=str) # needs sage.graphs + [[alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]], + [alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]] - sage: Phi = RootSystem(['B',2]).root_poset(); Phi + sage: Phi = RootSystem(['B',2]).root_poset(); Phi # needs sage.graphs Finite poset containing 4 elements - sage: Phi.cover_relations() - [[alpha[2], alpha[1] + alpha[2]], [alpha[1], alpha[1] + alpha[2]], [alpha[1] + alpha[2], alpha[1] + 2*alpha[2]]] + sage: Phi.cover_relations() # needs sage.graphs + [[alpha[2], alpha[1] + alpha[2]], [alpha[1], alpha[1] + alpha[2]], + [alpha[1] + alpha[2], alpha[1] + 2*alpha[2]]] """ return self.root_lattice().root_poset(restricted=restricted, facade=facade) def coroot_lattice(self): """ - Returns the coroot lattice associated to self. + Return the coroot lattice associated to ``self``. EXAMPLES:: @@ -521,7 +522,7 @@ def coroot_lattice(self): def coroot_space(self, base_ring=QQ): """ - Returns the coroot space associated to self. + Return the coroot space associated to ``self``. EXAMPLES:: @@ -533,7 +534,7 @@ def coroot_space(self, base_ring=QQ): @cached_method def weight_lattice(self, extended=False): """ - Returns the weight lattice associated to self. + Return the weight lattice associated to ``self``. .. SEEALSO:: @@ -546,15 +547,16 @@ def weight_lattice(self, extended=False): sage: RootSystem(['A',3]).weight_lattice() Weight lattice of the Root system of type ['A', 3] - sage: RootSystem(['A',3,1]).weight_space(extended = True) - Extended weight space over the Rational Field of the Root system of type ['A', 3, 1] + sage: RootSystem(['A',3,1]).weight_space(extended=True) + Extended weight space over the Rational Field + of the Root system of type ['A', 3, 1] """ return WeightSpace(self, ZZ, extended=extended) @cached_method def weight_space(self, base_ring=QQ, extended=False): """ - Returns the weight space associated to self. + Returns the weight space associated to ``self``. .. SEEALSO:: @@ -567,14 +569,15 @@ def weight_space(self, base_ring=QQ, extended=False): sage: RootSystem(['A',3]).weight_space() Weight space over the Rational Field of the Root system of type ['A', 3] - sage: RootSystem(['A',3,1]).weight_space(extended = True) - Extended weight space over the Rational Field of the Root system of type ['A', 3, 1] + sage: RootSystem(['A',3,1]).weight_space(extended=True) + Extended weight space over the Rational Field + of the Root system of type ['A', 3, 1] """ return WeightSpace(self, base_ring, extended=extended) def coweight_lattice(self, extended=False): """ - Returns the coweight lattice associated to self. + Return the coweight lattice associated to ``self``. This is the weight lattice of the dual root system. @@ -589,14 +592,14 @@ def coweight_lattice(self, extended=False): sage: RootSystem(['A',3]).coweight_lattice() Coweight lattice of the Root system of type ['A', 3] - sage: RootSystem(['A',3,1]).coweight_lattice(extended = True) + sage: RootSystem(['A',3,1]).coweight_lattice(extended=True) Extended coweight lattice of the Root system of type ['A', 3, 1] """ return self.dual.weight_lattice(extended=extended) def coweight_space(self, base_ring=QQ, extended=False): """ - Returns the coweight space associated to self. + Return the coweight space associated to ``self``. This is the weight space of the dual root system. @@ -612,7 +615,8 @@ def coweight_space(self, base_ring=QQ, extended=False): Coweight space over the Rational Field of the Root system of type ['A', 3] sage: RootSystem(['A',3,1]).coweight_space(extended=True) - Extended coweight space over the Rational Field of the Root system of type ['A', 3, 1] + Extended coweight space over the Rational Field + of the Root system of type ['A', 3, 1] """ return self.dual.weight_space(base_ring, extended=extended) @@ -720,7 +724,7 @@ def ambient_space(self, base_ring=QQ): An alternative base ring can be provided as an option:: sage: e = RootSystem(['B',3]).ambient_space(RR) - sage: TestSuite(e).run() + sage: TestSuite(e).run() # needs sage.graphs It should contain the smallest ring over which the ambient space can be defined (`\ZZ` in type `A` or `\QQ` otherwise). @@ -733,7 +737,7 @@ def ambient_space(self, base_ring=QQ): you are welcome to experiment:: sage: e = RootSystem(['G',2]).ambient_space(RR) - sage: TestSuite(e).run() + sage: TestSuite(e).run() # needs sage.graphs Failure in _test_root_lattice_realization: Traceback (most recent call last): ... @@ -787,9 +791,9 @@ def WeylDim(ct, coeffs): INPUT: - - ``type`` - a Cartan type + - ``ct`` -- a Cartan type - - ``coeffs`` - a list of nonnegative integers + - ``coeffs`` -- a list of nonnegative integers The length of the list must equal the rank type[1]. A dominant @@ -802,17 +806,20 @@ def WeylDim(ct, coeffs): For `SO(7)`, the Cartan type is `B_3`, so:: - sage: WeylDim(['B',3],[1,0,0]) # standard representation of SO(7) + sage: WeylDim(['B',3],[1,0,0]) # standard representation of SO(7) 7 - sage: WeylDim(['B',3],[0,1,0]) # exterior square + sage: WeylDim(['B',3],[0,1,0]) # exterior square 21 - sage: WeylDim(['B',3],[0,0,1]) # spin representation of spin(7) + sage: WeylDim(['B',3],[0,0,1]) # spin representation of spin(7) 8 - sage: WeylDim(['B',3],[1,0,1]) # sum of the first and third fundamental weights + sage: WeylDim(['B',3],[1,0,1]) # sum of the first and third fundamental weights 48 sage: [WeylDim(['F',4],x) for x in ([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])] [52, 1274, 273, 26] - sage: [WeylDim(['E', 6], x) for x in ([0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0], [1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1], [2, 0, 0, 0, 0, 0])] + sage: [WeylDim(['E', 6], x) + ....: for x in ([0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1], + ....: [0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0], + ....: [1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1], [2, 0, 0, 0, 0, 0])] [1, 78, 27, 351, 351, 351, 27, 650, 351] """ ct = CartanType(ct) diff --git a/src/sage/combinat/root_system/type_A.py b/src/sage/combinat/root_system/type_A.py index f3cb037d644..96bcec25f39 100644 --- a/src/sage/combinat/root_system/type_A.py +++ b/src/sage/combinat/root_system/type_A.py @@ -22,22 +22,23 @@ class AmbientSpace(ambient_space.AmbientSpace): sage: R = RootSystem(["A",3]) sage: e = R.ambient_space(); e Ambient space of the Root system of type ['A', 3] - sage: TestSuite(e).run() + sage: TestSuite(e).run() # needs sage.graphs By default, this ambient space uses the barycentric projection for plotting:: + sage: # needs sage.symbolic sage: L = RootSystem(["A",2]).ambient_space() sage: e = L.basis() - sage: L._plot_projection(e[0]) # optional - sage.symbolic + sage: L._plot_projection(e[0]) (1/2, 989/1142) - sage: L._plot_projection(e[1]) # optional - sage.symbolic + sage: L._plot_projection(e[1]) (-1, 0) - sage: L._plot_projection(e[2]) # optional - sage.symbolic + sage: L._plot_projection(e[2]) (1/2, -989/1142) sage: L = RootSystem(["A",3]).ambient_space() sage: l = L.an_element(); l (2, 2, 3, 0) - sage: L._plot_projection(l) # optional - sage.symbolic + sage: L._plot_projection(l) (0, -1121/1189, 7/3) .. SEEALSO:: @@ -253,22 +254,20 @@ def dynkin_diagram(self): EXAMPLES:: - sage: a = CartanType(['A',3]).dynkin_diagram() - sage: a + sage: a = CartanType(['A',3]).dynkin_diagram(); a # needs sage.graphs O---O---O 1 2 3 A3 - sage: a.edges(sort=True) + sage: a.edges(sort=True) # needs sage.graphs [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 1)] TESTS:: - sage: a = DynkinDiagram(['A',1]) - sage: a + sage: a = DynkinDiagram(['A',1]); a # needs sage.graphs O 1 A1 - sage: a.vertices(sort=False), a.edges(sort=False) + sage: a.vertices(sort=False), a.edges(sort=False) # needs sage.graphs ([1], []) """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_A_affine.py b/src/sage/combinat/root_system/type_A_affine.py index c287ae98f7e..7a7bb1cd9a0 100644 --- a/src/sage/combinat/root_system/type_A_affine.py +++ b/src/sage/combinat/root_system/type_A_affine.py @@ -72,8 +72,7 @@ def dynkin_diagram(self): EXAMPLES:: - sage: a = CartanType(['A',3,1]).dynkin_diagram() - sage: a + sage: a = CartanType(['A',3,1]).dynkin_diagram(); a # needs sage.graphs 0 O-------+ | | @@ -81,7 +80,7 @@ def dynkin_diagram(self): O---O---O 1 2 3 A3~ - sage: a.edges(sort=True) + sage: a.edges(sort=True) # needs sage.graphs [(0, 1, 1), (0, 3, 1), (1, 0, 1), @@ -91,12 +90,11 @@ def dynkin_diagram(self): (3, 0, 1), (3, 2, 1)] - sage: a = DynkinDiagram(['A',1,1]) - sage: a + sage: a = DynkinDiagram(['A',1,1]); a # needs sage.graphs O<=>O 0 1 A1~ - sage: a.edges(sort=True) + sage: a.edges(sort=True) # needs sage.graphs [(0, 1, 2), (1, 0, 2)] """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_B.py b/src/sage/combinat/root_system/type_B.py index 7a9b634b207..67794141adc 100644 --- a/src/sage/combinat/root_system/type_B.py +++ b/src/sage/combinat/root_system/type_B.py @@ -222,20 +222,18 @@ def dynkin_diagram(self): EXAMPLES:: - sage: b = CartanType(['B',3]).dynkin_diagram() - sage: b + sage: b = CartanType(['B',3]).dynkin_diagram(); b # needs sage.graphs O---O=>=O 1 2 3 B3 - sage: b.edges(sort=True) + sage: b.edges(sort=True) # needs sage.graphs [(1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1)] - sage: b = CartanType(['B',1]).dynkin_diagram() - sage: b + sage: b = CartanType(['B',1]).dynkin_diagram(); b # needs sage.graphs O 1 B1 - sage: b.edges(sort=True) + sage: b.edges(sort=True) # needs sage.graphs [] """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_BC_affine.py b/src/sage/combinat/root_system/type_BC_affine.py index aaa101b3350..1a64686bc16 100644 --- a/src/sage/combinat/root_system/type_BC_affine.py +++ b/src/sage/combinat/root_system/type_BC_affine.py @@ -22,9 +22,9 @@ def __init__(self, n): sage: ct = CartanType(['BC',4,2]) sage: ct ['BC', 4, 2] - sage: ct._repr_(compact = True) + sage: ct._repr_(compact=True) 'BC4~' - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs O=<=O---O---O=<=O 0 1 2 3 4 BC4~ @@ -43,19 +43,19 @@ def __init__(self, n): ['C', 4] sage: dual = ct.dual() - sage: dual.dynkin_diagram() + sage: dual.dynkin_diagram() # needs sage.graphs O=>=O---O---O=>=O 0 1 2 3 4 BC4~* sage: dual.special_node() 0 - sage: dual.classical().dynkin_diagram() + sage: dual.classical().dynkin_diagram() # needs sage.graphs O---O---O=>=O 1 2 3 4 B4 - sage: CartanType(['BC',1,2]).dynkin_diagram() + sage: CartanType(['BC',1,2]).dynkin_diagram() # needs sage.graphs 4 O=<=O 0 1 @@ -74,37 +74,34 @@ def dynkin_diagram(self): EXAMPLES:: - sage: c = CartanType(['BC',3,2]).dynkin_diagram() - sage: c + sage: c = CartanType(['BC',3,2]).dynkin_diagram(); c # needs sage.graphs O=<=O---O=<=O 0 1 2 3 BC3~ - sage: c.edges(sort=True) + sage: c.edges(sort=True) # needs sage.graphs [(0, 1, 1), (1, 0, 2), (1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] - sage: c = CartanType(["A", 6, 2]).dynkin_diagram() # should be the same as above; did fail at some point! - sage: c + sage: c = CartanType(["A", 6, 2]).dynkin_diagram() # should be the same as above; did fail at some point! # needs sage.graphs + sage: c # needs sage.graphs O=<=O---O=<=O 0 1 2 3 BC3~ - sage: c.edges(sort=True) + sage: c.edges(sort=True) # needs sage.graphs [(0, 1, 1), (1, 0, 2), (1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] - sage: c = CartanType(['BC',2,2]).dynkin_diagram() - sage: c + sage: c = CartanType(['BC',2,2]).dynkin_diagram(); c # needs sage.graphs O=<=O=<=O 0 1 2 BC2~ - sage: c.edges(sort=True) + sage: c.edges(sort=True) # needs sage.graphs [(0, 1, 1), (1, 0, 2), (1, 2, 1), (2, 1, 2)] - sage: c = CartanType(['BC',1,2]).dynkin_diagram() - sage: c + sage: c = CartanType(['BC',1,2]).dynkin_diagram(); c # needs sage.graphs 4 O=<=O 0 1 BC1~ - sage: c.edges(sort=True) + sage: c.edges(sort=True) # needs sage.graphs [(0, 1, 1), (1, 0, 4)] """ diff --git a/src/sage/combinat/root_system/type_B_affine.py b/src/sage/combinat/root_system/type_B_affine.py index ecf30bc226d..0e8fccd725e 100644 --- a/src/sage/combinat/root_system/type_B_affine.py +++ b/src/sage/combinat/root_system/type_B_affine.py @@ -54,8 +54,8 @@ def dynkin_diagram(self): EXAMPLES:: - sage: b = CartanType(['B',3,1]).dynkin_diagram() - sage: b + sage: # needs sage.graphs + sage: b = CartanType(['B',3,1]).dynkin_diagram(); b O 0 | | @@ -64,14 +64,12 @@ def dynkin_diagram(self): B3~ sage: b.edges(sort=True) [(0, 2, 1), (1, 2, 1), (2, 0, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1)] - sage: b = CartanType(['B',2,1]).dynkin_diagram(); b O=>=O=<=O 0 2 1 B2~ sage: b.edges(sort=True) [(0, 2, 2), (1, 2, 2), (2, 0, 1), (2, 1, 1)] - sage: b = CartanType(['B',1,1]).dynkin_diagram(); b O<=>O 0 1 diff --git a/src/sage/combinat/root_system/type_C.py b/src/sage/combinat/root_system/type_C.py index 57fdde0b5a5..57669883bea 100644 --- a/src/sage/combinat/root_system/type_C.py +++ b/src/sage/combinat/root_system/type_C.py @@ -31,7 +31,7 @@ class AmbientSpace(ambient_space.AmbientSpace): TESTS:: - sage: TestSuite(e).run() + sage: TestSuite(e).run() # needs sage.graphs """ def dimension(self): @@ -216,20 +216,18 @@ def dynkin_diagram(self): EXAMPLES:: - sage: c = CartanType(['C',3]).dynkin_diagram() - sage: c + sage: c = CartanType(['C',3]).dynkin_diagram(); c # needs sage.graphs O---O=<=O 1 2 3 C3 - sage: c.edges(sort=True) + sage: c.edges(sort=True) # needs sage.graphs [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] - sage: b = CartanType(['C',1]).dynkin_diagram() - sage: b + sage: b = CartanType(['C',1]).dynkin_diagram(); b # needs sage.graphs O 1 C1 - sage: b.edges(sort=True) + sage: b.edges(sort=True) # needs sage.graphs [] """ return self.dual().dynkin_diagram().dual() diff --git a/src/sage/combinat/root_system/type_C_affine.py b/src/sage/combinat/root_system/type_C_affine.py index 481626372bd..2ba823fd843 100644 --- a/src/sage/combinat/root_system/type_C_affine.py +++ b/src/sage/combinat/root_system/type_C_affine.py @@ -54,12 +54,11 @@ def dynkin_diagram(self): EXAMPLES:: - sage: c = CartanType(['C',3,1]).dynkin_diagram() - sage: c + sage: c = CartanType(['C',3,1]).dynkin_diagram(); c # needs sage.graphs O=>=O---O=<=O 0 1 2 3 C3~ - sage: c.edges(sort=True) + sage: c.edges(sort=True) # needs sage.graphs [(0, 1, 2), (1, 0, 1), (1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] """ diff --git a/src/sage/combinat/root_system/type_D.py b/src/sage/combinat/root_system/type_D.py index 4be291b384f..e933f662c93 100644 --- a/src/sage/combinat/root_system/type_D.py +++ b/src/sage/combinat/root_system/type_D.py @@ -224,42 +224,43 @@ def dynkin_diagram(self): EXAMPLES:: - sage: d = CartanType(['D',5]).dynkin_diagram(); d + sage: d = CartanType(['D',5]).dynkin_diagram(); d # needs sage.graphs O 5 | | O---O---O---O 1 2 3 4 D5 - sage: d.edges(sort=True) - [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 1), (3, 4, 1), (3, 5, 1), (4, 3, 1), (5, 3, 1)] + sage: d.edges(sort=True) # needs sage.graphs + [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 1), + (3, 4, 1), (3, 5, 1), (4, 3, 1), (5, 3, 1)] - sage: d = CartanType(['D',4]).dynkin_diagram(); d + sage: d = CartanType(['D',4]).dynkin_diagram(); d # needs sage.graphs O 4 | | O---O---O 1 2 3 D4 - sage: d.edges(sort=True) + sage: d.edges(sort=True) # needs sage.graphs [(1, 2, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (3, 2, 1), (4, 2, 1)] - sage: d = CartanType(['D',3]).dynkin_diagram(); d + sage: d = CartanType(['D',3]).dynkin_diagram(); d # needs sage.graphs O 3 | | O---O 1 2 D3 - sage: d.edges(sort=True) + sage: d.edges(sort=True) # needs sage.graphs [(1, 2, 1), (1, 3, 1), (2, 1, 1), (3, 1, 1)] - sage: d = CartanType(['D',2]).dynkin_diagram(); d + sage: d = CartanType(['D',2]).dynkin_diagram(); d # needs sage.graphs O O 1 2 D2 - sage: d.edges(sort=True) + sage: d.edges(sort=True) # needs sage.graphs [] """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_D_affine.py b/src/sage/combinat/root_system/type_D_affine.py index ae1b67812ff..1a3bdc15bb5 100644 --- a/src/sage/combinat/root_system/type_D_affine.py +++ b/src/sage/combinat/root_system/type_D_affine.py @@ -54,20 +54,18 @@ def dynkin_diagram(self): EXAMPLES:: - sage: d = CartanType(['D', 6, 1]).dynkin_diagram() - sage: d + sage: d = CartanType(['D', 6, 1]).dynkin_diagram(); d # needs sage.graphs 0 O O 6 | | | | O---O---O---O---O 1 2 3 4 5 D6~ - sage: d.edges(sort=True) + sage: d.edges(sort=True) # needs sage.graphs [(0, 2, 1), (1, 2, 1), (2, 0, 1), (2, 1, 1), (2, 3, 1), (3, 2, 1), (3, 4, 1), (4, 3, 1), (4, 5, 1), (4, 6, 1), (5, 4, 1), (6, 4, 1)] - sage: d = CartanType(['D', 4, 1]).dynkin_diagram() - sage: d + sage: d = CartanType(['D', 4, 1]).dynkin_diagram(); d # needs sage.graphs O 4 | | @@ -76,7 +74,7 @@ def dynkin_diagram(self): | O 0 D4~ - sage: d.edges(sort=True) + sage: d.edges(sort=True) # needs sage.graphs [(0, 2, 1), (1, 2, 1), (2, 0, 1), @@ -86,8 +84,7 @@ def dynkin_diagram(self): (3, 2, 1), (4, 2, 1)] - sage: d = CartanType(['D', 3, 1]).dynkin_diagram() - sage: d + sage: d = CartanType(['D', 3, 1]).dynkin_diagram(); d # needs sage.graphs 0 O-------+ | | @@ -95,8 +92,9 @@ def dynkin_diagram(self): O---O---O 3 1 2 D3~ - sage: d.edges(sort=True) - [(0, 2, 1), (0, 3, 1), (1, 2, 1), (1, 3, 1), (2, 0, 1), (2, 1, 1), (3, 0, 1), (3, 1, 1)] + sage: d.edges(sort=True) # needs sage.graphs + [(0, 2, 1), (0, 3, 1), (1, 2, 1), (1, 3, 1), + (2, 0, 1), (2, 1, 1), (3, 0, 1), (3, 1, 1)] """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_E.py b/src/sage/combinat/root_system/type_E.py index 05b81a31c60..2b25ab615e8 100644 --- a/src/sage/combinat/root_system/type_E.py +++ b/src/sage/combinat/root_system/type_E.py @@ -530,8 +530,8 @@ def dynkin_diagram(self): EXAMPLES:: - sage: e = CartanType(['E',6]).dynkin_diagram() - sage: e + sage: # needs sage.graphs + sage: e = CartanType(['E',6]).dynkin_diagram(); e O 2 | | @@ -539,9 +539,9 @@ def dynkin_diagram(self): 1 3 4 5 6 E6 sage: e.edges(sort=True) - [(1, 3, 1), (2, 4, 1), (3, 1, 1), (3, 4, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 4, 1), (5, 6, 1), (6, 5, 1)] - sage: e = CartanType(['E',7]).dynkin_diagram() - sage: e + [(1, 3, 1), (2, 4, 1), (3, 1, 1), (3, 4, 1), (4, 2, 1), + (4, 3, 1), (4, 5, 1), (5, 4, 1), (5, 6, 1), (6, 5, 1)] + sage: e = CartanType(['E',7]).dynkin_diagram(); e O 2 | | @@ -552,8 +552,7 @@ def dynkin_diagram(self): [(1, 3, 1), (2, 4, 1), (3, 1, 1), (3, 4, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 4, 1), (5, 6, 1), (6, 5, 1), (6, 7, 1), (7, 6, 1)] - sage: e = CartanType(['E',8]).dynkin_diagram() - sage: e + sage: e = CartanType(['E',8]).dynkin_diagram(); e O 2 | | diff --git a/src/sage/combinat/root_system/type_E_affine.py b/src/sage/combinat/root_system/type_E_affine.py index d7b8bbb2a34..7b43d33d5ba 100644 --- a/src/sage/combinat/root_system/type_E_affine.py +++ b/src/sage/combinat/root_system/type_E_affine.py @@ -66,8 +66,7 @@ def dynkin_diagram(self): EXAMPLES:: - sage: e = CartanType(['E', 6, 1]).dynkin_diagram() - sage: e + sage: e = CartanType(['E', 6, 1]).dynkin_diagram(); e # needs sage.graphs O 0 | | @@ -77,7 +76,7 @@ def dynkin_diagram(self): O---O---O---O---O 1 3 4 5 6 E6~ - sage: e.edges(sort=True) + sage: e.edges(sort=True) # needs sage.graphs [(0, 2, 1), (1, 3, 1), (2, 0, 1), @@ -91,8 +90,8 @@ def dynkin_diagram(self): (5, 6, 1), (6, 5, 1)] - sage: e = CartanType(['E', 7, 1]).dynkin_diagram() - sage: e + sage: # needs sage.graphs + sage: e = CartanType(['E', 7, 1]).dynkin_diagram(); e O 2 | | @@ -103,8 +102,7 @@ def dynkin_diagram(self): [(0, 1, 1), (1, 0, 1), (1, 3, 1), (2, 4, 1), (3, 1, 1), (3, 4, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 4, 1), (5, 6, 1), (6, 5, 1), (6, 7, 1), (7, 6, 1)] - sage: e = CartanType(['E', 8, 1]).dynkin_diagram() - sage: e + sage: e = CartanType(['E', 8, 1]).dynkin_diagram(); e O 2 | | diff --git a/src/sage/combinat/root_system/type_F.py b/src/sage/combinat/root_system/type_F.py index a7ab233b1b2..778b74166fb 100644 --- a/src/sage/combinat/root_system/type_F.py +++ b/src/sage/combinat/root_system/type_F.py @@ -37,7 +37,7 @@ def __init__(self, root_system, base_ring): TESTS:: - sage: TestSuite(e).run() + sage: TestSuite(e).run() # needs sage.graphs """ ambient_space.AmbientSpace.__init__(self, root_system, base_ring) v = ZZ(1)/ZZ(2) @@ -275,12 +275,11 @@ def dynkin_diagram(self): EXAMPLES:: - sage: f = CartanType(['F',4]).dynkin_diagram() - sage: f + sage: f = CartanType(['F',4]).dynkin_diagram(); f # needs sage.graphs O---O=>=O---O 1 2 3 4 F4 - sage: f.edges(sort=True) + sage: f.edges(sort=True) # needs sage.graphs [(1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1), (3, 4, 1), (4, 3, 1)] """ @@ -355,11 +354,11 @@ def dual(self): sage: F4.dual() ['F', 4] relabelled by {1: 4, 2: 3, 3: 2, 4: 1} - sage: F4.dynkin_diagram() + sage: F4.dynkin_diagram() # needs sage.graphs O---O=>=O---O 1 2 3 4 F4 - sage: F4.dual().dynkin_diagram() + sage: F4.dual().dynkin_diagram() # needs sage.graphs O---O=>=O---O 4 3 2 1 F4 relabelled by {1: 4, 2: 3, 3: 2, 4: 1} diff --git a/src/sage/combinat/root_system/type_F_affine.py b/src/sage/combinat/root_system/type_F_affine.py index 5e27c4c6aff..f5a4c2e84c2 100644 --- a/src/sage/combinat/root_system/type_F_affine.py +++ b/src/sage/combinat/root_system/type_F_affine.py @@ -55,13 +55,13 @@ def dynkin_diagram(self): EXAMPLES:: - sage: f = CartanType(['F', 4, 1]).dynkin_diagram() - sage: f + sage: f = CartanType(['F', 4, 1]).dynkin_diagram(); f # needs sage.graphs O---O---O=>=O---O 0 1 2 3 4 F4~ - sage: f.edges(sort=True) - [(0, 1, 1), (1, 0, 1), (1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1), (3, 4, 1), (4, 3, 1)] + sage: f.edges(sort=True) # needs sage.graphs + [(0, 1, 1), (1, 0, 1), (1, 2, 1), (2, 1, 1), + (2, 3, 2), (3, 2, 1), (3, 4, 1), (4, 3, 1)] """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_G.py b/src/sage/combinat/root_system/type_G.py index 8bc189ef756..e0a4c40c5f5 100644 --- a/src/sage/combinat/root_system/type_G.py +++ b/src/sage/combinat/root_system/type_G.py @@ -32,18 +32,19 @@ class AmbientSpace(ambient_space.AmbientSpace): By default, this ambient space uses the barycentric projection for plotting:: + sage: # needs sage.symbolic sage: L = RootSystem(["G",2]).ambient_space() sage: e = L.basis() - sage: L._plot_projection(e[0]) # optional - sage.symbolic + sage: L._plot_projection(e[0]) (1/2, 989/1142) - sage: L._plot_projection(e[1]) # optional - sage.symbolic + sage: L._plot_projection(e[1]) (-1, 0) - sage: L._plot_projection(e[2]) # optional - sage.symbolic + sage: L._plot_projection(e[2]) (1/2, -989/1142) sage: L = RootSystem(["A",3]).ambient_space() sage: l = L.an_element(); l (2, 2, 3, 0) - sage: L._plot_projection(l) # optional - sage.symbolic + sage: L._plot_projection(l) (0, -1121/1189, 7/3) .. SEEALSO:: @@ -185,13 +186,12 @@ def dynkin_diagram(self): EXAMPLES:: - sage: g = CartanType(['G',2]).dynkin_diagram() - sage: g + sage: g = CartanType(['G',2]).dynkin_diagram(); g # needs sage.graphs 3 O=<=O 1 2 G2 - sage: g.edges(sort=True) + sage: g.edges(sort=True) # needs sage.graphs [(1, 2, 1), (2, 1, 3)] """ from .dynkin_diagram import DynkinDiagram_class @@ -256,12 +256,12 @@ def dual(self): sage: G2.dual() ['G', 2] relabelled by {1: 2, 2: 1} - sage: G2.dynkin_diagram() + sage: G2.dynkin_diagram() # needs sage.graphs 3 O=<=O 1 2 G2 - sage: G2.dual().dynkin_diagram() + sage: G2.dual().dynkin_diagram() # needs sage.graphs 3 O=<=O 2 1 diff --git a/src/sage/combinat/root_system/type_G_affine.py b/src/sage/combinat/root_system/type_G_affine.py index cde34a41753..30c67d2f2c5 100644 --- a/src/sage/combinat/root_system/type_G_affine.py +++ b/src/sage/combinat/root_system/type_G_affine.py @@ -55,13 +55,12 @@ def dynkin_diagram(self): EXAMPLES:: - sage: g = CartanType(['G',2,1]).dynkin_diagram() - sage: g + sage: g = CartanType(['G',2,1]).dynkin_diagram(); g # needs sage.graphs 3 O=<=O---O 1 2 0 G2~ - sage: g.edges(sort=True) + sage: g.edges(sort=True) # needs sage.graphs [(0, 2, 1), (1, 2, 1), (2, 0, 1), (2, 1, 3)] """ from .dynkin_diagram import DynkinDiagram_class diff --git a/src/sage/combinat/root_system/type_H.py b/src/sage/combinat/root_system/type_H.py index 13d5b6eb04a..44f4b15db55 100644 --- a/src/sage/combinat/root_system/type_H.py +++ b/src/sage/combinat/root_system/type_H.py @@ -60,21 +60,21 @@ def coxeter_diagram(self): EXAMPLES:: sage: ct = CartanType(['H',3]) - sage: ct.coxeter_diagram() + sage: ct.coxeter_diagram() # needs sage.graphs Graph on 3 vertices - sage: ct.coxeter_diagram().edges(sort=True) + sage: ct.coxeter_diagram().edges(sort=True) # needs sage.graphs [(1, 2, 3), (2, 3, 5)] - sage: ct.coxeter_matrix() + sage: ct.coxeter_matrix() # needs sage.graphs [1 3 2] [3 1 5] [2 5 1] sage: ct = CartanType(['H',4]) - sage: ct.coxeter_diagram() + sage: ct.coxeter_diagram() # needs sage.graphs Graph on 4 vertices - sage: ct.coxeter_diagram().edges(sort=True) + sage: ct.coxeter_diagram().edges(sort=True) # needs sage.graphs [(1, 2, 3), (2, 3, 3), (3, 4, 5)] - sage: ct.coxeter_matrix() + sage: ct.coxeter_matrix() # needs sage.graphs [1 3 2 2] [3 1 3 2] [2 3 1 5] diff --git a/src/sage/combinat/root_system/type_I.py b/src/sage/combinat/root_system/type_I.py index bafa43b8410..76a24817bf9 100644 --- a/src/sage/combinat/root_system/type_I.py +++ b/src/sage/combinat/root_system/type_I.py @@ -84,11 +84,11 @@ def coxeter_diagram(self): EXAMPLES:: sage: ct = CartanType(['I', 4]) - sage: ct.coxeter_diagram() + sage: ct.coxeter_diagram() # needs sage.graphs Graph on 2 vertices - sage: ct.coxeter_diagram().edges(sort=True) + sage: ct.coxeter_diagram().edges(sort=True) # needs sage.graphs [(1, 2, 4)] - sage: ct.coxeter_matrix() + sage: ct.coxeter_matrix() # needs sage.graphs [1 4] [4 1] """ diff --git a/src/sage/combinat/root_system/type_affine.py b/src/sage/combinat/root_system/type_affine.py index 97644ac3998..2ee426867ca 100644 --- a/src/sage/combinat/root_system/type_affine.py +++ b/src/sage/combinat/root_system/type_affine.py @@ -37,7 +37,7 @@ class AmbientSpace(CombinatorialFreeModule): In type `BC`, the null root is in fact:: sage: R = RootSystem(["BC",3,2]).ambient_space() - sage: R.null_root() + sage: R.null_root() # needs sage.graphs 2*e['delta'] .. WARNING:: @@ -54,16 +54,16 @@ class AmbientSpace(CombinatorialFreeModule): are identified:: sage: L = RootSystem(["A",3,1]).ambient_space() - sage: Lambda = L.fundamental_weights() - sage: Lambda[0] + sage: Lambda = L.fundamental_weights() # needs sage.graphs + sage: Lambda[0] # needs sage.graphs e['deltacheck'] - sage: L.null_coroot() + sage: L.null_coroot() # needs sage.graphs e['deltacheck'] Therefore the scalar product of the null coroot with itself differs from the larger ambient space:: - sage: L.null_coroot().scalar(L.null_coroot()) + sage: L.null_coroot().scalar(L.null_coroot()) # needs sage.graphs 1 In general, scalar products between two elements that do not @@ -108,7 +108,7 @@ class AmbientSpace(CombinatorialFreeModule): TESTS:: - sage: Lambda[1] + sage: Lambda[1] # needs sage.graphs e[0] + e['deltacheck'] """ @classmethod @@ -247,22 +247,28 @@ def fundamental_weight(self, i): EXAMPLES:: - sage: RootSystem(['A',3,1]).ambient_space().fundamental_weight(2) + sage: RootSystem(['A',3,1]).ambient_space().fundamental_weight(2) # needs sage.graphs e[0] + e[1] + e['deltacheck'] - sage: RootSystem(['A',3,1]).ambient_space().fundamental_weights() - Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'], - 2: e[0] + e[1] + e['deltacheck'], 3: e[0] + e[1] + e[2] + e['deltacheck']} + sage: RootSystem(['A',3,1]).ambient_space().fundamental_weights() # needs sage.graphs + Finite family {0: e['deltacheck'], + 1: e[0] + e['deltacheck'], + 2: e[0] + e[1] + e['deltacheck'], + 3: e[0] + e[1] + e[2] + e['deltacheck']} sage: RootSystem(['A',3]).ambient_space().fundamental_weights() Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)} - sage: RootSystem(['A',3,1]).weight_lattice().fundamental_weights().map(attrcall("level")) + sage: A31wl = RootSystem(['A',3,1]).weight_lattice() + sage: A31wl.fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 1, 1: 1, 2: 1, 3: 1} - sage: RootSystem(['B',3,1]).ambient_space().fundamental_weights() - Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'], - 2: e[0] + e[1] + 2*e['deltacheck'], 3: 1/2*e[0] + 1/2*e[1] + 1/2*e[2] + e['deltacheck']} + sage: RootSystem(['B',3,1]).ambient_space().fundamental_weights() # needs sage.graphs + Finite family {0: e['deltacheck'], + 1: e[0] + e['deltacheck'], + 2: e[0] + e[1] + 2*e['deltacheck'], + 3: 1/2*e[0] + 1/2*e[1] + 1/2*e[2] + e['deltacheck']} sage: RootSystem(['B',3]).ambient_space().fundamental_weights() Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)} - sage: RootSystem(['B',3,1]).weight_lattice().fundamental_weights().map(attrcall("level")) + sage: B31wl = RootSystem(['B',3,1]).weight_lattice() + sage: B31wl.fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 1, 1: 1, 2: 2, 3: 1} In type `BC` dual, the coefficient of '\delta^\vee' is the level @@ -270,13 +276,14 @@ def fundamental_weight(self, i): `2\delta^\vee`:: sage: R = CartanType(['BC',3,2]).dual().root_system() - sage: R.ambient_space().fundamental_weights() - Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'], + sage: R.ambient_space().fundamental_weights() # needs sage.graphs + Finite family {0: e['deltacheck'], + 1: e[0] + e['deltacheck'], 2: e[0] + e[1] + e['deltacheck'], 3: 1/2*e[0] + 1/2*e[1] + 1/2*e[2] + 1/2*e['deltacheck']} - sage: R.weight_lattice().fundamental_weights().map(attrcall("level")) + sage: R.weight_lattice().fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 2, 1: 2, 2: 2, 3: 1} - sage: R.ambient_space().null_coroot() + sage: R.ambient_space().null_coroot() # needs sage.graphs 2*e['deltacheck'] By a slight naming abuse this function also accepts "delta" as @@ -314,22 +321,26 @@ def simple_root(self, i): sage: RootSystem(["A",3]).ambient_space().simple_roots() Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)} - sage: RootSystem(["A",3,1]).ambient_space().simple_roots() - Finite family {0: -e[0] + e[3] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: e[2] - e[3]} + sage: RootSystem(["A",3,1]).ambient_space().simple_roots() # needs sage.graphs + Finite family {0: -e[0] + e[3] + e['delta'], 1: e[0] - e[1], + 2: e[1] - e[2], 3: e[2] - e[3]} Here is a twisted affine example:: - sage: RootSystem(CartanType(["B",3,1]).dual()).ambient_space().simple_roots() - Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]} + sage: B31v = RootSystem(CartanType(["B",3,1]).dual()) + sage: B31v.ambient_space().simple_roots() # needs sage.graphs + Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], + 2: e[1] - e[2], 3: 2*e[2]} In fact `\delta` is really `1/a_0` times the null root (see the discussion in :class:`~sage.combinat.root_system.weight_space.WeightSpace`) but this only makes a difference in type `BC`:: sage: L = RootSystem(CartanType(["BC",3,2])).ambient_space() - sage: L.simple_roots() - Finite family {0: -e[0] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]} - sage: L.null_root() + sage: L.simple_roots() # needs sage.graphs + Finite family {0: -e[0] + e['delta'], 1: e[0] - e[1], + 2: e[1] - e[2], 3: 2*e[2]} + sage: L.null_root() # needs sage.graphs 2*e['delta'] .. NOTE:: @@ -367,10 +378,12 @@ def simple_coroot(self, i): It is built as the coroot associated to the simple root `\alpha_i`:: - sage: RootSystem(["B",3,1]).ambient_space().simple_roots() - Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: e[2]} - sage: RootSystem(["B",3,1]).ambient_space().simple_coroots() - Finite family {0: -e[0] - e[1] + e['deltacheck'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]} + sage: RootSystem(["B",3,1]).ambient_space().simple_roots() # needs sage.graphs + Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], + 2: e[1] - e[2], 3: e[2]} + sage: RootSystem(["B",3,1]).ambient_space().simple_coroots() # needs sage.graphs + Finite family {0: -e[0] - e[1] + e['deltacheck'], 1: e[0] - e[1], + 2: e[1] - e[2], 3: 2*e[2]} .. TODO:: Factor out this code with the classical ambient space. """ @@ -403,26 +416,28 @@ def _plot_projection(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: L = RootSystem(["B",2,1]).ambient_space() sage: e = L.basis() - sage: L._plot_projection(e[0]) # optional - sage.symbolic + sage: L._plot_projection(e[0]) (1, 0, 0) - sage: L._plot_projection(e[1]) # optional - sage.symbolic + sage: L._plot_projection(e[1]) (0, 1, 0) - sage: L._plot_projection(e["delta"]) # optional - sage.symbolic + sage: L._plot_projection(e["delta"]) (0, 0, 0) - sage: L._plot_projection(e["deltacheck"]) # optional - sage.symbolic + sage: L._plot_projection(e["deltacheck"]) (0, 0, 1) + sage: # needs sage.symbolic sage: L = RootSystem(["A",2,1]).ambient_space() sage: e = L.basis() - sage: L._plot_projection(e[0]) # optional - sage.symbolic + sage: L._plot_projection(e[0]) (1/2, 989/1142, 0) - sage: L._plot_projection(e[1]) # optional - sage.symbolic + sage: L._plot_projection(e[1]) (-1, 0, 0) - sage: L._plot_projection(e["delta"]) # optional - sage.symbolic + sage: L._plot_projection(e["delta"]) (0, 0, 0) - sage: L._plot_projection(e["deltacheck"]) # optional - sage.symbolic + sage: L._plot_projection(e["deltacheck"]) (0, 0, 1) """ from sage.modules.free_module_element import vector @@ -475,6 +490,7 @@ def associated_coroot(self): EXAMPLES:: + sage: # needs sage.graphs sage: alpha = RootSystem(['C',2,1]).ambient_space().simple_roots() sage: alpha Finite family {0: -2*e[0] + e['delta'], 1: e[0] - e[1], 2: 2*e[1]} diff --git a/src/sage/combinat/root_system/type_dual.py b/src/sage/combinat/root_system/type_dual.py index 38d39b80b90..778f091492a 100644 --- a/src/sage/combinat/root_system/type_dual.py +++ b/src/sage/combinat/root_system/type_dual.py @@ -338,7 +338,7 @@ def dynkin_diagram(self): EXAMPLES:: sage: ct = CartanType(['F', 4, 1]).dual() - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs O---O---O=<=O---O 0 1 2 3 4 F4~* @@ -379,7 +379,7 @@ class AmbientSpace(ambient_space.AmbientSpace): sage: ct = sage.combinat.root_system.type_dual.CartanType(CartanType(['F',4])) sage: L = ct.root_system().ambient_space(); L Ambient space of the Root system of type ['F', 4]^* - sage: TestSuite(L).run(skip=["_test_elements","_test_pickling"]) + sage: TestSuite(L).run(skip=["_test_elements","_test_pickling"]) # needs sage.graphs """ @lazy_attribute @@ -472,7 +472,7 @@ def fundamental_weights(self): sage: ct = sage.combinat.root_system.type_dual.CartanType(CartanType(['F',4])) sage: L = ct.root_system().ambient_space() - sage: L.fundamental_weights() + sage: L.fundamental_weights() # needs sage.graphs Finite family {1: (1, 1, 0, 0), 2: (2, 1, 1, 0), 3: (3, 1, 1, 1), 4: (2, 0, 0, 0)} Note that this ambient space is isomorphic, but not equal, to diff --git a/src/sage/combinat/root_system/type_folded.py b/src/sage/combinat/root_system/type_folded.py index bfb0d1513c6..58f4911c361 100644 --- a/src/sage/combinat/root_system/type_folded.py +++ b/src/sage/combinat/root_system/type_folded.py @@ -116,7 +116,7 @@ class CartanTypeFolded(UniqueRepresentation, SageObject): sage: fct = CartanType(['C',4,1]).as_folding(); fct ['C', 4, 1] as a folding of ['A', 7, 1] - sage: fct.scaling_factors() + sage: fct.scaling_factors() # needs sage.graphs Finite family {0: 2, 1: 1, 2: 1, 3: 1, 4: 2} sage: fct.folding_orbit() Finite family {0: (0,), 1: (1, 7), 2: (2, 6), 3: (3, 5), 4: (4,)} @@ -126,7 +126,7 @@ class CartanTypeFolded(UniqueRepresentation, SageObject): sage: fct = CartanType(['A',4,1]).as_folding(); fct ['A', 4, 1] as a folding of ['A', 4, 1] - sage: fct.scaling_factors() + sage: fct.scaling_factors() # needs sage.graphs Finite family {0: 1, 1: 1, 2: 1, 3: 1, 4: 1} sage: fct.folding_orbit() Finite family {0: (0,), 1: (1,), 2: (2,), 3: (3,), 4: (4,)} @@ -270,6 +270,7 @@ def scaling_factors(self): EXAMPLES:: + sage: # needs sage.graphs sage: fct = CartanType(['C', 4, 1]).as_folding() sage: fct.scaling_factors() Finite family {0: 2, 1: 1, 2: 1, 3: 1, 4: 2} diff --git a/src/sage/combinat/root_system/type_marked.py b/src/sage/combinat/root_system/type_marked.py index a15eb8d1547..5d80ca1052a 100644 --- a/src/sage/combinat/root_system/type_marked.py +++ b/src/sage/combinat/root_system/type_marked.py @@ -30,7 +30,7 @@ class CartanType(cartan_type.CartanType_decorator): We take the Cartan type `B_4`:: sage: T = CartanType(['B',4]) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 1 2 3 4 B4 @@ -38,14 +38,14 @@ class CartanType(cartan_type.CartanType_decorator): And mark some of its nodes:: sage: T = T.marked_nodes([2,3]) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---X---X=>=O 1 2 3 4 B4 with nodes (2, 3) marked Markings are not additive:: - sage: T.marked_nodes([1,4]).dynkin_diagram() + sage: T.marked_nodes([1,4]).dynkin_diagram() # needs sage.graphs X---O---O=>=X 1 2 3 4 B4 with nodes (1, 4) marked @@ -53,7 +53,7 @@ class CartanType(cartan_type.CartanType_decorator): And trivial relabelling are honoured nicely:: sage: T = T.marked_nodes([]) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 1 2 3 4 B4 @@ -160,14 +160,14 @@ def _repr_(self, compact=False): sage: CartanType(['F', 4, 1]).marked_nodes([0, 2])._repr_(compact = True) 'F4~ with nodes (0, 2) marked' - sage: D = DynkinDiagram("A2") - sage: D.marked_nodes([1]) + sage: D = DynkinDiagram("A2") # needs sage.graphs + sage: D.marked_nodes([1]) # needs sage.graphs O---O 1 2 A2 with node 1 marked - sage: CM = CartanMatrix([[2,-4],[-5,2]]) - sage: CM.marked_nodes([1]) + sage: CM = CartanMatrix([[2,-4],[-5,2]]) # needs sage.graphs + sage: CM.marked_nodes([1]) # needs sage.graphs [ 2 -4] [-5 2] with node 1 marked """ @@ -330,7 +330,7 @@ def dynkin_diagram(self): EXAMPLES:: - sage: CartanType(["G", 2]).marked_nodes([2]).dynkin_diagram() + sage: CartanType(["G", 2]).marked_nodes([2]).dynkin_diagram() # needs sage.graphs 3 O=<=X 1 2 @@ -340,11 +340,11 @@ def dynkin_diagram(self): To be compared with the examples in :meth:`ascii_art`:: - sage: CartanType(["G", 2]).relabel({1:2,2:1}).dynkin_diagram().edges(sort=True) + sage: CartanType(["G", 2]).relabel({1:2,2:1}).dynkin_diagram().edges(sort=True) # needs sage.graphs [(1, 2, 3), (2, 1, 1)] - sage: CartanType(["B", 3, 1]).relabel([1,3,2,0]).dynkin_diagram().edges(sort=True) + sage: CartanType(["B", 3, 1]).relabel([1,3,2,0]).dynkin_diagram().edges(sort=True) # needs sage.graphs [(0, 2, 1), (1, 2, 1), (2, 0, 2), (2, 1, 1), (2, 3, 1), (3, 2, 1)] - sage: CartanType(["F", 4, 1]).relabel(lambda n: 4-n).dynkin_diagram().edges(sort=True) + sage: CartanType(["F", 4, 1]).relabel(lambda n: 4-n).dynkin_diagram().edges(sort=True) # needs sage.graphs [(0, 1, 1), (1, 0, 1), (1, 2, 1), (2, 1, 2), (2, 3, 1), (3, 2, 1), (3, 4, 1), (4, 3, 1)] """ result = self._type.dynkin_diagram().copy() @@ -360,11 +360,11 @@ def dual(self): EXAMPLES:: sage: T = CartanType(["BC",3, 2]) - sage: T.marked_nodes([1,3]).dual().dynkin_diagram() + sage: T.marked_nodes([1,3]).dual().dynkin_diagram() # needs sage.graphs O=>=X---O=>=X 0 1 2 3 BC3~* with nodes (1, 3) marked - sage: T.dual().marked_nodes([1,3]).dynkin_diagram() + sage: T.dual().marked_nodes([1,3]).dynkin_diagram() # needs sage.graphs O=>=X---O=>=X 0 1 2 3 BC3~* with nodes (1, 3) marked @@ -378,11 +378,11 @@ def relabel(self, relabelling): EXAMPLES:: sage: T = CartanType(["BC",3, 2]) - sage: T.marked_nodes([1,3]).relabel(lambda x: x+2).dynkin_diagram() + sage: T.marked_nodes([1,3]).relabel(lambda x: x+2).dynkin_diagram() # needs sage.graphs O=<=X---O=<=X 2 3 4 5 BC3~ relabelled by {0: 2, 1: 3, 2: 4, 3: 5} with nodes (3, 5) marked - sage: T.relabel(lambda x: x+2).marked_nodes([3,5]).dynkin_diagram() + sage: T.relabel(lambda x: x+2).marked_nodes([3,5]).dynkin_diagram() # needs sage.graphs O=<=X---O=<=X 2 3 4 5 BC3~ relabelled by {0: 2, 1: 3, 2: 4, 3: 5} with nodes (3, 5) marked @@ -425,7 +425,7 @@ def _default_folded_cartan_type(self): Finite family {0: (0,), 1: (2,), 2: (1, 3, 4)} sage: CartanType(['G',2,1]).dual()._default_folded_cartan_type().folding_orbit() Finite family {0: (0,), 1: (1, 3, 4), 2: (2,)} - sage: CartanType(['C',3,1]).relabel({0:1, 1:0, 2:3, 3:2}).as_folding().scaling_factors() + sage: CartanType(['C',3,1]).relabel({0:1, 1:0, 2:3, 3:2}).as_folding().scaling_factors() # needs sage.graphs Finite family {0: 1, 1: 2, 2: 2, 3: 1} """ from sage.combinat.root_system.type_folded import CartanTypeFolded @@ -461,7 +461,7 @@ class AmbientSpace(ambient_space.AmbientSpace): sage: L = CartanType(["F",4]).marked_nodes([1,3]).root_system().ambient_space(); L Ambient space of the Root system of type ['F', 4] with nodes (1, 3) marked - sage: TestSuite(L).run() + sage: TestSuite(L).run() # needs sage.graphs """ @lazy_attribute def _space(self): @@ -567,11 +567,11 @@ def affine(self): EXAMPLES:: sage: B4 = CartanType(['B',4]).marked_nodes([1,3]) - sage: B4.dynkin_diagram() + sage: B4.dynkin_diagram() # needs sage.graphs X---O---X=>=O 1 2 3 4 B4 with nodes (1, 3) marked - sage: B4.affine().dynkin_diagram() + sage: B4.affine().dynkin_diagram() # needs sage.graphs O 0 | | @@ -670,7 +670,7 @@ def classical(self): EXAMPLES:: sage: T = CartanType(['A',4,1]).marked_nodes([0,2,4]) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs 0 X-----------+ | | @@ -679,10 +679,9 @@ def classical(self): 1 2 3 4 A4~ with nodes (0, 2, 4) marked - sage: T0 = T.classical() - sage: T0 + sage: T0 = T.classical(); T0 ['A', 4] with nodes (2, 4) marked - sage: T0.dynkin_diagram() + sage: T0.dynkin_diagram() # needs sage.graphs O---X---O---X 1 2 3 4 A4 with nodes (2, 4) marked diff --git a/src/sage/combinat/root_system/type_reducible.py b/src/sage/combinat/root_system/type_reducible.py index 527447b0e41..0f84b3f3b90 100644 --- a/src/sage/combinat/root_system/type_reducible.py +++ b/src/sage/combinat/root_system/type_reducible.py @@ -66,7 +66,7 @@ class CartanType(SageObject, CartanType_abstract): sage: t.index_set() (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) - sage: t.dynkin_diagram() + sage: t.dynkin_diagram() # needs sage.graphs O---O---O---O 1 2 3 4 O=<=O---O---O---O=<=O @@ -256,18 +256,18 @@ def cartan_matrix(self, subdivide=True): EXAMPLES:: sage: ct = CartanType("A2","B2") - sage: ct.cartan_matrix() + sage: ct.cartan_matrix() # needs sage.graphs [ 2 -1| 0 0] [-1 2| 0 0] [-----+-----] [ 0 0| 2 -1] [ 0 0|-2 2] - sage: ct.cartan_matrix(subdivide=False) + sage: ct.cartan_matrix(subdivide=False) # needs sage.graphs [ 2 -1 0 0] [-1 2 0 0] [ 0 0 2 -1] [ 0 0 -2 2] - sage: ct.index_set() == ct.cartan_matrix().index_set() + sage: ct.index_set() == ct.cartan_matrix().index_set() # needs sage.graphs True """ from sage.combinat.root_system.cartan_matrix import CartanMatrix @@ -280,8 +280,7 @@ def dynkin_diagram(self): EXAMPLES:: - sage: dd = CartanType("A2xB2xF4").dynkin_diagram() - sage: dd + sage: dd = CartanType("A2xB2xF4").dynkin_diagram(); dd # needs sage.graphs O---O 1 2 O=>=O @@ -289,10 +288,11 @@ def dynkin_diagram(self): O---O=>=O---O 5 6 7 8 A2xB2xF4 - sage: dd.edges(sort=True) - [(1, 2, 1), (2, 1, 1), (3, 4, 2), (4, 3, 1), (5, 6, 1), (6, 5, 1), (6, 7, 2), (7, 6, 1), (7, 8, 1), (8, 7, 1)] + sage: dd.edges(sort=True) # needs sage.graphs + [(1, 2, 1), (2, 1, 1), (3, 4, 2), (4, 3, 1), (5, 6, 1), + (6, 5, 1), (6, 7, 2), (7, 6, 1), (7, 8, 1), (8, 7, 1)] - sage: CartanType("F4xA2").dynkin_diagram() + sage: CartanType("F4xA2").dynkin_diagram() # needs sage.graphs O---O=>=O---O 1 2 3 4 O---O @@ -432,18 +432,17 @@ def coxeter_diagram(self): EXAMPLES:: - sage: cd = CartanType("A2xB2xF4").coxeter_diagram() - sage: cd + sage: cd = CartanType("A2xB2xF4").coxeter_diagram(); cd # needs sage.graphs Graph on 8 vertices - sage: cd.edges(sort=True) + sage: cd.edges(sort=True) # needs sage.graphs [(1, 2, 3), (3, 4, 4), (5, 6, 3), (6, 7, 4), (7, 8, 3)] - sage: CartanType("F4xA2").coxeter_diagram().edges(sort=True) + sage: CartanType("F4xA2").coxeter_diagram().edges(sort=True) # needs sage.graphs [(1, 2, 3), (2, 3, 4), (3, 4, 3), (5, 6, 3)] - sage: cd = CartanType("A1xH3").coxeter_diagram(); cd + sage: cd = CartanType("A1xH3").coxeter_diagram(); cd # needs sage.graphs Graph on 4 vertices - sage: cd.edges(sort=True) + sage: cd.edges(sort=True) # needs sage.graphs [(2, 3, 3), (3, 4, 5)] """ from sage.graphs.graph import Graph diff --git a/src/sage/combinat/root_system/type_relabel.py b/src/sage/combinat/root_system/type_relabel.py index 624619db3fc..142ddeffa45 100644 --- a/src/sage/combinat/root_system/type_relabel.py +++ b/src/sage/combinat/root_system/type_relabel.py @@ -75,7 +75,7 @@ def __init__(self, type, relabelling): We take the Cartan type `B_4`:: sage: T = CartanType(['B',4]) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 1 2 3 4 B4 @@ -85,23 +85,23 @@ def __init__(self, type, relabelling): sage: cycle = {1:2, 2:3, 3:4, 4:1} sage: T = T.relabel(cycle) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 2 3 4 1 B4 relabelled by {1: 2, 2: 3, 3: 4, 4: 1} - sage: T.dynkin_diagram().edges(sort=True) + sage: T.dynkin_diagram().edges(sort=True) # needs sage.graphs [(1, 4, 1), (2, 3, 1), (3, 2, 1), (3, 4, 1), (4, 1, 2), (4, 3, 1)] Multiple relabelling are recomposed into a single one:: sage: T = T.relabel(cycle) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 3 4 1 2 B4 relabelled by {1: 3, 2: 4, 3: 1, 4: 2} sage: T = T.relabel(cycle) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 4 1 2 3 B4 relabelled by {1: 4, 2: 1, 3: 2, 4: 3} @@ -109,7 +109,7 @@ def __init__(self, type, relabelling): And trivial relabelling are honoured nicely:: sage: T = T.relabel(cycle) - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 1 2 3 4 B4 @@ -149,19 +149,19 @@ def __init__(self, type, relabelling): Check for the original issues of :trac:`13724`:: sage: A3 = CartanType("A3") - sage: A3.cartan_matrix() + sage: A3.cartan_matrix() # needs sage.graphs [ 2 -1 0] [-1 2 -1] [ 0 -1 2] sage: A3r = A3.relabel({1:2,2:3,3:1}) - sage: A3r.cartan_matrix() + sage: A3r.cartan_matrix() # needs sage.graphs [ 2 0 -1] [ 0 2 -1] [-1 -1 2] sage: ct = CartanType(["D",4,3]).classical(); ct ['G', 2] - sage: ct.symmetrizer() + sage: ct.symmetrizer() # needs sage.graphs Finite family {1: 1, 2: 3} Check the underlying issue of :trac:`24892`, that the root system @@ -317,7 +317,7 @@ def dynkin_diagram(self): EXAMPLES:: - sage: CartanType(["G", 2]).relabel({1:2,2:1}).dynkin_diagram() + sage: CartanType(["G", 2]).relabel({1:2,2:1}).dynkin_diagram() # needs sage.graphs 3 O=<=O 2 1 @@ -327,11 +327,11 @@ def dynkin_diagram(self): To be compared with the examples in :meth:`ascii_art`:: - sage: CartanType(["G", 2]).relabel({1:2,2:1}).dynkin_diagram().edges(sort=True) + sage: CartanType(["G", 2]).relabel({1:2,2:1}).dynkin_diagram().edges(sort=True) # needs sage.graphs [(1, 2, 3), (2, 1, 1)] - sage: CartanType(["B", 3, 1]).relabel([1,3,2,0]).dynkin_diagram().edges(sort=True) + sage: CartanType(["B", 3, 1]).relabel([1,3,2,0]).dynkin_diagram().edges(sort=True) # needs sage.graphs [(0, 2, 1), (1, 2, 1), (2, 0, 2), (2, 1, 1), (2, 3, 1), (3, 2, 1)] - sage: CartanType(["F", 4, 1]).relabel(lambda n: 4-n).dynkin_diagram().edges(sort=True) + sage: CartanType(["F", 4, 1]).relabel(lambda n: 4-n).dynkin_diagram().edges(sort=True) # needs sage.graphs [(0, 1, 1), (1, 0, 1), (1, 2, 1), (2, 1, 2), (2, 3, 1), (3, 2, 1), (3, 4, 1), (4, 3, 1)] """ # Maybe we want to move this up as a relabel method for Dynkin diagram @@ -361,11 +361,11 @@ def dual(self): sage: T = CartanType(["BC",3, 2]) sage: cycle = {1:2, 2:3, 3:0, 0:1} - sage: T.relabel(cycle).dual().dynkin_diagram() + sage: T.relabel(cycle).dual().dynkin_diagram() # needs sage.graphs O=>=O---O=>=O 1 2 3 0 BC3~* relabelled by {0: 1, 1: 2, 2: 3, 3: 0} - sage: T.dual().relabel(cycle).dynkin_diagram() + sage: T.dual().relabel(cycle).dynkin_diagram() # needs sage.graphs O=>=O---O=>=O 1 2 3 0 BC3~* relabelled by {0: 1, 1: 2, 2: 3, 3: 0} @@ -384,7 +384,7 @@ def _default_folded_cartan_type(self): Finite family {0: (0,), 1: (2,), 2: (1, 3, 4)} sage: CartanType(['G',2,1]).dual()._default_folded_cartan_type().folding_orbit() Finite family {0: (0,), 1: (1, 3, 4), 2: (2,)} - sage: CartanType(['C',3,1]).relabel({0:1, 1:0, 2:3, 3:2}).as_folding().scaling_factors() + sage: CartanType(['C',3,1]).relabel({0:1, 1:0, 2:3, 3:2}).as_folding().scaling_factors() # needs sage.graphs Finite family {0: 1, 1: 2, 2: 2, 3: 1} """ from sage.combinat.root_system.type_folded import CartanTypeFolded @@ -413,9 +413,9 @@ def coxeter_diagram(self): EXAMPLES:: sage: ct = CartanType(['H', 3]).relabel({1:3,2:2,3:1}) - sage: G = ct.coxeter_diagram(); G + sage: G = ct.coxeter_diagram(); G # needs sage.graphs Graph on 3 vertices - sage: G.edges(sort=True) + sage: G.edges(sort=True) # needs sage.graphs [(1, 2, 5), (2, 3, 3)] """ return self._type.coxeter_diagram().relabel(self._relabelling, inplace=False, immutable=True) @@ -436,7 +436,7 @@ class AmbientSpace(ambient_space.AmbientSpace): sage: cycle = {1:2, 2:3, 3:4, 4:1} sage: L = CartanType(["F",4]).relabel(cycle).root_system().ambient_space(); L Ambient space of the Root system of type ['F', 4] relabelled by {1: 2, 2: 3, 3: 4, 4: 1} - sage: TestSuite(L).run() + sage: TestSuite(L).run() # needs sage.graphs """ @lazy_attribute @@ -555,11 +555,11 @@ def affine(self): EXAMPLES:: sage: B4 = CartanType(['B',4]) - sage: B4.dynkin_diagram() + sage: B4.dynkin_diagram() # needs sage.graphs O---O---O=>=O 1 2 3 4 B4 - sage: B4.affine().dynkin_diagram() + sage: B4.affine().dynkin_diagram() # needs sage.graphs O 0 | | @@ -569,11 +569,11 @@ def affine(self): If possible, this reuses the original label for the special node:: - sage: T = B4.relabel({1:2, 2:3, 3:4, 4:1}); T.dynkin_diagram() + sage: T = B4.relabel({1:2, 2:3, 3:4, 4:1}); T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 2 3 4 1 B4 relabelled by {1: 2, 2: 3, 3: 4, 4: 1} - sage: T.affine().dynkin_diagram() + sage: T.affine().dynkin_diagram() # needs sage.graphs O 0 | | @@ -583,11 +583,11 @@ def affine(self): Otherwise, it chooses a label for the special_node in `0,1,...`:: - sage: T = B4.relabel({1:0, 2:1, 3:2, 4:3}); T.dynkin_diagram() + sage: T = B4.relabel({1:0, 2:1, 3:2, 4:3}); T.dynkin_diagram() # needs sage.graphs O---O---O=>=O 0 1 2 3 B4 relabelled by {1: 0, 2: 1, 3: 2, 4: 3} - sage: T.affine().dynkin_diagram() + sage: T.affine().dynkin_diagram() # needs sage.graphs O 4 | | @@ -645,7 +645,7 @@ def classical(self): EXAMPLES:: sage: A41 = CartanType(['A',4,1]) - sage: A41.dynkin_diagram() + sage: A41.dynkin_diagram() # needs sage.graphs 0 O-----------+ | | @@ -657,7 +657,7 @@ def classical(self): sage: T = A41.relabel({0:1, 1:2, 2:3, 3:4, 4:0}) sage: T ['A', 4, 1] relabelled by {0: 1, 1: 2, 2: 3, 3: 4, 4: 0} - sage: T.dynkin_diagram() + sage: T.dynkin_diagram() # needs sage.graphs 1 O-----------+ | | @@ -669,7 +669,7 @@ def classical(self): sage: T0 = T.classical() sage: T0 ['A', 4] relabelled by {1: 2, 2: 3, 3: 4, 4: 0} - sage: T0.dynkin_diagram() + sage: T0.dynkin_diagram() # needs sage.graphs O---O---O---O 2 3 4 0 A4 relabelled by {1: 2, 2: 3, 3: 4, 4: 0} diff --git a/src/sage/combinat/root_system/type_super_A.py b/src/sage/combinat/root_system/type_super_A.py index 9eda2eeeee5..dedc56b9011 100644 --- a/src/sage/combinat/root_system/type_super_A.py +++ b/src/sage/combinat/root_system/type_super_A.py @@ -599,37 +599,36 @@ def dynkin_diagram(self): EXAMPLES:: - sage: a = CartanType(['A', [4,2]]).dynkin_diagram() - sage: a + sage: a = CartanType(['A', [4,2]]).dynkin_diagram(); a # needs sage.graphs O---O---O---O---X---O---O -4 -3 -2 -1 0 1 2 A4|2 - sage: a.edges(sort=True) + sage: a.edges(sort=True) # needs sage.graphs [(-4, -3, 1), (-3, -4, 1), (-3, -2, 1), (-2, -3, 1), (-2, -1, 1), (-1, -2, 1), (-1, 0, 1), (0, -1, 1), (0, 1, 1), (1, 0, -1), (1, 2, 1), (2, 1, 1)] TESTS:: - sage: a = DynkinDiagram(['A', [0,0]]); a + sage: a = DynkinDiagram(['A', [0,0]]); a # needs sage.graphs X 0 A0|0 - sage: a.vertices(sort=False), a.edges(sort=False) + sage: a.vertices(sort=False), a.edges(sort=False) # needs sage.graphs ([0], []) - sage: a = DynkinDiagram(['A', [1,0]]); a + sage: a = DynkinDiagram(['A', [1,0]]); a # needs sage.graphs O---X -1 0 A1|0 - sage: a.vertices(sort=True), a.edges(sort=True) + sage: a.vertices(sort=True), a.edges(sort=True) # needs sage.graphs ([-1, 0], [(-1, 0, 1), (0, -1, 1)]) - sage: a = DynkinDiagram(['A', [0,1]]); a + sage: a = DynkinDiagram(['A', [0,1]]); a # needs sage.graphs X---O 0 1 A0|1 - sage: a.vertices(sort=True), a.edges(sort=True) + sage: a.vertices(sort=True), a.edges(sort=True) # needs sage.graphs ([0, 1], [(0, 1, 1), (1, 0, -1)]) """ from .dynkin_diagram import DynkinDiagram_class @@ -652,7 +651,7 @@ def cartan_matrix(self): EXAMPLES:: sage: ct = CartanType(['A', [2,3]]) - sage: ct.cartan_matrix() + sage: ct.cartan_matrix() # needs sage.graphs [ 2 -1 0 0 0 0] [-1 2 -1 0 0 0] [ 0 -1 0 1 0 0] @@ -663,16 +662,16 @@ def cartan_matrix(self): TESTS:: sage: ct = CartanType(['A', [0,0]]) - sage: ct.cartan_matrix() + sage: ct.cartan_matrix() # needs sage.graphs [0] sage: ct = CartanType(['A', [1,0]]) - sage: ct.cartan_matrix() + sage: ct.cartan_matrix() # needs sage.graphs [ 2 -1] [-1 0] sage: ct = CartanType(['A', [0,1]]) - sage: ct.cartan_matrix() + sage: ct.cartan_matrix() # needs sage.graphs [ 0 1] [-1 2] """ @@ -696,14 +695,14 @@ def relabel(self, relabelling): EXAMPLES:: sage: ct = CartanType(['A', [1,2]]) - sage: ct.dynkin_diagram() + sage: ct.dynkin_diagram() # needs sage.graphs O---X---O---O -1 0 1 2 A1|2 - sage: f={1:2,2:1,0:0,-1:-1} + sage: f = {1:2, 2:1, 0:0, -1:-1} sage: ct.relabel(f) ['A', [1, 2]] relabelled by {-1: -1, 0: 0, 1: 2, 2: 1} - sage: ct.relabel(f).dynkin_diagram() + sage: ct.relabel(f).dynkin_diagram() # needs sage.graphs O---X---O---O -1 0 2 1 A1|2 relabelled by {-1: -1, 0: 0, 1: 2, 2: 1} diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 126a045327a..5485899d7ae 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -93,7 +93,8 @@ class WeightLatticeRealizations(Category_over_base_ring): sage: L(x) Traceback (most recent call last): ... - TypeError: do not know how to make x (= Lambda[2] + 1/2*Lambda[5]) an element of self (=Ambient lattice of the Root system of type ['A', 7]) + TypeError: do not know how to make x (= Lambda[2] + 1/2*Lambda[5]) + an element of self (=Ambient lattice of the Root system of type ['A', 7]) If `K_1` is a subring of `K_2`, then one could in theory have an embedding from the weight space over `K_1` to any weight lattice @@ -111,7 +112,8 @@ class WeightLatticeRealizations(Category_over_base_ring): sage: L(Lambda[1]) Traceback (most recent call last): ... - TypeError: do not know how to make x (= Lambda[1]) an element of self (=Ambient space of the Root system of type ['A', 7]) + TypeError: do not know how to make x (= Lambda[1]) an element + of self (=Ambient space of the Root system of type ['A', 7]) """ @cached_method @@ -243,12 +245,17 @@ def _test_weight_lattice_realization(self, **options): EXAMPLES:: - sage: RootSystem(['A',3]).weight_lattice()._test_weight_lattice_realization() + sage: RootSystem(['A',3]).weight_lattice()._test_weight_lattice_realization() # needs sage.graphs """ from sage.rings.integer_ring import ZZ tester = self._tester(**options) - Lambda = self.fundamental_weights() - alphacheck = self.simple_coroots() + + try: + Lambda = self.fundamental_weights() + alphacheck = self.simple_coroots() + except ImportError: + return + tester.assertEqual(tuple(Lambda.keys()), self.index_set()) # Check the consistency between simple_root and simple_roots @@ -291,7 +298,10 @@ def _test_weight_lattice_realization(self, **options): tester.assertTrue(self.rho().is_dominant()) if self.root_system.is_finite() and self.root_system.is_irreducible(): - tester.assertTrue(self.highest_root().is_dominant()) + try: + tester.assertTrue(self.highest_root().is_dominant()) + except ImportError: # when sage.graphs is missing (Dynkin diagram) + pass @cached_method def fundamental_weights(self): @@ -320,23 +330,23 @@ def simple_root(self, i): EXAMPLES: Since all the weight lattice realizations in Sage currently - implement a simple_root method, we have to call this one by + implement a ``simple_root`` method, we have to call this one by hand:: sage: from sage.combinat.root_system.weight_lattice_realizations import WeightLatticeRealizations sage: simple_root = WeightLatticeRealizations(QQ).parent_class.simple_root.f sage: L = RootSystem("A3").ambient_space() - sage: simple_root(L, 1) + sage: simple_root(L, 1) # needs sage.graphs (1, -1, 0, 0) - sage: simple_root(L, 2) + sage: simple_root(L, 2) # needs sage.graphs (0, 1, -1, 0) - sage: simple_root(L, 3) + sage: simple_root(L, 3) # needs sage.graphs (1, 1, 2, 0) Note that this last root differs from the one implemented in ``L`` by a multiple of the vector ``(1,1,1,1)``:: - sage: L.simple_roots() + sage: L.simple_roots() # needs sage.graphs Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)} This is a harmless artefact of the `SL` versus `GL` @@ -416,16 +426,16 @@ def reduced_word_of_alcove_morphism(self, f): coweight lattice:: sage: R = RootSystem(["A",2,1]).weight_lattice() - sage: alpha = R.simple_roots() + sage: alpha = R.simple_roots() # needs sage.graphs sage: Lambda = R.fundamental_weights() We consider first translations by elements of the root lattice:: - sage: R.reduced_word_of_alcove_morphism(alpha[0].translation) + sage: R.reduced_word_of_alcove_morphism(alpha[0].translation) # needs sage.graphs [1, 2, 1, 0] - sage: R.reduced_word_of_alcove_morphism(alpha[1].translation) + sage: R.reduced_word_of_alcove_morphism(alpha[1].translation) # needs sage.graphs [0, 2, 0, 1] - sage: R.reduced_word_of_alcove_morphism(alpha[2].translation) + sage: R.reduced_word_of_alcove_morphism(alpha[2].translation) # needs sage.graphs [0, 1, 0, 2] We continue with translations by elements of the classical @@ -434,9 +444,9 @@ def reduced_word_of_alcove_morphism(self, f): sage: omega1 = Lambda[1] - Lambda[0] sage: omega2 = Lambda[2] - Lambda[0] - sage: R.reduced_word_of_alcove_morphism(omega1.translation) + sage: R.reduced_word_of_alcove_morphism(omega1.translation) # needs sage.graphs [0, 2] - sage: R.reduced_word_of_alcove_morphism(omega2.translation) + sage: R.reduced_word_of_alcove_morphism(omega2.translation) # needs sage.graphs [0, 1] The following tests ensure that the code agrees with the tables @@ -444,6 +454,7 @@ def reduced_word_of_alcove_morphism(self, f): TESTS:: + sage: # needs sage.graphs sage: R = RootSystem(['A',5,1]).weight_lattice() sage: alpha = R.simple_roots() sage: Lambda = R.fundamental_weights() @@ -453,6 +464,7 @@ def reduced_word_of_alcove_morphism(self, f): sage: R.reduced_word_of_alcove_morphism(alpha[0].translation) [1, 2, 3, 4, 5, 4, 3, 2, 1, 0] + sage: # needs sage.graphs sage: R = RootSystem(['C',3,1]).weight_lattice() sage: alpha = R.simple_roots() sage: Lambda = R.fundamental_weights() @@ -465,15 +477,18 @@ def reduced_word_of_alcove_morphism(self, f): [0, 1, 0, 2, 1, 3, 2, 1, 3, 2] sage: R.reduced_word_of_alcove_morphism(omega3.translation) [0, 1, 0, 2, 1, 0] + + sage: # needs sage.libs.gap sage: W = WeylGroup(['C',3,1]) sage: s = W.simple_reflections() sage: w = s[0]*s[1]*s[2]*s[3]*s[2] - sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega2.translation)) == w*w + sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega2.translation)) == w*w # needs sage.graphs True sage: w = s[0]*s[1]*s[2]*s[0]*s[1]*s[0] - sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega3.translation)) == w + sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega3.translation)) == w # needs sage.graphs True + sage: # needs sage.graphs sage: R = RootSystem(['D',4,1]).weight_lattice() sage: Lambda = R.fundamental_weights() sage: omega1 = Lambda[1] - Lambda[0] @@ -488,24 +503,28 @@ def reduced_word_of_alcove_morphism(self, f): [0, 2, 1, 4, 2, 0] sage: R.reduced_word_of_alcove_morphism(omega4.translation) [0, 2, 1, 3, 2, 0] + + sage: # needs sage.libs.gap sage: W = WeylGroup(['D',4,1]) sage: s = W.simple_reflections() sage: w = s[0]*s[2]*s[3]*s[4]*s[2] sage: w1= s[1]*s[2]*s[3]*s[4]*s[2] - sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega2.translation)) == w*w1 + sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega2.translation)) == w*w1 # needs sage.graphs True sage: R = RootSystem(['D',5,1]).weight_lattice() sage: Lambda = R.fundamental_weights() sage: omega1 = Lambda[1] - Lambda[0] sage: omega2 = Lambda[2] - 2*Lambda[0] - sage: R.reduced_word_of_alcove_morphism(omega1.translation) + sage: R.reduced_word_of_alcove_morphism(omega1.translation) # needs sage.graphs [0, 2, 3, 4, 5, 3, 2, 0] + + sage: # needs sage.libs.gap sage: W = WeylGroup(['D',5,1]) sage: s = W.simple_reflections() sage: w = s[0]*s[2]*s[3]*s[4]*s[5]*s[3]*s[2] sage: w1= s[1]*s[2]*s[3]*s[4]*s[5]*s[3]*s[2] - sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega2.translation)) == w*w1 + sage: W.from_reduced_word(R.reduced_word_of_alcove_morphism(omega2.translation)) == w*w1 # needs sage.graphs True """ return f(self.rho()).reduced_word() @@ -526,12 +545,13 @@ def dynkin_diagram_automorphism_of_alcove_morphism(self, f): EXAMPLES:: sage: R = RootSystem(["A",2,1]).weight_lattice() - sage: alpha = R.simple_roots() + sage: alpha = R.simple_roots() # needs sage.graphs sage: Lambda = R.fundamental_weights() Translations by elements of the root lattice induce a trivial Dynkin diagram automorphism:: + sage: # needs sage.graphs sage: R.dynkin_diagram_automorphism_of_alcove_morphism(alpha[0].translation) {0: 0, 1: 1, 2: 2} sage: R.dynkin_diagram_automorphism_of_alcove_morphism(alpha[1].translation) @@ -545,16 +565,19 @@ def dynkin_diagram_automorphism_of_alcove_morphism(self, f): sage: omega1 = Lambda[1] - Lambda[0] sage: omega2 = Lambda[2] - Lambda[0] + sage: # needs sage.graphs sage: R.dynkin_diagram_automorphism_of_alcove_morphism(omega1.translation) {0: 1, 1: 2, 2: 0} sage: R.dynkin_diagram_automorphism_of_alcove_morphism(omega2.translation) {0: 2, 1: 0, 2: 1} + sage: # needs sage.graphs sage: R = RootSystem(['C',2,1]).weight_lattice() sage: alpha = R.simple_roots() sage: R.dynkin_diagram_automorphism_of_alcove_morphism(alpha[1].translation) {0: 2, 1: 1, 2: 0} + sage: # needs sage.graphs sage: R = RootSystem(['D',5,1]).weight_lattice() sage: Lambda = R.fundamental_weights() sage: omega1 = Lambda[1] - Lambda[0] @@ -597,6 +620,7 @@ def reduced_word_of_translation(self, t): EXAMPLES:: + sage: # needs sage.graphs sage: R = RootSystem(["A",2,1]).weight_lattice() sage: alpha = R.simple_roots() sage: R.reduced_word_of_translation(alpha[1]) @@ -610,21 +634,20 @@ def reduced_word_of_translation(self, t): sage: Lambda = R.fundamental_weights() sage: omega1 = Lambda[1] - Lambda[0] sage: omega2 = Lambda[2] - 2*Lambda[0] - sage: R.reduced_word_of_translation(omega1) + sage: R.reduced_word_of_translation(omega1) # needs sage.graphs [0, 2, 3, 4, 5, 3, 2, 0] - sage: R.reduced_word_of_translation(omega2) + sage: R.reduced_word_of_translation(omega2) # needs sage.graphs [0, 2, 1, 3, 2, 4, 3, 5, 3, 2, 1, 4, 3, 2] A non simply laced case:: sage: R = RootSystem(["C",2,1]).weight_lattice() sage: Lambda = R.fundamental_weights() - sage: c = R.cartan_type().translation_factors() - sage: c + sage: c = R.cartan_type().translation_factors(); c # needs sage.graphs Finite family {0: 1, 1: 2, 2: 1} - sage: R.reduced_word_of_translation((Lambda[1]-Lambda[0]) * c[1]) + sage: R.reduced_word_of_translation((Lambda[1]-Lambda[0]) * c[1]) # needs sage.graphs [0, 1, 2, 1] - sage: R.reduced_word_of_translation((Lambda[2]-Lambda[0]) * c[2]) + sage: R.reduced_word_of_translation((Lambda[2]-Lambda[0]) * c[2]) # needs sage.graphs [0, 1, 0] See also :meth:`_test_reduced_word_of_translation`. @@ -648,14 +671,17 @@ def _test_reduced_word_of_translation(self, elements=None, **options): EXAMPLES:: sage: R = RootSystem(['D',4,1]).weight_lattice() - sage: R._test_reduced_word_of_translation() + sage: R._test_reduced_word_of_translation() # needs sage.graphs See the documentation for :class:`TestSuite` for more information. """ tester = self._tester(**options) if not self.cartan_type().is_affine(): # won't be necessary anymore once root systems are categorified return - alpha = self.simple_roots() + try: + alpha = self.simple_roots() + except ImportError: # when sage.graphs is not available + return Lambda = self.fundamental_weights() rho = self.rho() G = self.dynkin_diagram() @@ -746,15 +772,15 @@ def signs_of_alcovewalk(self, walk): EXAMPLES:: sage: L = RootSystem(['C',2,1]).weight_lattice() - sage: L.signs_of_alcovewalk([1,2,0,1,2,1,2,0,1,2]) + sage: L.signs_of_alcovewalk([1,2,0,1,2,1,2,0,1,2]) # needs sage.libs.gap [-1, -1, 1, -1, 1, 1, 1, 1, 1, 1] sage: L = RootSystem(['A',2,1]).weight_lattice() - sage: L.signs_of_alcovewalk([0,1,2,1,2,0,1,2,0,1,2,0]) + sage: L.signs_of_alcovewalk([0,1,2,1,2,0,1,2,0,1,2,0]) # needs sage.libs.gap [1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1] sage: L = RootSystem(['B',2,1]).coweight_lattice() - sage: L.signs_of_alcovewalk([0,1,2,0,1,2]) + sage: L.signs_of_alcovewalk([0,1,2,0,1,2]) # needs sage.libs.gap [1, -1, 1, -1, 1, 1] .. WARNING:: @@ -790,10 +816,10 @@ def rho_classical(self): EXAMPLES:: - sage: RootSystem(['C',4,1]).weight_lattice().rho_classical() + sage: RootSystem(['C',4,1]).weight_lattice().rho_classical() # needs sage.graphs -4*Lambda[0] + Lambda[1] + Lambda[2] + Lambda[3] + Lambda[4] sage: L = RootSystem(['D',4,1]).weight_lattice() - sage: L.rho_classical().scalar(L.null_coroot()) + sage: L.rho_classical().scalar(L.null_coroot()) # needs sage.graphs 0 .. WARNING:: @@ -801,10 +827,10 @@ def rho_classical(self): In affine type BC dual, this does not live in the weight lattice:: sage: L = CartanType(["BC",2,2]).dual().root_system().weight_space() - sage: L.rho_classical() + sage: L.rho_classical() # needs sage.graphs -3/2*Lambda[0] + Lambda[1] + Lambda[2] sage: L = CartanType(["BC",2,2]).dual().root_system().weight_lattice() - sage: L.rho_classical() + sage: L.rho_classical() # needs sage.graphs Traceback (most recent call last): ... ValueError: 5 is not divisible by 2 @@ -828,6 +854,7 @@ def embed_at_level(self, x, level=1): EXAMPLES:: + sage: # needs sage.graphs sage: L = RootSystem(["B",3,1]).weight_space() sage: L0 = L.classical() sage: alpha = L0.simple_roots() @@ -860,7 +887,7 @@ def weyl_dimension(self, highest_weight): 20 sage: P = RootSystem(['C',2]).weight_lattice() sage: La = P.basis() - sage: P.weyl_dimension(La[1]+La[2]) + sage: P.weyl_dimension(La[1]+La[2]) # needs sage.graphs 16 sage: type(RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0])) @@ -899,24 +926,24 @@ def _symmetric_form_matrix(self): EXAMPLES:: sage: P = RootSystem(['B',2]).weight_lattice() - sage: P._symmetric_form_matrix + sage: P._symmetric_form_matrix # needs sage.graphs [2 1] [1 1] sage: P = RootSystem(['C',2]).weight_lattice() - sage: P._symmetric_form_matrix + sage: P._symmetric_form_matrix # needs sage.graphs [1 1] [1 2] sage: P = RootSystem(['C',2,1]).weight_lattice() - sage: P._symmetric_form_matrix + sage: P._symmetric_form_matrix # needs sage.graphs [0 0 0 1] [0 1 1 1] [0 1 2 1] [1 1 1 0] sage: P = RootSystem(['A',4,2]).weight_lattice() - sage: P._symmetric_form_matrix + sage: P._symmetric_form_matrix # needs sage.graphs [ 0 0 0 1/2] [ 0 2 2 1] [ 0 2 4 1] @@ -967,6 +994,7 @@ def symmetric_form(self, la): EXAMPLES:: + sage: # needs sage.graphs sage: P = RootSystem(['C',2]).weight_lattice() sage: al = P.simple_roots() sage: al[1].symmetric_form(al[1]) @@ -981,6 +1009,7 @@ def symmetric_form(self, la): ....: for i in P.index_set() for j in P.index_set()) True + sage: # needs sage.graphs sage: P = RootSystem(['C',2,1]).weight_lattice(extended=True) sage: al = P.simple_roots() sage: al[1].symmetric_form(al[1]) @@ -1004,9 +1033,9 @@ def symmetric_form(self, la): sage: P = RootSystem(['C',2,1]).weight_lattice() sage: Q = RootSystem(['C',2,1]).root_lattice() - sage: al = P.simple_roots() - sage: alQ = Q.simple_roots() - sage: all(al[i].symmetric_form(al[j]) == alQ[i].symmetric_form(alQ[j]) + sage: al = P.simple_roots() # needs sage.graphs + sage: alQ = Q.simple_roots() # needs sage.graphs + sage: all(al[i].symmetric_form(al[j]) == alQ[i].symmetric_form(alQ[j]) # needs sage.graphs ....: for i in P.index_set() for j in P.index_set()) True @@ -1015,7 +1044,7 @@ def symmetric_form(self, la): lattice:: sage: La = P.basis() - sage: [La[0].symmetric_form(al) for al in P.simple_roots()] + sage: [La[0].symmetric_form(al) for al in P.simple_roots()] # needs sage.graphs [0, 0, 0] TESTS: @@ -1023,8 +1052,8 @@ def symmetric_form(self, la): We check that `A_{2n}^{(2)}` has 3 different root lengths:: sage: P = RootSystem(['A',4,2]).weight_lattice() - sage: al = P.simple_roots() - sage: [al[i].symmetric_form(al[i]) for i in P.index_set()] + sage: al = P.simple_roots() # needs sage.graphs + sage: [al[i].symmetric_form(al[i]) for i in P.index_set()] # needs sage.graphs [2, 4, 8] Check that :trac:`31410` is fixed, and the symmetric form @@ -1043,7 +1072,8 @@ def symmetric_form(self, la): ....: rho = 1/2*sum(P) ....: return [beta.symmetric_form(rho) for beta in P] - sage: all(s1(ct) == s2(ct) for ct in CartanType.samples(finite=True, crystallographic=True)) + sage: all(s1(ct) == s2(ct) # needs sage.graphs + ....: for ct in CartanType.samples(finite=True, crystallographic=True)) True """ diff --git a/src/sage/combinat/root_system/weight_space.py b/src/sage/combinat/root_system/weight_space.py index 9e700a26f5a..8a5118714c7 100644 --- a/src/sage/combinat/root_system/weight_space.py +++ b/src/sage/combinat/root_system/weight_space.py @@ -40,12 +40,14 @@ class WeightSpace(CombinatorialFreeModule): sage: Q = RootSystem(['A', 3]).weight_lattice(); Q Weight lattice of the Root system of type ['A', 3] - sage: Q.simple_roots() - Finite family {1: 2*Lambda[1] - Lambda[2], 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], 3: -Lambda[2] + 2*Lambda[3]} + sage: Q.simple_roots() # needs sage.graphs + Finite family {1: 2*Lambda[1] - Lambda[2], + 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], + 3: -Lambda[2] + 2*Lambda[3]} sage: Q = RootSystem(['A', 3, 1]).weight_lattice(); Q Weight lattice of the Root system of type ['A', 3, 1] - sage: Q.simple_roots() + sage: Q.simple_roots() # needs sage.graphs Finite family {0: 2*Lambda[0] - Lambda[1] - Lambda[3], 1: -Lambda[0] + 2*Lambda[1] - Lambda[2], 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], @@ -54,12 +56,12 @@ class WeightSpace(CombinatorialFreeModule): For infinite types, the Cartan matrix is singular, and therefore the embedding of the root lattice is not faithful:: - sage: sum(Q.simple_roots()) + sage: sum(Q.simple_roots()) # needs sage.graphs 0 In particular, the null root is zero:: - sage: Q.null_root() + sage: Q.null_root() # needs sage.graphs 0 This can be compensated by extending the basis of the weight space @@ -69,7 +71,7 @@ class WeightSpace(CombinatorialFreeModule): types. In that case, if ``extended`` is set, then the basis of the weight space is extended by an element `\delta`:: - sage: Q = RootSystem(['A', 3, 1]).weight_lattice(extended = True); Q + sage: Q = RootSystem(['A', 3, 1]).weight_lattice(extended=True); Q Extended weight lattice of the Root system of type ['A', 3, 1] sage: Q.basis().keys() {0, 1, 2, 3, 'delta'} @@ -77,7 +79,7 @@ class WeightSpace(CombinatorialFreeModule): And the simple root `\alpha_0` associated to the special node is deformed as follows:: - sage: Q.simple_roots() + sage: Q.simple_roots() # needs sage.graphs Finite family {0: 2*Lambda[0] - Lambda[1] - Lambda[3] + delta, 1: -Lambda[0] + 2*Lambda[1] - Lambda[2], 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], @@ -85,7 +87,7 @@ class WeightSpace(CombinatorialFreeModule): Now, the null root is nonzero:: - sage: Q.null_root() + sage: Q.null_root() # needs sage.graphs delta .. WARNING:: @@ -98,9 +100,9 @@ class WeightSpace(CombinatorialFreeModule): `A_{2n}^{(2)}`). Therefore we currently have:: sage: Q = RootSystem(["A",4,2]).weight_lattice(extended=True) - sage: Q.simple_root(0) + sage: Q.simple_root(0) # needs sage.graphs 2*Lambda[0] - Lambda[1] + delta - sage: Q.null_root() + sage: Q.null_root() # needs sage.graphs 2*delta whereas, with the standard notations from the literature, one @@ -125,15 +127,16 @@ class WeightSpace(CombinatorialFreeModule): extended weight lattice on that basis element can be recovered with:: - sage: Q.null_root()[index] + sage: Q.null_root()[index] # needs sage.graphs 2 TESTS:: - sage: for ct in CartanType.samples(crystallographic=True)+[CartanType(["A",2],["C",5,1])]: + sage: for ct in (CartanType.samples(crystallographic=True) # needs sage.graphs + ....: + [CartanType(["A",2], ["C",5,1])]): ....: TestSuite(ct.root_system().weight_lattice()).run() ....: TestSuite(ct.root_system().weight_space()).run() - sage: for ct in CartanType.samples(affine=True): + sage: for ct in CartanType.samples(affine=True): # needs sage.graphs ....: if ct.is_implemented(): ....: P = ct.root_system().weight_space(extended=True) ....: TestSuite(P).run() @@ -163,9 +166,9 @@ def __init__(self, root_system, base_ring, extended): sage: from sage.combinat.root_system.weight_space import WeightSpace sage: Q = WeightSpace(R, QQ); Q Weight space over the Rational Field of the Root system of type ['A', 4] - sage: TestSuite(Q).run() + sage: TestSuite(Q).run() # needs sage.graphs - sage: WeightSpace(R, QQ, extended = True) + sage: WeightSpace(R, QQ, extended=True) Traceback (most recent call last): ... ValueError: extended weight lattices are only implemented for affine root systems @@ -315,13 +318,13 @@ def simple_root(self, j): EXAMPLES:: sage: L = RootSystem(["C",4]).weight_lattice() - sage: L.simple_root(3) + sage: L.simple_root(3) # needs sage.graphs -Lambda[2] + 2*Lambda[3] - Lambda[4] Its coefficients are given by the corresponding column of the Cartan matrix:: - sage: L.cartan_type().cartan_matrix()[:,2] + sage: L.cartan_type().cartan_matrix()[:,2] # needs sage.graphs [ 0] [-1] [ 2] @@ -329,7 +332,7 @@ def simple_root(self, j): Here are all simple roots:: - sage: L.simple_roots() + sage: L.simple_roots() # needs sage.graphs Finite family {1: 2*Lambda[1] - Lambda[2], 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], 3: -Lambda[2] + 2*Lambda[3] - Lambda[4], @@ -340,7 +343,7 @@ def simple_root(self, j): `\delta`, where `\delta` is the null root:: sage: L = RootSystem(["C",4,1]).weight_lattice(extended=True) - sage: L.simple_root(0) + sage: L.simple_root(0) # needs sage.graphs 2*Lambda[0] - 2*Lambda[1] + delta In fact `\delta` is really `1/a_0` times the null root (see @@ -348,9 +351,9 @@ def simple_root(self, j): but this only makes a difference in type `BC`:: sage: L = RootSystem(CartanType(["BC",4,2])).weight_lattice(extended=True) - sage: L.simple_root(0) + sage: L.simple_root(0) # needs sage.graphs 2*Lambda[0] - Lambda[1] + delta - sage: L.null_root() + sage: L.null_root() # needs sage.graphs 2*delta .. SEEALSO:: @@ -373,11 +376,11 @@ def _repr_term(self, m): EXAMPLES:: sage: L = RootSystem(["C",4,1]).weight_lattice(extended=True) - sage: L.simple_root(0) # indirect doctest + sage: L.simple_root(0) # indirect doctest # needs sage.graphs 2*Lambda[0] - 2*Lambda[1] + delta sage: L = RootSystem(["C",4,1]).coweight_lattice(extended=True) - sage: L.simple_root(0) # indirect doctest + sage: L.simple_root(0) # indirect doctest # needs sage.graphs 2*Lambdacheck[0] - Lambdacheck[1] + deltacheck """ if m == "delta": @@ -391,11 +394,11 @@ def _latex_term(self, m): EXAMPLES:: sage: L = RootSystem(["C",4,1]).weight_lattice(extended=True) - sage: latex(L.simple_root(0)) # indirect doctest + sage: latex(L.simple_root(0)) # indirect doctest # needs sage.graphs 2 \Lambda_{0} - 2 \Lambda_{1} + \delta sage: L = RootSystem(["C",4,1]).coweight_lattice(extended=True) - sage: latex(L.simple_root(0)) # indirect doctest + sage: latex(L.simple_root(0)) # indirect doctest # needs sage.graphs 2 \Lambda^\vee_{0} - \Lambda^\vee_{1} + \delta^\vee """ if m == "delta": @@ -494,12 +497,13 @@ def scalar(self, lambdacheck): won't be the job of this method:: sage: R = RootSystem(["A",3]) - sage: alpha = R.weight_space().roots() - sage: alphacheck = R.coweight_space().roots() - sage: alpha[1].scalar(alphacheck[1]) + sage: alpha = R.weight_space().roots() # needs sage.graphs + sage: alphacheck = R.coweight_space().roots() # needs sage.graphs + sage: alpha[1].scalar(alphacheck[1]) # needs sage.graphs Traceback (most recent call last): ... - ValueError: -Lambdacheck[1] + 2*Lambdacheck[2] - Lambdacheck[3] is not in the coroot space + ValueError: -Lambdacheck[1] + 2*Lambdacheck[2] - Lambdacheck[3] + is not in the coroot space """ # TODO: Find some better test if lambdacheck not in self.parent().coroot_lattice() and lambdacheck not in self.parent().coroot_space(): @@ -519,22 +523,22 @@ def is_dominant(self): sage: W = RootSystem(['A',3]).weight_space() sage: Lambda = W.basis() - sage: w = Lambda[1]+Lambda[3] + sage: w = Lambda[1] + Lambda[3] sage: w.is_dominant() True - sage: w = Lambda[1]-Lambda[2] + sage: w = Lambda[1] - Lambda[2] sage: w.is_dominant() False In the extended affine weight lattice, 'delta' is orthogonal to the positive coroots, so adding or subtracting it should not - effect dominance :: + affect dominance :: sage: P = RootSystem(['A',2,1]).weight_lattice(extended=true) sage: Lambda = P.fundamental_weights() - sage: delta = P.null_root() - sage: w = Lambda[1]-delta - sage: w.is_dominant() + sage: delta = P.null_root() # needs sage.graphs + sage: w = Lambda[1] - delta # needs sage.graphs + sage: w.is_dominant() # needs sage.graphs True """ diff --git a/src/sage/combinat/root_system/weyl_characters.py b/src/sage/combinat/root_system/weyl_characters.py index 94170220217..51baa89b661 100644 --- a/src/sage/combinat/root_system/weyl_characters.py +++ b/src/sage/combinat/root_system/weyl_characters.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups sage.modules """ Weyl Character Rings """ diff --git a/src/sage/combinat/root_system/weyl_group.py b/src/sage/combinat/root_system/weyl_group.py index 52ab428098b..b44a333455d 100644 --- a/src/sage/combinat/root_system/weyl_group.py +++ b/src/sage/combinat/root_system/weyl_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups sage.modules """ Weyl Groups @@ -16,14 +17,14 @@ sage: w = WeylGroup(['A',3]) sage: d = w.cayley_graph(); d Digraph on 24 vertices - sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03) # optional - sage.plot + sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03) # needs sage.plot The Cayley graph of the Weyl Group of type ['D', 4]:: sage: w = WeylGroup(['D',4]) sage: d = w.cayley_graph(); d Digraph on 192 vertices - sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03) # long time (less than one minute) # optional - sage.plot + sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03) # long time (less than one minute), needs sage.plot .. TODO:: @@ -76,6 +77,7 @@ def WeylGroup(x, prefix=None, implementation='matrix'): to products of simple reflections - ``implementation`` -- one of the following: + * ``'matrix'`` - as matrices acting on a root system * ``"permutation"`` - as a permutation group acting on the roots diff --git a/src/sage/combinat/rsk.py b/src/sage/combinat/rsk.py index db02acca89e..1a4ae2e548f 100644 --- a/src/sage/combinat/rsk.py +++ b/src/sage/combinat/rsk.py @@ -2955,7 +2955,7 @@ def _backward_format_output(self, obj1, obj2, output): if j == 0: df.append([]) if j > 0 and obj1[j] < obj1[j-1]: - for a in range(obj1[j-1]-obj1[j]): + for _ in range(obj1[j-1]-obj1[j]): df.append([]) df[-1].append(obj2[j]) if obj1: diff --git a/src/sage/combinat/sf/classical.py b/src/sage/combinat/sf/classical.py index efa439beee1..73bf285c14f 100644 --- a/src/sage/combinat/sf/classical.py +++ b/src/sage/combinat/sf/classical.py @@ -17,8 +17,8 @@ # https://www.gnu.org/licenses/ # **************************************************************************** from sage.rings.integer import Integer -from sage.rings.integer_ring import IntegerRing -from sage.rings.rational_field import RationalField +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.combinat.partition import _Partitions @@ -29,9 +29,6 @@ from . import jack from . import orthotriang -ZZ = IntegerRing() -QQ = RationalField() - translate = {'monomial':'MONOMIAL', 'homogeneous':'HOMSYM', 'powersum':'POWSYM', 'elementary':'ELMSYM', 'Schur':'SCHUR'} conversion_functions = {} diff --git a/src/sage/combinat/six_vertex_model.py b/src/sage/combinat/six_vertex_model.py index cbfd004ca35..cec485f23c7 100644 --- a/src/sage/combinat/six_vertex_model.py +++ b/src/sage/combinat/six_vertex_model.py @@ -438,7 +438,7 @@ def __classcall_private__(cls, n, m=None, boundary_conditions=None): cond = [] for dummy in range(2): val = [] - for k in range(m): + for _ in range(m): val.append(bdry) bdry = not bdry cond.append(tuple(val)) diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index fdb5f030790..3c5282eae8e 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -1108,10 +1108,11 @@ def rectify(self, algorithm=None): if algorithm == 'jdt': rect = self - for i in range(mu_size): + for _ in range(mu_size): rect = rect.slide() elif algorithm == 'schensted': - w = [x for row in reversed(self) for x in row if x is not None] + w = [x for row in reversed(self) for x in row + if x is not None] rect = Tableau([]).insert_word(w) else: raise ValueError("algorithm must be 'jdt', 'schensted', or None") diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index ba937db12ff..c3cf9299093 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -600,10 +600,8 @@ def _eval(self, n): sage: [sloane.A000008._eval(n) for n in range(14)] [1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 11, 12, 15, 16] """ - from sage.rings.big_oh import O - R, x = QQ[['x']].objgen() - p = 1/((1-x)*(1-x**2)*(1-x**5)*(1-x**10)+O(x**(n+4))) - return ZZ(p.coefficients()[n]) + from sage.combinat.partition import Partitions + return Partitions(n, parts_in=[1, 2, 5, 10]).cardinality() class A000009(SloaneSequence): @@ -657,7 +655,7 @@ def cf(self): sage: [next(it) for i in range(14)] [1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 15, 18] """ - R, x = QQ['x'].objgen() + _, x = QQ['x'].objgen() k = 0 yield ZZ.one() p = 1 @@ -8327,7 +8325,7 @@ def perm_mh(m, h): for i in range(m): for j in range(n): if i <= j and j <= i + h: - A[i,j] = 1 + A[i, j] = 1 return A.permanent() diff --git a/src/sage/combinat/species/recursive_species.py b/src/sage/combinat/species/recursive_species.py index a361bdfad20..3cd073f9f9c 100644 --- a/src/sage/combinat/species/recursive_species.py +++ b/src/sage/combinat/species/recursive_species.py @@ -230,7 +230,7 @@ def _gs(self, series_ring, base_ring): sage: F = CombinatorialSpecies() sage: F.generating_series() - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series """ if base_ring not in self._generating_series: self._generating_series[base_ring] = series_ring.undefined(valuation=(0 if self._min is None else self._min)) @@ -247,7 +247,7 @@ def _itgs(self, series_ring, base_ring): sage: F = CombinatorialSpecies() sage: F.isotype_generating_series() - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series """ if base_ring not in self._isotype_generating_series: self._isotype_generating_series[base_ring] = series_ring.undefined(valuation=(0 if self._min is None else self._min)) @@ -264,7 +264,7 @@ def _cis(self, series_ring, base_ring): sage: F = CombinatorialSpecies() sage: F.cycle_index_series() - Uninitialized Lazy Laurent Series + Uninitialized Lazy Series """ if base_ring not in self._cycle_index_series: self._cycle_index_series[base_ring] = series_ring.undefined(valuation=(0 if self._min is None else self._min)) @@ -401,6 +401,15 @@ def define(self, x): [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] sage: F.isotype_generating_series()[0:10] [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] + + Check that :issue:`35071` is fixed:: + + sage: X = species.SingletonSpecies() + sage: E = species.SetSpecies(max=3) + sage: B = species.CombinatorialSpecies(min=1) + sage: B.define(X*E(B)) + sage: B.generating_series() + z + z^2 + 3/2*z^3 + 5/2*z^4 + 9/2*z^5 + 17/2*z^6 + 133/8*z^7 + O(z^8) """ if not isinstance(x, GenericCombinatorialSpecies): raise TypeError("x must be a combinatorial species") diff --git a/src/sage/combinat/subword_complex.py b/src/sage/combinat/subword_complex.py index b7489bdf754..de7eefe946e 100644 --- a/src/sage/combinat/subword_complex.py +++ b/src/sage/combinat/subword_complex.py @@ -1131,7 +1131,6 @@ def __init__(self, Q, w, algorithm="inductive"): SimplicialComplex.__init__(self, maximal_faces=Fs, maximality_check=False, category=cat) - self.__custom_name = 'Subword complex' self._W = W try: T = W.coxeter_matrix().coxeter_type() diff --git a/src/sage/combinat/symmetric_group_representations.py b/src/sage/combinat/symmetric_group_representations.py index 5799fa03bcc..ee518756525 100644 --- a/src/sage/combinat/symmetric_group_representations.py +++ b/src/sage/combinat/symmetric_group_representations.py @@ -576,7 +576,7 @@ def _tableau_dict(self): # construct a dictionary pairing vertices with tableau t = StandardTableaux(self._partition).last() tableau_dict = {self._yang_baxter_graph.root(): t} - for (u, w, (i, beta)) in self._yang_baxter_graph._edges_in_bfs(): + for u, w, (i, _) in self._yang_baxter_graph._edges_in_bfs(): # TODO: improve the following si = PermutationConstructor((i, i + 1)) tableau_dict[w] = Tableau([[si(b) for b in row] diff --git a/src/sage/combinat/tableau_tuple.py b/src/sage/combinat/tableau_tuple.py index ce813f341c9..fb99c185e8e 100644 --- a/src/sage/combinat/tableau_tuple.py +++ b/src/sage/combinat/tableau_tuple.py @@ -2661,11 +2661,11 @@ def an_element(self): """ if self.size() == 0: return self.element_class(self, [[] for _ in range(self.level())]) - else: - tab = [[[m for m in range(1, self.size() + 1)]]] - for s in range(self.level() - 1): - tab.append([]) - return self.element_class(self, tab) + + tab = [[[m for m in range(1, self.size() + 1)]]] + for _ in range(self.level() - 1): + tab.append([]) + return self.element_class(self, tab) # ------------------------------------------------- diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index 77495f329c0..676a4846b23 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -930,11 +930,11 @@ def canonical(self): sage: (p + (3,4,5)).canonical() Polyomino: [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 1, 1), (1, 2, 0)], Color: deeppink """ - minxyz, maxxyz = self.bounding_box() + minxyz, _ = self.bounding_box() return self - minxyz def canonical_isometric_copies(self, orientation_preserving=True, - mod_box_isometries=False): + mod_box_isometries=False): r""" Return the list of image of ``self`` under isometries of the `n`-cube where the coordinates are all nonnegative and minimal. diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index 55684628cee..e476b756183 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -305,8 +305,8 @@ def coerce(self, other): Otherwise it will attempt to convert ``other`` to the domain of ``self``. If that fails, it will attempt to convert ``self`` to the domain of - ``other``. If both attempts fail, it raises a ``TypeError`` to signal - failure. + ``other``. If both attempts fail, it raises a :class:`TypeError` + to signal failure. EXAMPLES:: diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index af43487a574..b06acd3839e 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -3687,7 +3687,7 @@ def simplify_alphabet_size(self, Z=None): r""" If this morphism is simplifiable, return morphisms `h` and `k` such that this morphism is simplifiable with respect to `h` and `k`, otherwise - raise ``ValueError``. + raise :class:`ValueError`. This method is quite fast if this morphism is non-injective, but very slow if it is injective. diff --git a/src/sage/combinat/words/word_datatypes.pyx b/src/sage/combinat/words/word_datatypes.pyx index 900f86ad51a..57c8079aad6 100644 --- a/src/sage/combinat/words/word_datatypes.pyx +++ b/src/sage/combinat/words/word_datatypes.pyx @@ -696,7 +696,7 @@ cdef class WordDatatype_str(WordDatatype): sage: w.split("32") [word: , word: 30301030, word: , word: 12, word: 30, word: , word: 1] - If the separator is not a string a ValueError is raised:: + If the separator is not a string a :class:`ValueError` is raised:: sage: w = Word("le papa du papa du papa etait un petit pioupiou") sage: w.split(Word(['p','a','p','a'])) diff --git a/src/sage/combinat/yang_baxter_graph.py b/src/sage/combinat/yang_baxter_graph.py index d10a6bc47a5..306e8063f63 100644 --- a/src/sage/combinat/yang_baxter_graph.py +++ b/src/sage/combinat/yang_baxter_graph.py @@ -546,7 +546,7 @@ def relabel_edges(self, edge_dict, inplace=True): from copy import copy Y = copy(self) digraph = Y._digraph - for u, v, i in digraph.edges(sort=True): + for u, v in digraph.edges(sort=False, labels=False): digraph.set_edge_label(u, v, edge_dict[u, v]) if not inplace: return Y diff --git a/src/sage/cpython/_py2_random.py b/src/sage/cpython/_py2_random.py index 795820c6cc7..1cd9532fee4 100644 --- a/src/sage/cpython/_py2_random.py +++ b/src/sage/cpython/_py2_random.py @@ -281,9 +281,9 @@ def sample(self, population, k): population contains repeats, then each occurrence is a possible selection in the sample. - To choose a sample in a range of integers, use xrange as an argument. + To choose a sample in a range of integers, use range as an argument. This is especially fast and space efficient for sampling from a - large population: sample(xrange(10000000), 60) + large population: sample(range(10000000), 60) """ # Sampling without replacement entails tracking either potential diff --git a/src/sage/cpython/cython_metaclass.h b/src/sage/cpython/cython_metaclass.h index da06ab75a6b..ecf7f973c3e 100644 --- a/src/sage/cpython/cython_metaclass.h +++ b/src/sage/cpython/cython_metaclass.h @@ -52,6 +52,16 @@ static CYTHON_INLINE int Sage_PyType_Ready(PyTypeObject* t) if (r < 0) return r; +#if PY_VERSION_HEX >= 0x03050000 + // Cython 3 sets Py_TPFLAGS_HEAPTYPE before calling PyType_Ready, + // and resets just after the call. We need to reset it earlier, + // since otherwise the call to metaclass.__init__ below may have + // illegal memory accesses. + // See also: + // https://github.com/cython/cython/issues/3603 + t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; +#endif + /* Set or get metaclass (the type of t) */ PyTypeObject* metaclass; diff --git a/src/sage/cpython/cython_metaclass.pyx b/src/sage/cpython/cython_metaclass.pyx index 744d6e54791..a8fa92fc1a8 100644 --- a/src/sage/cpython/cython_metaclass.pyx +++ b/src/sage/cpython/cython_metaclass.pyx @@ -19,13 +19,16 @@ file if you are using one). In the extension type (a.k.a. ``cdef class``) for which you want to define a metaclass, define a method ``__getmetaclass__`` with a single -unused argument. This method should return a type to be used as +unused argument, and turn off the Cython directive +``always_allow_keywords``. This method should return a type to be used as metaclass: .. code-block:: cython + cimport cython cimport sage.cpython.cython_metaclass cdef class MyCustomType(): + @cython.always_allow_keywords(False) def __getmetaclass__(_): from foo import MyMetaclass return MyMetaclass @@ -61,10 +64,12 @@ In Python, this would be ``meta.__init__(cls, name, bases, dict)``. EXAMPLES:: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' + ....: cimport cython ....: cimport sage.cpython.cython_metaclass ....: cdef class MyCustomType(): + ....: @cython.always_allow_keywords(False) ....: def __getmetaclass__(_): ....: class MyMetaclass(type): ....: def __init__(*args): @@ -76,9 +81,9 @@ EXAMPLES:: ....: ''') Calling MyMetaclass.__init__(, None, None, None) Calling MyMetaclass.__init__(, None, None, None) - sage: MyCustomType.__class__ # optional - sage.misc.cython + sage: MyCustomType.__class__ # needs sage.misc.cython - sage: class MyPythonType(MyDerivedType): # optional - sage.misc.cython + sage: class MyPythonType(MyDerivedType): # needs sage.misc.cython ....: pass Calling MyMetaclass.__init__(, 'MyPythonType', (,), {...}) @@ -99,10 +104,12 @@ TESTS: Check that a proper exception is raised if ``__getmetaclass__`` returns a non-type:: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' + ....: cimport cython ....: cimport sage.cpython.cython_metaclass ....: cdef class MyCustomType(): + ....: @cython.always_allow_keywords(False) ....: def __getmetaclass__(_): ....: return 2 ....: ''') diff --git a/src/sage/cpython/debug.pyx b/src/sage/cpython/debug.pyx index 6fd9da310c8..986abff2a99 100644 --- a/src/sage/cpython/debug.pyx +++ b/src/sage/cpython/debug.pyx @@ -101,7 +101,7 @@ def getattr_debug(obj, name, default=_no_default): found '__doc__' in dict of got ... 'str'>) returning ... 'str'>) - sage: _ = getattr_debug(gp(1), "log") + sage: _ = getattr_debug(gp(1), "log") # needs sage.libs.pari getattr_debug(obj=1, name='log'): type(obj) = object has __dict__ slot () diff --git a/src/sage/cpython/getattr.pyx b/src/sage/cpython/getattr.pyx index 525ea5aa934..52afed49d64 100644 --- a/src/sage/cpython/getattr.pyx +++ b/src/sage/cpython/getattr.pyx @@ -37,7 +37,7 @@ cdef extern from "Python.h": cdef class AttributeErrorMessage: """ - Tries to emulate the standard Python ``AttributeError`` message. + Tries to emulate the standard Python :class:`AttributeError` message. .. NOTE:: @@ -55,7 +55,7 @@ cdef class AttributeErrorMessage: ... AttributeError: 'sage.rings.integer.Integer' object has no attribute 'bla' sage: x = polygen(ZZ, 'x') - sage: QQ[x].gen().bla # optional - sage.libs.flint + sage: QQ[x].gen().bla # needs sage.libs.flint Traceback (most recent call last): ... AttributeError: 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint' object has no attribute 'bla' @@ -68,7 +68,7 @@ cdef class AttributeErrorMessage: TESTS: - The error message used for the ``AttributeError`` is a unique object + The error message used for the :class:`AttributeError` is a unique object and is changed inplace. This is for reasons of efficiency. Hence, if one really needs the error message as a string, then one should make a copy of its string representation before it changes. :: @@ -240,7 +240,7 @@ cpdef getattr_from_other_class(self, cls, name): - ``name`` -- a string - If self is an instance of cls, raises an ``AttributeError``, to + If self is an instance of cls, raises an :class:`AttributeError`, to avoid a double lookup. This function is intended to be called from __getattr__, and so should not be called if name is an attribute of self. @@ -271,7 +271,7 @@ cpdef getattr_from_other_class(self, cls, name): Caveat: lazy attributes work with extension types only if they allow attribute assignment or have a public attribute - ``__cached_methods`` of type ````. This condition + ``_cached_methods`` of type ````. This condition is satisfied, e.g., by any class that is derived from :class:`Parent`:: @@ -300,7 +300,7 @@ cpdef getattr_from_other_class(self, cls, name): TypeError: descriptor '__weakref__' for 'A' objects doesn't apply to ...'sage.rings.integer.Integer' object - When this occurs, an ``AttributeError`` is raised:: + When this occurs, an :class:`AttributeError` is raised:: sage: getattr_from_other_class(1, A, "__weakref__") Traceback (most recent call last): @@ -367,7 +367,7 @@ cpdef getattr_from_other_class(self, cls, name): # Not a descriptor return attribute # Conditionally defined lazy_attributes don't work well with fake subclasses - # (a TypeError is raised if the lazy attribute is not defined). + # (a :class:`TypeError` is raised if the lazy attribute is not defined). # For the moment, we ignore that when this occurs. # Other descriptors (including __weakref__) also break. try: @@ -407,20 +407,21 @@ def dir_with_other_class(self, *cls): Check that objects without dicts are well handled:: - sage: cython("cdef class A:\n cdef public int a") # optional - sage.misc.cython - sage: cython("cdef class B:\n cdef public int b") # optional - sage.misc.cython - sage: x = A() # optional - sage.misc.cython - sage: x.a = 1 # optional - sage.misc.cython - sage: hasattr(x,'__dict__') # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython("cdef class A:\n cdef public int a") + sage: cython("cdef class B:\n cdef public int b") + sage: x = A() + sage: x.a = 1 + sage: hasattr(x,'__dict__') False - sage: dir_with_other_class(x, B) # optional - sage.misc.cython + sage: dir_with_other_class(x, B) [..., 'a', 'b'] TESTS: Check that :trac:`13043` is fixed:: - sage: len(dir(RIF))==len(set(dir(RIF))) + sage: len(dir(RIF))==len(set(dir(RIF))) # needs sage.rings.real_interval_field True """ ret = set() diff --git a/src/sage/cpython/string.pyx b/src/sage/cpython/string.pyx index eef3f74f335..554a8a128be 100644 --- a/src/sage/cpython/string.pyx +++ b/src/sage/cpython/string.pyx @@ -6,7 +6,7 @@ TESTS: Check that this can be used outside of Sage (see :trac:`25549`):: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: from sage.cpython.string cimport char_to_str ....: print(char_to_str("hello world!")) diff --git a/src/sage/cpython/wrapperdescr.pxd b/src/sage/cpython/wrapperdescr.pxd index d7e67a48ac6..b6775860710 100644 --- a/src/sage/cpython/wrapperdescr.pxd +++ b/src/sage/cpython/wrapperdescr.pxd @@ -39,25 +39,26 @@ cdef inline wrapperbase* get_slotdef(wrapper_descriptor slotwrapper) except NULL TESTS:: - sage: cython( # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython( ....: ''' ....: from sage.cpython.wrapperdescr cimport get_slotdef ....: from cpython.long cimport PyLong_FromVoidPtr ....: def py_get_slotdef(slotwrapper): ....: return PyLong_FromVoidPtr(get_slotdef(slotwrapper)) ....: ''') - sage: py_get_slotdef(object.__init__) # random # optional - sage.misc.cython + sage: py_get_slotdef(object.__init__) # random 140016903442416 - sage: py_get_slotdef(bytes.__lt__) # random # optional - sage.misc.cython + sage: py_get_slotdef(bytes.__lt__) # random 140016903441800 - sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(Integer.__lt__) # optional - sage.misc.cython + sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(Integer.__lt__) True - sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(bytes.__gt__) # optional - sage.misc.cython + sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(bytes.__gt__) False sage: class X(): ....: def __eq__(self, other): ....: return False - sage: py_get_slotdef(X.__eq__) # optional - sage.misc.cython + sage: py_get_slotdef(X.__eq__) Traceback (most recent call last): ... TypeError: Cannot convert ... to wrapper_descriptor diff --git a/src/sage/cpython/wrapperdescr.pyx b/src/sage/cpython/wrapperdescr.pyx index bea0ecd24a8..66c79ca38e2 100644 --- a/src/sage/cpython/wrapperdescr.pyx +++ b/src/sage/cpython/wrapperdescr.pyx @@ -68,8 +68,9 @@ def wrapperdescr_call(slotwrapper, self, *args, **kwds): 54 sage: wrapperdescr_call(Element.__mul__, 7/5, 9) 63/5 - sage: from sage.numerical.mip import MixedIntegerLinearProgram - sage: wrapperdescr_call(type.__call__, MixedIntegerLinearProgram, maximization=False) + sage: from sage.numerical.mip import MixedIntegerLinearProgram # needs sage.numerical.mip + sage: wrapperdescr_call(type.__call__, # needs sage.numerical.mip + ....: MixedIntegerLinearProgram, maximization=False) Mixed Integer Program (no objective, 0 variables, 0 constraints) TESTS:: diff --git a/src/sage/crypto/block_cipher/des.py b/src/sage/crypto/block_cipher/des.py index e0d7f8b0471..08afe715710 100644 --- a/src/sage/crypto/block_cipher/des.py +++ b/src/sage/crypto/block_cipher/des.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules sage.rings.finite_rings r""" DES @@ -77,7 +78,7 @@ from sage.rings.integer_ring import ZZ from sage.modules.free_module_element import vector from sage.rings.finite_rings.finite_field_constructor import GF -from sage.modules.vector_mod2_dense import Vector_mod2_dense +from sage.structure.element import Vector from sage.rings.integer import Integer from sage.crypto.sboxes import DES_S1_1, DES_S1_2, DES_S1_3, DES_S1_4 from sage.crypto.sboxes import DES_S2_1, DES_S2_2, DES_S2_3, DES_S2_4 @@ -511,7 +512,7 @@ def encrypt(self, plaintext, key): sage: des.encrypt(P, K56) == C True """ - if isinstance(plaintext, (list, tuple, Vector_mod2_dense)): + if isinstance(plaintext, (list, tuple, Vector)): inputType = 'vector' elif isinstance(plaintext, (Integer, int)): inputType = 'integer' @@ -568,7 +569,7 @@ def decrypt(self, ciphertext, key): sage: des.decrypt(C, K56).hex() == P True """ - if isinstance(ciphertext, (list, tuple, Vector_mod2_dense)): + if isinstance(ciphertext, (list, tuple, Vector)): inputType = 'vector' elif isinstance(ciphertext, (Integer, int)): inputType = 'integer' @@ -868,7 +869,7 @@ def __call__(self, key): pass a ``masterKey`` value on initialisation. Otherwise you can omit ``masterKey`` and pass a key when you call the object. """ - if isinstance(key, (list, tuple, Vector_mod2_dense)): + if isinstance(key, (list, tuple, Vector)): inputType = 'vector' elif isinstance(key, (Integer, int)): inputType = 'integer' diff --git a/src/sage/crypto/block_cipher/miniaes.py b/src/sage/crypto/block_cipher/miniaes.py index 95fcf1a258c..6eb9568b9fc 100644 --- a/src/sage/crypto/block_cipher/miniaes.py +++ b/src/sage/crypto/block_cipher/miniaes.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules sage.rings.finite_rings r""" Mini-AES diff --git a/src/sage/crypto/block_cipher/present.py b/src/sage/crypto/block_cipher/present.py index 1774e6d5977..6e5605692a1 100644 --- a/src/sage/crypto/block_cipher/present.py +++ b/src/sage/crypto/block_cipher/present.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules sage.rings.finite_rings r""" PRESENT @@ -63,8 +64,8 @@ from sage.rings.integer import Integer from sage.modules.free_module_element import vector from sage.rings.finite_rings.finite_field_constructor import GF +from sage.structure.element import Vector from sage.crypto.sboxes import PRESENT as PRESENTSBOX -from sage.modules.vector_mod2_dense import Vector_mod2_dense def _smallscale_present_linearlayer(nsboxes=16): @@ -417,7 +418,7 @@ def encrypt(self, plaintext, key): \leq 32` and current STATE `b_{63} \dots b_0`, addRoundkey consists of the operation for `0 \leq j \leq 63`, `b_j = b_j \oplus \kappa^i_j`. """ - if isinstance(plaintext, (list, tuple, Vector_mod2_dense)): + if isinstance(plaintext, (list, tuple, Vector)): inputType = 'vector' elif isinstance(plaintext, (Integer, int)): inputType = 'integer' @@ -473,7 +474,7 @@ def decrypt(self, ciphertext, key): sage: present.decrypt(c4, k4) == p4 True """ - if isinstance(ciphertext, (list, tuple, Vector_mod2_dense)): + if isinstance(ciphertext, (list, tuple, Vector)): inputType = 'vector' elif isinstance(ciphertext, (Integer, int)): inputType = 'integer' @@ -773,7 +774,7 @@ def __call__(self, K): pass a ``master_key`` value on initialisation. Otherwise you can omit ``master_key`` and pass a key when you call the object. """ - if isinstance(K, (list, tuple, Vector_mod2_dense)): + if isinstance(K, (list, tuple, Vector)): inputType = 'vector' elif isinstance(K, (Integer, int)): inputType = 'integer' diff --git a/src/sage/crypto/block_cipher/sdes.py b/src/sage/crypto/block_cipher/sdes.py index 02a7a14772c..30b8cf2516c 100644 --- a/src/sage/crypto/block_cipher/sdes.py +++ b/src/sage/crypto/block_cipher/sdes.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.rings.finite_rings r""" Simplified DES diff --git a/src/sage/crypto/boolean_function.pyx b/src/sage/crypto/boolean_function.pyx index 13d0a043ff8..fa99fab5ea3 100644 --- a/src/sage/crypto/boolean_function.pyx +++ b/src/sage/crypto/boolean_function.pyx @@ -10,14 +10,14 @@ and also algebraic immunity. EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: R. = GF(2^8,'a')[] sage: from sage.crypto.boolean_function import BooleanFunction - sage: B = BooleanFunction( x^254 ) # the Boolean function Tr(x^254) - sage: B + sage: B = BooleanFunction(x^254); B # the Boolean function Tr(x^254) Boolean function with 8 variables sage: B.nonlinearity() 112 - sage: B.algebraic_immunity() + sage: B.algebraic_immunity() # needs sage.rings.polynomial.pbori 4 AUTHOR: @@ -32,18 +32,20 @@ AUTHOR: from cysignals.signals cimport sig_check from libc.string cimport memcpy -from sage.structure.sage_object cimport SageObject -from sage.structure.richcmp cimport rich_to_bool -from sage.rings.integer_ring import ZZ -from sage.rings.integer cimport Integer -from sage.rings.finite_rings.finite_field_constructor import GF -from sage.rings.polynomial.pbori.pbori import BooleanPolynomial +from sage.data_structures.bitset_base cimport * +from sage.misc.superseded import deprecated_function_alias from sage.rings.finite_rings.finite_field_base import FiniteField +from sage.rings.finite_rings.finite_field_constructor import GF +from sage.rings.integer cimport Integer +from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_element import Polynomial +from sage.structure.richcmp cimport rich_to_bool +from sage.structure.sage_object cimport SageObject -from sage.misc.superseded import deprecated_function_alias - -from sage.data_structures.bitset_base cimport * +try: + from sage.rings.polynomial.pbori.pbori import BooleanPolynomial +except ImportError: + BooleanPolynomial = () # for details about the implementation of hamming_weight (in .pxd), # walsh_hadamard transform, reed_muller transform, and a lot @@ -61,7 +63,7 @@ cdef walsh_hadamard(long *f, int ldn): sage: from sage.crypto.boolean_function import BooleanFunction sage: B = BooleanFunction([1,0,0,1]) - sage: B.walsh_hadamard_transform() # indirect doctest + sage: B.walsh_hadamard_transform() # indirect doctest (0, 0, 0, -4) """ cdef long n, ldm, m, mh, t1, t2, r, j, u, v @@ -89,11 +91,12 @@ cdef long yellow_code(unsigned long a): EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: R. = BooleanPolynomialRing(3) sage: P = x*y - sage: B = BooleanFunction( P ) - sage: B.truth_table() # indirect doctest + sage: B = BooleanFunction(P) + sage: B.truth_table() # indirect doctest (False, False, False, True, False, False, False, True) """ cdef unsigned long s = (8*sizeof(unsigned long)) >> 1 @@ -122,11 +125,12 @@ cdef reed_muller(mp_limb_t* f, int ldn): EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: R. = BooleanPolynomialRing(3) sage: P = x*y - sage: B = BooleanFunction( P ) - sage: B.truth_table() # indirect doctest + sage: B = BooleanFunction(P) + sage: B.truth_table() # indirect doctest (False, False, False, True, False, False, False, True) """ cdef long n, ldm, m, mh, t1, t2, r, j @@ -154,15 +158,15 @@ cdef class BooleanFunction(SageObject): We can construct a Boolean Function from either: - - an integer - the result is the zero function with ``x`` variables; - - a list - it is expected to be the truth table of the + - an integer -- the result is the zero function with ``x`` variables; + - a list -- it is expected to be the truth table of the result. Therefore it must be of length a power of 2, and its elements are interpreted as Booleans; - - a string - representing the truth table in hexadecimal; - - a Boolean polynomial - the result is the corresponding Boolean function; - - a polynomial P over an extension of GF(2) - the result is - the Boolean function with truth table ``( Tr(P(x)) for x in - GF(2^k) )`` + - a string -- representing the truth table in hexadecimal; + - a Boolean polynomial -- the result is the corresponding Boolean function; + - a polynomial `P` over an extension of `\GF{2}` -- the result is + the Boolean function with truth table ``(Tr(P(x)) for x in + GF(2^k))`` EXAMPLES: @@ -179,10 +183,9 @@ cdef class BooleanFunction(SageObject): note that elements can be of different types:: - sage: B = BooleanFunction([False, sqrt(2)]) - sage: B + sage: B = BooleanFunction([False, sqrt(2)]); B # needs sage.symbolic Boolean function with 1 variable - sage: [b for b in B] + sage: [b for b in B] # needs sage.symbolic [False, True] from a string:: @@ -192,21 +195,20 @@ cdef class BooleanFunction(SageObject): from a :class:`sage.rings.polynomial.pbori.BooleanPolynomial`:: - sage: R. = BooleanPolynomialRing(3) - sage: P = x*y - sage: BooleanFunction( P ) + sage: R. = BooleanPolynomialRing(3) # needs sage.rings.polynomial.pbori + sage: P = x*y # needs sage.rings.polynomial.pbori + sage: BooleanFunction(P) # needs sage.rings.polynomial.pbori Boolean function with 3 variables from a polynomial over a binary field:: - sage: R. = GF(2^8,'a')[] - sage: B = BooleanFunction( x^7 ) - sage: B + sage: R. = GF(2^8,'a')[] # needs sage.rings.finite_rings + sage: B = BooleanFunction(x^7); B # needs sage.rings.finite_rings Boolean function with 8 variables two failure cases:: - sage: BooleanFunction(sqrt(2)) + sage: BooleanFunction(sqrt(2)) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to init the Boolean function @@ -255,29 +257,27 @@ cdef class BooleanFunction(SageObject): note that elements can be of different types:: - sage: B = BooleanFunction([False, sqrt(2)]) - sage: B + sage: B = BooleanFunction([False, sqrt(2)]); B # needs sage.symbolic Boolean function with 1 variable - sage: [b for b in B] + sage: [b for b in B] # needs sage.symbolic [False, True] from a :class:`sage.rings.polynomial.pbori.BooleanPolynomial`:: - sage: R. = BooleanPolynomialRing(3) - sage: P = x*y - sage: BooleanFunction( P ) + sage: R. = BooleanPolynomialRing(3) # needs sage.rings.polynomial.pbori + sage: P = x*y # needs sage.rings.polynomial.pbori + sage: BooleanFunction(P) # needs sage.rings.polynomial.pbori Boolean function with 3 variables from a polynomial over a binary field:: - sage: R. = GF(2^8,'a')[] - sage: B = BooleanFunction( x^7 ) - sage: B + sage: R. = GF(2^8,'a')[] # needs sage.rings.finite_rings + sage: B = BooleanFunction(x^7); B # needs sage.rings.finite_rings Boolean function with 8 variables two failure cases:: - sage: BooleanFunction(sqrt(2)) + sage: BooleanFunction(sqrt(2)) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to init the Boolean function @@ -396,8 +396,8 @@ cdef class BooleanFunction(SageObject): it also corresponds to the addition of algebraic normal forms:: - sage: S = A.algebraic_normal_form() + B.algebraic_normal_form() - sage: (A+B).algebraic_normal_form() == S + sage: S = A.algebraic_normal_form() + B.algebraic_normal_form() # needs sage.rings.polynomial.pbori + sage: (A+B).algebraic_normal_form() == S # needs sage.rings.polynomial.pbori True TESTS:: @@ -428,8 +428,8 @@ cdef class BooleanFunction(SageObject): it also corresponds to the multiplication of algebraic normal forms:: - sage: P = A.algebraic_normal_form() * B.algebraic_normal_form() - sage: (A*B).algebraic_normal_form() == P + sage: P = A.algebraic_normal_form() * B.algebraic_normal_form() # needs sage.rings.polynomial.pbori + sage: (A*B).algebraic_normal_form() == P # needs sage.rings.polynomial.pbori True TESTS:: @@ -499,10 +499,9 @@ cdef class BooleanFunction(SageObject): sage: from sage.crypto.boolean_function import BooleanFunction sage: B = BooleanFunction([0,1,1,0,1,0,1,1]) - sage: P = B.algebraic_normal_form() - sage: P + sage: P = B.algebraic_normal_form(); P # needs sage.rings.polynomial.pbori x0*x1*x2 + x0 + x1*x2 + x1 + x2 - sage: [ P(*ZZ(i).digits(base=2,padto=3)) for i in range(8) ] + sage: [P(*ZZ(i).digits(base=2, padto=3)) for i in range(8)] # needs sage.rings.polynomial.pbori [0, 1, 1, 0, 1, 0, 1, 1] """ cdef bitset_t anf @@ -548,15 +547,16 @@ cdef class BooleanFunction(SageObject): INPUT: a string representing the desired format, can be either - - 'bin' (default) : we return a tuple of Boolean values - - 'int' : we return a tuple of 0 or 1 values - - 'hex' : we return a string representing the truth_table in hexadecimal + - ``'bin'`` (default): we return a tuple of Boolean values + - ``'int'``: we return a tuple of 0 or 1 values + - ``'hex'``: we return a string representing the truth table in hexadecimal EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: R. = BooleanPolynomialRing(3) - sage: B = BooleanFunction( x*y*z + z + y + 1 ) + sage: B = BooleanFunction(x*y*z + z + y + 1) sage: B.truth_table() (True, True, False, False, False, False, True, False) sage: B.truth_table(format='int') @@ -564,9 +564,10 @@ cdef class BooleanFunction(SageObject): sage: B.truth_table(format='hex') '43' - sage: BooleanFunction('00ab').truth_table(format='hex') + sage: BooleanFunction('00ab').truth_table(format='hex') # needs sage.rings.polynomial.pbori '00ab' + sage: # needs sage.rings.polynomial.pbori sage: H = '0abbacadabbacad0' sage: len(H) 16 @@ -703,9 +704,9 @@ cdef class BooleanFunction(SageObject): EXAMPLES:: sage: from sage.crypto.boolean_function import BooleanFunction - sage: R. = GF(2^3,'a')[] - sage: B = BooleanFunction( x^3 ) - sage: B.walsh_hadamard_transform() + sage: R. = GF(2^3,'a')[] # needs sage.rings.finite_rings + sage: B = BooleanFunction(x^3) # needs sage.rings.finite_rings + sage: B.walsh_hadamard_transform() # needs sage.rings.finite_rings (0, -4, 0, 4, 0, 4, 0, 4) """ cdef long *temp @@ -837,8 +838,8 @@ cdef class BooleanFunction(SageObject): correlation immune of order `m`. A Boolean function is said to be correlation immune of order - `m`, if the output of the function is statistically - independent of the combination of any m of its inputs. + `m` if the output of the function is statistically + independent of the combination of any `m` of its inputs. EXAMPLES:: @@ -866,7 +867,7 @@ cdef class BooleanFunction(SageObject): A Boolean function is said to be resilient of order `m` if it is balanced and correlation immune of order `m`. - If the function is not balanced, we return -1. + If the function is not balanced, we return `-1`. EXAMPLES:: @@ -991,17 +992,17 @@ cdef class BooleanFunction(SageObject): INPUT: - ``d`` -- an integer; - - ``dim`` -- a Boolean (default: False), if True, return also + - ``dim`` -- a Boolean (default: ``False``), if ``True``, return also the dimension of the annihilator vector space. EXAMPLES:: sage: from sage.crypto.boolean_function import BooleanFunction sage: f = BooleanFunction("7969817CC5893BA6AC326E47619F5AD0") - sage: f.annihilator(1) is None + sage: f.annihilator(1) is None # needs sage.rings.polynomial.pbori True - sage: g = BooleanFunction( f.annihilator(3) ) - sage: set([ fi*g(i) for i,fi in enumerate(f) ]) + sage: g = BooleanFunction(f.annihilator(3)) # needs sage.rings.polynomial.pbori + sage: set(fi*g(i) for i,fi in enumerate(f)) # needs sage.rings.polynomial.pbori {0} """ # NOTE: this is a toy implementation @@ -1054,8 +1055,8 @@ cdef class BooleanFunction(SageObject): """ Return the algebraic immunity of the Boolean function. - This is the smallest integer `i` such that there exists a non - trivial annihilator for `self` or `~self`. + This is the smallest integer `i` such that there exists a + nontrivial annihilator for ``self`` or ``~self``. INPUT: @@ -1064,15 +1065,17 @@ cdef class BooleanFunction(SageObject): EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: R. = BooleanPolynomialRing(6) sage: B = BooleanFunction(x0*x1 + x1*x2 + x2*x3 + x3*x4 + x4*x5) sage: B.algebraic_immunity(annihilator=True) (2, x0*x1 + x1*x2 + x2*x3 + x3*x4 + x4*x5 + 1) - sage: B[0] +=1 + sage: B[0] += 1 sage: B.algebraic_immunity() 2 + sage: # needs sage.rings.finite_rings sage.rings.polynomial.pbori sage: R. = GF(2^8,'a')[] sage: B = BooleanFunction(x^31) sage: B.algebraic_immunity() @@ -1097,10 +1100,11 @@ cdef class BooleanFunction(SageObject): The algebraic degree of a Boolean function is defined as the degree of its algebraic normal form. Note that the degree of the constant - zero function is defined to be equal to -1. + zero function is defined to be equal to `-1`. EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: B. = BooleanPolynomialRing() sage: f = BooleanFunction(x1*x2 + x1*x2*x3 + x1) @@ -1120,6 +1124,7 @@ cdef class BooleanFunction(SageObject): EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: R. = BooleanPolynomialRing() sage: f = BooleanFunction(x0*x1 + x2 + x3) @@ -1160,7 +1165,7 @@ cdef class BooleanFunction(SageObject): True sage: f.is_linear_structure(7) False - sage: f.is_linear_structure(20) #parameter is out of range + sage: f.is_linear_structure(20) # parameter is out of range Traceback (most recent call last): ... IndexError: index out of range @@ -1174,7 +1179,7 @@ cdef class BooleanFunction(SageObject): Traceback (most recent call last): ... TypeError: input vector must be an element of a vector space with dimension 4 - sage: f.is_linear_structure('X') #failure case + sage: f.is_linear_structure('X') # failure case Traceback (most recent call last): ... TypeError: cannot compute is_linear_structure() using parameter X @@ -1246,6 +1251,7 @@ cdef class BooleanFunction(SageObject): EXAMPLES:: + sage: # needs sage.modules sage: from sage.crypto.boolean_function import BooleanFunction sage: f = BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0]) sage: LS = f.linear_structures() @@ -1281,6 +1287,7 @@ cdef class BooleanFunction(SageObject): EXAMPLES:: + sage: # needs sage.rings.polynomial.pbori sage: from sage.crypto.boolean_function import BooleanFunction sage: f = BooleanFunction([0,1,0,1,0,1,0,1]) sage: f.derivative(1).algebraic_normal_form() @@ -1288,8 +1295,8 @@ cdef class BooleanFunction(SageObject): sage: u = [1,0,0] sage: f.derivative(u).algebraic_normal_form() 1 - sage: v = vector(GF(2), u) - sage: f.derivative(u).algebraic_normal_form() + sage: v = vector(GF(2), u) # needs sage.modules + sage: f.derivative(v).algebraic_normal_form() # needs sage.modules 1 sage: f.derivative(8).algebraic_normal_form() Traceback (most recent call last): @@ -1391,7 +1398,7 @@ def unpickle_BooleanFunction(bool_list): sage: from sage.crypto.boolean_function import BooleanFunction sage: B = BooleanFunction([0,1,1,0]) - sage: loads(dumps(B)) == B # indirect doctest + sage: loads(dumps(B)) == B # indirect doctest True """ return BooleanFunction(bool_list) @@ -1424,7 +1431,7 @@ cdef class BooleanFunctionIterator: sage: from sage.crypto.boolean_function import BooleanFunction sage: B = BooleanFunction(1) - sage: [b for b in B] # indirect doctest + sage: [b for b in B] # indirect doctest [False, False] """ return self diff --git a/src/sage/crypto/cipher.py b/src/sage/crypto/cipher.py index 6d6ed6dd2b3..14e9df6a504 100644 --- a/src/sage/crypto/cipher.py +++ b/src/sage/crypto/cipher.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat """ Ciphers """ diff --git a/src/sage/crypto/classical.py b/src/sage/crypto/classical.py index 132a18cdee0..616dc861652 100644 --- a/src/sage/crypto/classical.py +++ b/src/sage/crypto/classical.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Classical Cryptosystems @@ -45,19 +46,22 @@ # - methods to cryptanalyze the Hill, substitution, transposition, and # Vigenere ciphers +from random import randint + +from sage.arith.misc import inverse_mod, xgcd +from sage.misc.lazy_import import lazy_import from sage.monoids.string_monoid import ( StringMonoid_class, AlphabeticStringMonoid) from sage.monoids.string_monoid_element import StringMonoidElement from sage.monoids.string_ops import strip_encoding -from sage.groups.perm_gps.permgroup_named import SymmetricGroup -from sage.groups.perm_gps.permgroup_element import PermutationGroupElement from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing -from sage.arith.misc import inverse_mod, xgcd -from random import randint -from sage.matrix.matrix_space import MatrixSpace + +lazy_import('sage.groups.perm_gps.permgroup_named', 'SymmetricGroup') +lazy_import('sage.groups.perm_gps.permgroup_element', 'PermutationGroupElement') +lazy_import('sage.matrix.matrix_space', 'MatrixSpace') from .cryptosystem import SymmetricKeyCryptosystem from .classical_cipher import ( @@ -1201,7 +1205,7 @@ def inverse_key(self, a, b): capital letters of the English alphabet, there are 12 such integers relatively prime to `n`:: - sage: euler_phi(A.alphabet_size()) + sage: euler_phi(A.alphabet_size()) # needs sage.libs.pari 12 And here is a list of those integers:: @@ -1285,7 +1289,7 @@ def random_key(self): class HillCryptosystem(SymmetricKeyCryptosystem): r""" - Create a Hill cryptosystem defined by the `m` x `m` matrix space + Create a Hill cryptosystem defined by the `m \times m` matrix space over `\ZZ / N \ZZ`, where `N` is the alphabet size of the string monoid ``S``. @@ -1302,19 +1306,17 @@ class HillCryptosystem(SymmetricKeyCryptosystem): EXAMPLES:: + sage: # needs sage.modules sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) - sage: E + sage: E = HillCryptosystem(S, 3); E Hill cryptosystem on Free alphabetic string monoid on A-Z of block length 3 sage: R = IntegerModRing(26) sage: M = MatrixSpace(R,3,3) - sage: A = M([[1,0,1],[0,1,1],[2,2,3]]) - sage: A + sage: A = M([[1,0,1],[0,1,1],[2,2,3]]); A [1 0 1] [0 1 1] [2 2 3] - sage: e = E(A) - sage: e + sage: e = E(A); e Hill cipher on Free alphabetic string monoid on A-Z of block length 3 sage: e(S("LAMAISONBLANCHE")) JYVKSKQPELAYKPV @@ -1322,8 +1324,8 @@ class HillCryptosystem(SymmetricKeyCryptosystem): TESTS:: sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) - sage: E == loads(dumps(E)) + sage: E = HillCryptosystem(S, 3) # needs sage.modules + sage: E == loads(dumps(E)) # needs sage.modules True """ @@ -1331,7 +1333,7 @@ def __init__(self, S, m): r""" See ``HillCryptosystem`` for full documentation. - Create a Hill cryptosystem defined by the `m` x `m` matrix space + Create a Hill cryptosystem defined by the `m \times m` matrix space over `\ZZ / N \ZZ`, where `N` is the alphabet size of the string monoid ``S``. @@ -1349,8 +1351,7 @@ def __init__(self, S, m): EXAMPLES:: sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) - sage: E + sage: E = HillCryptosystem(S, 3); E # needs sage.modules Hill cryptosystem on Free alphabetic string monoid on A-Z of block length 3 """ if not isinstance(S, StringMonoid_class): @@ -1369,18 +1370,16 @@ def __call__(self, A): EXAMPLES:: + sage: # needs sage.modules sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) - sage: E + sage: E = HillCryptosystem(S,3); E Hill cryptosystem on Free alphabetic string monoid on A-Z of block length 3 sage: M = E.key_space() - sage: A = M([[1,0,1],[0,1,1],[2,2,3]]) - sage: A + sage: A = M([[1,0,1],[0,1,1],[2,2,3]]); A [1 0 1] [0 1 1] [2 2 3] - sage: e = E(A) - sage: e + sage: e = E(A); e Hill cipher on Free alphabetic string monoid on A-Z of block length 3 sage: m = S("LAMAISONBLANCHE") sage: e(m) @@ -1405,10 +1404,9 @@ def _repr_(self): EXAMPLES:: sage: A = AlphabeticStrings() - sage: H = HillCryptosystem(A, 3) - sage: H + sage: H = HillCryptosystem(A, 3); H # needs sage.modules Hill cryptosystem on Free alphabetic string monoid on A-Z of block length 3 - sage: H._repr_() + sage: H._repr_() # needs sage.modules 'Hill cryptosystem on Free alphabetic string monoid on A-Z of block length 3' """ return "Hill cryptosystem on %s of block length %s" % ( @@ -1430,20 +1428,20 @@ def block_length(self): sage: A = AlphabeticStrings() sage: n = randint(1, A.ngens() - 1) - sage: H = HillCryptosystem(A, n) - sage: H.block_length() == n + sage: H = HillCryptosystem(A, n) # needs sage.modules + sage: H.block_length() == n # needs sage.modules True """ return self.key_space().nrows() def random_key(self): - """ + r""" A random key within the key space of this Hill cipher. That is, - generate a random `m` x `m` matrix to be used as a block + generate a random `m \times m` matrix to be used as a block permutation, where `m` is the block length of this Hill cipher. If `n` is the size of the cryptosystem alphabet, then there are `n^{m^2}` possible keys. However the number of valid keys, - i.e. invertible `m` x `m` square matrices, is smaller than + i.e. invertible `m \times m` square matrices, is smaller than `n^{m^2}`. OUTPUT: @@ -1452,6 +1450,7 @@ def random_key(self): EXAMPLES:: + sage: # needs sage.modules sage: A = AlphabeticStrings() sage: n = 3 sage: H = HillCryptosystem(A, n) @@ -1478,7 +1477,7 @@ def inverse_key(self, A): INPUT: - - ``A`` - an invertible matrix of the key space of this Hill cipher + - ``A`` -- an invertible matrix of the key space of this Hill cipher OUTPUT: @@ -1486,8 +1485,9 @@ def inverse_key(self, A): EXAMPLES:: + sage: # needs sage.modules sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) + sage: E = HillCryptosystem(S, 3) sage: A = E.random_key() sage: B = E.inverse_key(A) sage: M = S("LAMAISONBLANCHE") @@ -1519,7 +1519,7 @@ def encoding(self, M): INPUT: - - ``M`` - a string, possibly empty + - ``M`` -- a string, possibly empty OUTPUT: @@ -1529,8 +1529,8 @@ def encoding(self, M): sage: M = "The matrix cipher by Lester S. Hill." sage: A = AlphabeticStrings() - sage: H = HillCryptosystem(A, 7) - sage: H.encoding(M) == A.encoding(M) + sage: H = HillCryptosystem(A, 7) # needs sage.modules + sage: H.encoding(M) == A.encoding(M) # needs sage.modules True """ S = self.cipher_domain() @@ -1547,9 +1547,9 @@ def deciphering(self, A, C): INPUT: - - ``A`` - a key within the key space of this Hill cipher + - ``A`` -- a key within the key space of this Hill cipher - - ``C`` - a string (possibly empty) over the string monoid of this + - ``C`` -- a string (possibly empty) over the string monoid of this Hill cipher OUTPUT: @@ -1558,6 +1558,7 @@ def deciphering(self, A, C): EXAMPLES:: + sage: # needs sage.modules sage: H = HillCryptosystem(AlphabeticStrings(), 3) sage: K = H.random_key() sage: M = H.encoding("Good day, mate! How ya going?") @@ -1585,6 +1586,7 @@ def enciphering(self, A, M): EXAMPLES:: + sage: # needs sage.modules sage: H = HillCryptosystem(AlphabeticStrings(), 3) sage: K = H.random_key() sage: M = H.encoding("Good day, mate! How ya going?") @@ -1595,6 +1597,7 @@ def enciphering(self, A, M): e = self(A) return e(M) + class ShiftCryptosystem(SymmetricKeyCryptosystem): r""" Create a shift cryptosystem. @@ -3258,21 +3261,20 @@ class TranspositionCryptosystem(SymmetricKeyCryptosystem): EXAMPLES:: sage: S = AlphabeticStrings() - sage: E = TranspositionCryptosystem(S,14) - sage: E - Transposition cryptosystem on Free alphabetic string monoid on A-Z of block length 14 - sage: K = [ 14-i for i in range(14) ] - sage: K + sage: E = TranspositionCryptosystem(S,14); E # needs sage.groups + Transposition cryptosystem on + Free alphabetic string monoid on A-Z of block length 14 + sage: K = [14 - i for i in range(14)]; K [14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] - sage: e = E(K) - sage: e(S("THECATINTHEHAT")) + sage: e = E(K) # needs sage.groups + sage: e(S("THECATINTHEHAT")) # needs sage.groups TAHEHTNITACEHT TESTS:: sage: S = AlphabeticStrings() - sage: E = TranspositionCryptosystem(S,14) - sage: E == loads(dumps(E)) + sage: E = TranspositionCryptosystem(S,14) # needs sage.groups + sage: E == loads(dumps(E)) # needs sage.groups True """ @@ -3283,8 +3285,7 @@ def __init__(self, S, n): EXAMPLES:: sage: S = AlphabeticStrings() - sage: E = TranspositionCryptosystem(S,14) - sage: E + sage: E = TranspositionCryptosystem(S,14); E # needs sage.groups Transposition cryptosystem on Free alphabetic string monoid on A-Z of block length 14 """ if not isinstance(S, StringMonoid_class): @@ -3303,15 +3304,13 @@ def __call__(self, K): EXAMPLES:: sage: M = AlphabeticStrings() - sage: E = TranspositionCryptosystem(M,14) - sage: E + sage: E = TranspositionCryptosystem(M,14); E # needs sage.groups Transposition cryptosystem on Free alphabetic string monoid on A-Z of block length 14 - sage: K = [ 14-i for i in range(14) ] - sage: K + sage: K = [14 - i for i in range(14)]; K [14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] - sage: e = E(K) + sage: e = E(K) # needs sage.groups sage: m = M("THECATINTHEHAT") - sage: e(m) + sage: e(m) # needs sage.groups TAHEHTNITACEHT """ G = self.key_space() @@ -3331,10 +3330,9 @@ def _repr_(self): EXAMPLES:: sage: A = AlphabeticStrings() - sage: T = TranspositionCryptosystem(A, 14) - sage: T + sage: T = TranspositionCryptosystem(A, 14); T # needs sage.groups Transposition cryptosystem on Free alphabetic string monoid on A-Z of block length 14 - sage: T._repr_() + sage: T._repr_() # needs sage.groups 'Transposition cryptosystem on Free alphabetic string monoid on A-Z of block length 14' """ return "Transposition cryptosystem on %s of block length %s" % ( @@ -3352,6 +3350,7 @@ def random_key(self): EXAMPLES:: + sage: # needs sage.groups sage: S = AlphabeticStrings() sage: E = TranspositionCryptosystem(S, 14) sage: K = E.random_key() @@ -3372,10 +3371,10 @@ def inverse_key(self, K, check=True): INPUT: - - ``K`` - a key belonging to the key space of this transposition + - ``K`` -- a key belonging to the key space of this transposition cipher - - ``check`` - bool (default: ``True``); check that ``K`` belongs to + - ``check`` -- bool (default: ``True``); check that ``K`` belongs to the key space of this cryptosystem. OUTPUT: @@ -3384,6 +3383,7 @@ def inverse_key(self, K, check=True): EXAMPLES:: + sage: # needs sage.groups sage: S = AlphabeticStrings() sage: E = TranspositionCryptosystem(S, 14) sage: K = E.random_key() @@ -3410,7 +3410,7 @@ def encoding(self, M): INPUT: - - ``M`` - a string, possibly empty + - ``M`` -- a string, possibly empty OUTPUT: @@ -3420,8 +3420,8 @@ def encoding(self, M): sage: M = "Transposition cipher is not about matrix transpose." sage: A = AlphabeticStrings() - sage: T = TranspositionCryptosystem(A, 11) - sage: T.encoding(M) == A.encoding(M) + sage: T = TranspositionCryptosystem(A, 11) # needs sage.groups + sage: T.encoding(M) == A.encoding(M) # needs sage.groups True """ S = self.cipher_domain() @@ -3438,10 +3438,10 @@ def deciphering(self, K, C): INPUT: - - ``K`` - a key belonging to the key space of this transposition + - ``K`` -- a key belonging to the key space of this transposition cipher - - ``C`` - a string (possibly empty) over the string monoid of this + - ``C`` -- a string (possibly empty) over the string monoid of this cryptosystem. OUTPUT: @@ -3450,6 +3450,7 @@ def deciphering(self, K, C): EXAMPLES:: + sage: # needs sage.groups sage: T = TranspositionCryptosystem(AlphabeticStrings(), 14) sage: K = T.random_key() sage: M = T.encoding("The cat in the hat.") @@ -3465,10 +3466,10 @@ def enciphering(self, K, M): INPUT: - - ``K`` - a key belonging to the key space of this transposition + - ``K`` -- a key belonging to the key space of this transposition cipher - - ``M`` - a string (possibly empty) over the string monoid of this + - ``M`` -- a string (possibly empty) over the string monoid of this cryptosystem OUTPUT: @@ -3477,6 +3478,7 @@ def enciphering(self, K, M): EXAMPLES:: + sage: # needs sage.groups sage: T = TranspositionCryptosystem(AlphabeticStrings(), 14) sage: K = T.random_key() sage: M = T.encoding("The cat in the hat.") @@ -3486,6 +3488,7 @@ def enciphering(self, K, M): e = self(K) return e(M) + class VigenereCryptosystem(SymmetricKeyCryptosystem): """ Create a Vigenere cryptosystem of block length ``n``. @@ -3494,7 +3497,7 @@ class VigenereCryptosystem(SymmetricKeyCryptosystem): - ``S``-- a string monoid over some alphabet - - ``n`` - integer `> 0`; block length of an encryption/decryption key + - ``n`` -- integer `> 0`; block length of an encryption/decryption key OUTPUT: @@ -3621,7 +3624,7 @@ def inverse_key(self, K): INPUT: - - ``K`` - a key within the key space of this Vigenere cryptosystem + - ``K`` -- a key within the key space of this Vigenere cryptosystem OUTPUT: @@ -3653,7 +3656,7 @@ def encoding(self, M): INPUT: - - ``M`` - a string, possibly empty + - ``M`` -- a string, possibly empty OUTPUT: @@ -3681,9 +3684,9 @@ def deciphering(self, K, C): INPUT: - - ``K`` - a key belonging to the key space of this Vigenere cipher + - ``K`` -- a key belonging to the key space of this Vigenere cipher - - ``C`` - a string (possibly empty) over the string monoid of this + - ``C`` -- a string (possibly empty) over the string monoid of this cryptosystem OUTPUT: @@ -3707,9 +3710,9 @@ def enciphering(self, K, M): INPUT: - - ``K`` - a key belonging to the key space of this Vigenere cipher + - ``K`` -- a key belonging to the key space of this Vigenere cipher - - ``M`` - a string (possibly empty) over the string monoid of this + - ``M`` -- a string (possibly empty) over the string monoid of this cryptosystem OUTPUT: diff --git a/src/sage/crypto/classical_cipher.py b/src/sage/crypto/classical_cipher.py index 2d5722b04df..fd2c2464293 100644 --- a/src/sage/crypto/classical_cipher.py +++ b/src/sage/crypto/classical_cipher.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat """ Classical Ciphers """ @@ -8,9 +9,12 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** -from .cipher import SymmetricKeyCipher +from sage.misc.lazy_import import lazy_import from sage.monoids.string_monoid_element import StringMonoidElement -from sage.modules.free_module import FreeModule + +lazy_import('sage.modules.free_module', 'FreeModule') + +from .cipher import SymmetricKeyCipher class AffineCipher(SymmetricKeyCipher): @@ -152,6 +156,7 @@ def _repr_(self): # as the alphabet used for the plaintext and ciphertext spaces. return "Affine cipher on %s" % self.parent().cipher_domain() + class HillCipher(SymmetricKeyCipher): """ Hill cipher class @@ -164,13 +169,12 @@ def __init__(self, parent, key): EXAMPLES:: + sage: # needs sage.modules sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) - sage: E + sage: E = HillCryptosystem(S,3); E Hill cryptosystem on Free alphabetic string monoid on A-Z of block length 3 sage: M = E.key_space() - sage: A = M([[1,0,1],[0,1,1],[2,2,3]]) - sage: A + sage: A = M([[1,0,1],[0,1,1],[2,2,3]]); A [1 0 1] [0 1 1] [2 2 3] @@ -182,8 +186,8 @@ def __init__(self, parent, key): TESTS:: sage: S = AlphabeticStrings() - sage: E = HillCryptosystem(S,3) - sage: E == loads(dumps(E)) + sage: E = HillCryptosystem(S,3) # needs sage.modules + sage: E == loads(dumps(E)) # needs sage.modules True """ # TODO: some type checking that the key is an invertible matrix? @@ -216,6 +220,7 @@ def _repr_(self): EXAMPLES:: + sage: # needs sage.modules sage: H = HillCryptosystem(AlphabeticStrings(), 3) sage: M = MatrixSpace(IntegerModRing(26), 3, 3) sage: A = M([[1,0,1], [0,1,1], [2,2,3]]) @@ -466,12 +471,12 @@ def __init__(self, parent, key): EXAMPLES:: + sage: # needs sage.groups sage: S = AlphabeticStrings() - sage: E = TranspositionCryptosystem(S,14) - sage: E - Transposition cryptosystem on Free alphabetic string monoid on A-Z of block length 14 - sage: K = [ 14-i for i in range(14) ] - sage: K + sage: E = TranspositionCryptosystem(S,14); E + Transposition cryptosystem on + Free alphabetic string monoid on A-Z of block length 14 + sage: K = [ 14-i for i in range(14) ]; K [14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] sage: e = E(K) sage: m = S("THECATINTHEHAT") @@ -480,11 +485,11 @@ def __init__(self, parent, key): EXAMPLES:: + sage: # needs sage.groups sage: S = AlphabeticStrings() sage: E = TranspositionCryptosystem(S,15) sage: m = S("THECATANDTHEHAT") - sage: G = E.key_space() - sage: G + sage: G = E.key_space(); G Symmetric group of order 15! as a permutation group sage: g = G([ 3, 2, 1, 6, 5, 4, 9, 8, 7, 12, 11, 10, 15, 14, 13 ]) sage: e = E(g) @@ -494,8 +499,8 @@ def __init__(self, parent, key): TESTS:: sage: S = AlphabeticStrings() - sage: E = TranspositionCryptosystem(S,14) - sage: E == loads(dumps(E)) + sage: E = TranspositionCryptosystem(S,14) # needs sage.groups + sage: E == loads(dumps(E)) # needs sage.groups True """ n = parent.block_length() diff --git a/src/sage/crypto/cryptosystem.py b/src/sage/crypto/cryptosystem.py index 7ea7884a834..33cc87cf08e 100644 --- a/src/sage/crypto/cryptosystem.py +++ b/src/sage/crypto/cryptosystem.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Cryptosystems @@ -96,7 +97,7 @@ class Cryptosystem(parent_old.Parent, Set_generic): Substitution cryptosystem on Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3) Hill cryptosystem on Free binary string monoid of block length 3 - sage: TranspositionCryptosystem(OctalStrings(), 5) + sage: TranspositionCryptosystem(OctalStrings(), 5) # needs sage.groups Transposition cryptosystem on Free octal string monoid of block length 5 sage: VigenereCryptosystem(Radix64Strings(), 7) Vigenere cryptosystem on Free radix 64 string monoid of period 7 @@ -129,7 +130,7 @@ def __init__(self, plaintext_space, ciphertext_space, key_space, Substitution cryptosystem on Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3) Hill cryptosystem on Free binary string monoid of block length 3 - sage: TranspositionCryptosystem(OctalStrings(), 5) + sage: TranspositionCryptosystem(OctalStrings(), 5) # needs sage.groups Transposition cryptosystem on Free octal string monoid of block length 5 sage: VigenereCryptosystem(Radix64Strings(), 7) Vigenere cryptosystem on Free radix 64 string monoid of period 7 @@ -172,9 +173,9 @@ def __eq__(self, right): sage: hill2 = HillCryptosystem(AlphabeticStrings(), 4) sage: hill1 == hill2 True - sage: tran1 = TranspositionCryptosystem(HexadecimalStrings(), 5) - sage: tran2 = TranspositionCryptosystem(HexadecimalStrings(), 5) - sage: tran1 == tran2 + sage: tran1 = TranspositionCryptosystem(HexadecimalStrings(), 5) # needs sage.groups + sage: tran2 = TranspositionCryptosystem(HexadecimalStrings(), 5) # needs sage.groups + sage: tran1 == tran2 # needs sage.groups True sage: vig1 = VigenereCryptosystem(AlphabeticStrings(), 7) sage: vig2 = VigenereCryptosystem(AlphabeticStrings(), 7) @@ -195,9 +196,9 @@ def __eq__(self, right): sage: hill2 = HillCryptosystem(Radix64Strings(), 5) sage: hill1 == hill2 False - sage: tran1 = TranspositionCryptosystem(Radix64Strings(), 3) - sage: tran2 = TranspositionCryptosystem(HexadecimalStrings(), 3) - sage: tran1 == tran2 + sage: tran1 = TranspositionCryptosystem(Radix64Strings(), 3) # needs sage.groups + sage: tran2 = TranspositionCryptosystem(HexadecimalStrings(), 3) # needs sage.groups + sage: tran1 == tran2 # needs sage.groups False sage: vig1 = VigenereCryptosystem(AlphabeticStrings(), 7) sage: vig2 = VigenereCryptosystem(Radix64Strings(), 7) @@ -225,7 +226,7 @@ def plaintext_space(self): Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3).plaintext_space() Free binary string monoid - sage: TranspositionCryptosystem(OctalStrings(), 5).plaintext_space() + sage: TranspositionCryptosystem(OctalStrings(), 5).plaintext_space() # needs sage.groups Free octal string monoid sage: VigenereCryptosystem(Radix64Strings(), 7).plaintext_space() Free radix 64 string monoid @@ -248,7 +249,7 @@ def cipher_domain(self): Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3).cipher_domain() Free binary string monoid - sage: TranspositionCryptosystem(OctalStrings(), 5).cipher_domain() + sage: TranspositionCryptosystem(OctalStrings(), 5).cipher_domain() # needs sage.groups Free octal string monoid sage: VigenereCryptosystem(Radix64Strings(), 7).cipher_domain() Free radix 64 string monoid @@ -269,7 +270,7 @@ def ciphertext_space(self): Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3).ciphertext_space() Free binary string monoid - sage: TranspositionCryptosystem(OctalStrings(), 5).ciphertext_space() + sage: TranspositionCryptosystem(OctalStrings(), 5).ciphertext_space() # needs sage.groups Free octal string monoid sage: VigenereCryptosystem(Radix64Strings(), 7).ciphertext_space() Free radix 64 string monoid @@ -292,7 +293,7 @@ def cipher_codomain(self): Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3).cipher_codomain() Free binary string monoid - sage: TranspositionCryptosystem(OctalStrings(), 5).cipher_codomain() + sage: TranspositionCryptosystem(OctalStrings(), 5).cipher_codomain() # needs sage.groups Free octal string monoid sage: VigenereCryptosystem(Radix64Strings(), 7).cipher_codomain() Free radix 64 string monoid @@ -313,7 +314,7 @@ def key_space(self): Free hexadecimal string monoid sage: HillCryptosystem(BinaryStrings(), 3).key_space() Full MatrixSpace of 3 by 3 dense matrices over Ring of integers modulo 2 - sage: TranspositionCryptosystem(OctalStrings(), 5).key_space() + sage: TranspositionCryptosystem(OctalStrings(), 5).key_space() # needs sage.groups Symmetric group of order 5! as a permutation group sage: VigenereCryptosystem(Radix64Strings(), 7).key_space() Free radix 64 string monoid @@ -335,7 +336,7 @@ def block_length(self): 1 sage: HillCryptosystem(BinaryStrings(), 3).block_length() 3 - sage: TranspositionCryptosystem(OctalStrings(), 5).block_length() + sage: TranspositionCryptosystem(OctalStrings(), 5).block_length() # needs sage.groups 5 sage: VigenereCryptosystem(Radix64Strings(), 7).block_length() 1 diff --git a/src/sage/crypto/lattice.py b/src/sage/crypto/lattice.py index d7ee358b9a9..d24b87fe5d4 100644 --- a/src/sage/crypto/lattice.py +++ b/src/sage/crypto/lattice.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules """ Hard Lattice Generator @@ -35,27 +36,36 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, INPUT: - ``type`` -- one of the following strings - - ``'modular'`` (default) -- A class of lattices for which - asymptotic worst-case to average-case connections hold. For - more refer to [Aj1996]_. - - ``'random'`` -- Special case of modular (n=1). A dense class - of lattice used for testing basis reduction algorithms - proposed by Goldstein and Mayer [GM2002]_. - - ``'ideal'`` -- Special case of modular. Allows for a more - compact representation proposed by [LM2006]_. - - ``'cyclotomic'`` -- Special case of ideal. Allows for - efficient processing proposed by [LM2006]_. - - ``n`` -- Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`. + + - ``'modular'`` (default) -- A class of lattices for which + asymptotic worst-case to average-case connections hold. For + more refer to [Aj1996]_. + - ``'random'`` -- Special case of modular (n=1). A dense class + of lattice used for testing basis reduction algorithms + proposed by Goldstein and Mayer [GM2002]_. + - ``'ideal'`` -- Special case of modular. Allows for a more + compact representation proposed by [LM2006]_. + - ``'cyclotomic'`` -- Special case of ideal. Allows for + efficient processing proposed by [LM2006]_. + + - ``n`` -- Determinant size, primal: `det(L) = q^n`, dual: `det(L) = q^{m-n}`. For ideal lattices this is also the degree of the quotient polynomial. + - ``m`` -- Lattice dimension, `L \subseteq Z^m`. + - ``q`` -- Coefficient size, `q-Z^m \subseteq L`. + - ``seed`` -- Randomness seed. - - ``quotient`` -- For the type ideal, this determines the quotient + + - ``quotient`` -- For the type ``'ideal'``, this determines the quotient polynomial. Ignored for all other types. + - ``dual`` -- Set this flag if you want a basis for `q-dual(L)`, for example for Regev's LWE bases [Reg2005]_. + - ``ntl`` -- Set this flag if you want the lattice basis in NTL readable format. + - ``lattice`` -- Set this flag if you want a :class:`FreeModule_submodule_with_basis_integer` object instead of an integer matrix representing the basis. @@ -95,9 +105,9 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, [ 3082 0 0 0 0 0 0 0 1 0] [-4580 0 0 0 0 0 0 0 0 1] - Ideal bases with quotient x^n-1, m=2*n are NTRU bases:: + Ideal bases with quotient `x^n-1`, `m=2*n` are NTRU bases:: - sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4-1) + sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4 - 1) # needs sage.symbolic [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] @@ -110,7 +120,7 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, Ideal bases also work with polynomials:: sage: R. = PolynomialRing(ZZ) - sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=t^4-1) + sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=t^4 - 1) # needs sage.libs.pari [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] @@ -122,7 +132,7 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, Cyclotomic bases with n=2^k are SWIFFT bases:: - sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42) + sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42) # needs sage.libs.pari [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] @@ -149,9 +159,9 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, Relation of primal and dual bases:: - sage: B_primal=sage.crypto.gen_lattice(m=10, q=11, seed=42) - sage: B_dual=sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True) - sage: B_dual_alt=transpose(11*B_primal.inverse()).change_ring(ZZ) + sage: B_primal = sage.crypto.gen_lattice(m=10, q=11, seed=42) + sage: B_dual = sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True) + sage: B_dual_alt = transpose(11*B_primal.inverse()).change_ring(ZZ) sage: B_dual_alt.hermite_form() == B_dual.hermite_form() True @@ -159,11 +169,11 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, Test some bad quotient polynomials:: - sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=cos(x)) + sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=cos(x)) # needs sage.symbolic Traceback (most recent call last): ... TypeError: self must be a numeric expression - sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=x^23-1) + sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=x^23-1) # needs sage.symbolic Traceback (most recent call last): ... ValueError: ideal basis requires n = quotient.degree() @@ -218,7 +228,7 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.matrix.constructor import identity_matrix, block_matrix from sage.matrix.matrix_space import MatrixSpace - from sage.rings.integer_ring import IntegerRing + from sage.rings.integer_ring import ZZ if seed is not None: from sage.misc.randstate import set_random_seed set_random_seed(seed) @@ -227,7 +237,6 @@ def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, if n != 1: raise ValueError('random bases require n = 1') - ZZ = IntegerRing() ZZ_q = IntegerModRing(q) A = identity_matrix(ZZ_q, n) diff --git a/src/sage/crypto/lfsr.py b/src/sage/crypto/lfsr.py index b8aad014e27..869bdcf5990 100644 --- a/src/sage/crypto/lfsr.py +++ b/src/sage/crypto/lfsr.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings r""" Linear feedback shift register (LFSR) sequence commands diff --git a/src/sage/crypto/lwe.py b/src/sage/crypto/lwe.py index e6928d00213..0be1b92d77e 100644 --- a/src/sage/crypto/lwe.py +++ b/src/sage/crypto/lwe.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs scipy sage.symbolic """ (Ring-)LWE oracle generators @@ -52,6 +52,7 @@ Note that Ring-LWE samples are returned as vectors:: + sage: # needs sage.libs.pari sage: from sage.crypto.lwe import RingLWE sage: from sage.stats.distributions.discrete_gaussian_polynomial import DiscreteGaussianDistributionPolynomialSampler sage: D = DiscreteGaussianDistributionPolynomialSampler(ZZ['x'], euler_phi(16), 5) @@ -296,8 +297,8 @@ def __init__(self, n, q, D, secret_dist='uniform', m=None): fix the representation and recover the correct standard deviation of the noise:: - sage: from numpy import std - sage: while abs(std([e if e <= 200 else e-401 for e in S()]) - 3.0) > 0.01: + sage: from numpy import std # needs numpy + sage: while abs(std([e if e <= 200 else e-401 for e in S()]) - 3.0) > 0.01: # needs numpy ....: L = [] # reset L to avoid quadratic behaviour ....: add_samples() @@ -306,7 +307,7 @@ def __init__(self, n, q, D, secret_dist='uniform', m=None): sage: from sage.crypto.lwe import LWE sage: lwe = LWE(n=20, q=next_prime(400), D=D, m=30) sage: _ = [lwe() for _ in range(30)] - sage: lwe() # 31 + sage: lwe() # 31 Traceback (most recent call last): ... IndexError: Number of available samples exhausted. @@ -539,8 +540,8 @@ def __init__(self, N, q, D, poly=None, secret_dist='uniform', m=None): sage: from sage.crypto.lwe import RingLWE sage: from sage.stats.distributions.discrete_gaussian_polynomial import DiscreteGaussianDistributionPolynomialSampler - sage: D = DiscreteGaussianDistributionPolynomialSampler(ZZ['x'], n=euler_phi(20), sigma=3.0) - sage: RingLWE(N=20, q=next_prime(800), D=D) + sage: D = DiscreteGaussianDistributionPolynomialSampler(ZZ['x'], n=euler_phi(20), sigma=3.0) # needs sage.libs.pari + sage: RingLWE(N=20, q=next_prime(800), D=D) # needs sage.libs.pari RingLWE(20, 809, Discrete Gaussian sampler for polynomials of degree < 8 with σ=3.000000 in each component, x^8 - x^6 + x^4 - x^2 + 1, 'uniform', None) """ self.N = ZZ(N) @@ -587,6 +588,7 @@ def __call__(self): """ EXAMPLES:: + sage: # needs sage.libs.pari sage: from sage.crypto.lwe import DiscreteGaussianDistributionPolynomialSampler, RingLWE sage: N = 16 sage: n = euler_phi(N) diff --git a/src/sage/crypto/mq/mpolynomialsystemgenerator.py b/src/sage/crypto/mq/mpolynomialsystemgenerator.py index 3c0bb6b349c..9028dab1d98 100644 --- a/src/sage/crypto/mq/mpolynomialsystemgenerator.py +++ b/src/sage/crypto/mq/mpolynomialsystemgenerator.py @@ -68,7 +68,7 @@ def varstrs(self, name, round): sage: from sage.crypto.mq.mpolynomialsystemgenerator import MPolynomialSystemGenerator sage: msg = MPolynomialSystemGenerator() - sage: msg.varstrs('K', i) + sage: msg.varstrs('K', i) # needs sage.all Traceback (most recent call last): ... NotImplementedError diff --git a/src/sage/crypto/mq/rijndael_gf.py b/src/sage/crypto/mq/rijndael_gf.py index dbf2e0dd5a0..ba24ed0627e 100644 --- a/src/sage/crypto/mq/rijndael_gf.py +++ b/src/sage/crypto/mq/rijndael_gf.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules sage.rings.finite_rings r""" Rijndael-GF @@ -80,7 +81,7 @@ '3902dc1925dc116a8409850b1dfb9732'. We can use this example to demonstrate the correctness of this implementation:: - sage: rgf = RijndaelGF(4, 4) # change dimensions for this example + sage: rgf = RijndaelGF(4, 4) # change dimensions for this example sage: plain = '3243f6a8885a308d313198a2e0370734' sage: key = '2b7e151628aed2a6abf7158809cf4f3c' sage: expected_ciphertext = '3925841d02dc09fbdc118597196a0b32' @@ -160,8 +161,7 @@ finally perform the inversion step after the affine transformation polynomial has been evaluated. :: - sage: inv_affine = sb_pc(1, 2, algorithm='decrypt', - ....: no_inversion=True) + sage: inv_affine = sb_pc(1, 2, algorithm='decrypt', no_inversion=True) sage: state = rgf._hex_to_GF('ff87968431d86a51645151fa773ad009') sage: evaluated = inv_affine(state.list()) sage: result = evaluated * -1 @@ -252,7 +252,7 @@ ``apply_poly`` a dictionary mapping keywords to their values. :: sage: rgf.apply_poly(rgf.state_vrs, rgf.add_round_key_poly_constr(), - ....: poly_constr_attr={'round' : 5}) + ....: poly_constr_attr={'round': 5}) [a00 + k500 a01 + k501 a02 + k502 a03 + k503] [a10 + k510 a11 + k511 a12 + k512 a13 + k513] [a20 + k520 a21 + k521 a22 + k522 a23 + k523] @@ -269,10 +269,11 @@ when passed an index ``i,j`` will return `g(f(A))_{i,j}` in terms of the entries of `A`. :: + sage: # needs sage.libs.gap sage: rcpc = rgf.compose(rgf.shift_rows_poly_constr(), - ....: rgf.mix_columns_poly_constr()) - sage: rcpc - A polynomial constructor of a round component of Rijndael-GF block cipher with block length 4, key length 6, and 12 rounds. + ....: rgf.mix_columns_poly_constr()); rcpc + A polynomial constructor of a round component of Rijndael-GF block cipher + with block length 4, key length 6, and 12 rounds. sage: rcpc(2, 1) a01 + a12 + x*a23 + (x + 1)*a30 @@ -284,7 +285,7 @@ True sage: rcpc = rgf.compose(rgf.mix_columns_poly_constr(), - ....: rgf.shift_rows_poly_constr()) + ....: rgf.shift_rows_poly_constr()) sage: result = rgf.apply_poly(state, rcpc, algorithm='decrypt') sage: new_state = rgf.mix_columns(state, algorithm='decrypt') sage: new_state = rgf.shift_rows(new_state, algorithm='decrypt') @@ -301,8 +302,7 @@ ``compose`` will return a polynomial representing `g(f(A))_{i,j}` in terms of the entries of `A`. :: - sage: poly = rgf.mix_columns_poly_constr()(0, 3) - sage: poly + sage: poly = rgf.mix_columns_poly_constr()(0, 3); poly x*a03 + (x + 1)*a13 + a23 + a33 sage: rgf.compose(rgf.sub_bytes_poly_constr(), poly) (x^3 + x)*a03^254 + @@ -347,16 +347,18 @@ returned ``Round_Component_Poly_Constr`` object's ``__call__`` method must have its own ``algorithm`` keyword defaulted to 'encrypt'. :: + sage: # needs sage.libs.gap sage: poly = rgf.shift_rows_poly_constr()(2, 1) sage: rgf.compose(rgf.mix_columns_poly_constr(), poly, algorithm='decrypt') (x^3 + x^2 + 1)*a03 + (x^3 + 1)*a13 + (x^3 + x^2 + x)*a23 + (x^3 + x + 1)*a33 sage: state = rgf._hex_to_GF('80121e0776fd1d8a8d8c31bc965d1fee') sage: with_decrypt = rgf.compose(rgf.sub_bytes_poly_constr(), - ....: rgf.shift_rows_poly_constr(), algorithm='decrypt') + ....: rgf.shift_rows_poly_constr(), + ....: algorithm='decrypt') sage: result_wd = rgf.apply_poly(state, with_decrypt) sage: no_decrypt = rgf.compose(rgf.sub_bytes_poly_constr(), - ....: rgf.shift_rows_poly_constr()) + ....: rgf.shift_rows_poly_constr()) sage: result_nd = rgf.apply_poly(state, no_decrypt) sage: result_wd == result_nd True @@ -365,10 +367,10 @@ ``compose`` to make ``f`` and ``g`` use those keywords during polynomial creation. :: - sage: rcpc = rgf.compose(rgf.add_round_key_poly_constr(), - ....: rgf.add_round_key_poly_constr(), - ....: f_attr={'round' : 4}, g_attr={'round' : 7}) - sage: rcpc(1, 2) + sage: rcpc = rgf.compose(rgf.add_round_key_poly_constr(), # needs sage.libs.gap + ....: rgf.add_round_key_poly_constr(), + ....: f_attr={'round': 4}, g_attr={'round': 7}) + sage: rcpc(1, 2) # needs sage.libs.gap a12 + k412 + k712 In addition to building polynomial representations of state matrices, we can @@ -1118,14 +1120,16 @@ def _check_valid_PRmatrix(self, PRm, keyword): sage: rgf._check_valid_PRmatrix(5, 'state') Traceback (most recent call last): ... - TypeError: keyword 'state' must be a 4 x 4 matrix with entries from a multivariate PolynomialRing over Finite Field in x of size 2^8 + TypeError: keyword 'state' must be a 4 x 4 matrix with entries from + a multivariate PolynomialRing over Finite Field in x of size 2^8 sage: entries = [rgf._F.random_element() for i in range(24)] sage: wrong_dimensions = matrix(4, 6, entries) sage: rgf._check_valid_PRmatrix(wrong_dimensions, 'state') Traceback (most recent call last): ... - TypeError: keyword 'state' must be a 4 x 4 matrix with entries from a multivariate PolynomialRing over Finite Field in x of size 2^8 + TypeError: keyword 'state' must be a 4 x 4 matrix with entries from + a multivariate PolynomialRing over Finite Field in x of size 2^8 sage: F. = GF(3^4) sage: entries = [F.random_element() for i in range(16)] @@ -1133,7 +1137,8 @@ def _check_valid_PRmatrix(self, PRm, keyword): sage: rgf._check_valid_PRmatrix(wrong_base, 'state') Traceback (most recent call last): ... - TypeError: keyword 'state' must be a 4 x 4 matrix with entries from a multivariate PolynomialRing over Finite Field in x of size 2^8 + TypeError: keyword 'state' must be a 4 x 4 matrix with entries from + a multivariate PolynomialRing over Finite Field in x of size 2^8 """ from sage.rings.polynomial.multi_polynomial_ring_base import \ MPolynomialRing_base @@ -1265,7 +1270,8 @@ def expand_key_poly(self, row, col, round): sage: rgf.compose(rgf.sub_bytes_poly_constr(), rgf.expand_key_poly) Traceback (most recent call last): ... - TypeError: keyword 'g' must be a Round_Component_Poly_Constr or a polynomial over Finite Field in x of size 2^8 + TypeError: keyword 'g' must be a Round_Component_Poly_Constr or + a polynomial over Finite Field in x of size 2^8 sage: state = rgf._hex_to_GF('00000000000000000000000000000000') sage: rgf.apply_poly(state, rgf.expand_key_poly) @@ -1358,7 +1364,7 @@ def apply_poly(self, state, poly_constr, algorithm='encrypt', keys=None, sage: state = rgf._hex_to_GF('4915598f55e5d7a0daca94fa1f0a63f7') sage: apply_poly_result = rgf.apply_poly(state, - ....: rgf.sub_bytes_poly_constr()) + ....: rgf.sub_bytes_poly_constr()) sage: direct_result = rgf.sub_bytes(state) sage: direct_result == apply_poly_result True @@ -1373,7 +1379,8 @@ def apply_poly(self, state, poly_constr, algorithm='encrypt', keys=None, sage: key = rgf._hex_to_GF('54d990a16ba09ab596bbf40ea111702f') sage: keys = rgf.expand_key(key) sage: result = rgf.apply_poly(state, - ....: rgf.add_round_key_poly_constr(), keys=keys) + ....: rgf.add_round_key_poly_constr(), + ....: keys=keys) sage: result == rgf.add_round_key(state, key) True @@ -1385,8 +1392,8 @@ def apply_poly(self, state, poly_constr, algorithm='encrypt', keys=None, dictionary ``poly_constr_attr`` mapping keywords to their values. :: sage: rgf.apply_poly(rgf.state_vrs, - ....: rgf.add_round_key_poly_constr(), - ....: poly_constr_attr={'round' : 5}) + ....: rgf.add_round_key_poly_constr(), + ....: poly_constr_attr={'round': 5}) [a00 + k500 a01 + k501 a02 + k502 a03 + k503] [a10 + k510 a11 + k511 a12 + k512 a13 + k513] [a20 + k520 a21 + k521 a22 + k522 a23 + k523] @@ -1499,9 +1506,9 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): ``Round_Component_Poly_Constr`` object corresponding to the composition of multiple round functions as such:: - sage: fn = rgf.compose(rgf.shift_rows_poly_constr(), - ....: rgf.mix_columns_poly_constr()) - sage: fn(1, 3) + sage: fn = rgf.compose(rgf.shift_rows_poly_constr(), # needs sage.libs.gap + ....: rgf.mix_columns_poly_constr()) + sage: fn(1, 3) # needs sage.libs.gap a03 + x*a10 + (x + 1)*a21 + a32 If we use ``compose`` to make a new ``Round_Component_Poly_Constr`` @@ -1509,7 +1516,7 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): ``compose``:: sage: state = rgf._hex_to_GF('36400926f9336d2d9fb59d23c42c3950') - sage: result = rgf.apply_poly(state, fn) + sage: result = rgf.apply_poly(state, fn) # needs sage.libs.gap sage: rgf._GF_to_hex(result) 'f4bcd45432e554d075f1d6c51dd03b3c' @@ -1520,7 +1527,7 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): :: - sage: fn2 = rgf.compose(rgf.sub_bytes_poly_constr(), fn) + sage: fn2 = rgf.compose(rgf.sub_bytes_poly_constr(), fn) # needs sage.libs.gap If the second argument is a polynomial, then the value of ``algorithm`` is passed directly to the first argument `f` during evaluation. @@ -1528,21 +1535,22 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): object, changing ``algorithm`` does nothing since the returned object has its own ``algorithm='encrypt'`` keyword. :: - sage: f = rgf.compose(rgf.sub_bytes_poly_constr(), - ....: rgf.mix_columns_poly_constr(), algorithm='decrypt') - sage: g = rgf.compose(rgf.sub_bytes_poly_constr(), - ....: rgf.mix_columns_poly_constr()) - sage: all(f(i,j) == g(i,j) for i in range(4) for j in range(4)) + sage: f = rgf.compose(rgf.sub_bytes_poly_constr(), # needs sage.libs.gap + ....: rgf.mix_columns_poly_constr(), + ....: algorithm='decrypt') + sage: g = rgf.compose(rgf.sub_bytes_poly_constr(), # needs sage.libs.gap + ....: rgf.mix_columns_poly_constr()) + sage: all(f(i,j) == g(i,j) for i in range(4) for j in range(4)) # needs sage.libs.gap True We can change the keyword attributes of the ``__call__`` methods of ``f`` and ``g`` by passing dictionaries ``f_attr`` and ``g_attr`` to ``compose``. :: - sage: fn = rgf.compose(rgf.add_round_key_poly_constr(), - ....: rgf.add_round_key_poly_constr(), - ....: f_attr={'round' : 4}, g_attr={'round' : 7}) - sage: fn(1, 2) + sage: fn = rgf.compose(rgf.add_round_key_poly_constr(), # needs sage.libs.gap + ....: rgf.add_round_key_poly_constr(), + ....: f_attr={'round': 4}, g_attr={'round': 7}) + sage: fn(1, 2) # needs sage.libs.gap a12 + k412 + k712 """ if not isinstance(f, RijndaelGF.Round_Component_Poly_Constr): @@ -1572,10 +1580,10 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): return g(f_vals + self.subkey_vrs_list) else: if isinstance(g_attr, dict): - lm = lambda i, j, alg='encrypt' : \ + lm = lambda i, j, alg='encrypt': \ self.compose(f, g(i, j, alg, **g_attr), alg, f_attr, g_attr) else: - lm = lambda i, j, alg='encrypt' : \ + lm = lambda i, j, alg='encrypt': \ self.compose(f, g(i, j, alg), alg, f_attr, g_attr) return RijndaelGF.Round_Component_Poly_Constr(lm, self) @@ -1590,7 +1598,8 @@ def add_round_key_poly_constr(self): sage: rgf = RijndaelGF(4, 4) sage: ark_pc = rgf.add_round_key_poly_constr() sage: ark_pc - A polynomial constructor for the function 'Add Round Key' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. + A polynomial constructor for the function 'Add Round Key' of Rijndael-GF + block cipher with block length 4, key length 4, and 10 rounds. sage: ark_pc(0, 1) a01 + k001 @@ -1616,7 +1625,7 @@ def add_round_key_poly_constr(self): value. :: sage: rgf.apply_poly(rgf.state_vrs, ark_pc, - ....: poly_constr_attr={'round' : 6}) + ....: poly_constr_attr={'round': 6}) [a00 + k600 a01 + k601 a02 + k602 a03 + k603] [a10 + k610 a11 + k611 a12 + k612 a13 + k613] [a20 + k620 a21 + k621 a22 + k622 a23 + k623] @@ -1624,9 +1633,9 @@ def add_round_key_poly_constr(self): :: - sage: rcpc = rgf.compose(ark_pc, ark_pc, - ....: f_attr={'round' : 3}, g_attr={'round' : 5}) - sage: rcpc(3, 1) + sage: rcpc = rgf.compose(ark_pc, ark_pc, # needs sage.libs.gap + ....: f_attr={'round': 3}, g_attr={'round': 5}) + sage: rcpc(3, 1) # needs sage.libs.gap a31 + k331 + k531 """ return self._add_round_key_rcpc @@ -1666,10 +1675,8 @@ def _add_round_key_pc(self, row, col, algorithm='encrypt', round=0): As expected, since the encryption and decryption transformations are identical, changing ``algorithm`` has no effect. - sage: with_encrypt = rgf._add_round_key_pc(3, 2, - ....: 'encrypt') - sage: with_decrypt = rgf._add_round_key_pc(3, 2, - ....: 'decrypt') + sage: with_encrypt = rgf._add_round_key_pc(3, 2, 'encrypt') + sage: with_decrypt = rgf._add_round_key_pc(3, 2, 'decrypt') sage: with_encrypt == with_decrypt True """ @@ -1722,9 +1729,9 @@ def sub_bytes_poly_constr(self): sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) - sage: sb_pc = rgf.sub_bytes_poly_constr() - sage: sb_pc - A polynomial constructor for the function 'SubBytes' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. + sage: sb_pc = rgf.sub_bytes_poly_constr(); sb_pc + A polynomial constructor for the function 'SubBytes' of Rijndael-GF + block cipher with block length 4, key length 4, and 10 rounds. sage: sb_pc(2, 3) (x^2 + 1)*a23^254 + (x^3 + 1)*a23^253 + @@ -1772,17 +1779,17 @@ def sub_bytes_poly_constr(self): When passing the returned object to ``apply_poly`` and ``compose``, we can make those methods change the keyword ``no_inversion`` of this object's ``__call__`` method by passing the dictionary - ``{'no_inversion' : True}`` to them. :: + ``{'no_inversion': True}`` to them. :: sage: result = rgf.apply_poly(state, sb_pc, - ....: poly_constr_attr={'no_inversion' : True}) + ....: poly_constr_attr={'no_inversion': True}) sage: rgf._GF_to_hex(result) '961c72894526f746aa85fc920adcc719' :: - sage: rcpc = rgf.compose(sb_pc, rgf.shift_rows_poly_constr(), - ....: f_attr={'no_inversion' : True}) + sage: rcpc = rgf.compose(sb_pc, rgf.shift_rows_poly_constr(), # needs sage.libs.gap + ....: f_attr={'no_inversion': True}) Note that if we set ``algorithm='decrypt'`` for ``apply_poly``, it will perform the necessary performance enhancement described above @@ -1847,7 +1854,7 @@ def _sub_bytes_pc(self, row, col, algorithm='encrypt', no_inversion=False): calculated. :: sage: poly = rgf._sub_bytes_pc(0, 0, - ....: algorithm='decrypt', no_inversion=True) + ....: algorithm='decrypt', no_inversion=True) sage: state = rgf._hex_to_GF('b415f8016858552e4bb6124c5f998a4c') sage: poly(state.list()) ^ -1 x^7 + x^6 + x^2 + x @@ -1955,7 +1962,8 @@ def mix_columns_poly_constr(self): sage: rgf = RijndaelGF(4, 4) sage: mc_pc = rgf.mix_columns_poly_constr() sage: mc_pc - A polynomial constructor for the function 'Mix Columns' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. + A polynomial constructor for the function 'Mix Columns' of Rijndael-GF + block cipher with block length 4, key length 4, and 10 rounds. sage: mc_pc(1, 2) a02 + x*a12 + (x + 1)*a22 + a32 sage: mc_pc(1, 0, algorithm='decrypt') @@ -2180,13 +2188,14 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): EXAMPLES:: - sage: from sage.crypto.mq.rijndael_gf import \ - ....: RijndaelGF + sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: rcpc = RijndaelGF.Round_Component_Poly_Constr( - ....: rgf._shift_rows_pc, rgf, "Shift Rows") + ....: rgf._shift_rows_pc, rgf, "Shift Rows") sage: rcpc - A polynomial constructor for the function 'Shift Rows' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. + A polynomial constructor for the function 'Shift Rows' of + Rijndael-GF block cipher with block length 4, key length 4, + and 10 rounds. If `\phi` is the round component function to which this object corresponds to, then ``__call__(i,j)`` `= \phi(A)_{i,j}`, where @@ -2194,7 +2203,7 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): by ``__call__(i,j)`` will be in terms of the entries of `A`. :: sage: rcpc = RijndaelGF.Round_Component_Poly_Constr( - ....: rgf._mix_columns_pc, rgf, "Mix Columns") + ....: rgf._mix_columns_pc, rgf, "Mix Columns") sage: poly = rcpc(1, 2); poly a02 + x*a12 + (x + 1)*a22 + a32 sage: state = rgf._hex_to_GF('d1876c0f79c4300ab45594add66ff41f') @@ -2209,7 +2218,7 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): ``Round_Component_Poly_Constr`` object will act similarly. :: sage: all(rgf._mix_columns_pc(i, j) == rcpc(i, j) - ....: for i in range(4) for j in range(4)) + ....: for i in range(4) for j in range(4)) True Since all keyword arguments of ``polynomial_constr`` must have a @@ -2224,8 +2233,8 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): ``compose``. :: sage: rgf.apply_poly(rgf.state_vrs, - ....: rgf.add_round_key_poly_constr(), - ....: poly_constr_attr={'round' : 9}) + ....: rgf.add_round_key_poly_constr(), + ....: poly_constr_attr={'round': 9}) [a00 + k900 a01 + k901 a02 + k902 a03 + k903] [a10 + k910 a11 + k911 a12 + k912 a13 + k913] [a20 + k920 a21 + k921 a22 + k922 a23 + k923] @@ -2233,10 +2242,10 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): :: - sage: fn = rgf.compose(rgf.add_round_key_poly_constr(), - ....: rgf.add_round_key_poly_constr(), - ....: f_attr={'round' : 3}, g_attr={'round' : 7}) - sage: fn(2, 3) + sage: fn = rgf.compose(rgf.add_round_key_poly_constr(), # needs sage.libs.gap + ....: rgf.add_round_key_poly_constr(), + ....: f_attr={'round': 3}, g_attr={'round': 7}) + sage: fn(2, 3) # needs sage.libs.gap a23 + k323 + k723 Because all ``Round_Component_Poly_Constr`` objects are callable @@ -2245,9 +2254,9 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): keywords, however, must be checked in ``polynomial_constr``. :: sage: def my_poly_constr(row, col, algorithm='encrypt'): - ....: return x * rgf._F.one() # example body with no checks + ....: return x * rgf._F.one() # example body with no checks sage: rcpc = RijndaelGF.Round_Component_Poly_Constr( - ....: my_poly_constr, rgf, "My Poly Constr") + ....: my_poly_constr, rgf, "My Poly Constr") sage: rcpc(-1, 2) Traceback (most recent call last): ... @@ -2303,15 +2312,14 @@ def __call__(self, row, col, algorithm='encrypt', **kwargs): EXAMPLES:: - sage: from sage.crypto.mq.rijndael_gf import \ - ....: RijndaelGF + sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: rcpc = RijndaelGF.Round_Component_Poly_Constr( - ....: rgf._shift_rows_pc, rgf, "Shift Rows") + ....: rgf._shift_rows_pc, rgf, "Shift Rows") sage: rcpc(1, 2) a13 sage: all(rcpc(i, j) == rgf._shift_rows_pc(i, j) - ....: for i in range(4) for j in range(4)) + ....: for i in range(4) for j in range(4)) True """ if row not in range(4): @@ -2332,15 +2340,17 @@ def __repr__(self): EXAMPLES:: - sage: from sage.crypto.mq.rijndael_gf import \ - ....: RijndaelGF + sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: RijndaelGF.Round_Component_Poly_Constr( - ....: rgf._shift_rows_pc, rgf, "Shift Rows") - A polynomial constructor for the function 'Shift Rows' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. + ....: rgf._shift_rows_pc, rgf, "Shift Rows") + A polynomial constructor for the function 'Shift Rows' of + Rijndael-GF block cipher with block length 4, key length 4, + and 10 rounds. sage: RijndaelGF.Round_Component_Poly_Constr( - ....: rgf._shift_rows_pc, rgf) - A polynomial constructor of a round component of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. + ....: rgf._shift_rows_pc, rgf) + A polynomial constructor of a round component of Rijndael-GF + block cipher with block length 4, key length 4, and 10 rounds. """ if self._rc_name is None: msg = "A polynomial constructor of a round component of {0}" diff --git a/src/sage/crypto/mq/sr.py b/src/sage/crypto/mq/sr.py index ee3fce334a4..091ff4a96fa 100644 --- a/src/sage/crypto/mq/sr.py +++ b/src/sage/crypto/mq/sr.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules sage.rings.finite_rings r""" Small Scale Variants of the AES (SR) Polynomial System Generator @@ -103,8 +104,8 @@ sage: a = K.gen() sage: K = [a] sage: P = [1] - sage: F,s = sr.polynomial_system(P=P, K=K) - sage: F.groebner_basis() + sage: F,s = sr.polynomial_system(P=P, K=K) # needs sage.rings.polynomial.pbori + sage: F.groebner_basis() # needs sage.rings.polynomial.pbori [k100, k101 + 1, k102, k103 + k003, x100 + 1, x101 + k003 + 1, x102 + k003 + 1, x103 + k003, w100, w101, w102 + 1, w103 + k003 + 1, @@ -123,8 +124,8 @@ All solutions can easily be recovered using the variety function for ideals.:: - sage: I = F.ideal() - sage: for V in I.variety(): + sage: I = F.ideal() # needs sage.rings.polynomial.pbori + sage: for V in I.variety(): # needs sage.rings.polynomial.pbori sage.symbolic ....: for k,v in sorted(V.items()): ....: print("{} {}".format(k, v)) ....: print("\n") @@ -173,7 +174,7 @@ We can also verify the correctness of the variety by evaluating all ideal generators on all points.:: - sage: for V in I.variety(): + sage: for V in I.variety(): # needs sage.rings.polynomial.pbori sage.symbolic ....: for f in I.gens(): ....: if f.subs(V) != 0: ....: print("epic fail") @@ -206,7 +207,7 @@ or use ``S`` to find alternative polynomial representations for the S-Box.:: - sage: S.polynomials(degree=3) + sage: S.polynomials(degree=3) # needs sage.libs.singular [x0*x1 + x1*x2 + x0*x3 + x0*y2 + x1 + y0 + y1 + 1, x0*x1 + x0*x2 + x0*y0 + x0*y1 + x0*y2 + x1 + x2 + y0 + y1 + y2, x0*x1 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x1*y0 + x0*y1 + x0*y3, @@ -1651,7 +1652,7 @@ def variable_dict(self): 'x103': x103} sage: sr = mq.SR(1,1,1,4,gf2=True) - sage: sr.variable_dict() + sage: sr.variable_dict() # needs sage.rings.polynomial.pbori {'k000': k000, 'k001': k001, 'k002': k002, @@ -2003,16 +2004,16 @@ def polynomial_system(self, P=None, K=None, C=None): sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) sage: P = sr.vector([0, 0, 1, 0]) sage: K = sr.vector([1, 0, 0, 1]) - sage: F, s = sr.polynomial_system(P, K) + sage: F, s = sr.polynomial_system(P, K) # needs sage.rings.polynomial.pbori This returns a polynomial system:: - sage: F + sage: F # needs sage.rings.polynomial.pbori Polynomial Sequence with 36 Polynomials in 20 Variables and a solution:: - sage: s # random -- maybe we need a better doctest here? + sage: s # random -- maybe we need a better doctest here? # needs sage.rings.polynomial.pbori {k000: 1, k001: 0, k003: 1, k002: 0} This solution is not the only solution that we can learn from the @@ -2020,24 +2021,25 @@ def polynomial_system(self, P=None, K=None, C=None): :: - sage: F.groebner_basis()[-3:] + sage: F.groebner_basis()[-3:] # needs sage.rings.polynomial.pbori [k000 + 1, k001, k003 + 1] In particular we have two solutions:: - sage: len(F.ideal().variety()) + sage: len(F.ideal().variety()) # needs sage.rings.polynomial.pbori 2 In the following example we provide ``C`` explicitly:: sage: C = sr(P,K) - sage: F,s = sr.polynomial_system(P=P, C=C) - sage: F + sage: F,s = sr.polynomial_system(P=P, C=C) # needs sage.rings.polynomial.pbori + sage: F # needs sage.rings.polynomial.pbori Polynomial Sequence with 36 Polynomials in 20 Variables Alternatively, we can use symbols for the ``P`` and ``C``. First, we have to create a polynomial ring:: + sage: # needs sage.rings.polynomial.pbori sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) sage: R = sr.R sage: vn = sr.varstrs("P",0,1,4) + R.variable_names() + sr.varstrs("C",0,1,4) @@ -2047,6 +2049,7 @@ def polynomial_system(self, P=None, K=None, C=None): Now, we can construct the purely symbolic equation system:: + sage: # needs sage.rings.polynomial.pbori sage: C = sr.vars("C",0); C (C000, C001, C002, C003) sage: P = sr.vars("P",0) @@ -2061,13 +2064,13 @@ def polynomial_system(self, P=None, K=None, C=None): We show that the (returned) key is a solution to the returned system:: sage: sr = mq.SR(3,4,4,8, star=True, gf2=True, polybori=True) - sage: while True: # workaround (see :trac:`31891`) + sage: while True: # workaround (see :trac:`31891`) # needs sage.rings.polynomial.pbori ....: try: ....: F, s = sr.polynomial_system() ....: break ....: except ZeroDivisionError: ....: pass - sage: F.subs(s).groebner_basis() # long time + sage: F.subs(s).groebner_basis() # long time # needs sage.rings.polynomial.pbori Polynomial Sequence with 1248 Polynomials in 1248 Variables """ plaintext = P @@ -2588,7 +2591,7 @@ def phi(self, l, diffusion_matrix=False): sage: sr = mq.SR(2, 1, 2, 4, gf2=True) sage: k = sr.base_ring() sage: A = matrix(k, 1, 2, [k.gen(), 0] ) - sage: sr.phi(A) + sage: sr.phi(A) # needs sage.libs.gap [0 0] [0 0] [1 0] @@ -2642,7 +2645,7 @@ def antiphi(self, l): sage: sr = mq.SR(gf2=True) sage: A = sr.random_state_array() - sage: sr.antiphi(sr.phi(A)) == A + sage: sr.antiphi(sr.phi(A)) == A # needs sage.libs.gap True """ e = self.e @@ -3145,9 +3148,9 @@ def inversion_polynomials(self, xi, wi, length): EXAMPLES:: sage: sr = mq.SR(1, 1, 1, 8, gf2=True) - sage: xi = sr.vars('x', 1) - sage: wi = sr.vars('w', 1) - sage: sr.inversion_polynomials(xi, wi, len(xi))[:3] + sage: xi = sr.vars('x', 1) # needs sage.rings.polynomial.pbori + sage: wi = sr.vars('w', 1) # needs sage.rings.polynomial.pbori + sage: sr.inversion_polynomials(xi, wi, len(xi))[:3] # needs sage.rings.polynomial.pbori [x100*w100 + x100*w102 + x100*w103 + x100*w107 + x101*w101 + x101*w102 + x101*w106 + x102*w100 + x102*w101 + x102*w105 + x103*w100 + x103*w104 + x104*w103 + x105*w102 + x106*w101 + x107*w100, x100*w101 + x100*w103 + x100*w104 + x101*w100 + x101*w102 + x101*w103 + x101*w107 + x102*w101 + x102*w102 + x102*w106 + x103*w100 + x103*w101 + x103*w105 + x104*w100 + x104*w104 + x105*w103 + x106*w102 + x107*w101, x100*w102 + x100*w104 + x100*w105 + x101*w101 + x101*w103 + x101*w104 + x102*w100 + x102*w102 + x102*w103 + x102*w107 + x103*w101 + x103*w102 + x103*w106 + x104*w100 + x104*w101 + x104*w105 + x105*w100 + x105*w104 + x106*w103 + x107*w102] @@ -3227,7 +3230,7 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, sage: sr = SR_gf2_2(1, 1, 1, e) sage: P = PolynomialRing(GF(2),['x%d'%i for i in range(e)] + ['w%d'%i for i in range(e)],order='lex') sage: X,W = P.gens()[:e],P.gens()[e:] - sage: sr.inversion_polynomials_single_sbox(X, W, groebner=True) + sage: sr.inversion_polynomials_single_sbox(X, W, groebner=True) # needs sage.libs.singular [x0 + w0*w1*w2 + w0*w1 + w0*w2 + w0*w3 + w0 + w1 + w2, x1 + w0*w1*w3 + w0*w3 + w0 + w1*w3 + w1 + w2*w3, x2 + w0*w2*w3 + w0*w2 + w0 + w1*w2 + w1*w3 + w2*w3, @@ -3236,7 +3239,7 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, sage: from sage.crypto.mq.sr import SR_gf2_2 sage: e = 4 sage: sr = SR_gf2_2(1, 1, 1, e) - sage: sr.inversion_polynomials_single_sbox() + sage: sr.inversion_polynomials_single_sbox() # needs sage.libs.singular [w3*w1 + w3*w0 + w3*x2 + w3*x1 + w3 + w2*w1 + w1 + x3 + x2 + x1, w3*w2 + w3*w1 + w3*x3 + w2 + w1 + x3, w3*w2 + w3*w1 + w3*x2 + w3 + w2*x3 + x2 + x1, @@ -3269,8 +3272,8 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, sage: from sage.crypto.mq.sr import SR_gf2_2 sage: e = 4 sage: sr = SR_gf2_2(1, 1, 1, e) - sage: l = sr.inversion_polynomials_single_sbox() - sage: l == sr.inversion_polynomials_single_sbox(biaffine_only=True, correct_only=False) + sage: l = sr.inversion_polynomials_single_sbox() # needs sage.libs.singular + sage: l == sr.inversion_polynomials_single_sbox(biaffine_only=True, correct_only=False) # needs sage.libs.singular True """ diff --git a/src/sage/crypto/public_key/blum_goldwasser.py b/src/sage/crypto/public_key/blum_goldwasser.py index 8f076a4f70d..1d090673400 100644 --- a/src/sage/crypto/public_key/blum_goldwasser.py +++ b/src/sage/crypto/public_key/blum_goldwasser.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Blum-Goldwasser Probabilistic Encryption @@ -88,6 +89,7 @@ class BlumGoldwasser(PublicKeyCryptosystem): The following encryption/decryption example is taken from Example 8.57, pages 309--310 of [MvOV1996]_:: + sage: # needs sage.symbolic sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: bg = BlumGoldwasser(); bg The Blum-Goldwasser public-key encryption scheme. @@ -111,6 +113,7 @@ class BlumGoldwasser(PublicKeyCryptosystem): private key. Finally, compare the decrypted message with the original plaintext. :: + sage: # needs sage.libs.pari sage.symbolic sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: from sage.crypto.util import bin_to_ascii sage: bg = BlumGoldwasser() @@ -124,10 +127,10 @@ class BlumGoldwasser(PublicKeyCryptosystem): If `(p, q, a, b)` is a private key, then `n = pq` is the corresponding public key. Furthermore, we have `\gcd(p, q) = ap + bq = 1`. :: - sage: p, q, a, b = prikey - sage: pubkey == p * q + sage: p, q, a, b = prikey # needs sage.symbolic + sage: pubkey == p * q # needs sage.symbolic True - sage: gcd(p, q) == a*p + b*q == 1 + sage: gcd(p, q) == a*p + b*q == 1 # needs sage.symbolic True """ @@ -264,24 +267,25 @@ def decrypt(self, C, K): Decrypt a longer ciphertext and convert the resulting plaintext into an ASCII string:: + sage: # needs sage.libs.pari sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: from sage.crypto.util import bin_to_ascii sage: bg = BlumGoldwasser() sage: p = 78307; q = 412487 sage: K = bg.private_key(p, q) - sage: C = ([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], \ - ....: [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1], \ - ....: [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], \ - ....: [0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], \ - ....: [1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], \ - ....: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], \ - ....: [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0], \ - ....: [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1], \ - ....: [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], \ - ....: [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1], \ - ....: [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1], \ - ....: [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0], \ - ....: [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]], 3479653279) + sage: C = ([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], + ....: [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1], + ....: [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], + ....: [0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], + ....: [1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], + ....: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], + ....: [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0], + ....: [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1], + ....: [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], + ....: [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1], + ....: [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1], + ....: [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0], + ....: [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]], 3479653279) sage: P = bg.decrypt(C, K) sage: bin_to_ascii(flatten(P)) 'Blum-Goldwasser encryption' @@ -415,13 +419,13 @@ def encrypt(self, P, K, seed=None): sage: bg = BlumGoldwasser() sage: p = 499; q = 547; n = p * q sage: P = "10011100000100001100" - sage: C = bg.encrypt(P, n, seed=159201); C + sage: C = bg.encrypt(P, n, seed=159201); C # needs sage.symbolic ([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680) Convert the ciphertext sub-blocks into a binary string:: sage: bin = BinaryStrings() - sage: bin(flatten(C[0])) + sage: bin(flatten(C[0])) # needs sage.symbolic 00100000110011100100 Now encrypt an ASCII string. The result is random; no seed is @@ -432,7 +436,7 @@ def encrypt(self, P, K, seed=None): sage: bg = BlumGoldwasser() sage: K = 32300619509 sage: P = "Blum-Goldwasser encryption" - sage: bg.encrypt(P, K) # random + sage: bg.encrypt(P, K) # random # needs sage.symbolic ([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], \ [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1], \ [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], \ @@ -554,9 +558,9 @@ def private_key(self, p, q): sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: from sage.crypto.util import is_blum_prime sage: bg = BlumGoldwasser() - sage: P = primes_first_n(10); P + sage: P = primes_first_n(10); P # needs sage.libs.pari [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - sage: [is_blum_prime(_) for _ in P] + sage: [is_blum_prime(_) for _ in P] # needs sage.libs.pari [False, True, False, True, True, False, False, True, True, False] sage: bg.private_key(19, 23) (19, 23, -6, 5) @@ -566,6 +570,7 @@ def private_key(self, p, q): resulting private key `(p, q, a, b)` satisfies `\gcd(p, q) = ap + bq = 1`:: + sage: # needs sage.libs.pari sage: from sage.crypto.util import random_blum_prime sage: p = random_blum_prime(10**4, 10**5) sage: q = random_blum_prime(10**4, 10**5) @@ -628,9 +633,9 @@ def public_key(self, p, q): sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: from sage.crypto.util import is_blum_prime sage: bg = BlumGoldwasser() - sage: P = primes_first_n(10); P + sage: P = primes_first_n(10); P # needs sage.libs.pari [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - sage: [is_blum_prime(_) for _ in P] + sage: [is_blum_prime(_) for _ in P] # needs sage.libs.pari [False, True, False, True, True, False, False, True, True, False] sage: bg.public_key(3, 7) 21 @@ -639,6 +644,7 @@ def public_key(self, p, q): public key corresponding to those two primes, and test that the public key factorizes into Blum primes:: + sage: # needs sage.libs.pari sage: from sage.crypto.util import random_blum_prime sage: p = random_blum_prime(10**4, 10**5) sage: q = random_blum_prime(10**4, 10**5) @@ -730,6 +736,7 @@ def random_key(self, lbound, ubound, ntries=100): Choosing a random pair of public and private keys. We then test to see if they satisfy the requirements of the Blum-Goldwasser scheme:: + sage: # needs sage.libs.pari sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: from sage.crypto.util import is_blum_prime sage: bg = BlumGoldwasser() @@ -754,7 +761,7 @@ def random_key(self, lbound, ubound, ntries=100): sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser sage: bg = BlumGoldwasser() - sage: pubkey, privkey = bg.random_key(24, 30) + sage: pubkey, privkey = bg.random_key(24, 30) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: No Blum primes within the specified closed interval. diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index 453ac488a88..e2a99aa718e 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules sage.rings.finite_rings r""" S-Boxes and Their Algebraic Representations """ @@ -39,7 +40,7 @@ cdef Py_ssize_t _nterms(Py_ssize_t nvars, Py_ssize_t deg): sage: from sage.crypto.sbox import SBox sage: S = SBox(7,6,0,4,2,5,1,3) - sage: F = S.polynomials(degree=3) # indirect doctest + sage: F = S.polynomials(degree=3) # indirect doctest # needs sage.libs.singular """ cdef Py_ssize_t total = 1 cdef Py_ssize_t divisor = 1 @@ -58,9 +59,9 @@ cdef Py_ssize_t _nterms(Py_ssize_t nvars, Py_ssize_t deg): cdef class SBox(SageObject): r""" A substitution box or S-box is one of the basic components of - symmetric key cryptography. In general, an S-box takes ``m`` input - bits and transforms them into ``n`` output bits. This is called an - ``mxn`` S-box and is often implemented as a lookup table. These + symmetric key cryptography. In general, an S-box takes `m` input + bits and transforms them into `n` output bits. This is called an + `m \times n` S-box and is often implemented as a lookup table. These S-boxes are carefully chosen to resist linear and differential cryptanalysis [He2002]_. @@ -590,7 +591,7 @@ cdef class SBox(SageObject): ... IndexError: list index out of range sage: from sage.crypto.sboxes import PRESENT - sage: PRESENT.derivative(1).max_degree() < PRESENT.max_degree() + sage: PRESENT.derivative(1).max_degree() < PRESENT.max_degree() # needs sage.rings.polynomial.pbori True """ from sage.structure.element import is_Vector @@ -839,7 +840,8 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox(7,6,0,4,2,5,1,3) sage: S.ring() - Multivariate Polynomial Ring in x0, x1, x2, y0, y1, y2 over Finite Field of size 2 + Multivariate Polynomial Ring in x0, x1, x2, y0, y1, y2 over + Finite Field of size 2 """ return self._ring @@ -857,9 +859,9 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox([7,6,0,4,2,5,1,3]) - sage: F = S.polynomials() + sage: F = S.polynomials() # needs sage.libs.singular sage: s = S.solutions() - sage: any(f.subs(_s) for f in F for _s in s) + sage: any(f.subs(_s) for f in F for _s in s) # needs sage.libs.singular False """ if X is None and Y is None: @@ -907,7 +909,7 @@ cdef class SBox(SageObject): By default, this method returns an indirect representation:: - sage: S.polynomials() + sage: S.polynomials() # needs sage.libs.singular [x0*x2 + x1 + y1 + 1, x0*x1 + x1 + x2 + y0 + y1 + y2 + 1, x0*y1 + x0 + x2 + y0 + y2, @@ -929,7 +931,7 @@ cdef class SBox(SageObject): bits are greater than the input bits:: sage: P. = PolynomialRing(GF(2),6,order='lex') - sage: S.polynomials([x0,x1,x2],[y0,y1,y2], groebner=True) + sage: S.polynomials([x0,x1,x2],[y0,y1,y2], groebner=True) # needs sage.libs.singular [y0 + x0*x1 + x0*x2 + x0 + x1*x2 + x1 + 1, y1 + x0*x2 + x1 + 1, y2 + x0 + x1*x2 + x1 + x2 + 1] @@ -1270,11 +1272,11 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox([7,6,0,4,2,5,1,3]) sage: f3 = S.component_function(3) - sage: f3.algebraic_normal_form() + sage: f3.algebraic_normal_form() # needs sage.rings.polynomial.pbori x0*x1 + x0*x2 + x0 + x2 sage: f5 = S.component_function([1, 0, 1]) - sage: f5.algebraic_normal_form() + sage: f5.algebraic_normal_form() # needs sage.rings.polynomial.pbori x0*x2 + x0 + x1*x2 """ cdef Py_ssize_t m = self.m @@ -1449,7 +1451,7 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox(7,6,0,4,2,5,1,3) - sage: S.autocorrelation_table() + sage: S.autocorrelation_table() # needs sage.combinat [ 8 8 8 8 8 8 8 8] [ 8 0 0 0 0 0 0 -8] [ 8 0 -8 0 0 0 0 0] @@ -1573,7 +1575,7 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox([0,1,3,6,7,4,5,2]) - sage: S.linear_structures() + sage: S.linear_structures() # needs sage.combinat [(1, 1, 1), (2, 2, 1), (3, 3, 1), (4, 4, 1), (5, 5, 1), (6, 6, 1), (7, 7, 1)] """ @@ -1651,7 +1653,7 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2]) - sage: S.max_degree() + sage: S.max_degree() # needs sage.rings.polynomial.pbori 3 """ ret = ZZ.zero() @@ -1671,7 +1673,7 @@ cdef class SBox(SageObject): sage: from sage.crypto.sbox import SBox sage: S = SBox([12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2]) - sage: S.min_degree() + sage: S.min_degree() # needs sage.rings.polynomial.pbori 2 """ ret = ZZ(self.m) diff --git a/src/sage/crypto/sboxes.py b/src/sage/crypto/sboxes.py index 056ce082b50..27ca13fbcc3 100644 --- a/src/sage/crypto/sboxes.py +++ b/src/sage/crypto/sboxes.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules sage.rings.finite_rings r""" S-Boxes used in cryptographic schemes @@ -396,6 +397,7 @@ def monomial_function(n, e): X = R.gen() return SBox(X**e) + # Bijective S-Boxes mapping 9 bits to 9 # ===================================== diff --git a/src/sage/crypto/stream.py b/src/sage/crypto/stream.py index 71d8ffb9a21..636f588ad97 100644 --- a/src/sage/crypto/stream.py +++ b/src/sage/crypto/stream.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.rings.finite_rings """ Stream Cryptosystems """ diff --git a/src/sage/crypto/stream_cipher.py b/src/sage/crypto/stream_cipher.py index 198e93d9216..c6f46c8cef0 100644 --- a/src/sage/crypto/stream_cipher.py +++ b/src/sage/crypto/stream_cipher.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.rings.finite_rings """ Stream Ciphers """ diff --git a/src/sage/crypto/util.py b/src/sage/crypto/util.py index 637738e45d0..8590c83db5c 100644 --- a/src/sage/crypto/util.py +++ b/src/sage/crypto/util.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat """ Utility Functions for Cryptography @@ -23,11 +24,11 @@ from sage.arith.functions import lcm from sage.arith.misc import is_prime, primes, random_prime from sage.misc.lazy_import import lazy_import -from sage.monoids.string_monoid import BinaryStrings from sage.rings.finite_rings.integer_mod import Mod as mod from sage.rings.integer import Integer lazy_import('sage.arith.misc', ('carmichael_lambda'), deprecation=34719) +lazy_import('sage.monoids.string_monoid', 'BinaryStrings') def ascii_integer(B): @@ -297,14 +298,14 @@ def has_blum_prime(lbound, ubound): sage: from sage.crypto.util import has_blum_prime sage: from sage.crypto.util import is_blum_prime - sage: has_blum_prime(4, 100) + sage: has_blum_prime(4, 100) # needs sage.libs.pari True sage: for n in range(4, 100): ....: if is_blum_prime(n): ....: print(n) ....: break 7 - sage: has_blum_prime(24, 28) + sage: has_blum_prime(24, 28) # needs sage.libs.pari False TESTS: @@ -377,8 +378,8 @@ def is_blum_prime(n): False sage: is_blum_prime(7) True - sage: p = random_blum_prime(10**3, 10**5) - sage: is_blum_prime(p) + sage: p = random_blum_prime(10**3, 10**5) # needs sage.libs.pari + sage: is_blum_prime(p) # needs sage.libs.pari True """ if n < 0: @@ -486,10 +487,10 @@ def random_blum_prime(lbound, ubound, ntries=100): Choose a random prime and check that it is a Blum prime:: sage: from sage.crypto.util import random_blum_prime - sage: p = random_blum_prime(10**4, 10**5) - sage: is_prime(p) + sage: p = random_blum_prime(10**4, 10**5) # needs sage.libs.pari + sage: is_prime(p) # needs sage.libs.pari True - sage: mod(p, 4) == 3 + sage: mod(p, 4) == 3 # needs sage.libs.pari True TESTS: @@ -500,11 +501,11 @@ def random_blum_prime(lbound, ubound, ntries=100): is not a Blum prime. :: sage: from sage.crypto.util import random_blum_prime - sage: random_blum_prime(24, 30, ntries=10) + sage: random_blum_prime(24, 30, ntries=10) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: No Blum primes within the specified closed interval. - sage: random_blum_prime(24, 28) + sage: random_blum_prime(24, 28) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: No Blum primes within the specified closed interval. diff --git a/src/sage/data_structures/bitset.pyx b/src/sage/data_structures/bitset.pyx index b49f83f46d6..446062554c1 100644 --- a/src/sage/data_structures/bitset.pyx +++ b/src/sage/data_structures/bitset.pyx @@ -204,27 +204,28 @@ cdef class FrozenBitset: the number of elements currently in the bitset, while the capacity is the number of elements that the bitset can hold. :: - sage: p = primes_first_n(10); p + sage: p = primes_first_n(10); p # needs sage.libs.pari [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - sage: tuple(p) + sage: tuple(p) # needs sage.libs.pari (2, 3, 5, 7, 11, 13, 17, 19, 23, 29) - sage: F = FrozenBitset(p); F; FrozenBitset(tuple(p)) + sage: F = FrozenBitset(p); F; FrozenBitset(tuple(p)) # needs sage.libs.pari 001101010001010001010001000001 001101010001010001010001000001 Recover the primes from the bitset:: - sage: for b in F: + sage: for b in F: # needs sage.libs.pari ....: print(b) 2 3 ... 29 - sage: list(F) + sage: list(F) # needs sage.libs.pari [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] Query the bitset:: + sage: # needs sage.libs.pari sage: len(F) 10 sage: len(list(F)) @@ -2067,7 +2068,7 @@ def test_bitset(py_a, py_b, long n): Large enough to span multiple limbs. We don't explicitly check the number of limbs below because it will be different in the 32 bit versus 64 bit cases:: - sage: test_bitset('111001'*25, RealField(151)(pi).str(2)[2:], 69) + sage: test_bitset('111001'*25, RealField(151)(pi).str(2)[2:], 69) # needs sage.symbolic a 111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001111001 list a [0, 1, 2, 5, 6, 7, 8, 11, 12, 13, 14, 17, 18, 19, 20, 23, 24, 25, 26, 29, 30, 31, 32, 35, 36, 37, 38, 41, 42, 43, 44, 47, 48, 49, 50, 53, 54, 55, 56, 59, 60, 61, 62, 65, 66, 67, 68, 71, 72, 73, 74, 77, 78, 79, 80, 83, 84, 85, 86, 89, 90, 91, 92, 95, 96, 97, 98, 101, 102, 103, 104, 107, 108, 109, 110, 113, 114, 115, 116, 119, 120, 121, 122, 125, 126, 127, 128, 131, 132, 133, 134, 137, 138, 139, 140, 143, 144, 145, 146, 149] a.size 150 diff --git a/src/sage/data_structures/blas_dict.pyx b/src/sage/data_structures/blas_dict.pyx index df6bf29641e..c13cab2aab9 100644 --- a/src/sage/data_structures/blas_dict.pyx +++ b/src/sage/data_structures/blas_dict.pyx @@ -398,7 +398,8 @@ cpdef dict sum_of_terms(index_coeff_pairs): {'a': 1, 'b': 3} sage: blas.sum_of_terms([('a', 5), ('b', 3), ('a', -5)]) {'b': 3} - sage: blas.sum_of_terms([('a', 5), ('b', GF(2).one()), ('a', -5), ('b', GF(2).one())]) + sage: blas.sum_of_terms([('a', 5), ('b', GF(2).one()), + ....: ('a', -5), ('b', GF(2).one())]) {} """ cdef dict result = {} diff --git a/src/sage/data_structures/bounded_integer_sequences.pyx b/src/sage/data_structures/bounded_integer_sequences.pyx index 7e3846470c0..907f9b4298a 100644 --- a/src/sage/data_structures/bounded_integer_sequences.pyx +++ b/src/sage/data_structures/bounded_integer_sequences.pyx @@ -110,7 +110,7 @@ AUTHORS: from cysignals.signals cimport sig_check, sig_on, sig_off from sage.data_structures.bitset_base cimport * -from cpython.int cimport PyInt_FromSize_t +from cpython.long cimport PyLong_FromSize_t from cpython.slice cimport PySlice_GetIndicesEx from sage.libs.flint.flint cimport FLINT_BIT_COUNT as BIT_COUNT from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool @@ -295,7 +295,7 @@ cdef biseq_getitem_py(biseq_t S, mp_size_t index): """ cdef size_t out = biseq_getitem(S, index) - return PyInt_FromSize_t(out) + return PyLong_FromSize_t(out) cdef inline void biseq_inititem(biseq_t S, mp_size_t index, size_t item): """ diff --git a/src/sage/data_structures/stream.py b/src/sage/data_structures/stream.py index b11a27318f5..8838a4f1754 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -102,6 +102,7 @@ from sage.misc.lazy_import import lazy_import from sage.combinat.integer_vector_weighted import iterator_fast as wt_int_vec_iter from sage.categories.hopf_algebras_with_basis import HopfAlgebrasWithBasis +from sage.misc.cachefunc import cached_method lazy_import('sage.combinat.sf.sfa', ['_variables_recursive', '_raise_variables']) @@ -178,14 +179,13 @@ def __ne__(self, other): False sage: CS != Stream(-2) False - """ return False def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. The default implementation is ``False``. @@ -198,6 +198,21 @@ def is_nonzero(self): """ return False + def is_uninitialized(self): + r""" + Return ``True`` if ``self`` is an uninitialized stream. + + The default implementation is ``False``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_zero + sage: zero = Stream_zero() + sage: zero.is_uninitialized() + False + """ + return False + class Stream_inexact(Stream): """ @@ -236,7 +251,7 @@ def __init__(self, is_sparse, true_order): def is_nonzero(self): r""" - Return ``True`` if and only if the cache contains a nonzero element. + Return ``True`` if and only if the cache contains a non-zero element. EXAMPLES:: @@ -325,7 +340,7 @@ def __setstate__(self, d): def __getitem__(self, n): """ - Return the `n`-th coefficient of ``self``. + Return the ``n``-th coefficient of ``self``. INPUT: @@ -426,7 +441,7 @@ def iterate_coefficients(self): def order(self): r""" Return the order of ``self``, which is the minimum index ``n`` such - that ``self[n]`` is nonzero. + that ``self[n]`` is non-zero. EXAMPLES:: @@ -535,7 +550,10 @@ def __ne__(self, other): # TODO: more cases, in particular mixed implementations, # could be detected if not isinstance(other, Stream_inexact): - return False + return (other != self) + + if self.is_uninitialized() != other.is_uninitialized(): + return True if self._is_sparse and other._is_sparse: for i in self._cache: @@ -652,13 +670,13 @@ def __init__(self, initial_coefficients, constant=None, degree=None, order=None) # complicated otherwise for i, v in enumerate(initial_coefficients): if v: - # We have found the first nonzero coefficient + # We have found the first non-zero coefficient order += i initial_coefficients = initial_coefficients[i:] if order + len(initial_coefficients) == self._degree: # Strip off the constant values at the end for w in reversed(initial_coefficients): - if w != self._constant: + if not (w == self._constant): break initial_coefficients.pop() self._degree -= 1 @@ -731,7 +749,7 @@ def __getitem__(self, n): def order(self): r""" Return the order of ``self``, which is the minimum index - ``n`` such that ``self[n]`` is nonzero. + ``n`` such that ``self[n]`` is non-zero. EXAMPLES:: @@ -739,7 +757,6 @@ def order(self): sage: s = Stream_exact([1]) sage: s.order() 0 - """ return self._approximate_order @@ -836,13 +853,17 @@ def __ne__(self, other): [0, 0, 0, 2, 1, 1, 1, 1] sage: [f[i] for i in range(-3, 5)] [0, 0, 0, 2, 1, 1, 1, 1] - """ if isinstance(other, type(self)): return (self._degree != other._degree or self._approximate_order != other._approximate_order or self._initial_coefficients != other._initial_coefficients or self._constant != other._constant) + if other.is_uninitialized(): + return True + if isinstance(other, Stream_zero): + # We are assumed to be nonzero + return True # if other is not exact, we can at least compare with the # elements in its cache if other._is_sparse: @@ -862,9 +883,9 @@ def __ne__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. - An assumption of this class is that it is nonzero. + An assumption of this class is that it is non-zero. EXAMPLES:: @@ -914,7 +935,6 @@ class Stream_iterator(Stream_inexact): sage: f = Stream_iterator(iter(NonNegativeIntegers()), 1) sage: [f[i] for i in range(10)] [0, 0, 1, 2, 3, 4, 5, 6, 7, 8] - """ def __init__(self, iter, approximate_order, true_order=False): """ @@ -943,6 +963,11 @@ class Stream_function(Stream_inexact): - ``approximate_order`` -- integer; a lower bound for the order of the stream + .. NOTE:: + + We assume for equality that ``function`` is a function in the + mathematical sense. + EXAMPLES:: sage: from sage.data_structures.stream import Stream_function @@ -975,6 +1000,43 @@ def __init__(self, function, is_sparse, approximate_order, true_order=False): super().__init__(is_sparse, true_order) self._approximate_order = approximate_order + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_function + sage: f = Stream_function(lambda n: n, True, 0) + sage: g = Stream_function(lambda n: 1, False, 1) + sage: hash(f) == hash(g) + True + """ + # We don't hash the function as it might not be hashable. + return hash(type(self)) + + def __eq__(self, other): + r""" + Return whether ``self`` and ``other`` are known to be equal. + + INPUT: + + - ``other`` -- a stream + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_function + sage: fun = lambda n: n + sage: f = Stream_function(fun, True, 0) + sage: g = Stream_function(fun, False, 0) + sage: h = Stream_function(lambda n: n, False, 0) + sage: f == g + True + sage: f == h + False + """ + return isinstance(other, type(self)) and self.get_coefficient == other.get_coefficient + class Stream_uninitialized(Stream_inexact): r""" @@ -1002,7 +1064,6 @@ class Stream_uninitialized(Stream_inexact): sage: C._target = one sage: C[4] 0 - """ def __init__(self, approximate_order, true_order=False): """ @@ -1019,6 +1080,7 @@ def __init__(self, approximate_order, true_order=False): raise ValueError("the valuation must be specified for undefined series") super().__init__(False, true_order) self._approximate_order = approximate_order + self._initializing = False def iterate_coefficients(self): """ @@ -1041,6 +1103,36 @@ def iterate_coefficients(self): yield self._target[n] n += 1 + def is_uninitialized(self): + """ + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized + sage: C = Stream_uninitialized(0) + sage: C.is_uninitialized() + True + + A more subtle uninitialized series:: + + sage: L. = LazyPowerSeriesRing(QQ) + sage: T = L.undefined(1) + sage: D = L.undefined(0) + sage: T.define(z * exp(T) * D) + sage: T._coeff_stream.is_uninitialized() + True + """ + if self._target is None: + return True + if self._initializing: + return False + # We implement semaphore-like behavior for coupled (undefined) series + self._initializing = True + result = self._target.is_uninitialized() + self._initializing = False + return result + class Stream_unary(Stream_inexact): r""" @@ -1049,6 +1141,9 @@ class Stream_unary(Stream_inexact): INPUT: - ``series`` -- :class:`Stream` the operator acts on + - ``is_sparse`` -- boolean + - ``true_order`` -- boolean (default: ``False``) if the approximate order + is the actual order EXAMPLES:: @@ -1061,8 +1156,7 @@ class Stream_unary(Stream_inexact): sage: [g[i] for i in range(10)] [0, 4, 8, 12, 16, 20, 24, 28, 32, 36] """ - - def __init__(self, series, is_sparse): + def __init__(self, series, is_sparse, true_order=False): """ Initialize ``self``. @@ -1077,7 +1171,7 @@ def __init__(self, series, is_sparse): sage: TestSuite(g).run() """ self._series = series - super().__init__(is_sparse, False) + super().__init__(is_sparse, true_order) def __hash__(self): """ @@ -1117,6 +1211,20 @@ def __eq__(self, other): """ return isinstance(other, type(self)) and self._series == other._series + def is_uninitialized(self): + """ + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_unary + sage: C = Stream_uninitialized(0) + sage: M = Stream_unary(C, True) + sage: M.is_uninitialized() + True + """ + return self._series.is_uninitialized() + class Stream_binary(Stream_inexact): """ @@ -1205,6 +1313,24 @@ def __eq__(self, other): return False return self._left == other._left and self._right == other._right + def is_uninitialized(self): + """ + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_sub, Stream_function + sage: C = Stream_uninitialized(0) + sage: F = Stream_function(lambda n: n, True, 0) + sage: B = Stream_sub(F, C, True) + sage: B.is_uninitialized() + True + sage: Bp = Stream_sub(F, F, True) + sage: Bp.is_uninitialized() + False + """ + return self._left.is_uninitialized() or self._right.is_uninitialized() + class Stream_binaryCommutative(Stream_binary): r""" @@ -1282,7 +1408,6 @@ class Stream_zero(Stream): sage: s[5] 0 """ - def __init__(self): """ Initialize ``self``. @@ -1292,7 +1417,6 @@ def __init__(self): sage: from sage.data_structures.stream import Stream_zero sage: s = Stream_zero() sage: TestSuite(s).run() - """ super().__init__(True) self._approximate_order = infinity @@ -1345,6 +1469,33 @@ def __eq__(self, other): """ return self is other or isinstance(other, Stream_zero) + def __ne__(self, other): + """ + Return whether ``self`` and ``other`` are known to be different. + + INPUT: + + - ``other`` -- a stream + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_zero, Stream_function + sage: Stream_zero() != Stream_zero() + False + sage: f = Stream_function(lambda n: 2*n, True, 0) + sage: Stream_zero() != f + False + sage: f[0] + 0 + sage: Stream_zero() != f + False + sage: f[1] + 2 + sage: Stream_zero() != f + True + """ + return self is not other and not isinstance(other, Stream_zero) and other.is_nonzero() + def __hash__(self): """ Return the hash of ``self``. @@ -1545,18 +1696,15 @@ def get_coefficient(self, n): sage: [h.get_coefficient(i) for i in range(10)] [0, 0, 1, 6, 20, 50, 105, 196, 336, 540] """ - c = ZZ.zero() - for k in range(self._left._approximate_order, - n - self._right._approximate_order + 1): - val = self._left[k] - if val: - c += val * self._right[n-k] - return c + return sum(l * self._right[n - k] + for k in range(self._left._approximate_order, + n - self._right._approximate_order + 1) + if (l := self._left[k])) def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -1574,6 +1722,14 @@ def is_nonzero(self): return self._left.is_nonzero() and self._right.is_nonzero() +class Stream_cauchy_mul_commutative(Stream_cauchy_mul, Stream_binaryCommutative): + """ + Operator for multiplication of two coefficient streams using the + Cauchy product for commutative multiplication of coefficients. + """ + pass + + class Stream_dirichlet_convolve(Stream_binary): r""" Operator for the Dirichlet convolution of two streams. @@ -1622,7 +1778,7 @@ def _approximate_order(self): or self._right._approximate_order <= 0): raise ValueError("Dirichlet convolution is only defined for " "coefficient streams with minimal index of " - "nonzero coefficient at least 1") + "non-zero coefficient at least 1") return self._left._approximate_order * self._right._approximate_order def get_coefficient(self, n): @@ -1644,123 +1800,10 @@ def get_coefficient(self, n): sage: [h[i] for i in range(1, 10)] [1, 3, 4, 7, 6, 12, 8, 15, 13] """ - c = ZZ.zero() - for k in divisors(n): - if k < self._left._approximate_order or n // k < self._right._approximate_order: - continue - val = self._left[k] - if val: - c += val * self._right[n//k] - return c - - -class Stream_dirichlet_invert(Stream_unary): - r""" - Operator for inverse with respect to Dirichlet convolution of the stream. - - INPUT: - - - ``series`` -- a :class:`Stream` - - EXAMPLES:: - - sage: from sage.data_structures.stream import (Stream_dirichlet_invert, Stream_function) - sage: f = Stream_function(lambda n: 1, True, 1) - sage: g = Stream_dirichlet_invert(f, True) - sage: [g[i] for i in range(10)] - [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] - sage: [moebius(i) for i in range(10)] - [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] - """ - def __init__(self, series, is_sparse): - """ - Initialize. - - TESTS:: - - sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) - sage: f = Stream_exact([0, 0], constant=1) - sage: g = Stream_dirichlet_invert(f, True) - sage: g[1] - Traceback (most recent call last): - ... - ZeroDivisionError: the Dirichlet inverse only exists if the coefficient with index 1 is non-zero - """ - super().__init__(series, is_sparse) - self._zero = ZZ.zero() - - @lazy_attribute - def _approximate_order(self): - """ - Compute and return the approximate order of ``self``. - - EXAMPLES:: - - sage: from sage.data_structures.stream import Stream_function, Stream_dirichlet_invert - sage: f = Stream_function(lambda n: n, True, 1) - sage: h = Stream_dirichlet_invert(f, True) - sage: h._approximate_order - 1 - sage: [h[i] for i in range(5)] - [0, -2, -8, -12, -48] - """ - # this is the true order, but we want to check first - if self._series._approximate_order > 1: - raise ZeroDivisionError("the Dirichlet inverse only exists if the " - "coefficient with index 1 is non-zero") - self._true_order = True - return 1 - - @lazy_attribute - def _ainv(self): - """ - The inverse of the leading coefficient. - - EXAMPLES:: - - sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) - sage: f = Stream_exact([0, 3], constant=2) - sage: g = Stream_dirichlet_invert(f, True) - sage: g._ainv - 1/3 - - sage: f = Stream_exact([Zmod(6)(5)], constant=2, order=1) - sage: g = Stream_dirichlet_invert(f, True) - sage: g._ainv - 5 - """ - try: - return ~self._series[1] - except TypeError: - return self._series[1].inverse_of_unit() - - def get_coefficient(self, n): - """ - Return the ``n``-th coefficient of ``self``. - - INPUT: - - - ``n`` -- integer; the degree for the coefficient - - EXAMPLES:: - - sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) - sage: f = Stream_exact([0, 3], constant=2) - sage: g = Stream_dirichlet_invert(f, True) - sage: g.get_coefficient(6) - 2/27 - sage: [g[i] for i in range(8)] - [0, 1/3, -2/9, -2/9, -2/27, -2/9, 2/27, -2/9] - """ - if n == 1: - return self._ainv - c = self._zero - for k in divisors(n): - if k < n: - val = self._series[n//k] - if val: - c += self[k] * val - return -c * self._ainv + return sum(l * self._right[n//k] for k in divisors(n) + if (k >= self._left._approximate_order + and n // k >= self._right._approximate_order + and (l := self._left[k]))) class Stream_cauchy_compose(Stream_binary): @@ -1860,19 +1903,23 @@ def get_coefficient(self, n): fv = self._left._approximate_order gv = self._right._approximate_order if n < 0: - return sum(f_coeff_i * self._neg_powers[-i][n] - for i in range(fv, n // gv + 1) - if (f_coeff_i := self._left[i])) + return sum(l * self._neg_powers[-k][n] + for k in range(fv, n // gv + 1) + if (l := self._left[k])) # n > 0 while len(self._pos_powers) <= n // gv: # TODO: possibly we always want a dense cache here? - self._pos_powers.append(Stream_cauchy_mul(self._pos_powers[-1], self._right, self._is_sparse)) - ret = sum(f_coeff_i * self._neg_powers[-i][n] for i in range(fv, 0) - if (f_coeff_i := self._left[i])) - if n == 0: + self._pos_powers.append(Stream_cauchy_mul(self._pos_powers[-1], + self._right, + self._is_sparse)) + ret = sum(l * self._neg_powers[-k][n] for k in range(fv, 0) + if (l := self._left[k])) + + if not n: ret += self._left[0] - return ret + sum(f_coeff_i * self._pos_powers[i][n] for i in range(1, n // gv + 1) - if (f_coeff_i := self._left[i])) + + return ret + sum(l * self._pos_powers[k][n] for k in range(1, n // gv + 1) + if (l := self._left[k])) class Stream_plethysm(Stream_binary): @@ -1897,6 +1944,7 @@ class Stream_plethysm(Stream_binary): EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_function, Stream_plethysm sage: s = SymmetricFunctions(QQ).s() sage: p = SymmetricFunctions(QQ).p() @@ -1920,6 +1968,7 @@ class Stream_plethysm(Stream_binary): This class also handles the plethysm of an exact stream with a stream of order `0`:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_exact sage: f = Stream_exact([s[1]], order=1) sage: g = Stream_function(lambda n: s[n], True, 0) @@ -1931,6 +1980,7 @@ class Stream_plethysm(Stream_binary): Check corner cases:: + sage: # needs sage.modules sage: f0 = Stream_exact([p([])]) sage: f1 = Stream_exact([p[1]], order=1) sage: f2 = Stream_exact([p[2]], order=2 ) @@ -1944,21 +1994,24 @@ class Stream_plethysm(Stream_binary): Check that degree one elements are treated in the correct way:: + sage: # needs sage.modules sage: R. = QQ[]; p = SymmetricFunctions(R).p() sage: f_s = a1*p[1] + a2*p[2] + a11*p[1,1] sage: g_s = b1*p[1] + b21*p[2,1] + b111*p[1,1,1] sage: r_s = f_s(g_s) - sage: f = Stream_exact([f_s.restrict_degree(k) for k in range(f_s.degree()+1)]) - sage: g = Stream_exact([g_s.restrict_degree(k) for k in range(g_s.degree()+1)]) + sage: f = Stream_exact([f_s.restrict_degree(k) + ....: for k in range(f_s.degree()+1)]) + sage: g = Stream_exact([g_s.restrict_degree(k) + ....: for k in range(g_s.degree()+1)]) sage: r = Stream_plethysm(f, g, True, p) sage: r_s == sum(r[n] for n in range(2*(r_s.degree()+1))) True - sage: r_s - f_s(g_s, include=[]) + sage: r_s - f_s(g_s, include=[]) # needs sage.modules (a2*b1^2-a2*b1)*p[2] + (a2*b111^2-a2*b111)*p[2, 2, 2] + (a2*b21^2-a2*b21)*p[4, 2] - sage: r2 = Stream_plethysm(f, g, True, p, include=[]) - sage: r_s - sum(r2[n] for n in range(2*(r_s.degree()+1))) + sage: r2 = Stream_plethysm(f, g, True, p, include=[]) # needs sage.modules + sage: r_s - sum(r2[n] for n in range(2*(r_s.degree()+1))) # needs sage.modules (a2*b1^2-a2*b1)*p[2] + (a2*b111^2-a2*b111)*p[2, 2, 2] + (a2*b21^2-a2*b21)*p[4, 2] """ @@ -1968,6 +2021,7 @@ def __init__(self, f, g, is_sparse, p, ring=None, include=None, exclude=None): TESTS:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_function, Stream_plethysm sage: s = SymmetricFunctions(QQ).s() sage: p = SymmetricFunctions(QQ).p() @@ -1989,7 +2043,7 @@ def __init__(self, f, g, is_sparse, p, ring=None, include=None, exclude=None): self._basis = ring self._p = p g = Stream_map_coefficients(g, lambda x: p(x), is_sparse) - self._powers = [g] # a cache for the powers of g + self._powers = [g] # a cache for the powers of g in the powersum basis R = self._basis.base_ring() self._degree_one = _variables_recursive(R, include=include, exclude=exclude) @@ -2009,6 +2063,7 @@ def _approximate_order(self): EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_function, Stream_plethysm sage: p = SymmetricFunctions(QQ).p() sage: f = Stream_function(lambda n: p[n], True, 1) @@ -2035,6 +2090,7 @@ def get_coefficient(self, n): EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_function, Stream_plethysm sage: s = SymmetricFunctions(QQ).s() sage: p = SymmetricFunctions(QQ).p() @@ -2054,26 +2110,25 @@ def get_coefficient(self, n): if not n: # special case of 0 if self._right[0]: assert self._degree_f is not None, "the plethysm with a lazy symmetric function of valuation 0 is defined only for symmetric functions of finite support" + K = self._degree_f + else: + K = 1 + else: + K = n + 1 - return sum((c * self.compute_product(n, la) - for k in range(self._left._approximate_order, self._degree_f) - if self._left[k] - for la, c in self._left[k]), - self._basis.zero()) - - res = sum((c * self.compute_product(n, la) - for k in range(self._left._approximate_order, n+1) - if self._left[k] - for la, c in self._left[k]), - self._basis.zero()) - return res + return sum((c * self.compute_product(n, la) + for k in range(self._left._approximate_order, K) + if self._left[k] # necessary, because it might be int(0) + for la, c in self._left[k]), + self._basis.zero()) def compute_product(self, n, la): r""" - Compute the product ``c * p[la](self._right)`` in degree ``n``. + Compute the product ``p[la](self._right)`` in degree ``n``. EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_plethysm, Stream_exact, Stream_function, Stream_zero sage: s = SymmetricFunctions(QQ).s() sage: p = SymmetricFunctions(QQ).p() @@ -2086,21 +2141,26 @@ def compute_product(self, n, la): sage: A == p[2, 1](s[2] + s[3]).homogeneous_component(7) True + sage: # needs sage.modules sage: p2 = tensor([p, p]) sage: f = Stream_exact([1]) # irrelevant for this test - sage: g = Stream_function(lambda n: sum(tensor([p[k], p[n-k]]) for k in range(n+1)), True, 1) + sage: g = Stream_function(lambda n: sum(tensor([p[k], p[n-k]]) + ....: for k in range(n+1)), True, 1) sage: h = Stream_plethysm(f, g, True, p2) sage: A = h.compute_product(7, Partition([2, 1])) sage: B = p[2, 1](sum(g[n] for n in range(7))) - sage: B = p2.element_class(p2, {m: c for m, c in B if sum(mu.size() for mu in m) == 7}) + sage: B = p2.element_class(p2, {m: c for m, c in B + ....: if sum(mu.size() for mu in m) == 7}) sage: A == B True + sage: # needs sage.modules sage: f = Stream_exact([1]) # irrelevant for this test sage: g = Stream_function(lambda n: s[n], True, 0) sage: h = Stream_plethysm(f, g, True, p) sage: B = p[2, 2, 1](sum(p(s[i]) for i in range(7))) - sage: all(h.compute_product(k, Partition([2, 2, 1])) == B.restrict_degree(k) for k in range(7)) + sage: all(h.compute_product(k, Partition([2, 2, 1])) + ....: == B.restrict_degree(k) for k in range(7)) True """ # This is the approximate order of the result @@ -2118,22 +2178,35 @@ def compute_product(self, n, la): wgt.reverse() exp.reverse() for k in wt_int_vec_iter(n - ret_approx_order, wgt): - # TODO: it may make a big difference here if the - # approximate order would be updated. - # The test below is based on not removing the fixed block - #if any(d < self._right._approximate_order * m - # for m, d in zip(exp, k)): - # continue - ret += prod(self.stretched_power_restrict_degree(i, m, rao * m + d) - for i, m, d in zip(wgt, exp, k)) + # prod does not short-cut zero, therefore + # ret += prod(self.stretched_power_restrict_degree(i, m, rao * m + d) + # for i, m, d in zip(wgt, exp, k)) + # is expensive + lf = [] + for i, m, d in zip(wgt, exp, k): + f = self.stretched_power_restrict_degree(i, m, rao * m + d) + if not f: + break + lf.append(f) + else: + ret += prod(lf) + return ret + @cached_method def stretched_power_restrict_degree(self, i, m, d): r""" - Return the degree ``d*i`` part of ``p([i]*m)(g)``. + Return the degree ``d*i`` part of ``p([i]*m)(g)`` in + terms of ``self._basis``. + + INPUT: + + - ``i``, ``m`` -- positive integers + - ``d`` -- integer EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import Stream_plethysm, Stream_exact, Stream_function, Stream_zero sage: s = SymmetricFunctions(QQ).s() sage: p = SymmetricFunctions(QQ).p() @@ -2144,50 +2217,58 @@ def stretched_power_restrict_degree(self, i, m, d): sage: A == p[2,2,2](s[2] + s[3]).homogeneous_component(12) True + sage: # needs sage.modules sage: p2 = tensor([p, p]) sage: f = Stream_exact([1]) # irrelevant for this test - sage: g = Stream_function(lambda n: sum(tensor([p[k], p[n-k]]) for k in range(n+1)), True, 1) + sage: g = Stream_function(lambda n: sum(tensor([p[k], p[n-k]]) + ....: for k in range(n+1)), True, 1) sage: h = Stream_plethysm(f, g, True, p2) sage: A = h.stretched_power_restrict_degree(2, 3, 6) - sage: B = p[2,2,2](sum(g[n] for n in range(7))) # long time - sage: B = p2.element_class(p2, {m: c for m, c in B if sum(mu.size() for mu in m) == 12}) # long time - sage: A == B # long time + sage: B = p[2,2,2](sum(g[n] for n in range(7))) # long time + sage: B = p2.element_class(p2, {m: c for m, c in B # long time + ....: if sum(mu.size() for mu in m) == 12}) + sage: A == B # long time True + """ + # TODO: we should do lazy binary powering here while len(self._powers) < m: # TODO: possibly we always want a dense cache here? - self._powers.append(Stream_cauchy_mul(self._powers[-1], self._powers[0], self._is_sparse)) + self._powers.append(Stream_cauchy_mul(self._powers[-1], + self._powers[0], + self._is_sparse)) power_d = self._powers[m-1][d] # we have to check power_d for zero because it might be an # integer and not a symmetric function if power_d: + # _raise_variables(c, i, self._degree_one) cannot vanish + # because i is positive and c is non-zero if self._tensor_power is None: - terms = {mon.stretch(i): raised_c for mon, c in power_d - if (raised_c := _raise_variables(c, i, self._degree_one))} + terms = {mon.stretch(i): + _raise_variables(c, i, self._degree_one) + for mon, c in power_d} else: - terms = {tuple((mu.stretch(i) for mu in mon)): raised_c - for mon, c in power_d - if (raised_c := _raise_variables(c, i, self._degree_one))} - return self._p.element_class(self._p, terms) + terms = {tuple((mu.stretch(i) for mu in mon)): + _raise_variables(c, i, self._degree_one) + for mon, c in power_d} + return self._basis(self._p.element_class(self._p, terms)) - return self._p.zero() + return self._basis.zero() ##################################################################### # Unary operations -class Stream_scalar(Stream_inexact): +class Stream_scalar(Stream_unary): """ Base class for operators multiplying a coefficient stream by a scalar. - .. TODO:: - - This does not inherit from :class:`Stream_unary`, because of - the extra argument ``scalar``. However, we could also - override :meth:`Stream_unary.hash`, - :meth:`Stream_unary.__eq__`. Would this be any better? + INPUT: + - ``series`` -- a :class:`Stream` + - ``scalar`` -- a non-zero, non-one scalar + - ``is_sparse`` -- boolean """ def __init__(self, series, scalar, is_sparse): """ @@ -2199,10 +2280,10 @@ def __init__(self, series, scalar, is_sparse): sage: f = Stream_function(lambda n: -1, True, 0) sage: g = Stream_rmul(f, 3, True) """ - self._series = series self._scalar = scalar assert scalar, "the scalar must not be equal to 0" - super().__init__(is_sparse, series._true_order) + assert scalar != 1, "the scalar must not be equal to 1" + super().__init__(series, is_sparse, series._true_order) @lazy_attribute def _approximate_order(self): @@ -2267,7 +2348,7 @@ def __eq__(self, other): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -2294,10 +2375,11 @@ class Stream_rmul(Stream_scalar): INPUT: - ``series`` -- a :class:`Stream` - - ``scalar`` -- a scalar + - ``scalar`` -- a non-zero, non-one scalar EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import (Stream_rmul, Stream_function) sage: W = algebras.DifferentialWeyl(QQ, names=('x',)) sage: x, dx = W.gens() @@ -2335,10 +2417,11 @@ class Stream_lmul(Stream_scalar): INPUT: - ``series`` -- a :class:`Stream` - - ``scalar`` -- a scalar + - ``scalar`` -- a non-zero, non-one scalar EXAMPLES:: + sage: # needs sage.modules sage: from sage.data_structures.stream import (Stream_lmul, Stream_function) sage: W = algebras.DifferentialWeyl(QQ, names=('x',)) sage: x, dx = W.gens() @@ -2441,7 +2524,7 @@ def get_coefficient(self, n): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -2470,7 +2553,8 @@ class Stream_cauchy_invert(Stream_unary): - ``approximate_order`` -- ``None``, or a lower bound on the order of the resulting stream - Instances of this class are always dense. + Instances of this class are always dense, because of mathematical + necessities. EXAMPLES:: @@ -2579,9 +2663,9 @@ def iterate_coefficients(self): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. - An assumption of this class is that it is nonzero. + An assumption of this class is that it is non-zero. EXAMPLES:: @@ -2594,23 +2678,135 @@ def is_nonzero(self): return True -class Stream_map_coefficients(Stream_inexact): +class Stream_dirichlet_invert(Stream_unary): r""" - The stream with ``function`` applied to each nonzero coefficient - of ``series``. + Operator for inverse with respect to Dirichlet convolution of the stream. INPUT: - ``series`` -- a :class:`Stream` - - ``function`` -- a function that modifies the elements of the stream EXAMPLES:: - sage: from sage.data_structures.stream import (Stream_map_coefficients, Stream_function) + sage: from sage.data_structures.stream import (Stream_dirichlet_invert, Stream_function) sage: f = Stream_function(lambda n: 1, True, 1) - sage: g = Stream_map_coefficients(f, lambda n: -n, True) + sage: g = Stream_dirichlet_invert(f, True) sage: [g[i] for i in range(10)] - [0, -1, -1, -1, -1, -1, -1, -1, -1, -1] + [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] + sage: [moebius(i) for i in range(10)] # needs sage.libs.pari + [0, 1, -1, -1, 0, -1, 1, -1, 0, 0] + """ + def __init__(self, series, is_sparse): + """ + Initialize. + + TESTS:: + + sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) + sage: f = Stream_exact([0, 0], constant=1) + sage: g = Stream_dirichlet_invert(f, True) + sage: g[1] + Traceback (most recent call last): + ... + ZeroDivisionError: the Dirichlet inverse only exists if the coefficient with index 1 is non-zero + """ + super().__init__(series, is_sparse) + self._zero = ZZ.zero() + + @lazy_attribute + def _approximate_order(self): + """ + Compute and return the approximate order of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_function, Stream_dirichlet_invert + sage: f = Stream_function(lambda n: n, True, 1) + sage: h = Stream_dirichlet_invert(f, True) + sage: h._approximate_order + 1 + sage: [h[i] for i in range(5)] + [0, -2, -8, -12, -48] + """ + # this is the true order, but we want to check first + if self._series._approximate_order > 1: + raise ZeroDivisionError("the Dirichlet inverse only exists if the " + "coefficient with index 1 is non-zero") + self._true_order = True + return 1 + + @lazy_attribute + def _ainv(self): + """ + The inverse of the leading coefficient. + + EXAMPLES:: + + sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) + sage: f = Stream_exact([0, 3], constant=2) + sage: g = Stream_dirichlet_invert(f, True) + sage: g._ainv + 1/3 + + sage: f = Stream_exact([Zmod(6)(5)], constant=2, order=1) + sage: g = Stream_dirichlet_invert(f, True) + sage: g._ainv + 5 + """ + try: + return ~self._series[1] + except TypeError: + return self._series[1].inverse_of_unit() + + def get_coefficient(self, n): + """ + Return the ``n``-th coefficient of ``self``. + + INPUT: + + - ``n`` -- integer; the degree for the coefficient + + EXAMPLES:: + + sage: from sage.data_structures.stream import (Stream_exact, Stream_dirichlet_invert) + sage: f = Stream_exact([0, 3], constant=2) + sage: g = Stream_dirichlet_invert(f, True) + sage: g.get_coefficient(6) + 2/27 + sage: [g[i] for i in range(8)] + [0, 1/3, -2/9, -2/9, -2/27, -2/9, 2/27, -2/9] + """ + if n == 1: + return self._ainv + # TODO: isn't self[k] * l and l * self[k] the same here? + c = sum(self[k] * l for k in divisors(n) + if (k < n + and (l := self._series[n // k]))) + return -c * self._ainv + + +class Stream_map_coefficients(Stream_unary): + r""" + The stream with ``function`` applied to each non-zero coefficient + of ``series``. + + INPUT: + + - ``series`` -- a :class:`Stream` + - ``function`` -- a function that modifies the elements of the stream + + .. NOTE:: + + We assume for equality that ``function`` is a function in the + mathematical sense. + + EXAMPLES:: + + sage: from sage.data_structures.stream import (Stream_map_coefficients, Stream_function) + sage: f = Stream_function(lambda n: 1, True, 1) + sage: g = Stream_map_coefficients(f, lambda n: -n, True) + sage: [g[i] for i in range(10)] + [0, -1, -1, -1, -1, -1, -1, -1, -1, -1] """ def __init__(self, series, function, is_sparse, approximate_order=None, true_order=False): @@ -2625,8 +2821,7 @@ def __init__(self, series, function, is_sparse, approximate_order=None, true_ord sage: TestSuite(g).run(skip="_test_pickling") """ self._function = function - self._series = series - super().__init__(is_sparse, true_order) + super().__init__(series, is_sparse, true_order) if approximate_order is not None: self._approximate_order = approximate_order @@ -2717,7 +2912,7 @@ def __eq__(self, other): class Stream_shift(Stream): """ - Operator for shifting a nonzero, nonexact stream. + Operator for shifting a non-zero, non-exact stream. Instances of this class share the cache with its input stream. @@ -2763,7 +2958,7 @@ def _approximate_order(self): def order(self): r""" Return the order of ``self``, which is the minimum index - ``n`` such that ``self[n]`` is nonzero. + ``n`` such that ``self[n]`` is non-zero. EXAMPLES:: @@ -2789,7 +2984,7 @@ def __getitem__(self, n): sage: [M[i] for i in range(6)] [0, 0, 0, 1, 2, 3] """ - return self._series[n-self._shift] + return self._series[n - self._shift] def __hash__(self): """ @@ -2826,15 +3021,16 @@ def __eq__(self, other): sage: M2 == Stream_shift(F, 2) True """ - return (isinstance(other, type(self)) and self._shift == other._shift + return (isinstance(other, type(self)) + and self._shift == other._shift and self._series == other._series) def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. - An assumption of this class is that it is nonzero. + An assumption of this class is that it is non-zero. EXAMPLES:: @@ -2846,10 +3042,24 @@ def is_nonzero(self): """ return self._series.is_nonzero() + def is_uninitialized(self): + """ + Return ``True`` if ``self`` is an uninitialized stream. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_uninitialized, Stream_shift + sage: C = Stream_uninitialized(0) + sage: S = Stream_shift(C, 5) + sage: S.is_uninitialized() + True + """ + return self._series.is_uninitialized() + -class Stream_truncated(Stream_inexact): +class Stream_truncated(Stream_unary): """ - Operator for shifting a nonzero, nonexact stream that has + Operator for shifting a non-zero, non-exact stream that has been shifted below its minimal valuation. Instances of this class share the cache with its input stream. @@ -2897,9 +3107,8 @@ def __init__(self, series, shift, minimal_valuation): sage: s._approximate_order 3 """ - super().__init__(series._is_sparse, False) + super().__init__(series, series._is_sparse, False) assert isinstance(series, Stream_inexact) - self._series = series # We share self._series._cache but not self._series._approximate order # self._approximate_order cannot be updated by self._series.__getitem__ self._cache = series._cache @@ -3010,7 +3219,7 @@ def __eq__(self, other): def order(self): """ Return the order of ``self``, which is the minimum index ``n`` such - that ``self[n]`` is nonzero. + that ``self[n]`` is non-zero. EXAMPLES:: @@ -3056,7 +3265,7 @@ def order(self): def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -3096,14 +3305,15 @@ def is_nonzero(self): return any(self._cache[start:]) -class Stream_derivative(Stream_inexact): +class Stream_derivative(Stream_unary): """ - Operator for taking derivatives of a stream. + Operator for taking derivatives of a non-exact stream. INPUT: - ``series`` -- a :class:`Stream` - ``shift`` -- a positive integer + - ``is_sparse`` -- boolean """ def __init__(self, series, shift, is_sparse): """ @@ -3116,9 +3326,8 @@ def __init__(self, series, shift, is_sparse): sage: f2 = Stream_derivative(f, 2, True) sage: TestSuite(f2).run() """ - self._series = series self._shift = shift - super().__init__(is_sparse, False) + super().__init__(series, is_sparse, False) @lazy_attribute def _approximate_order(self): @@ -3162,7 +3371,7 @@ def __getitem__(self, n): sage: [f2[i] for i in range(-1, 4)] [0, 2, 6, 12, 20] """ - return (prod(n+k for k in range(1, self._shift + 1)) + return (prod(n + k for k in range(1, self._shift + 1)) * self._series[n + self._shift]) def __hash__(self): @@ -3180,7 +3389,6 @@ def __hash__(self): True sage: hash(f) == hash(g) False - """ return hash((type(self), self._series, self._shift)) @@ -3204,13 +3412,14 @@ def __eq__(self, other): sage: f == Stream_derivative(a, 1, True) True """ - return (isinstance(other, type(self)) and self._shift == other._shift + return (isinstance(other, type(self)) + and self._shift == other._shift and self._series == other._series) def is_nonzero(self): r""" Return ``True`` if and only if this stream is known - to be nonzero. + to be non-zero. EXAMPLES:: @@ -3222,3 +3431,323 @@ def is_nonzero(self): True """ return self._series.is_nonzero() + + +class Stream_infinite_operator(Stream): + r""" + Stream defined by applying an operator an infinite number of times. + + The ``iterator`` returns elements `s_i` to compute an infinite operator. + The valuation of `s_i` is weakly increasing as we iterate over `I` and + there are only finitely many terms with any fixed valuation. + In particular, this *assumes* the result is nonzero. + + .. WARNING:: + + This does not check that the input is valid. + + INPUT: + + - ``iterator`` -- the iterator for the factors + """ + def __init__(self, iterator): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + """ + self._op_iter = iterator + self._cur = None + self._cur_order = -infinity + super().__init__(False) + + @lazy_attribute + def _approximate_order(self): + r""" + Compute and return the approximate order of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum, Stream_infinite_product + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f._approximate_order + 1 + sage: it = (t^n for n in PositiveIntegers()) + sage: f = Stream_infinite_product(it) + sage: f._approximate_order + 0 + sage: it = (t^(n-10) for n in PositiveIntegers()) + sage: f = Stream_infinite_product(it) + sage: f._approximate_order + -45 + """ + if self._cur is None: + self._advance() + while self._cur_order <= 0: + self._advance() + return self._cur._coeff_stream._approximate_order + + def _advance(self): + r""" + Advance the iterator so that the approximate order increases + by at least one. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (n * t^n for n in range(10)) + sage: f = Stream_infinite_sum(it) + sage: f._cur is None + True + sage: f._advance() + sage: f._cur + t + 2*t^2 + sage: f._cur_order + 2 + sage: for _ in range(20): + ....: f._advance() + sage: f._cur + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 6*t^6 + 7*t^7 + 8*t^8 + 9*t^9 + sage: f._cur_order + +Infinity + + sage: it = (t^(n//3) / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f._advance() + sage: f._cur + 2 + 3*t + 3*t^2 + 3*t^3 + O(t^4) + sage: f._advance() + sage: f._cur + 2 + 5*t + 6*t^2 + 6*t^3 + 6*t^4 + O(t^5) + """ + if self._cur is None: + temp = next(self._op_iter) + if isinstance(temp._coeff_stream, Stream_zero): + self._advance() + return + self.initial(temp) + self._cur_order = temp._coeff_stream._approximate_order + + order = self._cur_order + while order == self._cur_order: + try: + next_factor = next(self._op_iter) + except StopIteration: + self._cur_order = infinity + return + if isinstance(next_factor._coeff_stream, Stream_zero): + continue + coeff_stream = next_factor._coeff_stream + while coeff_stream._approximate_order < order: + # This check also updates the next_factor._approximate_order + if coeff_stream[coeff_stream._approximate_order]: + order = coeff_stream._approximate_order + raise ValueError(f"invalid product computation with invalid order {order} < {self._cur_order}") + self.apply_operator(next_factor) + order = coeff_stream._approximate_order + # We check to see if we need to increment the order + if order == self._cur_order and not coeff_stream[order]: + order += 1 + self._cur_order = order + + def __getitem__(self, n): + r""" + Return the ``n``-th coefficient of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f[2] + 2 + sage: f[5] + 5 + """ + while n >= self._cur_order: + self._advance() + return self._cur[n] + + def order(self): + r""" + Return the order of ``self``, which is the minimum index ``n`` such + that ``self[n]`` is nonzero. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^(5+n) / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f.order() + 6 + """ + return self._approximate_order + + def __hash__(self): + r""" + Return the hash of ``self``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: hash(f) == hash((type(f), f._op_iter)) + True + """ + return hash((type(self), self._op_iter)) + + def __ne__(self, other): + r""" + Return whether ``self`` and ``other`` are known to be equal. + + INPUT: + + - ``other`` -- a stream + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: itf = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(itf) + sage: itg = (t^(2*n-1) / (1 - t) for n in PositiveIntegers()) + sage: g = Stream_infinite_sum(itg) + sage: f != g + False + sage: f[10] + 10 + sage: g[10] + 5 + sage: f != g + True + """ + if not isinstance(other, type(self)): + return True + ao = min(self._approximate_order, other._approximate_order) + if any(self[i] != other[i] for i in range(ao, min(self._cur_order, other._cur_order))): + return True + return False + + def is_nonzero(self): + r""" + Return ``True`` if and only if this stream is known + to be nonzero. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f.is_nonzero() + True + """ + return True + + +class Stream_infinite_sum(Stream_infinite_operator): + r""" + Stream defined by an infinite sum. + + The ``iterator`` returns elements `s_i` to compute the product + `\sum_{i \in I} s_i`. See :class:`Stream_infinite_operator` + for restrictions on the `s_i`. + + INPUT: + + - ``iterator`` -- the iterator for the factors + """ + def initial(self, obj): + r""" + Set the initial data. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f._cur is None + True + sage: f._advance() # indirect doctest + sage: f._cur + t + 2*t^2 + 2*t^3 + 2*t^4 + O(t^5) + """ + self._cur = obj + + def apply_operator(self, next_obj): + r""" + Apply the operator to ``next_obj``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_sum + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^(n//2) / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_sum(it) + sage: f._advance() + sage: f._advance() # indirect doctest + sage: f._cur + 1 + 3*t + 4*t^2 + 4*t^3 + 4*t^4 + O(t^5) + """ + self._cur += next_obj + + +class Stream_infinite_product(Stream_infinite_operator): + r""" + Stream defined by an infinite product. + + The ``iterator`` returns elements `p_i` to compute the product + `\prod_{i \in I} (1 + p_i)`. See :class:`Stream_infinite_operator` + for restrictions on the `p_i`. + + INPUT: + + - ``iterator`` -- the iterator for the factors + """ + def initial(self, obj): + r""" + Set the initial data. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_product + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_product(it) + sage: f._cur is None + True + sage: f._advance() # indirect doctest + sage: f._cur + 1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 6*t^6 + O(t^7) + """ + self._cur = obj + 1 + + def apply_operator(self, next_obj): + r""" + Apply the operator to ``next_obj``. + + EXAMPLES:: + + sage: from sage.data_structures.stream import Stream_infinite_product + sage: L. = LazyLaurentSeriesRing(QQ) + sage: it = (t^n / (1 - t) for n in PositiveIntegers()) + sage: f = Stream_infinite_product(it) + sage: f._advance() + sage: f._advance() # indirect doctest + sage: f._cur + 1 + t + 2*t^2 + 4*t^3 + 6*t^4 + 9*t^5 + 13*t^6 + O(t^7) + """ + self._cur = self._cur + self._cur * next_obj diff --git a/src/sage/databases/cremona.py b/src/sage/databases/cremona.py index 19cd672bb0f..54e83d639ad 100644 --- a/src/sage/databases/cremona.py +++ b/src/sage/databases/cremona.py @@ -217,7 +217,7 @@ def cremona_letter_code(n): Traceback (most recent call last): ... ValueError: Cremona letter codes are only defined for non-negative integers - sage: cremona_letter_code(x) + sage: cremona_letter_code(x) # needs sage.symbolic Traceback (most recent call last): ... ValueError: Cremona letter codes are only defined for non-negative integers diff --git a/src/sage/databases/cubic_hecke_db.py b/src/sage/databases/cubic_hecke_db.py index 99e96a9b816..b78e582d91e 100644 --- a/src/sage/databases/cubic_hecke_db.py +++ b/src/sage/databases/cubic_hecke_db.py @@ -1493,6 +1493,7 @@ def read_markov(bas_ele, variables, num_strands=4): EXAMPLES:: + sage: # needs sympy sage: from sage.databases.cubic_hecke_db import read_markov sage: from sympy import var sage: u, v, w, s = var('u, v, w, s') diff --git a/src/sage/databases/db_modular_polynomials.py b/src/sage/databases/db_modular_polynomials.py index d9f4b0752c2..4e0422539fc 100644 --- a/src/sage/databases/db_modular_polynomials.py +++ b/src/sage/databases/db_modular_polynomials.py @@ -20,16 +20,17 @@ def _dbz_to_string(name): r""" TESTS:: + sage: # optional - database_kohel sage: from sage.databases.db_modular_polynomials import _dbz_to_string - sage: _dbz_to_string('PolMod/Atk/pol.002.dbz') # optional - database_kohel + sage: _dbz_to_string('PolMod/Atk/pol.002.dbz') '3 0 1 \n2 1 -1 \n2 0 744 \n1 1 -1 \n1 0 184512 \n0 2 1 \n0 1 7256 \n0 0 15252992 \n' - sage: _dbz_to_string('PolMod/Cls/pol.001.dbz') # optional - database_kohel + sage: _dbz_to_string('PolMod/Cls/pol.001.dbz') '1 0 1 \n' - sage: _dbz_to_string('PolMod/Eta/pol.002.dbz') # optional - database_kohel + sage: _dbz_to_string('PolMod/Eta/pol.002.dbz') '3 0 1 \n2 0 48 \n1 1 -1 \n1 0 768 \n0 0 4096 \n' - sage: _dbz_to_string('PolMod/EtaCrr/crr.02.002.dbz') # optional - database_kohel + sage: _dbz_to_string('PolMod/EtaCrr/crr.02.002.dbz') '2 1 1 \n2 0 -48 \n1 1 2304 \n0 2 -4096 \n0 1 196608 \n' - sage: _dbz_to_string('PolHeeg/Cls/0000001-0005000/pol.0000003.dbz') # optional - database_kohel + sage: _dbz_to_string('PolHeeg/Cls/0000001-0005000/pol.0000003.dbz') '0\n1\n' """ from sage.env import SAGE_SHARE diff --git a/src/sage/databases/findstat.py b/src/sage/databases/findstat.py index 323a7a22910..86ab944744a 100644 --- a/src/sage/databases/findstat.py +++ b/src/sage/databases/findstat.py @@ -259,6 +259,7 @@ def mapping(sigma): from sage.combinat.colored_permutations import SignedPermutation, SignedPermutations from sage.combinat.plane_partition import PlanePartition from sage.combinat.decorated_permutation import DecoratedPermutation, DecoratedPermutations +from sage.combinat.set_partition_ordered import OrderedSetPartition, OrderedSetPartitions ###################################################################### # the FindStat URLs @@ -1556,11 +1557,12 @@ def reset(self): Check that new statistics and maps cannot be reset:: - sage: q = findstat([(d, randint(1, 1000)) for d in DyckWords(4)]) # optional -- internet - sage: q.set_description("Random values on Dyck paths.") # optional -- internet - sage: print(q.description()) # optional -- internet + sage: # optional - internet + sage: q = findstat([(d, randint(1, 1000)) for d in DyckWords(4)]) + sage: q.set_description("Random values on Dyck paths.") + sage: print(q.description()) Random values on Dyck paths. - sage: q.reset() # optional -- internet + sage: q.reset() Traceback (most recent call last): ... ValueError: cannot reset values of St000000: a new statistic on Dyck paths @@ -3280,14 +3282,15 @@ def set_properties_raw(self, value): EXAMPLES:: - sage: from sage.databases.findstat import FindStatMap # optional -- internet - sage: FindStatMap(61).set_properties_raw('surjective') # optional -- internet - sage: FindStatMap(61).properties_raw() # optional -- internet + sage: # optional - internet + sage: from sage.databases.findstat import FindStatMap + sage: FindStatMap(61).set_properties_raw('surjective') + sage: FindStatMap(61).properties_raw() 'surjective' - sage: FindStatMap(61) # optional -- internet + sage: FindStatMap(61) Mp00061(modified): to increasing tree - sage: FindStatMap(61).reset() # optional -- internet - sage: FindStatMap(61) # optional -- internet + sage: FindStatMap(61).reset() + sage: FindStatMap(61) Mp00061: to increasing tree """ if value != self.properties_raw(): @@ -4283,13 +4286,14 @@ def in_range(self, element): EXAMPLES:: + sage: # optional - internet sage: from sage.databases.findstat import FindStatCollection - sage: c = FindStatCollection("GelfandTsetlinPatterns") # optional -- internet - sage: c.in_range(GelfandTsetlinPattern([[2, 1], [1]])) # optional -- internet + sage: c = FindStatCollection("GelfandTsetlinPatterns") + sage: c.in_range(GelfandTsetlinPattern([[2, 1], [1]])) True - sage: c.in_range(GelfandTsetlinPattern([[3, 1], [1]])) # optional -- internet + sage: c.in_range(GelfandTsetlinPattern([[3, 1], [1]])) True - sage: c.in_range(GelfandTsetlinPattern([[7, 1], [1]])) # optional -- internet + sage: c.in_range(GelfandTsetlinPattern([[7, 1], [1]])) False TESTS:: @@ -4512,6 +4516,7 @@ def name(self, style="singular"): return self._data["NamePlural"] raise ValueError("argument 'style' (=%s) must be 'singular' or 'plural'" % style) + from collections import namedtuple _SupportedFindStatCollection = namedtuple("SupportedFindStatCollection", ["string_to_element", @@ -4670,7 +4675,13 @@ def name(self, style="singular"): for i, v in enumerate(x, 1))) + "]", DecoratedPermutations, lambda x: x.size(), - lambda x: isinstance(x, DecoratedPermutation))} + lambda x: isinstance(x, DecoratedPermutation)), + "OrderedSetPartitions": + _SupportedFindStatCollection(lambda x: OrderedSetPartition(literal_eval(x.replace('{','[').replace('}',']'))), + str, + OrderedSetPartitions, + lambda x: x.size(), + lambda x: isinstance(x, OrderedSetPartition))} class FindStatCollections(UniqueRepresentation, Parent): diff --git a/src/sage/databases/jones.py b/src/sage/databases/jones.py index 5afcaaa3f6b..26d4dbaa373 100644 --- a/src/sage/databases/jones.py +++ b/src/sage/databases/jones.py @@ -256,20 +256,21 @@ def ramified_at(self, S, d=None, var='a'): EXAMPLES:: - sage: J = JonesDatabase() # optional - database_jones_numfield - sage: J.ramified_at([101,109]) # optional - database_jones_numfield + sage: # optional - database_jones_numfield + sage: J = JonesDatabase() + sage: J.ramified_at([101,109]) [] - sage: J.ramified_at([109]) # optional - database_jones_numfield + sage: J.ramified_at([109]) [Number Field in a with defining polynomial x^2 - 109, Number Field in a with defining polynomial x^3 - x^2 - 36*x + 4, Number Field in a with defining polynomial x^4 - x^3 + 14*x^2 + 34*x + 393] - sage: J.ramified_at(101) # optional - database_jones_numfield + sage: J.ramified_at(101) [Number Field in a with defining polynomial x^2 - 101, Number Field in a with defining polynomial x^4 - x^3 + 13*x^2 - 19*x + 361, Number Field in a with defining polynomial x^5 + x^4 - 6*x^3 - x^2 + 18*x + 4, Number Field in a with defining polynomial x^5 + 2*x^4 + 7*x^3 + 4*x^2 + 11*x - 6, Number Field in a with defining polynomial x^5 - x^4 - 40*x^3 - 93*x^2 - 21*x + 17] - sage: J.ramified_at((2, 5, 29), 3, 'c') # optional - database_jones_numfield + sage: J.ramified_at((2, 5, 29), 3, 'c') [Number Field in c with defining polynomial x^3 - x^2 - 8*x - 28, Number Field in c with defining polynomial x^3 - x^2 + 10*x + 102, Number Field in c with defining polynomial x^3 - x^2 - 48*x - 188, diff --git a/src/sage/databases/oeis.py b/src/sage/databases/oeis.py index 368ee80e120..b6eeac3499c 100644 --- a/src/sage/databases/oeis.py +++ b/src/sage/databases/oeis.py @@ -5,8 +5,8 @@ You can query the OEIS (Online Database of Integer Sequences) through Sage in order to: - - identify a sequence from its first terms. - - obtain more terms, formulae, references, etc. for a given sequence. +- identify a sequence from its first terms. +- obtain more terms, formulae, references, etc. for a given sequence. AUTHORS: @@ -21,35 +21,36 @@ EXAMPLES:: - sage: oeis - The On-Line Encyclopedia of Integer Sequences (https://oeis.org/) + sage: oeis + The On-Line Encyclopedia of Integer Sequences (https://oeis.org/) What about a sequence starting with `3, 7, 15, 1` ? :: - sage: search = oeis([3, 7, 15, 1], max_results=4) ; search # optional -- internet # random + sage: # optional - internet + sage: search = oeis([3, 7, 15, 1], max_results=4); search # random 0: A001203: Simple continued fraction expansion of Pi. 1: A240698: Partial sums of divisors of n, cf. A027750. 2: A082495: a(n) = (2^n - 1) mod n. - 3: A165416: Irregular array read by rows: The n-th row contains those distinct positive integers that each, when written in binary, occurs as a substring in binary n. - - sage: [u.id() for u in search] # optional -- internet # random + 3: A165416: Irregular array read by rows: The n-th row contains those + distinct positive integers that each, when written in binary, + occurs as a substring in binary n. + sage: [u.id() for u in search] # random ['A001203', 'A240698', 'A082495', 'A165416'] - sage: c = search[0] ; c # optional -- internet + sage: c = search[0]; c A001203: Simple continued fraction expansion of Pi. :: - sage: c.first_terms(15) # optional -- internet + sage: # optional - internet + sage: c.first_terms(15) (3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1) - - sage: c.examples() # optional -- internet + sage: c.examples() 0: Pi = 3.1415926535897932384... 1: = 3 + 1/(7 + 1/(15 + 1/(1 + 1/(292 + ...)))) 2: = [a_0; a_1, a_2, a_3, ...] = [3; 7, 15, 1, 292, ...]. - - sage: c.comments() # optional -- internet + sage: c.comments() 0: The first 5821569425 terms were computed by _Eric W. Weisstein_ on Sep 18 2011. 1: The first 10672905501 terms were computed by _Eric W. Weisstein_ on Jul 17 2013. 2: The first 15000000000 terms were computed by _Eric W. Weisstein_ on Jul 27 2013. @@ -57,51 +58,49 @@ :: - sage: x = c.natural_object() ; type(x) # optional -- internet + sage: # optional - internet + sage: x = c.natural_object(); type(x) - - sage: x.convergents()[:7] # optional -- internet + sage: x.convergents()[:7] [3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317] - - sage: RR(x.value()) # optional -- internet + sage: RR(x.value()) 3.14159265358979 - sage: RR(x.value()) == RR(pi) # optional -- internet + sage: RR(x.value()) == RR(pi) True -What about posets ? Are they hard to count ? To which other structures are they -related ? +What about posets? Are they hard to count? To which other structures are they +related? :: + sage: # optional - internet sage: [Posets(i).cardinality() for i in range(10)] [1, 1, 2, 5, 16, 63, 318, 2045, 16999, 183231] - sage: oeis(_) # optional -- internet + sage: oeis(_) 0: A000112: Number of partially ordered sets ("posets") with n unlabeled elements. - sage: p = _[0] # optional -- internet - -:: - - sage: 'hard' in p.keywords() # optional -- internet + sage: p = _[0] + sage: 'hard' in p.keywords() True - sage: len(p.formulas()) # optional -- internet + sage: len(p.formulas()) 0 - sage: len(p.first_terms()) # optional -- internet + sage: len(p.first_terms()) 17 - -:: - - sage: p.cross_references(fetch=True) # optional -- internet # random - 0: A000798: Number of different quasi-orders (or topologies, or transitive digraphs) with n labeled elements. - 1: A001035: Number of partially ordered sets ("posets") with n labeled elements (or labeled acyclic transitive digraphs). + sage: p.cross_references(fetch=True) # random + 0: A000798: Number of different quasi-orders (or topologies, or transitive digraphs) + with n labeled elements. + 1: A001035: Number of partially ordered sets ("posets") with n labeled elements + (or labeled acyclic transitive digraphs). 2: A001930: Number of topologies, or transitive digraphs with n unlabeled nodes. 3: A006057: Number of topologies on n labeled points satisfying axioms T_0-T_4. 4: A079263: Number of constrained mixed models with n factors. 5: A079265: Number of antisymmetric transitive binary relations on n unlabeled points. - 6: A263859: Triangle read by rows: T(n,k) (n>=1, k>=0) is the number of posets with n elements and rank k (or depth k+1). + 6: A263859: Triangle read by rows: T(n,k) (n>=1, k>=0) is the number of posets + with n elements and rank k (or depth k+1). 7: A316978: Number of factorizations of n into factors > 1 with no equivalent primes. 8: A319559: Number of non-isomorphic T_0 set systems of weight n. 9: A326939: Number of T_0 sets of subsets of {1..n} that cover all n vertices. - 10: A326943: Number of T_0 sets of subsets of {1..n} that cover all n vertices and are closed under intersection. + 10: A326943: Number of T_0 sets of subsets of {1..n} that cover all n vertices and + are closed under intersection. ... What does the Taylor expansion of the `e^{e^x-1}` function have to do with @@ -109,25 +108,22 @@ :: + sage: # optional - internet, needs sage.symbolic sage: x = var('x') ; f(x) = e^(e^x - 1) - sage: L = [a*factorial(b) for a,b in taylor(f(x), x, 0, 20).coefficients()] ; L + sage: L = [a*factorial(b) for a,b in taylor(f(x), x, 0, 20).coefficients()]; L [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, 4213597, - 27644437, 190899322, 1382958545, 10480142147, 82864869804, 682076806159, - 5832742205057, 51724158235372] - - sage: oeis(L) # optional -- internet - 0: A000110: Bell or exponential numbers: number of ways to partition a set of n labeled elements. + 27644437, 190899322, 1382958545, 10480142147, 82864869804, 682076806159, + 5832742205057, 51724158235372] + sage: oeis(L) + 0: A000110: Bell or exponential numbers: number of ways to partition + a set of n labeled elements. 1: A292935: E.g.f.: exp(exp(-x) - 1). - - sage: b = _[0] # optional -- internet - - sage: b.formulas()[0] # optional -- internet + sage: b = _[0] + sage: b.formulas()[0] 'E.g.f.: exp(exp(x) - 1).' - - sage: [i for i in b.comments() if 'prime' in i][-1] # optional -- internet + sage: [i for i in b.comments() if 'prime' in i][-1] 'Number n is prime if ...' - - sage: [n for n in range(2, 20) if (b(n)-2) % n == 0] # optional -- internet + sage: [n for n in range(2, 20) if (b(n)-2) % n == 0] [2, 3, 5, 7, 11, 13, 17, 19] .. SEEALSO:: @@ -261,18 +257,18 @@ class OEIS: Sequences. You can query it using its methods, but ``OEIS`` can also be called directly with three arguments: - - ``query`` - it can be: + - ``query`` -- it can be: - a string representing an OEIS ID (e.g. 'A000045'). - an integer representing an OEIS ID (e.g. 45). - a list representing a sequence of integers. - a string, representing a text search. - - ``max_results`` - (integer, default: 30) the maximum number of + - ``max_results`` -- (integer, default: 30) the maximum number of results to return, they are sorted according to their relevance. In any cases, the OEIS website will never provide more than 100 results. - - ``first_result`` - (integer, default: 0) allow to skip the + - ``first_result`` -- (integer, default: 0) allow to skip the ``first_result`` first results in the search, to go further. This is useful if you are looking for a sequence that may appear after the 100 first found sequences. @@ -299,16 +295,17 @@ class OEIS: sage: oeis('A000040') # optional -- internet A000040: The prime numbers. - sage: oeis(45) # optional -- internet A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. The database can be searched by subsequence:: - sage: search = oeis([1,2,3,5,8,13]) ; search # optional -- internet + sage: search = oeis([1,2,3,5,8,13]); search # optional -- internet 0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. 1: A290689: Number of transitive rooted trees with n nodes. - 2: A027926: Triangular array T read by rows: T(n,0) = T(n,2n) = 1 for n >= 0; T(n,1) = 1 for n >= 1; T(n,k) = T(n-1,k-2) + T(n-1,k-1) for k = 2..2n-1, n >= 2. + 2: A027926: Triangular array T read by rows: T(n,0) = T(n,2n) = 1 for n >= 0; + T(n,1) = 1 for n >= 1; T(n,k) = T(n-1,k-2) + T(n-1,k-1) + for k = 2..2n-1, n >= 2. sage: fibo = search[0] # optional -- internet @@ -349,9 +346,10 @@ class OEIS: The database can be searched by description:: - sage: oeis('prime gap factorization', max_results=4) # optional --internet # random + sage: oeis('prime gap factorization', max_results=4) # random # optional -- internet 0: A073491: Numbers having no prime gaps in their factorization. - 1: A073485: Product of any number of consecutive primes; squarefree numbers with no gaps in their prime factorization. + 1: A073485: Product of any number of consecutive primes; squarefree numbers + with no gaps in their prime factorization. 2: A073490: Number of prime gaps in factorization of n. 3: A073492: Numbers having at least one prime gap in their factorization. @@ -362,7 +360,9 @@ class OEIS: sage: oeis([1,2,3,5,8,13]) # optional -- internet 0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. 1: A290689: Number of transitive rooted trees with n nodes. - 2: A027926: Triangular array T read by rows: T(n,0) = T(n,2n) = 1 for n >= 0; T(n,1) = 1 for n >= 1; T(n,k) = T(n-1,k-2) + T(n-1,k-1) for k = 2..2n-1, n >= 2. + 2: A027926: Triangular array T read by rows: T(n,0) = T(n,2n) = 1 for n >= 0; + T(n,1) = 1 for n >= 1; T(n,k) = T(n-1,k-2) + T(n-1,k-1) + for k = 2..2n-1, n >= 2. sage: oeis('A000045') # optional -- internet A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. @@ -659,20 +659,19 @@ class OEISSequence(SageObject, UniqueRepresentation): between calling and getting item, see :meth:`__call__` for more details :: + sage: # optional - internet sage: sfibo = oeis('A039834') - sage: sfibo.first_terms()[:10] # optional -- internet + sage: sfibo.first_terms()[:10] (1, 1, 0, 1, -1, 2, -3, 5, -8, 13) - - sage: sfibo(-2) # optional -- internet + sage: sfibo(-2) 1 - sage: sfibo(3) # optional -- internet + sage: sfibo(3) 2 - sage: sfibo.offsets() # optional -- internet + sage: sfibo.offsets() (-2, 6) - - sage: sfibo[0] # optional -- internet + sage: sfibo[0] 1 - sage: sfibo[6] # optional -- internet + sage: sfibo[6] -3 .. automethod:: __call__ @@ -1005,11 +1004,11 @@ def natural_object(self): OUTPUT: - If the sequence ``self`` corresponds to the digits of a real - number, returns the associated real number (as an element of - RealLazyField()). + number, returns the associated real number (as an element of + RealLazyField()). - If the sequence ``self`` corresponds to the convergents of a - continued fraction, returns the associated continued fraction. + continued fraction, returns the associated continued fraction. .. WARNING:: @@ -1024,25 +1023,25 @@ def natural_object(self): EXAMPLES:: - sage: g = oeis("A002852") ; g # optional -- internet + sage: g = oeis("A002852"); g # optional -- internet A002852: Continued fraction for Euler's constant (or Euler-Mascheroni constant) gamma. - sage: x = g.natural_object() ; type(x) # optional -- internet + sage: x = g.natural_object(); type(x) # optional -- internet sage: RDF(x) == RDF(euler_gamma) # optional -- internet True - sage: cfg = continued_fraction(euler_gamma) - sage: x[:90] == cfg[:90] # optional -- internet + sage: cfg = continued_fraction(euler_gamma) # needs sage.symbolic + sage: x[:90] == cfg[:90] # optional - internet # needs sage.symbolic True :: - sage: ee = oeis('A001113') ; ee # optional -- internet + sage: ee = oeis('A001113'); ee # optional -- internet A001113: Decimal expansion of e. - sage: x = ee.natural_object() ; x # optional -- internet + sage: x = ee.natural_object(); x # optional -- internet 2.718281828459046? sage: x.parent() # optional -- internet @@ -1053,7 +1052,7 @@ def natural_object(self): :: - sage: av = oeis('A087778') ; av # optional -- internet + sage: av = oeis('A087778'); av # optional -- internet A087778: Decimal expansion ... Avogadro... sage: av.natural_object() # optional -- internet @@ -1061,18 +1060,20 @@ def natural_object(self): :: - sage: fib = oeis('A000045') ; fib # optional -- internet + sage: fib = oeis('A000045'); fib # optional -- internet A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. - sage: x = fib.natural_object() ; x.universe() # optional -- internet + sage: x = fib.natural_object(); x.universe() # optional -- internet Non negative integer semiring :: - sage: sfib = oeis('A039834') ; sfib # optional -- internet - A039834: a(n+2) = -a(n+1) + a(n) (signed Fibonacci numbers) with a(-2) = a(-1) = 1; or Fibonacci numbers (A000045) extended to negative indices. + sage: sfib = oeis('A039834'); sfib # optional -- internet + A039834: a(n+2) = -a(n+1) + a(n) (signed Fibonacci numbers) with + a(-2) = a(-1) = 1; or Fibonacci numbers (A000045) + extended to negative indices. - sage: x = sfib.natural_object() ; x.universe() # optional -- internet + sage: x = sfib.natural_object(); x.universe() # optional -- internet Integer Ring TESTS:: @@ -1263,7 +1264,7 @@ def first_terms(self, number=None): EXAMPLES:: - sage: f = oeis(45) ; f # optional -- internet + sage: f = oeis(45); f # optional -- internet A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. sage: f.first_terms()[:10] # optional -- internet @@ -1271,7 +1272,7 @@ def first_terms(self, number=None): Handle dead sequences, see :trac:`17330` :: - sage: oeis(5000).first_terms(12) # optional -- internet + sage: oeis(5000).first_terms(12) # optional -- internet doctest:warning ... RuntimeWarning: This sequence is dead: "A005000: Erroneous version of A006505." @@ -1440,14 +1441,15 @@ def __iter__(self): sage: w = oeis(7540) ; w # optional -- internet A007540: Wilson primes: primes p such that (p-1)! == -1 (mod p^2). - sage: i = w.__iter__() # optional -- internet - sage: next(i) # optional -- internet + sage: # optional - internet + sage: i = w.__iter__() + sage: next(i) 5 - sage: next(i) # optional -- internet + sage: next(i) 13 - sage: next(i) # optional -- internet + sage: next(i) 563 - sage: next(i) # optional -- internet + sage: next(i) Traceback (most recent call last): ... LookupError: future values not provided by OEIS @@ -1517,17 +1519,16 @@ def links(self, browse=None, format='guess'): INPUT: - ``browse`` -- an integer, a list of integers, or the word 'all' - (default: ``None``) : which links to open in a web browser. + (default: ``None``): which links to open in a web browser. - - ``format`` -- string (default: 'guess') : how to display the links. + - ``format`` -- string (default: 'guess'): how to display the links. - OUTPUT: + OUTPUT: Tuple of strings (with fancy formatting): - - tuple of strings (with fancy formatting): - - if ``format`` is ``url``, returns a tuple of absolute links without description. - - if ``format`` is ``html``, returns nothing but prints a tuple of clickable absolute links in their context. - - if ``format`` is ``guess``, adapts the output to the context (command line or notebook). - - if ``format`` is ``raw``, the links as they appear in the database, relative links are not made absolute. + - if ``format`` is ``url``, returns a tuple of absolute links without description. + - if ``format`` is ``html``, returns nothing but prints a tuple of clickable absolute links in their context. + - if ``format`` is ``guess``, adapts the output to the context (command line or notebook). + - if ``format`` is ``raw``, the links as they appear in the database, relative links are not made absolute. EXAMPLES:: @@ -1635,7 +1636,9 @@ def cross_references(self, fetch=False): 0: A000010: Euler totient function phi(n): count numbers <= n and prime to n. 1: A002088: Sum of totient function: a(n) = Sum_{k=1..n} phi(k), cf. A000010. 2: A011755: a(n) = Sum_{k=1..n} k*phi(k). - 3: A049695: Array T read by diagonals; T(i,j) is the number of nonnegative slopes of lines determined by 2 lattice points in [ 0,i ] X [ 0,j ] if i > 0; T(0,j)=1 if j > 0; T(0,0)=0. + 3: A049695: Array T read by diagonals; T(i,j) is the number of nonnegative + slopes of lines determined by 2 lattice points in + [ 0,i ] X [ 0,j ] if i > 0; T(0,j)=1 if j > 0; T(0,0)=0. 4: A049703: a(0) = 0; for n>0, a(n) = A005598(n)/2. 5: A103116: a(n) = Sum_{i=1..n} (n-i+1)*phi(i). @@ -1664,8 +1667,10 @@ def extensions_or_errors(self): EXAMPLES:: - sage: sfibo = oeis('A039834') ; sfibo # optional -- internet - A039834: a(n+2) = -a(n+1) + a(n) (signed Fibonacci numbers) with a(-2) = a(-1) = 1; or Fibonacci numbers (A000045) extended to negative indices. + sage: sfibo = oeis('A039834'); sfibo # optional -- internet + A039834: a(n+2) = -a(n+1) + a(n) (signed Fibonacci numbers) with + a(-2) = a(-1) = 1; or Fibonacci numbers (A000045) extended + to negative indices. sage: sfibo.extensions_or_errors()[0] # optional -- internet 'Signs corrected by _Len Smiley_ and _N. J. A. Sloane_' @@ -1689,7 +1694,7 @@ def examples(self): EXAMPLES:: - sage: c = oeis(1203) ; c # optional -- internet + sage: c = oeis(1203); c # optional -- internet A001203: Simple continued fraction expansion of Pi. sage: c.examples() # optional -- internet @@ -1715,7 +1720,7 @@ def comments(self): EXAMPLES:: - sage: f = oeis(45) ; f # optional -- internet + sage: f = oeis(45); f # optional -- internet A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. sage: f.comments()[:8] # optional -- internet @@ -1747,7 +1752,7 @@ def url(self): EXAMPLES:: - sage: f = oeis(45) ; f # optional -- internet + sage: f = oeis(45); f # optional -- internet A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. sage: f.url() # optional -- internet @@ -1767,7 +1772,7 @@ def browse(self): EXAMPLES:: - sage: f = oeis(45) ; f # optional -- internet webbrowser + sage: f = oeis(45); f # optional -- internet webbrowser A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. sage: f.browse() # optional -- internet webbrowser @@ -1782,7 +1787,7 @@ def browse(self): def show(self): r""" - Display most available informations about the sequence ``self``. + Display most available information about the sequence ``self``. EXAMPLES:: @@ -2001,14 +2006,14 @@ def test_compile_sage_code(self): One correct sequence:: - sage: s = oeis.find_by_id('A027642') # optional -- internet - sage: s.test_compile_sage_code() # optional -- internet + sage: s = oeis.find_by_id('A027642') # optional -- internet + sage: s.test_compile_sage_code() # optional -- internet True One dead sequence:: - sage: s = oeis.find_by_id('A000154') # optional -- internet - sage: s.test_compile_sage_code() # optional -- internet + sage: s = oeis.find_by_id('A000154') # optional -- internet + sage: s.test_compile_sage_code() # optional -- internet doctest:warning ... RuntimeWarning: This sequence is dead: ... @@ -2032,7 +2037,7 @@ class FancyTuple(tuple): EXAMPLES:: sage: from sage.databases.oeis import FancyTuple - sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4]) ; t + sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4]); t 0: zero 1: one 2: two @@ -2050,14 +2055,14 @@ def __repr__(self): EXAMPLES:: sage: from sage.databases.oeis import FancyTuple - sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4]) ; t + sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4]); t 0: zero 1: one 2: two 3: three 4: 4 - sage: t = FancyTuple(['Français', 'Español', '中文']) ; t + sage: t = FancyTuple(['Français', 'Español', '中文']); t 0: Français 1: Español 2: 中文 diff --git a/src/sage/databases/stein_watkins.py b/src/sage/databases/stein_watkins.py index 2936fd6da1d..167fa3a195b 100644 --- a/src/sage/databases/stein_watkins.py +++ b/src/sage/databases/stein_watkins.py @@ -44,12 +44,13 @@ We type ``next(d)`` to get each isogeny class of curves from ``d``:: - sage: C = next(d) # optional - database_stein_watkins - sage: C # optional - database_stein_watkins + sage: # optional - database_stein_watkins + sage: C = next(d) + sage: C Stein-Watkins isogeny class of conductor 11 - sage: next(d) # optional - database_stein_watkins + sage: next(d) Stein-Watkins isogeny class of conductor 14 - sage: next(d) # optional - database_stein_watkins + sage: next(d) Stein-Watkins isogeny class of conductor 15 An isogeny class has a number of attributes that give data about @@ -58,21 +59,22 @@ :: - sage: C.data # optional - database_stein_watkins + sage: # optional - database_stein_watkins + sage: C.data ['11', '[11]', '0', '0.253842', '25', '+*1'] - sage: C.curves # optional - database_stein_watkins + sage: C.curves [[[0, -1, 1, 0, 0], '(1)', '1', '5'], [[0, -1, 1, -10, -20], '(5)', '1', '5'], [[0, -1, 1, -7820, -263580], '(1)', '1', '1']] - sage: C.conductor # optional - database_stein_watkins + sage: C.conductor 11 - sage: C.leading_coefficient # optional - database_stein_watkins + sage: C.leading_coefficient '0.253842' - sage: C.modular_degree # optional - database_stein_watkins + sage: C.modular_degree '+*1' - sage: C.rank # optional - database_stein_watkins + sage: C.rank 0 - sage: C.isogeny_number # optional - database_stein_watkins + sage: C.isogeny_number '25' If we were to continue typing ``next(d)`` we would @@ -101,16 +103,17 @@ Each call ``next(d)`` gives another elliptic curve of prime conductor:: - sage: C = next(d) # optional - database_stein_watkins - sage: C # optional - database_stein_watkins + sage: # optional - database_stein_watkins + sage: C = next(d) + sage: C Stein-Watkins isogeny class of conductor 17 - sage: C.curves # optional - database_stein_watkins + sage: C.curves [[[1, -1, 1, -1, 0], '[1]', '1', '4'], [[1, -1, 1, -6, -4], '[2]', '1', '2x'], [[1, -1, 1, -1, -14], '(4)', '1', '4'], [[1, -1, 1, -91, -310], '[1]', '1', '2']] - sage: C = next(d) # optional - database_stein_watkins - sage: C # optional - database_stein_watkins + sage: C = next(d) + sage: C Stein-Watkins isogeny class of conductor 19 REFERENCE: diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index 9261c69dd4b..66cedee9b75 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -289,7 +289,7 @@ def skipfile(filename, tested_optional_tags=False, *, if log: log(f"Skipping '{filename}' because it is created by the jupyter-sphinx extension for internal use and should not be tested") return True - if if_installed and ext in ('.py', '.pyx', '.pxd'): + if if_installed: module_name = get_basename(filename) try: if not importlib.util.find_spec(module_name): # tries to import the containing package diff --git a/src/sage/doctest/external.py b/src/sage/doctest/external.py index 8744bd93e72..9768202e76f 100644 --- a/src/sage/doctest/external.py +++ b/src/sage/doctest/external.py @@ -372,6 +372,7 @@ def external_software(): """ return sorted(f.name for f in external_features()) + external_software = external_software() diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 5b4dc56c7d1..19315eac6a2 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -1631,6 +1631,17 @@ def do_fixup(self, want, got): got = ld_pie_warning_regex.sub('', got) did_fixup = True + if "Overriding pythran description" in got: + # Some signatures changed in numpy-1.25.x that may yet be + # reverted, but which pythran would otherwise warn about. + # Pythran has a special case for numpy.random that hides + # the warning -- I guess until we know if the changes will + # be reverted -- but only in v0.14.0 of pythran. Ignoring + # This warning allows us to support older pythran with e.g. + # numpy-1.25.2. + pythran_numpy_warning_regex = re.compile(r'WARNING: Overriding pythran description with argspec information for: numpy\.random\.[a-z_]+') + got = pythran_numpy_warning_regex.sub('', got) + did_fixup = True return did_fixup, want, got def output_difference(self, example, got, optionflags): diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index d5dc83f0e1a..5064496052b 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -84,8 +84,10 @@ def get_basename(path): sage: from sage.doctest.sources import get_basename sage: from sage.env import SAGE_SRC sage: import os - sage: get_basename(os.path.join(SAGE_SRC,'sage','doctest','sources.py')) + sage: get_basename(os.path.join(SAGE_SRC, 'sage', 'doctest', 'sources.py')) 'sage.doctest.sources' + sage: get_basename(os.path.join(SAGE_SRC, 'sage', 'structure', 'element.pxd')) + 'sage.structure.element.pxd' """ if path is None: return None @@ -111,10 +113,14 @@ def get_basename(path): # it goes. while is_package_or_sage_namespace_package_dir(root): root = os.path.dirname(root) - fully_qualified_path = os.path.splitext(path[len(root) + 1:])[0] + fully_qualified_path, ext = os.path.splitext(path[len(root) + 1:]) if os.path.split(path)[1] == '__init__.py': fully_qualified_path = fully_qualified_path[:-9] - return fully_qualified_path.replace(os.path.sep, '.') + basename = fully_qualified_path.replace(os.path.sep, '.') + if ext in ['.pxd', '.pxi']: + # disambiguate from .pyx with the same basename + basename += ext + return basename class DocTestSource(): diff --git a/src/sage/dynamics/arithmetic_dynamics/all.py b/src/sage/dynamics/arithmetic_dynamics/all.py index d37ef38b437..f536734b5d9 100644 --- a/src/sage/dynamics/arithmetic_dynamics/all.py +++ b/src/sage/dynamics/arithmetic_dynamics/all.py @@ -5,5 +5,8 @@ from .projective_ds import DynamicalSystem_projective from .product_projective_ds import DynamicalSystem_product_projective from .berkovich_ds import DynamicalSystem_Berkovich +from .dynamical_semigroup import DynamicalSemigroup +from .dynamical_semigroup import DynamicalSemigroup_affine +from .dynamical_semigroup import DynamicalSemigroup_projective lazy_import('sage.dynamics.arithmetic_dynamics.wehlerK3', 'WehlerK3Surface') lazy_import('sage.dynamics.arithmetic_dynamics.wehlerK3', 'random_WehlerK3Surface') diff --git a/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py new file mode 100644 index 00000000000..5b324ddbd9a --- /dev/null +++ b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py @@ -0,0 +1,1541 @@ +r""" +Dynamical semigroups + +A dynamical semigroup is a finitely generated subsemigroup of +the endomorphism ring of a subscheme of projective or affine space. + +AUTHORS: + + - Dang Phan (August 6th, 2023): initial implementation +""" + +# **************************************************************************** +# Dang Phan +# +# 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 collections.abc import Collection +from sage.categories.fields import Fields +from sage.categories.number_fields import NumberFields +from sage.categories.semigroups import Semigroups +from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine +from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem +from sage.dynamics.arithmetic_dynamics.projective_ds import DynamicalSystem_projective +from sage.misc.classcall_metaclass import typecall +from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass +from sage.rings.finite_rings.finite_field_base import FiniteField +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.structure.parent import Parent + + +class DynamicalSemigroup(Parent, metaclass=InheritComparisonClasscallMetaclass): + r""" + A dynamical semigroup defined by a multiple dynamical systems on projective or affine space. + + INPUT: + + - ``ds_data`` -- list or tuple of dynamical systems or objects that define dynamical systems + + OUTPUT: + + :class:`DynamicalSemigroup_affine` if ``ds_data`` only contains dynamical systems + over affine space; and :class:`DynamicalSemigroup_projective` otherwise. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: DynamicalSemigroup(([x, y], [x^2, y^2])) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([x^2, y^2], P) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem_affine(x, A) + sage: DynamicalSemigroup(f) + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 1 dynamical system: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x) + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem(x, A) + sage: g = DynamicalSystem(x^2, A) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x) + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x^2) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: X = P.subscheme(x - y) + sage: f = DynamicalSystem_projective([x, y], X) + sage: g = DynamicalSystem_projective([x^2, y^2], X) + sage: DynamicalSemigroup_projective([f, g]) + Dynamical semigroup over Closed subscheme of Projective Space of dimension 1 over Rational Field defined by: + x - y defined by 2 dynamical systems: + Dynamical System of Closed subscheme of Projective Space of dimension 1 over Rational Field defined by: + x - y + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Closed subscheme of Projective Space of dimension 1 over Rational Field defined by: + x - y + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + If a dynamical semigroup is built from dynamical systems with different base rings, all systems will be coerced + to the largest base ring:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: Q. = ProjectiveSpace(RR, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([z^2, w^2], Q) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Real Field with 53 bits of precision defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: B. = AffineSpace(RR, 1) + sage: f = DynamicalSystem(x, A) + sage: g = DynamicalSystem(y^2, B) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Affine Space of dimension 1 over Real Field with 53 bits of precision defined by 2 dynamical systems: + Dynamical System of Affine Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x) to + (x) + Dynamical System of Affine Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x) to + (x^2) + + If a dynamical semigroup is built from dynamical systems over number fields, a composite number field is created + and all systems will be coerced to it. This composite number field contains all of the initial number fields:: + + sage: R. = QQ[] + sage: K. = NumberField(r^2 - 2) + sage: P. = ProjectiveSpace(QQ, 1) + sage: Q. = ProjectiveSpace(K, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([z^2, w^2], Q) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Number Field in k with defining polynomial r^2 - 2 defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Number Field in k with defining polynomial r^2 - 2 + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Number Field in k with defining polynomial r^2 - 2 + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + :: + + sage: R. = QQ[] + sage: K. = NumberField(r^2 - 2) + sage: L. = NumberField(r^2 - 3) + sage: P. = ProjectiveSpace(K, 1) + sage: Q. = ProjectiveSpace(L, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([z^2, w^2], Q) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Number Field in kl with defining polynomial r^4 - 10*r^2 + 1 defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Number Field in kl with defining polynomial r^4 - 10*r^2 + 1 + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Number Field in kl with defining polynomial r^4 - 10*r^2 + 1 + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + :: + + sage: R. = QQ[] + sage: K. = NumberField(r^2 - 2) + sage: L. = NumberField(r^2 - 3) + sage: P. = AffineSpace(K, 1) + sage: Q. = AffineSpace(L, 1) + sage: f = DynamicalSystem(x, P) + sage: g = DynamicalSystem(y^2, Q) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Affine Space of dimension 1 over Number Field in kl with defining polynomial r^4 - 10*r^2 + 1 defined by 2 dynamical systems: + Dynamical System of Affine Space of dimension 1 over Number Field in kl with defining polynomial r^4 - 10*r^2 + 1 + Defn: Defined on coordinates by sending (x) to + (x) + Dynamical System of Affine Space of dimension 1 over Number Field in kl with defining polynomial r^4 - 10*r^2 + 1 + Defn: Defined on coordinates by sending (x) to + (x^2) + + A dynamical semigroup may contain dynamical systems over function fields:: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, y], P) + sage: g = DynamicalSystem([x, r * y], P) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (r*x : y) + Dynamical System of Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : r*y) + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, y], P) + sage: g = DynamicalSystem([x, y], P) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (r*x : y) + Dynamical System of Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, y], P) + sage: g = DynamicalSystem([s * x, y], P) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Multivariate Polynomial Ring in r, s over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Multivariate Polynomial Ring in r, s over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (r*x : y) + Dynamical System of Projective Space of dimension 1 over Multivariate Polynomial Ring in r, s over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (s*x : y) + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, s * y], P) + sage: g = DynamicalSystem([s * x, r * y], P) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Multivariate Polynomial Ring in r, s over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Multivariate Polynomial Ring in r, s over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (r*x : s*y) + Dynamical System of Projective Space of dimension 1 over Multivariate Polynomial Ring in r, s over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (s*x : r*y) + + A dynamical semigroup may contain dynamical systems over finite fields:: + + sage: F = FiniteField(5) + sage: P. = ProjectiveSpace(F, 1) + sage: DynamicalSemigroup(([x, y], [x^2, y^2])) + Dynamical semigroup over Projective Space of dimension 1 over Finite Field of size 5 defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Finite Field of size 5 + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Finite Field of size 5 + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + If a dynamical semigroup is built from dynamical systems over both projective and affine spaces, all systems + will be homogenized to dynamical systems over projective space:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem(z^2, A) + sage: DynamicalSemigroup((f, g)) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: DynamicalSemigroup(1) + Traceback (most recent call last): + ... + TypeError: 1 does not define a 'DynamicalSemigroup' object + + :: + + sage: R. = QQ[] + sage: K. = NumberField(r^2 - 2) + sage: P. = ProjectiveSpace(RR, 1) + sage: Q. = ProjectiveSpace(K, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([z^2, w^2], Q) + sage: DynamicalSemigroup((f, g)) + Traceback (most recent call last): + ... + ValueError: given dynamical systems are not automorphic under global composition + + :: + + sage: F = FiniteField(5) + sage: P. = ProjectiveSpace(F, 1) + sage: Q. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([z^2, w^2], Q) + sage: DynamicalSemigroup((f, g)) + Traceback (most recent call last): + ... + ValueError: given dynamical systems are not automorphic under global composition + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: Q. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem([x, y]) + sage: g = DynamicalSystem([u^2, v^2, w^2]) + sage: DynamicalSemigroup((f, g)) + Traceback (most recent call last): + ... + ValueError: domains of 'DynamicalSystem' objects must be of the same dimension + """ + + @staticmethod + def __classcall_private__(cls, ds_data): + if isinstance(ds_data, Collection): + all_affine_systems = all(isinstance(ds_datum, DynamicalSystem_affine) for ds_datum in ds_data) + if all_affine_systems: + return DynamicalSemigroup_affine(ds_data) + elif isinstance(ds_data, DynamicalSystem_affine): + return DynamicalSemigroup_affine(ds_data) + elif not isinstance(ds_data, DynamicalSystem): + raise TypeError(str(ds_data) + " does not define a 'DynamicalSemigroup' object") + return DynamicalSemigroup_projective(ds_data) + + def __init__(self, systems): + r""" + The Python constructor. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: DynamicalSemigroup(([x, y], [x^2, y^2])) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + """ + + self._dynamical_systems = [] + for ds in systems: + if ds not in self._dynamical_systems: + self._dynamical_systems.append(ds) + Parent.__init__(self, category=Semigroups().FinitelyGeneratedAsMagma()) + + def __call__(self, input): + r""" + The result after evaluating this dynamical semigroup on a value. + + INPUT: + + - ``input`` -- one value that can be evaluated + with the generators of this dynamical semigroup. + + OUTPUT: A set of the resulting values after applying all of this dynamical semigroup's generators to ``input``. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f(2) + {(2 : 1), (4 : 1)} + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f([2, 1]) + {(2 : 1), (4 : 1)} + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f(f(2)) + Traceback (most recent call last): + ... + TypeError: unable to convert {(4 : 1), (2 : 1)} to an element of Rational Field + """ + result = set() + for ds in self.defining_systems(): + result.add(ds(self.domain()(input))) + return result + + def base_ring(self): + r""" + The base ring of this dynamical semigroup. This is identical + to the base ring of all of its defining dynamical system. + + OUTPUT: A ring. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f.base_ring() + Rational Field + """ + return self.defining_systems()[0].base_ring() + + def change_ring(self, new_ring): + r""" + Return a new :class:`DynamicalSemigroup` whose generators + are the initial dynamical systems coerced to ``new_ring``. + + INPUT: + + - ``new_ring`` -- a ring. + + OUTPUT: + + A :class:`DynamicalSemigroup` defined by this dynamical + semigroup's generators, but coerced to ``new_ring``. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f.change_ring(RR) + Dynamical semigroup over Projective Space of dimension 1 over Real Field with 53 bits of precision defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + """ + new_systems = [] + for ds in self.defining_systems(): + new_systems.append(ds.change_ring(new_ring)) + return DynamicalSemigroup_projective(new_systems) + + def domain(self): + r""" + Return the domain of the generators of this dynamical semigroup. + + OUTPUT: A subscheme of a projective space or affine space. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f.domain() + Projective Space of dimension 1 over Rational Field + """ + return self.defining_systems()[0].domain() + + def codomain(self): + r""" + Return the codomain of the generators of this dynamical semigroup. + + OUTPUT: A subscheme of a projective space or affine space. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f.codomain() + Projective Space of dimension 1 over Rational Field + """ + return self.defining_systems()[0].codomain() + + def defining_polynomials(self): + r""" + Return the set of polynomials that define the generators of this dynamical semigroup. + + OUTPUT: A set of polynomials. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f.defining_polynomials() + {(x, y), (x^2, y^2)} + """ + result = set() + for ds in self.defining_systems(): + result.add(ds.defining_polynomials()) + return result + + def defining_systems(self): + r""" + Return the generators of this dynamical semigroup. + + OUTPUT: A tuple of dynamical systems. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f.defining_systems() + (Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y), + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2)) + """ + return tuple(self._dynamical_systems) + + def nth_iterate(self, p, n): + r""" + Return a set of values that results from evaluating this dynamical semigroup + on the value ``p`` a total of ``n`` times. + + INPUT: + + - ``p`` -- a value on which dynamical systems can evaluate + - ``n`` -- a nonnegative integer + + OUTPUT: a set of values + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^2, y^2],)) + sage: f.nth_iterate(2, 0) + {(2 : 1)} + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^2, y^2],)) + sage: f.nth_iterate(2, 1) + {(4 : 1)} + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^2, y^2],)) + sage: f.nth_iterate(2, 2) + {(16 : 1)} + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: f.nth_iterate(2, 0) + {(2 : 1)} + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: f.nth_iterate(2, 1) + {(3 : 1), (4 : 1)} + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: f.nth_iterate(2, 2) + {(5/3 : 1), (2 : 1), (9 : 1), (16 : 1)} + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: f.nth_iterate(2, 3.5) + Traceback (most recent call last): + ... + TypeError: Attempt to coerce non-integral RealNumber to Integer + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: f.nth_iterate(2, -3) + Traceback (most recent call last): + ... + ValueError: -3 must be a nonnegative integer + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: f.nth_iterate(3, 2) == (f * f)(3) + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x + y, x - y], [x^2, y^2])) + sage: one = QQ(1) + sage: f.nth_iterate(2, one) + {(3 : 1), (4 : 1)} + + """ + n = ZZ(n) + if n < 0: + raise ValueError(str(n) + " must be a nonnegative integer") + result = {self.domain()(p)} + for i in range(1, n + 1): + next_iteration = set() + for point in result: + next_iteration.update(self(point)) + result = next_iteration + return result + + def orbit(self, p, n): + r""" + If ``n`` is an integer, return `(p, f(p), f^2(p), \dots, f^n(p))`. If ``n`` is a list or tuple in interval + notation `[a, b]`, return `(f^a(p), \dots, f^b(p))`. + + INPUT: + + - `p` -- value on which this dynamical semigroup can be evaluated + - `n` -- a nonnegative integer or a list or tuple of length 2 describing an + interval of the number line containing entirely nonnegative integers + + OUTPUT: a tuple of sets of values on the domain of this dynamical semigroup. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, 0) + ({(2 : 1)},) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, 1) + ({(2 : 1)}, {(2 : 1), (4 : 1)}) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, 2) + ({(2 : 1)}, {(2 : 1), (4 : 1)}, {(2 : 1), (4 : 1), (16 : 1)}) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, [1, 2]) + ({(2 : 1), (4 : 1)}, {(2 : 1), (4 : 1), (16 : 1)}) + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: one = QQ(1) + sage: d.orbit(2, one) + ({(2 : 1)}, {(2 : 1), (4 : 1)}) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, -2) + Traceback (most recent call last): + ... + ValueError: -2 must be a nonnegative integer + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, x) + Traceback (most recent call last): + ... + TypeError: not a constant polynomial + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, [1, 2, 3]) + Traceback (most recent call last): + ... + ValueError: [1, 2, 3] must be an integer or list or tuple of two integers + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, [-2, 1]) + Traceback (most recent call last): + ... + ValueError: [-2, 1] must contain exactly two nonnegative integers + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: d = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: d.orbit(2, [2, 1]) + Traceback (most recent call last): + ... + ValueError: [2, 1] cannot be in descending order + """ + + if not isinstance(n, Collection): + n = ZZ(n) + if n < 0: + raise ValueError(str(n) + " must be a nonnegative integer") + return self.orbit(p, [0, n]) + + if not len(n) == 2: + raise ValueError(str(n) + " must be an integer or list or tuple of two integers") + if ZZ(n[0]) < 0 or ZZ(n[1]) < 0: + raise ValueError(str(n) + " must contain exactly two nonnegative integers") + if ZZ(n[0]) > ZZ(n[1]): + raise ValueError(str(n) + " cannot be in descending order") + + result = [] + current_iterate = self.nth_iterate(p, n[0]) + result.append(current_iterate) + for i in range(n[0] + 1, n[1] + 1): + next_iterate = set() + for value in current_iterate: + next_iterate.update(self(value)) + result.append(next_iterate) + current_iterate = next_iterate + return tuple(result) + + def specialization(self, assignments): + r""" + Returns the specialization of the generators of this dynamical semigroup. + + INPUT: + + - `assignments` -- argument for specialization of the generators of this dynamical semigroup. + + OUTPUT: a dynamical semigroup with the specialization of the generators of this dynamical semigroup. + + EXAMPLES:: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, y], P) + sage: g = DynamicalSystem([x, r * y], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.specialization({r:2}) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (2*x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : 2*y) + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, y], P) + sage: g = DynamicalSystem([x, y], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.specialization({r:2}) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (2*x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, y], P) + sage: g = DynamicalSystem([s * x, y], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.specialization({r:2, s:3}) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (2*x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (3*x : y) + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([r * x, s * y], P) + sage: g = DynamicalSystem([s * x, r * y], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.specialization({s:3}) + Dynamical semigroup over Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (r*x : 3*y) + Dynamical System of Projective Space of dimension 1 over Univariate Polynomial Ring in r over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (3*x : r*y) + """ + specialized_systems = [] + for ds in self.defining_systems(): + specialized_systems.append(ds.specialization(assignments)) + return DynamicalSemigroup(specialized_systems) + + def __mul__(self, other_dynamical_semigroup): + r""" + Return a new :class:`DynamicalSemigroup` that is the result of multiplying + this dynamical semigroup with another dynamical semigroup of the same type + using the * operator. + + Let `f` be a dynamical semigroup with generators `\{ f_1, f_2, \dots, f_m \}` + and `g` be a dynamical semigroup with generators `\{ g_1, g_2, \dots, g_n \}`. + The product `f * g` has generators + `\{ f_i(g_j) : 1 \leq i \leq m, 1 \leq j \leq n \}`. + + INPUT: + + - ``other_dynamical_semigroup`` -- a dynamical semigroup + + OUTPUT: :class:`DynamicalSemigroup` + + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x^10, y^10], P) + sage: f = DynamicalSemigroup(f1) + sage: f*f + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 1 dynamical system: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^100 : y^100) + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem_affine(x^10, A) + sage: f = DynamicalSemigroup(f1) + sage: f*f + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 1 dynamical system: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x^100) + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x^2 + x * y, y^2 + x * y], P) + sage: g1 = DynamicalSystem([x^3 + x^2 * y, y^3 + x * y^2], P) + sage: f = DynamicalSemigroup(f1) + sage: g = DynamicalSemigroup(g1) + sage: f*g + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 1 dynamical system: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^6 + 2*x^5*y + 2*x^4*y^2 + 2*x^3*y^3 + x^2*y^4 : x^4*y^2 + 2*x^3*y^3 + 2*x^2*y^4 + 2*x*y^5 + y^6) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x^2 + x * y, y^2 + x * y], P) + sage: f2 = DynamicalSystem([x^2 - x * y, y^2 - x * y], P) + sage: g1 = DynamicalSystem([x^3 + x^2 * y, y^3 + x * y^2], P) + sage: g2 = DynamicalSystem([x^3 - x^2 * y, y^3 - x * y^2], P) + sage: f = DynamicalSemigroup((f1, f2)) + sage: g = DynamicalSemigroup((g1, g2)) + sage: f*g + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^6 + 2*x^5*y + 2*x^4*y^2 + 2*x^3*y^3 + x^2*y^4 : x^4*y^2 + 2*x^3*y^3 + 2*x^2*y^4 + 2*x*y^5 + y^6) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^6 - 2*x^5*y + 2*x^3*y^3 - x^2*y^4 : -x^4*y^2 + 2*x^3*y^3 - 2*x*y^5 + y^6) + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x^2 + x * y, y^2 - x * y], P) + sage: g1 = DynamicalSystem([x^3 - x^2 * y, y^3 + x * y^2], P) + sage: f = DynamicalSemigroup(f1) + sage: g = DynamicalSemigroup(g1) + sage: f*g == g*f + False + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x^2 + x * y, y^2 + x * y], P) + sage: g1 = DynamicalSystem([x^3 + x^2 * y, y^3 + x * y^2], P) + sage: h1 = DynamicalSystem([x^4 + x^3 * y, y^4 + x * y^3], P) + sage: f = DynamicalSemigroup(f1) + sage: g = DynamicalSemigroup(g1) + sage: h = DynamicalSemigroup(h1) + sage: (f*g)*h == f*(g*h) + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x, y], P) + sage: f = DynamicalSemigroup(f1) + sage: f*1 + Traceback (most recent call last): + ... + TypeError: can only multiply dynamical semigroups with other dynamical semigroups of the same type + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem_projective([x, y], P) + sage: g1 = DynamicalSystem_affine(z, A) + sage: f = DynamicalSemigroup_projective(f1) + sage: g = DynamicalSemigroup_affine(g1) + sage: f*g + Traceback (most recent call last): + ... + TypeError: can only multiply dynamical semigroups with other dynamical semigroups of the same type + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: Q. = ProjectiveSpace(RR, 1) + sage: f1 = DynamicalSystem([x, y], P) + sage: g1 = DynamicalSystem([z, w], Q) + sage: f = DynamicalSemigroup(f1) + sage: g = DynamicalSemigroup(g1) + sage: f*g + Traceback (most recent call last): + ... + ValueError: left dynamical semigroup's domain must equal right dynamical semigroup's codomain + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: Q. = ProjectiveSpace(QQ, 1) + sage: f1 = DynamicalSystem([x, y], P) + sage: g1 = DynamicalSystem([z, w], Q) + sage: f = DynamicalSemigroup(f1) + sage: g = DynamicalSemigroup(g1) + sage: f*g + Traceback (most recent call last): + ... + ValueError: left dynamical semigroup's domain must equal right dynamical semigroup's codomain + """ + if type(self) is not type(other_dynamical_semigroup): + raise TypeError("can only multiply dynamical semigroups with other dynamical semigroups of the same type") + if self.domain() != other_dynamical_semigroup.codomain(): + raise ValueError("left dynamical semigroup's domain must equal right dynamical semigroup's codomain") + composite_systems = [] + for f in self.defining_systems(): + for g in other_dynamical_semigroup.defining_systems(): + composite_systems.append(DynamicalSystem(f * g)) + return DynamicalSemigroup(composite_systems) + + def __pow__(self, n): + r""" + Return a new dynamical semigroup that is this dynamical semigroup with itself ``n`` times. + If ``n`` is zero, return a dynamical semigroup with the identity map. + + INPUT: + + - ``n`` -- a nonnegative integer + + OUTPUT: :class:`DynamicalSemigroup` + + EXAMPLES:: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem(x^2, A) + sage: d = DynamicalSemigroup(f) + sage: d^2 + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 1 dynamical system: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x^4) + + :: + + sage: A. = AffineSpace(QQ, 7) + sage: f = DynamicalSystem([t + u, v - w, x + y, z^2, u * t, v^2 - w^2, x * y * z], A) + sage: d = DynamicalSemigroup(f) + sage: d^0 + Dynamical semigroup over Affine Space of dimension 7 over Rational Field defined by 1 dynamical system: + Dynamical System of Affine Space of dimension 7 over Rational Field + Defn: Defined on coordinates by sending (x, y, z, w, t, u, v) to + (x, y, z, w, t, u, v) + + TESTS:: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: d = DynamicalSemigroup(f) + sage: d*d == d^2 + True + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: d = DynamicalSemigroup(f) + sage: d^3 * d^2 == d^(3 + 2) + True + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: d = DynamicalSemigroup(f) + sage: (d^3)^2 == d^(3 * 2) + True + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: g1 = DynamicalSystem(x^3 + x - 1, A) + sage: g2 = DynamicalSystem(x^2 - x + 1, A) + sage: f = DynamicalSemigroup((f1, f2)) + sage: g = DynamicalSemigroup((g1, g2)) + sage: (f * g) ^ 2 == f^2 * g^2 + False + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: g1 = DynamicalSystem(x^3 + x - 1, A) + sage: g2 = DynamicalSystem(x^2 - x + 1, A) + sage: f = DynamicalSemigroup((f1, f2)) + sage: g = DynamicalSemigroup((g1, g2)) + sage: f * g^0 == f + True + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: g1 = DynamicalSystem(x^3 + x - 1, A) + sage: g2 = DynamicalSystem(x^2 - x + 1, A) + sage: f = DynamicalSemigroup((f1, f2)) + sage: g = DynamicalSemigroup((g1, g2)) + sage: g * f^0 == g + True + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: d = DynamicalSemigroup((f1, f2)) + sage: d^1.5 + Traceback (most recent call last): + ... + TypeError: Attempt to coerce non-integral RealNumber to Integer + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f1 = DynamicalSystem(x^2 + 1, A) + sage: f2 = DynamicalSystem(x^3 - 1, A) + sage: d = DynamicalSemigroup((f1, f2)) + sage: d^(-1) + Traceback (most recent call last): + ... + ValueError: -1 must be a nonnegative integer + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem(x^2, A) + sage: d = DynamicalSemigroup(f) + sage: two = RR(2) + sage: d^two + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 1 dynamical system: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x^4) + """ + n = ZZ(n) + if n < 0: + raise ValueError(str(n) + " must be a nonnegative integer") + if n == 0: + return DynamicalSemigroup(DynamicalSystem(self.defining_systems()[0] ** 0)) + result = self + for i in range(n - 1): + result = result * self + return result + + def _repr_(self): + r""" + Return the :class:`String` representation of this dynamical semigroup. + + OUTPUT: A :class:`String` displaying information about this dynamical semigroup. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: DynamicalSemigroup(([x, y], [x^2, y^2])) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + """ + header = "Dynamical semigroup over %s defined by %d dynamical system" + if (len(self.defining_systems()) > 1): + header += "s" + header += ":" + header = header % (str(self.domain()), len(self.defining_systems())) + systems = [] + for ds in self.defining_systems(): + systems.append(str(ds)) + systems = '\n'.join(systems) + return header + "\n" + systems + + def __eq__(self, other): + r""" + Return whether two dynamical semigroups are equal. + + OUTPUT: + + A boolean that is True if and only if the generators of the two + dynamical semigroups are equal as sets and no generator is of degree 1. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^2, y^2], [x^3, y^3])) + sage: g = DynamicalSemigroup(([x^2, y^2], [x^3, y^3])) + sage: f == g + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^2, y^2], [x^2, y^2])) + sage: g = DynamicalSemigroup(([x^2, y^2], [x^2, y^2], [x^2, y^2])) + sage: f == g + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^3, y^3], [x^2, y^2])) + sage: g = DynamicalSemigroup(([x^2, y^2], [x^3, y^3])) + sage: f == g + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x^3, y^3], [x^2, y^2])) + sage: g = DynamicalSemigroup(([x^2, y^2], [y^3, x^3])) + sage: f == g + False + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: f == 1 + False + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSemigroup(([x, y], [x^2, y^2])) + sage: g = DynamicalSemigroup(([x^2, y^2], [x^3, y^3])) + sage: f == g + Traceback (most recent call last): + ... + NotImplementedError: cannot compare dynamical semigroups with at least one generator of degree 1 + """ + if isinstance(other, DynamicalSemigroup): + if any(ds.degree() == 1 for ds in self.defining_systems()) or \ + any(ds.degree() == 1 for ds in other.defining_systems()): + raise NotImplementedError("cannot compare dynamical semigroups with at least one generator of degree 1") + return all(ds in other.defining_systems() for ds in self.defining_systems()) and \ + all(ds in self.defining_systems() for ds in other.defining_systems()) + return False + + +class DynamicalSemigroup_projective(DynamicalSemigroup): + r""" + A dynamical semigroup defined by a multiple dynamical systems on projective space. + + INPUT: + + - ``ds_data`` -- list or tuple of dynamical systems or objects that define dynamical systems + over projective space. + + OUTPUT: :class:`DynamicalSemigroup_projective` + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: DynamicalSemigroup_projective(([x, y], [x^2, y^2])) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x : y) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x : y) to + (x^2 : y^2) + """ + + @staticmethod + def __classcall_private__(cls, ds_data): + systems = [] + + if isinstance(ds_data, Collection): + for ds_datum in ds_data: + if isinstance(ds_datum, DynamicalSystem_projective): + systems.append(ds_datum) + elif isinstance(ds_datum, DynamicalSystem_affine): + dimension = ds_datum.domain().dimension() + systems.append(ds_datum.homogenize(dimension)) + else: + try: + systems.append(DynamicalSystem_projective(ds_datum)) + except ValueError: + raise ValueError(str(ds_datum) + " does not define a 'DynamicalSystem_projective' object") + else: + if isinstance(ds_data, DynamicalSystem_projective): + systems.append(ds_data) + else: + try: + systems.append(DynamicalSystem_projective(ds_data)) + except ValueError: + raise ValueError(str(ds_data) + " does not define a 'DynamicalSystem_projective' object") + + systems = _standardize_domains_of_(systems) + if systems[0].base_ring() not in Fields(): + return typecall(cls, systems) + if isinstance(systems[0].base_ring(), FiniteField): + return DynamicalSemigroup_projective_finite_field(systems) + return DynamicalSemigroup_projective_field(systems) + + def dehomogenize(self, n): + r""" + Return a new :class:`DynamicalSemigroup_projective` with the dehomogenization at ``n`` of + the generators of this dynamical semigroup. + + INPUT: + + - ``n`` -- a tuple of nonnegative integers. If ``n`` is an integer, + then the two values of the tuple are assumed to be the same + + OUTPUT: :class:`DynamicalSemigroup_affine` + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([x^2, y^2], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.dehomogenize(0) + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (y) to + (y) + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (y) to + (y^2) + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([x^2, y^2], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.dehomogenize(1) + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x) + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x^2) + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x, y], P) + sage: g = DynamicalSystem([x^2, y^2], P) + sage: d = DynamicalSemigroup((f, g)) + sage: d.dehomogenize((1, 0)) + Traceback (most recent call last): + ... + ValueError: Scheme morphism: + From: Affine Space of dimension 1 over Rational Field + To: Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (1/x) is not a `DynamicalSystem_affine` object + """ + new_systems = [] + for ds in self.defining_systems(): + new_system = ds.dehomogenize(n) + if not isinstance(new_system, DynamicalSystem_affine): + raise ValueError(str(new_system) + " is not a `DynamicalSystem_affine` object") + new_systems.append(new_system) + return DynamicalSemigroup_affine(new_systems) + + +class DynamicalSemigroup_projective_field(DynamicalSemigroup_projective): + pass + + +class DynamicalSemigroup_projective_finite_field(DynamicalSemigroup_projective_field): + pass + + +class DynamicalSemigroup_affine(DynamicalSemigroup): + r""" + A dynamical semigroup defined by multiple dynamical systems on affine space. + + INPUT: + + - ``ds_data`` -- list or tuple of dynamical systems or objects that define dynamical systems + over affine space. + + OUTPUT: :class:`DynamicalSemigroup_affine` + + EXAMPLES:: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem(x, A) + sage: g = DynamicalSystem(x^2, A) + sage: DynamicalSemigroup_affine((f, g)) + Dynamical semigroup over Affine Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x) + Dynamical System of Affine Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x) to + (x^2) + """ + + @staticmethod + def __classcall_private__(cls, ds_data): + systems = [] + + if isinstance(ds_data, Collection): + for ds_datum in ds_data: + if isinstance(ds_datum, DynamicalSystem_affine): + systems.append(ds_datum) + else: + try: + systems.append(DynamicalSystem_affine(ds_datum)) + except ValueError: + raise ValueError(str(ds_datum) + " does not define a 'DynamicalSystem_affine' object") + else: + if isinstance(ds_data, DynamicalSystem_affine): + systems.append(ds_data) + else: + try: + systems.append(DynamicalSystem_affine(ds_data)) + except ValueError: + raise ValueError(str(ds_data) + " does not define a 'DynamicalSystem_affine' object") + + systems = _standardize_domains_of_(systems) + if systems[0].base_ring() not in Fields(): + return typecall(cls, systems) + if isinstance(systems[0].base_ring(), FiniteField): + return DynamicalSemigroup_affine_finite_field(systems) + return DynamicalSemigroup_affine_field(systems) + + def homogenize(self, n): + r""" + Return a new :class:`DynamicalSemigroup_projective` with the homogenization at ``n`` of + the generators of this dynamical semigroup. + + INPUT: + + - ``n`` -- a tuple of nonnegative integers. If ``n`` is an integer, + then the two values of the tuple are assumed to be the same + + OUTPUT: :class:`DynamicalSemigroup_projective` + + EXAMPLES:: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem(x + 1, A) + sage: g = DynamicalSystem(x^2, A) + sage: d = DynamicalSemigroup((f, g)) + sage: d.homogenize(1) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x0 : x1) to + (x0 + x1 : x1) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x0 : x1) to + (x0^2 : x1^2) + + :: + + sage: A. = AffineSpace(QQ, 1) + sage: f = DynamicalSystem(x + 1, A) + sage: g = DynamicalSystem(x^2, A) + sage: d = DynamicalSemigroup((f, g)) + sage: d.homogenize((1, 0)) + Dynamical semigroup over Projective Space of dimension 1 over Rational Field defined by 2 dynamical systems: + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x0 : x1) to + (x1 : x0 + x1) + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x0 : x1) to + (x1^2 : x0^2) + """ + new_systems = [] + for ds in self.defining_systems(): + new_systems.append(ds.homogenize(n)) + return DynamicalSemigroup_projective(new_systems) + + +class DynamicalSemigroup_affine_field(DynamicalSemigroup_affine): + pass + + +class DynamicalSemigroup_affine_finite_field(DynamicalSemigroup_affine_field): + pass + + +def _standardize_domains_of_(systems): + r""" + Coerces dynamical systems to the same domain and have the same generators. + + INPUT: + + - ``systems`` -- list of dynamical systems + + OUTPUT: list of dynamical systems from ``systems`` coerced to the same domain with the same generators + + EXAMPLES:: + + sage: A. = AffineSpace(QQ, 1) + sage: B. = AffineSpace(RR, 1) + sage: f = DynamicalSystem(x, A) + sage: g = DynamicalSystem(x^2, B) + sage: sage.dynamics.arithmetic_dynamics.dynamical_semigroup._standardize_domains_of_([f, g]) + [Dynamical System of Affine Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x) to + (x), + Dynamical System of Affine Space of dimension 1 over Real Field with 53 bits of precision + Defn: Defined on coordinates by sending (x) to + (x^2)] + """ + identical_domains = True + for ds in systems: + if ds.domain() != systems[0].domain(): + identical_domains = False + break + + over_number_fields = True + all_over_QQ = True + for ds in systems: + if ds.base_ring() not in NumberFields(): + over_number_fields = False + if ds.base_ring() is not QQ: + all_over_QQ = False + + biggest_ring = None + + if over_number_fields and not all_over_QQ: + number_fields = [] + for ds in systems: + number_fields.append(ds.base_ring()) + + minimal_composite_field = None + for field in number_fields: + if field is not QQ: + if minimal_composite_field is None: + minimal_composite_field = field + else: + minimal_composite_field = minimal_composite_field.composite_fields(field)[0] + + biggest_ring = minimal_composite_field + else: + for ds in systems: + if biggest_ring is None: + biggest_ring = ds.base_ring() + elif ds.base_ring().has_coerce_map_from(biggest_ring): + biggest_ring = ds.base_ring() + elif biggest_ring.has_coerce_map_from(ds.base_ring()): + pass + else: + raise ValueError("given dynamical systems are not automorphic \ + under global composition") + + for i in range(len(systems)): + if systems[i].base_ring() != biggest_ring: + systems[i] = systems[i].change_ring(biggest_ring) + + domain = systems[0].domain() + + identical_domains = all(ds.domain() == systems[0].domain() for ds in systems) + if not identical_domains: + for ds in systems: + if ds.domain().dimension() != systems[0].domain().dimension(): + raise ValueError("domains of 'DynamicalSystem' objects must be of the same dimension") + + gens = systems[0].domain().ambient_space().gens() + for i in range(len(systems)): + if systems[i].domain().coordinate_ring() != systems[0].domain().coordinate_ring(): + sub_dict = {} + old_gens = systems[i].domain().ambient_space().gens() + for j in range(len(old_gens)): + sub_dict[old_gens[j]] = gens[j] + new_polys = [] + for poly in systems[i].defining_polynomials(): + new_polys.append(poly.subs(sub_dict)) + systems[i] = DynamicalSystem(new_polys, domain) + + return systems diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 97cc1c1df3e..6520177f4a7 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -3372,8 +3372,9 @@ def affine_preperiodic_model(self, m, n, return_conjugation=False): r""" Return a dynamical system conjugate to this one with affine (n, m) preperiodic points. - If the base ring of this dynamical system is finite, there may not be a model - with affine preperiodic points, in which case a ValueError is thrown. + If the base ring of this dynamical system is finite, there may + not be a model with affine preperiodic points, in which case a + :class:`ValueError` is raised. INPUT: @@ -6482,6 +6483,309 @@ def postcritical_set(self, check=True): next_point = f(next_point) return post_critical_list + def is_chebyshev(self): + r""" + Check if ``self`` is a Chebyshev polynomial. + + OUTPUT: True if ``self`` is Chebyshev, False otherwise. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([x^4, y^4]) + sage: F.is_chebyshev() + False + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([x^2 + y^2, y^2]) + sage: F.is_chebyshev() + False + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([2*x^2 - y^2, y^2]) + sage: F.is_chebyshev() + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([x^3, 4*y^3 - 3*x^2*y]) + sage: F.is_chebyshev() + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([2*x^2 - y^2, y^2]) + sage: L. = CyclotomicField(4) + sage: M = Matrix([[0,i],[-i,0]]) + sage: F.conjugate(M) + Dynamical System of Projective Space of dimension 1 over Cyclotomic Field of order 4 and degree 2 + Defn: Defined on coordinates by sending (x : y) to + ((-i)*x^2 : (-i)*x^2 + (2*i)*y^2) + sage: F.is_chebyshev() + True + + REFERENCES: + + - [Mil2006]_ + """ + # We need `F` to be defined over a number field for + # the function `is_postcrtically_finite` to work + if self.base_ring() not in NumberFields(): + raise NotImplementedError("Base ring must be a number field") + + if self.domain().dimension() != 1: + return False + + # All Chebyshev polynomials are postcritically finite + if not self.is_postcritically_finite(): + return False + + # Get field of definition for critical points and change base field + critical_field, phi = self.field_of_definition_critical(return_embedding=True) + F_crit = self.change_ring(phi) + + # Get the critical points and post-critical set + crit_set = set(F_crit.critical_points()) + post_crit_set = set() + images_needed = copy(crit_set) + while len(images_needed) != 0: + Q = images_needed.pop() + Q2 = F_crit(Q) + if Q2 not in post_crit_set: + post_crit_set.add(Q2) + images_needed.add(Q2) + + crit_fixed_pts = set() + for crit in crit_set: + if F_crit.nth_iterate(crit, 1) == crit: + crit_fixed_pts.add(crit) + + # All Chebyshev maps have 3 post-critical values + if (len(post_crit_set) != 3) or (len(crit_fixed_pts) != 1): + return False + + f = F_crit.dehomogenize(1)[0] + x = f.parent().gen() + ram_points = {} + for crit in crit_set: + g = f + new_crit = crit + + # Check if critical point is infinity + if crit[1] == 0: + g = g.subs(x=1/x) + new_crit = F_crit.domain()([0, 1]) + + # Check if output is infinity + if F_crit.nth_iterate(crit, 1)[1] == 0: + g = 1/g + + new_crit = new_crit.dehomogenize(1)[0] + e = 1 + g = g.derivative(x) + + while g(new_crit) == 0: + e += 1 + g = g.derivative(x) + + ram_points[crit] = e + + r = {} + + # Set r value to 0 to represent infinity + r[crit_fixed_pts.pop()] = 0 + + # Get non-fixed tail points in the post-critical portrait + crit_tails = crit_set.difference(post_crit_set) + for crit in crit_tails: + # Each critical tail point has r value 1 + r[crit] = 1 + point = crit + + # Assign r values to every point in the orbit of crit. + # If we find a point in the orbit which already has an r value assigned, + # check that we get a consistent r value. + while F_crit.nth_iterate(point, 1) not in r.keys(): + if point not in ram_points.keys(): + r[F_crit.nth_iterate(point,1)] = r[point] + else: + r[F_crit.nth_iterate(point,1)] = r[point] * ram_points[point] + + point = F_crit.nth_iterate(point,1) + + # Once we get here, the image of point has an assigned r value + # We check that this value is consistent + if point not in ram_points.keys(): + if r[F_crit.nth_iterate(point,1)] != r[point]: + return False + elif r[F_crit.nth_iterate(point,1)] != r[point] * ram_points[point]: + return False + + # The non-one r values must be one of the following in order for F to be Chebyshev + r_vals = sorted([val for val in r.values() if val != 1]) + return r_vals == [0, 2, 2] + + def is_Lattes(self): + r""" + Check if ``self`` is a Lattes map + + OUTPUT: True if ``self`` is Lattes, False otherwise + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([x^3, y^3]) + sage: F.is_Lattes() + False + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) + sage: F.is_Lattes() + False + + :: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: F = DynamicalSystem_projective([x^2 + y^2 + z^2, y^2, z^2]) + sage: F.is_Lattes() + False + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([(x + y)*(x - y)^3, y*(2*x + y)^3]) + sage: F.is_Lattes() + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: F = DynamicalSystem_projective([(x + y)^4, 16*x*y*(x - y)^2]) + sage: F.is_Lattes() + True + + :: + + sage: f = P.Lattes_map(EllipticCurve([0, 0, 0, 0, 2]),2) + sage: f.is_Lattes() + True + + :: + + sage: f = P.Lattes_map(EllipticCurve([0, 0, 0, 0, 2]), 2) + sage: L. = CyclotomicField(4) + sage: M = Matrix([[i, 0], [0, -i]]) + sage: f.conjugate(M) + Dynamical System of Projective Space of dimension 1 over Cyclotomic Field of order 4 and degree 2 + Defn: Defined on coordinates by sending (x : y) to + ((-1/4*i)*x^4 + (-4*i)*x*y^3 : (-i)*x^3*y + (2*i)*y^4) + sage: f.is_Lattes() + True + + REFERENCES: + + - [Mil2006]_ + """ + # We need `f` to be defined over a number field for + # the function `is_postcrtically_finite` to work + if self.base_ring() not in NumberFields(): + raise NotImplementedError("Base ring must be a number field") + + if self.domain().dimension() != 1: + return False + + # All Lattes maps are postcritically finite + if not self.is_postcritically_finite(): + return False + + # Get field of definition for critical points and change basefield + critical_field, phi = self.field_of_definition_critical(return_embedding=True) + F_crit = self.change_ring(phi) + + # Get the critical points and post-critical set + crit = F_crit.critical_points() + post_crit = set() + images_needed = copy(crit) + while len(images_needed) != 0: + Q = images_needed.pop() + Q2 = F_crit(Q) + if Q2 not in post_crit: + post_crit.add(Q2) + images_needed.append(Q2) + + (crit_set, post_crit_set) = crit, list(post_crit) + + # All Lattes maps have 3 or 4 post critical values + if not len(post_crit_set) in [3, 4]: + return False + + f = F_crit.dehomogenize(1)[0] + x = f.parent().gen() + ram_points = {} + for crit in crit_set: + g = f + new_crit = crit + + # Check if critical point is infinity + if crit[1] == 0: + g = g.subs(x=1/x) + new_crit = F_crit.domain()([0, 1]) + + # Check if output is infinity + if F_crit.nth_iterate(crit, 1)[1] == 0: + g = 1/g + + new_crit = new_crit.dehomogenize(1)[0] + + e = 1 + g = g.derivative(x) + while g(new_crit) == 0: + e += 1 + g = g.derivative(x) + ram_points[crit] = e + + r = {} + + # Get tail points in the post-critical portrait + crit_tails = set(crit_set).difference(set(post_crit_set)) + for crit in crit_tails: + # Each critical tail point has r value 1 + r[crit] = 1 + point = crit + + # Assign r values to every point in the orbit of crit + # If we find a point in the orbit which already has an r value assigned, + # check that we get a consistent r value + while F_crit.nth_iterate(point, 1) not in r.keys(): + if point not in ram_points.keys(): + r[F_crit.nth_iterate(point, 1)] = r[point] + else: + r[F_crit.nth_iterate(point, 1)] = r[point] * ram_points[point] + + point = F_crit.nth_iterate(point,1) + + # Once we get here the image of point has an assigned r value + # We check that this value is consistent. + if point not in ram_points.keys(): + if r[F_crit.nth_iterate(point, 1)] != r[point]: + return False + else: + if r[F_crit.nth_iterate(point, 1)] != r[point] * ram_points[point]: + return False + + # The non-one r values must be one of the following in order for F to be Lattes + r_lattes_cases = [[2, 2, 2, 2], [3, 3, 3], [2, 4, 4], [2, 3, 6]] + r_vals = sorted([val for val in r.values() if val != 1]) + return r_vals in r_lattes_cases + class DynamicalSystem_projective_field(DynamicalSystem_projective, SchemeMorphism_polynomial_projective_space_field): diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index 97a16b9452a..236822c7a32 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -15,6 +15,7 @@ This module provides a function, :func:`fast_callable`, to transform such expressions into a form where they can be evaluated quickly:: + sage: # needs sage.symbolic sage: f = sin(x) + 3*x^2 sage: ff = fast_callable(f, vars=[x]) sage: ff(3.5) @@ -29,18 +30,19 @@ huge win over sage.calculus, which evidently has a lot of overhead. Compare the cost of evaluating Wilkinson's polynomial (in unexpanded form) at x=30:: + sage: # needs sage.symbolic sage: wilk = prod((x-i) for i in [1 .. 20]); wilk (x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5)*(x - 6)*(x - 7)*(x - 8)*(x - 9)*(x - 10)*(x - 11)*(x - 12)*(x - 13)*(x - 14)*(x - 15)*(x - 16)*(x - 17)*(x - 18)*(x - 19)*(x - 20) - sage: timeit('wilk.subs(x=30)') # random, long time + sage: timeit('wilk.subs(x=30)') # random # long time 625 loops, best of 3: 1.43 ms per loop sage: fc_wilk = fast_callable(wilk, vars=[x]) - sage: timeit('fc_wilk(30)') # random, long time + sage: timeit('fc_wilk(30)') # random # long time 625 loops, best of 3: 9.72 us per loop You can specify a particular domain for the evaluation using ``domain=``:: - sage: fc_wilk_zz = fast_callable(wilk, vars=[x], domain=ZZ) + sage: fc_wilk_zz = fast_callable(wilk, vars=[x], domain=ZZ) # needs sage.symbolic The meaning of domain=D is that each intermediate and final result is converted to type D. For instance, the previous example of @@ -58,7 +60,7 @@ the correct parent before we call D. We don't yet have a special interpreter with domain ZZ, so we can see how that compares to the generic fc_wilk example above:: - sage: timeit('fc_wilk_zz(30)') # random, long time + sage: timeit('fc_wilk_zz(30)') # random # long time # needs sage.symbolic 625 loops, best of 3: 15.4 us per loop However, for other types, using domain=D will get a large speedup, @@ -68,8 +70,8 @@ operation will be floating-point, we can just execute the floating-point operations directly and skip all the Python object creations that you would get from actually using RDF objects:: - sage: fc_wilk_rdf = fast_callable(wilk, vars=[x], domain=RDF) - sage: timeit('fc_wilk_rdf(30.0)') # random, long time + sage: fc_wilk_rdf = fast_callable(wilk, vars=[x], domain=RDF) # needs sage.symbolic + sage: timeit('fc_wilk_rdf(30.0)') # random # long time # needs sage.symbolic 625 loops, best of 3: 7 us per loop The domain does not need to be a Sage type; for instance, domain=float @@ -78,27 +80,27 @@ and domain=RDF; the only difference is that when domain=RDF is used, the return value is an RDF element, and when domain=float is used, the return value is a Python float.) :: - sage: fc_wilk_float = fast_callable(wilk, vars=[x], domain=float) - sage: timeit('fc_wilk_float(30.0)') # random, long time + sage: fc_wilk_float = fast_callable(wilk, vars=[x], domain=float) # needs sage.symbolic + sage: timeit('fc_wilk_float(30.0)') # random # long time # needs sage.symbolic 625 loops, best of 3: 5.04 us per loop We also have support for ``RR``:: - sage: fc_wilk_rr = fast_callable(wilk, vars=[x], domain=RR) - sage: timeit('fc_wilk_rr(30.0)') # random, long time + sage: fc_wilk_rr = fast_callable(wilk, vars=[x], domain=RR) # needs sage.symbolic + sage: timeit('fc_wilk_rr(30.0)') # random # long time # needs sage.symbolic 625 loops, best of 3: 13 us per loop For ``CC``:: - sage: fc_wilk_cc = fast_callable(wilk, vars=[x], domain=CC) - sage: timeit('fc_wilk_cc(30.0)') # random, long time + sage: fc_wilk_cc = fast_callable(wilk, vars=[x], domain=CC) # needs sage.symbolic + sage: timeit('fc_wilk_cc(30.0)') # random # long time # needs sage.symbolic 625 loops, best of 3: 23 us per loop And support for ``CDF``:: - sage: fc_wilk_cdf = fast_callable(wilk, vars=[x], domain=CDF) - sage: timeit('fc_wilk_cdf(30.0)') # random, long time + sage: fc_wilk_cdf = fast_callable(wilk, vars=[x], domain=CDF) # needs sage.symbolic + sage: timeit('fc_wilk_cdf(30.0)') # random # long time # needs sage.symbolic 625 loops, best of 3: 10.2 us per loop Currently, :func:`fast_callable` can accept two kinds of objects: @@ -122,6 +124,7 @@ ordering (you can include extra variable names here, too). :: For symbolic expressions, you need to specify the variable names, so that :func:`fast_callable` knows what order to use. :: + sage: # needs sage.symbolic sage: var('y,z,x') (y, z, x) sage: f = 10*y + 100*z + x @@ -131,8 +134,8 @@ that :func:`fast_callable` knows what order to use. :: You can also specify extra variable names:: - sage: ff = fast_callable(f, vars=('x','w','z','y')) - sage: ff(1,2,3,4) + sage: ff = fast_callable(f, vars=('x','w','z','y')) # needs sage.symbolic + sage: ff(1,2,3,4) # needs sage.symbolic 341 This should be enough for normal use of :func:`fast_callable`; let's @@ -178,8 +181,9 @@ expression trees, and returns an expression tree representing the function call. :: sage: v3 = etb.call(sin, v1+v2) - sage: v3 - sin(add(add(mul(add(v_0, v_1), add(v_1, v_1)), floordiv(v_1, v_1)), add(mul(3.14159000000000, v_0), mul(1729, v_1)))) + sage: v3 # needs sage.symbolic + sin(add(add(mul(add(v_0, v_1), add(v_1, v_1)), floordiv(v_1, v_1)), + add(mul(3.14159000000000, v_0), mul(1729, v_1)))) Many sage/Python built-in functions are specially handled; for instance, when evaluating an expression involving :func:`sin` over ``RDF``, @@ -201,15 +205,15 @@ expression tree built up using the methods described above. EXAMPLES:: - sage: var('x') + sage: var('x') # needs sage.symbolic x - sage: f = fast_callable(sqrt(x^7+1), vars=[x], domain=float) + sage: f = fast_callable(sqrt(x^7+1), vars=[x], domain=float) # needs sage.symbolic :: - sage: f(1) + sage: f(1) # needs sage.symbolic 1.4142135623730951 - sage: f.op_list() + sage: f.op_list() # needs sage.symbolic [('load_arg', 0), ('ipow', 7), ('load_const', 1.0), 'add', 'sqrt', 'return'] To interpret that last line, we load argument 0 ('x' in this case) onto @@ -225,7 +229,9 @@ Here we take sin of the first argument and add it to f:: sage: f = etb.call(sqrt, x^7 + 1) sage: g = etb.call(sin, x) sage: fast_callable(f+g).op_list() - [('load_arg', 0), ('ipow', 7), ('load_const', 1), 'add', ('py_call', , 1), ('load_arg', 0), ('py_call', sin, 1), 'add', 'return'] + [('load_arg', 0), ('ipow', 7), ('load_const', 1), 'add', + ('py_call', , 1), ('load_arg', 0), ('py_call', sin, 1), + 'add', 'return'] AUTHOR: @@ -261,7 +267,7 @@ AUTHOR: sage: c = etb.var('c') sage: for i in range(16): ....: z = z*z + c - sage: mand = fast_callable(z, domain=CDF) + sage: mand = fast_callable(z, domain=CDF) # needs sage.rings.complex_double Now ``ff`` does 32 complex arithmetic operations on each call (16 additions and 16 multiplications). However, if ``z*z`` produced @@ -335,6 +341,7 @@ def fast_callable(x, domain=None, vars=None, EXAMPLES:: + sage: # needs sage.symbolic sage: var('x') x sage: expr = sin(x) + 3*x^2 @@ -350,6 +357,7 @@ def fast_callable(x, domain=None, vars=None, the RDF interpreter; elements of RDF just don't display all their digits. We have special fast interpreter for domain=CDF:: + sage: # needs sage.symbolic sage: f_float = fast_callable(expr, vars=[x], domain=float) sage: f_float(2) 12.909297426825681 @@ -364,23 +372,34 @@ def fast_callable(x, domain=None, vars=None, sage: f = fast_callable(expr, vars=('z','x','y')) sage: f(1, 2, 3) sin(2) + 12 + sage: K. = QQ[] sage: p = -1/4*x^6 + 1/2*x^5 - x^4 - 12*x^3 + 1/2*x^2 - 1/95*x - 1/2 sage: fp = fast_callable(p, domain=RDF) sage: fp.op_list() - [('load_arg', 0), ('load_const', -0.25), 'mul', ('load_const', 0.5), 'add', ('load_arg', 0), 'mul', ('load_const', -1.0), 'add', ('load_arg', 0), 'mul', ('load_const', -12.0), 'add', ('load_arg', 0), 'mul', ('load_const', 0.5), 'add', ('load_arg', 0), 'mul', ('load_const', -0.010526315789473684), 'add', ('load_arg', 0), 'mul', ('load_const', -0.5), 'add', 'return'] + [('load_arg', 0), ('load_const', -0.25), 'mul', ('load_const', 0.5), 'add', + ('load_arg', 0), 'mul', ('load_const', -1.0), 'add', ('load_arg', 0), 'mul', + ('load_const', -12.0), 'add', ('load_arg', 0), 'mul', ('load_const', 0.5), + 'add', ('load_arg', 0), 'mul', ('load_const', -0.010526315789473684), + 'add', ('load_arg', 0), 'mul', ('load_const', -0.5), 'add', 'return'] sage: fp(3.14159) -552.4182988917153 + sage: K. = QQ[] sage: p = x*y^2 + 1/3*y^2 - x*z - y*z sage: fp = fast_callable(p, domain=RDF) sage: fp.op_list() - [('load_const', 0.0), ('load_const', 1.0), ('load_arg', 0), ('ipow', 1), ('load_arg', 1), ('ipow', 2), 'mul', 'mul', 'add', ('load_const', 0.3333333333333333), ('load_arg', 1), ('ipow', 2), 'mul', 'add', ('load_const', -1.0), ('load_arg', 0), ('ipow', 1), ('load_arg', 2), ('ipow', 1), 'mul', 'mul', 'add', ('load_const', -1.0), ('load_arg', 1), ('ipow', 1), ('load_arg', 2), ('ipow', 1), 'mul', 'mul', 'add', 'return'] - sage: fp(e, pi, sqrt(2)) # abs tol 3e-14 + [('load_const', 0.0), ('load_const', 1.0), ('load_arg', 0), ('ipow', 1), + ('load_arg', 1), ('ipow', 2), 'mul', 'mul', 'add', + ('load_const', 0.3333333333333333), ('load_arg', 1), ('ipow', 2), 'mul', 'add', + ('load_const', -1.0), ('load_arg', 0), ('ipow', 1), ('load_arg', 2), + ('ipow', 1), 'mul', 'mul', 'add', ('load_const', -1.0), ('load_arg', 1), + ('ipow', 1), ('load_arg', 2), ('ipow', 1), 'mul', 'mul', 'add', 'return'] + sage: fp(e, pi, sqrt(2)) # abs tol 3e-14 # needs sage.symbolic 21.831120464939584 - sage: symbolic_result = p(e, pi, sqrt(2)); symbolic_result + sage: symbolic_result = p(e, pi, sqrt(2)); symbolic_result # needs sage.symbolic pi^2*e + 1/3*pi^2 - sqrt(2)*pi - sqrt(2)*e - sage: n(symbolic_result) + sage: n(symbolic_result) # needs sage.symbolic 21.8311204649396 :: @@ -398,7 +417,9 @@ def fast_callable(x, domain=None, vars=None, Check that fast_callable also works for symbolic functions with evaluation functions:: - sage: def evalf_func(self, x, y, parent): return parent(x*y) if parent is not None else x*y + sage: # needs sage.symbolic + sage: def evalf_func(self, x, y, parent): + ....: return parent(x*y) if parent is not None else x*y sage: x,y = var('x,y') sage: f = function('f', evalf_func=evalf_func) sage: fc = fast_callable(f(x, y), vars=[x, y]) @@ -407,7 +428,9 @@ def fast_callable(x, domain=None, vars=None, And also when there are complex values involved:: - sage: def evalf_func(self, x, y, parent): return parent(I*x*y) if parent is not None else I*x*y + sage: # needs sage.symbolic + sage: def evalf_func(self, x, y, parent): + ....: return parent(I*x*y) if parent is not None else I*x*y sage: g = function('g', evalf_func=evalf_func) sage: fc = fast_callable(g(x, y), vars=[x, y]) sage: fc(3, 4) @@ -503,7 +526,7 @@ def _builder_and_stream(vars, domain): interpreter:: sage: domain = RDF - sage: from sage.structure.element import Element as domain # needs sage.modules + sage: from sage.structure.element import Element as domain sage: _builder_and_stream(["x", "y"], domain) (, ) @@ -568,7 +591,7 @@ def function_name(fn): sage: from sage.ext.fast_callable import function_name sage: function_name(operator.pow) 'pow' - sage: function_name(cos) + sage: function_name(cos) # needs sage.symbolic 'cos' sage: function_name(factorial) '{factorial}' @@ -675,9 +698,9 @@ cdef class ExpressionTreeBuilder: sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder('x') - sage: var('x') + sage: var('x') # needs sage.symbolic x - sage: etb._clean_var(x) + sage: etb._clean_var(x) # needs sage.symbolic 'x' sage: x = polygen(RR); x x @@ -700,10 +723,10 @@ cdef class ExpressionTreeBuilder: sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder('x') - sage: etb.constant(pi) + sage: etb.constant(pi) # needs sage.symbolic pi - sage: etb = ExpressionTreeBuilder('x', domain=RealField(200)) - sage: etb.constant(pi) + sage: etb = ExpressionTreeBuilder('x', domain=RealField(200)) # needs sage.rings.real_mpfr + sage: etb.constant(pi) # needs sage.rings.real_mpfr sage.symbolic 3.1415926535897932384626433832795028841971693993751058209749 """ if self._domain is not None: @@ -717,6 +740,7 @@ cdef class ExpressionTreeBuilder: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: var('a,b,some_really_long_name') (a, b, some_really_long_name) @@ -774,6 +798,7 @@ cdef class ExpressionTreeBuilder: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: etb.call(cos, x) @@ -803,8 +828,8 @@ cdef class ExpressionTreeBuilder: EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: etb.choice(etb.call(operator.eq, x, 0), 0, 1/x) + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: etb.choice(etb.call(operator.eq, x, 0), 0, 1/x) # needs sage.symbolic (0 if {eq}(v_0, 0) else div(1, v_0)) """ return ExpressionChoice(self, @@ -840,6 +865,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb.var(x) @@ -866,10 +892,10 @@ cdef class Expression: EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: v = etb(3); v # indirect doctest + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: v = etb(3); v # indirect doctest # needs sage.symbolic 3 - sage: v._get_etb() is etb + sage: v._get_etb() is etb # needs sage.symbolic True """ self._etb = etb @@ -881,10 +907,10 @@ cdef class Expression: EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: v = etb(3); v + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: v = etb(3); v # needs sage.symbolic 3 - sage: v._get_etb() is etb + sage: v._get_etb() is etb # needs sage.symbolic True """ return self._etb @@ -895,6 +921,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -917,6 +944,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -939,6 +967,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -961,6 +990,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -983,6 +1013,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1008,6 +1039,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1048,6 +1080,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1064,6 +1097,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1082,6 +1116,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1100,6 +1135,7 @@ cdef class Expression: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1118,8 +1154,8 @@ cdef class ExpressionConstant(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: type(etb(3)) + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: type(etb(3)) # needs sage.symbolic """ @@ -1131,6 +1167,7 @@ cdef class ExpressionConstant(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder, ExpressionConstant sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: etb(3) @@ -1154,8 +1191,8 @@ cdef class ExpressionConstant(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: etb(3).value() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: etb(3).value() # needs sage.symbolic 3 """ return self._value @@ -1167,6 +1204,7 @@ cdef class ExpressionConstant(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: v = etb.constant(pi) @@ -1186,8 +1224,8 @@ cdef class ExpressionVariable(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: type(etb.var(x)) + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: type(etb.var(x)) # needs sage.symbolic """ cdef int _variable_index @@ -1198,6 +1236,7 @@ cdef class ExpressionVariable(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder, ExpressionVariable sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: etb(x) @@ -1219,8 +1258,8 @@ cdef class ExpressionVariable(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: etb(x).variable_index() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: etb(x).variable_index() # needs sage.symbolic 0 """ return self._variable_index @@ -1231,6 +1270,7 @@ cdef class ExpressionVariable(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: v = etb._var_number(0) @@ -1253,8 +1293,8 @@ cdef class ExpressionCall(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: type(etb.call(sin, x)) + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: type(etb.call(sin, x)) # needs sage.symbolic """ cdef object _function @@ -1266,6 +1306,7 @@ cdef class ExpressionCall(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder, ExpressionCall sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1291,8 +1332,8 @@ cdef class ExpressionCall(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: etb.call(sin, x).function() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: etb.call(sin, x).function() # needs sage.symbolic sin """ return self._function @@ -1304,8 +1345,8 @@ cdef class ExpressionCall(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: etb.call(sin, x).arguments() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: etb.call(sin, x).arguments() # needs sage.symbolic [v_0] """ return copy(self._arguments) @@ -1316,6 +1357,7 @@ cdef class ExpressionCall(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb.var(x) @@ -1342,8 +1384,8 @@ cdef class ExpressionIPow(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: type(etb.var('x')^17) + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: type(etb.var('x')^17) # needs sage.symbolic """ cdef object _base @@ -1355,6 +1397,7 @@ cdef class ExpressionIPow(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder, ExpressionIPow sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1380,8 +1423,8 @@ cdef class ExpressionIPow(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: (etb(33)^42).base() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: (etb(33)^42).base() # needs sage.symbolic 33 """ return self._base @@ -1393,8 +1436,8 @@ cdef class ExpressionIPow(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: (etb(x)^(-1)).exponent() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: (etb(x)^(-1)).exponent() # needs sage.symbolic -1 """ return self._exponent @@ -1405,6 +1448,7 @@ cdef class ExpressionIPow(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb.var(x) @@ -1431,8 +1475,8 @@ cdef class ExpressionChoice(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: etb.choice(etb.call(operator.eq, x, 0), 0, 1/x) + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: etb.choice(etb.call(operator.eq, x, 0), 0, 1/x) # needs sage.symbolic (0 if {eq}(v_0, 0) else div(1, v_0)) """ @@ -1446,6 +1490,7 @@ cdef class ExpressionChoice(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder, ExpressionChoice sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1474,9 +1519,9 @@ cdef class ExpressionChoice(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: x = etb(x) - sage: etb.choice(x, ~x, 0).condition() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: x = etb(x) # needs sage.symbolic + sage: etb.choice(x, ~x, 0).condition() # needs sage.symbolic v_0 """ return self._cond @@ -1488,9 +1533,9 @@ cdef class ExpressionChoice(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: x = etb(x) - sage: etb.choice(x, ~x, 0).if_true() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: x = etb(x) # needs sage.symbolic + sage: etb.choice(x, ~x, 0).if_true() # needs sage.symbolic inv(v_0) """ return self._iftrue @@ -1502,9 +1547,9 @@ cdef class ExpressionChoice(Expression): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder - sage: etb = ExpressionTreeBuilder(vars=(x,)) - sage: x = etb(x) - sage: etb.choice(x, ~x, 0).if_false() + sage: etb = ExpressionTreeBuilder(vars=(x,)) # needs sage.symbolic + sage: x = etb(x) # needs sage.symbolic + sage: etb.choice(x, ~x, 0).if_false() # needs sage.symbolic 0 """ return self._iffalse @@ -1516,6 +1561,7 @@ cdef class ExpressionChoice(Expression): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=(x,)) sage: x = etb(x) @@ -1539,19 +1585,19 @@ cpdef _expression_binop_helper(s, o, op): EXAMPLES:: sage: from sage.ext.fast_callable import _expression_binop_helper, ExpressionTreeBuilder - sage: var('x,y') + sage: var('x,y') # needs sage.symbolic (x, y) - sage: etb = ExpressionTreeBuilder(vars=(x,y)) - sage: x = etb(x) + sage: etb = ExpressionTreeBuilder(vars=(x,y)) # needs sage.symbolic + sage: x = etb(x) # needs sage.symbolic Now x is an Expression, but y is not. Still, all the following cases work:: - sage: _expression_binop_helper(x, x, operator.add) + sage: _expression_binop_helper(x, x, operator.add) # needs sage.symbolic add(v_0, v_0) - sage: _expression_binop_helper(x, y, operator.add) + sage: _expression_binop_helper(x, y, operator.add) # needs sage.symbolic add(v_0, v_1) - sage: _expression_binop_helper(y, x, operator.add) + sage: _expression_binop_helper(y, x, operator.add) # needs sage.symbolic add(v_1, v_0) """ @@ -1595,9 +1641,9 @@ class IntegerPowerFunction(): sage: square = IntegerPowerFunction(2) sage: square (^2) - sage: square(pi) + sage: square(pi) # needs sage.symbolic pi^2 - sage: square(I) + sage: square(I) # needs sage.symbolic -1 sage: square(RIF(-1, 1)).str(style='brackets') '[0.0000000000000000 .. 1.0000000000000000]' @@ -1681,9 +1727,11 @@ cpdef dict get_builtin_functions(): sage: from sage.ext.fast_callable import get_builtin_functions sage: builtins = get_builtin_functions() - sage: sorted(set(builtins.values())) - ['abs', 'acos', 'acosh', 'add', 'asin', 'asinh', 'atan', 'atanh', 'ceil', 'cos', 'cosh', 'cot', 'csc', 'div', 'exp', 'floor', 'floordiv', 'inv', 'log', 'mul', 'neg', 'pow', 'sec', 'sin', 'sinh', 'sqrt', 'sub', 'tan', 'tanh'] - sage: builtins[sin] + sage: sorted(set(builtins.values())) # needs sage.symbolic + ['abs', 'acos', 'acosh', 'add', 'asin', 'asinh', 'atan', 'atanh', 'ceil', + 'cos', 'cosh', 'cot', 'csc', 'div', 'exp', 'floor', 'floordiv', 'inv', 'log', + 'mul', 'neg', 'pow', 'sec', 'sin', 'sinh', 'sqrt', 'sub', 'tan', 'tanh'] + sage: builtins[sin] # needs sage.symbolic 'sin' sage: builtins[ln] 'log' @@ -1736,9 +1784,11 @@ cpdef generate_code(Expression expr, InstructionStream stream): EXAMPLES:: sage: from sage.ext.fast_callable import ExpressionTreeBuilder, generate_code, InstructionStream + + sage: # needs sage.symbolic sage: etb = ExpressionTreeBuilder('x') sage: x = etb.var('x') - sage: expr = ((x+pi)*(x+1)) + sage: expr = (x+pi) * (x+1) sage: from sage.ext.interpreters.wrapper_py import metadata, Wrapper_py sage: instr_stream = InstructionStream(metadata, 1) sage: generate_code(expr, instr_stream) @@ -1756,6 +1806,8 @@ cpdef generate_code(Expression expr, InstructionStream stream): sage: def my_sqrt(x): ....: if x < 0: raise ValueError("sqrt of negative number") ....: return sqrt(x, extend=False) + + sage: # needs sage.symbolic sage: fc = fast_callable(expr, domain=RealField(130)) sage: fc(0) 3.1415926535897932384626433832795028842 @@ -1781,11 +1833,15 @@ cpdef generate_code(Expression expr, InstructionStream stream): sage: fc = fast_callable(etb.call(my_sin, x), domain=RDF) sage: fc(3) 0.1411200080598672 + + sage: # needs sage.rings.real_mpfr sage.symbolic sage: fc = fast_callable(etb.call(my_sin, x), domain=RealField(100)) sage: fc(3) 0.14112000805986722210074480281 sage: fc.op_list() [('load_arg', 0), ('py_call', , 1), 'return'] + + sage: # needs sage.symbolic sage: fc = fast_callable(etb.call(my_sqrt, x), domain=RDF) sage: fc(3) 1.7320508075688772 @@ -1802,6 +1858,7 @@ cpdef generate_code(Expression expr, InstructionStream stream): Traceback (most recent call last): ... ValueError: sqrt of negative number + sage: etb2 = ExpressionTreeBuilder(('y','z')) sage: y = etb2.var('y') sage: z = etb2.var('z') @@ -1812,26 +1869,28 @@ cpdef generate_code(Expression expr, InstructionStream stream): [('load_arg', 0), ('load_arg', 1), ('py_call', , 2), 'sqrt', 'return'] sage: fc.python_calls() [] - sage: fc = fast_callable(etb2.call(sqrt, etb2.call(my_norm, y, z)), domain=RR) - sage: fc(3, 4) + sage: fc = fast_callable(etb2.call(sqrt, etb2.call(my_norm, y, z)), domain=RR) # needs sage.rings.real_mpfr + sage: fc(3, 4) # needs sage.rings.real_mpfr 5.00000000000000 sage: fc = fast_callable(etb2.call(my_norm, y, z), domain=ZZ) sage: fc(3, 4) 25 sage: fc.op_list() [('load_arg', 0), ('load_arg', 1), ('py_call', , 2), 'return'] - sage: fc = fast_callable(expr) # needs sage.symbolic - sage: fc(3.0r) # needs sage.symbolic + + sage: # needs sage.symbolic + sage: fc = fast_callable(expr) + sage: fc(3.0r) 4.0*pi + 12.0 - sage: fc = fast_callable(x+3, domain=ZZ) # needs sage.symbolic - sage: fc(4) # needs sage.symbolic + sage: fc = fast_callable(x+3, domain=ZZ) + sage: fc(4) 7 - sage: fc = fast_callable(x/3, domain=ZZ) # needs sage.symbolic - sage: fc(4) # needs sage.symbolic + sage: fc = fast_callable(x/3, domain=ZZ) + sage: fc(4) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer - sage: fc(6) # needs sage.symbolic + sage: fc(6) 2 sage: fc = fast_callable(etb.call(sin, x), domain=ZZ) sage: fc(0) @@ -1843,6 +1902,7 @@ cpdef generate_code(Expression expr, InstructionStream stream): :: + sage: # needs sage.symbolic sage: fc = fast_callable(etb(x)^100) sage: fc(pi) pi^100 @@ -1857,18 +1917,18 @@ cpdef generate_code(Expression expr, InstructionStream stream): [('load_arg', 0), ('ipow', 100), 'return'] sage: fc(1.1) 13780.61233982... - sage: fc = fast_callable(etb(x)^100, domain=RR) - sage: fc.op_list() + sage: fc = fast_callable(etb(x)^100, domain=RR) # needs sage.rings.real_mpfr + sage: fc.op_list() # needs sage.rings.real_mpfr [('load_arg', 0), ('ipow', 100), 'return'] - sage: fc(1.1) + sage: fc(1.1) # needs sage.rings.real_mpfr 13780.6123398224 sage: fc = fast_callable(etb(x)^(-100), domain=RDF) sage: fc.op_list() [('load_arg', 0), ('ipow', -100), 'return'] sage: fc(1.1) 7.25657159014...e-05 - sage: fc = fast_callable(etb(x)^(-100), domain=RR) - sage: fc(1.1) + sage: fc = fast_callable(etb(x)^(-100), domain=RR) # needs sage.rings.real_mpfr + sage: fc(1.1) # needs sage.rings.real_mpfr 0.0000725657159014814 sage: expo = 2^32 sage: base = (1.0).nextabove() @@ -1879,10 +1939,10 @@ cpdef generate_code(Expression expr, InstructionStream stream): 1.0000009536747712 sage: RDF(base)^expo 1.0000009536747712 - sage: fc = fast_callable(etb(x)^expo, domain=RR) - sage: fc.op_list() + sage: fc = fast_callable(etb(x)^expo, domain=RR) # needs sage.rings.real_mpfr + sage: fc.op_list() # needs sage.rings.real_mpfr [('load_arg', 0), ('py_call', (^4294967296), 1), 'return'] - sage: fc(base) + sage: fc(base) # needs sage.rings.real_mpfr 1.00000095367477 sage: base^expo 1.00000095367477 @@ -1890,6 +1950,7 @@ cpdef generate_code(Expression expr, InstructionStream stream): Make sure we do not overflow the stack with highly nested expressions (:trac:`11766`):: + sage: # needs sage.rings.real_mpfr sage: R. = CC[] sage: f = R(list(range(100000))) sage: ff = fast_callable(f) @@ -2005,7 +2066,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.get_current() @@ -2041,7 +2103,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream, op_list sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.load_const(5) @@ -2066,7 +2129,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 12) sage: instr_stream.load_arg(5) @@ -2085,7 +2149,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.has_instr('return') @@ -2108,11 +2173,12 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.instr('load_arg', 0) - sage: instr_stream.instr('sin') + sage: instr_stream.instr('sin') # needs sage.symbolic sage: instr_stream.instr('py_call', math.sin, 1) sage: instr_stream.instr('abs') sage: instr_stream.instr('factorial') @@ -2120,7 +2186,7 @@ cdef class InstructionStream: ... KeyError: 'factorial' sage: instr_stream.instr('return') - sage: instr_stream.current_op_list() + sage: instr_stream.current_op_list() # needs sage.symbolic [('load_arg', 0), 'sin', ('py_call', , 1), 'abs', 'return'] """ self.instr0(opname, args) @@ -2186,7 +2252,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 1) sage: md = instr_stream.get_metadata() @@ -2204,7 +2271,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.instr('load_arg', 0) @@ -2226,7 +2294,8 @@ cdef class InstructionStream: EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.get_current() @@ -2374,7 +2443,8 @@ def op_list(args, metadata): EXAMPLES:: - sage: from sage.ext.interpreters.wrapper_rdf import metadata + sage: from sage.ext.interpreters.wrapper_el import metadata + sage: from sage.ext.interpreters.wrapper_rdf import metadata # needs sage.modules sage: from sage.ext.fast_callable import InstructionStream, op_list sage: instr_stream = InstructionStream(metadata, 1) sage: instr_stream.instr('load_arg', 0) @@ -2418,10 +2488,11 @@ cdef class Wrapper: EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import ExpressionTreeBuilder, generate_code, InstructionStream sage: etb = ExpressionTreeBuilder('x') sage: x = etb.var('x') - sage: expr = ((x+pi)*(x+1)) + sage: expr = (x+pi) * (x+1) sage: from sage.ext.interpreters.wrapper_py import metadata, Wrapper_py sage: instr_stream = InstructionStream(metadata, 1) sage: generate_code(expr, instr_stream) @@ -2454,7 +2525,7 @@ cdef class Wrapper: EXAMPLES:: - sage: fast_callable(sin(x)/x, vars=[x], domain=RDF).get_orig_args() + sage: fast_callable(sin(x)/x, vars=[x], domain=RDF).get_orig_args() # needs sage.symbolic {'args': 1, 'code': [0, 0, 16, 0, 0, 8, 2], 'constants': [], @@ -2470,7 +2541,7 @@ cdef class Wrapper: EXAMPLES:: - sage: fast_callable(cos(x)*x, vars=[x], domain=RDF).op_list() + sage: fast_callable(cos(x) * x, vars=[x], domain=RDF).op_list() # needs sage.symbolic [('load_arg', 0), ('load_arg', 0), 'cos', 'mul', 'return'] """ return op_list(self._orig_args, self._metadata) @@ -2486,9 +2557,9 @@ cdef class Wrapper: EXAMPLES:: - sage: fast_callable(abs(sin(x)), vars=[x], domain=RDF).python_calls() + sage: fast_callable(abs(sin(x)), vars=[x], domain=RDF).python_calls() # needs sage.symbolic [] - sage: fast_callable(abs(sin(factorial(x))), vars=[x]).python_calls() + sage: fast_callable(abs(sin(factorial(x))), vars=[x]).python_calls() # needs sage.symbolic [factorial, sin] """ ops = self.op_list() @@ -2557,6 +2628,7 @@ class FastCallableFloatWrapper: An error is thrown if the answer is complex:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import FastCallableFloatWrapper sage: f = sqrt(x) sage: ff = fast_callable(f, vars=[x], domain=CDF) @@ -2595,6 +2667,7 @@ class FastCallableFloatWrapper: The wrapper will ignore an imaginary part smaller in magnitude than ``imag_tol``, but not one larger:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import FastCallableFloatWrapper sage: f = x sage: ff = fast_callable(f, vars=[x], domain=CDF) @@ -2622,6 +2695,7 @@ class FastCallableFloatWrapper: Evaluation either returns a ``float``, or raises a ``ValueError``:: + sage: # needs sage.symbolic sage: from sage.ext.fast_callable import FastCallableFloatWrapper sage: f = x sage: ff = fast_callable(f, vars=[x], domain=CDF) diff --git a/src/sage/ext/fast_eval.pyx b/src/sage/ext/fast_eval.pyx index 7b45ea1c5a0..52fbc8f7406 100644 --- a/src/sage/ext/fast_eval.pyx +++ b/src/sage/ext/fast_eval.pyx @@ -51,14 +51,15 @@ def fast_float(f, *vars, old=None, expect_one_var=False): EXAMPLES:: sage: from sage.ext.fast_eval import fast_float - sage: x,y = var('x,y') - sage: f = fast_float(sqrt(x^2+y^2), 'x', 'y') - sage: f(3,4) + sage: x,y = var('x,y') # needs sage.symbolic + sage: f = fast_float(sqrt(x^2+y^2), 'x', 'y') # needs sage.symbolic + sage: f(3,4) # needs sage.symbolic 5.0 Specifying the argument names is essential, as fast_float objects only distinguish between arguments by order. :: + sage: # needs sage.symbolic sage: f = fast_float(x-y, 'x','y') sage: f(1,2) -1.0 diff --git a/src/sage/ext/memory.pyx b/src/sage/ext/memory.pyx index 1de6dedab82..b95130b19dd 100644 --- a/src/sage/ext/memory.pyx +++ b/src/sage/ext/memory.pyx @@ -3,14 +3,14 @@ Low-level memory allocation functions TESTS: -Check that a ``MemoryError`` is raised if we try to allocate a +Check that an error is raised if we try to allocate a ridiculously large integer, see :trac:`15363`:: - sage: 2^(2^63-3) - Traceback (most recent call last): - ... - OverflowError: exponent must be at most 2147483647 # 32-bit - RuntimeError: Aborted # 64-bit + sage: try: + ....: 2^(2^63-3) + ....: except (OverflowError, RuntimeError, FloatingPointError): + ....: print ('Overflow error') + ...Overflow error AUTHORS: diff --git a/src/sage/ext/memory_allocator.pxd b/src/sage/ext/memory_allocator.pxd index c4f2028f4e4..f96253345f6 100644 --- a/src/sage/ext/memory_allocator.pxd +++ b/src/sage/ext/memory_allocator.pxd @@ -56,7 +56,7 @@ cdef class MemoryAllocator: TESTS:: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: cdef MemoryAllocator mem = MemoryAllocator() @@ -87,7 +87,7 @@ cdef class MemoryAllocator: TESTS:: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: def foo(): @@ -97,7 +97,7 @@ cdef class MemoryAllocator: ....: ptr = mem.aligned_calloc(2**i, i, 2**i) ....: assert ptr == ( ptr) & ~(2**i-1) ....: ''') - sage: foo() # optional - sage.misc.cython + sage: foo() # needs sage.misc.cython doctest:...: DeprecationWarning: this class is deprecated; use the class from the python package `memory_allocator` See https://github.com/sagemath/sage/issues/31591 for details. @@ -124,7 +124,7 @@ cdef class MemoryAllocator: TESTS:: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: def foo(): @@ -134,8 +134,8 @@ cdef class MemoryAllocator: ....: ptr = mem.aligned_allocarray(2**i, i, 2**i) ....: assert ptr == ( ptr) & ~(2**i-1) ....: ''') - sage: foo() # random # might raise deprecation warning # optional - sage.misc.cython - sage: foo() # optional - sage.misc.cython + sage: foo() # random # might raise deprecation warning # needs sage.misc.cython + sage: foo() # needs sage.misc.cython """ # Find extra such that (nmemb + extra) * size >= nmemb * size + alignment - 1 # ⇔ extra * size >= alignment - 1 diff --git a/src/sage/ext/memory_allocator.pyx b/src/sage/ext/memory_allocator.pyx index 1f271a3e82e..0c2814658e9 100644 --- a/src/sage/ext/memory_allocator.pyx +++ b/src/sage/ext/memory_allocator.pyx @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.misc.cython +# sage.doctest: needs sage.misc.cython from cysignals.memory cimport * from sage.misc.superseded import deprecation diff --git a/src/sage/ext_data/valgrind/valgrind-python.supp b/src/sage/ext_data/valgrind/valgrind-python.supp new file mode 100644 index 00000000000..16aa2858484 --- /dev/null +++ b/src/sage/ext_data/valgrind/valgrind-python.supp @@ -0,0 +1,480 @@ +# From the CPython repository with the suppressions for _PyObject_Free +# and _PyObject_Realloc enabled. See the upstream suppression file for +# details: +# +# https://github.com/python/cpython/blob/main/Misc/valgrind-python.supp + +# all tool names: Addrcheck,Memcheck,cachegrind,helgrind,massif +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:address_in_range +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:address_in_range +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64) + Memcheck:Value8 + fun:address_in_range +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:address_in_range +} + +# +# Leaks (including possible leaks) +# Hmmm, I wonder if this masks some real leaks. I think it does. +# Will need to fix that. +# + +{ + Suppress leaking the GIL after a fork. + Memcheck:Leak + fun:malloc + fun:PyThread_allocate_lock + fun:PyEval_ReInitThreads +} + +{ + Suppress leaking the autoTLSkey. This looks like it shouldn't leak though. + Memcheck:Leak + fun:malloc + fun:PyThread_create_key + fun:_PyGILState_Init + fun:Py_InitializeEx + fun:Py_Main +} + +{ + Hmmm, is this a real leak or like the GIL? + Memcheck:Leak + fun:malloc + fun:PyThread_ReInitTLS +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:realloc + fun:_PyObject_GC_Resize + fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_New + fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_NewVar + fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING +} + +# +# Non-python specific leaks +# + +{ + Handle pthread issue (possibly leaked) + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls_storage + fun:_dl_allocate_tls +} + +{ + Handle pthread issue (possibly leaked) + Memcheck:Leak + fun:memalign + fun:_dl_allocate_tls_storage + fun:_dl_allocate_tls +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:_PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:_PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Addr8 + fun:_PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Value8 + fun:_PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:_PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:_PyObject_Realloc +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:_PyObject_Realloc +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Addr8 + fun:_PyObject_Realloc +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Value8 + fun:_PyObject_Realloc +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:_PyObject_Realloc +} + +### +### All the suppressions below are for errors that occur within libraries +### that Python uses. The problems to not appear to be related to Python's +### use of the libraries. +### + +{ + Generic ubuntu ld problems + Memcheck:Addr8 + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} + +{ + Generic gentoo ld problems + Memcheck:Cond + obj:/lib/ld-2.3.4.so + obj:/lib/ld-2.3.4.so + obj:/lib/ld-2.3.4.so + obj:/lib/ld-2.3.4.so +} + +{ + DBM problems, see test_dbm + Memcheck:Param + write(buf) + fun:write + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_close +} + +{ + DBM problems, see test_dbm + Memcheck:Value8 + fun:memmove + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_store + fun:dbm_ass_sub +} + +{ + DBM problems, see test_dbm + Memcheck:Cond + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_store + fun:dbm_ass_sub +} + +{ + DBM problems, see test_dbm + Memcheck:Cond + fun:memmove + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + obj:/usr/lib/libdb1.so.2 + fun:dbm_store + fun:dbm_ass_sub +} + +{ + GDBM problems, see test_gdbm + Memcheck:Param + write(buf) + fun:write + fun:gdbm_open + +} + +{ + Uninitialised byte(s) false alarm, see bpo-35561 + Memcheck:Param + epoll_ctl(event) + fun:epoll_ctl + fun:pyepoll_internal_ctl +} + +{ + ZLIB problems, see test_gzip + Memcheck:Cond + obj:/lib/libz.so.1.2.3 + obj:/lib/libz.so.1.2.3 + fun:deflate +} + +{ + Avoid problems w/readline doing a putenv and leaking on exit + Memcheck:Leak + fun:malloc + fun:xmalloc + fun:sh_set_lines_and_columns + fun:_rl_get_screen_size + fun:_rl_init_terminal_io + obj:/lib/libreadline.so.4.3 + fun:rl_initialize +} + +# Valgrind emits "Conditional jump or move depends on uninitialised value(s)" +# false alarms on GCC builtin strcmp() function. The GCC code is correct. +# +# Valgrind bug: https://bugs.kde.org/show_bug.cgi?id=264936 +{ + bpo-38118: Valgrind emits false alarm on GCC builtin strcmp() + Memcheck:Cond + fun:PyUnicode_Decode +} + + +### +### These occur from somewhere within the SSL, when running +### test_socket_sll. They are too general to leave on by default. +### +###{ +### somewhere in SSL stuff +### Memcheck:Cond +### fun:memset +###} +###{ +### somewhere in SSL stuff +### Memcheck:Value4 +### fun:memset +###} +### +###{ +### somewhere in SSL stuff +### Memcheck:Cond +### fun:MD5_Update +###} +### +###{ +### somewhere in SSL stuff +### Memcheck:Value4 +### fun:MD5_Update +###} + +# Fedora's package "openssl-1.0.1-0.1.beta2.fc17.x86_64" on x86_64 +# See http://bugs.python.org/issue14171 +{ + openssl 1.0.1 prng 1 + Memcheck:Cond + fun:bcmp + fun:fips_get_entropy + fun:FIPS_drbg_instantiate + fun:RAND_init_fips + fun:OPENSSL_init_library + fun:SSL_library_init + fun:init_hashlib +} + +{ + openssl 1.0.1 prng 2 + Memcheck:Cond + fun:fips_get_entropy + fun:FIPS_drbg_instantiate + fun:RAND_init_fips + fun:OPENSSL_init_library + fun:SSL_library_init + fun:init_hashlib +} + +{ + openssl 1.0.1 prng 3 + Memcheck:Value8 + fun:_x86_64_AES_encrypt_compact + fun:AES_encrypt +} + +# +# All of these problems come from using test_socket_ssl +# +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_bin2bn +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_num_bits_word +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:BN_num_bits_word +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_mod_exp_mont_word +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BN_mod_exp_mont +} + +{ + from test_socket_ssl + Memcheck:Param + write(buf) + fun:write + obj:/usr/lib/libcrypto.so.0.9.7 +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:RSA_verify +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:RSA_verify +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:DES_set_key_unchecked +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:DES_encrypt2 +} + +{ + from test_socket_ssl + Memcheck:Cond + obj:/usr/lib/libssl.so.0.9.7 +} + +{ + from test_socket_ssl + Memcheck:Value4 + obj:/usr/lib/libssl.so.0.9.7 +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:BUF_MEM_grow_clean +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:memcpy + fun:ssl3_read_bytes +} + +{ + from test_socket_ssl + Memcheck:Cond + fun:SHA1_Update +} + +{ + from test_socket_ssl + Memcheck:Value4 + fun:SHA1_Update +} + +{ + test_buffer_non_debug + Memcheck:Addr4 + fun:PyUnicodeUCS2_FSConverter +} + +{ + test_buffer_non_debug + Memcheck:Addr4 + fun:PyUnicode_FSConverter +} + +{ + wcscmp_false_positive + Memcheck:Addr8 + fun:wcscmp + fun:_PyOS_GetOpt + fun:Py_Main + fun:main +} + +# Additional suppressions for the unified decimal tests: +{ + test_decimal + Memcheck:Addr4 + fun:PyUnicodeUCS2_FSConverter +} + +{ + test_decimal2 + Memcheck:Addr4 + fun:PyUnicode_FSConverter +} + diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index f7c3c0749ee..ac3922552e4 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -392,13 +392,67 @@ def __init__(self): PythonModule('sage.interfaces.gap')]) +class sage__libs__linbox(JoinFeature): + r""" + A :class:`sage.features.Feature` describing the presence of :mod:`sage.libs.linbox` + and other modules depending on Givaro, FFLAS-FFPACK, LinBox. + + In addition to the modularization purposes that this tag serves, + it also provides attribution to the upstream project. + + TESTS:: + + sage: from sage.features.sagemath import sage__libs__linbox + sage: sage__libs__linbox().is_present() # needs sage.libs.linbox + FeatureTestResult('sage.libs.linbox', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sagemath import sage__libs__linbox + sage: isinstance(sage__libs__linbox(), sage__libs__linbox) + True + """ + JoinFeature.__init__(self, 'sage.libs.linbox', + [PythonModule('sage.rings.finite_rings.element_givaro')], + spkg='sagemath_linbox', type='standard') + + +class sage__libs__m4ri(JoinFeature): + r""" + A :class:`sage.features.Feature` describing the presence of Cython modules + depending on the M4RI and/or M4RIe libraries. + + In addition to the modularization purposes that this tag serves, + it also provides attribution to the upstream project. + + TESTS:: + + sage: from sage.features.sagemath import sage__libs__m4ri + sage: sage__libs__m4ri().is_present() # needs sage.libs.m4ri + FeatureTestResult('sage.libs.m4ri', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sagemath import sage__libs__m4ri + sage: isinstance(sage__libs__m4ri(), sage__libs__m4ri) + True + """ + JoinFeature.__init__(self, 'sage.libs.m4ri', + [PythonModule('sage.matrix.matrix_gf2e_dense')], + spkg='sagemath_m4ri', type='standard') + + class sage__libs__ntl(JoinFeature): r""" A :class:`sage.features.Feature` describing the presence of :mod:`sage.libs.ntl` - and other modules depending on NTL and arb. + and other modules depending on NTL. - In addition to the modularization purposes that this tag serves, it also provides attribution - to the upstream project. + In addition to the modularization purposes that this tag serves, + it also provides attribution to the upstream project. TESTS:: @@ -423,11 +477,12 @@ class sage__libs__pari(JoinFeature): r""" A :class:`~sage.features.Feature` describing the presence of :mod:`sage.libs.pari`. - SageMath uses the :ref:`PARI ` library (via :ref:`cypari2 `) for numerous purposes. - Doctests that involves such features should be marked ``# needs sage.libs.pari``. + SageMath uses the :ref:`PARI ` library (via :ref:`cypari2 + `) for numerous purposes. Doctests that involves such features + should be marked ``# needs sage.libs.pari``. - In addition to the modularization purposes that this tag serves, it also provides attribution - to the upstream project. + In addition to the modularization purposes that this tag serves, it also + provides attribution to the upstream project. EXAMPLES:: @@ -1005,6 +1060,8 @@ def all_features(): sage__libs__ecl(), sage__libs__flint(), sage__libs__gap(), + sage__libs__linbox(), + sage__libs__m4ri(), sage__libs__ntl(), sage__libs__pari(), sage__libs__singular(), diff --git a/src/sage/functions/airy.py b/src/sage/functions/airy.py index eceb9e6eafc..11f4c56be8c 100644 --- a/src/sage/functions/airy.py +++ b/src/sage/functions/airy.py @@ -30,9 +30,9 @@ Verify that the Airy functions are solutions to the differential equation:: - sage: diff(airy_ai(x), x, 2) - x * airy_ai(x) + sage: diff(airy_ai(x), x, 2) - x * airy_ai(x) # needs sage.symbolic 0 - sage: diff(airy_bi(x), x, 2) - x * airy_bi(x) + sage: diff(airy_bi(x), x, 2) - x * airy_bi(x) # needs sage.symbolic 0 """ @@ -46,11 +46,17 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression -from sage.symbolic.ring import SR -from sage.rings.integer_ring import ZZ from sage.calculus.functional import derivative +from sage.misc.lazy_import import lazy_import +from sage.rings.integer_ring import ZZ +from sage.structure.element import Expression +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', ['airyai', 'airybi'], + as_=['_mpmath_airyai', '_mpmath_airybi']) class FunctionAiryAiGeneral(BuiltinFunction): @@ -76,6 +82,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.airy import airy_ai_general sage: x, n = var('x n') sage: airy_ai_general(-2, x) @@ -95,10 +102,10 @@ def _derivative_(self, alpha, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_ai_general - sage: x, n = var('x n') - sage: derivative(airy_ai_general(n, x), x) + sage: x, n = var('x n') # needs sage.symbolic + sage: derivative(airy_ai_general(n, x), x) # needs sage.symbolic airy_ai(n + 1, x) - sage: derivative(airy_ai_general(n, x), n) + sage: derivative(airy_ai_general(n, x), n) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: cannot differentiate airy_ai @@ -114,10 +121,10 @@ def _eval_(self, alpha, x): EXAMPLES:: sage: from sage.functions.airy import airy_ai_general - sage: x, n = var('x n') - sage: airy_ai_general(-2, 1.0) + sage: x, n = var('x n') # needs sage.symbolic + sage: airy_ai_general(-2, 1.0) # needs mpmath 0.136645379421096 - sage: airy_ai_general(n, 1.0) + sage: airy_ai_general(n, 1.0) # needs sage.symbolic airy_ai(n, 1.00000000000000) """ if not isinstance(x, Expression) and \ @@ -138,13 +145,11 @@ def _evalf_(self, alpha, x, parent=None, algorithm=None): EXAMPLES:: sage: from sage.functions.airy import airy_ai_general - sage: airy_ai_general(-2, 1.0) + sage: airy_ai_general(-2, 1.0) # needs mpmath 0.136645379421096 """ - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airyai, x, derivative=alpha, - parent=parent) + return _mpmath_utils_call(_mpmath_airyai, x, derivative=alpha, + parent=parent) class FunctionAiryAiSimple(BuiltinFunction): @@ -155,9 +160,9 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: f = airy_ai_simple(x); f + sage: f = airy_ai_simple(x); f # needs sage.symbolic airy_ai(x) - sage: airy_ai_simple(x)._sympy_() + sage: airy_ai_simple(x)._sympy_() # needs sage.symbolic airyai(x) """ BuiltinFunction.__init__(self, 'airy_ai', @@ -173,7 +178,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: derivative(airy_ai_simple(x), x) + sage: derivative(airy_ai_simple(x), x) # needs sage.symbolic airy_ai_prime(x) """ return airy_ai_prime(x) @@ -183,13 +188,13 @@ def _eval_(self, x): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: airy_ai_simple(0) + sage: airy_ai_simple(0) # needs sage.symbolic 1/3*3^(1/3)/gamma(2/3) - sage: airy_ai_simple(0.0) + sage: airy_ai_simple(0.0) # needs mpmath 0.355028053887817 - sage: airy_ai_simple(I) + sage: airy_ai_simple(I) # needs sage.symbolic airy_ai(I) - sage: airy_ai_simple(1.0 * I) + sage: airy_ai_simple(1.0 * I) # needs sage.symbolic 0.331493305432141 - 0.317449858968444*I """ from .gamma import gamma @@ -202,27 +207,28 @@ def _evalf_(self, x, **kwargs): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: airy_ai_simple(0.0) + sage: airy_ai_simple(0.0) # needs mpmath 0.355028053887817 - sage: airy_ai_simple(1.0 * I) + sage: airy_ai_simple(1.0 * I) # needs sage.symbolic 0.331493305432141 - 0.317449858968444*I We can use several methods for numerical evaluation:: + sage: # needs sage.symbolic sage: airy_ai_simple(3).n(algorithm='mpmath') 0.00659113935746072 sage: airy_ai_simple(3).n(algorithm='mpmath', prec=100) 0.0065911393574607191442574484080 - sage: airy_ai_simple(3).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai_simple(3).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 0.006591139357460719 sage: airy_ai_simple(I).n(algorithm='scipy') # rel tol 1e-10 0.33149330543214117 - 0.3174498589684438*I TESTS:: - sage: parent(airy_ai_simple(3).n(algorithm='scipy')) + sage: parent(airy_ai_simple(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_ai_simple(3).n(algorithm='scipy', prec=200) + sage: airy_ai_simple(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_ai not implemented for precision > 53 @@ -246,9 +252,7 @@ def _evalf_(self, x, **kwargs): return CC(y) return parent(y) elif algorithm == 'mpmath': - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airyai, x, parent=parent) + return _mpmath_utils_call(_mpmath_airyai, x, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -261,12 +265,13 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: x, n = var('x n') sage: airy_ai_prime(x) airy_ai_prime(x) sage: airy_ai_prime(0) -1/3*3^(2/3)/gamma(1/3) - sage: airy_ai_prime(x)._sympy_() + sage: airy_ai_prime(x)._sympy_() # needs sympy airyaiprime(x) """ BuiltinFunction.__init__(self, 'airy_ai_prime', @@ -280,7 +285,7 @@ def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: derivative(airy_ai_prime(x), x) + sage: derivative(airy_ai_prime(x), x) # needs sage.symbolic x*airy_ai(x) """ return x * airy_ai_simple(x) @@ -289,9 +294,9 @@ def _eval_(self, x): """ EXAMPLES:: - sage: airy_ai_prime(0) + sage: airy_ai_prime(0) # needs sage.symbolic -1/3*3^(2/3)/gamma(1/3) - sage: airy_ai_prime(0.0) + sage: airy_ai_prime(0.0) # needs mpmath -0.258819403792807 """ from .gamma import gamma @@ -303,25 +308,26 @@ def _evalf_(self, x, **kwargs): """ EXAMPLES:: - sage: airy_ai_prime(0.0) + sage: airy_ai_prime(0.0) # needs mpmath -0.258819403792807 We can use several methods for numerical evaluation:: + sage: # needs sage.symbolic sage: airy_ai_prime(4).n(algorithm='mpmath') -0.00195864095020418 sage: airy_ai_prime(4).n(algorithm='mpmath', prec=100) -0.0019586409502041789001381409184 - sage: airy_ai_prime(4).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai_prime(4).n(algorithm='scipy') # rel tol 1e-10 # needs scipy -0.00195864095020418 - sage: airy_ai_prime(I).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai_prime(I).n(algorithm='scipy') # rel tol 1e-10 # needs scipy -0.43249265984180707 + 0.09804785622924324*I TESTS:: - sage: parent(airy_ai_prime(3).n(algorithm='scipy')) + sage: parent(airy_ai_prime(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_ai_prime(3).n(algorithm='scipy', prec=200) + sage: airy_ai_prime(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_ai_prime not implemented @@ -346,9 +352,7 @@ def _evalf_(self, x, **kwargs): return CC(y) return parent(y) elif algorithm == 'mpmath': - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airyai, x, derivative=1, + return _mpmath_utils_call(_mpmath_airyai, x, derivative=1, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -405,12 +409,13 @@ def airy_ai(alpha, x=None, hold_derivative=True, **kwds): EXAMPLES:: - sage: n, x = var('n x') - sage: airy_ai(x) + sage: n, x = var('n x') # needs sage.symbolic + sage: airy_ai(x) # needs sage.symbolic airy_ai(x) It can return derivatives or integrals:: + sage: # needs sage.symbolic sage: airy_ai(2, x) airy_ai(2, x) sage: airy_ai(1, x, hold_derivative=False) @@ -425,35 +430,35 @@ def airy_ai(alpha, x=None, hold_derivative=True, **kwds): It can be evaluated symbolically or numerically for real or complex values:: - sage: airy_ai(0) + sage: airy_ai(0) # needs sage.symbolic 1/3*3^(1/3)/gamma(2/3) - sage: airy_ai(0.0) + sage: airy_ai(0.0) # needs mpmath 0.355028053887817 - sage: airy_ai(I) + sage: airy_ai(I) # needs sage.symbolic airy_ai(I) - sage: airy_ai(1.0*I) + sage: airy_ai(1.0*I) # needs sage.symbolic 0.331493305432141 - 0.317449858968444*I The functions can be evaluated numerically either using mpmath. which can compute the values to arbitrary precision, and scipy:: - sage: airy_ai(2).n(prec=100) + sage: airy_ai(2).n(prec=100) # needs sage.symbolic 0.034924130423274379135322080792 - sage: airy_ai(2).n(algorithm='mpmath', prec=100) + sage: airy_ai(2).n(algorithm='mpmath', prec=100) # needs sage.symbolic 0.034924130423274379135322080792 - sage: airy_ai(2).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai(2).n(algorithm='scipy') # rel tol 1e-10 # needs scipy sage.symbolic 0.03492413042327323 And the derivatives can be evaluated:: - sage: airy_ai(1, 0) + sage: airy_ai(1, 0) # needs sage.symbolic -1/3*3^(2/3)/gamma(1/3) - sage: airy_ai(1, 0.0) + sage: airy_ai(1, 0.0) # needs mpmath -0.258819403792807 Plots:: - sage: plot(airy_ai(x), (x, -10, 5)) + plot(airy_ai_prime(x), + sage: plot(airy_ai(x), (x, -10, 5)) + plot(airy_ai_prime(x), # needs sage.plot sage.symbolic ....: (x, -10, 5), color='red') Graphics object consisting of 2 graphics primitives @@ -515,6 +520,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.airy import airy_bi_general sage: x, n = var('x n') sage: airy_bi_general(-2, x) @@ -534,10 +540,10 @@ def _derivative_(self, alpha, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_bi_general - sage: x, n = var('x n') - sage: derivative(airy_bi_general(n, x), x) + sage: x, n = var('x n') # needs sage.symbolic + sage: derivative(airy_bi_general(n, x), x) # needs sage.symbolic airy_bi(n + 1, x) - sage: derivative(airy_bi_general(n, x), n) + sage: derivative(airy_bi_general(n, x), n) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: cannot differentiate airy_bi @@ -553,10 +559,10 @@ def _eval_(self, alpha, x): EXAMPLES:: sage: from sage.functions.airy import airy_bi_general - sage: x, n = var('x n') - sage: airy_bi_general(-2, 1.0) + sage: x, n = var('x n') # needs sage.symbolic + sage: airy_bi_general(-2, 1.0) # needs mpmath 0.388621540699059 - sage: airy_bi_general(n, 1.0) + sage: airy_bi_general(n, 1.0) # needs sage.symbolic airy_bi(n, 1.00000000000000) """ if not isinstance(x, Expression) and \ @@ -573,14 +579,14 @@ def _evalf_(self, alpha, x, **kwargs): EXAMPLES:: sage: from sage.functions.airy import airy_bi_general - sage: airy_bi_general(-2, 1.0) + sage: airy_bi_general(-2, 1.0) # needs mpmath 0.388621540699059 """ parent = kwargs.get('parent') import mpmath from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airybi, x, derivative=alpha, + return _mpmath_utils_call(_mpmath_airybi, x, derivative=alpha, parent=parent) @@ -592,9 +598,9 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: f = airy_bi_simple(x); f + sage: f = airy_bi_simple(x); f # needs sage.symbolic airy_bi(x) - sage: f._sympy_() + sage: f._sympy_() # needs sympy sage.symbolic airybi(x) """ BuiltinFunction.__init__(self, 'airy_bi', @@ -610,7 +616,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: derivative(airy_bi_simple(x), x) + sage: derivative(airy_bi_simple(x), x) # needs sage.symbolic airy_bi_prime(x) """ return airy_bi_prime(x) @@ -620,15 +626,15 @@ def _eval_(self, x): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: airy_bi_simple(0) + sage: airy_bi_simple(0) # needs sage.symbolic 1/3*3^(5/6)/gamma(2/3) - sage: airy_bi_simple(0.0) + sage: airy_bi_simple(0.0) # needs mpmath 0.614926627446001 - sage: airy_bi_simple(0).n() == airy_bi(0.0) + sage: airy_bi_simple(0).n() == airy_bi(0.0) # needs mpmath sage.symbolic True - sage: airy_bi_simple(I) + sage: airy_bi_simple(I) # needs sage.symbolic airy_bi(I) - sage: airy_bi_simple(1.0 * I) + sage: airy_bi_simple(1.0 * I) # needs sage.symbolic 0.648858208330395 + 0.344958634768048*I """ from .gamma import gamma @@ -641,27 +647,28 @@ def _evalf_(self, x, **kwargs): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: airy_bi_simple(0.0) + sage: airy_bi_simple(0.0) # needs mpmath 0.614926627446001 - sage: airy_bi_simple(1.0 * I) + sage: airy_bi_simple(1.0 * I) # needs sage.symbolic 0.648858208330395 + 0.344958634768048*I We can use several methods for numerical evaluation:: - sage: airy_bi_simple(3).n(algorithm='mpmath') + sage: # needs sage.symbolic + sage: airy_bi_simple(3).n(algorithm='mpmath') # needs mpmath 14.0373289637302 - sage: airy_bi_simple(3).n(algorithm='mpmath', prec=100) + sage: airy_bi_simple(3).n(algorithm='mpmath', prec=100) # needs mpmath 14.037328963730232031740267314 - sage: airy_bi_simple(3).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi_simple(3).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 14.037328963730136 - sage: airy_bi_simple(I).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi_simple(I).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 0.648858208330395 + 0.34495863476804844*I TESTS:: - sage: parent(airy_bi_simple(3).n(algorithm='scipy')) + sage: parent(airy_bi_simple(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_bi_simple(3).n(algorithm='scipy', prec=200) + sage: airy_bi_simple(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_bi not implemented for precision > 53 @@ -687,7 +694,7 @@ def _evalf_(self, x, **kwargs): elif algorithm == 'mpmath': import mpmath from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airybi, x, parent=parent) + return _mpmath_utils_call(_mpmath_airybi, x, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -700,12 +707,13 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: x, n = var('x n') sage: airy_bi_prime(x) airy_bi_prime(x) sage: airy_bi_prime(0) 3^(1/6)/gamma(1/3) - sage: airy_bi_prime(x)._sympy_() + sage: airy_bi_prime(x)._sympy_() # needs sympy airybiprime(x) """ BuiltinFunction.__init__(self, 'airy_bi_prime', @@ -719,7 +727,7 @@ def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: derivative(airy_bi_prime(x), x) + sage: derivative(airy_bi_prime(x), x) # needs sage.symbolic x*airy_bi(x) """ return x * airy_bi_simple(x) @@ -728,9 +736,9 @@ def _eval_(self, x): """ EXAMPLES:: - sage: airy_bi_prime(0) + sage: airy_bi_prime(0) # needs sage.symbolic 3^(1/6)/gamma(1/3) - sage: airy_bi_prime(0.0) + sage: airy_bi_prime(0.0) # needs mpmath 0.448288357353826 """ from .gamma import gamma @@ -742,25 +750,26 @@ def _evalf_(self, x, **kwargs): """ EXAMPLES:: - sage: airy_bi_prime(0.0) + sage: airy_bi_prime(0.0) # needs mpmath 0.448288357353826 We can use several methods for numerical evaluation:: + sage: # needs sage.symbolic sage: airy_bi_prime(4).n(algorithm='mpmath') 161.926683504613 sage: airy_bi_prime(4).n(algorithm='mpmath', prec=100) 161.92668350461340184309492429 - sage: airy_bi_prime(4).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi_prime(4).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 161.92668350461398 sage: airy_bi_prime(I).n(algorithm='scipy') # rel tol 1e-10 0.135026646710819 - 0.1288373867812549*I TESTS:: - sage: parent(airy_bi_prime(3).n(algorithm='scipy')) + sage: parent(airy_bi_prime(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_bi_prime(3).n(algorithm='scipy', prec=200) + sage: airy_bi_prime(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_bi_prime not implemented @@ -785,9 +794,7 @@ def _evalf_(self, x, **kwargs): return CC(y) return parent(y) elif algorithm == 'mpmath': - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airybi, x, derivative=1, + return _mpmath_utils_call(_mpmath_airybi, x, derivative=1, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -845,12 +852,13 @@ def airy_bi(alpha, x=None, hold_derivative=True, **kwds): EXAMPLES:: - sage: n, x = var('n x') - sage: airy_bi(x) + sage: n, x = var('n x') # needs sage.symbolic + sage: airy_bi(x) # needs sage.symbolic airy_bi(x) It can return derivatives or integrals:: + sage: # needs sage.symbolic sage: airy_bi(2, x) airy_bi(2, x) sage: airy_bi(1, x, hold_derivative=False) @@ -865,35 +873,35 @@ def airy_bi(alpha, x=None, hold_derivative=True, **kwds): It can be evaluated symbolically or numerically for real or complex values:: - sage: airy_bi(0) + sage: airy_bi(0) # needs sage.symbolic 1/3*3^(5/6)/gamma(2/3) - sage: airy_bi(0.0) + sage: airy_bi(0.0) # needs mpmath 0.614926627446001 - sage: airy_bi(I) + sage: airy_bi(I) # needs sage.symbolic airy_bi(I) - sage: airy_bi(1.0*I) + sage: airy_bi(1.0*I) # needs sage.symbolic 0.648858208330395 + 0.344958634768048*I The functions can be evaluated numerically using mpmath, which can compute the values to arbitrary precision, and scipy:: - sage: airy_bi(2).n(prec=100) + sage: airy_bi(2).n(prec=100) # needs sage.symbolic 3.2980949999782147102806044252 - sage: airy_bi(2).n(algorithm='mpmath', prec=100) + sage: airy_bi(2).n(algorithm='mpmath', prec=100) # needs sage.symbolic 3.2980949999782147102806044252 - sage: airy_bi(2).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi(2).n(algorithm='scipy') # rel tol 1e-10 # needs scipy sage.symbolic 3.2980949999782134 And the derivatives can be evaluated:: - sage: airy_bi(1, 0) + sage: airy_bi(1, 0) # needs sage.symbolic 3^(1/6)/gamma(1/3) - sage: airy_bi(1, 0.0) + sage: airy_bi(1, 0.0) # needs mpmath 0.448288357353826 Plots:: - sage: plot(airy_bi(x), (x, -10, 5)) + plot(airy_bi_prime(x), + sage: plot(airy_bi(x), (x, -10, 5)) + plot(airy_bi_prime(x), # needs sage.plot sage.symbolic ....: (x, -10, 5), color='red') Graphics object consisting of 2 graphics primitives diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index 48607c49f56..24ee74b561c 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -122,33 +122,34 @@ Evaluate the Bessel J function symbolically and numerically:: + sage: # needs sage.symbolic sage: bessel_J(0, x) bessel_J(0, x) sage: bessel_J(0, 0) 1 sage: bessel_J(0, x).diff(x) -1/2*bessel_J(1, x) + 1/2*bessel_J(-1, x) - - sage: N(bessel_J(0, 0), digits = 20) + sage: N(bessel_J(0, 0), digits=20) 1.0000000000000000000 - sage: find_root(bessel_J(0,x), 0, 5) + sage: find_root(bessel_J(0,x), 0, 5) # needs scipy 2.404825557695773 Plot the Bessel J function:: - sage: f(x) = Bessel(0)(x); f + sage: f(x) = Bessel(0)(x); f # needs sage.symbolic x |--> bessel_J(0, x) - sage: plot(f, (x, 1, 10)) + sage: plot(f, (x, 1, 10)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive Visualize the Bessel Y function on the complex plane (set plot_points to a higher value to get more detail):: - sage: complex_plot(bessel_Y(0, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_Y(0, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive Evaluate a combination of Bessel functions:: + sage: # needs sage.symbolic sage: f(x) = bessel_J(1, x) - bessel_Y(0, x) sage: f(pi) bessel_J(1, pi) - bessel_Y(0, pi) @@ -160,6 +161,7 @@ Symbolically solve a second order differential equation with initial conditions `y(1) = a` and `y'(1) = b` in terms of Bessel functions:: + sage: # needs sage.symbolic sage: y = function('y')(x) sage: a, b = var('a, b') sage: diffeq = x^2*diff(y,x,x) + x*diff(y,x) + x^2*y == 0 @@ -212,18 +214,30 @@ from sage.misc.functional import sqrt from sage.functions.log import exp +from sage.functions.gamma import gamma from sage.functions.hyperbolic import sinh, cosh from sage.functions.trig import sin, cos -from sage.libs.mpmath import utils as mpmath_utils -from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import infinity, unsigned_infinity from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.structure.element import get_coercion_model -from sage.symbolic.constants import pi -from sage.symbolic.ring import SR +from sage.structure.element import Expression, get_coercion_model from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.symbolic.constants', 'pi') +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', + ['besseli', 'besselj', 'besselk', + 'bessely', 'hankel1', 'hankel2', + 'struveh', 'struvel'], + as_=['_mpmath_besseli', '_mpmath_besselj', '_mpmath_besselk', + '_mpmath_bessely', '_mpmath_hankel1', '_mpmath_hankel2', + '_mpmath_struveh', '_mpmath_struvel']) class Function_Bessel_J(BuiltinFunction): @@ -258,11 +272,12 @@ class Function_Bessel_J(BuiltinFunction): EXAMPLES:: - sage: bessel_J(1.0, 1.0) + sage: bessel_J(1.0, 1.0) # needs mpmath 0.440050585744933 + + sage: # needs sage.symbolic sage: bessel_J(2, I).n(digits=30) -0.135747669767038281182852569995 - sage: bessel_J(1, x) bessel_J(1, x) sage: n = var('n') @@ -271,34 +286,34 @@ class Function_Bessel_J(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_J(pi, bessel_J(1, I)); a bessel_J(pi, bessel_J(1, I)) sage: N(a, digits=20) 0.00059023706363796717363 - 0.0026098820470081958110*I - sage: f = bessel_J(2, x) sage: f.diff(x) -1/2*bessel_J(3, x) + 1/2*bessel_J(1, x) Comparison to a well-known integral representation of `J_1(1)`:: - sage: A = numerical_integral(1/pi*cos(x - sin(x)), 0, pi) - sage: A[0] # abs tol 1e-14 + sage: A = numerical_integral(1/pi*cos(x - sin(x)), 0, pi) # needs sage.symbolic + sage: A[0] # abs tol 1e-14 # needs sage.symbolic 0.44005058574493355 - sage: bessel_J(1.0, 1.0) - A[0] < 1e-15 + sage: bessel_J(1.0, 1.0) - A[0] < 1e-15 # needs sage.symbolic True Integration is supported directly and through Maxima:: - sage: f = bessel_J(2, x) - sage: f.integrate(x) + sage: f = bessel_J(2, x) # needs sage.symbolic + sage: f.integrate(x) # needs sage.symbolic 1/24*x^3*hypergeometric((3/2,), (5/2, 3), -1/4*x^2) Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_J(1,x), (x,0,5), color='blue') + sage: plot(bessel_J(1,x), (x,0,5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_J(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_J(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -308,7 +323,7 @@ class Function_Bessel_J(BuiltinFunction): Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_J(5, 1.5) in RR + sage: bessel_J(5, 1.5) in RR # needs mpmath True REFERENCES: @@ -327,7 +342,7 @@ def __init__(self): sage: sage.functions.bessel.Function_Bessel_J() bessel_J - sage: bessel_J(x, x)._sympy_() + sage: bessel_J(x, x)._sympy_() # needs sympy sage.symbolic besselj(x, x) """ BuiltinFunction.__init__(self, 'bessel_J', nargs=2, @@ -342,6 +357,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: bessel_J(0, 0) 1 @@ -358,7 +374,6 @@ def _eval_(self, n, x): sage: bessel_J(n, 0) bessel_J(n, 0) """ - from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return ZZ.one() @@ -375,15 +390,16 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_J(0.0, 1.0) + sage: bessel_J(0.0, 1.0) # needs mpmath 0.765197686557967 - sage: bessel_J(0, 1).n(digits=20) + sage: bessel_J(0, 1).n(digits=20) # needs sage.symbolic 0.76519768655796655145 - sage: bessel_J(0.5, 1.5) + sage: bessel_J(0.5, 1.5) # needs mpmath 0.649838074753747 Check for correct rounding (:trac:`17122`):: + sage: # needs sage.rings.real_mpfr sage: R = RealField(113) sage: a = R("8.935761195587725798762818805462843676e-01") sage: aa = RealField(200)(a) @@ -402,8 +418,7 @@ def _evalf_(self, n, x, parent=None, algorithm=None): pass n, x = get_coercion_model().canonical_coercion(n, x) - import mpmath - return mpmath_utils.call(mpmath.besselj, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_besselj, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -411,6 +426,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(z) = bessel_J(10, z) sage: derivative(f, z) z |--> -1/2*bessel_J(11, z) + 1/2*bessel_J(9, z) @@ -432,7 +448,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_J(1, x)) + sage: latex(bessel_J(1, x)) # needs sage.symbolic J_{1}(x) """ return r"J_{%s}(%s)" % (latex(n), latex(z)) @@ -466,10 +482,12 @@ class Function_Bessel_Y(BuiltinFunction): EXAMPLES:: - sage: bessel_Y(1, x) + sage: bessel_Y(1, x) # needs sage.symbolic bessel_Y(1, x) - sage: bessel_Y(1.0, 1.0) + sage: bessel_Y(1.0, 1.0) # needs mpmath -0.781212821300289 + + sage: # needs sage.symbolic sage: n = var('n') sage: bessel_Y(n, x) bessel_Y(n, x) @@ -482,29 +500,30 @@ class Function_Bessel_Y(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_Y(pi, bessel_Y(1, I)); a bessel_Y(pi, bessel_Y(1, I)) sage: N(a, digits=20) 4.2059146571791095708 + 21.307914215321993526*I - sage: f = bessel_Y(2, x) sage: f.diff(x) -1/2*bessel_Y(3, x) + 1/2*bessel_Y(1, x) High precision and complex valued inputs (see :trac:`4230`):: - sage: bessel_Y(0, 1).n(128) + sage: bessel_Y(0, 1).n(128) # needs sage.symbolic 0.088256964215676957982926766023515162828 - sage: bessel_Y(0, RealField(200)(1)) + sage: bessel_Y(0, RealField(200)(1)) # needs sage.rings.real_mpfr 0.088256964215676957982926766023515162827817523090675546711044 - sage: bessel_Y(0, ComplexField(200)(0.5+I)) - 0.077763160184438051408593468823822434235010300228009867784073 + 1.0142336049916069152644677682828326441579314239591288411739*I + sage: bessel_Y(0, ComplexField(200)(0.5+I)) # needs sage.symbolic + 0.077763160184438051408593468823822434235010300228009867784073 + + 1.0142336049916069152644677682828326441579314239591288411739*I Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_Y(1,x), (x,0,5), color='blue') + sage: plot(bessel_Y(1, x), (x, 0, 5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_Y(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_Y(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -516,11 +535,12 @@ class Function_Bessel_Y(BuiltinFunction): Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_Y(5, 1.5) in RR + sage: bessel_Y(5, 1.5) in RR # needs mpmath True Coercion works correctly (see :trac:`17130`):: + sage: # needs sage.rings.real_mpfr sage: r = bessel_Y(RealField(200)(1), 1.0); r -0.781212821300289 sage: parent(r) @@ -544,9 +564,9 @@ def __init__(self): EXAMPLES:: - sage: sage.functions.bessel.Function_Bessel_Y()(0, x) + sage: sage.functions.bessel.Function_Bessel_Y()(0, x) # needs sage.symbolic bessel_Y(0, x) - sage: bessel_Y(x, x)._sympy_() + sage: bessel_Y(x, x)._sympy_() # needs sympy sage.symbolic bessely(x, x) """ BuiltinFunction.__init__(self, 'bessel_Y', nargs=2, @@ -561,6 +581,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: bessel_Y(1, 0) Infinity sage: bessel_Y(I,0) @@ -572,10 +593,9 @@ def _eval_(self, n, x): TESTS:: - sage: bessel_Y(0, 0) + sage: bessel_Y(0, 0) # needs sage.symbolic -Infinity """ - from sage.rings.infinity import infinity, unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return -infinity @@ -590,15 +610,16 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_Y(0.5, 1.5) + sage: bessel_Y(0.5, 1.5) # needs mpmath -0.0460831658930974 - sage: bessel_Y(1.0+2*I, 3.0+4*I) + sage: bessel_Y(1.0+2*I, 3.0+4*I) # needs mpmath sage.symbolic 0.699410324467538 + 0.228917940896421*I - sage: bessel_Y(0, 1).n(256) + sage: bessel_Y(0, 1).n(256) # needs mpmath sage.symbolic 0.08825696421567695798292676602351516282781752309067554671104384761199978932351 Check for correct rounding (:trac:`17122`):: + sage: # needs mpmath sage.rings.real_mpfr sage: R = RealField(113) sage: a = R("8.935761195587725798762818805462843676e-01") sage: aa = RealField(200)(a) @@ -617,8 +638,7 @@ def _evalf_(self, n, x, parent=None, algorithm=None): pass n, x = get_coercion_model().canonical_coercion(n, x) - import mpmath - return mpmath_utils.call(mpmath.bessely, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_bessely, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -626,6 +646,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(x) = bessel_Y(10, x) sage: derivative(f, x) x |--> -1/2*bessel_Y(11, x) + 1/2*bessel_Y(9, x) @@ -646,7 +667,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_Y(1, x)) + sage: latex(bessel_Y(1, x)) # needs sage.symbolic Y_{1}(x) """ return r"Y_{%s}(%s)" % (latex(n), latex(z)) @@ -667,10 +688,12 @@ class Function_Bessel_I(BuiltinFunction): EXAMPLES:: + sage: bessel_I(1.0, 1.0) # needs mpmath + 0.565159103992485 + + sage: # needs sage.symbolic sage: bessel_I(1, x) bessel_I(1, x) - sage: bessel_I(1.0, 1.0) - 0.565159103992485 sage: n = var('n') sage: bessel_I(n, x) bessel_I(n, x) @@ -679,16 +702,17 @@ class Function_Bessel_I(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_I(pi, bessel_I(1, I)) sage: N(a, digits=20) 0.00026073272117205890524 - 0.0011528954889080572268*I - sage: f = bessel_I(2, x) sage: f.diff(x) 1/2*bessel_I(3, x) + 1/2*bessel_I(1, x) Special identities that bessel_I satisfies:: + sage: # needs sage.symbolic sage: bessel_I(1/2, x) sqrt(2)*sqrt(1/(pi*x))*sinh(x) sage: eq = bessel_I(1/2, x) == bessel_I(0.5, x) @@ -702,25 +726,26 @@ class Function_Bessel_I(BuiltinFunction): Examples of asymptotic behavior:: - sage: limit(bessel_I(0, x), x=oo) + sage: limit(bessel_I(0, x), x=oo) # needs sage.symbolic +Infinity - sage: limit(bessel_I(0, x), x=0) + sage: limit(bessel_I(0, x), x=0) # needs sage.symbolic 1 High precision and complex valued inputs:: - sage: bessel_I(0, 1).n(128) + sage: bessel_I(0, 1).n(128) # needs sage.symbolic 1.2660658777520083355982446252147175376 - sage: bessel_I(0, RealField(200)(1)) + sage: bessel_I(0, RealField(200)(1)) # needs sage.rings.real_mpfr 1.2660658777520083355982446252147175376076703113549622068081 - sage: bessel_I(0, ComplexField(200)(0.5+I)) - 0.80644357583493619472428518415019222845373366024179916785502 + 0.22686958987911161141397453401487525043310874687430711021434*I + sage: bessel_I(0, ComplexField(200)(0.5+I)) # needs sage.symbolic + 0.80644357583493619472428518415019222845373366024179916785502 + + 0.22686958987911161141397453401487525043310874687430711021434*I Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_I(1,x), (x,0,5), color='blue') + sage: plot(bessel_I(1, x), (x, 0, 5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_I(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_I(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -730,12 +755,12 @@ class Function_Bessel_I(BuiltinFunction): TESTS:: - sage: N(bessel_I(1,1),500) + sage: N(bessel_I(1,1),500) # needs sage.symbolic 0.565159103992485027207696027609863307328899621621092009480294489479255640964371134092664997766814410064677886055526302676857637684917179812041131208121 Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_I(5, 1.5) in RR + sage: bessel_I(5, 1.5) in RR # needs mpmath True REFERENCES: @@ -752,9 +777,9 @@ def __init__(self): EXAMPLES:: - sage: bessel_I(1,x) + sage: bessel_I(1, x) # needs sage.symbolic bessel_I(1, x) - sage: bessel_I(x, x)._sympy_() + sage: bessel_I(x, x)._sympy_() # needs sympy sage.symbolic besseli(x, x) """ BuiltinFunction.__init__(self, 'bessel_I', nargs=2, @@ -768,6 +793,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: n,y = var('n,y') sage: bessel_I(y, x) bessel_I(y, x) @@ -784,7 +810,6 @@ def _eval_(self, n, x): sage: bessel_I(n, 0) bessel_I(n, 0) """ - from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return ZZ.one() @@ -801,13 +826,12 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_I(0.0, 1.0) + sage: bessel_I(0.0, 1.0) # needs mpmath 1.26606587775201 - sage: bessel_I(1,3).n(digits=20) + sage: bessel_I(1,3).n(digits=20) # needs sage.symbolic 3.9533702174026093965 """ - import mpmath - return mpmath_utils.call(mpmath.besseli, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_besseli, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -816,6 +840,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(z) = bessel_I(10, x) sage: derivative(f, x) z |--> 1/2*bessel_I(11, x) + 1/2*bessel_I(9, x) @@ -836,7 +861,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_I(1, x)) + sage: latex(bessel_I(1, x)) # needs sage.symbolic I_{1}(x) """ return r"I_{%s}(%s)" % (latex(n), latex(z)) @@ -857,10 +882,12 @@ class Function_Bessel_K(BuiltinFunction): EXAMPLES:: + sage: bessel_K(1.0, 1.0) # needs mpmath + 0.601907230197235 + + sage: # needs sage.symbolic sage: bessel_K(1, x) bessel_K(1, x) - sage: bessel_K(1.0, 1.0) - 0.601907230197235 sage: n = var('n') sage: bessel_K(n, x) bessel_K(n, x) @@ -869,15 +896,14 @@ class Function_Bessel_K(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_K(pi, bessel_K(1, I)); a bessel_K(pi, bessel_K(1, I)) sage: N(a, digits=20) 3.8507583115005220156 + 0.068528298579883425456*I - sage: f = bessel_K(2, x) sage: f.diff(x) -1/2*bessel_K(3, x) - 1/2*bessel_K(1, x) - sage: bessel_K(1/2, x) sqrt(1/2)*sqrt(pi)*e^(-x)/sqrt(x) sage: bessel_K(1/2, -1) @@ -887,27 +913,28 @@ class Function_Bessel_K(BuiltinFunction): Examples of asymptotic behavior:: - sage: bessel_K(0, 0.0) + sage: bessel_K(0, 0.0) # needs mpmath +infinity - sage: limit(bessel_K(0, x), x=0) + sage: limit(bessel_K(0, x), x=0) # needs sage.symbolic +Infinity - sage: limit(bessel_K(0, x), x=oo) + sage: limit(bessel_K(0, x), x=oo) # needs sage.symbolic 0 High precision and complex valued inputs:: - sage: bessel_K(0, 1).n(128) + sage: bessel_K(0, 1).n(128) # needs sage.symbolic 0.42102443824070833333562737921260903614 - sage: bessel_K(0, RealField(200)(1)) + sage: bessel_K(0, RealField(200)(1)) # needs sage.rings.real_mpfr 0.42102443824070833333562737921260903613621974822666047229897 - sage: bessel_K(0, ComplexField(200)(0.5+I)) - 0.058365979093103864080375311643360048144715516692187818271179 - 0.67645499731334483535184142196073004335768129348518210260256*I + sage: bessel_K(0, ComplexField(200)(0.5+I)) # needs sage.rings.real_mpfr sage.symbolic + 0.058365979093103864080375311643360048144715516692187818271179 + - 0.67645499731334483535184142196073004335768129348518210260256*I Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_K(1,x), (x,0,5), color='blue') + sage: plot(bessel_K(1,x), (x,0,5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_K(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_K(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -921,13 +948,13 @@ class Function_Bessel_K(BuiltinFunction): The Bessel K function can be evaluated numerically at complex orders:: - sage: bessel_K(10 * I, 10).n() + sage: bessel_K(10 * I, 10).n() # needs sage.symbolic 9.82415743819925e-8 For a fixed imaginary order and increasing, real, second component the value of Bessel K is exponentially decaying:: - sage: for x in [10, 20, 50, 100, 200]: print(bessel_K(5*I, x).n()) + sage: for x in [10, 20, 50, 100, 200]: print(bessel_K(5*I, x).n()) # needs sage.symbolic 5.27812176514912e-6 3.11005908421801e-10 2.66182488515423e-23 - 8.59622057747552e-58*I @@ -936,7 +963,7 @@ class Function_Bessel_K(BuiltinFunction): Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_K(5, 1.5) in RR + sage: bessel_K(5, 1.5) in RR # needs mpmath True REFERENCES: @@ -955,7 +982,7 @@ def __init__(self): sage: sage.functions.bessel.Function_Bessel_K() bessel_K - sage: bessel_K(x, x)._sympy_() + sage: bessel_K(x, x)._sympy_() # needs sympy sage.symbolic besselk(x, x) """ BuiltinFunction.__init__(self, 'bessel_K', nargs=2, @@ -969,6 +996,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: bessel_K(1, 0) Infinity @@ -979,10 +1007,9 @@ def _eval_(self, n, x): TESTS:: - sage: bessel_K(0, 0) + sage: bessel_K(0, 0) # needs sage.symbolic +Infinity """ - from sage.rings.infinity import infinity, unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return infinity @@ -995,15 +1022,14 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_K(0.0, 1.0) + sage: bessel_K(0.0, 1.0) # needs mpmath 0.421024438240708 - sage: bessel_K(-1, 1).n(128) + sage: bessel_K(-1, 1).n(128) # needs sage.symbolic 0.60190723019723457473754000153561733926 - sage: bessel_K(0, RealField(128)(1)) + sage: bessel_K(0, RealField(128)(1)) # needs sage.rings.real_mpfr 0.42102443824070833333562737921260903614 """ - import mpmath - return mpmath_utils.call(mpmath.besselk, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_besselk, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -1011,6 +1037,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(x) = bessel_K(10, x) sage: derivative(f, x) x |--> -1/2*bessel_K(11, x) - 1/2*bessel_K(9, x) @@ -1031,7 +1058,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_K(1, x)) + sage: latex(bessel_K(1, x)) # needs sage.symbolic K_{1}(x) """ return r"K_{%s}(%s)" % (latex(n), latex(z)) @@ -1049,15 +1076,15 @@ def Bessel(*args, **kwds): A function factory that produces symbolic I, J, K, and Y Bessel functions. There are several ways to call this function: - - ``Bessel(order, type)`` - - ``Bessel(order)`` -- type defaults to 'J' - - ``Bessel(order, typ=T)`` - - ``Bessel(typ=T)`` -- order is unspecified, this is a 2-parameter - function - - ``Bessel()`` -- order is unspecified, type is 'J' + - ``Bessel(order, type)`` + - ``Bessel(order)`` -- type defaults to ``'J'`` + - ``Bessel(order, typ=T)`` + - ``Bessel(typ=T)`` -- order is unspecified, this is a 2-parameter + function + - ``Bessel()`` -- order is unspecified, type is ``'J'`` - where ``order`` can be any integer and T must be one of the strings 'I', - 'J', 'K', or 'Y'. + where ``order`` can be any integer and ``T`` must be one of the strings ``'I'``, + ``'J'``, ``'K'``, or ``'Y'``. See the EXAMPLES below. @@ -1067,53 +1094,58 @@ def Bessel(*args, **kwds): sage: Bessel() bessel_J + sage: Bessel(typ='K') + bessel_K + + sage: # needs sage.symbolic sage: Bessel(1)(x) bessel_J(1, x) sage: Bessel(1, 'Y')(x) bessel_Y(1, x) sage: Bessel(-2, 'Y')(x) bessel_Y(-2, x) - sage: Bessel(typ='K') - bessel_K sage: Bessel(0, typ='I')(x) bessel_I(0, x) Evaluation:: sage: f = Bessel(1) - sage: f(3.0) + sage: f(3.0) # needs mpmath 0.339058958525936 + + sage: # needs sage.symbolic sage: f(3) bessel_J(1, 3) sage: f(3).n(digits=50) 0.33905895852593645892551459720647889697308041819801 - sage: g = Bessel(typ='J') sage: g(1,3) bessel_J(1, 3) sage: g(2, 3+I).n() 0.634160370148554 + 0.0253384000032695*I - sage: abs(numerical_integral(1/pi*cos(3*sin(x)), 0.0, pi)[0] - Bessel(0, 'J')(3.0)) < 1e-15 + sage: abs(numerical_integral(1/pi*cos(3*sin(x)), 0.0, pi)[0] + ....: - Bessel(0, 'J')(3.0)) < 1e-15 True Symbolic calculus:: - sage: f(x) = Bessel(0, 'J')(x) - sage: derivative(f, x) + sage: f(x) = Bessel(0, 'J')(x) # needs sage.symbolic + sage: derivative(f, x) # needs sage.symbolic x |--> -1/2*bessel_J(1, x) + 1/2*bessel_J(-1, x) - sage: derivative(f, x, x) + sage: derivative(f, x, x) # needs sage.symbolic x |--> 1/4*bessel_J(2, x) - 1/2*bessel_J(0, x) + 1/4*bessel_J(-2, x) Verify that `J_0` satisfies Bessel's differential equation numerically using the ``test_relation()`` method:: - sage: y = bessel_J(0, x) - sage: diffeq = x^2*derivative(y,x,x) + x*derivative(y,x) + x^2*y == 0 - sage: diffeq.test_relation(proof=False) + sage: y = bessel_J(0, x) # needs sage.symbolic + sage: diffeq = x^2*derivative(y,x,x) + x*derivative(y,x) + x^2*y == 0 # needs sage.symbolic + sage: diffeq.test_relation(proof=False) # needs sage.symbolic True Conversion to other systems:: + sage: # needs sage.symbolic sage: x,y = var('x,y') sage: f = Bessel(typ='K')(x,y) sage: expected = f.derivative(y) @@ -1125,6 +1157,7 @@ def Bessel(*args, **kwds): satisfies `y(1) = 1` and `y'(1) = 1`, then verify the initial conditions and plot it:: + sage: # needs sage.symbolic sage: y = function('y')(x) sage: diffeq = x^2*diff(y,x,x) + x*diff(y,x) + x^2*y == 0 sage: f = desolve(diffeq, y, [1, 1, 1]); f @@ -1132,37 +1165,39 @@ def Bessel(*args, **kwds): 1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1)) - (bessel_J(1, 1) + bessel_J(0, 1))*bessel_Y(0, x)/(bessel_J(0, 1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1)) - sage: f.subs(x=1).n() # numerical verification + sage: f.subs(x=1).n() # numerical verification 1.00000000000000 sage: fp = f.diff(x) sage: fp.subs(x=1).n() 1.00000000000000 - sage: f.subs(x=1).simplify_full() # symbolic verification + sage: f.subs(x=1).simplify_full() # symbolic verification # needs sage.symbolic 1 - sage: fp = f.diff(x) - sage: fp.subs(x=1).simplify_full() + sage: fp = f.diff(x) # needs sage.symbolic + sage: fp.subs(x=1).simplify_full() # needs sage.symbolic 1 - sage: plot(f, (x,0,5)) + sage: plot(f, (x,0,5)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive Plotting:: - sage: f(x) = Bessel(0)(x); f + sage: f(x) = Bessel(0)(x); f # needs sage.symbolic x |--> bessel_J(0, x) - sage: plot(f, (x, 1, 10)) + sage: plot(f, (x, 1, 10)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: plot([ Bessel(i, 'J') for i in range(5) ], 2, 10) + sage: plot([Bessel(i, 'J') for i in range(5)], 2, 10) # needs sage.plot Graphics object consisting of 5 graphics primitives - sage: G = Graphics() - sage: G += sum([ plot(Bessel(i), 0, 4*pi, rgbcolor=hue(sin(pi*i/10))) for i in range(5) ]) - sage: show(G) + sage: G = Graphics() # needs sage.plot + sage: G += sum(plot(Bessel(i), 0, 4*pi, rgbcolor=hue(sin(pi*i/10))) # needs sage.plot sage.symbolic + ....: for i in range(5)) + sage: show(G) # needs sage.plot A recreation of Abramowitz and Stegun Figure 9.1:: + sage: # needs sage.plot sage.symbolic sage: G = plot(Bessel(0, 'J'), 0, 15, color='black') sage: G += plot(Bessel(0, 'Y'), 0, 15, color='black') sage: G += plot(Bessel(1, 'J'), 0, 15, color='black', linestyle='dotted') @@ -1220,11 +1255,11 @@ class Function_Struve_H(BuiltinFunction): EXAMPLES:: - sage: struve_H(-1/2,x) + sage: struve_H(-1/2, x) # needs sage.symbolic sqrt(2)*sqrt(1/(pi*x))*sin(x) - sage: struve_H(2,x) + sage: struve_H(2, x) # needs sage.symbolic struve_H(2, x) - sage: struve_H(1/2,pi).n() + sage: struve_H(1/2, pi).n() # needs sage.symbolic 0.900316316157106 REFERENCES: @@ -1239,10 +1274,11 @@ def __init__(self): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: maxima("struve_h(n,x);").sage() struve_H(n, x) - sage: struve_H(7/5,1)._maxima_() + sage: struve_H(7/5, 1)._maxima_() struve_h(7/5,1) sage: loads(dumps(struve_H(n,x))) struve_H(n, x) @@ -1258,19 +1294,20 @@ def _eval_(self, a, z): """ EXAMPLES:: - sage: struve_H(0,0) + sage: # needs sage.symbolic + sage: struve_H(0, 0) 0 - sage: struve_H(pi,0) + sage: struve_H(pi, 0) 0 - sage: struve_H(-1/2,x) + sage: struve_H(-1/2, x) sqrt(2)*sqrt(1/(pi*x))*sin(x) - sage: struve_H(1/2,-1) + sage: struve_H(1/2, -1) -sqrt(2)*sqrt(-1/pi)*(cos(1) - 1) - sage: struve_H(1/2,pi) + sage: struve_H(1/2, pi) 2*sqrt(2)/pi - sage: struve_H(2,x) + sage: struve_H(2, x) struve_H(2, x) - sage: struve_H(-3/2,x) + sage: struve_H(-3/2, x) -bessel_J(3/2, x) """ if z.is_zero() \ @@ -1278,10 +1315,8 @@ def _eval_(self, a, z): and a.real() >= -1: return ZZ.zero() if a == QQ((-1, 2)): - from sage.functions.trig import sin return sqrt(2 / (pi * z)) * sin(z) if a == QQ((1, 2)): - from sage.functions.trig import cos return sqrt(2 / (pi * z)) * (1 - cos(z)) if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): n = (a * (-2) - 1) / 2 @@ -1291,25 +1326,24 @@ def _evalf_(self, a, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: struve_H(1/2,pi).n() + sage: struve_H(1/2, pi).n() # needs sage.symbolic 0.900316316157106 - sage: struve_H(1/2,pi).n(200) + sage: struve_H(1/2, pi).n(200) # needs sage.symbolic 0.9003163161571060695551991910... """ - import mpmath - return mpmath_utils.call(mpmath.struveh, a, z, parent=parent) + return _mpmath_utils_call(_mpmath_struveh, a, z, parent=parent) def _derivative_(self, a, z, diff_param=None): """ EXAMPLES:: - sage: diff(struve_H(3/2,x),x) - -1/2*sqrt(2)*sqrt(1/(pi*x))*(cos(x) - 1) + 1/16*sqrt(2)*x^(3/2)/sqrt(pi) - 1/2*struve_H(5/2, x) + sage: diff(struve_H(3/2,x), x) # needs sage.symbolic + -1/2*sqrt(2)*sqrt(1/(pi*x))*(cos(x) - 1) + 1/16*sqrt(2)*x^(3/2)/sqrt(pi) + - 1/2*struve_H(5/2, x) """ if diff_param == 0: raise ValueError("cannot differentiate struve_H in the first parameter") - from .gamma import gamma from .other import sqrt return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_H(a + 1, z) + struve_H(a - 1, z)) / 2 @@ -1317,7 +1351,7 @@ def _print_latex_(self, a, z): """ EXAMPLES:: - sage: latex(struve_H(2,x)) + sage: latex(struve_H(2,x)) # needs sage.symbolic H_{{2}}({x}) """ return r"H_{{%s}}({%s})" % (a, z) @@ -1336,11 +1370,11 @@ class Function_Struve_L(BuiltinFunction): EXAMPLES:: - sage: struve_L(2,x) + sage: struve_L(2, x) # needs sage.symbolic struve_L(2, x) - sage: struve_L(1/2,pi).n() + sage: struve_L(1/2, pi).n() # needs sage.symbolic 4.76805417696286 - sage: diff(struve_L(1,x),x) + sage: diff(struve_L(1,x), x) # needs sage.symbolic 1/3*x/pi - 1/2*struve_L(2, x) + 1/2*struve_L(0, x) REFERENCES: @@ -1355,12 +1389,13 @@ def __init__(self): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: maxima("struve_l(n,x);").sage() struve_L(n, x) - sage: struve_L(7/5,1)._maxima_() + sage: struve_L(7/5, 1)._maxima_() struve_l(7/5,1) - sage: loads(dumps(struve_L(n,x))) + sage: loads(dumps(struve_L(n, x))) struve_L(n, x) """ BuiltinFunction.__init__(self, 'struve_L', nargs=2, @@ -1374,19 +1409,20 @@ def _eval_(self, a, z): """ EXAMPLES:: - sage: struve_L(-2,0) + sage: # needs sage.symbolic + sage: struve_L(-2, 0) struve_L(-2, 0) - sage: struve_L(-1,0) + sage: struve_L(-1, 0) 0 - sage: struve_L(pi,0) + sage: struve_L(pi, 0) 0 - sage: struve_L(-1/2,x) + sage: struve_L(-1/2, x) sqrt(2)*sqrt(1/(pi*x))*sinh(x) - sage: struve_L(1/2,1) + sage: struve_L(1/2, 1) sqrt(2)*(cosh(1) - 1)/sqrt(pi) - sage: struve_L(2,x) + sage: struve_L(2, x) struve_L(2, x) - sage: struve_L(-3/2,x) + sage: struve_L(-3/2, x) -bessel_I(3/2, x) """ if z.is_zero() \ @@ -1394,10 +1430,8 @@ def _eval_(self, a, z): and a.real() >= -1: return ZZ.zero() if a == -Integer(1) / 2: - from sage.functions.hyperbolic import sinh return sqrt(2 / (pi * z)) * sinh(z) if a == Integer(1) / 2: - from sage.functions.hyperbolic import cosh return sqrt(2 / (pi * z)) * (cosh(z) - 1) if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): n = (a * (-2) - 1) / 2 @@ -1407,25 +1441,23 @@ def _evalf_(self, a, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: struve_L(1/2,pi).n() + sage: struve_L(1/2, pi).n() # needs sage.symbolic 4.76805417696286 - sage: struve_L(1/2,pi).n(200) + sage: struve_L(1/2, pi).n(200) # needs sage.symbolic 4.768054176962864289162484345... """ - import mpmath - return mpmath_utils.call(mpmath.struvel, a, z, parent=parent) + return _mpmath_utils_call(_mpmath_struvel, a, z, parent=parent) def _derivative_(self, a, z, diff_param=None): """ EXAMPLES:: - sage: diff(struve_L(1,x),x) + sage: diff(struve_L(1,x), x) # needs sage.symbolic 1/3*x/pi - 1/2*struve_L(2, x) + 1/2*struve_L(0, x) """ if diff_param == 0: raise ValueError("cannot differentiate struve_L in the first parameter") - from .gamma import gamma from .other import sqrt return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_L(a + 1, z) + struve_L(a - 1, z)) / 2 @@ -1433,7 +1465,7 @@ def _print_latex_(self, a, z): """ EXAMPLES:: - sage: latex(struve_L(2,x)) + sage: latex(struve_L(2,x)) # needs sage.symbolic L_{{2}}({x}) """ return r"L_{{%s}}({%s})" % (a, z) @@ -1454,15 +1486,15 @@ class Function_Hankel1(BuiltinFunction): EXAMPLES:: - sage: hankel1(3, x) + sage: hankel1(3, x) # needs sage.symbolic hankel1(3, x) - sage: hankel1(3, 4.) + sage: hankel1(3, 4.) # needs mpmath 0.430171473875622 - 0.182022115953485*I - sage: latex(hankel1(3, x)) + sage: latex(hankel1(3, x)) # needs sage.symbolic H_{3}^{(1)}\left(x\right) - sage: hankel1(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 + sage: hankel1(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 # needs sage.symbolic 0.309062682819597 - 0.512591541605233*I - sage: hankel1(3, 3.) + sage: hankel1(3, 3.) # needs mpmath 0.309062722255252 - 0.538541616105032*I REFERENCES: @@ -1473,7 +1505,7 @@ def __init__(self): r""" TESTS:: - sage: hankel1(3, x)._sympy_() + sage: hankel1(3, x)._sympy_() # needs sympy sage.symbolic hankel1(3, x) """ BuiltinFunction.__init__(self, 'hankel1', nargs=2, @@ -1487,13 +1519,12 @@ def _evalf_(self, nu, z, parent, algorithm=None): r""" TESTS:: - sage: hankel1(3, 3).n(100) + sage: hankel1(3, 3).n(100) # needs sage.symbolic 0.30906272225525164361826019495 - 0.53854161610503161800470390534*I - sage: hankel1(I, I).n() + sage: hankel1(I, I).n() # needs sage.symbolic -0.886357449263715*I """ - from mpmath import hankel1 - return mpmath_utils.call(hankel1, nu, z, parent=parent) + return _mpmath_utils_call(_mpmath_hankel1, nu, z, parent=parent) def _latex_(self): r""" @@ -1508,7 +1539,7 @@ def _print_latex_(self, nu, z): r""" TESTS:: - sage: latex(hankel1(3, x)) + sage: latex(hankel1(3, x)) # needs sage.symbolic H_{3}^{(1)}\left(x\right) """ return r"H_{{{}}}^{{(1)}}\left({}\right)".format(latex(nu), latex(z)) @@ -1517,8 +1548,8 @@ def _derivative_(self, nu, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: hankel1(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: hankel1(x, y).diff(y) # needs sage.symbolic x*hankel1(x, y)/y - hankel1(x + 1, y) """ if diff_param == 1: @@ -1542,15 +1573,15 @@ class Function_Hankel2(BuiltinFunction): EXAMPLES:: - sage: hankel2(3, x) + sage: hankel2(3, x) # needs sage.symbolic hankel2(3, x) - sage: hankel2(3, 4.) + sage: hankel2(3, 4.) # needs mpmath 0.430171473875622 + 0.182022115953485*I - sage: latex(hankel2(3, x)) + sage: latex(hankel2(3, x)) # needs sage.symbolic H_{3}^{(2)}\left(x\right) - sage: hankel2(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 + sage: hankel2(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 # needs sage.symbolic 0.309062682819597 + 0.512591541605234*I - sage: hankel2(3, 3.) + sage: hankel2(3, 3.) # needs mpmath 0.309062722255252 + 0.538541616105032*I REFERENCES: @@ -1561,7 +1592,7 @@ def __init__(self): r""" TESTS:: - sage: hankel2(3, x)._sympy_() + sage: hankel2(3, x)._sympy_() # needs sympy sage.symbolic hankel2(3, x) """ BuiltinFunction.__init__(self, 'hankel2', nargs=2, @@ -1575,13 +1606,12 @@ def _evalf_(self, nu, z, parent, algorithm=None): r""" TESTS:: - sage: hankel2(3, 3).n(100) + sage: hankel2(3, 3).n(100) # needs sage.symbolic 0.30906272225525164361826019495 + 0.53854161610503161800470390534*I - sage: hankel2(I, I).n() + sage: hankel2(I, I).n() # needs sage.symbolic 0.790274862674015 + 0.444006335520019*I """ - from mpmath import hankel2 - return mpmath_utils.call(hankel2, nu, z, parent=parent) + return _mpmath_utils_call(_mpmath_hankel2, nu, z, parent=parent) def _latex_(self): r""" @@ -1596,7 +1626,7 @@ def _print_latex_(self, nu, z): r""" TESTS:: - sage: latex(hankel2(3, x)) + sage: latex(hankel2(3, x)) # needs sage.symbolic H_{3}^{(2)}\left(x\right) """ return r"H_{{{}}}^{{(2)}}\left({}\right)".format(latex(nu), latex(z)) @@ -1605,8 +1635,8 @@ def _derivative_(self, nu, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: hankel2(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: hankel2(x, y).diff(y) # needs sage.symbolic -1/2*hankel2(x + 1, y) + 1/2*hankel2(x - 1, y) """ if diff_param == 1: @@ -1630,16 +1660,18 @@ class SphericalBesselJ(BuiltinFunction): EXAMPLES:: + sage: spherical_bessel_J(3, 3.) # needs mpmath + 0.152051662030533 + sage: spherical_bessel_J(2.,3.) # rel tol 1e-10 # needs mpmath + 0.2986374970757335 + + sage: # needs sage.symbolic sage: spherical_bessel_J(3, x) spherical_bessel_J(3, x) sage: spherical_bessel_J(3 + 0.2 * I, 3) 0.150770999183897 - 0.0260662466510632*I sage: spherical_bessel_J(3, x).series(x == 2, 10).subs(x=3).n() 0.152051648665037 - sage: spherical_bessel_J(3, 3.) - 0.152051662030533 - sage: spherical_bessel_J(2.,3.) # rel tol 1e-10 - 0.2986374970757335 sage: spherical_bessel_J(4, x).simplify() -((45/x^2 - 105/x^4 - 1)*sin(x) + 5*(21/x^2 - 2)*cos(x)/x)/x sage: integrate(spherical_bessel_J(1,x)^2,(x,0,oo)) @@ -1659,7 +1691,7 @@ def __init__(self): r""" TESTS:: - sage: spherical_bessel_J(3, x)._sympy_() + sage: spherical_bessel_J(3, x)._sympy_() # needs sympy sage.symbolic jn(3, x) """ conversions = dict(mathematica='SphericalBesselJ', @@ -1672,12 +1704,12 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_bessel_J(3, 3).n(100) + sage: spherical_bessel_J(3, 3).n(100) # needs sage.symbolic 0.15205166203053329097480571600 - sage: spherical_bessel_J(I, I).n() + sage: spherical_bessel_J(I, I).n() # needs sage.symbolic 0.215520585196889 - 0.282308805801851*I """ - return mpmath_utils.call(spherical_bessel_f, 'besselj', n, z, + return _mpmath_utils_call(spherical_bessel_f, 'besselj', n, z, parent=parent) def _latex_(self): @@ -1693,7 +1725,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_bessel_J(4, x)) + sage: latex(spherical_bessel_J(4, x)) # needs sage.symbolic j_{4}\left(x\right) """ return r"j_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -1702,8 +1734,8 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: spherical_bessel_J(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: spherical_bessel_J(x, y).diff(y) # needs sage.symbolic -(x + 1)*spherical_bessel_J(x, y)/y + spherical_bessel_J(x - 1, y) """ if SR(n).is_numeric() and not SR(n).is_integer(): @@ -1730,6 +1762,7 @@ class SphericalBesselY(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: spherical_bessel_Y(3, x) spherical_bessel_Y(3, x) sage: spherical_bessel_Y(3 + 0.2 * I, 3) @@ -1757,7 +1790,7 @@ def __init__(self): r""" TESTS:: - sage: spherical_bessel_Y(3, x)._sympy_() + sage: spherical_bessel_Y(3, x)._sympy_() # needs sympy sage.symbolic yn(3, x) """ conversions = dict(mathematica='SphericalBesselY', @@ -1770,12 +1803,12 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_bessel_Y(3, 3).n(100) + sage: spherical_bessel_Y(3, 3).n(100) # needs sage.symbolic -0.50802305570981460285684870920 - sage: spherical_bessel_Y(I, I).n() + sage: spherical_bessel_Y(I, I).n() # needs sage.symbolic -0.174225389805399 + 1.36247234140312*I """ - return mpmath_utils.call(spherical_bessel_f, 'bessely', n, z, + return _mpmath_utils_call(spherical_bessel_f, 'bessely', n, z, parent=parent) def _latex_(self): @@ -1791,7 +1824,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_bessel_Y(4, x)) + sage: latex(spherical_bessel_Y(4, x)) # needs sage.symbolic y_{4}\left(x\right) """ return r"y_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -1800,8 +1833,8 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: spherical_bessel_Y(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: spherical_bessel_Y(x, y).diff(y) # needs sage.symbolic -1/2*spherical_bessel_Y(x, y)/y -... 1/2*spherical_bessel_Y(x + 1, y) + 1/2*spherical_bessel_Y(x - 1, y) """ @@ -1830,6 +1863,7 @@ class SphericalHankel1(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: spherical_hankel1(3, x) spherical_hankel1(3, x) sage: spherical_hankel1(3 + 0.2 * I, 3) @@ -1867,12 +1901,12 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_hankel1(3, 3).n(100) + sage: spherical_hankel1(3, 3).n(100) # needs sage.symbolic 0.15205166203053329097480571600 - 0.50802305570981460285684870920*I - sage: spherical_hankel1(I, I).n() + sage: spherical_hankel1(I, I).n() # needs sage.symbolic -1.14695175620623 - 0.456534195607250*I """ - return mpmath_utils.call(spherical_bessel_f, 'hankel1', n, z, + return _mpmath_utils_call(spherical_bessel_f, 'hankel1', n, z, parent=parent) def _latex_(self): @@ -1888,7 +1922,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_hankel1(4, x)) + sage: latex(spherical_hankel1(4, x)) # needs sage.symbolic h_{4}^{(1)}\left(x\right) """ return r"h_{{{}}}^{{(1)}}\left({}\right)".format(latex(n), latex(z)) @@ -1897,8 +1931,8 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: spherical_hankel1(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: spherical_hankel1(x, y).diff(y) # needs sage.symbolic -1/2*spherical_hankel1(x, y)/y -... 1/2*spherical_hankel1(x + 1, y) + 1/2*spherical_hankel1(x - 1, y) """ @@ -1927,6 +1961,7 @@ class SphericalHankel2(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: spherical_hankel2(3, x) spherical_hankel2(3, x) sage: spherical_hankel2(3 + 0.2 * I, 3) @@ -1967,13 +2002,13 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_hankel2(3, 3).n(100) + sage: spherical_hankel2(3, 3).n(100) # needs sage.symbolic 0.15205166203053329097480571600 + 0.50802305570981460285684870920*I - sage: spherical_hankel2(I, I).n() + sage: spherical_hankel2(I, I).n() # needs sage.symbolic 1.57799292660001 - 0.108083415996452*I """ - return mpmath_utils.call(spherical_bessel_f, 'hankel2', n, z, - parent=parent) + return _mpmath_utils_call(spherical_bessel_f, 'hankel2', n, z, + parent=parent) def _latex_(self): r""" @@ -1988,7 +2023,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_hankel2(4, x)) + sage: latex(spherical_hankel2(4, x)) # needs sage.symbolic h_{4}^{(2)}\left(x\right) """ return r"h_{{{}}}^{{(2)}}\left({}\right)".format(latex(n), latex(z)) @@ -1997,6 +2032,7 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: + sage: # needs sage.symbolic sage: y = var('y') sage: spherical_hankel2(x, y).diff(y) -1/2*spherical_hankel2(x, y)/y -... @@ -2033,9 +2069,9 @@ def spherical_bessel_f(F, n, z): EXAMPLES:: sage: from sage.functions.bessel import spherical_bessel_f - sage: spherical_bessel_f('besselj', 3, 4) + sage: spherical_bessel_f('besselj', 3, 4) # needs mpmath mpf('0.22924385795503024') - sage: spherical_bessel_f('hankel1', 3, 4) + sage: spherical_bessel_f('hankel1', 3, 4) # needs mpmath mpc(real='0.22924385795503024', imag='-0.21864196590306359') TESTS: @@ -2043,13 +2079,12 @@ def spherical_bessel_f(F, n, z): Check that :trac:`28474` is fixed:: sage: from sage.functions.bessel import spherical_bessel_f - sage: spherical_bessel_f('besselj', 3, -4) + sage: spherical_bessel_f('besselj', 3, -4) # needs mpmath mpc(real='-0.22924385795503024', imag='0.0') - sage: spherical_bessel_f('bessely', 3, -4) + sage: spherical_bessel_f('bessely', 3, -4) # needs mpmath mpc(real='-0.21864196590306359', imag='0.0') """ - from mpmath import mp - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: n = ctx.convert(n) diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py index c5221683442..1e4b74d5afe 100644 --- a/src/sage/functions/error.py +++ b/src/sage/functions/error.py @@ -40,15 +40,26 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.structure.all import parent as s_parent -from sage.symbolic.function import BuiltinFunction -from sage.libs.mpmath import utils as mpmath_utils -from sage.symbolic.expression import Expression -from sage.functions.all import exp from sage.misc.functional import sqrt -from sage.symbolic.constants import I, pi -from sage.rings.rational import Rational +from sage.misc.lazy_import import lazy_import +from sage.misc.persist import register_unpickle_override from sage.rings.infinity import unsigned_infinity +from sage.rings.rational import Rational +from sage.structure.element import Expression, parent as s_parent +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.functions.log', ['exp']) +lazy_import('sage.functions.trig', ['sin', 'cos']) + +lazy_import('sage.symbolic.constants', ['I', 'pi']) + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('sage.libs.mpmath.all', 'erf', as_='_mpmath_erf') +lazy_import('sage.libs.mpmath.all', 'erfc', as_='_mpmath_erfc') +lazy_import('sage.libs.mpmath.all', 'erfi', as_='_mpmath_erfi') +lazy_import('sage.libs.mpmath.all', 'erfinv', as_='_mpmath_erfinv') +lazy_import('sage.libs.mpmath.all', 'fresnelc', as_='_mpmath_fresnelc') +lazy_import('sage.libs.mpmath.all', 'fresnels', as_='_mpmath_fresnels') class Function_erf(BuiltinFunction): @@ -68,21 +79,21 @@ class Function_erf(BuiltinFunction): We can evaluate numerically:: - sage: erf(2) + sage: erf(2) # needs sage.symbolic erf(2) - sage: erf(2).n() + sage: erf(2).n() # needs sage.symbolic 0.995322265018953 - sage: erf(2).n(100) + sage: erf(2).n(100) # needs sage.symbolic 0.99532226501895273416206925637 - sage: erf(ComplexField(100)(2+3j)) + sage: erf(ComplexField(100)(2+3j)) # needs sage.rings.real_mpfr -20.829461427614568389103088452 + 8.6873182714701631444280787545*I Basic symbolic properties are handled by Sage and Maxima:: - sage: x = var("x") - sage: diff(erf(x),x) + sage: x = var("x") # needs sage.symbolic + sage: diff(erf(x),x) # needs sage.symbolic 2*e^(-x^2)/sqrt(pi) - sage: integrate(erf(x),x) + sage: integrate(erf(x),x) # needs sage.symbolic x*erf(x) + e^(-x^2)/sqrt(pi) ALGORITHM: @@ -99,78 +110,78 @@ class Function_erf(BuiltinFunction): Check limits:: - sage: limit(erf(x),x=0) + sage: limit(erf(x), x=0) # needs sage.symbolic 0 - sage: limit(erf(x),x=infinity) + sage: limit(erf(x), x=infinity) # needs sage.symbolic 1 Check that it's odd:: - sage: erf(1.0) + sage: erf(1.0) # needs mpmath 0.842700792949715 - sage: erf(-1.0) + sage: erf(-1.0) # needs mpmath -0.842700792949715 Check against other implementations and against the definition:: - sage: erf(3).n() + sage: erf(3).n() # needs sage.symbolic 0.999977909503001 - sage: maxima.erf(3).n() + sage: maxima.erf(3).n() # needs sage.symbolic 0.999977909503001 - sage: (1-pari(3).erfc()) + sage: 1 - pari(3).erfc() # needs sage.libs.pari 0.999977909503001 - sage: RR(3).erf() + sage: RR(3).erf() # needs sage.rings.real_mpfr 0.999977909503001 - sage: (integrate(exp(-x**2),(x,0,3))*2/sqrt(pi)).n() + sage: (integrate(exp(-x**2), (x,0,3))*2/sqrt(pi)).n() # needs sage.symbolic 0.999977909503001 :trac:`9044`:: - sage: N(erf(sqrt(2)),200) + sage: N(erf(sqrt(2)),200) # needs sage.symbolic 0.95449973610364158559943472566693312505644755259664313203267 :trac:`11626`:: - sage: n(erf(2),100) + sage: n(erf(2),100) # needs sage.symbolic 0.99532226501895273416206925637 - sage: erf(2).n(100) + sage: erf(2).n(100) # needs sage.symbolic 0.99532226501895273416206925637 Test (indirectly) :trac:`11885`:: sage: erf(float(0.5)) 0.5204998778130465 - sage: erf(complex(0.5)) + sage: erf(complex(0.5)) # needs sage.rings.complex_double (0.5204998778130465+0j) Ensure conversion from maxima elements works:: - sage: merf = maxima(erf(x)).sage().operator() - sage: merf.parent() == erf.parent() + sage: merf = maxima(erf(x)).sage().operator() # needs sage.symbolic + sage: merf.parent() == erf.parent() # needs sage.symbolic True Make sure we can dump and load it:: - sage: loads(dumps(erf(2))) + sage: loads(dumps(erf(2))) # needs sage.symbolic erf(2) Special-case 0 for immediate evaluation:: - sage: erf(0) + sage: erf(0) # needs mpmath 0 - sage: solve(erf(x)==0,x) + sage: solve(erf(x)==0, x) # needs sage.symbolic [x == 0] Make sure that we can hold:: - sage: erf(0,hold=True) + sage: erf(0, hold=True) # needs sage.symbolic erf(0) - sage: simplify(erf(0,hold=True)) + sage: simplify(erf(0, hold=True)) # needs sage.symbolic 0 Check that high-precision ComplexField inputs work:: - sage: CC(erf(ComplexField(1000)(2+3j))) + sage: CC(erf(ComplexField(1000)(2+3j))) # needs sage.rings.real_mpfr -20.8294614276146 + 8.68731827147016*I """ @@ -180,9 +191,9 @@ def __init__(self): EXAMPLES:: - sage: maxima(erf(2)) + sage: maxima(erf(2)) # needs sage.symbolic erf(2) - sage: erf(2)._sympy_() + sage: erf(2)._sympy_() # needs sympy sage.symbolic erf(2) """ BuiltinFunction.__init__(self, "erf", latex_name=r"\operatorname{erf}", @@ -197,6 +208,7 @@ def _eval_(self, x): Input is not an expression but is exact:: + sage: # needs sage.symbolic sage: erf(0) 0 sage: erf(1) @@ -210,17 +222,17 @@ def _eval_(self, x): Input is not an expression and is not exact:: - sage: erf(0.0) + sage: erf(0.0) # needs mpmath 0.000000000000000 Input is an expression but not a trivial zero:: - sage: erf(x) + sage: erf(x) # needs sage.symbolic erf(x) Input is an expression which is trivially zero:: - sage: erf(SR(0)) + sage: erf(SR(0)) # needs sage.symbolic 0 """ if isinstance(x, Expression): @@ -240,39 +252,38 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erf(2).n() + sage: erf(2).n() # needs sage.symbolic 0.995322265018953 - sage: erf(2).n(200) + sage: erf(2).n(200) # needs sage.symbolic 0.99532226501895273416206925636725292861089179704006007673835 - sage: erf(pi - 1/2*I).n(100) + sage: erf(pi - 1/2*I).n(100) # needs sage.symbolic 1.0000111669099367825726058952 + 1.6332655417638522934072124547e-6*I TESTS: Check that PARI/GP through the GP interface gives the same answer:: - sage: gp.set_real_precision(59) # random + sage: gp.set_real_precision(59) # random # needs sage.libs.pari 38 - sage: print(gp.eval("1 - erfc(1)")); print(erf(1).n(200)) + sage: print(gp.eval("1 - erfc(1)")); print(erf(1).n(200)) # needs sage.libs.pari 0.84270079294971486934122063508260925929606699796630290845994 0.84270079294971486934122063508260925929606699796630290845994 Check that for an imaginary input, the output is also imaginary, see :trac:`13193`:: - sage: erf(3.0*I) + sage: erf(3.0*I) # needs sage.symbolic 1629.99462260157*I - sage: erf(33.0*I) + sage: erf(33.0*I) # needs sage.symbolic 1.51286977510409e471*I Check that real ball evaluation is fixed :trac:`28061`:: - sage: RealBallField(128)(erf(5)) # abs tol 1e-38 + sage: RealBallField(128)(erf(5)) # abs tol 1e-38 # needs sage.symbolic [0.99999999999846254020557196514981165651 +/- 7.33e-39] """ R = parent or s_parent(x) - import mpmath - y = mpmath_utils.call(mpmath.erf, x, parent=R) + y = _mpmath_utils_call(_mpmath_erf, x, parent=R) return y def _derivative_(self, x, diff_param=None): @@ -281,18 +292,18 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erf(x).diff(x) + sage: erf(x).diff(x) # needs sage.symbolic 2*e^(-x^2)/sqrt(pi) TESTS: Check if :trac:`8568` is fixed:: - sage: var('c,x') + sage: var('c,x') # needs sage.symbolic (c, x) - sage: derivative(erf(c*x),x) + sage: derivative(erf(c*x),x) # needs sage.symbolic 2*c*e^(-c^2*x^2)/sqrt(pi) - sage: erf(c*x).diff(x)._maxima_init_() + sage: erf(c*x).diff(x)._maxima_init_() # needs sage.symbolic '((%pi)^(-1/2))*(_SAGE_VAR_c)*(exp(((_SAGE_VAR_c)^(2))*((_SAGE_VAR_x)^(2))*(-1)))*(2)' """ return 2*exp(-x**2)/sqrt(pi) @@ -317,9 +328,9 @@ def __init__(self): EXAMPLES:: - sage: maxima(erfi(2)) + sage: maxima(erfi(2)) # needs sage.symbolic erfi(2) - sage: erfi(2)._sympy_() + sage: erfi(2)._sympy_() # needs sympy sage.symbolic erfi(2) """ BuiltinFunction.__init__(self, "erfi", @@ -332,6 +343,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: erfi(0) 0 sage: erfi(SR(0)) @@ -353,16 +365,15 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erfi(2.) + sage: erfi(2.) # needs mpmath 18.5648024145756 - sage: erfi(2).n(100) + sage: erfi(2).n(100) # needs sage.symbolic 18.564802414575552598704291913 - sage: erfi(-2*I).n(100) + sage: erfi(-2*I).n(100) # needs sage.symbolic -0.99532226501895273416206925637*I """ R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erfi, x, parent=R) + return _mpmath_utils_call(_mpmath_erfi, x, parent=R) def _derivative_(self, x, diff_param=None): """ @@ -370,7 +381,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erfi(x).diff(x) + sage: erfi(x).diff(x) # needs sage.symbolic 2*e^(x^2)/sqrt(pi) """ @@ -392,23 +403,23 @@ class Function_erfc(BuiltinFunction): EXAMPLES:: - sage: erfc(6) + sage: erfc(6) # needs sage.symbolic erfc(6) - sage: erfc(6).n() + sage: erfc(6).n() # needs sage.symbolic 2.15197367124989e-17 - sage: erfc(RealField(100)(1/2)) + sage: erfc(RealField(100)(1/2)) # needs sage.rings.real_mpfr 0.47950012218695346231725334611 - sage: 1 - erfc(0.5) + sage: 1 - erfc(0.5) # needs mpmath 0.520499877813047 - sage: erf(0.5) + sage: erf(0.5) # needs mpmath 0.520499877813047 TESTS: Check that :trac:`25991` is fixed:: - sage: erfc(x)._fricas_() # optional - fricas + sage: erfc(x)._fricas_() # optional - fricas, needs sage.symbolic - erf(x) + 1 """ @@ -416,9 +427,9 @@ def __init__(self): r""" EXAMPLES:: - sage: maxima(erfc(2)) + sage: maxima(erfc(2)) # needs sage.symbolic erfc(2) - sage: erfc(2)._sympy_() + sage: erfc(2)._sympy_() # needs sympy sage.symbolic erfc(2) """ BuiltinFunction.__init__(self, "erfc", @@ -432,6 +443,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: erfc(0) 1 sage: erfc(SR(0)) @@ -458,16 +470,15 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erfc(4).n() + sage: erfc(4).n() # needs sage.symbolic 1.54172579002800e-8 - sage: erfc(4).n(100) + sage: erfc(4).n(100) # needs sage.symbolic 1.5417257900280018852159673487e-8 - sage: erfc(4*I).n(100) + sage: erfc(4*I).n(100) # needs sage.symbolic 1.0000000000000000000000000000 - 1.2969597307176392315279409506e6*I """ R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erfc, x, parent=R) + return _mpmath_utils_call(_mpmath_erfc, x, parent=R) def _derivative_(self, x, diff_param=None): """ @@ -475,7 +486,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erfc(x).diff(x) + sage: erfc(x).diff(x) # needs sage.symbolic -2*e^(-x^2)/sqrt(pi) """ return -2*exp(-x**2)/sqrt(pi) @@ -500,15 +511,16 @@ def __init__(self): EXAMPLES:: - sage: erfinv(2)._sympy_() + sage: erfinv(2)._sympy_() # needs sympy sage.symbolic erfinv(2) - sage: maxima(erfinv(2)) + sage: maxima(erfinv(2)) # needs sage.symbolic inverse_erf(2) TESTS: Check that :trac:`11349` is fixed:: + sage: # needs sage.symbolic sage: _ = var('z,t') sage: PDF = exp(-x^2 /2)/sqrt(2*pi) sage: integralExpr = integrate(PDF,x,z,oo).subs(z==log(t)) @@ -527,11 +539,11 @@ def _eval_(self, x): """ EXAMPLES:: - sage: erfinv(0) + sage: erfinv(0) # needs mpmath 0 - sage: erfinv(SR(0)) + sage: erfinv(SR(0)) # needs sage.symbolic 0 - sage: erfinv(1) + sage: erfinv(1) # needs sage.symbolic Infinity """ if isinstance(x, Expression): @@ -548,14 +560,13 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erfinv(0.2) + sage: erfinv(0.2) # needs mpmath 0.179143454621292 - sage: erfinv(1/5).n(100) + sage: erfinv(1/5).n(100) # needs sage.symbolic 0.17914345462129167649274901663 """ R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erfinv, x, parent=R) + return _mpmath_utils_call(_mpmath_erfinv, x, parent=R) def _derivative_(self, x, diff_param=None): """ @@ -563,7 +574,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erfinv(x).diff(x) + sage: erfinv(x).diff(x) # needs sage.symbolic 1/2*sqrt(pi)*e^(erfinv(x)^2) """ return sqrt(pi)*exp(erfinv(x)**2)/2 @@ -572,7 +583,6 @@ def _derivative_(self, x, diff_param=None): erfinv = Function_erfinv() -from sage.misc.persist import register_unpickle_override register_unpickle_override('sage.functions.other', 'Function_erf', Function_erf) @@ -599,6 +609,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: fresnel_sin(0) 0 sage: fresnel_sin(x).subs(x==0) @@ -606,7 +617,7 @@ def __init__(self): sage: x = var('x') sage: fresnel_sin(1).n(100) 0.43825914739035476607675669662 - sage: fresnel_sin(x)._sympy_() + sage: fresnel_sin(x)._sympy_() # needs sympy fresnels(x) """ BuiltinFunction.__init__(self, "fresnel_sin", nargs=1, @@ -621,15 +632,15 @@ def _eval_(self, x): r""" EXAMPLES:: - sage: fresnel_sin(pi) + sage: fresnel_sin(pi) # needs sage.symbolic fresnel_sin(pi) - sage: fresnel_sin(oo) + sage: fresnel_sin(oo) # needs mpmath 1/2 - sage: fresnel_sin(-oo) + sage: fresnel_sin(-oo) # needs mpmath -1/2 - sage: fresnel_sin(I*oo) + sage: fresnel_sin(I*oo) # needs sage.symbolic -1/2*I - sage: fresnel_sin(-I*oo) + sage: fresnel_sin(-I*oo) # needs sage.symbolic 1/2*I """ if isinstance(x, Expression): @@ -653,26 +664,23 @@ def _evalf_(self, x, parent=None, algorithm=None): r""" EXAMPLES:: - sage: fresnel_sin(pi) + sage: fresnel_sin(pi) # needs sage.symbolic fresnel_sin(pi) - sage: fresnel_sin(pi).n(100) + sage: fresnel_sin(pi).n(100) # needs sage.symbolic 0.59824907809026766482843860921 - sage: fresnel_sin(1.0+2*I) + sage: fresnel_sin(1.0+2*I) # needs sage.symbolic 36.7254648839914 + 15.5877511044046*I """ - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.fresnels, x, parent=parent) + return _mpmath_utils_call(_mpmath_fresnels, x, parent=parent) def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: x = var('x') - sage: fresnel_sin(x).diff(x) + sage: x = var('x') # needs sage.symbolic + sage: fresnel_sin(x).diff(x) # needs sage.symbolic sin(1/2*pi*x^2) """ - from sage.functions.trig import sin return sin(pi*x**2/2) @@ -699,6 +707,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: fresnel_cos(0) 0 sage: fresnel_cos(x).subs(x==0) @@ -706,7 +715,7 @@ def __init__(self): sage: x = var('x') sage: fresnel_cos(1).n(100) 0.77989340037682282947420641365 - sage: fresnel_cos(x)._sympy_() + sage: fresnel_cos(x)._sympy_() # needs sympy fresnelc(x) """ BuiltinFunction.__init__(self, "fresnel_cos", nargs=1, @@ -721,15 +730,15 @@ def _eval_(self, x): r""" EXAMPLES:: - sage: fresnel_cos(pi) + sage: fresnel_cos(pi) # needs sage.symbolic fresnel_cos(pi) - sage: fresnel_cos(oo) + sage: fresnel_cos(oo) # needs mpmath 1/2 - sage: fresnel_cos(-oo) + sage: fresnel_cos(-oo) # needs mpmath -1/2 - sage: fresnel_cos(I*oo) + sage: fresnel_cos(I*oo) # needs sage.symbolic 1/2*I - sage: fresnel_cos(-I*oo) + sage: fresnel_cos(-I*oo) # needs sage.symbolic -1/2*I """ if isinstance(x, Expression): @@ -753,26 +762,23 @@ def _evalf_(self, x, parent=None, algorithm=None): r""" EXAMPLES:: - sage: fresnel_cos(pi) + sage: fresnel_cos(pi) # needs sage.symbolic fresnel_cos(pi) - sage: fresnel_cos(pi).n(100) + sage: fresnel_cos(pi).n(100) # needs sage.symbolic 0.52369854372622864215767570284 - sage: fresnel_cos(1.0+2*I) + sage: fresnel_cos(1.0+2*I) # needs sage.symbolic 16.0878713741255 - 36.2256879928817*I """ - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.fresnelc, x, parent=parent) + return _mpmath_utils_call(_mpmath_fresnelc, x, parent=parent) def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: x = var('x') - sage: fresnel_cos(x).diff(x) + sage: x = var('x') # needs sage.symbolic + sage: fresnel_cos(x).diff(x) # needs sage.symbolic cos(1/2*pi*x^2) """ - from sage.functions.trig import cos return cos(pi*x**2/2) diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py index a2099dbb4ab..5fb024c877c 100644 --- a/src/sage/functions/exp_integral.py +++ b/src/sage/functions/exp_integral.py @@ -46,20 +46,28 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import math +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import Infinity +from sage.rings.integer_ring import ZZ +from sage.structure.element import Expression, parent from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression -from sage.structure.all import parent -from sage.misc.latex import latex -from sage.libs.mpmath import utils as mpmath_utils -mpmath_utils_call = mpmath_utils.call # eliminate some overhead in _evalf_ -from sage.rings.real_mpfr import RealField -from sage.rings.integer_ring import ZZ -from sage.functions.log import exp, log -from sage.functions.trig import sin, cos -from sage.functions.hyperbolic import sinh, cosh -import math +lazy_import('sage.functions.log', ['exp', 'log']) +lazy_import('sage.functions.trig', ['sin', 'cos']) +lazy_import('sage.functions.hyperbolic', ['sinh', 'cosh']) + +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.real_mpfr', 'RealField') + +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', + ['chi', 'ci', 'e1', 'ei', 'expint', 'ei', 'li', 'shi', 'si'], + as_=['_mpmath_chi', '_mpmath_ci', '_mpmath_e1', '_mpmath_ei', '_mpmath_expint', + '_mpmath_ei', '_mpmath_li', '_mpmath_shi', '_mpmath_si']) class Function_exp_integral_e(BuiltinFunction): @@ -79,61 +87,60 @@ class Function_exp_integral_e(BuiltinFunction): Numerical evaluation is handled using mpmath:: - sage: N(exp_integral_e(1,1)) + sage: N(exp_integral_e(1, 1)) # needs sage.symbolic 0.219383934395520 - sage: exp_integral_e(1, RealField(100)(1)) + sage: exp_integral_e(1, RealField(100)(1)) # needs sage.symbolic 0.21938393439552027367716377546 We can compare this to PARI's evaluation of :meth:`exponential_integral_1`:: - sage: N(exponential_integral_1(1)) + sage: N(exponential_integral_1(1)) # needs sage.symbolic 0.219383934395520 We can verify one case of [AS1964]_ 5.1.45, i.e. `E_n(z) = z^{n-1}\Gamma(1-n,z)`:: - sage: N(exp_integral_e(2, 3+I)) + sage: N(exp_integral_e(2, 3+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I - sage: N((3+I)*gamma(-1, 3+I)) + sage: N((3+I)*gamma(-1, 3+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I Maxima returns the following improper integral as a multiple of ``exp_integral_e(1,1)``:: - sage: uu = integral(e^(-x)*log(x+1),x,0,oo) - sage: uu + sage: uu = integral(e^(-x)*log(x+1), x, 0, oo); uu # needs sage.symbolic e*exp_integral_e(1, 1) - sage: uu.n(digits=30) + sage: uu.n(digits=30) # needs sage.symbolic 0.596347362323194074341078499369 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e(2,x) sage: f.diff(x) -exp_integral_e(1, x) - sage: f.integrate(x) -exp_integral_e(3, x) - - sage: f = exp_integral_e(-1,x) + sage: f = exp_integral_e(-1, x) sage: f.integrate(x) Ei(-x) - gamma(-1, x) Some special values of ``exp_integral_e`` can be simplified. [AS1964]_ 5.1.23:: - sage: exp_integral_e(0,x) + sage: exp_integral_e(0, x) # needs sage.symbolic e^(-x)/x [AS1964]_ 5.1.24:: - sage: exp_integral_e(6,0) + sage: # needs sage.symbolic + sage: exp_integral_e(6, 0) 1/5 sage: nn = var('nn') sage: assume(nn > 1) - sage: f = exp_integral_e(nn,0) + sage: f = exp_integral_e(nn, 0) sage: f.simplify() 1/(nn - 1) @@ -150,9 +157,9 @@ def __init__(self): EXAMPLES:: - sage: exp_integral_e(1, 0) + sage: exp_integral_e(1, 0) # needs sage.symbolic exp_integral_e(1, 0) - sage: exp_integral_e(1, x)._sympy_() + sage: exp_integral_e(1, x)._sympy_() # needs sage.symbolic expint(1, x) """ @@ -164,18 +171,18 @@ def _eval_(self, n, z): """ EXAMPLES:: - sage: exp_integral_e(1.0, x) + sage: exp_integral_e(1.0, x) # needs sage.symbolic exp_integral_e(1.00000000000000, x) - sage: exp_integral_e(x, 1.0) + sage: exp_integral_e(x, 1.0) # needs sage.symbolic exp_integral_e(x, 1.00000000000000) - sage: exp_integral_e(3, 0) + sage: exp_integral_e(3, 0) # needs mpmath 1/2 TESTS: Check that Python ints work (:trac:`14766`):: - sage: exp_integral_e(int(3), 0) + sage: exp_integral_e(int(3), 0) # needs mpmath 1/2 """ z_zero = False @@ -211,15 +218,14 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: exp_integral_e(1.0, 1.0) + sage: exp_integral_e(1.0, 1.0) # needs mpmath 0.219383934395520 - sage: N(exp_integral_e(1, 1+I)) + sage: N(exp_integral_e(1, 1+I)) # needs sage.symbolic 0.000281624451981418 - 0.179324535039359*I - sage: exp_integral_e(1, RealField(100)(1)) + sage: exp_integral_e(1, RealField(100)(1)) # needs sage.rings.real_mpfr 0.21938393439552027367716377546 """ - import mpmath - return mpmath_utils.call(mpmath.expint, n, z, parent=parent) + return _mpmath_utils_call(_mpmath_expint, n, z, parent=parent) def _print_latex_(self, n, z): r""" @@ -227,7 +233,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(exp_integral_e(1, -x - 1)) + sage: latex(exp_integral_e(1, -x - 1)) # needs sage.symbolic E_{1}\left(-x - 1\right) """ return r"E_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -240,12 +246,12 @@ def _derivative_(self, n, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') - sage: f = exp_integral_e(2,x) + sage: f = exp_integral_e(2, x) sage: f.diff(x) -exp_integral_e(1, x) - - sage: f = exp_integral_e(2,sqrt(x)) + sage: f = exp_integral_e(2, sqrt(x)) sage: f.diff(x) -1/2*exp_integral_e(1, sqrt(x))/sqrt(x) """ @@ -269,33 +275,33 @@ class Function_exp_integral_e1(BuiltinFunction): EXAMPLES:: - sage: exp_integral_e1(x) + sage: exp_integral_e1(x) # needs sage.symbolic exp_integral_e1(x) - sage: exp_integral_e1(1.0) + sage: exp_integral_e1(1.0) # needs mpmath 0.219383934395520 Numerical evaluation is handled using mpmath:: - sage: N(exp_integral_e1(1)) + sage: N(exp_integral_e1(1)) # needs sage.symbolic 0.219383934395520 - sage: exp_integral_e1(RealField(100)(1)) + sage: exp_integral_e1(RealField(100)(1)) # needs sage.rings.real_mpfr 0.21938393439552027367716377546 We can compare this to PARI's evaluation of :meth:`exponential_integral_1`:: - sage: N(exp_integral_e1(2.0)) + sage: N(exp_integral_e1(2.0)) # needs mpmath 0.0489005107080611 - sage: N(exponential_integral_1(2.0)) + sage: N(exponential_integral_1(2.0)) # needs sage.rings.real_mpfr 0.0489005107080611 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e1(x) sage: f.diff(x) -e^(-x)/x - sage: f.integrate(x) -exp_integral_e(2, x) @@ -311,9 +317,9 @@ def __init__(self): EXAMPLES:: - sage: exp_integral_e1(1) + sage: exp_integral_e1(1) # needs sage.symbolic exp_integral_e1(1) - sage: exp_integral_e1(x)._sympy_() + sage: exp_integral_e1(x)._sympy_() # needs sympy sage.symbolic expint(1, x) """ @@ -325,14 +331,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(exp_integral_e1(1+I)) + sage: N(exp_integral_e1(1+I)) # needs sage.symbolic 0.000281624451981418 - 0.179324535039359*I - sage: exp_integral_e1(RealField(200)(0.5)) + sage: exp_integral_e1(RealField(200)(0.5)) # needs sage.rings.real_mpfr 0.55977359477616081174679593931508523522684689031635351524829 """ - import mpmath - return mpmath_utils_call(mpmath.e1, z, parent=parent) + return _mpmath_utils_call(_mpmath_e1, z, parent=parent) def _print_latex_(self, z): r""" @@ -340,7 +345,7 @@ def _print_latex_(self, z): EXAMPLES:: - sage: latex(exp_integral_e1(2)) + sage: latex(exp_integral_e1(2)) # needs sage.symbolic E_{1}\left(2\right) """ return r"E_{{1}}\left({}\right)".format(latex(z)) @@ -353,11 +358,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e1(x) sage: f.diff(x) -e^(-x)/x - sage: f = exp_integral_e1(x^2) sage: f.diff(x) -2*e^(-x^2)/x @@ -383,22 +388,22 @@ class Function_log_integral(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: N(log_integral(3)) + sage: N(log_integral(3)) # needs sage.symbolic 2.16358859466719 - sage: N(log_integral(3), digits=30) + sage: N(log_integral(3), digits=30) # needs sage.symbolic 2.16358859466719197287692236735 - sage: log_integral(ComplexField(100)(3+I)) + sage: log_integral(ComplexField(100)(3+I)) # needs sage.symbolic 2.2879892769816826157078450911 + 0.87232935488528370139883806779*I - sage: log_integral(0) + sage: log_integral(0) # needs mpmath 0 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral(x) sage: f.diff(x) 1/log(x) - sage: f.integrate(x) x*log_integral(x) - Ei(2*log(x)) @@ -406,7 +411,7 @@ class Function_log_integral(BuiltinFunction): 1,925,320,391,606,803,968,923 many prime numbers less than 1e23. The value of ``log_integral(1e23)`` is very close to this:: - sage: log_integral(1e23) + sage: log_integral(1e23) # needs mpmath 1.92532039161405e21 ALGORITHM: @@ -429,18 +434,18 @@ def __init__(self): EXAMPLES:: - sage: log_integral(3) + sage: log_integral(3) # needs sage.symbolic log_integral(3) - sage: log_integral(x)._sympy_() + sage: log_integral(x)._sympy_() # needs sympy sage.symbolic li(x) - sage: log_integral(x)._fricas_init_() + sage: log_integral(x)._fricas_init_() # needs sage.symbolic 'li(x)' TESTS: Verify that :trac:`28917` is fixed:: - sage: latex(log_integral(x)) + sage: latex(log_integral(x)) # needs sage.symbolic \operatorname{log\_integral}\left(x\right) """ BuiltinFunction.__init__(self, "log_integral", nargs=1, @@ -453,12 +458,12 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: log_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: log_integral(z) # needs sage.symbolic log_integral(z) - sage: log_integral(3.0) + sage: log_integral(3.0) # needs mpmath 2.16358859466719 - sage: log_integral(0) + sage: log_integral(0) # needs mpmath 0 """ @@ -473,14 +478,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(log_integral(1e6)) + sage: N(log_integral(1e6)) # needs mpmath 78627.5491594622 - sage: log_integral(RealField(200)(1e6)) + sage: log_integral(RealField(200)(1e6)) # needs sage.rings.real_mpfr 78627.549159462181919862910747947261161321874382421767074759 """ - import mpmath - return mpmath_utils_call(mpmath.li, z, parent=parent) + return _mpmath_utils_call(_mpmath_li, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -488,11 +492,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral(x) sage: f.diff(x) 1/log(x) - sage: f = log_integral(x^2) sage: f.diff(x) 2*x/log(x^2) @@ -537,13 +541,13 @@ class Function_log_integral_offset(BuiltinFunction): So we have:: - sage: li(4.5)-li(2.0)-Li(4.5) + sage: li(4.5) - li(2.0) - Li(4.5) # needs mpmath 0.000000000000000 `\operatorname{Li}(x)` is extended to complex arguments `z` by analytic continuation (see [AS1964]_ 5.1.3):: - sage: Li(6.6+5.4*I) + sage: Li(6.6 + 5.4*I) # needs sage.symbolic 3.97032201503632 + 2.62311237593572*I The function `\operatorname{Li}` is an approximation for the number of @@ -570,6 +574,7 @@ class Function_log_integral_offset(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: + sage: # needs sage.symbolic sage: N(log_integral_offset(3)) 1.11842481454970 sage: N(log_integral_offset(3), digits=30) @@ -578,7 +583,7 @@ class Function_log_integral_offset(BuiltinFunction): 1.2428254968641898308632562019 + 0.87232935488528370139883806779*I sage: log_integral_offset(2) 0 - sage: for n in range(1,7): + sage: for n in range(1,7): # needs primecountpy ....: print('%-10s%-10s%-20s'%(10^n, prime_pi(10^n), N(Li(10^n)))) 10 4 5.12043572466980 100 25 29.0809778039621 @@ -591,20 +596,21 @@ class Function_log_integral_offset(BuiltinFunction): There are 1,925,320,391,606,803,968,923 prime numbers less than 1e23. The value of ``log_integral_offset(1e23)`` is very close to this:: - sage: log_integral_offset(1e23) + sage: log_integral_offset(1e23) # needs mpmath 1.92532039161405e21 Symbolic derivatives are handled by Sage and integration by Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral_offset(x) sage: f.diff(x) 1/log(x) sage: f.integrate(x) -x*log_integral(2) + x*log_integral(x) - Ei(2*log(x)) - sage: Li(x).integrate(x,2.0,4.5).n(digits=10) + sage: Li(x).integrate(x, 2.0, 4.5).n(digits=10) 3.186411697 - sage: N(f.integrate(x,2.0,3.0)) # abs tol 1e-15 + sage: N(f.integrate(x, 2.0, 3.0)) # abs tol 1e-15 0.601621785860587 ALGORITHM: @@ -626,9 +632,9 @@ def __init__(self): EXAMPLES:: - sage: log_integral_offset(3) + sage: log_integral_offset(3) # needs sage.symbolic log_integral(3) - log_integral(2) - sage: log_integral_offset(x, hold=True)._sympy_() + sage: log_integral_offset(x, hold=True)._sympy_() # needs sympy sage.symbolic Li(x) TESTS: @@ -647,18 +653,17 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: log_integral_offset(z) + sage: z = var('z') # needs sage.symbolic + sage: log_integral_offset(z) # needs sage.symbolic -log_integral(2) + log_integral(z) - sage: log_integral_offset(3.0) + sage: log_integral_offset(3.0) # needs mpmath 1.11842481454970 - sage: log_integral_offset(2) + sage: log_integral_offset(2) # needs mpmath 0 """ if z == 2: - import sage.symbolic.ring - return sage.symbolic.ring.SR(0) + return SR(0) return li(z)-li(2) # If we return:(li(z)-li(2)) we get correct symbolic integration. # But on definite integration it returns x.xxxx-li(2). @@ -667,16 +672,15 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(log_integral_offset(1e6)) + sage: N(log_integral_offset(1e6)) # needs mpmath 78626.5039956821 - sage: log_integral_offset(RealField(200)(1e6)) + sage: log_integral_offset(RealField(200)(1e6)) # needs sage.rings.real_mpfr 78626.503995682064427078066159058066548185351766843615873183 - sage: li(4.5)-li(2.0)-Li(4.5) + sage: li(4.5) - li(2.0) - Li(4.5) # needs mpmath 0.000000000000000 """ - import mpmath - return mpmath_utils_call(mpmath.li, z, offset=True, parent=parent) + return _mpmath_utils_call(_mpmath_li, z, offset=True, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -684,11 +688,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral_offset(x) sage: f.diff(x) 1/log(x) - sage: f = log_integral_offset(x^2) sage: f.diff(x) 2*x/log(x^2) @@ -713,56 +717,55 @@ class Function_sin_integral(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: sin_integral(0) + sage: sin_integral(0) # needs mpmath 0 - sage: sin_integral(0.0) + sage: sin_integral(0.0) # needs mpmath 0.000000000000000 - sage: sin_integral(3.0) + sage: sin_integral(3.0) # needs mpmath 1.84865252799947 - sage: N(sin_integral(3), digits=30) + sage: N(sin_integral(3), digits=30) # needs sage.symbolic 1.84865252799946825639773025111 - sage: sin_integral(ComplexField(100)(3+I)) + sage: sin_integral(ComplexField(100)(3+I)) # needs sage.symbolic 2.0277151656451253616038525998 + 0.015210926166954211913653130271*I The alias ``Si`` can be used instead of ``sin_integral``:: - sage: Si(3.0) + sage: Si(3.0) # needs mpmath 1.84865252799947 The limit of `\operatorname{Si}(z)` as `z \to \infty` is `\pi/2`:: - sage: N(sin_integral(1e23)) + sage: N(sin_integral(1e23)) # needs mpmath 1.57079632679490 - sage: N(pi/2) + sage: N(pi/2) # needs sage.symbolic 1.57079632679490 At 200 bits of precision `\operatorname{Si}(10^{23})` agrees with `\pi/2` up to `10^{-24}`:: - sage: sin_integral(RealField(200)(1e23)) + sage: sin_integral(RealField(200)(1e23)) # needs sage.rings.real_mpfr 1.5707963267948966192313288218697837425815368604836679189519 - sage: N(pi/2, prec=200) + sage: N(pi/2, prec=200) # needs sage.symbolic 1.5707963267948966192313216916397514420985846996875529104875 The exponential sine integral is analytic everywhere:: - sage: sin_integral(-1.0) + sage: sin_integral(-1.0) # needs mpmath -0.946083070367183 - sage: sin_integral(-2.0) + sage: sin_integral(-2.0) # needs mpmath -1.60541297680269 - sage: sin_integral(-1e23) + sage: sin_integral(-1e23) # needs mpmath -1.57079632679490 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = sin_integral(x) sage: f.diff(x) sin(x)/x - sage: f.integrate(x) x*sin_integral(x) + cos(x) - sage: integrate(sin(x)/x, x) -1/2*I*Ei(I*x) + 1/2*I*Ei(-I*x) @@ -772,19 +775,20 @@ class Function_sin_integral(BuiltinFunction): \operatorname{Ei}(ix) - \pi/2`, which are both anti-derivatives of `\sin(x)/x`, at some random positive real numbers:: - sage: f(x) = 1/2*I*Ei(-I*x) - 1/2*I*Ei(I*x) - pi/2 - sage: g(x) = sin_integral(x) - sage: R = [ abs(RDF.random_element()) for i in range(100) ] - sage: all(abs(f(x) - g(x)) < 1e-10 for x in R) + sage: f(x) = 1/2*I*Ei(-I*x) - 1/2*I*Ei(I*x) - pi/2 # needs sage.symbolic + sage: g(x) = sin_integral(x) # needs sage.symbolic + sage: R = [abs(RDF.random_element()) for i in range(100)] + sage: all(abs(f(x) - g(x)) < 1e-10 for x in R) # needs sage.symbolic True The Nielsen spiral is the parametric plot of (Si(t), Ci(t)):: - sage: x=var('x') + sage: # needs sage.symbolic + sage: x = var('x') sage: f(x) = sin_integral(x) sage: g(x) = cos_integral(x) - sage: P = parametric_plot([f, g], (x, 0.5 ,20)) - sage: show(P, frame=True, axes=False) + sage: P = parametric_plot([f, g], (x, 0.5 ,20)) # needs sage.plot + sage: show(P, frame=True, axes=False) # needs sage.plot ALGORITHM: @@ -805,13 +809,14 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: sin_integral(1) sin_integral(1) - sage: sin_integral(x)._sympy_() + sage: sin_integral(x)._sympy_() # needs sympy Si(x) sage: sin_integral(x)._fricas_init_() 'Si(x)' - sage: sin_integral(x)._giac_() + sage: sin_integral(x)._giac_() # needs sage.libs.giac Si(sageVARx) """ BuiltinFunction.__init__(self, "sin_integral", nargs=1, @@ -824,12 +829,12 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: sin_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: sin_integral(z) # needs sage.symbolic sin_integral(z) - sage: sin_integral(3.0) + sage: sin_integral(3.0) # needs mpmath 1.84865252799947 - sage: sin_integral(0) + sage: sin_integral(0) # needs mpmath 0 """ @@ -845,29 +850,28 @@ def _evalf_(self, z, parent=None, algorithm=None): The limit `\operatorname{Si}(z)` as `z \to \infty` is `\pi/2`:: - sage: N(sin_integral(1e23) - pi/2) + sage: N(sin_integral(1e23) - pi/2) # needs sage.symbolic 0.000000000000000 At 200 bits of precision `\operatorname{Si}(10^{23})` agrees with `\pi/2` up to `10^{-24}`:: - sage: sin_integral(RealField(200)(1e23)) + sage: sin_integral(RealField(200)(1e23)) # needs sage.rings.real_mpfr 1.5707963267948966192313288218697837425815368604836679189519 - sage: N(pi/2, prec=200) + sage: N(pi/2, prec=200) # needs sage.symbolic 1.5707963267948966192313216916397514420985846996875529104875 The exponential sine integral is analytic everywhere, even on the negative real axis:: - sage: sin_integral(-1.0) + sage: sin_integral(-1.0) # needs mpmath -0.946083070367183 - sage: sin_integral(-2.0) + sage: sin_integral(-2.0) # needs mpmath -1.60541297680269 - sage: sin_integral(-1e23) + sage: sin_integral(-1e23) # needs mpmath -1.57079632679490 """ - import mpmath - return mpmath_utils_call(mpmath.si, z, parent=parent) + return _mpmath_utils_call(_mpmath_si, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -877,11 +881,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = sin_integral(x) sage: f.diff(x) sin(x)/x - sage: f = sin_integral(x^2) sage: f.diff(x) 2*sin(x^2)/x @@ -906,62 +910,63 @@ class Function_cos_integral(BuiltinFunction): EXAMPLES:: - sage: z = var('z') - sage: cos_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: cos_integral(z) # needs sage.symbolic cos_integral(z) - sage: cos_integral(3.0) + sage: cos_integral(3.0) # needs mpmath 0.119629786008000 - sage: cos_integral(0) + sage: cos_integral(0) # needs sage.symbolic cos_integral(0) - sage: N(cos_integral(0)) + sage: N(cos_integral(0)) # needs mpmath -infinity Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: cos_integral(3.0) + sage: cos_integral(3.0) # needs mpmath 0.119629786008000 The alias ``Ci`` can be used instead of ``cos_integral``:: - sage: Ci(3.0) + sage: Ci(3.0) # needs mpmath 0.119629786008000 Compare ``cos_integral(3.0)`` to the definition of the value using numerical integration:: - sage: a = numerical_integral((cos(x)-1)/x, 0, 3)[0] - sage: abs(N(euler_gamma + log(3)) + a - N(cos_integral(3.0))) < 1e-14 + sage: a = numerical_integral((cos(x)-1)/x, 0, 3)[0] # needs sage.symbolic + sage: abs(N(euler_gamma + log(3)) + a - N(cos_integral(3.0))) < 1e-14 # needs sage.symbolic True Arbitrary precision and complex arguments are handled:: - sage: N(cos_integral(3), digits=30) + sage: N(cos_integral(3), digits=30) # needs sage.symbolic 0.119629786008000327626472281177 - sage: cos_integral(ComplexField(100)(3+I)) + sage: cos_integral(ComplexField(100)(3+I)) # needs sage.symbolic 0.078134230477495714401983633057 - 0.37814733904787920181190368789*I The limit `\operatorname{Ci}(z)` as `z \to \infty` is zero:: - sage: N(cos_integral(1e23)) + sage: N(cos_integral(1e23)) # needs mpmath -3.24053937643003e-24 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cos_integral(x) sage: f.diff(x) cos(x)/x - sage: f.integrate(x) x*cos_integral(x) - sin(x) The Nielsen spiral is the parametric plot of (Si(t), Ci(t)):: - sage: t=var('t') + sage: # needs sage.symbolic + sage: t = var('t') sage: f(t) = sin_integral(t) sage: g(t) = cos_integral(t) - sage: P = parametric_plot([f, g], (t, 0.5 ,20)) - sage: show(P, frame=True, axes=False) + sage: P = parametric_plot([f, g], (t, 0.5 ,20)) # needs sage.plot + sage: show(P, frame=True, axes=False) # needs sage.plot ALGORITHM: @@ -982,13 +987,14 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: cos_integral(1) cos_integral(1) - sage: cos_integral(x)._sympy_() + sage: cos_integral(x)._sympy_() # needs sympy Ci(x) sage: cos_integral(x)._fricas_init_() 'Ci(x)' - sage: cos_integral(x)._giac_() + sage: cos_integral(x)._giac_() # needs sage.libs.giac Ci(sageVARx) """ BuiltinFunction.__init__(self, "cos_integral", nargs=1, @@ -1001,16 +1007,15 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(cos_integral(1e23)) < 1e-20 + sage: N(cos_integral(1e23)) < 1e-20 # needs mpmath True - sage: N(cos_integral(10^-10), digits=30) + sage: N(cos_integral(10^-10), digits=30) # needs sage.symbolic -22.4486352650389239795759024568 - sage: cos_integral(ComplexField(100)(I)) + sage: cos_integral(ComplexField(100)(I)) # needs sage.symbolic 0.83786694098020824089467857943 + 1.5707963267948966192313216916*I """ - import mpmath - return mpmath_utils_call(mpmath.ci, z, parent=parent) + return _mpmath_utils_call(_mpmath_ci, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -1018,11 +1023,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cos_integral(x) sage: f.diff(x) cos(x)/x - sage: f = cos_integral(x^2) sage: f.diff(x) 2*cos(x^2)/x @@ -1048,45 +1053,45 @@ class Function_sinh_integral(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: sinh_integral(3.0) + sage: sinh_integral(3.0) # needs mpmath 4.97344047585981 - sage: sinh_integral(1.0) + sage: sinh_integral(1.0) # needs mpmath 1.05725087537573 - sage: sinh_integral(-1.0) + sage: sinh_integral(-1.0) # needs mpmath -1.05725087537573 The alias ``Shi`` can be used instead of ``sinh_integral``:: - sage: Shi(3.0) + sage: Shi(3.0) # needs mpmath 4.97344047585981 Compare ``sinh_integral(3.0)`` to the definition of the value using numerical integration:: - sage: a = numerical_integral(sinh(x)/x, 0, 3)[0] - sage: abs(a - N(sinh_integral(3))) < 1e-14 + sage: a = numerical_integral(sinh(x)/x, 0, 3)[0] # needs sage.symbolic + sage: abs(a - N(sinh_integral(3))) < 1e-14 # needs sage.symbolic True Arbitrary precision and complex arguments are handled:: - sage: N(sinh_integral(3), digits=30) + sage: N(sinh_integral(3), digits=30) # needs sage.symbolic 4.97344047585980679771041838252 - sage: sinh_integral(ComplexField(100)(3+I)) + sage: sinh_integral(ComplexField(100)(3+I)) # needs sage.symbolic 3.9134623660329374406788354078 + 3.0427678212908839256360163759*I The limit `\operatorname{Shi}(z)` as `z \to \infty` is `\infty`:: - sage: N(sinh_integral(Infinity)) + sage: N(sinh_integral(Infinity)) # needs mpmath +infinity Symbolic derivatives and integrals are handled by Sage and Maxima:: - sage: x = var('x') - sage: f = sinh_integral(x) - sage: f.diff(x) + sage: x = var('x') # needs sage.symbolic + sage: f = sinh_integral(x) # needs sage.symbolic + sage: f.diff(x) # needs sage.symbolic sinh(x)/x - sage: f.integrate(x) + sage: f.integrate(x) # needs sage.symbolic x*sinh_integral(x) - cosh(x) Note that due to some problems with the way Maxima handles these @@ -1094,11 +1099,11 @@ class Function_sinh_integral(BuiltinFunction): results (typically when using inexact endpoints) due to inconsistent branching:: - sage: integrate(sinh_integral(x), x, 0, 1/2) + sage: integrate(sinh_integral(x), x, 0, 1/2) # needs sage.symbolic -cosh(1/2) + 1/2*sinh_integral(1/2) + 1 - sage: integrate(sinh_integral(x), x, 0, 1/2).n() # correct + sage: integrate(sinh_integral(x), x, 0, 1/2).n() # correct # needs sage.symbolic 0.125872409703453 - sage: integrate(sinh_integral(x), x, 0, 0.5).n() # fixed in maxima 5.29.1 + sage: integrate(sinh_integral(x), x, 0, 0.5).n() # fixed in maxima 5.29.1 # needs sage.symbolic 0.125872409703453 ALGORITHM: @@ -1120,9 +1125,9 @@ def __init__(self): EXAMPLES:: - sage: sinh_integral(1) + sage: sinh_integral(1) # needs sage.symbolic sinh_integral(1) - sage: sinh_integral(x)._sympy_() + sage: sinh_integral(x)._sympy_() # needs sympy sage.symbolic Shi(x) """ @@ -1136,12 +1141,12 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: sinh_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: sinh_integral(z) # needs sage.symbolic sinh_integral(z) - sage: sinh_integral(3.0) + sage: sinh_integral(3.0) # needs mpmath 4.97344047585981 - sage: sinh_integral(0) + sage: sinh_integral(0) # needs mpmath 0 """ @@ -1156,14 +1161,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(sinh_integral(10^-10), digits=30) + sage: N(sinh_integral(10^-10), digits=30) # needs sage.symbolic 1.00000000000000000000055555556e-10 - sage: sinh_integral(ComplexField(100)(I)) + sage: sinh_integral(ComplexField(100)(I)) # needs sage.symbolic 0.94608307036718301494135331382*I """ - import mpmath - return mpmath_utils_call(mpmath.shi, z, parent=parent) + return _mpmath_utils_call(_mpmath_shi, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -1171,11 +1175,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = sinh_integral(x) sage: f.diff(x) sinh(x)/x - sage: f = sinh_integral(ln(x)) sage: f.diff(x) 1/2*(x^2 - 1)/(x^2*log(x)) @@ -1199,54 +1203,54 @@ class Function_cosh_integral(BuiltinFunction): EXAMPLES:: - sage: z = var('z') - sage: cosh_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: cosh_integral(z) # needs sage.symbolic cosh_integral(z) - sage: cosh_integral(3.0) + sage: cosh_integral(3.0) # needs mpmath 4.96039209476561 Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: cosh_integral(1.0) + sage: cosh_integral(1.0) # needs mpmath 0.837866940980208 The alias ``Chi`` can be used instead of ``cosh_integral``:: - sage: Chi(1.0) + sage: Chi(1.0) # needs mpmath 0.837866940980208 Here is an example from the mpmath documentation:: - sage: f(x) = cosh_integral(x) - sage: find_root(f, 0.1, 1.0) + sage: f(x) = cosh_integral(x) # needs sage.symbolic + sage: find_root(f, 0.1, 1.0) # needs scipy sage.symbolic 0.523822571389... Compare ``cosh_integral(3.0)`` to the definition of the value using numerical integration:: - sage: a = numerical_integral((cosh(x)-1)/x, 0, 3)[0] - sage: abs(N(euler_gamma + log(3)) + a - N(cosh_integral(3.0))) < 1e-14 + sage: a = numerical_integral((cosh(x)-1)/x, 0, 3)[0] # needs sage.symbolic + sage: abs(N(euler_gamma + log(3)) + a - N(cosh_integral(3.0))) < 1e-14 # needs sage.symbolic True Arbitrary precision and complex arguments are handled:: - sage: N(cosh_integral(3), digits=30) + sage: N(cosh_integral(3), digits=30) # needs sage.symbolic 4.96039209476560976029791763669 - sage: cosh_integral(ComplexField(100)(3+I)) + sage: cosh_integral(ComplexField(100)(3+I)) # needs sage.symbolic 3.9096723099686417127843516794 + 3.0547519627014217273323873274*I The limit of `\operatorname{Chi}(z)` as `z \to \infty` is `\infty`:: - sage: N(cosh_integral(Infinity)) + sage: N(cosh_integral(Infinity)) # needs mpmath +infinity Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cosh_integral(x) sage: f.diff(x) cosh(x)/x - sage: f.integrate(x) x*cosh_integral(x) - sinh(x) @@ -1269,9 +1273,9 @@ def __init__(self): EXAMPLES:: - sage: cosh_integral(1) + sage: cosh_integral(1) # needs sage.symbolic cosh_integral(1) - sage: cosh_integral(x)._sympy_() + sage: cosh_integral(x)._sympy_() # needs sage.symbolic Chi(x) """ @@ -1285,14 +1289,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(cosh_integral(10^-10), digits=30) + sage: N(cosh_integral(10^-10), digits=30) # needs sage.symbolic -22.4486352650389239795709024568 - sage: cosh_integral(ComplexField(100)(I)) + sage: cosh_integral(ComplexField(100)(I)) # needs sage.symbolic 0.33740392290096813466264620389 + 1.5707963267948966192313216916*I """ - import mpmath - return mpmath_utils_call(mpmath.chi, z, parent=parent) + return _mpmath_utils_call(_mpmath_chi, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -1300,11 +1303,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cosh_integral(x) sage: f.diff(x) cosh(x)/x - sage: f = cosh_integral(ln(x)) sage: f.diff(x) 1/2*(x^2 + 1)/(x^2*log(x)) @@ -1339,31 +1342,33 @@ class Function_exp_integral(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: Ei(10) Ei(10) sage: Ei(I) Ei(I) sage: Ei(3+I) Ei(I + 3) - sage: Ei(1.3) - 2.72139888023202 sage: Ei(10r) Ei(10) - sage: Ei(1.3r) + + sage: Ei(1.3) # needs mpmath + 2.72139888023202 + sage: Ei(1.3r) # needs mpmath 2.7213988802320235 The branch cut for this function is along the negative real axis:: - sage: Ei(-3 + 0.1*I) + sage: Ei(-3 + 0.1*I) # needs sage.symbolic -0.0129379427181693 + 3.13993830250942*I - sage: Ei(-3 - 0.1*I) + sage: Ei(-3 - 0.1*I) # needs sage.symbolic -0.0129379427181693 - 3.13993830250942*I The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:: - sage: Ei(RealField(300)(1.1)) + sage: Ei(RealField(300)(1.1)) # needs sage.rings.real_mpfr 2.16737827956340282358378734233807621497112737591639704719499002090327541763352339357795426 ALGORITHM: Uses mpmath. @@ -1372,6 +1377,7 @@ class Function_exp_integral(BuiltinFunction): Show that the evaluation and limit issue in :trac:`13271` is fixed:: + sage: # needs sage.symbolic sage: var('Z') Z sage: (Ei(-Z)).limit(Z=oo) @@ -1385,9 +1391,9 @@ def __init__(self): """ TESTS:: - sage: Ei(10) + sage: Ei(10) # needs sage.symbolic Ei(10) - sage: Ei(x)._sympy_() + sage: Ei(x)._sympy_() # needs sympy sage.symbolic Ei(x) """ BuiltinFunction.__init__(self, "Ei", @@ -1399,6 +1405,7 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: + sage: # needs sage.symbolic sage: Ei(10).n() 2492.22897624188 sage: Ei(20).n() @@ -1408,13 +1415,13 @@ def _evalf_(self, x, parent=None, algorithm=None): sage: Ei(3+I).n() 7.82313467600158 + 6.09751978399231*I """ - import mpmath - return mpmath_utils_call(mpmath.ei, x, parent=parent) + return _mpmath_utils_call(_mpmath_ei, x, parent=parent) def _derivative_(self, x, diff_param=None): """ EXAMPLES:: + sage: # needs sage.symbolic sage: Ei(x).diff(x) e^x/x sage: Ei(x).diff(x).subs(x=1) @@ -1463,27 +1470,29 @@ def exponential_integral_1(x, n=0): EXAMPLES:: + sage: # needs sage.libs.pari sage: exponential_integral_1(2) 0.0489005107080611 sage: exponential_integral_1(2, 4) # abs tol 1e-18 [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245] sage: exponential_integral_1(40, 5) - [0.000000000000000, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90] - sage: exponential_integral_1(0) - +Infinity - sage: r = exponential_integral_1(RealField(150)(1)) - sage: r + [0.000000000000000, 2.22854325868847e-37, 6.33732515501151e-55, + 2.02336191509997e-72, 6.88522610630764e-90] + sage: r = exponential_integral_1(RealField(150)(1)); r 0.21938393439552027367716377546012164903104729 sage: parent(r) Real Field with 150 bits of precision sage: exponential_integral_1(RealField(150)(100)) 3.6835977616820321802351926205081189876552201e-46 + sage: exponential_integral_1(0) + +Infinity + TESTS: The relative error for a single value should be less than 1 ulp:: - sage: for prec in [20..1000]: # long time (22s on sage.math, 2013) + sage: for prec in [20..1000]: # long time (22s on sage.math, 2013), needs sage.libs.pari ....: R = RealField(prec) ....: S = RealField(prec+64) ....: for t in range(8): # Try 8 values for each precision @@ -1497,7 +1506,7 @@ def exponential_integral_1(x, n=0): The absolute error for a vector should be less than `2^{-p} c`, where `p` is the precision in bits of `x` and `c = 2` ``max(1, exponential_integral_1(x))``:: - sage: for prec in [20..128]: # long time (15s on sage.math, 2013) + sage: for prec in [20..128]: # long time (15s on sage.math, 2013), needs sage.libs.pari ....: R = RealField(prec) ....: S = RealField(prec+64) ....: a = R.random_element(-15,10).exp() @@ -1519,7 +1528,6 @@ def exponential_integral_1(x, n=0): """ if isinstance(x, Expression): if x.is_trivial_zero(): - from sage.rings.infinity import Infinity return Infinity else: raise NotImplementedError("Use the symbolic exponential integral " + @@ -1527,7 +1535,6 @@ def exponential_integral_1(x, n=0): # x == 0 => return Infinity if not x: - from sage.rings.infinity import Infinity return Infinity # Figure out output precision diff --git a/src/sage/functions/gamma.py b/src/sage/functions/gamma.py index e93e518b0b9..8ecf834a8a8 100644 --- a/src/sage/functions/gamma.py +++ b/src/sage/functions/gamma.py @@ -1,16 +1,24 @@ """ Gamma and related functions """ -from sage.symbolic.function import GinacFunction, BuiltinFunction -from sage.symbolic.expression import register_symbol, symbol_table -from sage.structure.all import parent as s_parent -from sage.rings.complex_mpfr import ComplexField +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import Infinity from sage.rings.rational import Rational -from sage.functions.exp_integral import Ei -from sage.libs.mpmath import utils as mpmath_utils -from .log import exp -from .other import sqrt -from sage.symbolic.constants import pi +from sage.structure.element import parent as s_parent +from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.symbolic.symbols import register_symbol, symbol_table + +lazy_import('sage.rings.complex_mpfr', 'ComplexField') + +lazy_import('sage.functions.error', 'erf') +lazy_import('sage.functions.exp_integral', 'Ei') +lazy_import('sage.functions.log', 'exp') +lazy_import('sage.functions.other', 'sqrt') + +lazy_import('sage.symbolic.constants', 'pi') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'gammainc', as_='_mpmath_gammainc') class Function_gamma(GinacFunction): @@ -32,9 +40,9 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.gamma import gamma1 - sage: gamma1(CDF(0.5,14)) + sage: gamma1(CDF(0.5, 14)) # needs sage.libs.pari -4.0537030780372815e-10 - 5.773299834553605e-10*I - sage: gamma1(CDF(I)) + sage: gamma1(CDF(I)) # needs sage.libs.pari sage.symbolic -0.15494982830181067 - 0.49801566811835607*I Recall that `\Gamma(n)` is `n-1` factorial:: @@ -43,124 +51,124 @@ def __init__(self): True sage: gamma1(6) 120 - sage: gamma1(1/2) + sage: gamma1(1/2) # needs sage.symbolic sqrt(pi) sage: gamma1(-1) Infinity - sage: gamma1(I) + sage: gamma1(I) # needs sage.symbolic gamma(I) - sage: gamma1(x/2)(x=5) + sage: gamma1(x/2)(x=5) # needs sage.symbolic 3/4*sqrt(pi) sage: gamma1(float(6)) # For ARM: rel tol 3e-16 120.0 - sage: gamma(6.) + sage: gamma(6.) # needs sage.symbolic 120.000000000000 - sage: gamma1(x) + sage: gamma1(x) # needs sage.symbolic gamma(x) :: - sage: gamma1(pi) + sage: gamma1(pi) # needs sage.symbolic gamma(pi) - sage: gamma1(i) + sage: gamma1(i) # needs sage.symbolic gamma(I) - sage: gamma1(i).n() + sage: gamma1(i).n() # needs sage.symbolic -0.154949828301811 - 0.498015668118356*I sage: gamma1(int(5)) 24 :: - sage: conjugate(gamma(x)) + sage: conjugate(gamma(x)) # needs sage.symbolic gamma(conjugate(x)) :: - sage: plot(gamma1(x),(x,1,5)) + sage: plot(gamma1(x), (x,1,5)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive We are also able to compute the Laurent expansion of the Gamma function (as well as of functions containing the Gamma function):: - sage: gamma(x).series(x==0, 2) + sage: gamma(x).series(x==0, 2) # needs sage.symbolic 1*x^(-1) + (-euler_gamma) + (1/2*euler_gamma^2 + 1/12*pi^2)*x + Order(x^2) - sage: (gamma(x)^2).series(x==0, 1) + sage: (gamma(x)^2).series(x==0, 1) # needs sage.symbolic 1*x^(-2) + (-2*euler_gamma)*x^(-1) + (2*euler_gamma^2 + 1/6*pi^2) + Order(x) To prevent automatic evaluation use the ``hold`` argument:: - sage: gamma1(1/2,hold=True) + sage: gamma1(1/2, hold=True) # needs sage.symbolic gamma(1/2) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: gamma1(1/2,hold=True).simplify() + sage: gamma1(1/2, hold=True).simplify() # needs sage.symbolic sqrt(pi) TESTS: - sage: gamma(x)._sympy_() + sage: gamma(x)._sympy_() # needs sympy sage.symbolic gamma(x) We verify that we can convert this function to Maxima and convert back to Sage:: - sage: z = var('z') - sage: maxima(gamma1(z)).sage() + sage: z = var('z') # needs sage.symbolic + sage: maxima(gamma1(z)).sage() # needs sage.symbolic gamma(z) - sage: latex(gamma1(z)) + sage: latex(gamma1(z)) # needs sage.symbolic \Gamma\left(z\right) Test that :trac:`5556` is fixed:: - sage: gamma1(3/4) + sage: gamma1(3/4) # needs sage.symbolic gamma(3/4) - sage: gamma1(3/4).n(100) + sage: gamma1(3/4).n(100) # needs sage.symbolic 1.2254167024651776451290983034 Check that negative integer input works:: sage: (-1).gamma() Infinity - sage: (-1.).gamma() + sage: (-1.).gamma() # needs sage.rings.real_mpfr NaN - sage: CC(-1).gamma() + sage: CC(-1).gamma() # needs sage.libs.pari Infinity sage: RDF(-1).gamma() NaN - sage: CDF(-1).gamma() + sage: CDF(-1).gamma() # needs sage.libs.pari sage.rings.complex_double Infinity Check if :trac:`8297` is fixed:: - sage: latex(gamma(1/4)) + sage: latex(gamma(1/4)) # needs sage.symbolic \Gamma\left(\frac{1}{4}\right) Test pickling:: - sage: loads(dumps(gamma(x))) + sage: loads(dumps(gamma(x))) # needs sage.symbolic gamma(x) Check that the implementations roughly agrees (note there might be difference of several ulp on more complicated entries):: - sage: import mpmath - sage: float(gamma(10.)) == gamma(10.r) == float(gamma(mpmath.mpf(10))) + sage: import mpmath # needs mpmath + sage: float(gamma(10.)) == gamma(10.r) == float(gamma(mpmath.mpf(10))) # needs mpmath True - sage: float(gamma(8.5)) == gamma(8.5r) == float(gamma(mpmath.mpf(8.5))) + sage: float(gamma(8.5)) == gamma(8.5r) == float(gamma(mpmath.mpf(8.5))) # needs mpmath True Check that ``QQbar`` half integers work with the ``pi`` formula:: - sage: gamma(QQbar(1/2)) + sage: gamma(QQbar(1/2)) # needs sage.rings.number_field sage.symbolic sqrt(pi) - sage: gamma(QQbar(-9/2)) + sage: gamma(QQbar(-9/2)) # needs sage.rings.number_field sage.symbolic -32/945*sqrt(pi) .. SEEALSO:: @@ -175,6 +183,7 @@ def __init__(self): 'fricas':'Gamma', 'giac':'Gamma'}) + gamma1 = Function_gamma() @@ -197,14 +206,13 @@ def __init__(self): Numerical evaluation happens when appropriate, to the appropriate accuracy (see :trac:`10072`):: + sage: # needs sage.symbolic sage: log_gamma(6) log(120) sage: log_gamma(6.) 4.78749174278205 sage: log_gamma(6).n() 4.78749174278205 - sage: log_gamma(RealField(100)(6)) - 4.7874917427820459942477009345 sage: log_gamma(2.4 + I) -0.0308566579348816 + 0.693427705955790*I sage: log_gamma(-3.1) @@ -212,17 +220,21 @@ def __init__(self): sage: log_gamma(-1.1) == log(gamma(-1.1)) False + sage: log_gamma(RealField(100)(6)) # needs sage.rings.real_mpfr + 4.7874917427820459942477009345 + Symbolic input works (see :trac:`10075`):: - sage: log_gamma(3*x) + sage: log_gamma(3*x) # needs sage.symbolic log_gamma(3*x) - sage: log_gamma(3 + I) + sage: log_gamma(3 + I) # needs sage.symbolic log_gamma(I + 3) - sage: log_gamma(3 + I + x) + sage: log_gamma(3 + I + x) # needs sage.symbolic log_gamma(x + I + 3) Check that :trac:`12521` is fixed:: + sage: # needs sage.symbolic sage: log_gamma(-2.1) 1.53171380819509 - 9.42477796076938*I sage: log_gamma(CC(-2.1)) @@ -237,35 +249,38 @@ def __init__(self): to evaluate a held expression, use the ``n()`` numerical evaluation method:: - sage: log_gamma(SR(5), hold=True) + sage: log_gamma(SR(5), hold=True) # needs sage.symbolic log_gamma(5) - sage: log_gamma(SR(5), hold=True).n() + sage: log_gamma(SR(5), hold=True).n() # needs sage.symbolic 3.17805383034795 TESTS:: + sage: log_gamma(pari(6)) # needs sage.libs.pari + 4.78749174278205 + + sage: # needs sage.symbolic sage: log_gamma(-2.1 + I) -1.90373724496982 - 7.18482377077183*I - sage: log_gamma(pari(6)) - 4.78749174278205 - sage: log_gamma(x)._sympy_() + sage: log_gamma(x)._sympy_() # needs sympy loggamma(x) - sage: log_gamma(CC(6)) + sage: log_gamma(CC(6)) # needs sage.rings.real_mpfr 4.78749174278205 - sage: log_gamma(CC(-2.5)) + sage: log_gamma(CC(-2.5)) # needs sage.rings.real_mpfr -0.0562437164976741 - 9.42477796076938*I sage: log_gamma(RDF(-2.5)) -0.056243716497674054 - 9.42477796076938*I - sage: log_gamma(CDF(-2.5)) + sage: log_gamma(CDF(-2.5)) # needs sage.rings.complex_double -0.056243716497674054 - 9.42477796076938*I sage: log_gamma(float(-2.5)) (-0.056243716497674054-9.42477796076938j) - sage: log_gamma(complex(-2.5)) + sage: log_gamma(complex(-2.5)) # needs sage.rings.complex_double (-0.056243716497674054-9.42477796076938j) ``conjugate(log_gamma(x)) == log_gamma(conjugate(x))`` unless on the branch cut, which runs along the negative real axis.:: + sage: # needs sage.symbolic sage: conjugate(log_gamma(x)) conjugate(log_gamma(x)) sage: var('y', domain='positive') @@ -302,45 +317,49 @@ def __init__(self): EXAMPLES:: - sage: gamma_inc(CDF(0,1), 3) + sage: gamma_inc(CDF(0,1), 3) # needs sage.libs.pari sage.rings.complex_double 0.0032085749933691158 + 0.012406185811871568*I - sage: gamma_inc(RDF(1), 3) + sage: gamma_inc(RDF(1), 3) # needs sage.rings.complex_double 0.049787068367863944 - sage: gamma_inc(3,2) + + sage: # needs sage.symbolic + sage: gamma_inc(3, 2) gamma(3, 2) - sage: gamma_inc(x,0) + sage: gamma_inc(x, 0) gamma(x) - sage: latex(gamma_inc(3,2)) + sage: latex(gamma_inc(3, 2)) \Gamma\left(3, 2\right) - sage: loads(dumps((gamma_inc(3,2)))) + sage: loads(dumps((gamma_inc(3, 2)))) gamma(3, 2) - sage: i = ComplexField(30).0; gamma_inc(2, 1 + i) + + sage: i = ComplexField(30).0; gamma_inc(2, 1 + i) # needs sage.rings.real_mpfr 0.70709210 - 0.42035364*I - sage: gamma_inc(2., 5) + sage: gamma_inc(2., 5) # needs sage.rings.complex_double 0.0404276819945128 - sage: x,y=var('x,y') - sage: gamma_inc(x,y).diff(x) + + sage: x, y = var('x,y') # needs sage.symbolic + sage: gamma_inc(x,y).diff(x) # needs sage.symbolic diff(gamma(x, y), x) - sage: (gamma_inc(x,x+1).diff(x)).simplify() + sage: (gamma_inc(x, x + 1).diff(x)).simplify() # needs sage.symbolic -(x + 1)^(x - 1)*e^(-x - 1) + D[0](gamma)(x, x + 1) TESTS: Check that :trac:`21407` is fixed:: - sage: gamma(-1,5)._sympy_() + sage: gamma(-1, 5)._sympy_() # needs sympy sage.symbolic expint(2, 5)/5 - sage: gamma(-3/2,5)._sympy_() + sage: gamma(-3/2, 5)._sympy_() # needs sympy sage.symbolic -6*sqrt(5)*exp(-5)/25 + 4*sqrt(pi)*erfc(sqrt(5))/3 Check that :trac:`25597` is fixed:: - sage: gamma(-1,5)._fricas_() # optional - fricas + sage: gamma(-1, 5)._fricas_() # optional - fricas, needs sage.symbolic Gamma(- 1,5) - sage: var('t') # optional - fricas + sage: var('t') # needs sage.symbolic t - sage: integrate(-exp(-x)*x^(t-1), x, algorithm="fricas") # optional - fricas + sage: integrate(-exp(-x)*x^(t-1), x, algorithm="fricas") # optional - fricas, needs sage.symbolic gamma(t, x) .. SEEALSO:: @@ -356,6 +375,7 @@ def _method_arguments(self, x, y): r""" TESTS:: + sage: # needs sage.libs.flint sage: b = RBF(1, 1e-10) sage: gamma(b) # abs tol 1e-9 [1.0000000000 +/- 5.78e-11] @@ -372,21 +392,23 @@ def _eval_(self, x, y): """ EXAMPLES:: - sage: gamma_inc(2.,0) + sage: gamma_inc(2., 0) # needs sage.rings.complex_double 1.00000000000000 - sage: gamma_inc(2,0) + sage: gamma_inc(2, 0) # needs sage.rings.real_mpfr 1 - sage: gamma_inc(1/2,2) + + sage: # needs sage.symbolic + sage: gamma_inc(1/2, 2) -sqrt(pi)*(erf(sqrt(2)) - 1) - sage: gamma_inc(1/2,1) + sage: gamma_inc(1/2, 1) -sqrt(pi)*(erf(1) - 1) - sage: gamma_inc(1/2,0) + sage: gamma_inc(1/2, 0) sqrt(pi) - sage: gamma_inc(x,0) + sage: gamma_inc(x, 0) gamma(x) - sage: gamma_inc(1,2) + sage: gamma_inc(1, 2) e^(-2) - sage: gamma_inc(0,2) + sage: gamma_inc(0, 2) -Ei(-2) """ if y == 0: @@ -396,7 +418,6 @@ def _eval_(self, x, y): if x == 0: return -Ei(-y) if x == Rational((1, 2)): # only for x>0 - from sage.functions.error import erf return sqrt(pi) * (1 - erf(sqrt(y))) return None @@ -404,41 +425,41 @@ def _evalf_(self, x, y, parent=None, algorithm='pari'): """ EXAMPLES:: - sage: gamma_inc(0,2) + sage: gamma_inc(0, 2) # needs sage.symbolic -Ei(-2) - sage: gamma_inc(0,2.) + sage: gamma_inc(0, 2.) # needs sage.rings.real_mpfr 0.0489005107080611 - sage: gamma_inc(0,2).n(algorithm='pari') + sage: gamma_inc(0, 2).n(algorithm='pari') # needs sage.libs.pari sage.symbolic 0.0489005107080611 - sage: gamma_inc(0,2).n(200) + sage: gamma_inc(0, 2).n(200) # needs sage.symbolic 0.048900510708061119567239835228... - sage: gamma_inc(3,2).n() + sage: gamma_inc(3, 2).n() # needs sage.symbolic 1.35335283236613 TESTS: Check that :trac:`7099` is fixed:: - sage: R = RealField(1024) - sage: gamma(R(9), R(10^-3)) # rel tol 1e-308 + sage: R = RealField(1024) # needs sage.rings.real_mpfr + sage: gamma(R(9), R(10^-3)) # rel tol 1e-308 # needs sage.rings.real_mpfr 40319.99999999999999999999999999988898884344822911869926361916294165058203634104838326009191542490601781777105678829520585311300510347676330951251563007679436243294653538925717144381702105700908686088851362675381239820118402497959018315224423868693918493033078310647199219674433536605771315869983788442389633 - sage: numerical_approx(gamma(9, 10^(-3)) - gamma(9), digits=40) # abs tol 1e-36 + sage: numerical_approx(gamma(9, 10^(-3)) - gamma(9), digits=40) # abs tol 1e-36 # needs sage.symbolic -1.110111598370794007949063502542063148294e-28 Check that :trac:`17328` is fixed:: - sage: gamma_inc(float(-1), float(-1)) + sage: gamma_inc(float(-1), float(-1)) # needs sage.rings.real_mpfr (-0.8231640121031085+3.141592653589793j) - sage: gamma_inc(RR(-1), RR(-1)) + sage: gamma_inc(RR(-1), RR(-1)) # needs sage.rings.complex_double -0.823164012103109 + 3.14159265358979*I - sage: gamma_inc(-1, float(-log(3))) - gamma_inc(-1, float(-log(2))) # abs tol 1e-15 + sage: gamma_inc(-1, float(-log(3))) - gamma_inc(-1, float(-log(2))) # abs tol 1e-15 # needs sage.symbolic (1.2730972164471142+0j) Check that :trac:`17130` is fixed:: - sage: r = gamma_inc(float(0), float(1)); r + sage: r = gamma_inc(float(0), float(1)); r # needs sage.rings.real_mpfr 0.21938393439552029 - sage: type(r) + sage: type(r) # needs sage.rings.real_mpfr <... 'float'> """ R = parent or s_parent(x) @@ -460,14 +481,14 @@ def _evalf_(self, x, y, parent=None, algorithm='pari'): if algorithm == 'pari': v = ComplexField(prec)(x).gamma_inc(y) else: - import mpmath - v = ComplexField(prec)(mpmath_utils.call(mpmath.gammainc, x, y, parent=R)) + v = ComplexField(prec)(_mpmath_utils_call(_mpmath_gammainc, x, y, parent=R)) if v.is_real(): return R(v) else: return C(v) -# synonym. + +# shorter alias gamma_inc = Function_gamma_inc() @@ -484,10 +505,12 @@ def __init__(self): EXAMPLES:: - sage: gamma_inc_lower(CDF(0,1), 3) + sage: gamma_inc_lower(CDF(0,1), 3) # needs sage.rings.complex_double -0.1581584032951798 - 0.5104218539302277*I - sage: gamma_inc_lower(RDF(1), 3) + sage: gamma_inc_lower(RDF(1), 3) # needs sage.rings.complex_double 0.950212931632136 + + sage: # needs sage.symbolic sage: gamma_inc_lower(3, 2, hold=True) gamma_inc_lower(3, 2) sage: gamma_inc_lower(3, 2) @@ -498,16 +521,17 @@ def __init__(self): \gamma\left(x, x\right) sage: loads(dumps((gamma_inc_lower(x, x)))) gamma_inc_lower(x, x) - sage: i = ComplexField(30).0; gamma_inc_lower(2, 1 + i) + + sage: i = ComplexField(30).0; gamma_inc_lower(2, 1 + i) # needs sage.rings.real_mpfr 0.29290790 + 0.42035364*I - sage: gamma_inc_lower(2., 5) + sage: gamma_inc_lower(2., 5) # needs sage.rings.complex_double 0.959572318005487 Interfaces to other software:: - sage: gamma_inc_lower(x,x)._sympy_() + sage: gamma_inc_lower(x, x)._sympy_() # needs sympy sage.symbolic lowergamma(x, x) - sage: maxima(gamma_inc_lower(x,x)) + sage: maxima(gamma_inc_lower(x, x)) # needs sage.symbolic gamma_incomplete_lower(_SAGE_VAR_x,_SAGE_VAR_x) .. SEEALSO:: @@ -522,33 +546,34 @@ def _eval_(self, x, y): """ EXAMPLES:: - sage: gamma_inc_lower(2.,0) + sage: gamma_inc_lower(2., 0) # needs sage.rings.complex_double 0.000000000000000 - sage: gamma_inc_lower(2,0) + + sage: # needs sage.symbolic + sage: gamma_inc_lower(2, 0) 0 - sage: gamma_inc_lower(1/2,2) + sage: gamma_inc_lower(1/2, 2) sqrt(pi)*erf(sqrt(2)) - sage: gamma_inc_lower(1/2,1) + sage: gamma_inc_lower(1/2, 1) sqrt(pi)*erf(1) - sage: gamma_inc_lower(1/2,0) + sage: gamma_inc_lower(1/2, 0) 0 - sage: gamma_inc_lower(x,0) + sage: gamma_inc_lower(x, 0) 0 - sage: gamma_inc_lower(1,2) + sage: gamma_inc_lower(1, 2) -e^(-2) + 1 - sage: gamma_inc_lower(0,2) + sage: gamma_inc_lower(0, 2) +Infinity - sage: gamma_inc_lower(2,377/79) + sage: gamma_inc_lower(2, 377/79) -456/79*e^(-377/79) + 1 - sage: gamma_inc_lower(3,x) + sage: gamma_inc_lower(3, x) -(x^2 + 2*x + 2)*e^(-x) + 2 - sage: gamma_inc_lower(9/2,37/7) + sage: gamma_inc_lower(9/2, 37/7) -1/38416*sqrt(pi)*(1672946*sqrt(259)*e^(-37/7)/sqrt(pi) - 252105*erf(1/7*sqrt(259))) """ if y == 0: return 0 if x == 0: - from sage.rings.infinity import Infinity return Infinity elif x == 1: return 1 - exp(-y) @@ -561,11 +586,11 @@ def _evalf_(self, x, y, parent=None, algorithm='mpmath'): """ EXAMPLES:: - sage: gamma_inc_lower(3,2.) + sage: gamma_inc_lower(3, 2.) # needs sage.rings.real_mpfr 0.646647167633873 - sage: gamma_inc_lower(3,2).n(200) + sage: gamma_inc_lower(3, 2).n(200) # needs sage.symbolic 0.646647167633873081060005050275155... - sage: gamma_inc_lower(0,2.) + sage: gamma_inc_lower(0, 2.) # needs sage.rings.real_mpfr +infinity """ R = parent or s_parent(x) @@ -587,18 +612,17 @@ def _evalf_(self, x, y, parent=None, algorithm='mpmath'): Cx = ComplexField(prec)(x) v = Cx.gamma() - Cx.gamma_inc(y) else: - import mpmath - v = ComplexField(prec)(mpmath_utils.call(mpmath.gammainc, x, 0, y, parent=R)) + v = ComplexField(prec)(_mpmath_utils_call(_mpmath_gammainc, x, 0, y, parent=R)) return R(v) if v.is_real() else C(v) def _derivative_(self, x, y, diff_param=None): """ EXAMPLES:: - sage: x,y = var('x,y') - sage: gamma_inc_lower(x,y).diff(y) + sage: x, y = var('x,y') # needs sage.symbolic + sage: gamma_inc_lower(x, y).diff(y) # needs sage.symbolic y^(x - 1)*e^(-y) - sage: gamma_inc_lower(x,y).diff(x) + sage: gamma_inc_lower(x, y).diff(x) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: cannot differentiate gamma_inc_lower in the first parameter @@ -613,7 +637,7 @@ def _mathematica_init_evaled_(self, *args): r""" EXAMPLES:: - sage: gamma_inc_lower(4/3, 1)._mathematica_() # indirect doctest, optional - mathematica + sage: gamma_inc_lower(4/3, 1)._mathematica_() # indirect doctest # optional - mathematica, needs sage.symbolic Gamma[4/3, 0, 1] """ args_mathematica = [] @@ -627,7 +651,8 @@ def _mathematica_init_evaled_(self, *args): x, z = args_mathematica return "Gamma[%s,0,%s]" % (x, z) -# synonym. + +# shorter alias gamma_inc_lower = Function_gamma_inc_lower() @@ -641,9 +666,9 @@ def gamma(a, *args, **kwds): True sage: gamma(6) 120 - sage: gamma(1/2) + sage: gamma(1/2) # needs sage.symbolic sqrt(pi) - sage: gamma(-4/3) + sage: gamma(-4/3) # needs sage.symbolic gamma(-4/3) sage: gamma(-1) Infinity @@ -652,47 +677,48 @@ def gamma(a, *args, **kwds): :: - sage: gamma_inc(3,2) + sage: gamma_inc(3, 2) # needs sage.symbolic gamma(3, 2) - sage: gamma_inc(x,0) + sage: gamma_inc(x,0) # needs sage.symbolic gamma(x) :: - sage: gamma(5, hold=True) + sage: gamma(5, hold=True) # needs sage.symbolic gamma(5) - sage: gamma(x, 0, hold=True) + sage: gamma(x, 0, hold=True) # needs sage.symbolic gamma(x, 0) :: - sage: gamma(CDF(I)) + sage: gamma(CDF(I)) # needs sage.libs.pari sage.symbolic -0.15494982830181067 - 0.49801566811835607*I - sage: gamma(CDF(0.5,14)) + sage: gamma(CDF(0.5, 14)) # needs sage.libs.pari -4.0537030780372815e-10 - 5.773299834553605e-10*I Use ``numerical_approx`` to get higher precision from symbolic expressions:: - sage: gamma(pi).n(100) + sage: gamma(pi).n(100) # needs sage.symbolic 2.2880377953400324179595889091 - sage: gamma(3/4).n(100) + sage: gamma(3/4).n(100) # needs sage.symbolic 1.2254167024651776451290983034 The precision for the result is also deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired.:: - sage: t = gamma(RealField(100)(2.5)); t + sage: t = gamma(RealField(100)(2.5)); t # needs sage.rings.real_mpfr 1.3293403881791370204736256125 - sage: t.prec() + sage: t.prec() # needs sage.rings.real_mpfr 100 The gamma function only works with input that can be coerced to the Symbolic Ring:: - sage: Q. = NumberField(x^2+1) - sage: gamma(i) + sage: x = polygen(ZZ, 'x') + sage: Q. = NumberField(x^2 + 1) # needs sage.rings.number_field + sage: gamma(i) # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... TypeError: cannot coerce arguments: no canonical coercion from Number Field in i with defining polynomial x^2 + 1 to Symbolic Ring @@ -727,6 +753,7 @@ def _mathematica_gamma3(*args): assert len(args) == 3 return gamma_inc(args[0], args[1]) - gamma_inc(args[0], args[2]) + register_symbol(_mathematica_gamma3, dict(mathematica='Gamma'), 3) @@ -743,37 +770,38 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.gamma import psi1 - sage: psi1(x) + sage: psi1(x) # needs sage.symbolic psi(x) - sage: psi1(x).derivative(x) + sage: psi1(x).derivative(x) # needs sage.symbolic psi(1, x) :: - sage: psi1(3) + sage: psi1(3) # needs sage.symbolic -euler_gamma + 3/2 :: - sage: psi(.5) + sage: psi(.5) # needs sage.symbolic -1.96351002602142 - sage: psi(RealField(100)(.5)) + sage: psi(RealField(100)(.5)) # needs sage.rings.real_mpfr sage.symbolic -1.9635100260214234794409763330 TESTS:: - sage: latex(psi1(x)) + sage: latex(psi1(x)) # needs sage.symbolic \psi\left(x\right) - sage: loads(dumps(psi1(x)+1)) + sage: loads(dumps(psi1(x) + 1)) # needs sage.symbolic psi(x) + 1 + sage: # needs sage.symbolic sage: t = psi1(x); t psi(x) sage: t.subs(x=.2) -5.28903989659219 - sage: psi(x)._sympy_() + sage: psi(x)._sympy_() # needs sympy polygamma(0, x) - sage: psi(x)._fricas_() # optional - fricas + sage: psi(x)._fricas_() # optional - fricas digamma(x) """ GinacFunction.__init__(self, "psi", nargs=1, latex_name=r'\psi', @@ -791,6 +819,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.gamma import psi2 sage: psi2(2, x) psi(2, x) @@ -802,39 +831,40 @@ def __init__(self): :: - sage: psi2(0, x) + sage: psi2(0, x) # needs sage.symbolic psi(x) - sage: psi2(-1, x) + sage: psi2(-1, x) # needs sage.symbolic log(gamma(x)) - sage: psi2(3, 1) + sage: psi2(3, 1) # needs sage.symbolic 1/15*pi^4 :: - sage: psi2(2, .5).n() + sage: psi2(2, .5).n() # needs sage.symbolic -16.8287966442343 - sage: psi2(2, .5).n(100) + sage: psi2(2, .5).n(100) # needs sage.symbolic -16.828796644234319995596334261 TESTS:: - sage: psi2(n, x).derivative(n) + sage: psi2(n, x).derivative(n) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: cannot diff psi(n,x) with respect to n + sage: # needs sage.symbolic sage: latex(psi2(2,x)) \psi\left(2, x\right) - sage: loads(dumps(psi2(2,x)+1)) + sage: loads(dumps(psi2(2,x) + 1)) psi(2, x) + 1 - sage: psi(2, x)._sympy_() + sage: psi(2, x)._sympy_() # needs sympy polygamma(2, x) - sage: psi(2, x)._fricas_() # optional - fricas + sage: psi(2, x)._fricas_() # optional - fricas polygamma(2,x) Fixed conversion:: - sage: psi(2,x)._maple_init_() + sage: psi(2, x)._maple_init_() # needs sage.symbolic 'Psi(2,x)' """ GinacFunction.__init__(self, "psi", nargs=2, latex_name=r'\psi', @@ -851,9 +881,9 @@ def _maxima_init_evaled_(self, *args): These are indirect doctests for this function.:: sage: from sage.functions.gamma import psi2 - sage: psi2(2, x)._maxima_() + sage: psi2(2, x)._maxima_() # needs sage.symbolic psi[2](_SAGE_VAR_x) - sage: psi2(4, x)._maxima_() + sage: psi2(4, x)._maxima_() # needs sage.symbolic psi[4](_SAGE_VAR_x) """ args_maxima = [] @@ -867,6 +897,7 @@ def _maxima_init_evaled_(self, *args): n, x = args_maxima return "psi[%s](%s)" % (n, x) + psi1 = Function_psi1() psi2 = Function_psi2() @@ -885,6 +916,7 @@ def psi(x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: psi(x) psi(x) sage: psi(.5) @@ -900,14 +932,14 @@ def psi(x, *args, **kwds): :: - sage: psi(3, hold=True) + sage: psi(3, hold=True) # needs sage.symbolic psi(3) - sage: psi(1, 5, hold=True) + sage: psi(1, 5, hold=True) # needs sage.symbolic psi(1, 5) TESTS:: - sage: psi(2, x, 3) + sage: psi(2, x, 3) # needs sage.symbolic Traceback (most recent call last): ... TypeError: Symbolic function psi takes at most 2 arguments (3 given) @@ -918,6 +950,7 @@ def psi(x, *args, **kwds): raise TypeError("Symbolic function psi takes at most 2 arguments (%s given)" % (len(args) + 1)) return psi2(x, args[0], **kwds) + # We have to add the wrapper function manually to the symbol_table when we have # two functions with different number of arguments and the same name symbol_table['functions']['psi'] = psi @@ -926,6 +959,7 @@ def psi(x, *args, **kwds): def _swap_psi(a, b): return psi(b, a) + register_symbol(_swap_psi, {'giac': 'Psi'}, 2) @@ -979,30 +1013,32 @@ def __init__(self): EXAMPLES:: - sage: beta(3,2) + sage: # needs sage.symbolic + sage: beta(3, 2) 1/12 sage: beta(3,1) 1/3 - sage: beta(1/2,1/2) + sage: beta(1/2, 1/2) beta(1/2, 1/2) sage: beta(-1,1) -1 sage: beta(-1/2,-1/2) 0 - sage: ex = beta(x/2,3) + sage: ex = beta(x/2, 3) sage: set(ex.operands()) == set([1/2*x, 3]) True sage: beta(.5,.5) 3.14159265358979 - sage: beta(1,2.0+I) + sage: beta(1, 2.0+I) 0.400000000000000 - 0.200000000000000*I - sage: ex = beta(3,x+I) + sage: ex = beta(3, x+I) sage: set(ex.operands()) == set([x+I, 3]) True The result is symbolic if exact input is given:: - sage: ex = beta(2,1+5*I); ex + sage: # needs sage.symbolic + sage: ex = beta(2, 1+5*I); ex beta(... sage: set(ex.operands()) == set([1+5*I, 2]) True @@ -1015,7 +1051,7 @@ def __init__(self): sage: beta(2., I) -0.500000000000000 - 0.500000000000000*I - sage: beta(x, x)._sympy_() + sage: beta(x, x)._sympy_() # needs sympy sage.symbolic beta(x, x) Test pickling:: @@ -1025,7 +1061,7 @@ def __init__(self): Check that :trac:`15196` is fixed:: - sage: beta(-1.3,-0.4) + sage: beta(-1.3, -0.4) # needs sage.symbolic -4.92909641669610 """ GinacFunction.__init__(self, 'beta', nargs=2, @@ -1041,9 +1077,10 @@ def _method_arguments(self, x, y): r""" TESTS:: - sage: RBF(beta(sin(3),sqrt(RBF(2).add_error(1e-8)/3))) # abs tol 6e-7 + sage: RBF(beta(sin(3), sqrt(RBF(2).add_error(1e-8)/3))) # abs tol 6e-7 # needs sage.libs.flint sage.symbolic [7.407662 +/- 6.17e-7] """ return [x, y] + beta = Function_beta() diff --git a/src/sage/functions/generalized.py b/src/sage/functions/generalized.py index d912ea23719..3d58d4d9d0a 100644 --- a/src/sage/functions/generalized.py +++ b/src/sage/functions/generalized.py @@ -16,28 +16,28 @@ Dirac delta function:: - sage: dirac_delta(x) + sage: dirac_delta(x) # needs sage.symbolic dirac_delta(x) Heaviside step function:: - sage: heaviside(x) + sage: heaviside(x) # needs sage.symbolic heaviside(x) Unit step function:: - sage: unit_step(x) + sage: unit_step(x) # needs sage.symbolic unit_step(x) Signum (sgn) function:: - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) Kronecker delta function:: - sage: m,n=var('m,n') - sage: kronecker_delta(m,n) + sage: m, n = var('m,n') # needs sage.symbolic + sage: kronecker_delta(m, n) # needs sage.symbolic kronecker_delta(m, n) """ @@ -51,9 +51,12 @@ # ############################################################################## -from sage.symbolic.function import (BuiltinFunction, GinacFunction) -from sage.rings.complex_interval_field import ComplexIntervalField +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ +from sage.symbolic.function import BuiltinFunction, GinacFunction + +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.complex_interval_field', 'ComplexIntervalField') class FunctionDiracDelta(BuiltinFunction): @@ -78,13 +81,14 @@ class FunctionDiracDelta(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: dirac_delta(1) 0 sage: dirac_delta(0) dirac_delta(0) sage: dirac_delta(x) dirac_delta(x) - sage: integrate(dirac_delta(x), x, -1, 1, algorithm='sympy') + sage: integrate(dirac_delta(x), x, -1, 1, algorithm='sympy') # needs sympy 1 REFERENCES: @@ -102,6 +106,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: dirac_delta(1) 0 sage: dirac_delta(0) @@ -111,9 +116,9 @@ def __init__(self): sage: latex(dirac_delta(x)) \delta\left(x\right) - sage: loads(dumps(dirac_delta(x))) + sage: loads(dumps(dirac_delta(x))) # needs sage.symbolic dirac_delta(x) - sage: dirac_delta(x)._sympy_() + sage: dirac_delta(x)._sympy_() # needs sympy sage.symbolic DiracDelta(x) """ BuiltinFunction.__init__(self, "dirac_delta", latex_name=r"\delta", @@ -130,6 +135,7 @@ def _eval_(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: dirac_delta(1) 0 sage: dirac_delta(0) @@ -141,7 +147,7 @@ def _eval_(self, x): Evaluation test:: - sage: dirac_delta(x).subs(x=1) + sage: dirac_delta(x).subs(x=1) # needs sage.symbolic 0 """ try: @@ -154,8 +160,8 @@ def _evalf_(self, x, **kwds): """ TESTS:: - sage: h(x) = dirac_delta(x) - sage: h(pi).numerical_approx() + sage: h(x) = dirac_delta(x) # needs sage.symbolic + sage: h(pi).numerical_approx() # needs sage.symbolic 0.000000000000000 """ approx_x = ComplexIntervalField()(x) @@ -188,6 +194,7 @@ class FunctionHeaviside(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: heaviside(-1) 0 sage: heaviside(1) @@ -197,23 +204,24 @@ class FunctionHeaviside(GinacFunction): sage: heaviside(x) heaviside(x) - sage: heaviside(-1/2) + sage: heaviside(-1/2) # needs sage.symbolic 0 - sage: heaviside(exp(-1000000000000000000000)) + sage: heaviside(exp(-1000000000000000000000)) # needs sage.symbolic 1 TESTS:: - sage: heaviside(x)._sympy_() + sage: heaviside(x)._sympy_() # needs sympy sage.symbolic Heaviside(x) - sage: heaviside(x).subs(x=1) + sage: heaviside(x).subs(x=1) # needs sage.symbolic 1 - sage: heaviside(x).subs(x=-1) + sage: heaviside(x).subs(x=-1) # needs sage.symbolic 0 :: - sage: ex = heaviside(x)+1 + sage: # needs sage.symbolic + sage: ex = heaviside(x) + 1 sage: t = loads(dumps(ex)); t heaviside(x) + 1 sage: bool(t == ex) @@ -236,6 +244,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: heaviside(-1) 0 sage: heaviside(1) @@ -246,9 +255,9 @@ def __init__(self): heaviside(x) sage: latex(heaviside(x)) H\left(x\right) - sage: heaviside(x)._sympy_() + sage: heaviside(x)._sympy_() # needs sympy Heaviside(x) - sage: heaviside(x)._giac_() + sage: heaviside(x)._giac_() # needs sage.libs.giac Heaviside(sageVARx) sage: h(x) = heaviside(x) sage: h(pi).numerical_approx() @@ -266,7 +275,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: heaviside(x).diff(x) + sage: heaviside(x).diff(x) # needs sage.symbolic dirac_delta(x) """ return dirac_delta(x) @@ -293,6 +302,7 @@ class FunctionUnitStep(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: unit_step(-1) 0 sage: unit_step(1) @@ -306,6 +316,7 @@ class FunctionUnitStep(GinacFunction): TESTS:: + sage: # needs sage.symbolic sage: unit_step(x).subs(x=1) 1 sage: unit_step(x).subs(x=0) @@ -324,6 +335,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: unit_step(-1) 0 sage: unit_step(1) @@ -337,9 +349,9 @@ def __init__(self): TESTS:: - sage: t = loads(dumps(unit_step(x)+1)); t + sage: t = loads(dumps(unit_step(x) + 1)); t # needs sage.symbolic unit_step(x) + 1 - sage: t.subs(x=0) + sage: t.subs(x=0) # needs sage.symbolic 2 """ GinacFunction.__init__(self, "unit_step", latex_name=r"\mathrm{u}", @@ -351,7 +363,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: unit_step(x).diff(x) + sage: unit_step(x).diff(x) # needs sage.symbolic dirac_delta(x) """ return dirac_delta(x) @@ -384,7 +396,7 @@ class FunctionSignum(BuiltinFunction): 1 sage: sgn(0) 0 - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) We can also use ``sign``:: @@ -393,24 +405,24 @@ class FunctionSignum(BuiltinFunction): 1 sage: sign(0) 0 - sage: a = AA(-5).nth_root(7) - sage: sign(a) + sage: a = AA(-5).nth_root(7) # needs sage.rings.number_field + sage: sign(a) # needs sage.rings.number_field -1 TESTS: Check if conversions to sympy and others work (:trac:`11921`):: - sage: sgn(x)._sympy_() + sage: sgn(x)._sympy_() # needs sympy sage.symbolic sign(x) - sage: sgn(x)._fricas_init_() + sage: sgn(x)._fricas_init_() # needs sage.symbolic '(x+->abs(x)/x)(x)' - sage: sgn(x)._giac_() + sage: sgn(x)._giac_() # needs sage.libs.giac sage.symbolic sign(sageVARx) Test for :trac:`31085`:: - sage: fricas(sign(x)).eval(x=-3) # optional - fricas + sage: fricas(sign(x)).eval(x=-3) # optional - fricas # needs sage.symbolic - 1 REFERENCES: @@ -430,9 +442,9 @@ def __init__(self): 1 sage: sgn(0) 0 - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) - sage: sgn(x)._sympy_() + sage: sgn(x)._sympy_() # needs sympy sage.symbolic sign(x) """ BuiltinFunction.__init__(self, "sgn", latex_name=r"\mathrm{sgn}", @@ -452,18 +464,18 @@ def _eval_(self, x): 1 sage: sgn(0) 0 - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) - sage: sgn(-exp(-10000000000000000000)) + sage: sgn(-exp(-10000000000000000000)) # needs sage.symbolic -1 Evaluation test:: - sage: sgn(x).subs(x=1) + sage: sgn(x).subs(x=1) # needs sage.symbolic 1 - sage: sgn(x).subs(x=0) + sage: sgn(x).subs(x=0) # needs sage.symbolic 0 - sage: sgn(x).subs(x=-1) + sage: sgn(x).subs(x=-1) # needs sage.symbolic -1 More tests:: @@ -472,9 +484,9 @@ def _eval_(self, x): 1 sage: sign(RDF(2)) 1 - sage: sign(AA(-2)) + sage: sign(AA(-2)) # needs sage.rings.number_field -1 - sage: sign(AA(0)) + sage: sign(AA(0)) # needs sage.rings.number_field 0 """ try: @@ -489,6 +501,7 @@ def _evalf_(self, x, **kwds): Check that :trac:`16587` is fixed:: + sage: # needs sage.symbolic sage: M = sgn(3/2, hold=True); M sgn(3/2) sage: M.n() @@ -518,7 +531,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: sgn(x).diff(x) + sage: sgn(x).diff(x) # needs sage.symbolic 2*dirac_delta(x) """ assert diff_param == 0 @@ -547,12 +560,12 @@ class FunctionKroneckerDelta(BuiltinFunction): EXAMPLES:: - sage: kronecker_delta(1,2) + sage: kronecker_delta(1,2) # needs sage.rings.complex_interval_field 0 - sage: kronecker_delta(1,1) + sage: kronecker_delta(1,1) # needs sage.rings.complex_interval_field 1 - sage: m,n=var('m,n') - sage: kronecker_delta(m,n) + sage: m, n = var('m,n') # needs sage.symbolic + sage: kronecker_delta(m, n) # needs sage.symbolic kronecker_delta(m, n) REFERENCES: @@ -566,12 +579,12 @@ def __init__(self): EXAMPLES:: - sage: kronecker_delta(1,2) + sage: kronecker_delta(1,2) # needs sage.rings.complex_interval_field 0 - sage: kronecker_delta(1,1) + sage: kronecker_delta(1,1) # needs sage.rings.complex_interval_field 1 - sage: y = var('y') - sage: kronecker_delta(x, y)._sympy_() + sage: y = var('y') # needs sage.symbolic + sage: kronecker_delta(x, y)._sympy_() # needs sympy sage.symbolic KroneckerDelta(x, y) """ BuiltinFunction.__init__(self, "kronecker_delta", nargs=2, @@ -585,25 +598,26 @@ def _eval_(self, m, n): EXAMPLES:: - sage: kronecker_delta(1,2) + sage: kronecker_delta(1,2) # needs sage.rings.complex_interval_field 0 - sage: kronecker_delta(1,1) + sage: kronecker_delta(1,1) # needs sage.rings.complex_interval_field 1 Kronecker delta is a symmetric function. We keep arguments sorted to ensure that k_d(m, n) - k_d(n, m) cancels automatically:: - sage: x,y = var('x,y') + sage: # needs sage.symbolic + sage: x, y = var('x,y') sage: kronecker_delta(x, y) kronecker_delta(x, y) sage: kronecker_delta(y, x) kronecker_delta(x, y) - sage: kronecker_delta(x,2*x) + sage: kronecker_delta(x, 2*x) kronecker_delta(2*x, x) Evaluation test:: - sage: kronecker_delta(1,x).subs(x=1) + sage: kronecker_delta(1, x).subs(x=1) # needs sage.symbolic 1 """ try: @@ -616,8 +630,8 @@ def _evalf_(self, m, n, **kwds): """ TESTS:: - sage: h(x) = kronecker_delta(3,x) - sage: h(pi).numerical_approx() + sage: h(x) = kronecker_delta(3, x) # needs sage.symbolic + sage: h(pi).numerical_approx() # needs sage.symbolic 0.000000000000000 """ if bool(repr(m) > repr(n)): @@ -637,7 +651,7 @@ def _derivative_(self, *args, **kwds): EXAMPLES:: - sage: kronecker_delta(x,1).diff(x) + sage: kronecker_delta(x, 1).diff(x) # needs sage.symbolic 0 """ # Kronecker delta is non-zero (but finite) only in the set of @@ -653,11 +667,10 @@ def _print_latex_(self, m, n, **kwds): EXAMPLES:: sage: from sage.misc.latex import latex - sage: m,n=var('m,n') - sage: latex(kronecker_delta(m,n)) + sage: m, n = var('m,n') # needs sage.symbolic + sage: latex(kronecker_delta(m, n)) # needs sage.symbolic \delta_{m,n} """ - from sage.misc.latex import latex return r"\delta_{%s,%s}" % (latex(m), latex(n)) diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py index 9a362b8882f..6c70caef310 100644 --- a/src/sage/functions/hyperbolic.py +++ b/src/sage/functions/hyperbolic.py @@ -28,16 +28,15 @@ Inverse hyperbolic functions have logarithmic expressions, so expressions of the form ``exp(c*f(x))`` simplify:: + sage: # needs sage.symbolic sage: exp(2*atanh(x)) -(x + 1)/(x - 1) sage: exp(2*acoth(x)) (x + 1)/(x - 1) - sage: exp(2*asinh(x)) (x + sqrt(x^2 + 1))^2 sage: exp(2*acosh(x)) (x + sqrt(x^2 - 1))^2 - sage: exp(2*asech(x)) (sqrt(-x^2 + 1)/x + 1/x)^2 sage: exp(2*acsch(x)) @@ -54,28 +53,29 @@ def __init__(self): EXAMPLES:: - sage: sinh(pi) - sinh(pi) sage: sinh(3.1415) 11.5476653707437 + + sage: # needs sage.symbolic + sage: sinh(pi) + sinh(pi) sage: float(sinh(pi)) 11.54873935725774... sage: RR(sinh(pi)) 11.5487393572577 - sage: latex(sinh(x)) \sinh\left(x\right) - sage: sinh(x)._sympy_() + sage: sinh(x)._sympy_() # needs sympy sinh(x) To prevent automatic evaluation, use the ``hold`` parameter:: - sage: sinh(arccosh(x),hold=True) + sage: sinh(arccosh(x), hold=True) # needs sage.symbolic sinh(arccosh(x)) To then evaluate again, use the ``unhold`` method:: - sage: sinh(arccosh(x),hold=True).unhold() + sage: sinh(arccosh(x), hold=True).unhold() # needs sage.symbolic sqrt(x + 1)*sqrt(x - 1) """ GinacFunction.__init__(self, "sinh", latex_name=r"\sinh") @@ -91,28 +91,29 @@ def __init__(self): EXAMPLES:: - sage: cosh(pi) - cosh(pi) sage: cosh(3.1415) 11.5908832931176 + + sage: # needs sage.symbolic + sage: cosh(pi) + cosh(pi) sage: float(cosh(pi)) 11.591953275521519 sage: RR(cosh(1/2)) 1.12762596520638 - sage: latex(cosh(x)) \cosh\left(x\right) - sage: cosh(x)._sympy_() + sage: cosh(x)._sympy_() # needs sympy cosh(x) To prevent automatic evaluation, use the ``hold`` parameter:: - sage: cosh(arcsinh(x),hold=True) + sage: cosh(arcsinh(x), hold=True) # needs sage.symbolic cosh(arcsinh(x)) To then evaluate again, use the ``unhold`` method:: - sage: cosh(arcsinh(x),hold=True).unhold() + sage: cosh(arcsinh(x), hold=True).unhold() # needs sage.symbolic sqrt(x^2 + 1) """ GinacFunction.__init__(self, "cosh", latex_name=r"\cosh") @@ -128,14 +129,16 @@ def __init__(self): EXAMPLES:: - sage: tanh(pi) - tanh(pi) sage: tanh(3.1415) 0.996271386633702 - sage: float(tanh(pi)) - 0.99627207622075 sage: tan(3.1415/4) 0.999953674278156 + + sage: # needs sage.symbolic + sage: tanh(pi) + tanh(pi) + sage: float(tanh(pi)) + 0.99627207622075 sage: tanh(pi/4) tanh(1/4*pi) sage: RR(tanh(1/2)) @@ -143,32 +146,33 @@ def __init__(self): :: - sage: CC(tanh(pi + I*e)) + sage: CC(tanh(pi + I*e)) # needs sage.rings.real_mpfr sage.symbolic 0.997524731976164 - 0.00279068768100315*I - sage: ComplexField(100)(tanh(pi + I*e)) + sage: ComplexField(100)(tanh(pi + I*e)) # needs sage.rings.real_mpfr sage.symbolic 0.99752473197616361034204366446 - 0.0027906876810031453884245163923*I - sage: CDF(tanh(pi + I*e)) # rel tol 2e-15 + sage: CDF(tanh(pi + I*e)) # rel tol 2e-15 # needs sage.rings.complex_double sage.symbolic 0.9975247319761636 - 0.002790687681003147*I To prevent automatic evaluation, use the ``hold`` parameter:: - sage: tanh(arcsinh(x),hold=True) + sage: tanh(arcsinh(x), hold=True) # needs sage.symbolic tanh(arcsinh(x)) To then evaluate again, use the ``unhold`` method:: - sage: tanh(arcsinh(x),hold=True).unhold() + sage: tanh(arcsinh(x), hold=True).unhold() # needs sage.symbolic x/sqrt(x^2 + 1) TESTS:: - sage: latex(tanh(x)) + sage: latex(tanh(x)) # needs sage.symbolic \tanh\left(x\right) - sage: tanh(x)._sympy_() + sage: tanh(x)._sympy_() # needs sympy sage.symbolic tanh(x) Check that real/imaginary parts are correct (:trac:`20098`):: + sage: # needs sage.symbolic sage: tanh(1+2*I).n() 1.16673625724092 - 0.243458201185725*I sage: tanh(1+2*I).real().n() @@ -193,6 +197,12 @@ def __init__(self): EXAMPLES:: + sage: coth(3.1415) + 1.00374256795520 + sage: coth(complex(1, 2)) # abs tol 1e-15 # needs sage.rings.complex_double + (0.8213297974938518+0.17138361290918508j) + + sage: # needs sage.symbolic sage: coth(pi) coth(pi) sage: coth(0) @@ -207,22 +217,19 @@ def __init__(self): Infinity sage: coth(7.*pi*I/2) -I*cot(3.50000000000000*pi) - sage: coth(3.1415) - 1.00374256795520 sage: float(coth(pi)) 1.0037418731973213 sage: RR(coth(pi)) 1.00374187319732 - sage: coth(complex(1, 2)) # abs tol 1e-15 - (0.8213297974938518+0.17138361290918508j) + sage: # needs sage.symbolic sage: bool(diff(coth(x), x) == diff(1/tanh(x), x)) True sage: diff(coth(x), x) -1/sinh(x)^2 sage: latex(coth(x)) \coth\left(x\right) - sage: coth(x)._sympy_() + sage: coth(x)._sympy_() # needs sympy coth(x) """ GinacFunction.__init__(self, "coth", latex_name=r"\coth") @@ -231,9 +238,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: coth(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: coth(a) # needs numpy array([1.03731472, 1.00496982, 1.00067115]) """ return 1.0 / tanh(x) @@ -249,10 +256,12 @@ def __init__(self): EXAMPLES:: - sage: sech(pi) - sech(pi) sage: sech(3.1415) 0.0862747018248192 + + sage: # needs sage.symbolic + sage: sech(pi) + sech(pi) sage: float(sech(pi)) 0.0862667383340544... sage: RR(sech(pi)) @@ -270,13 +279,14 @@ def __init__(self): sage: sech(8.*pi*I/2) sec(4.00000000000000*pi) + sage: # needs sage.symbolic sage: bool(diff(sech(x), x) == diff(1/cosh(x), x)) True sage: diff(sech(x), x) -sech(x)*tanh(x) sage: latex(sech(x)) \operatorname{sech}\left(x\right) - sage: sech(x)._sympy_() + sage: sech(x)._sympy_() # needs sympy sech(x) """ GinacFunction.__init__(self, "sech", latex_name=r"\operatorname{sech}",) @@ -285,9 +295,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: sech(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: sech(a) # needs numpy array([0.26580223, 0.09932793, 0.03661899]) """ return 1.0 / cosh(x) @@ -303,10 +313,12 @@ def __init__(self): EXAMPLES:: - sage: csch(pi) - csch(pi) sage: csch(3.1415) 0.0865975907592133 + + sage: # needs sage.symbolic + sage: csch(pi) + csch(pi) sage: float(csch(pi)) 0.0865895375300469... sage: RR(csch(pi)) @@ -322,13 +334,14 @@ def __init__(self): sage: csch(7.*pi*I/2) -I*csc(3.50000000000000*pi) + sage: # needs sage.symbolic sage: bool(diff(csch(x), x) == diff(1/sinh(x), x)) True sage: diff(csch(x), x) -coth(x)*csch(x) sage: latex(csch(x)) \operatorname{csch}\left(x\right) - sage: csch(x)._sympy_() + sage: csch(x)._sympy_() # needs sympy csch(x) """ GinacFunction.__init__(self, "csch", latex_name=r"\operatorname{csch}") @@ -337,9 +350,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: csch(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: csch(a) # needs numpy array([0.27572056, 0.09982157, 0.03664357]) """ return 1.0 / sinh(x) @@ -364,24 +377,25 @@ def __init__(self): arcsinh sage: asinh(0.5) 0.481211825059603 - sage: asinh(1/2) + sage: asinh(1/2) # needs sage.symbolic arcsinh(1/2) - sage: asinh(1 + I*1.0) + sage: asinh(1 + I*1.0) # needs sage.symbolic 1.06127506190504 + 0.666239432492515*I To prevent automatic evaluation use the ``hold`` argument:: - sage: asinh(-2,hold=True) + sage: asinh(-2, hold=True) # needs sage.symbolic arcsinh(-2) To then evaluate again, use the ``unhold`` method:: - sage: asinh(-2,hold=True).unhold() + sage: asinh(-2, hold=True).unhold() # needs sage.symbolic -arcsinh(2) ``conjugate(asinh(x))==asinh(conjugate(x))`` unless on the branch cuts which run along the imaginary axis outside the interval [-I, +I].:: + sage: # needs sage.symbolic sage: conjugate(asinh(x)) conjugate(arcsinh(x)) sage: var('y', domain='positive') @@ -399,11 +413,11 @@ def __init__(self): TESTS:: - sage: asinh(x).operator() + sage: asinh(x).operator() # needs sage.symbolic arcsinh - sage: latex(asinh(x)) + sage: latex(asinh(x)) # needs sage.symbolic \operatorname{arsinh}\left(x\right) - sage: asinh(x)._sympy_() + sage: asinh(x)._sympy_() # needs sympy sage.symbolic asinh(x) """ GinacFunction.__init__(self, "arcsinh", @@ -422,6 +436,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: acosh(1/2) arccosh(1/2) sage: acosh(1 + I*1.0) @@ -430,7 +445,8 @@ def __init__(self): 1.3169578969248168 sage: cosh(float(acosh(2))) 2.0 - sage: acosh(complex(1, 2)) # abs tol 1e-15 + + sage: acosh(complex(1, 2)) # abs tol 1e-15 # needs sage.rings.complex_double (1.5285709194809982+1.1437177404024204j) .. warning:: @@ -442,14 +458,16 @@ def __init__(self): :: + sage: acosh(CC(0.5)) # needs sage.rings.real_mpfr + 1.04719755119660*I + + sage: # needs sage.symbolic sage: acosh(0.5) NaN sage: acosh(1/2) arccosh(1/2) sage: acosh(1/2).n() NaN - sage: acosh(CC(0.5)) - 1.04719755119660*I sage: acosh(0) 1/2*I*pi sage: acosh(-1) @@ -457,17 +475,18 @@ def __init__(self): To prevent automatic evaluation use the ``hold`` argument:: - sage: acosh(-1,hold=True) + sage: acosh(-1, hold=True) # needs sage.symbolic arccosh(-1) To then evaluate again, use the ``unhold`` method:: - sage: acosh(-1,hold=True).unhold() + sage: acosh(-1, hold=True).unhold() # needs sage.symbolic I*pi ``conjugate(arccosh(x))==arccosh(conjugate(x))`` unless on the branch cut which runs along the real axis from +1 to -inf.:: + sage: # needs sage.symbolic sage: conjugate(acosh(x)) conjugate(arccosh(x)) sage: var('y', domain='positive') @@ -485,11 +504,11 @@ def __init__(self): TESTS:: - sage: acosh(x).operator() + sage: acosh(x).operator() # needs sage.symbolic arccosh - sage: latex(acosh(x)) + sage: latex(acosh(x)) # needs sage.symbolic \operatorname{arcosh}\left(x\right) - sage: acosh(x)._sympy_() + sage: acosh(x)._sympy_() # needs sympy sage.symbolic acosh(x) """ GinacFunction.__init__(self, "arccosh", @@ -510,31 +529,32 @@ def __init__(self): sage: atanh(0.5) 0.549306144334055 - sage: atanh(1/2) + sage: atanh(1/2) # needs sage.symbolic 1/2*log(3) - sage: atanh(1 + I*1.0) + sage: atanh(1 + I*1.0) # needs sage.symbolic 0.402359478108525 + 1.01722196789785*I To prevent automatic evaluation use the ``hold`` argument:: - sage: atanh(-1/2,hold=True) + sage: atanh(-1/2, hold=True) # needs sage.symbolic arctanh(-1/2) To then evaluate again, use the ``unhold`` method:: - sage: atanh(-1/2,hold=True).unhold() + sage: atanh(-1/2, hold=True).unhold() # needs sage.symbolic -1/2*log(3) ``conjugate(arctanh(x)) == arctanh(conjugate(x))`` unless on the branch cuts which run along the real axis outside the interval [-1, +1]. :: + sage: # needs sage.symbolic sage: conjugate(atanh(x)) conjugate(arctanh(x)) sage: var('y', domain='positive') y sage: conjugate(atanh(y)) conjugate(arctanh(y)) - sage: conjugate(atanh(y+I)) + sage: conjugate(atanh(y + I)) conjugate(arctanh(y + I)) sage: conjugate(atanh(1/16)) 1/2*log(17/15) @@ -545,11 +565,11 @@ def __init__(self): TESTS:: - sage: atanh(x).operator() + sage: atanh(x).operator() # needs sage.symbolic arctanh - sage: latex(atanh(x)) + sage: latex(atanh(x)) # needs sage.symbolic \operatorname{artanh}\left(x\right) - sage: atanh(x)._sympy_() + sage: atanh(x)._sympy_() # needs sympy sage.symbolic atanh(x) """ GinacFunction.__init__(self, "arctanh", @@ -568,6 +588,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: acoth(2.0) 0.549306144334055 sage: acoth(2) @@ -577,28 +598,28 @@ def __init__(self): sage: acoth(2).n(200) 0.54930614433405484569762261846126285232374527891137472586735 - sage: bool(diff(acoth(x), x) == diff(atanh(x), x)) + sage: bool(diff(acoth(x), x) == diff(atanh(x), x)) # needs sage.symbolic True - sage: diff(acoth(x), x) + sage: diff(acoth(x), x) # needs sage.symbolic -1/(x^2 - 1) - sage: float(acoth(2)) + sage: float(acoth(2)) # needs sage.symbolic 0.5493061443340549 - sage: float(acoth(2).n(53)) # Correct result to 53 bits + sage: float(acoth(2).n(53)) # Correct result to 53 bits # needs sage.rings.real_mpfr sage.symbolic 0.5493061443340549 - sage: float(acoth(2).n(100)) # Compute 100 bits and then round to 53 + sage: float(acoth(2).n(100)) # Compute 100 bits and then round to 53 # needs sage.rings.real_mpfr sage.symbolic 0.5493061443340549 TESTS:: - sage: latex(acoth(x)) + sage: latex(acoth(x)) # needs sage.symbolic \operatorname{arcoth}\left(x\right) - sage: acoth(x)._sympy_() + sage: acoth(x)._sympy_() # needs sympy sage.symbolic acoth(x) Check that :trac:`23636` is fixed:: - sage: acoth(float(1.1)) + sage: acoth(float(1.1)) # needs sage.symbolic 1.5222612188617113 """ GinacFunction.__init__(self, "arccoth", @@ -611,9 +632,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2,5) - sage: acoth(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2,5) # needs numpy + sage: acoth(a) # needs numpy array([0.54930614, 0.34657359, 0.25541281]) """ return arctanh(1.0 / x) @@ -629,6 +650,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: asech(0.5) 1.31695789692482 sage: asech(1/2) @@ -640,11 +662,11 @@ def __init__(self): sage: float(asech(1/2)) 1.3169578969248168 - sage: diff(asech(x), x) + sage: diff(asech(x), x) # needs sage.symbolic -1/(sqrt(-x^2 + 1)*x) - sage: latex(asech(x)) + sage: latex(asech(x)) # needs sage.symbolic \operatorname{arsech}\left(x\right) - sage: asech(x)._sympy_() + sage: asech(x)._sympy_() # needs sympy sage.symbolic asech(x) """ GinacFunction.__init__(self, "arcsech", @@ -657,9 +679,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.linspace(0,1,3) - sage: asech(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,1,3) # needs numpy + sage: asech(a) # needs numpy doctest:...: RuntimeWarning: divide by zero encountered in ...divide array([ inf, 1.3169579, 0. ]) """ @@ -676,6 +698,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: acsch(2.0) 0.481211825059603 sage: acsch(2) @@ -687,18 +710,18 @@ def __init__(self): sage: float(acsch(1)) 0.881373587019543 - sage: diff(acsch(x), x) + sage: diff(acsch(x), x) # needs sage.symbolic -1/(sqrt(x^2 + 1)*x) - sage: latex(acsch(x)) + sage: latex(acsch(x)) # needs sage.symbolic \operatorname{arcsch}\left(x\right) TESTS: Check that :trac:`20818` is fixed:: - sage: acsch(float(0.1)) + sage: acsch(float(0.1)) # needs sage.symbolic 2.99822295029797 - sage: acsch(x)._sympy_() + sage: acsch(x)._sympy_() # needs sympy sage.symbolic acsch(x) """ GinacFunction.__init__(self, "arccsch", @@ -711,9 +734,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.linspace(0,1,3) - sage: acsch(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,1,3) # needs numpy + sage: acsch(a) # needs numpy doctest:...: RuntimeWarning: divide by zero encountered in ...divide array([ inf, 1.44363548, 0.88137359]) """ diff --git a/src/sage/functions/hypergeometric.py b/src/sage/functions/hypergeometric.py index fc2fb5875ce..1c2712382f3 100644 --- a/src/sage/functions/hypergeometric.py +++ b/src/sage/functions/hypergeometric.py @@ -49,6 +49,7 @@ Computing terms and series:: + sage: # needs sage.symbolic sage: var('z') z sage: hypergeometric([], [], z).series(z, 0) @@ -60,6 +61,7 @@ sage: hypergeometric([], [], z).series(z, 3) 1 + 1*z + 1/2*z^2 + Order(z^3) + sage: # needs sage.symbolic sage: hypergeometric([-2], [], z).series(z, 3) 1 + (-2)*z + 1*z^2 sage: hypergeometric([-2], [], z).series(z, 6) @@ -71,26 +73,27 @@ sage: hypergeometric([-2], [], z).series(z, 2).is_terminating_series() False - sage: hypergeometric([1], [], z).series(z, 6) + sage: hypergeometric([1], [], z).series(z, 6) # needs sage.symbolic 1 + 1*z + 1*z^2 + 1*z^3 + 1*z^4 + 1*z^5 + Order(z^6) - sage: hypergeometric([], [1/2], -z^2/4).series(z, 11) + sage: hypergeometric([], [1/2], -z^2/4).series(z, 11) # needs sage.symbolic 1 + (-1/2)*z^2 + 1/24*z^4 + (-1/720)*z^6 + 1/40320*z^8 +... (-1/3628800)*z^10 + Order(z^11) sage: hypergeometric([1], [5], x).series(x, 5) 1 + 1/5*x + 1/30*x^2 + 1/210*x^3 + 1/1680*x^4 + Order(x^5) - sage: sum(hypergeometric([1, 2], [3], 1/3).terms(6)).n() + sage: sum(hypergeometric([1, 2], [3], 1/3).terms(6)).n() # needs sage.symbolic 1.29788359788360 - sage: hypergeometric([1, 2], [3], 1/3).n() + sage: hypergeometric([1, 2], [3], 1/3).n() # needs sage.symbolic 1.29837194594696 sage: hypergeometric([], [], x).series(x, 20)(x=1).n() == e.n() True Plotting:: + sage: # needs sage.symbolic sage: f(x) = hypergeometric([1, 1], [3, 3, 3], x) - sage: plot(f, x, -30, 30) + sage: plot(f, x, -30, 30) # needs sage.plot Graphics object consisting of 1 graphics primitive sage: g(x) = hypergeometric([x], [], 2) sage: complex_plot(g, (-1, 1), (-1, 1)) @@ -98,6 +101,7 @@ Numeric evaluation:: + sage: # needs sage.symbolic sage: hypergeometric([1], [], 1/10).n() # geometric series 1.11111111111111 sage: hypergeometric([], [], 1).n() # e @@ -115,42 +119,42 @@ Conversions:: - sage: maxima(hypergeometric([1, 1, 1], [3, 3, 3], x)) + sage: maxima(hypergeometric([1, 1, 1], [3, 3, 3], x)) # needs sage.symbolic hypergeometric([1,1,1],[3,3,3],_SAGE_VAR_x) - sage: hypergeometric((5, 4), (4, 4), 3)._sympy_() + sage: hypergeometric((5, 4), (4, 4), 3)._sympy_() # needs sage.symbolic hyper((5, 4), (4, 4), 3) - sage: hypergeometric((5, 4), (4, 4), 3)._mathematica_init_() + sage: hypergeometric((5, 4), (4, 4), 3)._mathematica_init_() # needs sage.symbolic 'HypergeometricPFQ[{5,4},{4,4},3]' Arbitrary level of nesting for conversions:: - sage: maxima(nest(lambda y: hypergeometric([y], [], x), 3, 1)) + sage: maxima(nest(lambda y: hypergeometric([y], [], x), 3, 1)) # needs sage.symbolic 1/(1-_SAGE_VAR_x)^(1/(1-_SAGE_VAR_x)^(1/(1-_SAGE_VAR_x))) - sage: maxima(nest(lambda y: hypergeometric([y], [3], x), 3, 1))._sage_() + sage: maxima(nest(lambda y: hypergeometric([y], [3], x), 3, 1))._sage_() # needs sage.symbolic hypergeometric((hypergeometric((hypergeometric((1,), (3,), x),), (3,),... x),), (3,), x) - sage: nest(lambda y: hypergeometric([y], [], x), 3, 1)._mathematica_init_() + sage: nest(lambda y: hypergeometric([y], [], x), 3, 1)._mathematica_init_() # needs sage.symbolic 'HypergeometricPFQ[{HypergeometricPFQ[{HypergeometricPFQ[{1},{},x]},... The confluent hypergeometric functions can arise as solutions to second-order differential equations (example from `here `_):: - sage: var('m') + sage: var('m') # needs sage.symbolic m - sage: y = function('y')(x) - sage: desolve(diff(y, x, 2) + 2*x*diff(y, x) - 4*m*y, y, + sage: y = function('y')(x) # needs sage.symbolic + sage: desolve(diff(y, x, 2) + 2*x*diff(y, x) - 4*m*y, y, # needs sage.symbolic ....: contrib_ode=true, ivar=x) [y(x) == _K1*hypergeometric_M(-m, 1/2, -x^2) +... _K2*hypergeometric_U(-m, 1/2, -x^2)] Series expansions of confluent hypergeometric functions:: - sage: hypergeometric_M(2, 2, x).series(x, 3) + sage: hypergeometric_M(2, 2, x).series(x, 3) # needs sage.symbolic 1 + 1*x + 1/2*x^2 + Order(x^3) - sage: hypergeometric_U(2, 2, x).series(x == 3, 100).subs(x=1).n() + sage: hypergeometric_U(2, 2, x).series(x == 3, 100).subs(x=1).n() # needs sage.symbolic 0.403652637676806 - sage: hypergeometric_U(2, 2, 1).n() + sage: hypergeometric_U(2, 2, 1).n() # needs mpmath 0.403652637676806 """ @@ -174,18 +178,24 @@ from sage.functions.hyperbolic import cosh, sinh from sage.functions.log import exp, log from sage.functions.other import sqrt, real_part -from sage.libs.mpmath import utils as mpmath_utils -from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.rings.infinity import Infinity from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.structure.element import get_coercion_model -from sage.symbolic.constants import pi -from sage.symbolic.expression import Expression +from sage.structure.element import Expression, get_coercion_model from sage.symbolic.function import BuiltinFunction -from sage.symbolic.ring import SR + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.symbolic.constants', 'pi') +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'hyp1f1', as_='_mpmath_hyp1f1') +lazy_import('mpmath', 'hyper', as_='_mpmath_hyper') +lazy_import('mpmath', 'hyperu', as_='_mpmath_hyperu') def rational_param_as_tuple(x): @@ -200,7 +210,7 @@ def rational_param_as_tuple(x): (1, 2) sage: rational_param_as_tuple(3) 3 - sage: rational_param_as_tuple(pi) + sage: rational_param_as_tuple(pi) # needs sage.symbolic pi """ try: @@ -237,7 +247,7 @@ def __init__(self): EXAMPLES:: - sage: maxima(hypergeometric) + sage: maxima(hypergeometric) # needs sage.symbolic hypergeometric TESTS:: @@ -268,6 +278,7 @@ def __call__(self, a, b, z, **kwargs): EXAMPLES:: + sage: # needs sage.symbolic sage: hypergeometric([], [], 1) hypergeometric((), (), 1) sage: hypergeometric([], [1], 1) @@ -292,7 +303,7 @@ def _print_latex_(self, a, b, z): r""" TESTS:: - sage: latex(hypergeometric([1, 1], [2], -1)) + sage: latex(hypergeometric([1, 1], [2], -1)) # needs sage.symbolic \,_2F_1\left(\begin{matrix} 1,1 \\ 2 \end{matrix} ; -1 \right) """ @@ -306,7 +317,7 @@ def _eval_(self, a, b, z, **kwargs): """ EXAMPLES:: - sage: hypergeometric([], [], 0) + sage: hypergeometric([], [], 0) # needs sage.symbolic 1 """ if not isinstance(a, tuple) or not isinstance(b, tuple): @@ -329,12 +340,12 @@ def _evalf_try_(self, a, b, z): EXAMPLES:: - sage: hypergeometric._evalf_try_((1.0,), (2.0,), 3.0) + sage: hypergeometric._evalf_try_((1.0,), (2.0,), 3.0) # needs mpmath 6.36184564106256 - sage: hypergeometric._evalf_try_((1.0, 1), (), 3.0) + sage: hypergeometric._evalf_try_((1.0, 1), (), 3.0) # needs mpmath -0.0377593153441588 + 0.750349833788561*I sage: hypergeometric._evalf_try_((1, 1), (), 3) # exact input - sage: hypergeometric._evalf_try_((x,), (), 1.0) # symbolic + sage: hypergeometric._evalf_try_((x,), (), 1.0) # symbolic # needs sage.symbolic sage: hypergeometric._evalf_try_(1.0, 2.0, 3.0) # not tuples """ # We need to override this for hypergeometric functions since @@ -353,32 +364,31 @@ def _evalf_(self, a, b, z, parent, algorithm=None): """ TESTS:: - sage: hypergeometric([1, 1], [2], -1).n() + sage: hypergeometric([1, 1], [2], -1).n() # needs sage.symbolic 0.693147180559945 - sage: hypergeometric([], [], RealField(100)(1)) + sage: hypergeometric([], [], RealField(100)(1)) # needs sage.rings.real_mpfr sage.symbolic 2.7182818284590452353602874714 """ if not isinstance(a, tuple) or not isinstance(b, tuple): raise TypeError("The first two parameters must be of type list") - from mpmath import hyper aa = [rational_param_as_tuple(c) for c in a] bb = [rational_param_as_tuple(c) for c in b] - return mpmath_utils.call(hyper, aa, bb, z, parent=parent) + return _mpmath_utils_call(_mpmath_hyper, aa, bb, z, parent=parent) def _tderivative_(self, a, b, z, *args, **kwargs): """ EXAMPLES:: - sage: hypergeometric([1/3, 2/3], [5], x^2).diff(x) + sage: hypergeometric([1/3, 2/3], [5], x^2).diff(x) # needs sage.symbolic 4/45*x*hypergeometric((4/3, 5/3), (6,), x^2) - sage: hypergeometric([1, 2], [x], 2).diff(x) + sage: hypergeometric([1, 2], [x], 2).diff(x) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: derivative of hypergeometric function with... respect to parameters. Try calling .simplify_hypergeometric()... first. - sage: hypergeometric([1/3, 2/3], [5], 2).diff(x) + sage: hypergeometric([1/3, 2/3], [5], 2).diff(x) # needs sage.symbolic 0 """ diff_param = kwargs['diff_param'] @@ -404,16 +414,17 @@ def _fast_callable_(self, a, b, z, etb): EXAMPLES:: + sage: # needs sage.symbolic sage: h = hypergeometric([], [], x) sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x']) sage: h._fast_callable_(etb) {hypergeometric((), (), x)}(v_0) - sage: var('x, y') + sage: var('x, y') # needs sage.symbolic (x, y) - sage: f = fast_callable(hypergeometric([y], [], x), vars=[x, y]) - sage: f(3, 4) + sage: f = fast_callable(hypergeometric([y], [], x), vars=[x, y]) # needs sage.symbolic + sage: f(3, 4) # needs sage.symbolic hypergeometric((4,), (), 3) """ return etb.call(self, *map(etb.var, etb._vars)) @@ -424,7 +435,7 @@ def sorted_parameters(self, a, b, z): EXAMPLES:: - sage: hypergeometric([2, 1, 3], [5, 4], + sage: hypergeometric([2, 1, 3], [5, 4], # needs sage.symbolic ....: 1/2).sorted_parameters() hypergeometric((1, 2, 3), (4, 5), 1/2) """ @@ -437,12 +448,12 @@ def eliminate_parameters(self, a, b, z): EXAMPLES:: - sage: hypergeometric([1, 1, 2, 5], [5, 1, 4], + sage: hypergeometric([1, 1, 2, 5], [5, 1, 4], # needs sage.symbolic ....: 1/2).eliminate_parameters() hypergeometric((1, 2), (4,), 1/2) sage: hypergeometric([x], [x], x).eliminate_parameters() hypergeometric((), (), x) - sage: hypergeometric((5, 4), (4, 4), 3).eliminate_parameters() + sage: hypergeometric((5, 4), (4, 4), 3).eliminate_parameters() # needs sage.symbolic hypergeometric((5,), (4,), 3) """ aa = list(a) # tuples are immutable @@ -475,6 +486,7 @@ def is_termwise_finite(self, a, b, z): EXAMPLES:: + sage: # needs sage.symbolic sage: hypergeometric([2], [3, 4], 5).is_termwise_finite() True sage: hypergeometric([2], [-3, 4], 5).is_termwise_finite() @@ -485,6 +497,7 @@ def is_termwise_finite(self, a, b, z): ....: 5).is_termwise_finite() # ambiguous False + sage: # needs sage.symbolic sage: hypergeometric([0], [-1], 5).is_termwise_finite() True sage: hypergeometric([0], [0], @@ -548,18 +561,19 @@ def is_absolutely_convergent(self, a, b, z): Degree giving infinite radius of convergence:: - sage: hypergeometric([2, 3], [4, 5], + sage: hypergeometric([2, 3], [4, 5], # needs sage.symbolic ....: 6).is_absolutely_convergent() True - sage: hypergeometric([2, 3], [-4, 5], + sage: hypergeometric([2, 3], [-4, 5], # needs sage.symbolic ....: 6).is_absolutely_convergent() # undefined False - sage: (hypergeometric([2, 3], [-4, 5], Infinity) + sage: (hypergeometric([2, 3], [-4, 5], Infinity) # needs sage.symbolic ....: .is_absolutely_convergent()) # undefined False Ordinary geometric series (unit radius of convergence):: + sage: # needs sage.symbolic sage: hypergeometric([1], [], 1/2).is_absolutely_convergent() True sage: hypergeometric([1], [], 2).is_absolutely_convergent() @@ -573,6 +587,7 @@ def is_absolutely_convergent(self, a, b, z): Degree `p = q+1` (unit radius of convergence):: + sage: # needs sage.symbolic sage: hypergeometric([2, 3], [4], 6).is_absolutely_convergent() False sage: hypergeometric([2, 3], [4], 1).is_absolutely_convergent() @@ -596,13 +611,13 @@ def is_absolutely_convergent(self, a, b, z): Degree giving zero radius of convergence:: - sage: hypergeometric([1, 2, 3], [4], + sage: hypergeometric([1, 2, 3], [4], # needs sage.symbolic ....: 2).is_absolutely_convergent() False - sage: hypergeometric([1, 2, 3], [4], + sage: hypergeometric([1, 2, 3], [4], # needs sage.symbolic ....: 1/2).is_absolutely_convergent() False - sage: (hypergeometric([1, 2, -3], [4], 1/2) + sage: (hypergeometric([1, 2, -3], [4], 1/2) # needs sage.symbolic ....: .is_absolutely_convergent()) # polynomial True """ @@ -658,6 +673,7 @@ def deflated(self, a, b, z): EXAMPLES:: + sage: # needs sage.symbolic sage: x = hypergeometric([6, 1], [3, 4, 5], 10) sage: y = x.deflated() sage: y @@ -669,6 +685,7 @@ def deflated(self, a, b, z): 2.87893612686782 2.87893612686782 + sage: # needs sage.symbolic sage: x = hypergeometric([6, 7], [3, 4, 5], 10) sage: y = x.deflated() sage: y @@ -691,6 +708,7 @@ def _deflated(self, a, b, z): EXAMPLES:: + sage: # needs sage.symbolic sage: x = hypergeometric([5], [4], 3) sage: y = x.deflated() sage: y @@ -748,6 +766,7 @@ def closed_form(hyp): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.hypergeometric import closed_form sage: var('a b c z') (a, b, c, z) @@ -939,6 +958,7 @@ class Hypergeometric_M(BuiltinFunction): EXAMPLES:: + sage: # needs mpmath sage: hypergeometric_M(1, 1, 1) hypergeometric_M(1, 1, 1) sage: hypergeometric_M(1, 1, 1.) @@ -947,16 +967,18 @@ class Hypergeometric_M(BuiltinFunction): 2.7182818284590452354 sage: hypergeometric_M(1, 1, 1).simplify_hypergeometric() e - sage: hypergeometric_M(1, 1/2, x).simplify_hypergeometric() - (-I*sqrt(pi)*x*erf(I*sqrt(-x))*e^x + sqrt(-x))/sqrt(-x) sage: hypergeometric_M(1, 3/2, 1).simplify_hypergeometric() 1/2*sqrt(pi)*erf(1)*e + + sage: hypergeometric_M(1, 1/2, x).simplify_hypergeometric() # needs sage.symbolic + (-I*sqrt(pi)*x*erf(I*sqrt(-x))*e^x + sqrt(-x))/sqrt(-x) + """ def __init__(self): r""" TESTS:: - sage: maxima(hypergeometric_M(1,1,x)) + sage: maxima(hypergeometric_M(1,1,x)) # needs sage.symbolic kummer_m(1,1,_SAGE_VAR_x) sage: latex(hypergeometric_M(1,1,x)) M\left(1, 1, x\right) @@ -973,8 +995,8 @@ def _eval_(self, a, b, z, **kwargs): """ TESTS:: - sage: (a,b)=var('a,b') - sage: hypergeometric_M(a,b,0) + sage: (a,b)=var('a,b') # needs sage.symbolic + sage: hypergeometric_M(a,b,0) # needs sage.symbolic 1 """ if not isinstance(z, Expression) and z == 0: @@ -985,11 +1007,10 @@ def _evalf_(self, a, b, z, parent, algorithm=None): """ TESTS:: - sage: hypergeometric_M(1,1,1).n() + sage: hypergeometric_M(1,1,1).n() # needs mpmath 2.71828182845905 """ - from mpmath import hyp1f1 - return mpmath_utils.call(hyp1f1, a, b, z, parent=parent) + return _mpmath_utils_call(_mpmath_hyp1f1, a, b, z, parent=parent) def _derivative_(self, a, b, z, diff_param): """ @@ -1014,9 +1035,9 @@ def generalized(self, a, b, z): EXAMPLES:: - sage: var('a b z') + sage: var('a b z') # needs sage.symbolic (a, b, z) - sage: hypergeometric_M(a, b, z).generalized() + sage: hypergeometric_M(a, b, z).generalized() # needs sage.symbolic hypergeometric((a,), (b,), z) """ @@ -1050,27 +1071,28 @@ class Hypergeometric_U(BuiltinFunction): EXAMPLES:: + sage: # needs mpmath sage: hypergeometric_U(1, 1, 1) hypergeometric_U(1, 1, 1) sage: hypergeometric_U(1, 1, 1.) 0.596347362323194 sage: hypergeometric_U(1, 1, 1).n(70) 0.59634736232319407434 - sage: hypergeometric_U(10^4, 1/3, 1).n() + sage: hypergeometric_U(10^4, 1/3, 1).n() # needs sage.libs.pari 6.60377008885811e-35745 - sage: hypergeometric_U(2 + I, 2, 1).n() - 0.183481989942099 - 0.458685959185190*I - sage: hypergeometric_U(1, 3, x).simplify_hypergeometric() - (x + 1)/x^2 sage: hypergeometric_U(1, 2, 2).simplify_hypergeometric() 1/2 + sage: hypergeometric_U(2 + I, 2, 1).n() # needs sage.symbolic + 0.183481989942099 - 0.458685959185190*I + sage: hypergeometric_U(1, 3, x).simplify_hypergeometric() # needs sage.symbolic + (x + 1)/x^2 """ def __init__(self): r""" TESTS:: - sage: maxima(hypergeometric_U(1,1,x)) + sage: maxima(hypergeometric_U(1,1,x)) # needs sage.symbolic kummer_u(1,1,_SAGE_VAR_x) sage: latex(hypergeometric_U(1,1,x)) U\left(1, 1, x\right) @@ -1090,11 +1112,10 @@ def _evalf_(self, a, b, z, parent, algorithm=None): """ TESTS:: - sage: hypergeometric_U(1,1,1).n() + sage: hypergeometric_U(1,1,1).n() # needs mpmath 0.596347362323194 """ - from mpmath import hyperu - return mpmath_utils.call(hyperu, a, b, z, parent=parent) + return _mpmath_utils_call(_mpmath_hyperu, a, b, z, parent=parent) def _derivative_(self, a, b, z, diff_param): """ @@ -1119,13 +1140,13 @@ def generalized(self, a, b, z): EXAMPLES:: - sage: var('a b z') + sage: var('a b z') # needs sage.symbolic (a, b, z) - sage: hypergeometric_U(a, b, z).generalized() + sage: hypergeometric_U(a, b, z).generalized() # needs sage.symbolic hypergeometric((a, a - b + 1), (), -1/z)/z^a - sage: hypergeometric_U(1, 3, 1/2).generalized() + sage: hypergeometric_U(1, 3, 1/2).generalized() # needs mpmath 2*hypergeometric((1, -1), (), -2) - sage: hypergeometric_U(3, I, 2).generalized() + sage: hypergeometric_U(3, I, 2).generalized() # needs sage.symbolic 1/8*hypergeometric((3, -I + 4), (), -1/2) """ diff --git a/src/sage/functions/jacobi.py b/src/sage/functions/jacobi.py index 8bb6b911add..629b24ce930 100644 --- a/src/sage/functions/jacobi.py +++ b/src/sage/functions/jacobi.py @@ -145,17 +145,21 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.symbolic.function import BuiltinFunction -from sage.functions.trig import (arctan, arcsin, arccos, arccot, arcsec, - arccsc, csc, sec, sin, cos, tan, cot) from sage.functions.hyperbolic import (arctanh, arccosh, arcsinh, arcsech, arccsch, arccoth, cosh, coth, sech, csch, tanh, sinh) -from sage.rings.rational_field import QQ -from sage.rings.integer import Integer from sage.functions.special import elliptic_e, elliptic_kc -from sage.libs.mpmath import utils -from sage.misc.latex import latex +from sage.functions.trig import (arctan, arcsin, arccos, arccot, arcsec, + arccsc, csc, sec, sin, cos, tan, cot) +from sage.misc.lazy_import import lazy_import +from sage.rings.integer import Integer +from sage.rings.rational_field import QQ +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'ellipfun', as_='_mpmath_ellipfun') HALF = QQ((1, 2)) @@ -176,18 +180,19 @@ def __init__(self, kind): TESTS:: - sage: N(jacobi("sn", I, 1/2)) # abs tol 1e-12 + sage: N(jacobi("sn", I, 1/2)) # abs tol 1e-12 # needs sage.symbolic -8.59454886300046e-73 + 1.34737147138542*I - sage: CN = fricas(jacobi('cn',x, 2)); CN # optional - fricas + sage: # optional - fricas, needs sage.symbolic + sage: CN = fricas(jacobi('cn',x, 2)); CN jacobiCn(x,2) - sage: fricas.series(CN, x=0) # optional - fricas + sage: fricas.series(CN, x=0) 1 2 3 4 17 6 79 8 1381 10 11 1 - - x + - x - -- x + --- x - ----- x + O(x ) 2 8 80 640 19200 - sage: fricas(jacobi('sn',x, 2)) # optional - fricas + sage: fricas(jacobi('sn',x, 2)) jacobiSn(x,2) - sage: fricas(jacobi('dn',x, 2)) # optional - fricas + sage: fricas(jacobi('dn',x, 2)) jacobiDn(x,2) """ if kind not in ['nd', 'ns', 'nc', 'dn', 'ds', 'dc', 'sn', 'sd', @@ -208,7 +213,8 @@ def _eval_(self, x, m): Check that the simplifications are correct:: - sage: from mpmath import almosteq + sage: # needs mpmath sage.symbolic + sage: from sage.libs.mpmath.all import almosteq sage: almosteq(n(jacobi_nd(8, 0, hold=True)), n(jacobi_nd(8, 0))) True sage: almosteq(n(jacobi_nd(1, 1, hold=True)), n(jacobi_nd(1, 1))) @@ -356,13 +362,12 @@ def _evalf_(self, x, m, parent, algorithm=None): r""" TESTS:: - sage: jacobi_sn(3, 4).n(100) + sage: jacobi_sn(3, 4).n(100) # needs mpmath sage.symbolic -0.33260000892770027112809652714 + 1.7077912301715219199143891076e-33*I - sage: jacobi_dn(I, I).n() + sage: jacobi_dn(I, I).n() # needs mpmath sage.symbolic 0.874189950651018 + 0.667346865048825*I """ - from mpmath import ellipfun - return utils.call(ellipfun, self.kind, x, m, parent=parent) + return _mpmath_utils_call(_mpmath_ellipfun, self.kind, x, m, parent=parent) def _derivative_(self, x, m, diff_param): r""" @@ -371,6 +376,7 @@ def _derivative_(self, x, m, diff_param): sn, cn, and dn are analytic for all real ``x``, so we can check that the derivatives are correct by computing the series:: + sage: # needs mpmath sage.symbolic sage: from mpmath import almosteq sage: a = 0.9327542442482303 sage: b = 0.7402326293643771 @@ -508,7 +514,7 @@ def _print_latex_(self, x, m): r""" TESTS:: - sage: latex(jacobi_sn(x, 3)) + sage: latex(jacobi_sn(x, 3)) # needs sage.symbolic \operatorname{sn}\left(x\middle|3\right) """ return r"\operatorname{{{}}}\left({}\middle|{}\right)".format(self.kind, @@ -561,6 +567,7 @@ def _eval_(self, x, m): Check that the simplifications are correct:: + sage: # needs mpmath sage.symbolic sage: from mpmath import almosteq sage: almosteq(n(inverse_jacobi_cd(1, -8, hold=True)), ....: n(inverse_jacobi_cd(1, -8))) @@ -713,12 +720,12 @@ def _evalf_(self, x, m, parent, algorithm=None): r""" TESTS:: - sage: inverse_jacobi_cn(2, 3).n() + sage: inverse_jacobi_cn(2, 3).n() # needs mpmath 0.859663746362987*I - sage: inverse_jacobi_cd(3, 4).n(100) + sage: inverse_jacobi_cd(3, 4).n(100) # needs mpmath -0.67214752201235862490069823239 + 2.1565156474996432354386749988*I """ - return utils.call(inverse_jacobi_f, self.kind, x, m, parent=parent) + return _mpmath_utils_call(inverse_jacobi_f, self.kind, x, m, parent=parent) def _derivative_(self, x, m, diff_param): r""" @@ -727,6 +734,7 @@ def _derivative_(self, x, m, diff_param): Check that ``dy/dx * dx/dy == 1``, where ``y = jacobi_pq(x, m)`` and ``x = inverse_jacobi_pq(y, m)``:: + sage: # needs mpmath sage.symbolic sage: from mpmath import almosteq sage: a = 0.130103220857094 sage: b = 0.437176765041986 @@ -899,7 +907,7 @@ def _print_latex_(self, x, m): r""" TESTS:: - sage: latex(inverse_jacobi_dn(x, 3)) + sage: latex(inverse_jacobi_dn(x, 3)) # needs sage.symbolic \operatorname{arcdn}\left(x\middle|3\right) """ return r"\operatorname{{arc{}}}\left({}\middle|{}\right)".format(self.kind, @@ -935,6 +943,7 @@ def jacobi(kind, z, m, **kwargs): EXAMPLES:: + sage: # needs mpmath sage: jacobi('sn', 1, 1) tanh(1) sage: jacobi('cd', 1, 1/2) @@ -944,8 +953,9 @@ def jacobi(kind, z, m, **kwargs): sage: (RDF(jacobi('cn', 1, 1/2)), RDF(jacobi('dn', 1, 1/2)), ....: RDF(jacobi('cn', 1, 1/2) / jacobi('dn', 1, 1/2))) (0.5959765676721407, 0.8231610016315962, 0.7240097216593705) - sage: jsn = jacobi('sn', x, 1) - sage: P = plot(jsn, 0, 1) + + sage: jsn = jacobi('sn', x, 1) # needs sage.symbolic + sage: P = plot(jsn, 0, 1) # needs sage.plot sage.symbolic """ if kind == 'nd': return jacobi_nd(z, m, **kwargs) @@ -996,20 +1006,24 @@ def inverse_jacobi(kind, x, m, **kwargs): EXAMPLES:: - sage: jacobi('dn', inverse_jacobi('dn', 3, 0.4), 0.4) + sage: jacobi('dn', inverse_jacobi('dn', 3, 0.4), 0.4) # needs mpmath 3.00000000000000 - sage: inverse_jacobi('dn', 10, 1/10).n(digits=50) + sage: inverse_jacobi('dn', 10, 1/10).n(digits=50) # needs mpmath 2.4777736267904273296523691232988240759001423661683*I - sage: inverse_jacobi_dn(x, 1) + sage: inverse_jacobi_dn(x, 1) # needs sage.symbolic arcsech(x) - sage: inverse_jacobi_dn(1, 3) + sage: inverse_jacobi_dn(1, 3) # needs mpmath 0 + + sage: # needs sage.symbolic sage: m = var('m') sage: z = inverse_jacobi_dn(x, m).series(x, 4).subs(x=0.1, m=0.7) sage: jacobi_dn(z, 0.7) 0.0999892750039819... sage: inverse_jacobi_nd(x, 1) arccosh(x) + + sage: # needs mpmath sage: inverse_jacobi_nd(1, 2) 0 sage: inverse_jacobi_ns(10^-5, 3).n() @@ -1022,7 +1036,7 @@ def inverse_jacobi(kind, x, m, **kwargs): 0.499098231322220 sage: inverse_jacobi('sn', 0.4707504, 0.5) 0.499999911466555 - sage: P = plot(inverse_jacobi('sn', x, 0.5), 0, 1) + sage: P = plot(inverse_jacobi('sn', x, 0.5), 0, 1) # needs sage.plot """ if kind == 'nd': return inverse_jacobi_nd(x, m, **kwargs) @@ -1076,11 +1090,11 @@ def _eval_(self, x, m): r""" TESTS:: - sage: jacobi_am(x, 0) + sage: jacobi_am(x, 0) # needs sage.symbolic x - sage: jacobi_am(0, x) + sage: jacobi_am(0, x) # needs sage.symbolic 0 - sage: jacobi_am(3, 4.) + sage: jacobi_am(3, 4.) # needs mpmath -0.339059208303591 """ if m == 0: @@ -1093,18 +1107,18 @@ def _evalf_(self, x, m, parent, algorithm=None): r""" TESTS:: - sage: jacobi_am(1, 2).n(100) + sage: jacobi_am(1, 2).n(100) # needs mpmath 0.73704379494724574105101929735 """ - return utils.call(jacobi_am_f, x, m, parent=parent) + return _mpmath_utils_call(jacobi_am_f, x, m, parent=parent) def _derivative_(self, x, m, diff_param): r""" TESTS:: - sage: diff(jacobi_am(x, 3), x) + sage: diff(jacobi_am(x, 3), x) # needs sage.symbolic jacobi_dn(x, 3) - sage: diff(jacobi_am(3, x), x) + sage: diff(jacobi_am(3, x), x) # needs sage.symbolic -1/2*(x*jacobi_cn(3, x)*jacobi_sn(3, x) -... (3*x + elliptic_e(jacobi_am(3, x), x) - 3)*jacobi_dn(3, x))/((x - 1)*x) """ @@ -1128,7 +1142,7 @@ def _print_latex_(self, x, m): r""" TESTS:: - sage: latex(jacobi_am(3,x)) + sage: latex(jacobi_am(3,x)) # needs sage.symbolic \operatorname{am}\left(3\middle|x\right) """ return r"\operatorname{{am}}\left({}\middle|{}\right)".format(latex(x), @@ -1146,9 +1160,10 @@ def inverse_jacobi_f(kind, x, m): TESTS:: - sage: from mpmath import ellipfun, chop + sage: from mpmath import ellipfun, chop # needs mpmath sage: from sage.functions.jacobi import inverse_jacobi_f + sage: # needs mpmath sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.6, 0), 0)) mpf('0.59999999999999998') sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.6, 1), 1)) @@ -1162,6 +1177,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.8, 4), 4)) mpf('0.80000000000000004') + sage: # needs mpmath sage: chop(ellipfun('ns', inverse_jacobi_f('ns', 0.8, 0), 0)) mpf('0.80000000000000004') sage: chop(ellipfun('ns', inverse_jacobi_f('ns', -0.7, 1), 1)) @@ -1173,6 +1189,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('ns', inverse_jacobi_f('ns', -10, 6), 6)) mpf('-10.0') + sage: # needs mpmath sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -10, 0), 0)) mpf('-9.9999999999999982') sage: chop(ellipfun('cn', inverse_jacobi_f('cn', 50, 1), 1)) @@ -1188,6 +1205,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -2, 0.9), 0.9)) mpf('-2.0') + sage: # needs mpmath sage: chop(ellipfun('nc', inverse_jacobi_f('nc', -4, 0), 0)) mpf('-3.9999999999999987') sage: chop(ellipfun('nc', inverse_jacobi_f('nc', 7, 1), 1)) @@ -1199,6 +1217,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('nc', inverse_jacobi_f('nc', -18, -4), -4)) mpf('-17.999999999999925') + sage: # needs mpmath sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -0.3, 1), 1)) mpf('-0.29999999999999999') sage: chop(ellipfun('dn', inverse_jacobi_f('dn', 1, -1), -1)) @@ -1216,6 +1235,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -1.9, 0.2), 0.2)) mpf('-1.8999999999999999') + sage: # needs mpmath sage: chop(ellipfun('nd', inverse_jacobi_f('nd', -1.9, 1), 1)) mpf('-1.8999999999999999') sage: chop(ellipfun('nd', inverse_jacobi_f('nd', 1, -1), -1)) @@ -1227,6 +1247,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('nd', inverse_jacobi_f('nd', -3, 0.8), 0.8)) mpf('-2.9999999999999996') + sage: # needs mpmath sage: chop(ellipfun('sc', inverse_jacobi_f('sc', -3, 0), 0)) mpf('-3.0') sage: chop(ellipfun('sc', inverse_jacobi_f('sc', 2, 1), 1)) @@ -1236,6 +1257,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('sc', inverse_jacobi_f('sc', -7, 3), 3)) mpf('-7.0') + sage: # needs mpmath sage: chop(ellipfun('cs', inverse_jacobi_f('cs', -7, 0), 0)) mpf('-6.9999999999999991') sage: chop(ellipfun('cs', inverse_jacobi_f('cs', 8, 1), 1)) @@ -1247,18 +1269,19 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('cs', inverse_jacobi_f('cs', -6, 8), 8)) mpf('-6.0000000000000018') - sage: chop(ellipfun('cd', inverse_jacobi_f('cd', -6, 0), 0)) + sage: chop(ellipfun('cd', inverse_jacobi_f('cd', -6, 0), 0)) # needs mpmath mpf('-6.0000000000000009') - sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 1, 3), 3)) + sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 1, 3), 3)) # needs mpmath mpf('1.0') - sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 6, 8), 8)) + sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 6, 8), 8)) # needs mpmath mpf('6.0000000000000027') - sage: chop(ellipfun('dc', inverse_jacobi_f('dc', 5, 0), 0)) + sage: chop(ellipfun('dc', inverse_jacobi_f('dc', 5, 0), 0)) # needs mpmath mpf('5.0000000000000018') - sage: chop(ellipfun('dc', inverse_jacobi_f('dc', -4, 2), 2)) + sage: chop(ellipfun('dc', inverse_jacobi_f('dc', -4, 2), 2)) # needs mpmath mpf('-4.0000000000000018') + sage: # needs mpmath sage: chop(ellipfun('sd', inverse_jacobi_f('sd', -4, 0), 0)) mpf('-3.9999999999999991') sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 7, 1), 1)) @@ -1268,12 +1291,10 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 8, 0.8), 0.8)) mpf('7.9999999999999991') - sage: chop(ellipfun('ds', inverse_jacobi_f('ds', 4, 0.25), 0.25)) + sage: chop(ellipfun('ds', inverse_jacobi_f('ds', 4, 0.25), 0.25)) # needs mpmath mpf('4.0') """ - from mpmath import mp - - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: x = ctx.convert(x) @@ -1614,6 +1635,7 @@ def jacobi_am_f(x, m): TESTS:: + sage: # needs mpmath sage: from mpmath import ellipf sage: from sage.functions.jacobi import jacobi_am_f sage: ellipf(jacobi_am_f(0.5, 1), 1) @@ -1629,9 +1651,7 @@ def jacobi_am_f(x, m): sage: jacobi_am_f(-3, 2) mpf('0.36067407399586108') """ - from mpmath import mp - - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: x = ctx.convert(x) diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index 6f9133841a3..38c6ca08bbe 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -8,20 +8,35 @@ - Tomas Kalvoda (2015-04-01): Add :meth:`exp_polar()` (:trac:`18085`) """ -from sage.symbolic.function import GinacFunction, BuiltinFunction -from sage.symbolic.constants import e as const_e -from sage.symbolic.constants import pi as const_pi -from sage.libs.mpmath import utils as mpmath_utils -from sage.structure.all import parent as s_parent -from sage.symbolic.expression import Expression, register_symbol -from sage.rings.real_double import RDF -from sage.rings.complex_double import CDF +from sage.misc.functional import log as log +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ +from sage.rings.real_double import RDF +from sage.structure.element import Expression, parent as s_parent +from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.symbolic.symbols import register_symbol -from sage.misc.functional import log as log +lazy_import('sage.functions.gamma', 'psi1') +lazy_import('sage.functions.other', 'imag') +lazy_import('sage.functions.transcendental', ['hurwitz_zeta', 'zeta']) + +lazy_import('sage.symbolic.constants', 'e', as_='const_e') +lazy_import('sage.symbolic.constants', 'pi', as_='const_pi') +lazy_import('sage.rings.complex_double', 'CDF') + +lazy_import('sage.libs.flint.arith', 'harmonic_number', as_='_flint_harmonic_number') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'harmonic', as_='_mpmath_harmonic') +lazy_import('mpmath', 'lambertw', as_='_mpmath_lambertw') + +lazy_import('sympy', 'polylog', as_='_sympy_polylog') +lazy_import('sympy', 'sympify', as_='_sympify') + +lazy_import('scipy.special', 'lambertw', as_='_scipy_lambertw') class Function_exp(GinacFunction): @@ -30,6 +45,7 @@ class Function_exp(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: exp(-1) e^(-1) sage: exp(2) @@ -42,28 +58,30 @@ class Function_exp(GinacFunction): x*e^(x^2) sage: exp(2.5) 12.1824939607035 + sage: exp(I*pi/12) + (1/4*I + 1/4)*sqrt(6) - (1/4*I - 1/4)*sqrt(2) + sage: exp(float(2.5)) 12.182493960703473 sage: exp(RDF('2.5')) 12.182493960703473 - sage: exp(I*pi/12) - (1/4*I + 1/4)*sqrt(6) - (1/4*I - 1/4)*sqrt(2) To prevent automatic evaluation, use the ``hold`` parameter:: - sage: exp(I*pi,hold=True) + sage: exp(I*pi, hold=True) # needs sage.symbolic e^(I*pi) - sage: exp(0,hold=True) + sage: exp(0, hold=True) # needs sage.symbolic e^0 To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: exp(0,hold=True).simplify() + sage: exp(0, hold=True).simplify() # needs sage.symbolic 1 :: + sage: # needs sage.symbolic sage: exp(pi*I/2) I sage: exp(pi*I) @@ -76,25 +94,26 @@ class Function_exp(GinacFunction): For the sake of simplification, the argument is reduced modulo the period of the complex exponential function, `2\pi i`:: - sage: k = var('k', domain='integer') - sage: exp(2*k*pi*I) + sage: k = var('k', domain='integer') # needs sage.symbolic + sage: exp(2*k*pi*I) # needs sage.symbolic 1 - sage: exp(log(2) + 2*k*pi*I) + sage: exp(log(2) + 2*k*pi*I) # needs sage.symbolic 2 The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:: - sage: t = exp(RealField(100)(2)); t + sage: t = exp(RealField(100)(2)); t # needs sage.rings.real_mpfr 7.3890560989306502272304274606 - sage: t.prec() + sage: t.prec() # needs sage.rings.real_mpfr 100 - sage: exp(2).n(100) + sage: exp(2).n(100) # needs sage.symbolic 7.3890560989306502272304274606 TESTS:: + sage: # needs sage.symbolic sage: latex(exp(x)) e^{x} sage: latex(exp(sqrt(x))) @@ -105,25 +124,27 @@ class Function_exp(GinacFunction): \left(e^{\sqrt{x}}\right)^{x} sage: latex(exp(sqrt(x)^x)) e^{\left(\sqrt{x}^{x}\right)} - sage: exp(x)._sympy_() + sage: exp(x)._sympy_() # needs sympy exp(x) Test conjugates:: - sage: conjugate(exp(x)) + sage: conjugate(exp(x)) # needs sage.symbolic e^conjugate(x) Test simplifications when taking powers of exp (:trac:`7264`):: + sage: # needs sage.symbolic sage: var('a,b,c,II') (a, b, c, II) sage: model_exp = exp(II)**a*(b) - sage: sol1_l={b: 5.0, a: 1.1} + sage: sol1_l = {b: 5.0, a: 1.1} sage: model_exp.subs(sol1_l) 5.00000000000000*e^(1.10000000000000*II) :: + sage: # needs sage.symbolic sage: exp(3)^II*exp(x) e^(3*II + x) sage: exp(x)*exp(x) @@ -135,14 +156,14 @@ class Function_exp(GinacFunction): Another instance of the same problem (:trac:`7394`):: - sage: 2*sqrt(e) + sage: 2*sqrt(e) # needs sage.symbolic 2*e^(1/2) Check that :trac:`19918` is fixed:: - sage: exp(-x^2).subs(x=oo) + sage: exp(-x^2).subs(x=oo) # needs sage.symbolic 0 - sage: exp(-x).subs(x=-oo) + sage: exp(-x).subs(x=-oo) # needs sage.symbolic +Infinity """ def __init__(self): @@ -151,7 +172,7 @@ def __init__(self): sage: loads(dumps(exp)) exp - sage: maxima(exp(x))._sage_() + sage: maxima(exp(x))._sage_() # needs sage.symbolic e^x """ GinacFunction.__init__(self, "exp", latex_name=r"\exp", @@ -169,20 +190,21 @@ class Function_log1(GinacFunction): EXAMPLES:: - sage: ln(e^2) + sage: ln(e^2) # needs sage.symbolic 2 - sage: ln(2) + sage: ln(2) # needs sage.symbolic log(2) - sage: ln(10) + sage: ln(10) # needs sage.symbolic log(10) TESTS:: + sage: # needs sage.symbolic sage: latex(x.log()) \log\left(x\right) sage: latex(log(1/4)) \log\left(\frac{1}{4}\right) - sage: log(x)._sympy_() + sage: log(x)._sympy_() # needs sympy log(x) sage: loads(dumps(ln(x)+1)) log(x) + 1 @@ -190,13 +212,14 @@ class Function_log1(GinacFunction): ``conjugate(log(x))==log(conjugate(x))`` unless on the branch cut which runs along the negative real axis.:: + sage: # needs sage.symbolic sage: conjugate(log(x)) conjugate(log(x)) sage: var('y', domain='positive') y sage: conjugate(log(y)) log(y) - sage: conjugate(log(y+I)) + sage: conjugate(log(y + I)) conjugate(log(y + I)) sage: conjugate(log(-1)) -I*pi @@ -208,20 +231,20 @@ class Function_log1(GinacFunction): sage: from sage.functions.log import function_log as log sage: log(float(5)) 1.6094379124341003 - sage: log(float(0)) + sage: log(float(0)) # needs sage.symbolic -inf - sage: log(float(-1)) + sage: log(float(-1)) # needs sage.symbolic 3.141592653589793j - sage: log(x).subs(x=float(-1)) + sage: log(x).subs(x=float(-1)) # needs sage.symbolic 3.141592653589793j :trac:`22142`:: - sage: log(QQbar(sqrt(2))) + sage: log(QQbar(sqrt(2))) # needs sage.rings.number_field sage.symbolic log(1.414213562373095?) - sage: log(QQbar(sqrt(2))*1.) + sage: log(QQbar(sqrt(2))*1.) # needs sage.rings.number_field sage.symbolic 0.346573590279973 - sage: polylog(QQbar(sqrt(2)),3) + sage: polylog(QQbar(sqrt(2)),3) # needs sage.rings.number_field sage.symbolic polylog(1.414213562373095?, 3) """ def __init__(self): @@ -230,7 +253,7 @@ def __init__(self): sage: loads(dumps(ln)) log - sage: maxima(ln(x))._sage_() + sage: maxima(ln(x))._sage_() # needs sage.symbolic log(x) """ GinacFunction.__init__(self, 'log', latex_name=r'\log', @@ -250,14 +273,14 @@ class Function_log2(GinacFunction): EXAMPLES:: sage: from sage.functions.log import logb - sage: logb(1000,10) + sage: logb(1000, 10) # needs sage.symbolic 3 TESTS:: - sage: logb(7, 2) + sage: logb(7, 2) # needs sage.symbolic log(7)/log(2) - sage: logb(int(7), 2) + sage: logb(int(7), 2) # needs sage.symbolic log(7)/log(2) """ def __init__(self): @@ -283,16 +306,17 @@ def __init__(self): `\text{Li}_s(z) = \sum_{k=1}^{\infty} z^k / k^s`. The first argument is `s` (usually an integer called the weight) - and the second argument is `z` : ``polylog(s, z)``. + and the second argument is `z`: ``polylog(s, z)``. This definition is valid for arbitrary complex numbers `s` and `z` with `|z| < 1`. It can be extended to `|z| \ge 1` by the process of analytic continuation, with a branch cut along the positive real axis - from `1` to `+\infty`. A `NaN` value may be returned for floating + from `1` to `+\infty`. A ``NaN`` value may be returned for floating point arguments that are on the branch cut. EXAMPLES:: + sage: # needs sage.symbolic sage: polylog(2.7, 0) 0.000000000000000 sage: polylog(2, 1) @@ -308,55 +332,54 @@ def __init__(self): sage: polylog(4, 0.5) 0.517479061673899 + sage: # needs sage.symbolic sage: polylog(1, x) -log(-x + 1) - sage: polylog(2,x^2+1) + sage: polylog(2, x^2 + 1) dilog(x^2 + 1) - sage: f = polylog(4, 1); f 1/90*pi^4 sage: f.n() 1.08232323371114 - sage: polylog(4, 2).n() 2.42786280675470 - 0.174371300025453*I - sage: complex(polylog(4,2)) + sage: complex(polylog(4, 2)) (2.4278628067547032-0.17437130002545306j) - sage: float(polylog(4,0.5)) + sage: float(polylog(4, 0.5)) 0.5174790616738993 - sage: z = var('z') - sage: polylog(2,z).series(z==0, 5) + sage: polylog(2, z).series(z==0, 5) 1*z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + Order(z^5) sage: loads(dumps(polylog)) polylog - sage: latex(polylog(5, x)) + sage: latex(polylog(5, x)) # needs sage.symbolic {\rm Li}_{5}(x) - sage: polylog(x, x)._sympy_() + sage: polylog(x, x)._sympy_() # needs sympy sage.symbolic polylog(x, x) TESTS: Check if :trac:`8459` is fixed:: - sage: t = maxima(polylog(5,x)).sage(); t + sage: t = maxima(polylog(5,x)).sage(); t # needs sage.symbolic polylog(5, x) - sage: t.operator() == polylog + sage: t.operator() == polylog # needs sage.symbolic True - sage: t.subs(x=.5).n() + sage: t.subs(x=.5).n() # needs sage.symbolic 0.50840057924226... Check if :trac:`18386` is fixed:: - sage: polylog(2.0, 1) + sage: polylog(2.0, 1) # needs sage.symbolic 1.64493406684823 - sage: polylog(2, 1.0) + sage: polylog(2, 1.0) # needs sage.symbolic 1.64493406684823 - sage: polylog(2.0, 1.0) + sage: polylog(2.0, 1.0) # needs sage.symbolic 1.64493406684823 + sage: # needs sage.libs.flint sage: polylog(2, RealBallField(100)(1/3)) [0.36621322997706348761674629766... +/- ...] sage: polylog(2, ComplexBallField(100)(4/3)) @@ -370,12 +393,12 @@ def __init__(self): sage: parent(_) Complex ball field with 53 bits of precision - sage: polylog(1,-1) # known bug + sage: polylog(1, -1) # known bug # needs sage.symbolic -log(2) Check for :trac:`21907`:: - sage: bool(x*polylog(x,x)==0) + sage: bool(x*polylog(x,x)==0) # needs sage.symbolic False """ GinacFunction.__init__(self, "polylog", nargs=2, @@ -390,9 +413,9 @@ def _maxima_init_evaled_(self, *args): These are indirect doctests for this function:: - sage: polylog(2, x)._maxima_() + sage: polylog(2, x)._maxima_() # needs sage.symbolic li[2](_SAGE_VAR_x) - sage: polylog(4, x)._maxima_() + sage: polylog(4, x)._maxima_() # needs sage.symbolic polylog(4,_SAGE_VAR_x) """ args_maxima = [] @@ -414,8 +437,8 @@ def _method_arguments(self, k, z): r""" TESTS:: - sage: b = RBF(1/2, .0001) - sage: polylog(2, b) + sage: b = RBF(1/2, .0001) # needs sage.libs.flint + sage: polylog(2, b) # needs sage.libs.flint [0.582 +/- ...] """ return [z, k] @@ -430,10 +453,11 @@ def __init__(self): The dilogarithm function `\text{Li}_2(z) = \sum_{k=1}^{\infty} z^k / k^2`. - This is simply an alias for polylog(2, z). + This is simply an alias for ``polylog(2, z)``. EXAMPLES:: + sage: # needs sage.symbolic sage: dilog(1) 1/6*pi^2 sage: dilog(1/2) @@ -457,14 +481,16 @@ def __init__(self): sage: dilog(z).diff(z, 2) log(-z + 1)/z^2 - 1/((z - 1)*z) sage: dilog(z).series(z==1/2, 3) - (1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2) + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3) + (1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2) + + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3) - sage: latex(dilog(z)) + sage: latex(dilog(z)) # needs sage.symbolic {\rm Li}_2\left(z\right) Dilog has a branch point at `1`. Sage's floating point libraries may handle this differently from the symbolic package:: + sage: # needs sage.symbolic sage: dilog(1) 1/6*pi^2 sage: dilog(1.) @@ -479,9 +505,10 @@ def __init__(self): ``conjugate(dilog(x))==dilog(conjugate(x))`` unless on the branch cuts which run along the positive real axis beginning at 1.:: + sage: # needs sage.symbolic sage: conjugate(dilog(x)) conjugate(dilog(x)) - sage: var('y',domain='positive') + sage: var('y', domain='positive') y sage: conjugate(dilog(y)) conjugate(dilog(y)) @@ -497,10 +524,12 @@ def __init__(self): Check that return type matches argument type where possible (:trac:`18386`):: - sage: dilog(0.5) + sage: dilog(0.5) # needs sage.symbolic 0.582240526465012 - sage: dilog(-1.0) + sage: dilog(-1.0) # needs sage.symbolic -0.822467033424113 + + sage: # needs sage.rings.real_mpfr sage.symbolic sage: y = dilog(RealField(13)(0.5)) sage: parent(y) Real Field with 13 bits of precision @@ -520,16 +549,14 @@ def _sympy_(self, z): EXAMPLES:: - sage: w = dilog(x)._sympy_(); w + sage: w = dilog(x)._sympy_(); w # needs sympy sage.symbolic polylog(2, x) - sage: w.diff() + sage: w.diff() # needs sympy sage.symbolic polylog(1, x)/x - sage: w._sage_() + sage: w._sage_() # needs sympy sage.symbolic dilog(x) """ - import sympy - from sympy import polylog as sympy_polylog - return sympy_polylog(2, sympy.sympify(z, evaluate=False)) + return _sympy_polylog(2, _sympify(z, evaluate=False)) dilog = Function_dilog() @@ -566,55 +593,55 @@ class Function_lambert_w(BuiltinFunction): Evaluation of the principal branch:: - sage: lambert_w(1.0) + sage: lambert_w(1.0) # needs scipy 0.567143290409784 - sage: lambert_w(-1).n() + sage: lambert_w(-1).n() # needs mpmath -0.318131505204764 + 1.33723570143069*I - sage: lambert_w(-1.5 + 5*I) + sage: lambert_w(-1.5 + 5*I) # needs mpmath sage.symbolic 1.17418016254171 + 1.10651494102011*I Evaluation of other branches:: - sage: lambert_w(2, 1.0) + sage: lambert_w(2, 1.0) # needs scipy -2.40158510486800 + 10.7762995161151*I Solutions to certain exponential equations are returned in terms of lambert_w:: - sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True) - sage: z = S[0].rhs(); z + sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True) # needs sage.symbolic + sage: z = S[0].rhs(); z # needs sage.symbolic -1/5*lambert_w(5) - sage: N(z) + sage: N(z) # needs sage.symbolic -0.265344933048440 Check the defining equation numerically at `z=5`:: - sage: N(lambert_w(5)*exp(lambert_w(5)) - 5) + sage: N(lambert_w(5)*exp(lambert_w(5)) - 5) # needs mpmath 0.000000000000000 There are several special values of the principal branch which are automatically simplified:: - sage: lambert_w(0) + sage: lambert_w(0) # needs mpmath 0 - sage: lambert_w(e) + sage: lambert_w(e) # needs sage.symbolic 1 - sage: lambert_w(-1/e) + sage: lambert_w(-1/e) # needs sage.symbolic -1 Integration (of the principal branch) is evaluated using Maxima:: - sage: integrate(lambert_w(x), x) + sage: integrate(lambert_w(x), x) # needs sage.symbolic (lambert_w(x)^2 - lambert_w(x) + 1)*x/lambert_w(x) - sage: integrate(lambert_w(x), x, 0, 1) + sage: integrate(lambert_w(x), x, 0, 1) # needs sage.symbolic (lambert_w(1)^2 - lambert_w(1) + 1)/lambert_w(1) - 1 - sage: integrate(lambert_w(x), x, 0, 1.0) + sage: integrate(lambert_w(x), x, 0, 1.0) # needs sage.symbolic 0.3303661247616807 Warning: The integral of a non-principal branch is not implemented, neither is numerical integration using GSL. The :meth:`numerical_integral` function does work if you pass a lambda function:: - sage: numerical_integral(lambda x: lambert_w(x), 0, 1) + sage: numerical_integral(lambda x: lambert_w(x), 0, 1) # needs sage.modules (0.33036612476168054, 3.667800782666048e-15) """ @@ -624,27 +651,27 @@ def __init__(self): EXAMPLES:: - sage: lambert_w(0, 1.0) + sage: lambert_w(0, 1.0) # needs scipy 0.567143290409784 - sage: lambert_w(x, x)._sympy_() + sage: lambert_w(x, x)._sympy_() # needs sympy sage.symbolic LambertW(x, x) TESTS: Check that :trac:`25987` is fixed:: - sage: lambert_w(x)._fricas_() # optional - fricas + sage: lambert_w(x)._fricas_() # optional - fricas, needs sage.symbolic lambertW(x) - sage: fricas(lambert_w(x)).eval(x = -1/e) # optional - fricas + sage: fricas(lambert_w(x)).eval(x=-1/e) # optional - fricas, needs sage.symbolic - 1 The two-argument form of Lambert's function is not supported by FriCAS, so we return a generic operator:: - sage: var("n") + sage: var("n") # needs sage.symbolic n - sage: lambert_w(n, x)._fricas_() # optional - fricas + sage: lambert_w(n, x)._fricas_() # optional - fricas, needs sage.symbolic generalizedLambertW(n,x) """ BuiltinFunction.__init__(self, "lambert_w", nargs=2, @@ -662,9 +689,9 @@ def __call__(self, *args, **kwds): EXAMPLES:: - sage: lambert_w(1) + sage: lambert_w(1) # needs sage.symbolic lambert_w(1) - sage: lambert_w(1, 2) + sage: lambert_w(1, 2) # needs sage.symbolic lambert_w(1, 2) """ if len(args) == 2: @@ -678,6 +705,7 @@ def _method_arguments(self, n, z): r""" TESTS:: + sage: # needs sage.libs.flint sage: b = RBF(1, 0.001) sage: lambert_w(b) [0.567 +/- 6.44e-4] @@ -697,29 +725,29 @@ def _eval_(self, n, z): """ EXAMPLES:: - sage: lambert_w(6.0) + sage: lambert_w(6.0) # needs scipy 1.43240477589830 - sage: lambert_w(1) + sage: lambert_w(1) # needs sage.symbolic lambert_w(1) - sage: lambert_w(x+1) + sage: lambert_w(x + 1) # needs sage.symbolic lambert_w(x + 1) There are three special values which are automatically simplified:: - sage: lambert_w(0) + sage: lambert_w(0) # needs mpmath 0 - sage: lambert_w(e) + sage: lambert_w(e) # needs sage.symbolic 1 - sage: lambert_w(-1/e) + sage: lambert_w(-1/e) # needs sage.symbolic -1 - sage: lambert_w(SR(0)) + sage: lambert_w(SR(0)) # needs sage.symbolic 0 The special values only hold on the principal branch:: - sage: lambert_w(1,e) + sage: lambert_w(1, e) # needs sage.symbolic lambert_w(1, e) - sage: lambert_w(1, e.n()) + sage: lambert_w(1, e.n()) # needs sage.symbolic -0.532092121986380 + 4.59715801330257*I TESTS: @@ -728,11 +756,11 @@ def _eval_(self, n, z): value should be either the same as the parent of the input, or a Sage type:: - sage: parent(lambert_w(int(0))) + sage: parent(lambert_w(int(0))) # needs mpmath <... 'int'> - sage: parent(lambert_w(Integer(0))) + sage: parent(lambert_w(Integer(0))) # needs mpmath Integer Ring - sage: parent(lambert_w(e)) + sage: parent(lambert_w(e)) # needs sage.symbolic Symbolic Ring """ if not isinstance(z, Expression): @@ -750,13 +778,14 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(lambert_w(1)) + sage: N(lambert_w(1)) # needs sage.symbolic 0.567143290409784 - sage: lambert_w(RealField(100)(1)) + sage: lambert_w(RealField(100)(1)) # needs sage.rings.real_mpfr 0.56714329040978387299996866221 SciPy is used to evaluate for float, RDF, and CDF inputs:: + sage: # needs scipy sage: lambert_w(RDF(1)) 0.5671432904097838 sage: lambert_w(float(1)) @@ -772,8 +801,7 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ R = parent or s_parent(z) if R is float or R is RDF: - from scipy.special import lambertw - res = lambertw(z, n) + res = _scipy_lambertw(z, n) # SciPy always returns a complex value, make it real if possible if not res.imag: return R(res.real) @@ -782,11 +810,9 @@ def _evalf_(self, n, z, parent=None, algorithm=None): else: return CDF(res) elif R is complex or R is CDF: - from scipy.special import lambertw - return R(lambertw(z, n)) + return R(_scipy_lambertw(z, n)) else: - import mpmath - return mpmath_utils.call(mpmath.lambertw, z, n, parent=R) + return _mpmath_utils_call(_mpmath_lambertw, z, n, parent=R) def _derivative_(self, n, z, diff_param=None): r""" @@ -794,19 +820,19 @@ def _derivative_(self, n, z, diff_param=None): EXAMPLES:: - sage: x = var('x') - sage: derivative(lambert_w(x), x) + sage: x = var('x') # needs sage.symbolic + sage: derivative(lambert_w(x), x) # needs sage.symbolic lambert_w(x)/(x*lambert_w(x) + x) - sage: derivative(lambert_w(2, exp(x)), x) + sage: derivative(lambert_w(2, exp(x)), x) # needs sage.symbolic e^x*lambert_w(2, e^x)/(e^x*lambert_w(2, e^x) + e^x) TESTS: Differentiation in the first parameter raises an error :trac:`14788`:: - sage: n = var('n') - sage: lambert_w(n, x).diff(n) + sage: n = var('n') # needs sage.symbolic + sage: lambert_w(n, x).diff(n) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot differentiate lambert_w in the first parameter @@ -822,16 +848,16 @@ def _maxima_init_evaled_(self, n, z): These are indirect doctests for this function.:: - sage: lambert_w(0, x)._maxima_() + sage: lambert_w(0, x)._maxima_() # needs sage.symbolic lambert_w(_SAGE_VAR_x) - sage: lambert_w(1, x)._maxima_() + sage: lambert_w(1, x)._maxima_() # needs sage.symbolic generalized_lambert_w(1,_SAGE_VAR_x) TESTS:: - sage: lambert_w(x)._maxima_()._sage_() + sage: lambert_w(x)._maxima_()._sage_() # needs sage.symbolic lambert_w(x) - sage: lambert_w(2, x)._maxima_()._sage_() + sage: lambert_w(2, x)._maxima_()._sage_() # needs sage.symbolic lambert_w(2, x) """ if isinstance(z, str): @@ -852,9 +878,9 @@ def _print_(self, n, z): EXAMPLES:: - sage: lambert_w(1) + sage: lambert_w(1) # needs sage.symbolic lambert_w(1) - sage: lambert_w(0,x) + sage: lambert_w(0, x) # needs sage.symbolic lambert_w(x) """ if n == 0: @@ -869,13 +895,14 @@ def _print_latex_(self, n, z): EXAMPLES:: + sage: # needs sage.symbolic sage: latex(lambert_w(1)) \operatorname{W}({1}) - sage: latex(lambert_w(0,x)) + sage: latex(lambert_w(0, x)) \operatorname{W}({x}) - sage: latex(lambert_w(1,x)) + sage: latex(lambert_w(1, x)) \operatorname{W_{1}}({x}) - sage: latex(lambert_w(1,x+exp(x))) + sage: latex(lambert_w(1, x + exp(x))) \operatorname{W_{1}}({x + e^{x}}) """ if n == 0: @@ -908,23 +935,23 @@ def __init__(self): The following expressions are evaluated using the exponential function:: - sage: exp_polar(pi*I/2) + sage: exp_polar(pi*I/2) # needs sage.symbolic I - sage: x = var('x', domain='real') - sage: exp_polar(-1/2*I*pi + x) + sage: x = var('x', domain='real') # needs sage.symbolic + sage: exp_polar(-1/2*I*pi + x) # needs sage.symbolic e^(-1/2*I*pi + x) The function is left unevaluated when the imaginary part of the input `z` does not satisfy `-\pi < \Im(z) \leq \pi`:: - sage: exp_polar(2*pi*I) + sage: exp_polar(2*pi*I) # needs sage.symbolic exp_polar(2*I*pi) - sage: exp_polar(-4*pi*I) + sage: exp_polar(-4*pi*I) # needs sage.symbolic exp_polar(-4*I*pi) This fixes :trac:`18085`:: - sage: integrate(1/sqrt(1+x^3),x,algorithm='sympy') + sage: integrate(1/sqrt(1+x^3), x, algorithm='sympy') # needs sage.symbolic 1/3*x*gamma(1/3)*hypergeometric((1/3, 1/2), (4/3,), -x^3)/gamma(4/3) @@ -948,25 +975,23 @@ def _evalf_(self, z, parent=None, algorithm=None): If the imaginary part of `z` obeys `-\pi < z \leq \pi`, then `\operatorname{exp\_polar}(z)` is evaluated as `\exp(z)`:: - sage: exp_polar(1.0 + 2.0*I) + sage: exp_polar(1.0 + 2.0*I) # needs sage.symbolic -1.13120438375681 + 2.47172667200482*I If the imaginary part of `z` is outside of that interval the expression is left unevaluated:: - sage: exp_polar(-5.0 + 8.0*I) + sage: exp_polar(-5.0 + 8.0*I) # needs sage.symbolic exp_polar(-5.00000000000000 + 8.00000000000000*I) An attempt to numerically evaluate such an expression raises an error:: - sage: exp_polar(-5.0 + 8.0*I).n() + sage: exp_polar(-5.0 + 8.0*I).n() # needs sage.symbolic Traceback (most recent call last): ... ValueError: invalid attempt to numerically evaluate exp_polar() """ - from sage.functions.other import imag - if (not isinstance(z, Expression) and bool(-const_pi < imag(z) <= const_pi)): return exp(z) @@ -977,17 +1002,17 @@ def _eval_(self, z): """ EXAMPLES:: - sage: exp_polar(3*I*pi) + sage: exp_polar(3*I*pi) # needs sage.symbolic exp_polar(3*I*pi) - sage: x = var('x', domain='real') - sage: exp_polar(4*I*pi + x) + sage: x = var('x', domain='real') # needs sage.symbolic + sage: exp_polar(4*I*pi + x) # needs sage.symbolic exp_polar(4*I*pi + x) TESTS: Check that :trac:`24441` is fixed:: - sage: exp_polar(arcsec(jacobi_sn(1.1*I*x, x))) # should be fast + sage: exp_polar(arcsec(jacobi_sn(1.1*I*x, x))) # should be fast # needs sage.symbolic exp_polar(arcsec(jacobi_sn(1.10000000000000*I*x, x))) """ try: @@ -1021,7 +1046,7 @@ class Function_harmonic_number_generalized(BuiltinFunction): H_{s,m}=\zeta(m)-\zeta(m,s-1) If called with a single argument, that argument is ``s`` and ``m`` is - assumed to be 1 (the normal harmonic numbers ``H_s``). + assumed to be 1 (the normal harmonic numbers `H_s`). ALGORITHM: @@ -1035,42 +1060,44 @@ class Function_harmonic_number_generalized(BuiltinFunction): Evaluation of integer, rational, or complex argument:: - sage: harmonic_number(5) + sage: harmonic_number(5) # needs mpmath 137/60 - sage: harmonic_number(3,3) + + sage: # needs sage.symbolic + sage: harmonic_number(3, 3) 251/216 sage: harmonic_number(5/2) -2*log(2) + 46/15 - sage: harmonic_number(3.,3) + sage: harmonic_number(3., 3) zeta(3) - 0.0400198661225573 - sage: harmonic_number(3.,3.) + sage: harmonic_number(3., 3.) 1.16203703703704 - sage: harmonic_number(3,3).n(200) + sage: harmonic_number(3, 3).n(200) 1.16203703703703703703703... - sage: harmonic_number(1+I,5) + sage: harmonic_number(1 + I, 5) harmonic_number(I + 1, 5) - sage: harmonic_number(5,1.+I) + sage: harmonic_number(5, 1. + I) 1.57436810798989 - 1.06194728851357*I Solutions to certain sums are returned in terms of harmonic numbers:: - sage: k=var('k') - sage: sum(1/k^7,k,1,x) + sage: k = var('k') # needs sage.symbolic + sage: sum(1/k^7,k,1,x) # needs sage.symbolic harmonic_number(x, 7) Check the defining integral at a random integer:: - sage: n=randint(10,100) - sage: bool(SR(integrate((1-x^n)/(1-x),x,0,1)) == harmonic_number(n)) + sage: n = randint(10,100) + sage: bool(SR(integrate((1-x^n)/(1-x),x,0,1)) == harmonic_number(n)) # needs sage.symbolic True There are several special values which are automatically simplified:: - sage: harmonic_number(0) + sage: harmonic_number(0) # needs mpmath 0 - sage: harmonic_number(1) + sage: harmonic_number(1) # needs mpmath 1 - sage: harmonic_number(x,1) + sage: harmonic_number(x, 1) # needs sage.symbolic harmonic_number(x) """ @@ -1078,9 +1105,9 @@ def __init__(self): r""" EXAMPLES:: - sage: loads(dumps(harmonic_number(x,5))) + sage: loads(dumps(harmonic_number(x, 5))) # needs sage.symbolic harmonic_number(x, 5) - sage: harmonic_number(x, x)._sympy_() + sage: harmonic_number(x, x)._sympy_() # needs sympy sage.symbolic harmonic(x, x) """ BuiltinFunction.__init__(self, "harmonic_number", nargs=2, @@ -1089,15 +1116,15 @@ def __init__(self): def __call__(self, z, m=1, **kwds): r""" Custom call method allows the user to pass one argument or two. If - one argument is passed, we assume it is ``z`` and that ``m=1``. + one argument is passed, we assume it is ``z`` and that `m=1`. EXAMPLES:: - sage: harmonic_number(x) + sage: harmonic_number(x) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x,1) + sage: harmonic_number(x, 1) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x,2) + sage: harmonic_number(x, 2) # needs sage.symbolic harmonic_number(x, 2) """ return BuiltinFunction.__call__(self, z, m, **kwds) @@ -1106,30 +1133,32 @@ def _eval_(self, z, m): """ EXAMPLES:: - sage: harmonic_number(x,0) + sage: harmonic_number(5) # needs mpmath + 137/60 + + sage: # needs sage.symbolic + sage: harmonic_number(x, 0) x - sage: harmonic_number(x,1) + sage: harmonic_number(x, 1) harmonic_number(x) - sage: harmonic_number(5) - 137/60 - sage: harmonic_number(3,3) + sage: harmonic_number(3, 3) 251/216 - sage: harmonic_number(3,3).n() # this goes from rational to float + sage: harmonic_number(3, 3).n() # this goes from rational to float 1.16203703703704 - sage: harmonic_number(3,3.) # the following uses zeta functions + sage: harmonic_number(3, 3.) # the following uses zeta functions 1.16203703703704 - sage: harmonic_number(3.,3) + sage: harmonic_number(3., 3) zeta(3) - 0.0400198661225573 - sage: harmonic_number(0.1,5) + sage: harmonic_number(0.1, 5) zeta(5) - 0.650300133161038 - sage: harmonic_number(0.1,5).n() + sage: harmonic_number(0.1, 5).n() 0.386627621982332 - sage: harmonic_number(3,5/2) + sage: harmonic_number(3, 5/2) 1/27*sqrt(3) + 1/8*sqrt(2) + 1 TESTS:: - sage: harmonic_number(int(3), int(3)) + sage: harmonic_number(int(3), int(3)) # needs sage.symbolic 1.162037037037037 """ if m == 0: @@ -1144,13 +1173,14 @@ def _evalf_(self, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: harmonic_number(3.,3) + sage: # needs sage.symbolic + sage: harmonic_number(3., 3) zeta(3) - 0.0400198661225573 - sage: harmonic_number(3.,3.) + sage: harmonic_number(3., 3.) 1.16203703703704 - sage: harmonic_number(3,3).n(200) + sage: harmonic_number(3, 3).n(200) 1.16203703703703703703703... - sage: harmonic_number(5,I).n() + sage: harmonic_number(5, I).n() 2.36889632899995 - 3.51181956521611*I """ if m == 0: @@ -1160,16 +1190,15 @@ def _evalf_(self, z, m, parent=None, algorithm=None): elif m == 1: return harmonic_m1._evalf_(z, parent, algorithm) - from sage.functions.transcendental import zeta, hurwitz_zeta return zeta(m) - hurwitz_zeta(m, z + 1) def _maxima_init_evaled_(self, n, z): """ EXAMPLES:: - sage: maxima_calculus(harmonic_number(x,2)) + sage: maxima_calculus(harmonic_number(x, 2)) # needs sage.symbolic gen_harmonic_number(2,_SAGE_VAR_x) - sage: maxima_calculus(harmonic_number(3,harmonic_number(x,3),hold=True)) + sage: maxima_calculus(harmonic_number(3, harmonic_number(x,3), hold=True)) # needs sage.symbolic 1/3^gen_harmonic_number(3,_SAGE_VAR_x)+1/2^gen_harmonic_number(3,_SAGE_VAR_x)+1 """ if isinstance(n, str): @@ -1192,6 +1221,7 @@ def _derivative_(self, n, m, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: k,m,n = var('k,m,n') sage: sum(1/k, k, 1, x).diff(x) 1/6*pi^2 - harmonic_number(x, 2) @@ -1204,7 +1234,6 @@ def _derivative_(self, n, m, diff_param=None): ... ValueError: cannot differentiate harmonic_number in the second parameter """ - from sage.functions.transcendental import zeta if diff_param == 1: raise ValueError("cannot differentiate harmonic_number in the second parameter") if m == 1: @@ -1216,9 +1245,9 @@ def _print_(self, z, m): """ EXAMPLES:: - sage: harmonic_number(x) + sage: harmonic_number(x) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x,2) + sage: harmonic_number(x, 2) # needs sage.symbolic harmonic_number(x, 2) """ if m == 1: @@ -1230,9 +1259,9 @@ def _print_latex_(self, z, m): """ EXAMPLES:: - sage: latex(harmonic_number(x)) + sage: latex(harmonic_number(x)) # needs sage.symbolic H_{x} - sage: latex(harmonic_number(x,2)) + sage: latex(harmonic_number(x, 2)) # needs sage.symbolic H_{{x},{2}} """ if m == 1: @@ -1250,13 +1279,14 @@ class _Function_swap_harmonic(BuiltinFunction): EXAMPLES:: - sage: maxima(harmonic_number(x,2)) # maxima expect interface + sage: # needs sage.symbolic + sage: maxima(harmonic_number(x, 2)) # maxima expect interface gen_harmonic_number(2,_SAGE_VAR_x) sage: from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms sage: sefms('gen_harmonic_number(3,x)') harmonic_number(x, 3) sage: from sage.interfaces.maxima_lib import maxima_lib, max_to_sr - sage: c=maxima_lib(harmonic_number(x,2)); c + sage: c = maxima_lib(harmonic_number(x,2)); c gen_harmonic_number(2,_SAGE_VAR_x) sage: max_to_sr(c.ecl()) harmonic_number(x, 2) @@ -1294,10 +1324,10 @@ def __init__(self): r""" EXAMPLES:: - sage: k=var('k') - sage: loads(dumps(sum(1/k,k,1,x))) + sage: k = var('k') # needs sage.symbolic + sage: loads(dumps(sum(1/k, k, 1, x))) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x)._sympy_() + sage: harmonic_number(x)._sympy_() # needs sympy sage.symbolic harmonic(x) """ BuiltinFunction.__init__(self, "harmonic_number", nargs=1, @@ -1310,15 +1340,15 @@ def _eval_(self, z, **kwds): """ EXAMPLES:: - sage: harmonic_number(0) + sage: harmonic_number(0) # needs mpmath 0 - sage: harmonic_number(1) + sage: harmonic_number(1) # needs mpmath 1 - sage: harmonic_number(20) + sage: harmonic_number(20) # needs mpmath 55835135/15519504 - sage: harmonic_number(5/2) + sage: harmonic_number(5/2) # needs sage.symbolic -2*log(2) + 46/15 - sage: harmonic_number(2*x) + sage: harmonic_number(2*x) # needs sage.symbolic harmonic_number(2*x) """ if z in ZZ: @@ -1327,28 +1357,25 @@ def _eval_(self, z, **kwds): elif z == 1: return Integer(1) elif z > 1: - import sage.libs.flint.arith as flint_arith - return flint_arith.harmonic_number(z) + return _flint_harmonic_number(z) elif z in QQ: - from .gamma import psi1 return psi1(z + 1) - psi1(1) def _evalf_(self, z, parent=None, algorithm='mpmath'): """ EXAMPLES:: - sage: harmonic_number(20).n() # this goes from rational to float + sage: # needs mpmath + sage: harmonic_number(20).n() # this goes from rational to float 3.59773965714368 sage: harmonic_number(20).n(200) 3.59773965714368191148376906... - sage: harmonic_number(20.) # this computes the integral with mpmath + sage: harmonic_number(20.) # this computes the integral with mpmath 3.59773965714368 - sage: harmonic_number(1.0*I) + sage: harmonic_number(1.0*I) # needs sage.symbolic 0.671865985524010 + 1.07667404746858*I """ - from sage.libs.mpmath import utils as mpmath_utils - import mpmath - return mpmath_utils.call(mpmath.harmonic, z, parent=parent) + return _mpmath_utils_call(_mpmath_harmonic, z, parent=parent) def _derivative_(self, z, diff_param=None): """ @@ -1356,19 +1383,18 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: - sage: k=var('k') - sage: sum(1/k,k,1,x).diff(x) + sage: k = var('k') # needs sage.symbolic + sage: sum(1/k, k, 1, x).diff(x) # needs sage.symbolic 1/6*pi^2 - harmonic_number(x, 2) """ - from sage.functions.transcendental import zeta return zeta(2) - harmonic_number(z, 2) def _print_latex_(self, z): """ EXAMPLES:: - sage: k=var('k') - sage: latex(sum(1/k,k,1,x)) + sage: k = var('k') # needs sage.symbolic + sage: latex(sum(1/k, k, 1, x)) # needs sage.symbolic H_{x} """ return r"H_{%s}" % z diff --git a/src/sage/functions/min_max.py b/src/sage/functions/min_max.py index 28419136e52..caaed6f1193 100644 --- a/src/sage/functions/min_max.py +++ b/src/sage/functions/min_max.py @@ -7,15 +7,16 @@ Here you can see some differences:: - sage: max(x, x^2) + sage: max(x, x^2) # needs sage.symbolic x - sage: max_symbolic(x, x^2) + sage: max_symbolic(x, x^2) # needs sage.symbolic max(x, x^2) - sage: f(x) = max_symbolic(x, x^2); f(1/2) + sage: f(x) = max_symbolic(x, x^2); f(1/2) # needs sage.symbolic 1/2 This works as expected for more than two entries:: + sage: # needs sage.symbolic sage: max(3, 5, x) 5 sage: min(3, 5, x) @@ -33,11 +34,13 @@ # https://www.gnu.org/licenses/ ############################################################################### +from builtins import max as builtin_max, min as builtin_min + +from sage.misc.lazy_import import lazy_import +from sage.structure.element import Expression from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression -from sage.symbolic.ring import SR -from builtins import max as builtin_max, min as builtin_min +lazy_import('sage.symbolic.ring', 'SR') class MinMax_base(BuiltinFunction): @@ -45,6 +48,7 @@ def eval_helper(self, this_f, builtin_f, initial_val, args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: max_symbolic(3, 5, x) # indirect doctest max(x, 5) sage: max_symbolic([5.0r]) # indirect doctest @@ -89,20 +93,20 @@ def __call__(self, *args, **kwds): """ EXAMPLES:: - sage: max_symbolic(3, 5, x) + sage: max_symbolic(3, 5, x) # needs sage.symbolic max(x, 5) - sage: max_symbolic(3, 5, x, hold=True) + sage: max_symbolic(3, 5, x, hold=True) # needs sage.symbolic max(3, 5, x) - sage: max_symbolic([3, 5, x]) + sage: max_symbolic([3, 5, x]) # needs sage.symbolic max(x, 5) :: - sage: min_symbolic(3, 5, x) + sage: min_symbolic(3, 5, x) # needs sage.symbolic min(x, 3) - sage: min_symbolic(3, 5, x, hold=True) + sage: min_symbolic(3, 5, x, hold=True) # needs sage.symbolic min(3, 5, x) - sage: min_symbolic([3, 5, x]) + sage: min_symbolic([3, 5, x]) # needs sage.symbolic min(x, 3) TESTS: @@ -116,6 +120,7 @@ def __call__(self, *args, **kwds): Check if a single argument which is not iterable works:: + sage: # needs sage.symbolic sage: max_symbolic(None) Traceback (most recent call last): ... @@ -162,6 +167,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: max_symbolic(3, x) max(3, x) sage: max_symbolic(3, x).subs(x=5) @@ -173,11 +179,11 @@ def __init__(self): TESTS:: - sage: loads(dumps(max_symbolic(x, 5))) + sage: loads(dumps(max_symbolic(x, 5))) # needs sage.symbolic max(x, 5) - sage: latex(max_symbolic(x, 5)) + sage: latex(max_symbolic(x, 5)) # needs sage.symbolic \max\left(x, 5\right) - sage: max_symbolic(x, 5)._sympy_() + sage: max_symbolic(x, 5)._sympy_() # needs sympy sage.symbolic Max(5, x) """ BuiltinFunction.__init__(self, 'max', nargs=0, latex_name=r"\max", @@ -187,6 +193,7 @@ def _eval_(self, *args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = max_symbolic(x, 5); t max(x, 5) sage: t.subs(x=3) # indirect doctest @@ -215,6 +222,7 @@ def _evalf_(self, *args, **kwds): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = max_symbolic(sin(x), cos(x)) sage: t.subs(x=1).n(200) 0.84147098480789650665250232163029899962256306079837106567275 @@ -231,10 +239,10 @@ def _evalf_(self, *args, **kwds): We can usually integrate these expressions, but can't guarantee a symbolic answer in closed form:: - sage: f = max_symbolic(sin(x), cos(x)) - sage: r = integral(f, x, 0, 1) + sage: f = max_symbolic(sin(x), cos(x)) # needs sage.symbolic + sage: r = integral(f, x, 0, 1) # needs sage.symbolic ... - sage: r.n() # abs tol 1e-8 + sage: r.n() # abs tol 1e-8 # needs sage.symbolic 0.873911256504955 """ return max_symbolic(args) @@ -254,6 +262,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: min_symbolic(3, x) min(3, x) sage: min_symbolic(3, x).subs(x=5) @@ -265,11 +274,11 @@ def __init__(self): TESTS:: - sage: loads(dumps(min_symbolic(x, 5))) + sage: loads(dumps(min_symbolic(x, 5))) # needs sage.symbolic min(x, 5) - sage: latex(min_symbolic(x, 5)) + sage: latex(min_symbolic(x, 5)) # needs sage.symbolic \min\left(x, 5\right) - sage: min_symbolic(x, 5)._sympy_() + sage: min_symbolic(x, 5)._sympy_() # needs sympy sage.symbolic Min(5, x) """ BuiltinFunction.__init__(self, 'min', nargs=0, latex_name=r"\min", @@ -279,6 +288,7 @@ def _eval_(self, *args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = min_symbolic(x, 5); t min(x, 5) sage: t.subs(x=3) # indirect doctest @@ -307,6 +317,7 @@ def _evalf_(self, *args, **kwds): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = min_symbolic(sin(x), cos(x)) sage: t.subs(x=1).n(200) 0.54030230586813971740093660744297660373231042061792222767010 diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 60c785c74d4..7a9322973ad 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -395,20 +395,33 @@ import warnings -from sage.misc.latex import latex -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import RR -from sage.rings.cc import CC -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing import sage.rings.abc -from sage.symbolic.function import BuiltinFunction, GinacFunction -from sage.symbolic.expression import Expression -from sage.symbolic.ring import SR -from sage.functions.other import factorial, binomial -from sage.structure.element import parent from sage.arith.misc import rising_factorial +from sage.misc.lazy_import import lazy_import +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.symbolic.function import BuiltinFunction, GinacFunction +from sage.structure.element import Expression, parent + +lazy_import('sage.functions.other', ['factorial', 'binomial']) + +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.cc', 'CC') +lazy_import('sage.rings.polynomial.polynomial_ring_constructor', 'PolynomialRing') +lazy_import('sage.rings.real_mpfr', 'RR') + +lazy_import('sage.symbolic.ring', 'SR') +lazy_import('sage.calculus.calculus', 'maxima', as_='_maxima') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('sage.libs.mpmath.all', 'chebyt', as_='_mpmath_chebyt') +lazy_import('sage.libs.mpmath.all', 'chebyu', as_='_mpmath_chebyu') +lazy_import('sage.libs.mpmath.all', 'laguerre', as_='_mpmath_laguerre') +lazy_import('sage.libs.mpmath.all', 'legenp', as_='_mpmath_legenp') +lazy_import('sage.libs.mpmath.all', 'legenq', as_='_mpmath_legenq') + +lazy_import('scipy.special', 'eval_chebyu', as_='_scipy_chebyu') class OrthogonalFunction(BuiltinFunction): @@ -466,9 +479,9 @@ def _eval_special_values_(self, *args): EXAMPLES:: - sage: var('n') + sage: var('n') # needs sage.symbolic n - sage: chebyshev_T(n,-1) + sage: chebyshev_T(n, -1) # needs sage.symbolic (-1)^n """ raise ValueError("no special values known") @@ -480,9 +493,9 @@ def _eval_(self, n, *args): EXAMPLES:: - sage: var('n,x') + sage: var('n,x') # needs sage.symbolic (n, x) - sage: chebyshev_T(5,x) + sage: chebyshev_T(5, x) # needs sage.symbolic 16*x^5 - 20*x^3 + 5*x """ return None @@ -497,9 +510,10 @@ def __call__(self, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: chebyshev_T(5, x) 16*x^5 - 20*x^3 + 5*x - sage: chebyshev_T(5, x, algorithm='pari') + sage: chebyshev_T(5, x, algorithm='pari') # needs sage.libs.pari 16*x^5 - 20*x^3 + 5*x sage: chebyshev_T(5, x, algorithm='maxima') 16*x^5 - 20*x^3 + 5*x @@ -512,9 +526,8 @@ def __call__(self, *args, **kwds): elif algorithm == 'recursive': return self.eval_recursive(*args, **kwds) elif algorithm == 'maxima': - from sage.calculus.calculus import maxima kwds['hold'] = True - return maxima(self._eval_(*args, **kwds))._sage_() + return _maxima(self._eval_(*args, **kwds))._sage_() return super(OrthogonalFunction, self).__call__(*args, **kwds) @@ -525,7 +538,7 @@ class ChebyshevFunction(OrthogonalFunction): EXAMPLES:: - sage: chebyshev_T(3,x) + sage: chebyshev_T(3, x) # needs sage.symbolic 4*x^3 - 3*x """ def __call__(self, n, *args, **kwds): @@ -538,16 +551,17 @@ def __call__(self, n, *args, **kwds): EXAMPLES:: - sage: K. = NumberField(x^3-x-1) - sage: chebyshev_T(5, a) + sage: x = polygen(QQ, 'x') + sage: K. = NumberField(x^3 - x - 1) # needs sage.rings.number_field + sage: chebyshev_T(5, a) # needs sage.rings.number_field 16*a^2 + a - 4 - sage: chebyshev_T(5,MatrixSpace(ZZ, 2)([1, 2, -4, 7])) + sage: chebyshev_T(5, MatrixSpace(ZZ, 2)([1, 2, -4, 7])) # needs sage.modules [-40799 44162] [-88324 91687] sage: R. = QQ[] sage: parent(chebyshev_T(5, x)) Univariate Polynomial Ring in x over Rational Field - sage: chebyshev_T(5, 2, hold=True) + sage: chebyshev_T(5, 2, hold=True) # needs sage.symbolic chebyshev_T(5, 2) sage: chebyshev_T(1,2,3) Traceback (most recent call last): @@ -570,18 +584,20 @@ def _eval_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n,x') (n, x) - sage: chebyshev_T(5,x) + sage: chebyshev_T(5, x) 16*x^5 - 20*x^3 + 5*x sage: chebyshev_T(64, x) 2*(2*(2*(2*(2*(2*x^2 - 1)^2 - 1)^2 - 1)^2 - 1)^2 - 1)^2 - 1 - sage: chebyshev_T(n,-1) + sage: chebyshev_T(n, -1) (-1)^n - sage: chebyshev_T(-7,x) + sage: chebyshev_T(-7, x) 64*x^7 - 112*x^5 + 56*x^3 - 7*x - sage: chebyshev_T(3/2,x) + sage: chebyshev_T(3/2, x) chebyshev_T(3/2, x) + sage: R. = QQ[] sage: chebyshev_T(2,t) 2*t^2 - 1 @@ -589,14 +605,14 @@ def _eval_(self, n, x): 4*t^2 - 1 sage: parent(chebyshev_T(4, RIF(5))) Real Interval Field with 53 bits of precision - sage: RR2 = RealField(5) - sage: chebyshev_T(100000,RR2(2)) + sage: RR2 = RealField(5) # needs sage.rings.real_mpfr + sage: chebyshev_T(100000, RR2(2)) # needs sage.rings.real_mpfr 8.9e57180 - sage: chebyshev_T(5,Qp(3)(2)) + sage: chebyshev_T(5, Qp(3)(2)) # needs sage.rings.padics 2 + 3^2 + 3^3 + 3^4 + 3^5 + O(3^20) - sage: chebyshev_T(100001/2, 2) + sage: chebyshev_T(100001/2, 2) # needs sage.symbolic ...chebyshev_T(100001/2, 2) - sage: chebyshev_U._eval_(1.5, Mod(8,9)) is None + sage: chebyshev_U._eval_(1.5, Mod(8,9)) is None # needs mpmath True """ # n is an integer => evaluate algebraically (as polynomial) @@ -639,12 +655,11 @@ class Func_chebyshev_T(ChebyshevFunction): EXAMPLES:: - sage: chebyshev_T(5,x) + sage: chebyshev_T(5, x) # needs sage.symbolic 16*x^5 - 20*x^3 + 5*x - sage: var('k') + sage: var('k') # needs sage.symbolic k - sage: test = chebyshev_T(k,x) - sage: test + sage: test = chebyshev_T(k, x); test # needs sage.symbolic chebyshev_T(k, x) """ def __init__(self): @@ -653,15 +668,16 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n, x') (n, x) sage: from sage.functions.orthogonal_polys import Func_chebyshev_T sage: chebyshev_T2 = Func_chebyshev_T() - sage: chebyshev_T2(1,x) + sage: chebyshev_T2(1, x) x - sage: chebyshev_T(x, x)._sympy_() + sage: chebyshev_T(x, x)._sympy_() # needs sympy chebyshevt(x, x) - sage: maxima(chebyshev_T(1,x, hold=True)) + sage: maxima(chebyshev_T(1, x, hold=True)) _SAGE_VAR_x sage: maxima(chebyshev_T(n, chebyshev_T(n, x))) chebyshev_t(_SAGE_VAR_n,chebyshev_t(_SAGE_VAR_n,_SAGE_VAR_x)) @@ -685,7 +701,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(chebyshev_T(3, x, hold=True)) + sage: latex(chebyshev_T(3, x, hold=True)) # needs sage.symbolic T_{3}\left(x\right) """ return r"T_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -697,15 +713,16 @@ def _eval_special_values_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n') n - sage: chebyshev_T(n,1) + sage: chebyshev_T(n, 1) 1 - sage: chebyshev_T(n,0) + sage: chebyshev_T(n, 0) 1/2*(-1)^(1/2*n)*((-1)^n + 1) - sage: chebyshev_T(n,-1) + sage: chebyshev_T(n, -1) (-1)^n - sage: chebyshev_T._eval_special_values_(3/2,x) + sage: chebyshev_T._eval_special_values_(3/2, x) Traceback (most recent call last): ... ValueError: no special value found @@ -731,13 +748,14 @@ def _evalf_(self, n, x, **kwds): EXAMPLES:: - sage: chebyshev_T._evalf_(10,3) + sage: # needs sage.rings.real_mpfr + sage: chebyshev_T._evalf_(10, 3) 2.26195370000000e7 - sage: chebyshev_T._evalf_(10,3,parent=RealField(75)) + sage: chebyshev_T._evalf_(10, 3, parent=RealField(75)) 2.261953700000000000000e7 - sage: chebyshev_T._evalf_(10,I) + sage: chebyshev_T._evalf_(10, I) # needs sage.symbolic -3363.00000000000 - sage: chebyshev_T._evalf_(5,0.3) + sage: chebyshev_T._evalf_(5, 0.3) 0.998880000000000 sage: chebyshev_T(1/2, 0) 0.707106781186548 @@ -750,15 +768,15 @@ def _evalf_(self, n, x, **kwds): This simply evaluates using :class:`RealField` or :class:`ComplexField`:: - sage: chebyshev_T(1234.5, RDF(2.1)) + sage: chebyshev_T(1234.5, RDF(2.1)) # needs sage.rings.real_mpfr 5.48174256255782e735 - sage: chebyshev_T(1234.5, I) + sage: chebyshev_T(1234.5, I) # needs sage.rings.real_mpfr sage.symbolic -1.21629397684152e472 - 1.21629397684152e472*I For large values of ``n``, mpmath fails (but the algebraic formula still works):: - sage: chebyshev_T._evalf_(10^6, 0.1) + sage: chebyshev_T._evalf_(10^6, 0.1) # needs sage.rings.real_mpfr Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. @@ -782,10 +800,7 @@ def _evalf_(self, n, x, **kwds): if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent)) - from sage.libs.mpmath.all import call as mpcall - from sage.libs.mpmath.all import chebyt as mpchebyt - - return mpcall(mpchebyt, n, x, parent=real_parent) + return _mpmath_utils_call(_mpmath_chebyt, n, x, parent=real_parent) def eval_formula(self, n, x): """ @@ -802,18 +817,20 @@ def eval_formula(self, n, x): EXAMPLES:: - sage: chebyshev_T.eval_formula(-1,x) + sage: # needs sage.symbolic + sage: chebyshev_T.eval_formula(-1, x) x - sage: chebyshev_T.eval_formula(0,x) + sage: chebyshev_T.eval_formula(0, x) 1 - sage: chebyshev_T.eval_formula(1,x) + sage: chebyshev_T.eval_formula(1, x) x - sage: chebyshev_T.eval_formula(2,0.1) == chebyshev_T._evalf_(2,0.1) - True - sage: chebyshev_T.eval_formula(10,x) + sage: chebyshev_T.eval_formula(10, x) 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1 - sage: chebyshev_T.eval_algebraic(10,x).expand() + sage: chebyshev_T.eval_algebraic(10, x).expand() 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1 + + sage: chebyshev_T.eval_formula(2, 0.1) == chebyshev_T._evalf_(2, 0.1) # needs sage.rings.complex_double + True """ if n < 0: return self.eval_formula(-n, x) @@ -841,9 +858,9 @@ def eval_algebraic(self, n, x): EXAMPLES:: - sage: chebyshev_T.eval_algebraic(5, x) + sage: chebyshev_T.eval_algebraic(5, x) # needs sage.symbolic 2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x - sage: chebyshev_T(-7, x) - chebyshev_T(7,x) + sage: chebyshev_T(-7, x) - chebyshev_T(7, x) # needs sage.symbolic 0 sage: R. = ZZ[] sage: chebyshev_T.eval_algebraic(-1, t) @@ -856,12 +873,15 @@ def eval_algebraic(self, n, x): 1/2 sage: chebyshev_T(7^100, Mod(2,3)) 2 - sage: n = 97; x = RIF(pi/2/n) - sage: chebyshev_T(n, cos(x)).contains_zero() + sage: n = 97; x = RIF(pi/2/n) # needs sage.symbolic + sage: chebyshev_T(n, cos(x)).contains_zero() # needs sage.symbolic True + + sage: # needs sage.rings.padics sage: R. = Zp(2, 8, 'capped-abs')[] - sage: chebyshev_T(10^6+1, t) - (2^7 + O(2^8))*t^5 + O(2^8)*t^4 + (2^6 + O(2^8))*t^3 + O(2^8)*t^2 + (1 + 2^6 + O(2^8))*t + O(2^8) + sage: chebyshev_T(10^6 + 1, t) + (2^7 + O(2^8))*t^5 + O(2^8)*t^4 + (2^6 + O(2^8))*t^3 + O(2^8)*t^2 + + (1 + 2^6 + O(2^8))*t + O(2^8) """ if n == 0: return parent(x).one() @@ -877,9 +897,9 @@ def _eval_recursive_(self, n, x, both=False): EXAMPLES:: - sage: chebyshev_T._eval_recursive_(5, x) + sage: chebyshev_T._eval_recursive_(5, x) # needs sage.symbolic (2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x, False) - sage: chebyshev_T._eval_recursive_(5, x, True) + sage: chebyshev_T._eval_recursive_(5, x, True) # needs sage.symbolic (2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x, 2*(2*x^2 - 1)^2 - 1) """ if n == 1: @@ -898,6 +918,7 @@ def _eval_numpy_(self, n, x): EXAMPLES:: + sage: # needs numpy scipy sage: import numpy sage: z = numpy.array([1,2]) sage: z2 = numpy.array([[1,2],[1,2]]) @@ -922,13 +943,14 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: var('k') k - sage: derivative(chebyshev_T(k,x),x) + sage: derivative(chebyshev_T(k, x), x) k*chebyshev_U(k - 1, x) - sage: derivative(chebyshev_T(3,x),x) + sage: derivative(chebyshev_T(3, x), x) 12*x^2 - 3 - sage: derivative(chebyshev_T(k,x),k) + sage: derivative(chebyshev_T(k, x), k) Traceback (most recent call last): ... NotImplementedError: derivative w.r.t. to the index is not supported yet @@ -965,13 +987,14 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n, x') (n, x) sage: from sage.functions.orthogonal_polys import Func_chebyshev_U sage: chebyshev_U2 = Func_chebyshev_U() - sage: chebyshev_U2(1,x) + sage: chebyshev_U2(1, x) 2*x - sage: chebyshev_U(x, x)._sympy_() + sage: chebyshev_U(x, x)._sympy_() # needs sympy chebyshevu(x, x) sage: maxima(chebyshev_U(2,x, hold=True)) 3*(...-...(8*(1-_SAGE_VAR_x))/3)+(4*(1-_SAGE_VAR_x)^2)/3+1) @@ -997,7 +1020,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(chebyshev_U(3, x, hold=True)) + sage: latex(chebyshev_U(3, x, hold=True)) # needs sage.symbolic U_{3}\left(x\right) """ return r"U_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -1018,6 +1041,7 @@ def eval_formula(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: chebyshev_U.eval_formula(10, x) 1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1 sage: chebyshev_U.eval_formula(-2, x) @@ -1054,13 +1078,13 @@ def eval_algebraic(self, n, x): EXAMPLES:: - sage: chebyshev_U.eval_algebraic(5,x) + sage: chebyshev_U.eval_algebraic(5, x) # needs sage.symbolic -2*((2*x + 1)*(2*x - 1)*x - 4*(2*x^2 - 1)*x)*(2*x + 1)*(2*x - 1) sage: parent(chebyshev_U(3, Mod(8,9))) Ring of integers modulo 9 sage: parent(chebyshev_U(3, Mod(1,9))) Ring of integers modulo 9 - sage: chebyshev_U(-3,x) + chebyshev_U(1,x) + sage: chebyshev_U(-3, x) + chebyshev_U(1, x) # needs sage.symbolic 0 sage: chebyshev_U(-1,Mod(5,8)) 0 @@ -1075,11 +1099,11 @@ def eval_algebraic(self, n, x): 1 sage: chebyshev_U.eval_algebraic(1, t) 2*t - sage: n = 97; x = RIF(pi/n) - sage: chebyshev_U(n-1, cos(x)).contains_zero() + sage: n = 97; x = RIF(pi/n) # needs sage.symbolic + sage: chebyshev_U(n - 1, cos(x)).contains_zero() # needs sage.symbolic True - sage: R. = Zp(2, 6, 'capped-abs')[] - sage: chebyshev_U(10^6+1, t) + sage: R. = Zp(2, 6, 'capped-abs')[] # needs sage.rings.padics + sage: chebyshev_U(10^6 + 1, t) # needs sage.rings.padics (2 + O(2^6))*t + O(2^6) """ if n == -1: @@ -1096,10 +1120,11 @@ def _eval_recursive_(self, n, x, both=False): EXAMPLES:: - sage: chebyshev_U._eval_recursive_(3, x) + sage: chebyshev_U._eval_recursive_(3, x) # needs sage.symbolic (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, False) - sage: chebyshev_U._eval_recursive_(3, x, True) - (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, ((2*x + 1)*(2*x - 1) + 2*x)*((2*x + 1)*(2*x - 1) - 2*x)) + sage: chebyshev_U._eval_recursive_(3, x, True) # needs sage.symbolic + (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, + ((2*x + 1)*(2*x - 1) + 2*x)*((2*x + 1)*(2*x - 1) - 2*x)) """ if n == 0: return parent(x).one(), 2*x @@ -1117,11 +1142,11 @@ def _evalf_(self, n, x, **kwds): EXAMPLES:: - sage: chebyshev_U(5,-4+3.*I) + sage: chebyshev_U(5,-4+3.*I) # needs sage.symbolic 98280.0000000000 - 11310.0000000000*I - sage: chebyshev_U(10,3).n(75) + sage: chebyshev_U(10, 3).n(75) # needs sage.symbolic 4.661117900000000000000e7 - sage: chebyshev_U._evalf_(1.5, Mod(8,9)) + sage: chebyshev_U._evalf_(1.5, Mod(8,9)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: cannot evaluate chebyshev_U with parent Ring of integers modulo 9 @@ -1143,10 +1168,7 @@ def _evalf_(self, n, x, **kwds): if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent)) - from sage.libs.mpmath.all import call as mpcall - from sage.libs.mpmath.all import chebyu as mpchebyu - - return mpcall(mpchebyu, n, x, parent=real_parent) + return _mpmath_utils_call(_mpmath_chebyu, n, x, parent=real_parent) def _eval_special_values_(self, n, x): """ @@ -1155,13 +1177,14 @@ def _eval_special_values_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n') n - sage: chebyshev_U(n,1) + sage: chebyshev_U(n, 1) n + 1 - sage: chebyshev_U(n,0) + sage: chebyshev_U(n, 0) 1/2*(-1)^(1/2*n)*((-1)^n + 1) - sage: chebyshev_U(n,-1) + sage: chebyshev_U(n, -1) (-1)^n*(n + 1) sage: chebyshev_U._eval_special_values_(n, 2) Traceback (most recent call last): @@ -1185,6 +1208,7 @@ def _eval_numpy_(self, n, x): EXAMPLES:: + sage: # needs numpy scipy sage: import numpy sage: z = numpy.array([1,2]) sage: z2 = numpy.array([[1,2],[1,2]]) @@ -1199,8 +1223,7 @@ def _eval_numpy_(self, n, x): sage: chebyshev_U(z,0.1) array([ 0.2 , -0.96]) """ - from scipy.special import eval_chebyu - return eval_chebyu(n, x) + return _scipy_chebyu(n, x) def _derivative_(self, n, x, diff_param): """ @@ -1209,13 +1232,14 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: var('k') k - sage: derivative(chebyshev_U(k,x),x) + sage: derivative(chebyshev_U(k,x), x) ((k + 1)*chebyshev_T(k + 1, x) - x*chebyshev_U(k, x))/(x^2 - 1) - sage: derivative(chebyshev_U(3,x),x) + sage: derivative(chebyshev_U(3,x), x) 24*x^2 - 4 - sage: derivative(chebyshev_U(k,x),k) + sage: derivative(chebyshev_U(k,x), k) Traceback (most recent call last): ... NotImplementedError: derivative w.r.t. to the index is not supported yet @@ -1234,29 +1258,31 @@ class Func_legendre_P(GinacFunction): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: legendre_P(4, 2.0) 55.3750000000000 sage: legendre_P(1, x) x - sage: legendre_P(4, x+1) + sage: legendre_P(4, x + 1) 35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8 sage: legendre_P(1/2, I+1.) 1.05338240025858 + 0.359890322109665*I sage: legendre_P(0, SR(1)).parent() Symbolic Ring - sage: legendre_P(0, 0) + sage: legendre_P(0, 0) # needs sage.symbolic 1 - sage: legendre_P(1, x) + sage: legendre_P(1, x) # needs sage.symbolic x + sage: # needs sage.symbolic sage: legendre_P(4, 2.) 55.3750000000000 - sage: legendre_P(5.5,1.00001) + sage: legendre_P(5.5, 1.00001) 1.00017875754114 - sage: legendre_P(1/2, I+1).n() + sage: legendre_P(1/2, I + 1).n() 1.05338240025858 + 0.359890322109665*I - sage: legendre_P(1/2, I+1).n(59) + sage: legendre_P(1/2, I + 1).n(59) 1.0533824002585801 + 0.35989032210966539*I sage: legendre_P(42, RR(12345678)) 2.66314881466753e309 @@ -1267,22 +1293,24 @@ class Func_legendre_P(GinacFunction): sage: legendre_P(201/2, 0).n(100) 0.056138617863017877699963095883 + sage: # needs sage.symbolic sage: R. = QQ[] - sage: legendre_P(4,x) + sage: legendre_P(4, x) 35/8*x^4 - 15/4*x^2 + 3/8 - sage: legendre_P(10000,x).coefficient(x,1) + sage: legendre_P(10000, x).coefficient(x, 1) 0 sage: var('t,x') (t, x) - sage: legendre_P(-5,t) + sage: legendre_P(-5, t) 35/8*t^4 - 15/4*t^2 + 3/8 - sage: legendre_P(4, x+1) + sage: legendre_P(4, x + 1) 35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8 sage: legendre_P(4, sqrt(2)) 83/8 sage: legendre_P(4, I*e) 35/8*e^4 + 15/4*e^2 + 3/8 + sage: # needs sage.symbolic sage: n = var('n') sage: derivative(legendre_P(n,x), x) (n*x*legendre_P(n, x) - n*legendre_P(n - 1, x))/(x^2 - 1) @@ -1297,12 +1325,13 @@ class Func_legendre_P(GinacFunction): Verify that :trac:`33962` is fixed:: - sage: [legendre_P(n, 0) for n in range(-10, 10)] + sage: [legendre_P(n, 0) for n in range(-10, 10)] # needs sage.symbolic [0, 35/128, 0, -5/16, 0, 3/8, 0, -1/2, 0, 1, 1, 0, -1/2, 0, 3/8, 0, -5/16, 0, 35/128, 0] Verify that :trac:`33963` is fixed:: + sage: # needs sage.symbolic sage: n = var("n") sage: assume(n, "integer") sage: assume(n, "even") @@ -1336,7 +1365,7 @@ def __init__(self): sage: loads(dumps(legendre_Q)) legendre_Q - sage: maxima(legendre_Q(20,x, hold=True))._sage_().coefficient(x,10) + sage: maxima(legendre_Q(20, x, hold=True))._sage_().coefficient(x, 10) # needs sage.symbolic -29113619535/131072*log(-(x + 1)/(x - 1)) """ BuiltinFunction.__init__(self, "legendre_Q", nargs=2, latex_name=r"Q", @@ -1350,15 +1379,16 @@ def _eval_(self, n, x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: legendre_Q(2,x) 1/4*(3*x^2 - 1)*(log(x + 1) - log(-x + 1)) - 3/2*x - sage: legendre_Q(5,0) + sage: legendre_Q(5, 0) -8/15 - sage: legendre_Q(2,2*x) + sage: legendre_Q(2, 2*x) 1/4*(12*x^2 - 1)*(log(2*x + 1) - log(-2*x + 1)) - 3*x sage: legendre_Q(1/2, I+1.) -0.511424110789061 + 1.34356195297194*I - sage: legendre_Q(-1,x) + sage: legendre_Q(-1, x) Infinity """ ret = self._eval_special_values_(n, x) @@ -1376,6 +1406,7 @@ def _eval_special_values_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n') n sage: legendre_Q(n, 0) @@ -1415,20 +1446,18 @@ def _evalf_(self, n, x, parent=None, **kwds): EXAMPLES:: - sage: legendre_Q(4, 2.) + sage: legendre_Q(4, 2.) # needs mpmath 0.00116107583162041 - 86.9828465962674*I - sage: legendre_Q(1/2, I+1.) + sage: legendre_Q(1/2, I+1.) # needs sage.symbolic -0.511424110789061 + 1.34356195297194*I - sage: legendre_Q(1/2, I+1).n(59) + sage: legendre_Q(1/2, I+1).n(59) # needs sage.symbolic -0.51142411078906080 + 1.3435619529719394*I """ ret = self._eval_special_values_(n, x) if ret is not None: return ret - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.legenq, n, 0, x, parent=parent) + return _mpmath_utils_call(_mpmath_legenq, n, 0, x, parent=parent) def eval_recursive(self, n, arg, **kwds): """ @@ -1436,9 +1465,9 @@ def eval_recursive(self, n, arg, **kwds): EXAMPLES:: - sage: legendre_Q.eval_recursive(2,x) + sage: legendre_Q.eval_recursive(2, x) # needs sage.symbolic 3/4*x^2*(log(x + 1) - log(-x + 1)) - 3/2*x - 1/4*log(x + 1) + 1/4*log(-x + 1) - sage: legendre_Q.eval_recursive(20,x).expand().coefficient(x,10) + sage: legendre_Q.eval_recursive(20, x).expand().coefficient(x, 10) # needs sage.symbolic -29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1) """ from sage.functions.log import ln @@ -1472,15 +1501,17 @@ def eval_formula(self, n, arg, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: legendre_Q.eval_formula(1, x) 1/2*x*(log(x + 1) - log(-x + 1)) - 1 - sage: legendre_Q.eval_formula(2,x).expand().collect(log(1+x)).collect(log(1-x)) + sage: legendre_Q.eval_formula(2, x).expand().collect(log(1+x)).collect(log(1-x)) 1/4*(3*x^2 - 1)*log(x + 1) - 1/4*(3*x^2 - 1)*log(-x + 1) - 3/2*x - sage: legendre_Q.eval_formula(20,x).coefficient(x,10) + sage: legendre_Q.eval_formula(20, x).coefficient(x, 10) -29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1) sage: legendre_Q(0, 2) -1/2*I*pi + 1/2*log(3) - sage: legendre_Q(0, 2.) + + sage: legendre_Q(0, 2.) # needs mpmath 0.549306144334055 - 1.57079632679490*I """ from sage.functions.log import ln @@ -1498,9 +1529,9 @@ def _Wfunc(self, n, arg): EXAMPLES:: - sage: legendre_Q._Wfunc(2, x) + sage: legendre_Q._Wfunc(2, x) # needs sage.symbolic 3/2*x - sage: legendre_Q._Wfunc(7, x) + sage: legendre_Q._Wfunc(7, x) # needs sage.symbolic 429/16*x^6 - 275/8*x^4 + 849/80*x^2 - 16/35 """ if n == 0: @@ -1524,14 +1555,15 @@ def _derivative_(self, n, x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: derivative(legendre_Q(n,x), x) (n*x*legendre_Q(n, x) - n*legendre_Q(n - 1, x))/(x^2 - 1) - sage: ex1 = legendre_Q(5,x,hold=True).diff(x).expand().simplify_full() - sage: ex2 = legendre_Q(5,x).diff(x).expand().simplify_full() + sage: ex1 = legendre_Q(5, x, hold=True).diff(x).expand().simplify_full() + sage: ex2 = legendre_Q(5, x).diff(x).expand().simplify_full() sage: ex1.subs(x=7).n() == ex2.subs(x=7).n() True - sage: derivative(legendre_Q(n,x), n) + sage: derivative(legendre_Q(n, x), n) Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the index is not supported. @@ -1580,7 +1612,7 @@ class Func_assoc_legendre_P(BuiltinFunction): We give the first Ferrers functions for non-negative integers `n` and `m` in the interval `-1 |n|` for integers:: - sage: gen_legendre_P(2,3,4) + sage: gen_legendre_P(2, 3, 4) # needs mpmath 0 Case `x = 0`:: - sage: gen_legendre_P(13/2,2,0) + sage: # needs sage.symbolic + sage: gen_legendre_P(13/2, 2, 0) 4*sqrt(pi)/(gamma(13/4)*gamma(-15/4)) - sage: (m,n) = var('m,n') - sage: gen_legendre_P(n,m,0) + sage: m, n = var('m,n') + sage: gen_legendre_P(n, m, 0) sqrt(pi)*2^m/(gamma(-1/2*m + 1/2*n + 1)*gamma(-1/2*m - 1/2*n + 1/2)) - sage: gen_legendre_P(n,3,0) + sage: gen_legendre_P(n, 3, 0) 8*sqrt(pi)/(gamma(1/2*n - 1/2)*gamma(-1/2*n - 1)) - sage: gen_legendre_P(3,m,0) + sage: gen_legendre_P(3, m, 0) sqrt(pi)*2^m/(gamma(-1/2*m + 5/2)*gamma(-1/2*m - 1)) Case `m = n` for integers:: + sage: # needs sage.symbolic sage: m = var('m') sage: assume(m, 'integer') sage: gen_legendre_P(m, m, x) @@ -1739,9 +1775,9 @@ def _eval_special_values_(self, n, m, x): Case `n = 0`:: - sage: gen_legendre_P(m, 0, x) + sage: gen_legendre_P(m, 0, x) # needs sage.symbolic legendre_P(m, x) - sage: gen_legendre_P(2,0,4) == legendre_P(2,4) + sage: gen_legendre_P(2, 0, 4) == legendre_P(2, 4) # needs sage.symbolic True """ @@ -1769,11 +1805,11 @@ def _eval_int_ord_deg_(self, n, m, x): TESTS:: - sage: gen_legendre_P._eval_int_ord_deg_(-2, 1, x) + sage: gen_legendre_P._eval_int_ord_deg_(-2, 1, x) # needs sage.symbolic -sqrt(-x^2 + 1) - sage: gen_legendre_P._eval_int_ord_deg_(2, -1, x) + sage: gen_legendre_P._eval_int_ord_deg_(2, -1, x) # needs sage.symbolic 1/2*sqrt(-x^2 + 1)*x - sage: gen_legendre_P._eval_int_ord_deg_(-2, -1, x) + sage: gen_legendre_P._eval_int_ord_deg_(-2, -1, x) # needs sage.symbolic 1/2*sqrt(-x^2 + 1) """ @@ -1793,19 +1829,17 @@ def _evalf_(self, n, m, x, parent=None, **kwds): EXAMPLES:: - sage: gen_legendre_P(10,2,3).n() # abs tol 1e-14 + sage: gen_legendre_P(10, 2, 3).n() # abs tol 1e-14 # needs sage.symbolic -7.19496360000000e8 - sage: gen_legendre_P(5/2,2,1.+I) + sage: gen_legendre_P(5/2,2,1.+I) # needs sage.symbolic 14.3165258449040 - 12.7850496155152*I - sage: gen_legendre_P(5/2,2,ComplexField(70)(1+I)) + sage: gen_legendre_P(5/2, 2, ComplexField(70)(1+I)) # needs sage.rings.real_mpfr sage.symbolic 14.316525844904028532 - 12.785049615515157033*I - sage: gen_legendre_P(2/3,1,0.) + sage: gen_legendre_P(2/3, 1, 0.) # needs mpmath -0.773063511309286 """ - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.legenp, n, m, x, parent=parent) + return _mpmath_utils_call(_mpmath_legenp, n, m, x, parent=parent) def eval_gen_poly(self, n, m, arg, **kwds): r""" @@ -1826,9 +1860,9 @@ def eval_gen_poly(self, n, m, arg, **kwds): EXAMPLES:: - sage: gen_legendre_P(7,4,x) + sage: gen_legendre_P(7, 4, x) # needs sage.symbolic 3465/2*(13*x^3 - 3*x)*(x^2 - 1)^2 - sage: gen_legendre_P(3,1,sqrt(x)) + sage: gen_legendre_P(3, 1, sqrt(x)) # needs sage.symbolic -3/2*(5*x - 1)*sqrt(-x + 1) REFERENCE: @@ -1855,10 +1889,12 @@ def _derivative_(self, n, m, x, *args, **kwds): EXAMPLES:: - sage: (m,n) = var('m,n') + sage: # needs sage.symbolic + sage: m, n = var('m,n') sage: derivative(gen_legendre_P(n,m,x), x) - -((n + 1)*x*gen_legendre_P(n, m, x) + (m - n - 1)*gen_legendre_P(n + 1, m, x))/(x^2 - 1) - sage: gen_legendre_P(3,2,x,hold=True).diff(x).expand().simplify_full() + -((n + 1)*x*gen_legendre_P(n, m, x) + + (m - n - 1)*gen_legendre_P(n + 1, m, x))/(x^2 - 1) + sage: gen_legendre_P(3, 2, x, hold=True).diff(x).expand().simplify_full() -45*x^2 + 15 sage: derivative(gen_legendre_P(n,m,x), n) Traceback (most recent call last): @@ -1884,7 +1920,7 @@ def __init__(self): sage: loads(dumps(gen_legendre_Q)) gen_legendre_Q - sage: maxima(gen_legendre_Q(2,1,3, hold=True))._sage_().simplify_full() + sage: maxima(gen_legendre_Q(2, 1, 3, hold=True))._sage_().simplify_full() # needs sage.symbolic 1/4*sqrt(2)*(36*pi - 36*I*log(2) + 25*I) """ BuiltinFunction.__init__(self, "gen_legendre_Q", nargs=3, latex_name=r"Q", @@ -1898,7 +1934,7 @@ def _eval_(self, n, m, x, *args, **kwds): EXAMPLES:: - sage: gen_legendre_Q(2,1,3) + sage: gen_legendre_Q(2, 1, 3) # needs sage.symbolic -1/4*sqrt(-2)*(-36*I*pi + 36*log(2) - 25) """ ret = self._eval_special_values_(n, m, x) @@ -1915,8 +1951,8 @@ def _eval_special_values_(self, n, m, x): EXAMPLES:: - sage: n, m = var('n m') - sage: gen_legendre_Q(n,m,0) + sage: n, m = var('n m') # needs sage.symbolic + sage: gen_legendre_Q(n, m, 0) # needs sage.symbolic -sqrt(pi)*2^(m - 1)*gamma(1/2*m + 1/2*n + 1/2)*sin(1/2*pi*m + 1/2*pi*n)/gamma(-1/2*m + 1/2*n + 1) """ if m == 0: @@ -1936,18 +1972,16 @@ def _evalf_(self, n, m, x, parent=None, **kwds): EXAMPLES:: - sage: gen_legendre_Q(2,1,3.) + sage: gen_legendre_Q(2, 1, 3.) # needs mpmath -39.9859464434253 + 0.0165114736149193*I - sage: gen_legendre_Q(2,1,ComplexField(70)(3)) + sage: gen_legendre_Q(2, 1, ComplexField(70)(3)) # needs sage.rings.real_mpfr -39.985946443425296223 + 0.016511473614919329585*I """ ret = self._eval_special_values_(n, m, x) if ret is not None: return ret - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.legenq, n, m, x, parent=parent) + return _mpmath_utils_call(_mpmath_legenq, n, m, x, parent=parent) def eval_recursive(self, n, m, x, **kwds): """ @@ -1955,15 +1989,16 @@ def eval_recursive(self, n, m, x, **kwds): EXAMPLES:: - sage: gen_legendre_Q(3,4,x) + sage: # needs sage.symbolic + sage: gen_legendre_Q(3, 4, x) 48/(x^2 - 1)^2 - sage: gen_legendre_Q(4,5,x) + sage: gen_legendre_Q(4, 5, x) -384/((x^2 - 1)^2*sqrt(-x^2 + 1)) - sage: gen_legendre_Q(0,1,x) + sage: gen_legendre_Q(0, 1, x) -1/sqrt(-x^2 + 1) - sage: gen_legendre_Q(0,2,x) + sage: gen_legendre_Q(0, 2, x) -1/2*((x + 1)^2 - (x - 1)^2)/(x^2 - 1) - sage: gen_legendre_Q(2,2,x).subs(x=2).expand() + sage: gen_legendre_Q(2, 2, x).subs(x=2).expand() 9/2*I*pi - 9/2*log(3) + 14/3 """ from sage.misc.functional import sqrt @@ -1985,11 +2020,13 @@ def _derivative_(self, n, m, x, *args, **kwds): EXAMPLES:: - sage: (m,n) = var('m,n') + sage: # needs sage.symbolic + sage: m, n = var('m,n') sage: derivative(gen_legendre_Q(n,m,x), x) - -((n + 1)*x*gen_legendre_Q(n, m, x) + (m - n - 1)*gen_legendre_Q(n + 1, m, x))/(x^2 - 1) - sage: ex1=gen_legendre_Q(3,2,x,hold=True).diff(x).expand().simplify_full() - sage: ex2=gen_legendre_Q(3,2,x).diff(x).expand().simplify_full() + -((n + 1)*x*gen_legendre_Q(n, m, x) + + (m - n - 1)*gen_legendre_Q(n + 1, m, x))/(x^2 - 1) + sage: ex1 = gen_legendre_Q(3, 2, x, hold=True).diff(x).expand().simplify_full() + sage: ex2 = gen_legendre_Q(3, 2, x).diff(x).expand().simplify_full() sage: ex1.subs(x=5).n() == ex2.subs(x=5).n() True sage: derivative(gen_legendre_Q(n,m,x), n) @@ -2017,44 +2054,43 @@ class Func_hermite(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: x = PolynomialRing(QQ, 'x').gen() - sage: hermite(2,x) + sage: hermite(2, x) 4*x^2 - 2 - sage: hermite(3,x) + sage: hermite(3, x) 8*x^3 - 12*x - sage: hermite(3,2) + sage: hermite(3, 2) 40 sage: S. = PolynomialRing(RR) - sage: hermite(3,y) + sage: hermite(3, y) 8.00000000000000*y^3 - 12.0000000000000*y sage: R. = QQ[] - sage: hermite(3,y^2) + sage: hermite(3, y^2) 8*y^6 - 12*y^2 sage: w = var('w') - sage: hermite(3,2*w) + sage: hermite(3, 2*w) 64*w^3 - 24*w - sage: hermite(5,3.1416) + sage: hermite(5, 3.1416) 5208.69733891963 - sage: hermite(5,RealField(100)(pi)) + sage: hermite(5, RealField(100)(pi)) 5208.6167627118104649470287166 Check that :trac:`17192` is fixed:: + sage: # needs sage.symbolic sage: x = PolynomialRing(QQ, 'x').gen() - sage: hermite(0,x) + sage: hermite(0, x) 1 - - sage: hermite(-1,x) + sage: hermite(-1, x) Traceback (most recent call last): ... RuntimeError: hermite_eval: The index n must be a nonnegative integer - - sage: hermite(-7,x) + sage: hermite(-7, x) Traceback (most recent call last): ... RuntimeError: hermite_eval: The index n must be a nonnegative integer - - sage: m,x = SR.var('m,x') + sage: m, x = SR.var('m,x') sage: hermite(m, x).diff(m) Traceback (most recent call last): ... @@ -2068,17 +2104,17 @@ def __init__(self): sage: loads(dumps(hermite)) hermite - sage: hermite(x, x)._sympy_() + sage: hermite(x, x)._sympy_() # needs sympy sage.symbolic hermite(x, x) TESTS:: - sage: fricas(hermite(x, 5)) # optional - fricas + sage: fricas(hermite(x, 5)) # optional - fricas # needs sage.symbolic hermiteH(x,5) - sage: hermite(5,x) + sage: hermite(5, x) # needs sage.symbolic 32*x^5 - 160*x^3 + 120*x - sage: fricas.hermiteH(5,x) # optional - fricas + sage: fricas.hermiteH(5, x) # optional - fricas # needs sage.symbolic 5 3 32 x - 160 x + 120 x """ @@ -2111,7 +2147,7 @@ class Func_jacobi_P(OrthogonalFunction): sage: x = PolynomialRing(QQ, 'x').gen() sage: jacobi_P(2,0,0,x) 3/2*x^2 - 1/2 - sage: jacobi_P(2,1,2,1.2) + sage: jacobi_P(2,1,2,1.2) # needs sage.symbolic 5.01000000000000 """ def __init__(self): @@ -2120,22 +2156,22 @@ def __init__(self): EXAMPLES:: - sage: n,a,b,x = SR.var('n,a,b,x') + sage: n, a, b, x = SR.var('n,a,b,x') # needs sage.symbolic sage: loads(dumps(jacobi_P)) jacobi_P - sage: jacobi_P(n, a, b, x, hold=True)._sympy_() + sage: jacobi_P(n, a, b, x, hold=True)._sympy_() # needs sympy sage.symbolic jacobi(n, a, b, x) TESTS:: - sage: fricas(jacobi_P(1/2,4,1/3,x)) # optional - fricas + sage: fricas(jacobi_P(1/2, 4, 1/3, x)) # optional - fricas, needs sage.symbolic 1 1 jacobiP(-,4,-,x) 2 3 - sage: jacobi_P(1,2,3,x) + sage: jacobi_P(1, 2, 3, x) # needs sage.symbolic 7/2*x - 1/2 - sage: fricas.jacobiP(1,2,3,x) # optional - fricas + sage: fricas.jacobiP(1, 2, 3, x) # optional - fricas, needs sage.symbolic 7 x - 1 ------- 2 @@ -2151,16 +2187,17 @@ def _eval_(self, n, a, b, x): """ EXAMPLES:: - sage: n,a,b,x = SR.var('n,a,b,x') - sage: jacobi_P(1,n,n,n) + sage: # needs sage.symbolic + sage: n, a, b, x = SR.var('n,a,b,x') + sage: jacobi_P(1, n, n, n) (n + 1)*n - sage: jacobi_P(2,n,n,n) + sage: jacobi_P(2, n, n, n) 1/4*(2*n - 1)*(n + 2)*(n + 1)^2 - sage: jacobi_P(1,n,n,x) + sage: jacobi_P(1, n, n, x) (n + 1)*x - sage: jacobi_P(3,2,1,x) + sage: jacobi_P(3, 2, 1, x) 21/2*x^3 + 7/2*x^2 - 7/2*x - 1/2 - sage: jacobi_P(1,a,b,x) + sage: jacobi_P(1, a, b, x) 1/2*a*x + 1/2*b*x + 1/2*a - 1/2*b + x TESTS: @@ -2199,11 +2236,11 @@ def _evalf_(self, n, a, b, x, **kwds): """ EXAMPLES:: - sage: jacobi_P(2, 1, 2, 1.2) + sage: jacobi_P(2, 1, 2, 1.2) # needs sage.symbolic 5.01000000000000 - sage: jacobi_P(2, 1, 2, 1.2, hold=True).n(20) + sage: jacobi_P(2, 1, 2, 1.2, hold=True).n(20) # needs sage.symbolic 5.0100 - sage: jacobi_P(2, 1, 2, pi+I, hold=True).n(100) + sage: jacobi_P(2, 1, 2, pi + I, hold=True).n(100) # needs sage.symbolic 41.103034125334442891187112674 + 31.486722862692829003857755524*I """ from sage.rings.complex_arb import ComplexBallField as CBF @@ -2246,62 +2283,66 @@ class Func_ultraspherical(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: ultraspherical(8, 101/11, x) 795972057547264/214358881*x^8 - 62604543852032/19487171*x^6... sage: x = PolynomialRing(QQ, 'x').gen() - sage: ultraspherical(2,3/2,x) + sage: ultraspherical(2, 3/2, x) 15/2*x^2 - 3/2 - sage: ultraspherical(1,1,x) + sage: ultraspherical(1, 1, x) 2*x - sage: t = PolynomialRing(RationalField(),"t").gen() - sage: gegenbauer(3,2,t) + sage: t = PolynomialRing(RationalField(), "t").gen() + sage: gegenbauer(3, 2, t) 32*t^3 - 12*t sage: x = SR.var('x') sage: n = ZZ.random_element(5, 5001) sage: a = QQ.random_element().abs() + 5 - sage: s = ( (n+1)*ultraspherical(n+1,a,x) - ....: - 2*x*(n+a)*ultraspherical(n,a,x) - ....: + (n+2*a-1)*ultraspherical(n-1,a,x) ) + sage: s = ( (n + 1)*ultraspherical(n + 1, a, x) + ....: - 2*x*(n + a)*ultraspherical(n, a, x) + ....: + (n + 2*a - 1)*ultraspherical(n - 1, a, x) ) sage: s.expand().is_zero() True - sage: ultraspherical(5,9/10,3.1416) + sage: ultraspherical(5, 9/10, 3.1416) 6949.55439044240 - sage: ultraspherical(5,9/10,RealField(100)(pi)) + sage: ultraspherical(5, 9/10, RealField(100)(pi)) # needs sage.rings.real_mpfr 6949.4695419382702451843080687 - sage: a,n = SR.var('a,n') - sage: gegenbauer(2,a,x) + sage: # needs sage.symbolic + sage: a, n = SR.var('a,n') + sage: gegenbauer(2, a, x) 2*(a + 1)*a*x^2 - a - sage: gegenbauer(3,a,x) + sage: gegenbauer(3, a, x) 4/3*(a + 2)*(a + 1)*a*x^3 - 2*(a + 1)*a*x - sage: gegenbauer(3,a,x).expand() + sage: gegenbauer(3, a, x).expand() 4/3*a^3*x^3 + 4*a^2*x^3 + 8/3*a*x^3 - 2*a^2*x - 2*a*x - sage: gegenbauer(10,a,x).expand().coefficient(x,2) + sage: gegenbauer(10, a, x).expand().coefficient(x, 2) 1/12*a^6 + 5/4*a^5 + 85/12*a^4 + 75/4*a^3 + 137/6*a^2 + 10*a - sage: ex = gegenbauer(100,a,x) - sage: (ex.subs(a==55/98) - gegenbauer(100,55/98,x)).is_trivial_zero() + sage: ex = gegenbauer(100, a, x) + sage: (ex.subs(a==55/98) - gegenbauer(100, 55/98, x)).is_trivial_zero() True - sage: gegenbauer(2,-3,x) + sage: # needs sage.symbolic + sage: gegenbauer(2, -3, x) 12*x^2 + 3 sage: gegenbauer(120,-99/2,3) 1654502372608570682112687530178328494861923493372493824 - sage: gegenbauer(5,9/2,x) + sage: gegenbauer(5, 9/2, x) 21879/8*x^5 - 6435/4*x^3 + 1287/8*x sage: gegenbauer(15,3/2,5) 3903412392243800 - sage: derivative(gegenbauer(n,a,x),x) + sage: derivative(gegenbauer(n, a, x), x) # needs sage.symbolic 2*a*gegenbauer(n - 1, a + 1, x) - sage: derivative(gegenbauer(3,a,x),x) + sage: derivative(gegenbauer(3, a, x), x) # needs sage.symbolic 4*(a + 2)*(a + 1)*a*x^2 - 2*(a + 1)*a - sage: derivative(gegenbauer(n,a,x),a) + sage: derivative(gegenbauer(n, a, x), a) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: derivative w.r.t. to the second index is not supported yet Numerical evaluation with the mpmath library:: + sage: # needs mpmath sage: from mpmath import gegenbauer as gegenbauer_mp sage: from mpmath import mp sage: mp.pretty = True; mp.dps=25 @@ -2315,15 +2356,15 @@ class Func_ultraspherical(GinacFunction): Check that :trac:`17192` is fixed:: sage: x = PolynomialRing(QQ, 'x').gen() - sage: ultraspherical(0,1,x) + sage: ultraspherical(0, 1, x) # needs sage.symbolic 1 - sage: ultraspherical(-1,1,x) + sage: ultraspherical(-1, 1, x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: gegenb_eval: The index n must be a nonnegative integer - sage: ultraspherical(-7,1,x) + sage: ultraspherical(-7, 1, x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: gegenb_eval: The index n must be a nonnegative integer @@ -2336,7 +2377,7 @@ def __init__(self): sage: loads(dumps(ultraspherical)) gegenbauer - sage: ultraspherical(x, x, x)._sympy_() + sage: ultraspherical(x, x, x)._sympy_() # needs sympy sage.symbolic gegenbauer(x, x, x) """ GinacFunction.__init__(self, "gegenbauer", nargs=3, latex_name=r"C", @@ -2362,15 +2403,19 @@ def __init__(self): EXAMPLES:: - sage: n,x = var('n,x') - sage: loads(dumps(laguerre)) - laguerre - sage: laguerre(x, x)._sympy_() + sage: # needs sage.symbolic + sage: n, x = var('n,x') + sage: laguerre(x, x)._sympy_() # needs sympy laguerre(x, x) sage: maxima(laguerre(1, x, hold=True)) 1-_SAGE_VAR_x sage: maxima(laguerre(n, laguerre(n, x))) laguerre(_SAGE_VAR_n,laguerre(_SAGE_VAR_n,_SAGE_VAR_x)) + + TESTS:: + + sage: loads(dumps(laguerre)) + laguerre """ OrthogonalFunction.__init__(self, "laguerre", nargs=2, latex_name=r"L", conversions={'maxima': 'laguerre', @@ -2386,17 +2431,17 @@ def _eval_(self, n, x, *args, **kwds): EXAMPLES:: sage: x = PolynomialRing(QQ, 'x').gen() - sage: laguerre(2,x) + sage: laguerre(2, x) # needs mpmath 1/2*x^2 - 2*x + 1 - sage: laguerre(3,x) + sage: laguerre(3, x) # needs mpmath -1/6*x^3 + 3/2*x^2 - 3*x + 1 - sage: laguerre(2,2) + sage: laguerre(2, 2) # needs mpmath -1 - sage: laguerre(-1, x) + sage: laguerre(-1, x) # needs sage.symbolic e^x - sage: laguerre(-6, x) + sage: laguerre(-6, x) # needs sage.symbolic 1/120*(x^5 + 25*x^4 + 200*x^3 + 600*x^2 + 600*x + 120)*e^x - sage: laguerre(-9,2) + sage: laguerre(-9,2) # needs sage.symbolic 66769/315*e^2 """ from sage.rings.integer import Integer @@ -2416,9 +2461,9 @@ def _eval_special_values_(self, n, x): EXAMPLES:: - sage: laguerre(0, 0) + sage: laguerre(0, 0) # needs mpmath 1 - sage: laguerre(1, x) + sage: laguerre(1, x) # needs sage.symbolic -x + 1 """ if n == 0 or x == 0: @@ -2432,14 +2477,14 @@ def _pol_laguerre(self, n, x): EXAMPLES:: - sage: laguerre(3,sin(x)) + sage: laguerre(3, sin(x)) # needs sage.symbolic -1/6*sin(x)^3 + 3/2*sin(x)^2 - 3*sin(x) + 1 sage: R. = PolynomialRing(QQ, 'x') - sage: laguerre(4,x) + sage: laguerre(4, x) # needs mpmath 1/24*x^4 - 2/3*x^3 + 3*x^2 - 4*x + 1 - sage: laguerre(4,x+1) + sage: laguerre(4, x + 1) # needs mpmath 1/24*(x + 1)^4 - 2/3*(x + 1)^3 + 3*(x + 1)^2 - 4*x - 3 - sage: laguerre(10,1+I) + sage: laguerre(10,1+I) # needs sage.symbolic 142511/113400*I + 95867/22680 """ if hasattr(x, 'pyobject'): @@ -2456,24 +2501,22 @@ def _evalf_(self, n, x, **kwds): EXAMPLES:: - sage: laguerre(100,RealField(300)(pi)) + sage: laguerre(100, RealField(300)(pi)) # needs sage.symbolic -0.638322077840648311606324... - sage: laguerre(10,1.+I) + sage: laguerre(10,1.+I) # needs sage.symbolic 4.22694003527337 + 1.25671075837743*I - sage: laguerre(-9, 2.) + sage: laguerre(-9, 2.) # needs sage.symbolic 1566.22186244286 """ the_parent = kwds.get('parent', None) if the_parent is None: the_parent = parent(x) - import mpmath - from sage.libs.mpmath.all import call as mpcall if n < 0: # work around mpmath issue 307 from sage.functions.log import exp - return exp(x) * mpcall(mpmath.laguerre, -n-1, 0, -x, parent=the_parent) + return exp(x) * _mpmath_utils_call(_mpmath_laguerre, -n-1, 0, -x, parent=the_parent) else: - return mpcall(mpmath.laguerre, n, 0, x, parent=the_parent) + return _mpmath_utils_call(_mpmath_laguerre, n, 0, x, parent=the_parent) def _derivative_(self, n, x, *args, **kwds): """ @@ -2481,13 +2524,13 @@ def _derivative_(self, n, x, *args, **kwds): EXAMPLES:: - sage: n=var('n') - sage: diff(laguerre(n,x), x) + sage: n = var('n') # needs sage.symbolic + sage: diff(laguerre(n, x), x) # needs sage.symbolic -gen_laguerre(n - 1, 1, x) TESTS:: - sage: diff(laguerre(x,x)) + sage: diff(laguerre(x, x)) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the index is not supported. @@ -2515,15 +2558,19 @@ def __init__(self): EXAMPLES:: - sage: a,n,x = var('a, n, x') - sage: loads(dumps(gen_laguerre)) - gen_laguerre - sage: gen_laguerre(x, x, x)._sympy_() + sage: # needs sage.symbolic + sage: a, n, x = var('a, n, x') + sage: gen_laguerre(x, x, x)._sympy_() # needs sympy assoc_laguerre(x, x, x) - sage: maxima(gen_laguerre(1,2,x, hold=True)) + sage: maxima(gen_laguerre(1, 2, x, hold=True)) 3*(1-_SAGE_VAR_x/3) sage: maxima(gen_laguerre(n, a, gen_laguerre(n, a, x))) gen_laguerre(_SAGE_VAR_n,_SAGE_VAR_a, gen_laguerre(_SAGE_VAR_n,_SAGE_VAR_a,_SAGE_VAR_x)) + + TESTS:: + + sage: loads(dumps(gen_laguerre)) + gen_laguerre """ OrthogonalFunction.__init__(self, "gen_laguerre", nargs=3, latex_name=r"L", conversions={'maxima': 'gen_laguerre', @@ -2537,6 +2584,7 @@ def _eval_(self, n, a, x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: gen_laguerre(2, 1, x) 1/2*x^2 - 3*x + 3 sage: gen_laguerre(2, 1/2, x) @@ -2562,11 +2610,11 @@ def _eval_special_values_(self, n, a, x): EXAMPLES:: - sage: gen_laguerre(0, 1, pi) + sage: gen_laguerre(0, 1, pi) # needs sage.symbolic 1 - sage: gen_laguerre(1, 2, x) + sage: gen_laguerre(1, 2, x) # needs sage.symbolic -x + 3 - sage: gen_laguerre(3, 4, 0) + sage: gen_laguerre(3, 4, 0) # needs mpmath 35 """ if n == 0: @@ -2583,14 +2631,14 @@ def _pol_gen_laguerre(self, n, a, x): """ EXAMPLES:: - sage: gen_laguerre(3, 1/2, sin(x)) + sage: gen_laguerre(3, 1/2, sin(x)) # needs sage.symbolic -1/6*sin(x)^3 + 7/4*sin(x)^2 - 35/8*sin(x) + 35/16 sage: R. = PolynomialRing(QQ, 'x') - sage: gen_laguerre(4, -1/2, x) + sage: gen_laguerre(4, -1/2, x) # needs mpmath 1/24*x^4 - 7/12*x^3 + 35/16*x^2 - 35/16*x + 35/128 - sage: gen_laguerre(4, -1/2, x+1) + sage: gen_laguerre(4, -1/2, x + 1) # needs mpmath 1/24*(x + 1)^4 - 7/12*(x + 1)^3 + 35/16*(x + 1)^2 - 35/16*x - 245/128 - sage: gen_laguerre(10, 1, 1+I) + sage: gen_laguerre(10, 1, 1+I) # needs sage.symbolic 25189/2100*I + 11792/2835 """ return sum(binomial(n + a, n - k) * (-1)**k / factorial(k) * x**k @@ -2600,17 +2648,15 @@ def _evalf_(self, n, a, x, **kwds): """ EXAMPLES:: - sage: gen_laguerre(100,1,RealField(300)(pi)) + sage: gen_laguerre(100, 1, RealField(300)(pi)) # needs sage.symbolic -0.89430788373354541911... - sage: gen_laguerre(10,1/2,1.+I) + sage: gen_laguerre(10,1/2,1.+I) # needs sage.symbolic 5.34469635574906 + 5.23754057922902*I """ the_parent = kwds.get('parent', None) if the_parent is None: the_parent = parent(x) - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.laguerre, n, a, x, parent=the_parent) + return _mpmath_utils_call(_mpmath_laguerre, n, a, x, parent=the_parent) def _derivative_(self, n, a, x, diff_param): """ @@ -2618,17 +2664,17 @@ def _derivative_(self, n, a, x, diff_param): EXAMPLES:: - sage: (a,n)=var('a,n') - sage: diff(gen_laguerre(n,a,x), x) + sage: a, n = var('a,n') # needs sage.symbolic + sage: diff(gen_laguerre(n,a,x), x) # needs sage.symbolic -gen_laguerre(n - 1, a + 1, x) - sage: gen_laguerre(n,a,x).diff(a) + sage: gen_laguerre(n,a,x).diff(a) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the second index is not supported. TESTS:: - sage: diff(gen_laguerre(n,a,x), n) + sage: diff(gen_laguerre(n,a,x), n) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the index is not supported. @@ -2671,8 +2717,8 @@ class Func_krawtchouk(OrthogonalFunction): We verify the orthogonality for `n = 4`:: sage: n = 4 - sage: p = SR.var('p') - sage: matrix([[sum(binomial(n,m) * p**m * (1-p)**(n-m) + sage: p = SR.var('p') # needs sage.symbolic + sage: matrix([[sum(binomial(n,m) * p**m * (1-p)**(n-m) # needs sage.symbolic ....: * krawtchouk(i,m,n,p) * krawtchouk(j,m,n,p) ....: for m in range(n+1)).expand().factor() ....: for i in range(n+1)] for j in range(n+1)]) @@ -2684,8 +2730,8 @@ class Func_krawtchouk(OrthogonalFunction): We verify the relationship between the Krawtchouk implementations:: - sage: q = SR.var('q') - sage: all(codes.bounds.krawtchouk(n, 1/q, j, x)*(-q)^j + sage: q = SR.var('q') # needs sage.symbolic + sage: all(codes.bounds.krawtchouk(n, 1/q, j, x)*(-q)^j # needs sage.symbolic ....: == krawtchouk(j, x, n, 1-q) for j in range(n+1)) True """ @@ -2695,10 +2741,10 @@ def __init__(self): EXAMPLES:: - sage: k,x,n,p = var('k,x,n,p') + sage: k, x, n, p = var('k,x,n,p') # needs sage.symbolic sage: TestSuite(krawtchouk).run() - sage: TestSuite(krawtchouk(k, x, n, p)).run() - sage: TestSuite(krawtchouk(3, x, n, p)).run() + sage: TestSuite(krawtchouk(k, x, n, p)).run() # needs sage.symbolic + sage: TestSuite(krawtchouk(3, x, n, p)).run() # needs sage.symbolic """ super().__init__(name="krawtchouk", nargs=4, latex_name="K") @@ -2708,8 +2754,8 @@ def eval_formula(self, k, x, n, p): EXAMPLES:: - sage: x,n,p = var('x,n,p') - sage: krawtchouk.eval_formula(3, x, n, p).expand().collect(x) + sage: x, n, p = var('x,n,p') # needs sage.symbolic + sage: krawtchouk.eval_formula(3, x, n, p).expand().collect(x) # needs sage.symbolic -1/6*n^3*p^3 + 1/2*n^2*p^3 - 1/3*n*p^3 - 1/2*(n*p - 2*p + 1)*x^2 + 1/6*x^3 + 1/6*(3*n^2*p^2 - 9*n*p^2 + 3*n*p + 6*p^2 - 6*p + 2)*x """ @@ -2723,7 +2769,8 @@ def _eval_(self, j, x, n, p, *args, **kwds): EXAMPLES:: - sage: k,x,n,p = var('k,x,n,p') + sage: # needs sage.symbolic + sage: k, x, n, p = var('k,x,n,p') sage: krawtchouk(3, x, 5, p).expand() -10*p^3 + 6*p^2*x - 3/2*p*x^2 + 1/6*x^3 + 3/2*p*x - 1/2*x^2 + 1/3*x sage: krawtchouk(k, x, 5, p) @@ -2733,11 +2780,11 @@ def _eval_(self, j, x, n, p, *args, **kwds): sage: krawtchouk(k, x, n, p) (-1)^k*p^k*binomial(n, k)*hypergeometric((-k, -x), (-n,), 1/p) - sage: k3_hypergeo = krawtchouk(k,x,n,p)(k=3).simplify_hypergeometric() - sage: bool(k3_hypergeo == krawtchouk(3,x,n,p)) + sage: k3_hypergeo = krawtchouk(k,x,n,p)(k=3).simplify_hypergeometric() # needs sage.symbolic + sage: bool(k3_hypergeo == krawtchouk(3,x,n,p)) # needs sage.symbolic True - sage: krawtchouk(2,x,n,p,hold=True) + sage: krawtchouk(2, x, n, p, hold=True) # needs sage.symbolic krawtchouk(2, x, n, p) """ if kwds.get('hold', False): @@ -2757,21 +2804,24 @@ def eval_recursive(self, j, x, n, p, *args, **kwds): EXAMPLES:: - sage: x,n,p = var('x,n,p') - sage: krawtchouk.eval_recursive(0,x,n,p) + sage: # needs sage.symbolic + sage: x, n, p = var('x,n,p') + sage: krawtchouk.eval_recursive(0, x, n, p) 1 - sage: krawtchouk.eval_recursive(1,x,n,p) + sage: krawtchouk.eval_recursive(1, x, n, p) -n*p + x - sage: krawtchouk.eval_recursive(2,x,n,p).collect(x) - 1/2*n^2*p^2 + 1/2*n*(p - 1)*p - n*p^2 + 1/2*n*p - 1/2*(2*n*p - 2*p + 1)*x + 1/2*x^2 - sage: bool(krawtchouk.eval_recursive(2,x,n,p) == krawtchouk(2,x,n,p)) + sage: krawtchouk.eval_recursive(2, x, n, p).collect(x) + 1/2*n^2*p^2 + 1/2*n*(p - 1)*p - n*p^2 + 1/2*n*p + - 1/2*(2*n*p - 2*p + 1)*x + 1/2*x^2 + sage: bool(krawtchouk.eval_recursive(2, x, n, p) == krawtchouk(2, x, n, p)) True - sage: bool(krawtchouk.eval_recursive(3,x,n,p) == krawtchouk(3,x,n,p)) + sage: bool(krawtchouk.eval_recursive(3, x, n, p) == krawtchouk(3, x, n, p)) True - sage: bool(krawtchouk.eval_recursive(4,x,n,p) == krawtchouk(4,x,n,p)) + sage: bool(krawtchouk.eval_recursive(4, x, n, p) == krawtchouk(4, x, n, p)) True - sage: M = matrix([[-1/2,-1],[1,0]]) - sage: krawtchouk.eval_recursive(2, M, 3, 1/2) + + sage: M = matrix([[-1/2, -1], [1, 0]]) # needs sage.modules + sage: krawtchouk.eval_recursive(2, M, 3, 1/2) # needs sage.modules [ 9/8 7/4] [-7/4 1/4] """ @@ -2804,10 +2854,10 @@ def __init__(self): EXAMPLES:: - sage: n,x,b,c = var('n,x,b,c') + sage: n, x, b, c = var('n,x,b,c') # needs sage.symbolic sage: TestSuite(meixner).run() - sage: TestSuite(meixner(3, x, b, c)).run() - sage: TestSuite(meixner(n, x, b, c)).run() + sage: TestSuite(meixner(3, x, b, c)).run() # needs sage.symbolic + sage: TestSuite(meixner(n, x, b, c)).run() # needs sage.symbolic """ super().__init__(name="meixner", nargs=4, latex_name="M") @@ -2817,8 +2867,8 @@ def eval_formula(self, n, x, b, c): EXAMPLES:: - sage: x,b,c = var('x,b,c') - sage: meixner.eval_formula(3, x, b, c).expand().collect(x) + sage: x, b, c = var('x,b,c') # needs sage.symbolic + sage: meixner.eval_formula(3, x, b, c).expand().collect(x) # needs sage.symbolic -x^3*(3/c - 3/c^2 + 1/c^3 - 1) + b^3 + 3*(b - 2*b/c + b/c^2 - 1/c - 1/c^2 + 1/c^3 + 1)*x^2 + 3*b^2 + (3*b^2 + 6*b - 3*b^2/c - 3*b/c - 3*b/c^2 - 2/c^3 + 2)*x + 2*b @@ -2837,7 +2887,8 @@ def _eval_(self, n, x, b, c, *args, **kwds): EXAMPLES:: - sage: n,x,b,c = var('n,x,b,c') + sage: # needs sage.symbolic + sage: n, x, b, c = var('n,x,b,c') sage: meixner(2, x, b, c).collect(x) -x^2*(2/c - 1/c^2 - 1) + b^2 + (2*b - 2*b/c - 1/c^2 + 1)*x + b sage: meixner(3, x, b, c).factor().collect(x) @@ -2847,16 +2898,17 @@ def _eval_(self, n, x, b, c, *args, **kwds): sage: meixner(n, x, b, c) gamma(b + n)*hypergeometric((-n, -x), (b,), -1/c + 1)/gamma(b) - sage: n3_hypergeo = meixner(n,x,b,c)(n=3).simplify_hypergeometric() + sage: # needs sage.symbolic + sage: n3_hypergeo = meixner(n, x, b, c)(n=3).simplify_hypergeometric() sage: n3_hypergeo = n3_hypergeo.simplify_full() - sage: bool(n3_hypergeo == meixner(3,x,b,c)) + sage: bool(n3_hypergeo == meixner(3, x, b, c)) True - sage: n4_hypergeo = meixner(n,x,b,c)(n=4).simplify_hypergeometric() + sage: n4_hypergeo = meixner(n, x, b, c)(n=4).simplify_hypergeometric() sage: n4_hypergeo = n4_hypergeo.simplify_full() - sage: bool(n4_hypergeo == meixner(4,x,b,c)) + sage: bool(n4_hypergeo == meixner(4, x, b, c)) True - sage: meixner(2,x,b,c,hold=True) + sage: meixner(2, x, b, c, hold=True) # needs sage.symbolic meixner(2, x, b, c) """ if kwds.get('hold', False): @@ -2877,24 +2929,25 @@ def eval_recursive(self, n, x, b, c, *args, **kwds): EXAMPLES:: - sage: x,b,c = var('x,b,c') - sage: meixner.eval_recursive(0,x,b,c) + sage: # needs sage.symbolic + sage: x, b, c = var('x,b,c') + sage: meixner.eval_recursive(0, x, b, c) 1 - sage: meixner.eval_recursive(1,x,b,c) + sage: meixner.eval_recursive(1, x, b, c) -x*(1/c - 1) + b - sage: meixner.eval_recursive(2,x,b,c).simplify_full().collect(x) + sage: meixner.eval_recursive(2, x, b, c).simplify_full().collect(x) -x^2*(2/c - 1/c^2 - 1) + b^2 + (2*b - 2*b/c - 1/c^2 + 1)*x + b - sage: bool(meixner(2,x,b,c) == meixner.eval_recursive(2,x,b,c)) + sage: bool(meixner(2, x, b, c) == meixner.eval_recursive(2, x, b, c)) True - sage: bool(meixner(3,x,b,c) == meixner.eval_recursive(3,x,b,c)) + sage: bool(meixner(3, x, b, c) == meixner.eval_recursive(3, x, b, c)) True - sage: bool(meixner(4,x,b,c) == meixner.eval_recursive(4,x,b,c)) + sage: bool(meixner(4, x, b, c) == meixner.eval_recursive(4, x, b, c)) True - sage: M = matrix([[-1/2,-1],[1,0]]) + sage: M = matrix([[-1/2, -1], [1, 0]]) sage: ret = meixner.eval_recursive(2, M, b, c).simplify_full().factor() sage: for i in range(2): # make the output polynomials in 1/c ....: for j in range(2): - ....: ret[i,j] = ret[i,j].collect(c) + ....: ret[i, j] = ret[i, j].collect(c) sage: ret [b^2 + 1/2*(2*b + 3)/c - 1/4/c^2 - 5/4 -2*b + (2*b - 1)/c + 3/2/c^2 - 1/2] [ 2*b - (2*b - 1)/c - 3/2/c^2 + 1/2 b^2 + b + 2/c - 1/c^2 - 1] @@ -2926,20 +2979,21 @@ class Func_hahn(OrthogonalFunction): We verify the orthogonality for `n = 3`:: + sage: # needs sage.symbolic sage: n = 2 - sage: a,b = SR.var('a,b') - sage: def rho(k,a,b,n): - ....: return binomial(a+k,k) * binomial(b+n-k,n-k) - sage: M = matrix([[sum(rho(k,a,b,n) - ....: * hahn(i,k,a,b,n) * hahn(j,k,a,b,n) - ....: for k in range(n+1)).expand().factor() + sage: a, b = SR.var('a,b') + sage: def rho(k, a, b, n): + ....: return binomial(a + k, k) * binomial(b + n - k, n - k) + sage: M = matrix([[sum(rho(k, a, b, n) + ....: * hahn(i, k, a, b, n) * hahn(j, k, a, b, n) + ....: for k in range(n + 1)).expand().factor() ....: for i in range(n+1)] for j in range(n+1)]) sage: M = M.factor() sage: P = rising_factorial - sage: def diag(i,a,b,n): - ....: return ((-1)^i * factorial(i) * P(b+1,i) * P(i+a+b+1,n+1) - ....: / (factorial(n) * (2*i+a+b+1) * P(-n,i) * P(a+1,i))) - sage: all(M[i,i] == diag(i,a,b,n) for i in range(3)) + sage: def diag(i, a, b, n): + ....: return ((-1)^i * factorial(i) * P(b + 1, i) * P(i + a + b + 1, n + 1) + ....: / (factorial(n) * (2*i + a + b + 1) * P(-n, i) * P(a + 1, i))) + sage: all(M[i,i] == diag(i, a, b, n) for i in range(3)) True sage: all(M[i,j] == 0 for i in range(3) for j in range(3) if i != j) True @@ -2950,10 +3004,10 @@ def __init__(self): EXAMPLES:: - sage: k,x,a,b,n = var('k,x,a,b,n') + sage: k, x, a, b, n = var('k,x,a,b,n') # needs sage.symbolic sage: TestSuite(hahn).run() - sage: TestSuite(hahn(3, x, a, b, n)).run() - sage: TestSuite(hahn(k, x, a, b, n)).run(skip="_test_category") + sage: TestSuite(hahn(3, x, a, b, n)).run() # needs sage.symbolic + sage: TestSuite(hahn(k, x, a, b, n)).run(skip="_test_category") # needs sage.symbolic """ super().__init__(name="hahn", nargs=5, latex_name="Q") @@ -2963,7 +3017,8 @@ def eval_formula(self, k, x, a, b, n): EXAMPLES:: - sage: k,x,a,b,n = var('k,x,a,b,n') + sage: # needs sage.symbolic + sage: k, x, a, b, n = var('k,x,a,b,n') sage: Q2 = hahn.eval_formula(2, x, a, b, n).simplify_full() sage: Q2.coefficient(x^2).factor() (a + b + 4)*(a + b + 3)/((a + 2)*(a + 1)*(n - 1)*n) @@ -2982,20 +3037,21 @@ def _eval_(self, k, x, a, b, n, *args, **kwds): EXAMPLES:: - sage: k,x,a,b,n = var('k,x,a,b,n') - sage: hahn(1, x, a, b, n).collect(x) + sage: k, x, a, b, n = var('k,x,a,b,n') # needs sage.symbolic + sage: hahn(1, x, a, b, n).collect(x) # needs sage.symbolic -(a + b + 2)*x/((a + 1)*n) + 1 - sage: hahn(k, x, a, b, n) + sage: hahn(k, x, a, b, n) # needs sage.symbolic hypergeometric((-k, a + b + k + 1, -x), (a + 1, -n), 1) - sage: k2_hypergeo = hahn(k,x,a,b,n)(k=2).simplify_hypergeometric() - sage: bool(k2_hypergeo == hahn(2,x,a,b,n)) + sage: # needs sage.symbolic + sage: k2_hypergeo = hahn(k, x, a, b, n)(k=2).simplify_hypergeometric() + sage: bool(k2_hypergeo == hahn(2, x, a, b, n)) True - sage: k3_hypergeo = hahn(k,x,a,b,n)(k=3).simplify_hypergeometric() - sage: bool(k3_hypergeo == hahn(3,x,a,b,n)) + sage: k3_hypergeo = hahn(k, x, a, b, n)(k=3).simplify_hypergeometric() + sage: bool(k3_hypergeo == hahn(3, x, a, b, n)) True - sage: hahn(2,x,a,b,n,hold=True) + sage: hahn(2, x, a, b, n, hold=True) # needs sage.symbolic hahn(2, x, a, b, n) """ if kwds.get('hold', False): @@ -3015,20 +3071,21 @@ def eval_recursive(self, k, x, a, b, n, *args, **kwds): EXAMPLES:: - sage: x,a,b,n = var('x,a,b,n') - sage: hahn.eval_recursive(0,x,a,b,n) + sage: # needs sage.symbolic + sage: x, a, b, n = var('x,a,b,n') + sage: hahn.eval_recursive(0, x, a, b, n) 1 - sage: hahn.eval_recursive(1,x,a,b,n) + sage: hahn.eval_recursive(1, x, a, b, n) -(a + b + 2)*x/((a + 1)*n) + 1 - sage: bool(hahn(2,x,a,b,n) == hahn.eval_recursive(2,x,a,b,n)) + sage: bool(hahn(2, x, a, b, n) == hahn.eval_recursive(2, x, a, b, n)) True - sage: bool(hahn(3,x,a,b,n) == hahn.eval_recursive(3,x,a,b,n)) + sage: bool(hahn(3, x, a, b, n) == hahn.eval_recursive(3, x, a, b, n)) True - sage: bool(hahn(4,x,a,b,n) == hahn.eval_recursive(4,x,a,b,n)) + sage: bool(hahn(4, x, a, b, n) == hahn.eval_recursive(4, x, a, b, n)) True - sage: M = matrix([[-1/2,-1],[1,0]]) - sage: ret = hahn.eval_recursive(2, M, 1, 2, n).simplify_full().factor() - sage: ret + sage: M = matrix([[-1/2, -1], [1, 0]]) # needs sage.modules + sage: ret = hahn.eval_recursive(2, M, 1, 2, n).simplify_full().factor() # needs sage.modules + sage: ret # needs sage.modules [1/4*(4*n^2 + 8*n - 19)/((n - 1)*n) 3/2*(4*n + 3)/((n - 1)*n)] [ -3/2*(4*n + 3)/((n - 1)*n) (n^2 - n - 7)/((n - 1)*n)] """ diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 5a0f06a27f8..9dbe9787545 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -6,39 +6,37 @@ Check that gamma function imports are deprecated (:trac:`24411`):: sage: from sage.functions.other import beta - sage: beta(x, x) + sage: beta(x, x) # needs sage.symbolic doctest:warning...: DeprecationWarning: Importing beta from here is deprecated; please use "from sage.functions.gamma import beta" instead. See https://github.com/sagemath/sage/issues/24411 for details. beta(x, x) """ -from sage.misc.lazy_import import lazy_import -lazy_import('sage.functions.gamma', - ('gamma', 'log_gamma', 'gamma_inc', - 'gamma_inc_lower', 'psi', 'beta'), deprecation=24411) +import math -from sage.symbolic.function import GinacFunction, BuiltinFunction -from sage.symbolic.expression import Expression, register_symbol, symbol_table -from sage.symbolic.ring import SR, SymbolicRing +from sage.arith.misc import binomial as arith_binomial +from sage.functions.trig import arctan2 +from sage.misc.functional import sqrt +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational import Rational -from sage.rings.complex_mpfr import ComplexField -from sage.misc.latex import latex -from sage.structure.element import Element -import math - -from sage.structure.element import coercion_model - +from sage.structure.element import coercion_model, Element, Expression # avoid name conflicts with `parent` as a function parameter -from sage.structure.all import parent as s_parent +from sage.structure.element import parent as s_parent +from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.symbolic.symbols import register_symbol, symbol_table -from sage.functions.trig import arctan2 +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.complex_mpfr', 'ComplexField') -from sage.arith.misc import binomial as arith_binomial +lazy_import('sage.symbolic.ring', 'SR') -from sage.misc.functional import sqrt + +lazy_import('sage.functions.gamma', + ('gamma', 'log_gamma', 'gamma_inc', + 'gamma_inc_lower', 'psi', 'beta'), deprecation=24411) class Function_abs(GinacFunction): @@ -48,14 +46,16 @@ def __init__(self): EXAMPLES:: + sage: abs(-2) + 2 + + sage: # needs sage.symbolic sage: var('x y') (x, y) sage: abs(x) abs(x) sage: abs(x^2 + y^2) abs(x^2 + y^2) - sage: abs(-2) - 2 sage: sqrt(x^2) sqrt(x^2) sage: abs(sqrt(x)) @@ -66,20 +66,21 @@ def __init__(self): sage: f = sage.functions.other.Function_abs() sage: latex(f) \mathrm{abs} - sage: latex(abs(x)) + sage: latex(abs(x)) # needs sage.symbolic {\left| x \right|} - sage: abs(x)._sympy_() + sage: abs(x)._sympy_() # needs sympy sage.symbolic Abs(x) Test pickling:: - sage: loads(dumps(abs(x))) + sage: loads(dumps(abs(x))) # needs sage.symbolic abs(x) TESTS: Check that :trac:`12588` is fixed:: + sage: # needs sage.symbolic sage: abs(pi*I) pi sage: abs(pi*I*catalan) @@ -117,7 +118,7 @@ def __init__(self): sage: abs((pi+e)*x) (pi + e)*abs(x) - sage: fricas(abs(x)).sage().derivative() # optional - fricas + sage: fricas(abs(x)).sage().derivative() # optional - fricas # needs sage.symbolic 1/2*(x + conjugate(x))/abs(x) """ GinacFunction.__init__(self, "abs", latex_name=r"\mathrm{abs}", @@ -126,6 +127,7 @@ def __init__(self): giac='abs', fricas='abs')) + abs = abs_symbolic = Function_abs() @@ -146,9 +148,9 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): TESTS:: - sage: numbers = [SR(10^100 + exp(-100)), SR(10^100 - exp(-100)), SR(10^100)] - sage: numbers += [-n for n in numbers] - sage: for n in numbers: + sage: numbers = [SR(10^100 + exp(-100)), SR(10^100 - exp(-100)), SR(10^100)] # needs sage.symbolic + sage: numbers += [-n for n in numbers] # needs sage.symbolic + sage: for n in numbers: # needs sage.symbolic ....: f = floor(n) ....: c = ceil(n) ....: if f == c: @@ -158,6 +160,7 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): A test from :trac:`12121`:: + sage: # needs sage.symbolic sage: e1 = pi - continued_fraction(pi).convergent(2785) sage: e2 = e - continued_fraction(e).convergent(1500) sage: f = e1/e2 @@ -174,7 +177,7 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): Traceback (most recent call last): ... ValueError: Calling ceil() on infinity or NaN - sage: ceil(NaN) + sage: ceil(NaN) # needs sage.symbolic Traceback (most recent call last): ... ValueError: Calling ceil() on infinity or NaN @@ -182,10 +185,10 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): Test that elements of symbolic subrings work in the same way as elements of ``SR``, :trac:`32724`:: - sage: SCR = SR.subring(no_variables=True) - sage: floor(log(2^(3/2)) / log(2) + 1/2) + sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic + sage: floor(log(2^(3/2)) / log(2) + 1/2) # needs sage.symbolic 2 - sage: floor(SCR(log(2^(-3/2)) / log(2) + 1/2)) + sage: floor(SCR(log(2^(-3/2)) / log(2) + 1/2)) # needs sage.symbolic -1 """ # First, some obvious things... @@ -224,7 +227,7 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): # Might it be needed to simplify x? This only applies for # elements of SR (or its subrings) - need_to_simplify = isinstance(s_parent(x), SymbolicRing) + need_to_simplify = isinstance(x, Expression) # An integer which is close to x. We use this to increase precision # by subtracting this guess before converting to an interval field. @@ -320,8 +323,8 @@ def __init__(self): EXAMPLES:: - sage: a = ceil(2/5 + x) - sage: a + sage: # needs sage.symbolic + sage: a = ceil(2/5 + x); a ceil(x + 2/5) sage: a(x=4) 5 @@ -338,7 +341,7 @@ def __init__(self): :: - sage: ceil(sin(8)/sin(2)) + sage: ceil(sin(8)/sin(2)) # needs sage.symbolic 2 :: @@ -350,45 +353,45 @@ def __init__(self): :: - sage: ceil(factorial(50)/exp(1)) + sage: ceil(factorial(50)/exp(1)) # needs sage.symbolic 11188719610782480504630258070757734324011354208865721592720336801 - sage: ceil(SR(10^50 + 10^(-50))) + sage: ceil(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000001 - sage: ceil(SR(10^50 - 10^(-50))) + sage: ceil(SR(10^50 - 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 Small numbers which are extremely close to an integer are hard to deal with:: - sage: ceil((33^100 + 1)^(1/100)) + sage: ceil((33^100 + 1)^(1/100)) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute ceil(...) using 256 bits of precision This can be fixed by giving a sufficiently large ``bits`` argument:: - sage: ceil((33^100 + 1)^(1/100), bits=500) + sage: ceil((33^100 + 1)^(1/100), bits=500) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute ceil(...) using 512 bits of precision - sage: ceil((33^100 + 1)^(1/100), bits=1000) + sage: ceil((33^100 + 1)^(1/100), bits=1000) # needs sage.symbolic 34 :: - sage: ceil(sec(e)) + sage: ceil(sec(e)) # needs sage.symbolic -1 - sage: latex(ceil(x)) + sage: latex(ceil(x)) # needs sage.symbolic \left \lceil x \right \rceil - sage: ceil(x)._sympy_() + sage: ceil(x)._sympy_() # needs sympy sage.symbolic ceiling(x) :: - sage: import numpy - sage: a = numpy.linspace(0,2,6) - sage: ceil(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,2,6) # needs numpy + sage: ceil(a) # needs numpy array([0., 1., 1., 2., 2., 2.]) Test pickling:: @@ -405,7 +408,7 @@ def _print_latex_(self, x): r""" EXAMPLES:: - sage: latex(ceil(x)) # indirect doctest + sage: latex(ceil(x)) # indirect doctest # needs sage.symbolic \left \lceil x \right \rceil """ return r"\left \lceil %s \right \rceil"%latex(x) @@ -419,13 +422,13 @@ def __call__(self, x, **kwds): TESTS:: - sage: ceil(SR(10^50 + 10^(-50))) + sage: ceil(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000001 - sage: ceil(SR(10^50 - 10^(-50))) + sage: ceil(SR(10^50 - 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 sage: ceil(int(10^50)) 100000000000000000000000000000000000000000000000000 - sage: ceil((1725033*pi - 5419351)/(25510582*pi - 80143857)) + sage: ceil((1725033*pi - 5419351)/(25510582*pi - 80143857)) # needs sage.symbolic -2 """ return _eval_floor_ceil(self, x, "ceil", **kwds) @@ -434,12 +437,13 @@ def _eval_(self, x): """ EXAMPLES:: - sage: ceil(x).subs(x==7.5) + sage: ceil(x).subs(x==7.5) # needs sage.symbolic 8 - sage: ceil(x) + sage: ceil(x) # needs sage.symbolic ceil(x) - sage: var('x',domain='integer') + sage: # needs sage.symbolic + sage: var('x', domain='integer') x sage: ceil(x) x @@ -463,6 +467,7 @@ def _eval_(self, x): return Integer(math.ceil(x)) return None + ceil = Function_ceil() @@ -496,6 +501,8 @@ def __init__(self): 5 sage: type(floor(5.4)) + + sage: # needs sage.symbolic sage: var('x') x sage: a = floor(5.25 + x); a @@ -507,6 +514,7 @@ def __init__(self): :: + sage: # needs sage.symbolic sage: floor(cos(8) / cos(2)) 0 sage: floor(log(4) / log(2)) @@ -522,11 +530,11 @@ def __init__(self): :: - sage: floor(factorial(50)/exp(1)) + sage: floor(factorial(50)/exp(1)) # needs sage.symbolic 11188719610782480504630258070757734324011354208865721592720336800 - sage: floor(SR(10^50 + 10^(-50))) + sage: floor(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 - sage: floor(SR(10^50 - 10^(-50))) + sage: floor(SR(10^50 - 10^(-50))) # needs sage.symbolic 99999999999999999999999999999999999999999999999999 sage: floor(int(10^50)) 100000000000000000000000000000000000000000000000000 @@ -534,27 +542,27 @@ def __init__(self): Small numbers which are extremely close to an integer are hard to deal with:: - sage: floor((33^100 + 1)^(1/100)) + sage: floor((33^100 + 1)^(1/100)) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute floor(...) using 256 bits of precision This can be fixed by giving a sufficiently large ``bits`` argument:: - sage: floor((33^100 + 1)^(1/100), bits=500) + sage: floor((33^100 + 1)^(1/100), bits=500) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute floor(...) using 512 bits of precision - sage: floor((33^100 + 1)^(1/100), bits=1000) + sage: floor((33^100 + 1)^(1/100), bits=1000) # needs sage.symbolic 33 :: - sage: import numpy - sage: a = numpy.linspace(0,2,6) - sage: floor(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,2,6) # needs numpy + sage: floor(a) # needs numpy array([0., 0., 0., 1., 1., 2.]) - sage: floor(x)._sympy_() + sage: floor(x)._sympy_() # needs sympy sage.symbolic floor(x) Test pickling:: @@ -569,7 +577,7 @@ def _print_latex_(self, x): r""" EXAMPLES:: - sage: latex(floor(x)) + sage: latex(floor(x)) # needs sage.symbolic \left \lfloor x \right \rfloor """ return r"\left \lfloor %s \right \rfloor"%latex(x) @@ -583,13 +591,13 @@ def __call__(self, x, **kwds): TESTS:: - sage: floor(SR(10^50 + 10^(-50))) + sage: floor(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 - sage: floor(SR(10^50 - 10^(-50))) + sage: floor(SR(10^50 - 10^(-50))) # needs sage.symbolic 99999999999999999999999999999999999999999999999999 sage: floor(int(10^50)) 100000000000000000000000000000000000000000000000000 - sage: floor((1725033*pi - 5419351)/(25510582*pi - 80143857)) + sage: floor((1725033*pi - 5419351)/(25510582*pi - 80143857)) # needs sage.symbolic -3 """ return _eval_floor_ceil(self, x, "floor", **kwds) @@ -598,12 +606,13 @@ def _eval_(self, x): """ EXAMPLES:: - sage: floor(x).subs(x==7.5) + sage: floor(x).subs(x==7.5) # needs sage.symbolic 7 - sage: floor(x) + sage: floor(x) # needs sage.symbolic floor(x) - sage: var('x',domain='integer') + sage: # needs sage.symbolic + sage: var('x', domain='integer') x sage: floor(x) x @@ -627,6 +636,7 @@ def _eval_(self, x): return Integer(math.floor(x)) return None + floor = Function_floor() @@ -645,17 +655,17 @@ def __init__(self): EXAMPLES:: - sage: x = SR('x') - sage: x.Order() + sage: x = SR('x') # needs sage.symbolic + sage: x.Order() # needs sage.symbolic Order(x) - sage: (x^2 + x).Order() + sage: (x^2 + x).Order() # needs sage.symbolic Order(x^2 + x) TESTS: Check that :trac:`19425` is resolved:: - sage: x.Order().operator() + sage: x.Order().operator() # needs sage.symbolic Order """ GinacFunction.__init__(self, "Order", @@ -666,6 +676,7 @@ def _sympy_(self, arg): """ EXAMPLES:: + sage: # needs sympy sage.symbolic sage: x.Order()._sympy_() O(x) sage: SR(1).Order()._sympy_() @@ -675,9 +686,9 @@ def _sympy_(self, arg): sage: exp(x).series(x==1, 3)._sympy_() E + E*(x - 1) + E*(x - 1)**2/2 + O((x - 1)**3, (x, 1)) - sage: (-(pi-x)^3).Order()._sympy_() + sage: (-(pi-x)^3).Order()._sympy_() # needs sympy sage.symbolic O((x - pi)**3, (x, pi)) - sage: cos(x).series(x==pi, 3)._sympy_() + sage: cos(x).series(x==pi, 3)._sympy_() # needs sympy sage.symbolic -1 + (pi - x)**2/2 + O((x - pi)**3, (x, pi)) """ roots = arg.solve(arg.default_variable(), algorithm='sympy', @@ -690,6 +701,7 @@ def _sympy_(self, arg): import sympy return sympy.O(*sympy.sympify(arg, evaluate=False)) + Order = Function_Order() @@ -708,6 +720,8 @@ def __init__(self): sage: frac(456/123) 29/41 + + sage: # needs sage.symbolic sage: var('x') x sage: a = frac(5.4 + x); a @@ -716,7 +730,7 @@ def __init__(self): cos(8)/cos(2) sage: latex(frac(x)) \operatorname{frac}\left(x\right) - sage: frac(x)._sympy_() + sage: frac(x)._sympy_() # needs sympy frac(x) Test pickling:: @@ -732,9 +746,9 @@ def _evalf_(self, x, **kwds): """ EXAMPLES:: - sage: frac(pi).n() + sage: frac(pi).n() # needs sage.symbolic 0.141592653589793 - sage: frac(pi).n(200) + sage: frac(pi).n(200) # needs sage.symbolic 0.14159265358979323846264338327950288419716939937510582097494 """ return x - floor(x) @@ -743,9 +757,9 @@ def _eval_(self, x): """ EXAMPLES:: - sage: frac(x).subs(x==7.5) + sage: frac(x).subs(x==7.5) # needs sage.symbolic 0.500000000000000 - sage: frac(x) + sage: frac(x) # needs sage.symbolic frac(x) """ try: @@ -761,6 +775,7 @@ def _eval_(self, x): return x - ret return None + frac = Function_frac() @@ -781,9 +796,9 @@ class Function_real_nth_root(BuiltinFunction): EXAMPLES:: - sage: real_nth_root(2, 3) + sage: real_nth_root(2, 3) # needs sage.symbolic 2^(1/3) - sage: real_nth_root(-2, 3) + sage: real_nth_root(-2, 3) # needs sage.symbolic -2^(1/3) sage: real_nth_root(8, 3) 2 @@ -804,8 +819,8 @@ class Function_real_nth_root(BuiltinFunction): Some symbolic calculus:: - sage: f = real_nth_root(x, 5)^3 - sage: f + sage: # needs sage.symbolic + sage: f = real_nth_root(x, 5)^3; f real_nth_root(x^3, 5) sage: f.diff() 3/5*x^2*real_nth_root(x^(-12), 5) @@ -822,14 +837,14 @@ def __init__(self): TESTS:: - sage: cube_root = real_nth_root(x, 3) - sage: loads(dumps(cube_root)) + sage: cube_root = real_nth_root(x, 3) # needs sage.symbolic + sage: loads(dumps(cube_root)) # needs sage.symbolic real_nth_root(x, 3) :: - sage: f = real_nth_root(x, 3) - sage: f._sympy_() + sage: f = real_nth_root(x, 3) # needs sage.symbolic + sage: f._sympy_() # needs sympy sage.symbolic Piecewise((Abs(x)**(1/3)*sign(x), Eq(im(x), 0)), (x**(1/3), True)) """ @@ -842,9 +857,9 @@ def _print_latex_(self, base, exp): r""" TESTS:: - sage: latex(real_nth_root(x, 3)) + sage: latex(real_nth_root(x, 3)) # needs sage.symbolic x^{\frac{1}{3}} - sage: latex(real_nth_root(x^2 + x, 3)) + sage: latex(real_nth_root(x^2 + x, 3)) # needs sage.symbolic {\left(x^{2} + x\right)}^{\frac{1}{3}} """ return latex(base**(1/exp)) @@ -855,7 +870,7 @@ def _evalf_(self, base, exp, parent=None): sage: real_nth_root(RDF(-2), 3) -1.25992104989487... - sage: real_nth_root(Reals(100)(2), 2) + sage: real_nth_root(Reals(100)(2), 2) # needs sage.rings.real_mpfr 1.4142135623730950488016887242 """ if hasattr(exp, 'real_part'): @@ -894,9 +909,9 @@ def _eval_(self, base, exp): """ TESTS:: - sage: real_nth_root(x, 1) + sage: real_nth_root(x, 1) # needs sage.symbolic x - sage: real_nth_root(x, 3) + sage: real_nth_root(x, 3) # needs sage.symbolic real_nth_root(x, 3) sage: real_nth_root(RIF(2), 3) @@ -919,8 +934,8 @@ def _power_(self, base, exp, power_param=None): """ TESTS:: - sage: f = real_nth_root(x, 3) - sage: f^5 + sage: f = real_nth_root(x, 3) # needs sage.symbolic + sage: f^5 # needs sage.symbolic real_nth_root(x^5, 3) """ return self(base**power_param, exp) @@ -929,6 +944,7 @@ def _derivative_(self, base, exp, diff_param=None): """ TESTS:: + sage: # needs sage.symbolic sage: f = real_nth_root(x, 3) sage: f.diff() 1/3*real_nth_root(x^(-2), 3) @@ -944,6 +960,7 @@ def _derivative_(self, base, exp, diff_param=None): """ return 1/exp * self(base, exp)**(1-exp) + real_nth_root = Function_real_nth_root() @@ -954,6 +971,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arg(3+i) arctan(1/3) sage: arg(-1+i) @@ -971,6 +989,7 @@ def __init__(self): sage: arg(0) 0 + sage: # needs sage.symbolic sage: latex(arg(x)) {\rm arg}\left(x\right) sage: maxima(arg(x)) @@ -979,25 +998,25 @@ def __init__(self): atan(1/2) sage: maxima(arg(sqrt(2)+i)) atan(1/sqrt(2)) - sage: arg(x)._sympy_() + sage: arg(x)._sympy_() # needs sympy arg(x) - sage: arg(2+i) + sage: arg(2+i) # needs sage.symbolic arctan(1/2) - sage: arg(sqrt(2)+i) + sage: arg(sqrt(2)+i) # needs sage.symbolic arg(sqrt(2) + I) - sage: arg(sqrt(2)+i).simplify() + sage: arg(sqrt(2)+i).simplify() # needs sage.symbolic arctan(1/2*sqrt(2)) TESTS:: - sage: arg(0.0) + sage: arg(0.0) # needs sage.rings.complex_double 0.000000000000000 - sage: arg(3.0) + sage: arg(3.0) # needs sage.rings.complex_double 0.000000000000000 - sage: arg(-2.5) + sage: arg(-2.5) # needs sage.rings.complex_double 3.14159265358979 - sage: arg(2.0+3*i) + sage: arg(2.0+3*i) # needs sage.symbolic 0.982793723247329 """ BuiltinFunction.__init__(self, "arg", @@ -1010,6 +1029,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: arg(3+i) arctan(1/3) sage: arg(-1+i) @@ -1043,6 +1063,7 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: + sage: # needs sage.rings.complex_double sage: arg(0.0) 0.000000000000000 sage: arg(3.0) @@ -1051,19 +1072,20 @@ def _evalf_(self, x, parent=None, algorithm=None): 0.00000000000000000000000000 sage: arg(3.00000000000000000000000000).prec() 90 - sage: arg(ComplexIntervalField(90)(3)).prec() - 90 - sage: arg(ComplexIntervalField(90)(3)).parent() - Real Interval Field with 90 bits of precision - sage: arg(3.0r) - 0.0 sage: arg(RDF(3)) 0.0 sage: arg(RDF(3)).parent() Real Double Field sage: arg(-2.5) 3.14159265358979 - sage: arg(2.0+3*i) + + sage: arg(ComplexIntervalField(90)(3)).prec() # needs sage.rings.complex_interval_field + 90 + sage: arg(ComplexIntervalField(90)(3)).parent() # needs sage.rings.complex_interval_field + Real Interval Field with 90 bits of precision + sage: arg(3.0r) # needs sage.rings.real_mpfr + 0.0 + sage: arg(2.0+3*i) # needs sage.symbolic 0.982793723247329 TESTS: @@ -1071,7 +1093,7 @@ def _evalf_(self, x, parent=None, algorithm=None): Make sure that the ``_evalf_`` method works when it receives a keyword argument ``parent`` :trac:`12289`:: - sage: arg(5+I, hold=True).n() + sage: arg(5+I, hold=True).n() # needs sage.symbolic 0.197395559849881 """ try: @@ -1091,6 +1113,7 @@ def _evalf_(self, x, parent=None, algorithm=None): return parent(x).arg() + arg=Function_arg() @@ -1105,19 +1128,19 @@ def __init__(self): It is possible to prevent automatic evaluation using the ``hold`` parameter:: - sage: real_part(I,hold=True) + sage: real_part(I, hold=True) # needs sage.symbolic real_part(I) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: real_part(I,hold=True).simplify() + sage: real_part(I, hold=True).simplify() # needs sage.symbolic 0 EXAMPLES:: - sage: z = 1+2*I - sage: real(z) + sage: z = 1+2*I # needs sage.symbolic + sage: real(z) # needs sage.symbolic 1 sage: real(5/3) 5/3 @@ -1134,6 +1157,7 @@ def __init__(self): Sage can recognize some expressions as real and accordingly return the identical argument:: + sage: # needs sage.symbolic sage: SR.var('x', domain='integer').real_part() x sage: SR.var('x', domain='integer').imag_part() @@ -1152,22 +1176,22 @@ def __init__(self): sage: loads(dumps(real_part)) real_part - sage: real_part(x)._sympy_() + sage: real_part(x)._sympy_() # needs sympy sage.symbolic re(x) Check if :trac:`6401` is fixed:: - sage: latex(x.real()) + sage: latex(x.real()) # needs sage.symbolic \Re \left( x \right) - sage: f(x) = function('f')(x) - sage: latex( f(x).real()) + sage: f(x) = function('f')(x) # needs sage.symbolic + sage: latex( f(x).real()) # needs sage.symbolic \Re \left( f\left(x\right) \right) Check that some real part expansions evaluate correctly (:trac:`21614`):: - sage: real(sqrt(sin(x))).subs(x==0) + sage: real(sqrt(sin(x))).subs(x==0) # needs sage.symbolic 0 """ GinacFunction.__init__(self, "real_part", @@ -1189,6 +1213,7 @@ def __call__(self, x, **kwargs): else: return GinacFunction.__call__(self, x, **kwargs) + real = real_part = Function_real_part() @@ -1200,36 +1225,36 @@ def __init__(self): It is possible to prevent automatic evaluation using the ``hold`` parameter:: - sage: imag_part(I,hold=True) + sage: imag_part(I, hold=True) # needs sage.symbolic imag_part(I) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: imag_part(I,hold=True).simplify() + sage: imag_part(I, hold=True).simplify() # needs sage.symbolic 1 TESTS:: - sage: z = 1+2*I - sage: imaginary(z) + sage: z = 1+2*I # needs sage.symbolic + sage: imaginary(z) # needs sage.symbolic 2 - sage: imag(z) + sage: imag(z) # needs sage.symbolic 2 sage: imag(complex(3, 4)) 4.0 sage: loads(dumps(imag_part)) imag_part - sage: imag_part(x)._sympy_() + sage: imag_part(x)._sympy_() # needs sympy sage.symbolic im(x) Check if :trac:`6401` is fixed:: - sage: latex(x.imag()) + sage: latex(x.imag()) # needs sage.symbolic \Im \left( x \right) - sage: f(x) = function('f')(x) - sage: latex( f(x).imag()) + sage: f(x) = function('f')(x) # needs sage.symbolic + sage: latex(f(x).imag()) # needs sage.symbolic \Im \left( f\left(x\right) \right) """ GinacFunction.__init__(self, "imag_part", @@ -1267,21 +1292,22 @@ def __init__(self): It is possible to prevent automatic evaluation using the ``hold`` parameter:: - sage: conjugate(I,hold=True) + sage: conjugate(I, hold=True) # needs sage.symbolic conjugate(I) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: conjugate(I,hold=True).simplify() + sage: conjugate(I, hold=True).simplify() # needs sage.symbolic -I TESTS:: + sage: # needs sage.symbolic sage: x,y = var('x,y') sage: x.conjugate() conjugate(x) - sage: _._sympy_() + sage: _._sympy_() # needs sympy conjugate(x) sage: latex(conjugate(x)) \overline{x} @@ -1300,6 +1326,7 @@ def __init__(self): Check if :trac:`8755` is fixed:: + sage: # needs sage.symbolic sage: conjugate(sqrt(-3)) conjugate(sqrt(-3)) sage: conjugate(sqrt(3)) @@ -1308,14 +1335,15 @@ def __init__(self): conjugate(sqrt(x)) sage: conjugate(x^2) conjugate(x)^2 - sage: var('y',domain='positive') + sage: var('y', domain='positive') y sage: conjugate(sqrt(y)) sqrt(y) Check if :trac:`10964` is fixed:: - sage: z= I*sqrt(-3); z + sage: # needs sage.symbolic + sage: z = I*sqrt(-3); z I*sqrt(-3) sage: conjugate(z) -I*conjugate(sqrt(-3)) @@ -1326,8 +1354,8 @@ def __init__(self): Check that sums are handled correctly:: - sage: y = var('y', domain='real') - sage: conjugate(y + I) + sage: y = var('y', domain='real') # needs sage.symbolic + sage: conjugate(y + I) # needs sage.symbolic y - I Test pickling:: @@ -1352,7 +1380,7 @@ def __init__(self): INPUT: - - ``n`` - a non-negative integer, a complex number (except negative + - ``n`` -- a non-negative integer, a complex number (except negative integers) or any symbolic expression @@ -1369,6 +1397,7 @@ def __init__(self): sage: factorial(6) == 6*5*4*3*2 True + sage: # needs sage.symbolic sage: x = SR.var('x') sage: f = factorial(x + factorial(x)); f factorial(x + factorial(x)) @@ -1379,24 +1408,24 @@ def __init__(self): To prevent automatic evaluation use the ``hold`` argument:: - sage: factorial(5, hold=True) + sage: factorial(5, hold=True) # needs sage.symbolic factorial(5) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: factorial(5, hold=True).simplify() + sage: factorial(5, hold=True).simplify() # needs sage.symbolic 120 We can also give input other than nonnegative integers. For other nonnegative numbers, the :func:`sage.functions.gamma.gamma` function is used:: - sage: factorial(1/2) + sage: factorial(1/2) # needs sage.symbolic 1/2*sqrt(pi) - sage: factorial(3/4) + sage: factorial(3/4) # needs sage.symbolic gamma(7/4) - sage: factorial(2.3) + sage: factorial(2.3) # needs sage.symbolic 2.68343738195577 But negative input always fails:: @@ -1408,9 +1437,9 @@ def __init__(self): And very large integers remain unevaluated:: - sage: factorial(2**64) + sage: factorial(2**64) # needs sage.symbolic factorial(18446744073709551616) - sage: SR(2**64).factorial() + sage: SR(2**64).factorial() # needs sage.symbolic factorial(18446744073709551616) TESTS: @@ -1418,6 +1447,7 @@ def __init__(self): We verify that we can convert this function to Maxima and bring it back into Sage.:: + sage: # needs sage.symbolic sage: z = var('z') sage: factorial._maxima_init_() 'factorial' @@ -1425,17 +1455,18 @@ def __init__(self): factorial(_SAGE_VAR_z) sage: _.sage() factorial(z) - sage: _._sympy_() + sage: _._sympy_() # needs sympy factorial(z) sage: k = var('k') sage: factorial(k) factorial(k) - sage: factorial(3.14) + sage: factorial(3.14) # needs sage.symbolic 7.173269190187... Test latex typesetting:: + sage: # needs sage.symbolic sage: latex(factorial(x)) x! sage: latex(factorial(2*x)) @@ -1454,6 +1485,7 @@ def __init__(self): Check that :trac:`11539` is fixed:: + sage: # needs sage.symbolic sage: (factorial(x) == 0).simplify() factorial(x) == 0 sage: maxima(factorial(x) == 0).sage() @@ -1464,8 +1496,8 @@ def __init__(self): Check that :trac:`16166` is fixed:: - sage: RBF = RealBallField(53) - sage: factorial(RBF(4.2)) # abs tol 1e-13 + sage: RBF = RealBallField(53) # needs sage.libs.flint + sage: factorial(RBF(4.2)) # abs tol 1e-13 # needs sage.libs.flint [32.5780960503314 +/- 6.06e-14] Test pickling:: @@ -1490,6 +1522,7 @@ def _eval_(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: k = var('k') sage: k.factorial() factorial(k) @@ -1508,14 +1541,14 @@ def _eval_(self, x): Check that :trac:`25421` is fixed:: - sage: factorial(RBF(2)**64) + sage: factorial(RBF(2)**64) # needs sage.libs.flint [+/- 2.30e+347382171326740403407] Check that :trac:`26749` is fixed:: - sage: factorial(float(3.2)) # abs tol 1e-14 + sage: factorial(float(3.2)) # abs tol 1e-14 # needs sage.symbolic 7.7566895357931776 - sage: type(factorial(float(3.2))) + sage: type(factorial(float(3.2))) # needs sage.symbolic """ if isinstance(x, (int, Integer)): @@ -1532,6 +1565,7 @@ def _eval_(self, x): from sage.functions.gamma import gamma return gamma(x + 1) + factorial = Function_factorial() @@ -1564,40 +1598,42 @@ def __init__(self): EXAMPLES:: - sage: binomial(5,2) + sage: # needs sage.symbolic + sage: binomial(5, 2) 10 - sage: binomial(2,0) + sage: binomial(2, 0) 1 - sage: binomial(1/2, 0) + sage: binomial(1/2, 0) # needs sage.libs.pari 1 - sage: binomial(3,-1) + sage: binomial(3, -1) 0 - sage: binomial(20,10) + sage: binomial(20, 10) 184756 sage: binomial(-2, 5) -6 - sage: binomial(RealField()('2.5'), 2) - 1.87500000000000 - sage: n=var('n'); binomial(n,2) + sage: n = var('n'); binomial(n, 2) 1/2*(n - 1)*n - sage: n=var('n'); binomial(n,n) + sage: n = var('n'); binomial(n, n) 1 - sage: n=var('n'); binomial(n,n-1) + sage: n = var('n'); binomial(n, n - 1) n sage: binomial(2^100, 2^100) 1 + sage: binomial(RealField()('2.5'), 2) # needs sage.rings.real_mpfr + 1.87500000000000 + :: - sage: k, i = var('k,i') - sage: binomial(k,i) + sage: k, i = var('k,i') # needs sage.symbolic + sage: binomial(k,i) # needs sage.symbolic binomial(k, i) We can use a ``hold`` parameter to prevent automatic evaluation:: - sage: SR(5).binomial(3, hold=True) + sage: SR(5).binomial(3, hold=True) # needs sage.symbolic binomial(5, 3) - sage: SR(5).binomial(3, hold=True).simplify() + sage: SR(5).binomial(3, hold=True).simplify() # needs sage.symbolic 10 TESTS: @@ -1607,12 +1643,13 @@ def __init__(self): :: - sage: n,k = var('n,k') + sage: # needs sage.symbolic + sage: n, k = var('n,k') sage: maxima(binomial(n,k)) binomial(_SAGE_VAR_n,_SAGE_VAR_k) sage: _.sage() binomial(n, k) - sage: _._sympy_() + sage: _._sympy_() # needs sympy binomial(n, k) sage: binomial._maxima_init_() 'binomial' @@ -1620,19 +1657,19 @@ def __init__(self): For polynomials:: sage: y = polygen(QQ, 'y') - sage: binomial(y, 2).parent() + sage: binomial(y, 2).parent() # needs sage.symbolic Univariate Polynomial Ring in y over Rational Field :trac:`16726`:: - sage: binomial(CIF(1), 2) + sage: binomial(CIF(1), 2) # needs sage.symbolic 0 - sage: binomial(CIF(3), 2) + sage: binomial(CIF(3), 2) # needs sage.symbolic 3 Test pickling:: - sage: loads(dumps(binomial(n,k))) + sage: loads(dumps(binomial(n, k))) # needs sage.symbolic binomial(n, k) """ GinacFunction.__init__(self, "binomial", nargs=2, preserved_arg=1, @@ -1649,6 +1686,7 @@ def _binomial_sym(self, n, k): EXAMPLES:: + sage: # needs sage.symbolic sage: binomial._binomial_sym(x, 3) 1/6*(x - 1)*(x - 2)*x sage: binomial._binomial_sym(x, x) @@ -1657,7 +1695,6 @@ def _binomial_sym(self, n, k): ValueError: second argument must be an integer sage: binomial._binomial_sym(x, SR(3)) 1/6*(x - 1)*(x - 2)*x - sage: binomial._binomial_sym(x, 0r) 1 sage: binomial._binomial_sym(x, -1) @@ -1691,8 +1728,10 @@ def _eval_(self, n, k): 10 sage: type(binomial._eval_(5, 3)) - sage: type(binomial._eval_(5., 3)) + sage: type(binomial._eval_(5., 3)) # needs sage.rings.real_mpfr + + sage: # needs sage.symbolic sage: binomial._eval_(x, 3) 1/6*(x - 1)*(x - 2)*x sage: binomial._eval_(x, x-2) @@ -1726,17 +1765,18 @@ def _evalf_(self, n, k, parent=None, algorithm=None): 10.0 sage: type(binomial._evalf_(5.r, 3)) <... 'float'> - sage: binomial._evalf_(1/2,1/1) + sage: binomial._evalf_(1/2, 1/1) # needs sage.libs.pari 1/2 - sage: binomial._evalf_(10^20+1/1,10^20) + sage: binomial._evalf_(10^20 + 1/1, 10^20) 100000000000000000001 - sage: binomial._evalf_(SR(10**7),10**7) + sage: binomial._evalf_(SR(10**7), 10**7) # needs sage.symbolic 1 - sage: binomial._evalf_(3/2,SR(1/1)) + sage: binomial._evalf_(3/2, SR(1/1)) # needs sage.symbolic 3/2 """ return arith_binomial(n, k) + binomial = Function_binomial() @@ -1747,9 +1787,9 @@ class Function_sum(BuiltinFunction): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: r = ssum(x, x, 1, 10); r + sage: r = ssum(x, x, 1, 10); r # needs sage.symbolic sum(x, x, 1, 10) - sage: r.unhold() + sage: r.unhold() # needs sage.symbolic 55 """ def __init__(self): @@ -1757,7 +1797,7 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: maxima(ssum(x, x, 1, 10)) + sage: maxima(ssum(x, x, 1, 10)) # needs sage.symbolic 55 """ BuiltinFunction.__init__(self, "sum", nargs=4, @@ -1768,7 +1808,7 @@ def _print_latex_(self, x, var, a, b): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: latex(ssum(x^2, x, 1, 10)) + sage: latex(ssum(x^2, x, 1, 10)) # needs sage.symbolic {\sum_{x=1}^{10} x^{2}} """ return r"{{\sum_{{{}={}}}^{{{}}} {}}}".format(latex(var), latex(a), @@ -1780,20 +1820,21 @@ def _sympy_(self, term, k, a, n): EXAMPLES:: + sage: # needs sage.symbolic sage: var('k, n') (k, n) - sage: s = sum(k, k, 1, n, hold=True) - sage: s + sage: s = sum(k, k, 1, n, hold=True); s sum(k, k, 1, n) - sage: s._sympy_() # indirect test + sage: s._sympy_() # indirect test # needs sympy Sum(k, (k, 1, n)) - sage: s._sympy_().doit() + sage: s._sympy_().doit() # needs sympy n**2/2 + n/2 """ import sympy return sympy.Sum(term, (k, a, n)) + symbolic_sum = Function_sum() @@ -1804,24 +1845,25 @@ class Function_prod(BuiltinFunction): EXAMPLES:: sage: from sage.functions.other import symbolic_product as sprod - sage: r = sprod(x, x, 1, 10); r + sage: r = sprod(x, x, 1, 10); r # needs sage.symbolic product(x, x, 1, 10) - sage: r.unhold() + sage: r.unhold() # needs sage.symbolic 3628800 """ def __init__(self): """ EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_product as sprod sage: _ = var('m n', domain='integer') sage: r = maxima(sprod(sin(m), m, 1, n)).sage(); r product(sin(m), m, 1, n) sage: isinstance(r.operator(), sage.functions.other.Function_prod) True - sage: r = sympy(sprod(sin(m), m, 1, n)).sage(); r # known bug + sage: r = sympy(sprod(sin(m), m, 1, n)).sage(); r # known bug # needs sympy product(sin(m), m, 1, n) - sage: isinstance(r.operator(), # known bug + sage: isinstance(r.operator(), # known bug # needs sympy ....: sage.functions.other.Function_prod) True sage: giac(sprod(m, m, 1, n)).sage() @@ -1836,7 +1878,7 @@ def _print_latex_(self, x, var, a, b): EXAMPLES:: sage: from sage.functions.other import symbolic_product as sprod - sage: latex(sprod(x^2, x, 1, 10)) + sage: latex(sprod(x^2, x, 1, 10)) # needs sage.symbolic {\prod_{x=1}^{10} x^{2}} """ return r"{{\prod_{{{}={}}}^{{{}}} {}}}".format(latex(var), latex(a), @@ -1848,15 +1890,16 @@ def _sympy_(self, term, k, a, n): EXAMPLES:: - sage: var('k, n') + sage: var('k, n') # needs sage.symbolic (k, n) - sage: p = product(k^2+k+1,k,1,n, hold=True) - sage: p._sympy_() # indirect test + sage: p = product(k^2 + k + 1, k, 1, n, hold=True) # needs sympy sage.symbolic + sage: p._sympy_() # indirect test # needs sympy sage.symbolic Product(k**2 + k + 1, (k, 1, n)) """ import sympy return sympy.Product(term, (k, a, n)) + symbolic_product = Function_prod() @@ -1867,11 +1910,12 @@ class Function_limit(BuiltinFunction): This function is called to create formal wrappers of limits that Maxima can't compute:: - sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a + sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a # needs sage.symbolic -limit((erf(x) - 1)*e^(x^2), x, +Infinity) EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_limit as slimit sage: slimit(1/x, x, +oo) limit(1/x, x, +Infinity) @@ -1889,7 +1933,7 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.other import symbolic_limit as slimit - sage: maxima(slimit(1/x, x, +oo)) + sage: maxima(slimit(1/x, x, +oo)) # needs sage.symbolic 0 """ BuiltinFunction.__init__(self, "limit", nargs=0, @@ -1909,6 +1953,7 @@ def _print_latex_(self, ex, var, to, direction=''): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_limit as slimit sage: var('x,a') (x, a) @@ -1923,6 +1968,7 @@ def _print_latex_(self, ex, var, to, direction=''): When one-sided limits are converted back from maxima, the direction argument becomes a symbolic variable. We check if typesetting these works:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_limit as slimit sage: var('minus,plus') (minus, plus) @@ -1941,12 +1987,13 @@ def _print_latex_(self, ex, var, to, direction=''): Check if :trac:`13181` is fixed:: + sage: # needs sage.symbolic sage: t = var('t') - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='-')) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x), t=x, dir='-')) \lim_{t \to x^-}\, \sqrt{-t + x} E_{\frac{1}{2}}\left(i \, t - i \, x\right) - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='+')) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x), t=x, dir='+')) \lim_{t \to x^+}\, \sqrt{-t + x} E_{\frac{1}{2}}\left(i \, t - i \, x\right) - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x)) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x), t=x)) \lim_{t \to x}\, \sqrt{-t + x} E_{\frac{1}{2}}\left(i \, t - i \, x\right) """ if repr(direction) == 'minus': @@ -1958,6 +2005,7 @@ def _print_latex_(self, ex, var, to, direction=''): return r"\lim_{{{} \to {}{}}}\, {}".format(latex(var), latex(to), dir_str, latex(ex)) + symbolic_limit = Function_limit() @@ -1972,6 +2020,7 @@ class Function_cases(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: ex = cases([(x==0, pi), (True, 0)]); ex cases(((x == 0, pi), (1, 0))) sage: ex.subs(x==0) @@ -1986,9 +2035,10 @@ class Function_cases(GinacFunction): The first encountered default is used, as well as the first relation that can be trivially decided:: - sage: cases(((True, pi), (True, 0))) + sage: cases(((True, pi), (True, 0))) # needs sage.symbolic pi + sage: # needs sage.symbolic sage: _ = var('y') sage: ex = cases(((x==0, pi), (y==1, 0))); ex cases(((x == 0, pi), (y == 1, 0))) @@ -2010,7 +2060,7 @@ def __call__(self, l, **kwargs): """ EXAMPLES:: - sage: ex = cases([(x==0, pi), (True, 0)]); ex + sage: ex = cases([(x==0, pi), (True, 0)]); ex # needs sage.symbolic cases(((x == 0, pi), (1, 0))) TESTS:: @@ -2020,7 +2070,7 @@ def __call__(self, l, **kwargs): ... TypeError: ...__call__() missing 1 required positional argument: 'l' - sage: cases(x) + sage: cases(x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: cases argument not a sequence @@ -2032,17 +2082,16 @@ def _print_latex_(self, l, **kwargs): r""" EXAMPLES:: - sage: ex = cases([(x==0, pi), (True, 0)]); ex + sage: ex = cases([(x==0, pi), (True, 0)]); ex # needs sage.symbolic cases(((x == 0, pi), (1, 0))) - sage: latex(ex) + sage: latex(ex) # needs sage.symbolic \begin{cases}{\pi} & {x = 0}\\{0} & {1}\end{cases} TESTS: Verify that :trac:`25624` is fixed:: - sage: L = latex(cases([(x == 0, 0), (1, 1)])) - sage: L + sage: L = latex(cases([(x == 0, 0), (1, 1)])); L # needs sage.symbolic \begin{cases}{0} & {x = 0}\\{1} & {1}\end{cases} """ if not isinstance(l, (list, tuple)): @@ -2063,10 +2112,9 @@ def _sympy_(self, l): EXAMPLES:: - sage: ex = cases(((x<0, pi), (x==1, 1), (True, 0))) - sage: assert ex == ex._sympy_()._sage_() + sage: ex = cases(((x<0, pi), (x==1, 1), (True, 0))) # needs sage.symbolic + sage: assert ex == ex._sympy_()._sage_() # needs sympy sage.symbolic """ - from sage.symbolic.ring import SR from sympy import Piecewise as pw args = [] for tup in l.operands(): @@ -2094,6 +2142,7 @@ class Function_crootof(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: c = complex_root_of(x^6 + x + 1, 1); c complex_root_of(x^6 + x + 1, 1) sage: c.n() @@ -2118,6 +2167,7 @@ def _eval_(self, poly, index): """ TESTS:: + sage: # needs sage.symbolic sage: _ = var('y') sage: complex_root_of(1, 1) Traceback (most recent call last): @@ -2143,9 +2193,9 @@ def _evalf_(self, poly, index, parent=None, algorithm=None): """ EXAMPLES:: - sage: complex_root_of(x^2-2, 1).n() + sage: complex_root_of(x^2 - 2, 1).n() # needs sage.symbolic 1.41421356237309 - sage: complex_root_of(x^2-2, 3).n() + sage: complex_root_of(x^2 - 2, 3).n() # needs sage.symbolic Traceback (most recent call last): ... IndexError: root index out of [-2, 1] range, got 3 @@ -2154,9 +2204,9 @@ def _evalf_(self, poly, index, parent=None, algorithm=None): Check that low precision is handled (:trac:`24378`):: - sage: complex_root_of(x^8-1, 7).n(2) + sage: complex_root_of(x^8 - 1, 7).n(2) # needs sage.symbolic 0.75 + 0.75*I - sage: complex_root_of(x^8-1, 7).n(20) + sage: complex_root_of(x^8 - 1, 7).n(20) # needs sage.symbolic 0.70711 + 0.70711*I """ from sympy.core.evalf import prec_to_dps @@ -2168,6 +2218,7 @@ def _evalf_(self, poly, index, parent=None, algorithm=None): sobj = CRootOf(Poly(poly._sympy_()), int(index)) return parent(sobj.n(1 + prec_to_dps(prec))._sage_()) + complex_root_of = Function_crootof() @@ -2176,12 +2227,13 @@ class Function_elementof(BuiltinFunction): Formal set membership function that is only accessible internally. This function is called to express a set membership statement, - usually as part of a solution set returned by ``solve()``. + usually as part of a solution set returned by :func:`solve`. See :class:`sage.sets.set.Set` and :class:`sage.sets.real_set.RealSet` for possible set arguments. EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import element_of sage: element_of(x, SR(ZZ)) element_of(x, Integer Ring) @@ -2208,9 +2260,9 @@ def _eval_(self, x, s): EXAMPLES:: sage: from sage.functions.other import element_of - sage: element_of(x, SR(RealSet(-oo, oo))) + sage: element_of(x, SR(RealSet(-oo, oo))) # needs sage.symbolic element_of(x, (-oo, +oo)) - sage: element_of(x, 0) + sage: element_of(x, 0) # needs sage.symbolic Traceback (most recent call last): ... ValueError: not a set: 0 @@ -2234,11 +2286,12 @@ def _print_latex_(self, ex, s): EXAMPLES:: sage: from sage.functions.other import element_of - sage: latex(element_of(x, SR(ZZ))) + sage: latex(element_of(x, SR(ZZ))) # needs sage.symbolic x \in \Bold{Z} - sage: latex(element_of(x, SR(Set([4,6,8])))) + sage: latex(element_of(x, SR(Set([4,6,8])))) # needs sage.symbolic x \in \left\{8, 4, 6\right\} """ return r"{} \in {}".format(latex(ex), latex(s)) + element_of = Function_elementof() diff --git a/src/sage/functions/piecewise.py b/src/sage/functions/piecewise.py index 6955f6209eb..ff3851a1776 100644 --- a/src/sage/functions/piecewise.py +++ b/src/sage/functions/piecewise.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.symbolic r""" Piecewise functions @@ -71,11 +71,12 @@ # https://www.gnu.org/licenses/ # **************************************************************************** - -from sage.symbolic.function import BuiltinFunction -from sage.sets.real_set import RealSet -from sage.symbolic.ring import SR +from sage.misc.lazy_import import lazy_import from sage.rings.infinity import minus_infinity, infinity +from sage.sets.real_set import RealSet +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.symbolic.ring', 'SR') class PiecewiseFunction(BuiltinFunction): @@ -756,17 +757,22 @@ def integral(self, parameters, variable, x=None, a=None, b=None, definite=False, sage: f2(x) = 3 - x sage: f = piecewise([[(-2, 0), f1], [(0, 3), f2]]) sage: f.integral() - piecewise(x|-->2*x + 4 on (-2, 0), x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x) + piecewise(x|-->2*x + 4 on (-2, 0), + x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x) sage: f1(y) = -1 sage: f2(y) = y + 3 sage: f3(y) = -y - 1 sage: f4(y) = y^2 - 1 sage: f5(y) = 3 - sage: f = piecewise([[[-4,-3],f1],[(-3,-2),f2],[[-2,0],f3],[(0,2),f4],[[2,3],f5]]) - sage: F = f.integral(y) - sage: F - piecewise(y|-->-y - 4 on [-4, -3], y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2), y|-->-1/2*y^2 - y - 1/2 on [-2, 0], y|-->1/3*y^3 - y - 1/2 on (0, 2), y|-->3*y - 35/6 on [2, 3]; y) + sage: f = piecewise([[[-4,-3],f1], [(-3,-2),f2], [[-2,0],f3], + ....: [(0,2),f4], [[2,3],f5]]) + sage: F = f.integral(y); F + piecewise(y|-->-y - 4 on [-4, -3], + y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2), + y|-->-1/2*y^2 - y - 1/2 on [-2, 0], + y|-->1/3*y^3 - y - 1/2 on (0, 2), + y|-->3*y - 35/6 on [2, 3]; y) Ensure results are consistent with FTC:: @@ -792,7 +798,9 @@ def integral(self, parameters, variable, x=None, a=None, b=None, definite=False, sage: f3(y) = 3 sage: f = piecewise([[(-infinity, -3), f1], [(-3, 0), f2], [(0, infinity), f3]]) sage: f.integral() - piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3), y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0), y|-->3*y + 9/2 on (0, +oo); y) + piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3), + y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0), + y|-->3*y + 9/2 on (0, +oo); y) :: @@ -934,33 +942,51 @@ def convolution(self, parameters, variable, other): EXAMPLES:: sage: x = PolynomialRing(QQ,'x').gen() - sage: f = piecewise([[[0,1],1]]) ## example 0 + sage: f = piecewise([[[0,1],1]]) ## example 0 sage: g = f.convolution(f); g piecewise(x|-->x on (0, 1], x|-->-x + 2 on (1, 2]; x) sage: h = f.convolution(g); h - piecewise(x|-->1/2*x^2 on (0, 1], x|-->-x^2 + 3*x - 3/2 on (1, 2], x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) - sage: f = piecewise([[(0,1),1],[(1,2),2],[(2,3),1]]) ## example 1 + piecewise(x|-->1/2*x^2 on (0, 1], + x|-->-x^2 + 3*x - 3/2 on (1, 2], + x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) + sage: f = piecewise([[(0,1),1], [(1,2),2], [(2,3),1]]) ## example 1 sage: g = f.convolution(f) sage: h = f.convolution(g); h - piecewise(x|-->1/2*x^2 on (0, 1], x|-->2*x^2 - 3*x + 3/2 on (1, 3], x|-->-2*x^2 + 21*x - 69/2 on (3, 4], x|-->-5*x^2 + 45*x - 165/2 on (4, 5], x|-->-2*x^2 + 15*x - 15/2 on (5, 6], x|-->2*x^2 - 33*x + 273/2 on (6, 8], x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x) - sage: f = piecewise([[(-1,1),1]]) ## example 2 + piecewise(x|-->1/2*x^2 on (0, 1], + x|-->2*x^2 - 3*x + 3/2 on (1, 3], + x|-->-2*x^2 + 21*x - 69/2 on (3, 4], + x|-->-5*x^2 + 45*x - 165/2 on (4, 5], + x|-->-2*x^2 + 15*x - 15/2 on (5, 6], + x|-->2*x^2 - 33*x + 273/2 on (6, 8], + x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x) + sage: f = piecewise([[(-1,1),1]]) ## example 2 sage: g = piecewise([[(0,3),x]]) sage: f.convolution(g) - piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1], x|-->2*x on (1, 2], x|-->-1/2*x^2 + x + 4 on (2, 4]; x) - sage: g = piecewise([[(0,3),1],[(3,4),2]]) + piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1], + x|-->2*x on (1, 2], + x|-->-1/2*x^2 + x + 4 on (2, 4]; x) + sage: g = piecewise([[(0,3),1], [(3,4),2]]) sage: f.convolution(g) - piecewise(x|-->x + 1 on (-1, 1], x|-->2 on (1, 2], x|-->x on (2, 3], x|-->-x + 6 on (3, 4], x|-->-2*x + 10 on (4, 5]; x) + piecewise(x|-->x + 1 on (-1, 1], + x|-->2 on (1, 2], + x|-->x on (2, 3], + x|-->-x + 6 on (3, 4], + x|-->-2*x + 10 on (4, 5]; x) Check that the bugs raised in :trac:`12123` are fixed:: sage: f = piecewise([[(-2, 2), 2]]) sage: g = piecewise([[(0, 2), 3/4]]) sage: f.convolution(g) - piecewise(x|-->3/2*x + 3 on (-2, 0], x|-->3 on (0, 2], x|-->-3/2*x + 6 on (2, 4]; x) + piecewise(x|-->3/2*x + 3 on (-2, 0], + x|-->3 on (0, 2], + x|-->-3/2*x + 6 on (2, 4]; x) sage: f = piecewise([[(-1, 1), 1]]) sage: g = piecewise([[(0, 1), x], [(1, 2), -x + 2]]) sage: f.convolution(g) - piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 0], x|-->-1/2*x^2 + x + 1/2 on (0, 2], x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) + piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 0], + x|-->-1/2*x^2 + x + 1/2 on (0, 2], + x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) """ from sage.symbolic.integration.integral import definite_integral f = self @@ -1014,11 +1040,14 @@ def trapezoid(self, parameters, variable, N): sage: f = piecewise([[[0,1], x^2], [RealSet.open_closed(1,2), 5-x^2]]) sage: f.trapezoid(2) - piecewise(x|-->1/2*x on (0, 1/2), x|-->3/2*x - 1/2 on (1/2, 1), x|-->7/2*x - 5/2 on (1, 3/2), x|-->-7/2*x + 8 on (3/2, 2); x) - sage: f = piecewise([[[-1,1], 1-x^2]]) + piecewise(x|-->1/2*x on (0, 1/2), + x|-->3/2*x - 1/2 on (1/2, 1), + x|-->7/2*x - 5/2 on (1, 3/2), + x|-->-7/2*x + 8 on (3/2, 2); x) + sage: f = piecewise([[[-1,1], 1 - x^2]]) sage: f.trapezoid(4).integral(definite=True) 5/4 - sage: f = piecewise([[[-1,1], 1/2+x-x^3]]) ## example 3 + sage: f = piecewise([[[-1,1], 1/2 + x - x^3]]) ## example 3 sage: f.trapezoid(6).integral(definite=True) 1 @@ -1031,7 +1060,10 @@ def trapezoid(self, parameters, variable, N): sage: f2 = 5-y^2 sage: f = piecewise([[[0,1],f1], [RealSet.open_closed(1,2),f2]]) sage: f.trapezoid(2) - piecewise(y|-->1/2*y on (0, 1/2), y|-->3/2*y - 1/2 on (1/2, 1), y|-->7/2*y - 5/2 on (1, 3/2), y|-->-7/2*y + 8 on (3/2, 2); y) + piecewise(y|-->1/2*y on (0, 1/2), + y|-->3/2*y - 1/2 on (1/2, 1), + y|-->7/2*y - 5/2 on (1, 3/2), + y|-->-7/2*y + 8 on (3/2, 2); y) """ def func(x0, x1): f0, f1 = self(x0), self(x1) @@ -1066,7 +1098,7 @@ def laplace(self, parameters, variable, x='x', s='t'): EXAMPLES:: sage: x, s, w = var('x, s, w') - sage: f = piecewise([[(0,1),1],[[1,2], 1-x]]) + sage: f = piecewise([[(0,1),1], [[1,2], 1 - x]]) sage: f.laplace(x, s) -e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2 sage: f.laplace(x, w) @@ -1075,7 +1107,7 @@ def laplace(self, parameters, variable, x='x', s='t'): :: sage: y, t = var('y, t') - sage: f = piecewise([[[1,2], 1-y]]) + sage: f = piecewise([[[1,2], 1 - y]]) sage: f.laplace(y, t) (t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2 @@ -1085,7 +1117,7 @@ def laplace(self, parameters, variable, x='x', s='t'): sage: t = var('t') sage: f1(t) = -t sage: f2(t) = 2 - sage: f = piecewise([[[0,1],f1],[(1,infinity),f2]]) + sage: f = piecewise([[[0,1],f1], [(1,infinity),f2]]) sage: f.laplace(t,s) (s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2 """ @@ -1151,8 +1183,8 @@ def fourier_series_cosine_coefficient(self, parameters, more than one period, the half-period must be passed as the second argument; for instance:: - sage: f2 = piecewise([((0,1), x), ((1,2), 2-x), - ....: ((2,3), x-2), ((3,4), 2-(x-2))]) + sage: f2 = piecewise([((0,1), x), ((1,2), 2 - x), + ....: ((2,3), x - 2), ((3,4), 2 - (x-2))]) sage: bool(f2.restriction((0,2)) == f) # f2 extends f on (0,4) True sage: f2.fourier_series_cosine_coefficient(3, 1) # half-period = 1 @@ -1160,7 +1192,7 @@ def fourier_series_cosine_coefficient(self, parameters, The default half-period is 2 and one has:: - sage: f2.fourier_series_cosine_coefficient(3) # half-period = 2 + sage: f2.fourier_series_cosine_coefficient(3) # half-period = 2 0 The Fourier coefficient `-4/(9\pi^2)` obtained above is actually @@ -1382,15 +1414,15 @@ def _sympy_(self, parameters, variable): EXAMPLES:: sage: ex = piecewise([((0, 1), pi), ([1, 2], x)]) - sage: f = ex._sympy_(); f + sage: f = ex._sympy_(); f # needs sympy Piecewise((pi, (x > 0) & (x < 1)), (x, (x >= 1) & (x <= 2))) - sage: f.diff() + sage: f.diff() # needs sympy Piecewise((0, (x > 0) & (x < 1)), (1, (x >= 1) & (x <= 2))) sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))]) - sage: g = ex._sympy_(); g + sage: g = ex._sympy_(); g # needs sympy Piecewise((1/x, (x > -100) & (x < -2)), (cos(x), x > 1)) - sage: g.diff() + sage: g.diff() # needs sympy Piecewise((-1/x**2, (x > -100) & (x < -2)), (-sin(x), x > 1)) """ from sympy import Piecewise as pw @@ -1408,22 +1440,22 @@ def _giac_init_(self, parameters, variable): EXAMPLES:: sage: ex = piecewise([((0, 1), pi), ([1, 2], x)]) - sage: f = ex._giac_(); f + sage: f = ex._giac_(); f # needs sage.libs.giac piecewise(((sageVARx>0) and (1>sageVARx)),pi,((sageVARx>=1) and (2>=sageVARx)),sageVARx) - sage: f.diff(x) + sage: f.diff(x) # needs sage.libs.giac piecewise(((sageVARx>0) and (1>sageVARx)),0,((sageVARx>=1) and (2>=sageVARx)),1) - sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))]) - sage: g = ex._giac_(); g + sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))]) # needs sage.libs.giac + sage: g = ex._giac_(); g # needs sage.libs.giac piecewise(((sageVARx>-100) and ((-2)>sageVARx)),1/sageVARx,sageVARx>1,cos(sageVARx)) - sage: g.diff(x) + sage: g.diff(x) # needs sage.libs.giac piecewise(((sageVARx>-100) and ((-2)>sageVARx)),-1/sageVARx^2,sageVARx>1,-sin(sageVARx)) TESTS:: - sage: f = piecewise([([0,1],x),((1,2),3*x)]) - sage: a = libgiac(f) # random because verbose - sage: a + sage: f = piecewise([([0,1], x), ((1,2), 3*x)]) + sage: a = libgiac(f) # random because verbose # needs sage.libs.giac + sage: a # needs sage.libs.giac piecewise(((sageVARx>=0) and (1>=sageVARx)),sageVARx,((sageVARx>1) and (2>sageVARx)),sageVARx*3) """ from sage.misc.flatten import flatten diff --git a/src/sage/functions/prime_pi.pyx b/src/sage/functions/prime_pi.pyx index fd2956be193..141e538cf74 100644 --- a/src/sage/functions/prime_pi.pyx +++ b/src/sage/functions/prime_pi.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs primecountpy r""" Counting primes @@ -32,10 +33,13 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** +from sage.misc.lazy_import import LazyImport from sage.rings.integer cimport Integer from sage.symbolic.function cimport BuiltinFunction -from primecountpy.primecount import prime_pi as _prime_pi -from primecountpy.primecount import phi as _phi + +_prime_pi = LazyImport('primecountpy.primecount', 'prime_pi', as_name='prime_pi') +_phi = LazyImport('primecountpy.primecount', 'phi', as_name='_phi') + cdef class PrimePi(BuiltinFunction): def __init__(self): @@ -45,8 +49,8 @@ cdef class PrimePi(BuiltinFunction): INPUT: - - ``x`` - a real number - - ``prime_bound`` - (default 0) a real number < 2^32, ``prime_pi`` will + - ``x`` -- a real number + - ``prime_bound`` -- (default 0) a real number < 2^32; :func:`prime_pi` will make sure to use all the primes up to ``prime_bound`` (although, possibly more) in computing ``prime_pi``, this can potentially speedup the time of computation, at a cost to memory usage. @@ -59,6 +63,7 @@ cdef class PrimePi(BuiltinFunction): These examples test common inputs:: + sage: # needs sage.symbolic sage: prime_pi(7) 4 sage: prime_pi(100) @@ -73,13 +78,13 @@ cdef class PrimePi(BuiltinFunction): The following test is to verify that :trac:`4670` has been essentially resolved:: - sage: prime_pi(10^10) + sage: prime_pi(10^10) # needs sage.symbolic 455052511 - The ``prime_pi`` function also has a special plotting method, so it + The :func:`prime_pi` function also has a special plotting method, so it plots quickly and perfectly as a step function:: - sage: P = plot(prime_pi, 50, 100) + sage: P = plot(prime_pi, 50, 100) # needs sage.plot sage.symbolic """ super(PrimePi, self).__init__('prime_pi', latex_name=r"\pi", @@ -91,6 +96,7 @@ cdef class PrimePi(BuiltinFunction): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: prime_pi.__call__(756) 133 sage: prime_pi.__call__(6574, 577) @@ -128,7 +134,7 @@ cdef class PrimePi(BuiltinFunction): Make sure we actually compute correct results for 64-bit entries:: - sage: for i in (32..42): prime_pi(2^i) # long time (13s on sage.math, 2011) + sage: for i in (32..42): prime_pi(2^i) # long time (13s on sage.math, 2011) 203280221 393615806 762939111 @@ -181,9 +187,9 @@ cdef class PrimePi(BuiltinFunction): EXAMPLES:: - sage: plot(prime_pi, 1, 100) + sage: plot(prime_pi, 1, 100) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: prime_pi.plot(1, 51, thickness=2, vertical_lines=False) + sage: prime_pi.plot(1, 51, thickness=2, vertical_lines=False) # needs sage.plot sage.symbolic Graphics object consisting of 16 graphics primitives """ from sage.plot.step import plot_step_function @@ -200,9 +206,10 @@ cdef class PrimePi(BuiltinFunction): v.append((xmax, y)) return plot_step_function(v, vertical_lines=vertical_lines, **kwds) -######## + prime_pi = PrimePi() + cpdef Integer legendre_phi(x, a): r""" Legendre's formula, also known as the partial sieve function, is a useful @@ -257,4 +264,5 @@ cpdef Integer legendre_phi(x, a): # Deal with the general case return Integer(_phi(y, a)) + partial_sieve_function = legendre_phi diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index bf352a8bbc6..93e032d0677 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -141,15 +141,27 @@ # **************************************************************************** import sage.rings.abc + +from sage.misc.functional import sqrt +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer -from sage.misc.latex import latex from sage.rings.integer_ring import ZZ -from sage.symbolic.constants import pi +from sage.structure.element import parent as s_parent from sage.symbolic.function import BuiltinFunction -from sage.libs.mpmath import utils as mpmath_utils -from sage.functions.all import sin, cot, exp -from sage.misc.functional import sqrt -from sage.symbolic.constants import I + +lazy_import('sage.functions.jacobi', 'jacobi_am_f') +lazy_import('sage.functions.log', ['exp']) +lazy_import('sage.functions.trig', ['sin', 'cot']) + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.symbolic.constants', ['I', 'pi']) + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', + ['spherharm', 'ellipe', 'ellipf', 'ellipk', 'ellippi'], + as_=['_mpmath_spherharm', '_mpmath_ellipe', '_mpmath_ellipf', + '_mpmath_ellipk', '_mpmath_ellippi']) class SphericalHarmonic(BuiltinFunction): @@ -161,6 +173,7 @@ class SphericalHarmonic(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: x, y = var('x, y') sage: spherical_harmonic(3, 2, x, y) 1/8*sqrt(30)*sqrt(7)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi) @@ -175,6 +188,7 @@ class SphericalHarmonic(BuiltinFunction): The degree `n` and the order `m` can be symbolic:: + sage: # needs sage.symbolic sage: n, m = var('n m') sage: spherical_harmonic(n, m, x, y) spherical_harmonic(n, m, x, y) @@ -189,26 +203,27 @@ class SphericalHarmonic(BuiltinFunction): The convention regarding the Condon-Shortley phase `(-1)^m` is the same as for SymPy's spherical harmonics and :wikipedia:`Spherical_harmonics`:: + sage: # needs sage.symbolic sage: spherical_harmonic(1, 1, x, y) -1/4*sqrt(3)*sqrt(2)*e^(I*y)*sin(x)/sqrt(pi) - sage: from sympy import Ynm - sage: Ynm(1, 1, x, y).expand(func=True) + sage: from sympy import Ynm # needs sympy + sage: Ynm(1, 1, x, y).expand(func=True) # needs sympy -sqrt(6)*exp(I*y)*sin(x)/(4*sqrt(pi)) - sage: spherical_harmonic(1, 1, x, y) - Ynm(1, 1, x, y) + sage: spherical_harmonic(1, 1, x, y) - Ynm(1, 1, x, y) # needs sympy 0 It also agrees with SciPy's spherical harmonics:: - sage: spherical_harmonic(1, 1, pi/2, pi).n() # abs tol 1e-14 + sage: spherical_harmonic(1, 1, pi/2, pi).n() # abs tol 1e-14 # needs sage.symbolic 0.345494149471335 - sage: from scipy.special import sph_harm # NB: arguments x and y are swapped - sage: sph_harm(1, 1, pi.n(), (pi/2).n()) # abs tol 1e-14 + sage: from scipy.special import sph_harm # NB: arguments x and y are swapped # needs scipy + sage: sph_harm(1, 1, pi.n(), (pi/2).n()) # abs tol 1e-14 # needs scipy sage.symbolic (0.3454941494713355-4.231083042742082e-17j) Note that this convention differs from the one in Maxima, as revealed by the sign difference for odd values of `m`:: - sage: maxima.spherical_harmonic(1, 1, x, y).sage() + sage: maxima.spherical_harmonic(1, 1, x, y).sage() # needs sage.symbolic 1/2*sqrt(3/2)*e^(I*y)*sin(x)/sqrt(pi) It follows that, contrary to Maxima, SageMath uses the same sign convention @@ -224,8 +239,8 @@ def __init__(self): r""" TESTS:: - sage: n, m, theta, phi = var('n m theta phi') - sage: spherical_harmonic(n, m, theta, phi)._sympy_() + sage: n, m, theta, phi = var('n m theta phi') # needs sage.symbolic + sage: spherical_harmonic(n, m, theta, phi)._sympy_() # needs sympy sage.symbolic Ynm(n, m, theta, phi) """ BuiltinFunction.__init__(self, 'spherical_harmonic', nargs=4, @@ -239,6 +254,7 @@ def _eval_(self, n, m, theta, phi, **kwargs): r""" TESTS:: + sage: # needs sage.symbolic sage: x, y = var('x y') sage: spherical_harmonic(1, 2, x, y) 0 @@ -255,28 +271,29 @@ def _eval_(self, n, m, theta, phi, **kwargs): Check that :trac:`20939` is fixed:: - sage: ex = spherical_harmonic(3, 2, 1, 2*pi/3) - sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly() + sage: ex = spherical_harmonic(3, 2, 1, 2*pi/3) # needs sage.symbolic + sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly() # needs sage.rings.number_field sage.symbolic x^4 + 105/32*x^2 + 11025/1024 Check whether Sage yields correct results compared to Maxima, up to the Condon-Shortley phase factor `(-1)^m` (see :trac:`25034` and :trac:`33117`):: - sage: spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 + sage: # needs sage.symbolic + sage: spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 -0.259120612103502 - 0.149603355150537*I - sage: maxima.spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 + sage: maxima.spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 0.259120612103502 + 0.149603355150537*I - sage: spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 + sage: spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 0.259120612103502 - 0.149603355150537*I - sage: maxima.spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 + sage: maxima.spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 -0.259120612103502 + 0.149603355150537*I Check that :trac:`33501` is fixed:: - sage: spherical_harmonic(2, 1, x, y) + sage: spherical_harmonic(2, 1, x, y) # needs sage.symbolic -1/4*sqrt(6)*sqrt(5)*cos(x)*e^(I*y)*sin(x)/sqrt(pi) - sage: spherical_harmonic(5, -3, x, y) + sage: spherical_harmonic(5, -3, x, y) # needs sage.symbolic -1/32*(9*sqrt(385)*sin(x)^4 - 8*sqrt(385)*sin(x)^2)*e^(-3*I*y)*sin(x)/sqrt(pi) """ @@ -298,9 +315,9 @@ def _evalf_(self, n, m, theta, phi, parent, **kwds): r""" TESTS:: - sage: spherical_harmonic(3 + I, 2, 1, 2).n(100) + sage: spherical_harmonic(3 + I, 2, 1, 2).n(100) # needs sage.symbolic -0.35115433730748836508201061672 - 0.41556223397536866209990358597*I - sage: spherical_harmonic(I, I, I, I).n() + sage: spherical_harmonic(I, I, I, I).n() # needs sage.symbolic 7.66678546069894 - 0.265754432549751*I Consistency with ``_eval_``:: @@ -308,21 +325,20 @@ def _evalf_(self, n, m, theta, phi, parent, **kwds): sage: d = lambda a, b: abs(spherical_harmonic(a, b, 1., 2.) ....: - spherical_harmonic(a, b, 1, 2).n()) sage: ab = [(0, 0), (1, -1), (1, 0), (1, 1), (3, 2), (3, 3)] - sage: all(d(a, b) < 1e-14 for a, b in ab) + sage: all(d(a, b) < 1e-14 for a, b in ab) # needs sage.symbolic True """ - from mpmath import spherharm - return mpmath_utils.call(spherharm, n, m, theta, phi, parent=parent) + return _mpmath_utils_call(_mpmath_spherharm, n, m, theta, phi, parent=parent) def _derivative_(self, n, m, theta, phi, diff_param): r""" TESTS:: + sage: # needs sage.symbolic sage: n, m, theta, phi = var('n m theta phi') sage: Ynm = spherical_harmonic(n, m, theta, phi) - sage: DY_theta = Ynm.diff(theta) - sage: DY_theta + sage: DY_theta = Ynm.diff(theta); DY_theta m*cot(theta)*spherical_harmonic(n, m, theta, phi) + sqrt(-(m + n + 1)*(m - n))*e^(-I*phi)*spherical_harmonic(n, m + 1, theta, phi) sage: Ynm.diff(phi) @@ -330,6 +346,7 @@ def _derivative_(self, n, m, theta, phi, diff_param): Check that :trac:`33117` is fixed:: + sage: # needs sage.symbolic sage: DY_theta.subs({n: 1, m: 0}) -1/2*sqrt(3)*sin(theta)/sqrt(pi) sage: Ynm.subs({n: 1, m: 0}).diff(theta) @@ -365,8 +382,8 @@ def _print_latex_(self, n, m, theta, phi): r""" TESTS:: - sage: y = var('y') - sage: latex(spherical_harmonic(3, 2, x, y, hold=True)) + sage: y = var('y') # needs sage.symbolic + sage: latex(spherical_harmonic(3, 2, x, y, hold=True)) # needs sage.symbolic Y_{3}^{2}\left(x, y\right) """ return r"Y_{{{}}}^{{{}}}\left({}, {}\right)".format( @@ -402,30 +419,31 @@ def elliptic_j(z, prec=53): EXAMPLES:: - sage: elliptic_j(CC(i)) + sage: elliptic_j(CC(i)) # needs sage.rings.real_mpfr 1728.00000000000 - sage: elliptic_j(sqrt(-2.0)) + sage: elliptic_j(sqrt(-2.0)) # needs sage.rings.complex_double 8000.00000000000 - sage: z = ComplexField(100)(1,sqrt(11))/2 - sage: elliptic_j(z) + sage: z = ComplexField(100)(1, sqrt(11))/2 # needs sage.rings.real_mpfr sage.symbolic + sage: elliptic_j(z) # needs sage.rings.real_mpfr sage.symbolic -32768.000... - sage: elliptic_j(z).real().round() + sage: elliptic_j(z).real().round() # needs sage.rings.real_mpfr sage.symbolic -32768 :: - sage: tau = (1 + sqrt(-163))/2 - sage: (-elliptic_j(tau.n(100)).real().round())^(1/3) + sage: tau = (1 + sqrt(-163))/2 # needs sage.symbolic + sage: (-elliptic_j(tau.n(100)).real().round())^(1/3) # needs sage.symbolic 640320 This example shows the need for higher precision than the default one of the `ComplexField`, see :trac:`28355`:: - sage: -elliptic_j(tau) # rel tol 1e-2 + sage: # needs sage.symbolic + sage: -elliptic_j(tau) # rel tol 1e-2 2.62537412640767e17 - 732.558854258998*I - sage: -elliptic_j(tau,75) # rel tol 1e-2 + sage: -elliptic_j(tau, 75) # rel tol 1e-2 2.625374126407680000000e17 - 0.0001309913593909879441262*I - sage: -elliptic_j(tau,100) # rel tol 1e-2 + sage: -elliptic_j(tau, 100) # rel tol 1e-2 2.6253741264076799999999999999e17 - 1.3012822400356887122945119790e-12*I sage: (-elliptic_j(tau, 100).real().round())^(1/3) 640320 @@ -455,16 +473,16 @@ class EllipticE(BuiltinFunction): EXAMPLES:: - sage: z = var("z") - sage: elliptic_e(z, 1) + sage: z = var("z") # needs sage.symbolic + sage: elliptic_e(z, 1) # needs sage.symbolic elliptic_e(z, 1) - sage: elliptic_e(z, 1).simplify() # not tested - gives wrong answer with maxima < 5.47 + sage: elliptic_e(z, 1).simplify() # not tested # needs sage.symbolic 2*round(z/pi) - sin(pi*round(z/pi) - z) - sage: elliptic_e(z, 0) + sage: elliptic_e(z, 0) # needs sage.symbolic z - sage: elliptic_e(0.5, 0.1) # abs tol 2e-15 + sage: elliptic_e(0.5, 0.1) # abs tol 2e-15 # needs mpmath 0.498011394498832 - sage: elliptic_e(1/2, 1/10).n(200) + sage: elliptic_e(1/2, 1/10).n(200) # needs sage.symbolic 0.4980113944988315331154610406... .. SEEALSO:: @@ -487,27 +505,28 @@ def __init__(self): sage: loads(dumps(elliptic_e)) elliptic_e - sage: elliptic_e(x, x)._sympy_() + sage: elliptic_e(x, x)._sympy_() # needs sympy sage.symbolic elliptic_e(x, x) Check that :trac:`34085` is fixed:: - sage: _ = var("x y") - sage: fricas(elliptic_e(x, y)) # optional - fricas + sage: _ = var("x y") # needs sage.symbolic + sage: fricas(elliptic_e(x, y)) # optional - fricas, needs sage.symbolic ellipticE(sin(x),y) However, the conversion is only correct in the interval `[-\pi/2, \pi/2]`:: - sage: fricas(elliptic_e(x, y)).D(x).sage()/elliptic_e(x, y).diff(x) # optional - fricas + sage: fricas(elliptic_e(x, y)).D(x).sage()/elliptic_e(x, y).diff(x) # optional - fricas, needs sage.symbolic cos(x)/sqrt(-sin(x)^2 + 1) Numerically:: - sage: f = lambda x, y: elliptic_e(arcsin(x), y).subs(x=x, y=y) # optional - fricas - sage: g = lambda x, y: fricas.ellipticE(x, y).sage() # optional - fricas - sage: d = lambda x, y: f(x, y) - g(x, y) # optional - fricas - sage: [d(N(-pi/2+x), y) for x in range(1, 3) for y in range(-2,2)] # optional - fricas tol 1e-8 + sage: f = lambda x, y: elliptic_e(arcsin(x), y).subs(x=x, y=y) + sage: g = lambda x, y: fricas.ellipticE(x, y).sage() + sage: d = lambda x, y: f(x, y) - g(x, y) + sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic + ....: for x in range(1, 3) for y in range(-2, 2)] [0.000000000000000, 0.000000000000000, 0.000000000000000, @@ -530,6 +549,7 @@ def _eval_(self, z, m): """ EXAMPLES:: + sage: # needs sage.symbolic sage: z = var("z") sage: elliptic_e(0, x) 0 @@ -542,7 +562,7 @@ def _eval_(self, z, m): Here arccoth doesn't have 1 in its domain, so we just hold the expression:: - sage: elliptic_e(arccoth(1), x^2*e) + sage: elliptic_e(arccoth(1), x^2*e) # needs sage.symbolic elliptic_e(+Infinity, x^2*e) """ if z == 0: @@ -556,32 +576,31 @@ def _evalf_(self, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_e(0.5, 0.1) + sage: elliptic_e(0.5, 0.1) # needs mpmath 0.498011394498832 - sage: elliptic_e(1/2, 1/10).n(200) + sage: elliptic_e(1/2, 1/10).n(200) # needs sage.symbolic 0.4980113944988315331154610406... - sage: elliptic_e(I, I).n() + sage: elliptic_e(I, I).n() # needs sage.symbolic -0.189847437084712 + 1.03209769372160*I TESTS: This gave an error in Maxima (:trac:`15046`):: - sage: elliptic_e(2.5, 2.5) + sage: elliptic_e(2.5, 2.5) # needs mpmath 0.535647771608740 + 1.63996015168665*I """ - R = parent or parent(z) - from mpmath import ellipe - return mpmath_utils.call(ellipe, z, m, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellipe, z, m, parent=R) def _derivative_(self, z, m, diff_param): """ EXAMPLES:: - sage: x,z = var('x,z') - sage: elliptic_e(z, x).diff(z, 1) + sage: x, z = var('x,z') # needs sage.symbolic + sage: elliptic_e(z, x).diff(z, 1) # needs sage.symbolic sqrt(-x*sin(z)^2 + 1) - sage: elliptic_e(z, x).diff(x, 1) + sage: elliptic_e(z, x).diff(x, 1) # needs sage.symbolic 1/2*(elliptic_e(z, x) - elliptic_f(z, x))/x """ if diff_param == 0: @@ -593,7 +612,7 @@ def _print_latex_(self, z, m): r""" EXAMPLES:: - sage: latex(elliptic_e(pi, x)) + sage: latex(elliptic_e(pi, x)) # needs sage.symbolic E(\pi\,|\,x) """ return r"E(%s\,|\,%s)" % (latex(z), latex(m)) @@ -612,9 +631,9 @@ class EllipticEC(BuiltinFunction): EXAMPLES:: - sage: elliptic_ec(0.1) + sage: elliptic_ec(0.1) # needs mpmath 1.53075763689776 - sage: elliptic_ec(x).diff() + sage: elliptic_ec(x).diff() # needs sage.symbolic 1/2*(elliptic_ec(x) - elliptic_kc(x))/x .. SEEALSO:: @@ -631,17 +650,17 @@ def __init__(self): sage: loads(dumps(elliptic_ec)) elliptic_ec - sage: elliptic_ec(x)._sympy_() + sage: elliptic_ec(x)._sympy_() # needs sage.symbolic elliptic_e(x) TESTS:: - sage: fricas(elliptic_ec(x)) # optional - fricas + sage: fricas(elliptic_ec(x)) # optional - fricas, needs sage.symbolic ellipticE(x) - sage: elliptic_ec(0.5) # abs tol 1e-8 + sage: elliptic_ec(0.5) # abs tol 1e-8 # needs sage.symbolic 1.35064388104768 - sage: fricas.ellipticE(0.5).sage() # abs tol 1e-8 # optional - fricas + sage: fricas.ellipticE(0.5).sage() # abs tol 1e-8 # optional - fricas, needs sage.symbolic 1.3506438810476755025201749 """ BuiltinFunction.__init__(self, 'elliptic_ec', nargs=1, latex_name='E', @@ -654,11 +673,11 @@ def _eval_(self, x): """ EXAMPLES:: - sage: elliptic_ec(0) + sage: elliptic_ec(0) # needs sage.symbolic 1/2*pi - sage: elliptic_ec(1) + sage: elliptic_ec(1) # needs sage.symbolic 1 - sage: elliptic_ec(x) + sage: elliptic_ec(x) # needs sage.symbolic elliptic_ec(x) """ if x == 0: @@ -670,22 +689,21 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_ec(sqrt(2)/2).n() + sage: elliptic_ec(sqrt(2)/2).n() # needs sage.symbolic 1.23742252487318 - sage: elliptic_ec(sqrt(2)/2).n(200) + sage: elliptic_ec(sqrt(2)/2).n(200) # needs sage.symbolic 1.237422524873181672854746084083... - sage: elliptic_ec(I).n() + sage: elliptic_ec(I).n() # needs sage.symbolic 1.63241178144043 - 0.369219492375499*I """ - R = parent or parent(x) - from mpmath import ellipe - return mpmath_utils.call(ellipe, x, parent=R) + R = parent or s_parent(x) + return _mpmath_utils_call(_mpmath_ellipe, x, parent=R) def _derivative_(self, x, diff_param): """ EXAMPLES:: - sage: elliptic_ec(x).diff() + sage: elliptic_ec(x).diff() # needs sage.symbolic 1/2*(elliptic_ec(x) - elliptic_kc(x))/x """ return (elliptic_ec(x) - elliptic_kc(x)) / (Integer(2) * x) @@ -710,7 +728,7 @@ class EllipticEU(BuiltinFunction): EXAMPLES:: - sage: elliptic_eu (0.5, 0.1) + sage: elliptic_eu(0.5, 0.1) # needs mpmath 0.496054551286597 .. SEEALSO:: @@ -737,7 +755,7 @@ def _eval_(self, u, m): """ EXAMPLES:: - sage: elliptic_eu(1,1) + sage: elliptic_eu(1, 1) # needs sage.symbolic elliptic_eu(1, 1) """ pass @@ -746,22 +764,22 @@ def _evalf_(self, u, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_eu(1,1).n() + sage: elliptic_eu(1, 1).n() # needs sage.symbolic 0.761594155955765 - sage: elliptic_eu(1,1).n(200) + sage: elliptic_eu(1, 1).n(200) # needs sage.symbolic 0.7615941559557648881194582... """ - R = parent or parent(u) - return mpmath_utils.call(elliptic_eu_f, u, m, parent=R) + R = parent or s_parent(u) + return _mpmath_utils_call(elliptic_eu_f, u, m, parent=R) def _derivative_(self, u, m, diff_param): """ EXAMPLES:: - sage: x,m = var('x,m') - sage: elliptic_eu(x,m).diff(x) + sage: x, m = var('x,m') # needs sage.symbolic + sage: elliptic_eu(x, m).diff(x) # needs sage.symbolic sqrt(-m*jacobi_sn(x, m)^2 + 1)*jacobi_dn(x, m) - sage: elliptic_eu(x,m).diff(m) + sage: elliptic_eu(x, m).diff(m) # needs sage.symbolic 1/2*(elliptic_eu(x, m) - elliptic_f(jacobi_am(x, m), m))/m - 1/2*(m*jacobi_cn(x, m)*jacobi_sn(x, m) @@ -785,7 +803,7 @@ def _print_latex_(self, u, m): """ EXAMPLES:: - sage: latex(elliptic_eu(1,x)) + sage: latex(elliptic_eu(1, x)) # needs sage.symbolic E(1;x) """ return r"E(%s;%s)" % (latex(u), latex(m)) @@ -801,13 +819,10 @@ def elliptic_eu_f(u, m): EXAMPLES:: sage: from sage.functions.special import elliptic_eu_f - sage: elliptic_eu_f(0.5, 0.1) + sage: elliptic_eu_f(0.5, 0.1) # needs mpmath mpf('0.49605455128659691') """ - from mpmath import mp - from sage.functions.jacobi import jacobi_am_f - - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: u = ctx.convert(u) @@ -834,12 +849,12 @@ class EllipticF(BuiltinFunction): EXAMPLES:: - sage: z = var("z") - sage: elliptic_f (z, 0) + sage: z = var("z") # needs sage.symbolic + sage: elliptic_f(z, 0) # needs sage.symbolic z - sage: elliptic_f (z, 1).simplify() + sage: elliptic_f(z, 1).simplify() # needs sage.symbolic log(tan(1/4*pi + 1/2*z)) - sage: elliptic_f (0.2, 0.1) + sage: elliptic_f(0.2, 0.1) # needs mpmath 0.200132506747543 .. SEEALSO:: @@ -856,27 +871,28 @@ def __init__(self): sage: loads(dumps(elliptic_f)) elliptic_f - sage: elliptic_f(x, 2)._sympy_() + sage: elliptic_f(x, 2)._sympy_() # needs sympy sage.symbolic elliptic_f(x, 2) Check that :trac:`34186` is fixed:: - sage: _ = var("x y") - sage: fricas(elliptic_f(x, y)) # optional - fricas + sage: _ = var("x y") # needs sage.symbolic + sage: fricas(elliptic_f(x, y)) # optional - fricas, needs sage.symbolic ellipticF(sin(x),y) However, the conversion is only correct in the interval `[-\pi/2, \pi/2]`:: - sage: fricas(elliptic_f(x, y)).D(x).sage()/elliptic_f(x, y).diff(x) # optional - fricas + sage: fricas(elliptic_f(x, y)).D(x).sage()/elliptic_f(x, y).diff(x) # optional - fricas, needs sage.symbolic cos(x)/sqrt(-sin(x)^2 + 1) Numerically:: - sage: f = lambda x, y: elliptic_f(arcsin(x), y).subs(x=x, y=y) # optional - fricas - sage: g = lambda x, y: fricas.ellipticF(x, y).sage() # optional - fricas - sage: d = lambda x, y: f(x, y) - g(x, y) # optional - fricas - sage: [d(N(-pi/2+x), y) for x in range(1, 3) for y in range(-2,2)] # optional - fricas tol 1e-8 + sage: f = lambda x, y: elliptic_f(arcsin(x), y).subs(x=x, y=y) + sage: g = lambda x, y: fricas.ellipticF(x, y).sage() + sage: d = lambda x, y: f(x, y) - g(x, y) + sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic + ....: for x in range(1, 3) for y in range(-2,2)] [0.000000000000000, 0.000000000000000, 0.000000000000000, @@ -897,13 +913,14 @@ def _eval_(self, z, m): """ EXAMPLES:: - sage: elliptic_f(x,1) + sage: # needs sage.symbolic + sage: elliptic_f(x, 1) elliptic_f(x, 1) - sage: elliptic_f(x,0) + sage: elliptic_f(x, 0) x - sage: elliptic_f(0,1) + sage: elliptic_f(0, 1) 0 - sage: elliptic_f(pi/2,x) + sage: elliptic_f(pi/2, x) elliptic_kc(x) """ if m == 0: @@ -917,25 +934,24 @@ def _evalf_(self, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_f(1,1).n() + sage: elliptic_f(1, 1).n() # needs sage.symbolic 1.22619117088352 - sage: elliptic_f(1,1).n(200) + sage: elliptic_f(1, 1).n(200) # needs sage.symbolic 1.22619117088351707081306096... - sage: elliptic_f(I,I).n() + sage: elliptic_f(I, I).n() # needs sage.symbolic 0.149965060031782 + 0.925097284105771*I """ - R = parent or parent(z) - from mpmath import ellipf - return mpmath_utils.call(ellipf, z, m, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellipf, z, m, parent=R) def _derivative_(self, z, m, diff_param): """ EXAMPLES:: - sage: x,m = var('x,m') - sage: elliptic_f(x,m).diff(x) + sage: x, m = var('x,m') # needs sage.symbolic + sage: elliptic_f(x, m).diff(x) # needs sage.symbolic 1/sqrt(-m*sin(x)^2 + 1) - sage: elliptic_f(x,m).diff(m) + sage: elliptic_f(x, m).diff(m) # needs sage.symbolic -1/2*elliptic_f(x, m)/m + 1/4*sin(2*x)/(sqrt(-m*sin(x)^2 + 1)*(m - 1)) - 1/2*elliptic_e(x, m)/((m - 1)*m) @@ -953,7 +969,7 @@ def _print_latex_(self, z, m): r""" EXAMPLES:: - sage: latex(elliptic_f(x,pi)) + sage: latex(elliptic_f(x, pi)) # needs sage.symbolic F(x\,|\,\pi) """ return r"F(%s\,|\,%s)" % (latex(z), latex(m)) @@ -972,7 +988,7 @@ class EllipticKC(BuiltinFunction): EXAMPLES:: - sage: elliptic_kc(0.5) + sage: elliptic_kc(0.5) # needs mpmath 1.85407467730137 .. SEEALSO:: @@ -993,17 +1009,17 @@ def __init__(self): sage: loads(dumps(elliptic_kc)) elliptic_kc - sage: elliptic_kc(x)._sympy_() + sage: elliptic_kc(x)._sympy_() # needs sage.symbolic elliptic_k(x) TESTS:: - sage: fricas(elliptic_kc(x)) # optional - fricas + sage: fricas(elliptic_kc(x)) # optional - fricas, needs sage.symbolic ellipticK(x) - sage: elliptic_kc(0.3) # abs tol 1e-8 + sage: elliptic_kc(0.3) # abs tol 1e-8 # needs mpmath 1.71388944817879 - sage: fricas.ellipticK(0.3).sage() # abs tol 1e-3 # optional - fricas + sage: fricas.ellipticK(0.3).sage() # abs tol 1e-3 # optional - fricas, needs sage.symbolic 1.7138894481787910555457043 """ BuiltinFunction.__init__(self, 'elliptic_kc', nargs=1, latex_name='K', @@ -1016,9 +1032,9 @@ def _eval_(self, z): """ EXAMPLES:: - sage: elliptic_kc(0) + sage: elliptic_kc(0) # needs sage.symbolic 1/2*pi - sage: elliptic_kc(1/2) + sage: elliptic_kc(1/2) # needs sage.symbolic elliptic_kc(1/2) TESTS: @@ -1026,10 +1042,10 @@ def _eval_(self, z): Check if complex numbers in the arguments are converted to maxima correctly (see :trac:`7557`):: - sage: t = jacobi_sn(1.2+2*I*elliptic_kc(1-.5),.5) - sage: maxima(t) # abs tol 1e-13 + sage: t = jacobi_sn(1.2 + 2*I*elliptic_kc(1 - .5), .5) # needs sage.symbolic + sage: maxima(t) # abs tol 1e-13 # needs sage.symbolic 0.88771548861928029 - 1.7301614091485560e-15*%i - sage: t.n() # abs tol 1e-13 + sage: t.n() # abs tol 1e-13 # needs sage.symbolic 0.887715488619280 - 1.73016140914856e-15*I """ if z == 0: @@ -1041,22 +1057,21 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_kc(1/2).n() + sage: elliptic_kc(1/2).n() # needs sage.symbolic 1.85407467730137 - sage: elliptic_kc(1/2).n(200) + sage: elliptic_kc(1/2).n(200) # needs sage.symbolic 1.85407467730137191843385034... - sage: elliptic_kc(I).n() + sage: elliptic_kc(I).n() # needs sage.symbolic 1.42127228104504 + 0.295380284214777*I """ - R = parent or parent(z) - from mpmath import ellipk - return mpmath_utils.call(ellipk, z, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellipk, z, parent=R) def _derivative_(self, z, diff_param): """ EXAMPLES:: - sage: elliptic_kc(x).diff(x) + sage: elliptic_kc(x).diff(x) # needs sage.symbolic -1/2*((x - 1)*elliptic_kc(x) + elliptic_ec(x))/((x - 1)*x) """ @@ -1085,15 +1100,15 @@ class EllipticPi(BuiltinFunction): EXAMPLES:: - sage: N(elliptic_pi(1, pi/4, 1)) + sage: N(elliptic_pi(1, pi/4, 1)) # needs sage.symbolic 1.14779357469632 Compare the value computed by Maxima to the definition as a definite integral (using GSL):: - sage: elliptic_pi(0.1, 0.2, 0.3) + sage: elliptic_pi(0.1, 0.2, 0.3) # needs mpmath 0.200665068220979 - sage: numerical_integral(1/(1-0.1*sin(x)^2)/sqrt(1-0.3*sin(x)^2), 0.0, 0.2) + sage: numerical_integral(1/(1-0.1*sin(x)^2)/sqrt(1-0.3*sin(x)^2), 0.0, 0.2) # needs sage.symbolic (0.2006650682209791, 2.227829789769088e-15) REFERENCES: @@ -1106,7 +1121,7 @@ def __init__(self): sage: loads(dumps(elliptic_pi)) elliptic_pi - sage: elliptic_pi(x, pi/4, 1)._sympy_() + sage: elliptic_pi(x, pi/4, 1)._sympy_() # needs sympy sage.symbolic elliptic_pi(x, pi/4, 1) """ BuiltinFunction.__init__(self, 'elliptic_pi', nargs=3, @@ -1119,9 +1134,9 @@ def _eval_(self, n, z, m): """ EXAMPLES:: - sage: elliptic_pi(x,x,pi) + sage: elliptic_pi(x, x, pi) # needs sympy sage.symbolic elliptic_pi(x, x, pi) - sage: elliptic_pi(0,x,pi) + sage: elliptic_pi(0, x, pi) # needs sympy sage.symbolic elliptic_f(x, pi) """ if n == 0: @@ -1131,32 +1146,33 @@ def _evalf_(self, n, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_pi(pi,1/2,1).n() + sage: # needs sage.symbolic + sage: elliptic_pi(pi, 1/2, 1).n() 0.795062820631931 - sage: elliptic_pi(pi,1/2,1).n(200) + sage: elliptic_pi(pi, 1/2, 1).n(200) 0.79506282063193125292514098445... - sage: elliptic_pi(pi,1,1).n() + sage: elliptic_pi(pi, 1, 1).n() 0.0991592574231369 - 1.30004368185937*I - sage: elliptic_pi(pi,I,I).n() + sage: elliptic_pi(pi, I, I).n() 0.0542471560940594 + 0.552096453413081*I """ - R = parent or parent(z) - from mpmath import ellippi - return mpmath_utils.call(ellippi, n, z, m, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellippi, n, z, m, parent=R) def _derivative_(self, n, z, m, diff_param): """ EXAMPLES:: - sage: n,z,m = var('n,z,m') - sage: elliptic_pi(n,z,m).diff(n) + sage: # needs sage.symbolic + sage: n, z, m = var('n,z,m') + sage: elliptic_pi(n, z, m).diff(n) 1/4*(sqrt(-m*sin(z)^2 + 1)*n*sin(2*z)/(n*sin(z)^2 - 1) + 2*(m - n)*elliptic_f(z, m)/n + 2*(n^2 - m)*elliptic_pi(n, z, m)/n + 2*elliptic_e(z, m))/((m - n)*(n - 1)) - sage: elliptic_pi(n,z,m).diff(z) + sage: elliptic_pi(n, z, m).diff(z) -1/(sqrt(-m*sin(z)^2 + 1)*(n*sin(z)^2 - 1)) - sage: elliptic_pi(n,z,m).diff(m) + sage: elliptic_pi(n, z, m).diff(m) 1/4*(m*sin(2*z)/(sqrt(-m*sin(z)^2 + 1)*(m - 1)) - 2*elliptic_e(z, m)/(m - 1) - 2*elliptic_pi(n, z, m))/(m - n) @@ -1183,7 +1199,7 @@ def _print_latex_(self, n, z, m): r""" EXAMPLES:: - sage: latex(elliptic_pi(x,pi,0)) + sage: latex(elliptic_pi(x, pi, 0)) # needs sage.symbolic \Pi(x,\pi,0) """ return r"\Pi(%s,%s,%s)" % (latex(n), latex(z), latex(m)) diff --git a/src/sage/functions/spike_function.py b/src/sage/functions/spike_function.py index 83fde81b0ca..4739ca7ffb4 100644 --- a/src/sage/functions/spike_function.py +++ b/src/sage/functions/spike_function.py @@ -20,10 +20,11 @@ import math from sage.misc.lazy_import import lazy_import -lazy_import("sage.plot.all", "line") -from sage.modules.free_module_element import vector from sage.rings.real_double import RDF +lazy_import('sage.modules.free_module_element', 'vector') +lazy_import('sage.plot.all', 'line') + class SpikeFunction: """ @@ -31,9 +32,9 @@ class SpikeFunction: INPUT: - - ``v`` - list of pairs (x, height) + - ``v`` -- list of pairs (x, height) - - ``eps`` - parameter that determines approximation to a true spike + - ``eps`` -- parameter that determines approximation to a true spike OUTPUT: @@ -41,12 +42,12 @@ class SpikeFunction: EXAMPLES:: - sage: spike_function([(-3,4),(-1,1),(2,3)],0.001) + sage: spike_function([(-3,4), (-1,1), (2,3)], 0.001) A spike function with spikes at [-3.0, -1.0, 2.0] Putting the spikes too close together may delete some:: - sage: spike_function([(1,1),(1.01,4)],0.1) + sage: spike_function([(1,1), (1.01,4)], 0.1) Some overlapping spikes have been deleted. You might want to use a smaller value for eps. A spike function with spikes at [1.0] @@ -55,10 +56,9 @@ class SpikeFunction: ``spike_function``, but one can use it directly:: sage: from sage.functions.spike_function import SpikeFunction - sage: S = SpikeFunction([(0,1),(1,2),(pi,-5)]) - sage: S + sage: S = SpikeFunction([(0,1), (1,2), (pi,-5)]); S # needs sage.symbolic A spike function with spikes at [0.0, 1.0, 3.141592653589793] - sage: S.support + sage: S.support # needs sage.symbolic [0.0, 1.0, 3.141592653589793] """ def __init__(self, v, eps=0.0000001): @@ -67,7 +67,7 @@ def __init__(self, v, eps=0.0000001): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)],0.001); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)], 0.001); S A spike function with spikes at [-3.0, -1.0, 2.0] sage: S.height [4.0, 1.0, 3.0] @@ -99,7 +99,7 @@ def __repr__(self): EXAMPLES:: - sage: spike_function([(-3,4),(-1,1),(2,3)],0.001) + sage: spike_function([(-3,4), (-1,1), (2,3)], 0.001) A spike function with spikes at [-3.0, -1.0, 2.0] """ return "A spike function with spikes at %s" % self.support @@ -113,7 +113,7 @@ def _eval(self, x): EXAMPLES:: - sage: S = spike_function([(0,5)],eps=.001) + sage: S = spike_function([(0,5)], eps=.001) sage: S(0) 5.0 sage: S(.1) @@ -156,10 +156,10 @@ def plot_fft_abs(self, samples=2**12, xmin=None, xmax=None, **kwds): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)]); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)]); S A spike function with spikes at [-3.0, -1.0, 2.0] - sage: P = S.plot_fft_abs(8) - sage: p = P[0]; p.ydata # abs tol 1e-8 + sage: P = S.plot_fft_abs(8) # needs sage.plot + sage: p = P[0]; p.ydata # abs tol 1e-8 # needs sage.plot [5.0, 5.0, 3.367958691924177, 3.367958691924177, 4.123105625617661, 4.123105625617661, 4.759921664218055, 4.759921664218055] """ @@ -175,10 +175,10 @@ def plot_fft_arg(self, samples=2**12, xmin=None, xmax=None, **kwds): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)]); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)]); S A spike function with spikes at [-3.0, -1.0, 2.0] - sage: P = S.plot_fft_arg(8) - sage: p = P[0]; p.ydata # abs tol 1e-8 + sage: P = S.plot_fft_arg(8) # needs sage.plot + sage: p = P[0]; p.ydata # abs tol 1e-8 # needs sage.plot [0.0, 0.0, -0.211524990023434, -0.211524990023434, 0.244978663126864, 0.244978663126864, -0.149106180027477, -0.149106180027477] @@ -194,9 +194,9 @@ def vector(self, samples=2**16, xmin=None, xmax=None): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)],0.001); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)],0.001); S A spike function with spikes at [-3.0, -1.0, 2.0] - sage: S.vector(16) + sage: S.vector(16) # needs sage.modules (4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) """ @@ -220,8 +220,8 @@ def _ranges(self, xmin, xmax): EXAMPLES:: - sage: S = spike_function([(-1,1),(1,40)]) - sage: S._ranges(None,None) + sage: S = spike_function([(-1,1), (1,40)]) + sage: S._ranges(None, None) (-1.0, 1.0) """ width = (self.support[-1] + self.support[0])/float(2) @@ -239,9 +239,9 @@ def plot(self, xmin=None, xmax=None, **kwds): EXAMPLES:: - sage: S = spike_function([(-1,1),(1,40)]) - sage: P = plot(S) - sage: P[0] + sage: S = spike_function([(-1,1), (1,40)]) + sage: P = plot(S) # needs sage.plot + sage: P[0] # needs sage.plot Line defined by 8 points """ v = [] diff --git a/src/sage/functions/transcendental.py b/src/sage/functions/transcendental.py index bafa3283990..d0a30362fdf 100644 --- a/src/sage/functions/transcendental.py +++ b/src/sage/functions/transcendental.py @@ -15,25 +15,26 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +import math import sys +from sage.misc.lazy_import import lazy_import from sage.misc.misc import increase_recursion_limit from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR -from sage.rings.real_double import RDF -from sage.rings.complex_mpfr import ComplexField, is_ComplexNumber -from sage.rings.cc import CC -from sage.rings.real_mpfr import (RealField, is_RealNumber) - from sage.symbolic.function import GinacFunction, BuiltinFunction -import sage.libs.mpmath.utils as mpmath_utils -from sage.combinat.combinat import bernoulli_polynomial +lazy_import('sage.functions.gamma', 'psi') +lazy_import('sage.functions.other', 'factorial') -from .gamma import psi -from .other import factorial +lazy_import('sage.combinat.combinat', 'bernoulli_polynomial') +lazy_import('sage.rings.cc', 'CC') +lazy_import('sage.rings.complex_mpfr', ['ComplexField', 'is_ComplexNumber']) +lazy_import('sage.rings.polynomial.polynomial_real_mpfr_dense', 'PolynomialRealDense') +lazy_import('sage.rings.real_double', 'RDF') +lazy_import('sage.rings.real_mpfr', ['RR', 'RealField', 'is_RealNumber']) -I = CC.gen(0) +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'zeta', as_='_mpmath_zeta') class Function_zeta(GinacFunction): @@ -45,21 +46,23 @@ def __init__(self): - ``s`` - real or complex number - If s is a real number the computation is done using the MPFR + If s is a real number, the computation is done using the MPFR library. When the input is not real, the computation is done using the PARI C library. EXAMPLES:: + sage: RR = RealField(200) # needs sage.rings.real_mpfr + sage: zeta(RR(2)) # needs sage.rings.real_mpfr + 1.6449340668482264364724151666460251892189499012067984377356 + + sage: # needs sage.symbolic sage: zeta(x) zeta(x) sage: zeta(2) 1/6*pi^2 sage: zeta(2.) 1.64493406684823 - sage: RR = RealField(200) - sage: zeta(RR(2)) - 1.6449340668482264364724151666460251892189499012067984377356 sage: zeta(I) zeta(I) sage: zeta(I).n() @@ -72,80 +75,81 @@ def __init__(self): It is possible to use the ``hold`` argument to prevent automatic evaluation:: - sage: zeta(2,hold=True) + sage: zeta(2, hold=True) # needs sage.symbolic zeta(2) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = zeta(2,hold=True); a.simplify() + sage: a = zeta(2, hold=True); a.simplify() # needs sage.symbolic 1/6*pi^2 The Laurent expansion of `\zeta(s)` at `s=1` is implemented by means of the :wikipedia:`Stieltjes constants `:: - sage: s = SR('s') - sage: zeta(s).series(s==1, 2) + sage: s = SR('s') # needs sage.symbolic + sage: zeta(s).series(s==1, 2) # needs sage.symbolic 1*(s - 1)^(-1) + euler_gamma + (-stieltjes(1))*(s - 1) + Order((s - 1)^2) Generally, the Stieltjes constants occur in the Laurent expansion of `\zeta`-type singularities:: - sage: zeta(2*s/(s+1)).series(s==1, 2) + sage: zeta(2*s/(s+1)).series(s==1, 2) # needs sage.symbolic 2*(s - 1)^(-1) + (euler_gamma + 1) + (-1/2*stieltjes(1))*(s - 1) + Order((s - 1)^2) TESTS:: + sage: # needs sage.symbolic sage: latex(zeta(x)) \zeta(x) sage: a = loads(dumps(zeta(x))) sage: a.operator() == zeta True - sage: zeta(x)._sympy_() + sage: zeta(x)._sympy_() # needs sympy zeta(x) - sage: zeta(1) + sage: zeta(1) # needs sage.symbolic Infinity - sage: zeta(x).subs(x=1) + sage: zeta(x).subs(x=1) # needs sage.symbolic Infinity Check that :trac:`19799` is resolved:: - sage: zeta(pi) + sage: zeta(pi) # needs sage.symbolic zeta(pi) - sage: zeta(pi).n() # rel tol 1e-10 + sage: zeta(pi).n() # rel tol 1e-10 # needs sage.symbolic 1.17624173838258 Check that :trac:`20082` is fixed:: - sage: zeta(x).series(x==pi, 2) + sage: zeta(x).series(x==pi, 2) # needs sage.symbolic (zeta(pi)) + (zetaderiv(1, pi))*(-pi + x) + Order((pi - x)^2) - sage: (zeta(x) * 1/(1 - exp(-x))).residue(x==2*pi*I) + sage: (zeta(x) * 1/(1 - exp(-x))).residue(x==2*pi*I) # needs sage.symbolic zeta(2*I*pi) Check that :trac:`20102` is fixed:: - sage: (zeta(x)^2).series(x==1, 1) + sage: (zeta(x)^2).series(x==1, 1) # needs sage.symbolic 1*(x - 1)^(-2) + (2*euler_gamma)*(x - 1)^(-1) + (euler_gamma^2 - 2*stieltjes(1)) + Order(x - 1) - sage: (zeta(x)^4).residue(x==1) + sage: (zeta(x)^4).residue(x==1) # needs sage.symbolic 4/3*euler_gamma*(3*euler_gamma^2 - 2*stieltjes(1)) - 28/3*euler_gamma*stieltjes(1) + 2*stieltjes(2) Check that the right infinities are returned (:trac:`19439`):: - sage: zeta(1.0) + sage: zeta(1.0) # needs sage.symbolic +infinity - sage: zeta(SR(1.0)) + sage: zeta(SR(1.0)) # needs sage.symbolic Infinity Fixed conversion:: - sage: zeta(3)._maple_init_() + sage: zeta(3)._maple_init_() # needs sage.symbolic 'Zeta(3)' - sage: zeta(3)._maple_().sage() # optional - maple + sage: zeta(3)._maple_().sage() # optional - maple # needs sage.symbolic zeta(3) """ GinacFunction.__init__(self, 'zeta', @@ -173,6 +177,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: _ = var('n') sage: stieltjes(n) stieltjes(n) @@ -184,25 +189,26 @@ def __init__(self): stieltjes(2) sage: stieltjes(2).n(100) -0.0096903631928723184845303860352 - sage: RR = RealField(200) - sage: stieltjes(RR(2)) + sage: RR = RealField(200) # needs sage.rings.real_mpfr + sage: stieltjes(RR(2)) # needs sage.rings.real_mpfr -0.0096903631928723184845303860352125293590658061013407498807014 It is possible to use the ``hold`` argument to prevent automatic evaluation:: - sage: stieltjes(0,hold=True) + sage: stieltjes(0, hold=True) # needs sage.symbolic stieltjes(0) + sage: # needs sage.symbolic sage: latex(stieltjes(n)) \gamma_{n} sage: a = loads(dumps(stieltjes(n))) sage: a.operator() == stieltjes True - sage: stieltjes(x)._sympy_() + sage: stieltjes(x)._sympy_() # needs sympy stieltjes(x) - sage: stieltjes(x).subs(x==0) + sage: stieltjes(x).subs(x==0) # needs sage.symbolic euler_gamma """ GinacFunction.__init__(self, "stieltjes", nargs=1, @@ -219,9 +225,9 @@ def __init__(self): r""" TESTS:: - sage: latex(hurwitz_zeta(x, 2)) + sage: latex(hurwitz_zeta(x, 2)) # needs sage.symbolic \zeta\left(x, 2\right) - sage: hurwitz_zeta(x, 2)._sympy_() + sage: hurwitz_zeta(x, 2)._sympy_() # needs sympy sage.symbolic zeta(x, 2) """ BuiltinFunction.__init__(self, 'hurwitz_zeta', nargs=2, @@ -233,16 +239,18 @@ def _eval_(self, s, x): r""" TESTS:: + sage: # needs sage.symbolic sage: hurwitz_zeta(x, 1) zeta(x) sage: hurwitz_zeta(4, 3) 1/90*pi^4 - 17/16 sage: hurwitz_zeta(-4, x) -1/5*x^5 + 1/2*x^4 - 1/3*x^3 + 1/30*x - sage: hurwitz_zeta(3, 0.5) - 8.41439832211716 sage: hurwitz_zeta(0, x) -x + 1/2 + + sage: hurwitz_zeta(3, 0.5) # needs mpmath + 8.41439832211716 """ if x == 1: return zeta(s) @@ -257,22 +265,21 @@ def _evalf_(self, s, x, parent=None, algorithm=None): r""" TESTS:: - sage: hurwitz_zeta(11/10, 1/2).n() + sage: hurwitz_zeta(11/10, 1/2).n() # needs sage.symbolic 12.1038134956837 - sage: hurwitz_zeta(11/10, 1/2).n(100) + sage: hurwitz_zeta(11/10, 1/2).n(100) # needs sage.symbolic 12.103813495683755105709077413 sage: hurwitz_zeta(11/10, 1 + 1j).n() 9.85014164287853 - 1.06139499403981*I """ - from mpmath import zeta - return mpmath_utils.call(zeta, s, x, parent=parent) + return _mpmath_utils_call(_mpmath_zeta, s, x, parent=parent) def _derivative_(self, s, x, diff_param): r""" TESTS:: - sage: y = var('y') - sage: diff(hurwitz_zeta(x, y), y) + sage: y = var('y') # needs sage.symbolic + sage: diff(hurwitz_zeta(x, y), y) # needs sage.symbolic -x*hurwitz_zeta(x + 1, y) """ if diff_param == 1: @@ -305,6 +312,7 @@ def hurwitz_zeta(s, x, **kwargs): Symbolic evaluations:: + sage: # needs sage.symbolic sage: hurwitz_zeta(x, 1) zeta(x) sage: hurwitz_zeta(4, 3) @@ -318,13 +326,13 @@ def hurwitz_zeta(s, x, **kwargs): Numerical evaluations:: - sage: hurwitz_zeta(3, 1/2).n() + sage: hurwitz_zeta(3, 1/2).n() # needs mpmath 8.41439832211716 - sage: hurwitz_zeta(11/10, 1/2).n() + sage: hurwitz_zeta(11/10, 1/2).n() # needs sage.symbolic 12.1038134956837 - sage: hurwitz_zeta(3, x).series(x, 60).subs(x=0.5).n() + sage: hurwitz_zeta(3, x).series(x, 60).subs(x=0.5).n() # needs sage.symbolic 8.41439832211716 - sage: hurwitz_zeta(3, 0.5) + sage: hurwitz_zeta(3, 0.5) # needs mpmath 8.41439832211716 REFERENCES: @@ -341,31 +349,32 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: zetaderiv(1, x) zetaderiv(1, x) sage: zetaderiv(1, x).diff(x) zetaderiv(2, x) sage: var('n') n - sage: zetaderiv(n,x) + sage: zetaderiv(n, x) zetaderiv(n, x) sage: zetaderiv(1, 4).n() -0.0689112658961254 - sage: import mpmath; mpmath.diff(lambda x: mpmath.zeta(x), 4) + sage: import mpmath; mpmath.diff(lambda x: mpmath.zeta(x), 4) # needs mpmath mpf('-0.068911265896125382') TESTS:: - sage: latex(zetaderiv(2,x)) + sage: latex(zetaderiv(2, x)) # needs sage.symbolic \zeta^\prime\left(2, x\right) - sage: a = loads(dumps(zetaderiv(2,x))) - sage: a.operator() == zetaderiv + sage: a = loads(dumps(zetaderiv(2, x))) # needs sage.symbolic + sage: a.operator() == zetaderiv # needs sage.symbolic True - sage: b = RBF(3/2, 1e-10) - sage: zetaderiv(1, b, hold=True) + sage: b = RBF(3/2, 1e-10) # needs sage.libs.flint + sage: zetaderiv(1, b, hold=True) # needs sage.libs.flint sage.symbolic zetaderiv(1, [1.500000000 +/- 1.01e-10]) - sage: zetaderiv(b, 1) + sage: zetaderiv(b, 1) # needs sage.libs.flint sage.symbolic zetaderiv([1.500000000 +/- 1.01e-10], 1) """ GinacFunction.__init__(self, "zetaderiv", nargs=2, @@ -375,19 +384,18 @@ def _evalf_(self, n, x, parent=None, algorithm=None): r""" TESTS:: - sage: zetaderiv(0, 3, hold=True).n() == zeta(3).n() + sage: zetaderiv(0, 3, hold=True).n() == zeta(3).n() # needs sage.symbolic True - sage: zetaderiv(2, 3 + I).n() + sage: zetaderiv(2, 3 + I).n() # needs sage.symbolic 0.0213814086193841 - 0.174938812330834*I """ - from mpmath import zeta - return mpmath_utils.call(zeta, x, 1, n, parent=parent) + return _mpmath_utils_call(_mpmath_zeta, x, 1, n, parent=parent) def _method_arguments(self, k, x, **args): r""" TESTS:: - sage: zetaderiv(1, RBF(3/2, 0.0001)) + sage: zetaderiv(1, RBF(3/2, 0.0001)) # needs sage.libs.flint [-3.93 +/- ...e-3] """ return [x, k] @@ -422,13 +430,16 @@ def zeta_symmetric(s): EXAMPLES:: - sage: zeta_symmetric(0.7) - 0.497580414651127 - sage: zeta_symmetric(1-0.7) - 0.497580414651127 + sage: # needs sage.rings.real_mpfr sage: RR = RealField(200) sage: zeta_symmetric(RR(0.7)) 0.49758041465112690357779107525638385212657443284080589766062 + + sage: # needs sage.libs.pari sage.rings.real_mpfr + sage: zeta_symmetric(0.7) + 0.497580414651127 + sage: zeta_symmetric(1 - 0.7) + 0.497580414651127 sage: C. = ComplexField() sage: zeta_symmetric(0.5 + i*14.0) 0.000201294444235258 + 1.49077798716757e-19*I @@ -452,10 +463,6 @@ def zeta_symmetric(s): return (s/2 + 1).gamma() * (s-1) * (R.pi()**(-s/2)) * s.zeta() -import math -from sage.rings.polynomial.polynomial_real_mpfr_dense import PolynomialRealDense - - class DickmanRho(BuiltinFunction): r""" Dickman's function is the continuous function satisfying the @@ -490,13 +497,14 @@ class DickmanRho(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: dickman_rho(2) 0.306852819440055 sage: dickman_rho(10) 2.77017183772596e-11 sage: dickman_rho(10.00000000000000000000000000000000000000) 2.77017183772595898875812120063434232634e-11 - sage: plot(log(dickman_rho(x)), (x, 0, 15)) + sage: plot(log(dickman_rho(x)), (x, 0, 15)) # needs sage.plot Graphics object consisting of 1 graphics primitive AUTHORS: @@ -515,11 +523,11 @@ def __init__(self): TESTS:: - sage: dickman_rho(x) + sage: dickman_rho(x) # needs sage.symbolic dickman_rho(x) - sage: dickman_rho(3) + sage: dickman_rho(3) # needs sage.symbolic 0.0486083882911316 - sage: dickman_rho(pi) + sage: dickman_rho(pi) # needs sage.symbolic 0.0359690758968463 """ self._cur_prec = 0 @@ -529,9 +537,12 @@ def _eval_(self, x): """ EXAMPLES:: - sage: [dickman_rho(n) for n in [1..10]] - [1.00000000000000, 0.306852819440055, 0.0486083882911316, 0.00491092564776083, 0.000354724700456040, 0.0000196496963539553, 8.74566995329392e-7, 3.23206930422610e-8, 1.01624828273784e-9, 2.77017183772596e-11] - sage: dickman_rho(0) + sage: [dickman_rho(n) for n in [1..10]] # needs sage.symbolic + [1.00000000000000, 0.306852819440055, 0.0486083882911316, + 0.00491092564776083, 0.000354724700456040, 0.0000196496963539553, + 8.74566995329392e-7, 3.23206930422610e-8, 1.01624828273784e-9, + 2.77017183772596e-11] + sage: dickman_rho(0) # needs sage.symbolic 1.00000000000000 """ if not is_RealNumber(x): @@ -576,7 +587,7 @@ def power_series(self, n, abs_prec): -9.9376e-8*x^11 + 3.7722e-7*x^10 - 1.4684e-6*x^9 + 5.8783e-6*x^8 - 0.000024259*x^7 + 0.00010341*x^6 - 0.00045583*x^5 + 0.0020773*x^4 - 0.0097336*x^3 + 0.045224*x^2 - 0.11891*x + 0.13032 sage: f(-1), f(0), f(1) (0.30685, 0.13032, 0.048608) - sage: dickman_rho(2), dickman_rho(2.5), dickman_rho(3) + sage: dickman_rho(2), dickman_rho(2.5), dickman_rho(3) # needs sage.symbolic (0.306852819440055, 0.130319561832251, 0.0486083882911316) """ return self._compute_power_series(n, abs_prec, cache_ring=None) @@ -654,11 +665,11 @@ def approximate(self, x, parent=None): EXAMPLES:: - sage: dickman_rho.approximate(10) + sage: dickman_rho.approximate(10) # needs sage.rings.real_mpfr 2.41739196365564e-11 - sage: dickman_rho(10) + sage: dickman_rho(10) # needs sage.symbolic 2.77017183772596e-11 - sage: dickman_rho.approximate(1000) + sage: dickman_rho.approximate(1000) # needs sage.rings.real_mpfr 4.32938809066403e-3464 """ log, exp, sqrt, pi = math.log, math.exp, math.sqrt, math.pi diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py index 16aeeae43ab..62e5bd35b2e 100644 --- a/src/sage/functions/trig.py +++ b/src/sage/functions/trig.py @@ -1,9 +1,10 @@ r""" Trigonometric functions """ -from sage.symbolic.function import GinacFunction import math +from sage.symbolic.function import GinacFunction + class Function_sin(GinacFunction): def __init__(self): @@ -12,45 +13,48 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: sin(0) 0 sage: sin(x).subs(x==0) 0 sage: sin(2).n(100) 0.90929742682568169539601986591 - sage: loads(dumps(sin)) - sin - sage: sin(x)._sympy_() + sage: sin(x)._sympy_() # needs sympy sin(x) We can prevent evaluation using the ``hold`` parameter:: - sage: sin(0,hold=True) + sage: sin(0, hold=True) # needs sage.symbolic sin(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = sin(0,hold=True); a.simplify() + sage: a = sin(0, hold=True); a.simplify() # needs sage.symbolic 0 If possible, the argument is also reduced modulo the period length `2\pi`, and well-known identities are directly evaluated:: - sage: k = var('k', domain='integer') - sage: sin(1 + 2*k*pi) + sage: k = var('k', domain='integer') # needs sage.symbolic + sage: sin(1 + 2*k*pi) # needs sage.symbolic sin(1) - sage: sin(k*pi) + sage: sin(k*pi) # needs sage.symbolic 0 TESTS:: - sage: conjugate(sin(x)) + sage: loads(dumps(sin)) + sin + + sage: conjugate(sin(x)) # needs sage.symbolic sin(conjugate(x)) sage: sin(complex(1,1)) # rel tol 1e-15 (1.2984575814159773+0.6349639147847361j) + sage: # needs sage.symbolic sage: sin(pi/5) 1/4*sqrt(-2*sqrt(5) + 10) sage: sin(pi/8) @@ -94,27 +98,33 @@ def __init__(self): sage: csc(104*pi/105) csc(1/105*pi) - sage: all(sin(rat*pi).n(200)-sin(rat*pi,hold=True).n(200) < 1e-30 for rat in [1/5,2/5,1/30,7/30,11/30,13/30,1/8,3/8,1/24,5/24,7/24,11/24]) + sage: all(sin(rat*pi).n(200) - sin(rat*pi, hold=True).n(200) < 1e-30 # needs sage.symbolic + ....: for rat in [1/5, 2/5, 1/30, 7/30, 11/30, 13/30, + ....: 1/8, 3/8, 1/24, 5/24, 7/24, 11/24]) True - sage: all(cos(rat*pi).n(200)-cos(rat*pi,hold=True).n(200) < 1e-30 for rat in [1/10,3/10,1/12,5/12,1/15,2/15,4/15,7/15,1/8,3/8,1/24,5/24,11/24]) + sage: all(cos(rat*pi).n(200)-cos(rat*pi, hold=True).n(200) < 1e-30 # needs sage.symbolic + ....: for rat in [1/10, 3/10, 1/12, 5/12, 1/15, 2/15, 4/15, 7/15, + ....: 1/8, 3/8, 1/24, 5/24, 11/24]) True - sage: all(tan(rat*pi).n(200)-tan(rat*pi,hold=True).n(200) < 1e-30 for rat in [1/5,2/5,1/10,3/10,1/20,3/20,7/20,9/20,1/8,3/8,1/16,3/16,5/16,7/16,1/24,5/24,7/24,11/24]) + sage: all(tan(rat*pi).n(200)-tan(rat*pi, hold=True).n(200) < 1e-30 # needs sage.symbolic + ....: for rat in [1/5, 2/5, 1/10, 3/10, 1/20, 3/20, 7/20, 9/20, + ....: 1/8, 3/8, 1/16, 3/16, 5/16, 7/16, 1/24, 5/24, 7/24, 11/24]) True Check that :trac:`20456` is fixed:: - sage: assume(x>0) - sage: sin(pi*x) + sage: assume(x > 0) # needs sage.symbolic + sage: sin(pi*x) # needs sage.symbolic sin(pi*x) - sage: forget() + sage: forget() # needs sage.symbolic Check that :trac:`20752` is fixed:: - sage: sin(3*pi+41/42*pi) + sage: sin(3*pi + 41/42*pi) # needs sage.symbolic -sin(1/42*pi) - sage: sin(-5*pi+1/42*pi) + sage: sin(-5*pi + 1/42*pi) # needs sage.symbolic -sin(1/42*pi) - sage: sin(pi-1/42*pi) + sage: sin(pi - 1/42*pi) # needs sage.symbolic sin(1/42*pi) """ GinacFunction.__init__(self, 'sin', latex_name=r"\sin", @@ -132,32 +142,32 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: cos(pi) -1 sage: cos(x).subs(x==pi) -1 sage: cos(2).n(100) -0.41614683654714238699756822950 - sage: loads(dumps(cos)) - cos - sage: cos(x)._sympy_() + sage: cos(x)._sympy_() # needs sympy cos(x) We can prevent evaluation using the ``hold`` parameter:: - sage: cos(0,hold=True) + sage: cos(0, hold=True) # needs sage.symbolic cos(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = cos(0,hold=True); a.simplify() + sage: a = cos(0, hold=True); a.simplify() # needs sage.symbolic 1 If possible, the argument is also reduced modulo the period length `2\pi`, and well-known identities are directly evaluated:: + sage: # needs sage.symbolic sage: k = var('k', domain='integer') sage: cos(1 + 2*k*pi) cos(1) @@ -168,18 +178,21 @@ def __init__(self): TESTS:: - sage: conjugate(cos(x)) + sage: loads(dumps(cos)) + cos + + sage: conjugate(cos(x)) # needs sage.symbolic cos(conjugate(x)) sage: cos(complex(1,1)) # rel tol 1e-15 (0.8337300251311491-0.9888977057628651j) Check that :trac:`20752` is fixed:: - sage: cos(3*pi+41/42*pi) + sage: cos(3*pi + 41/42*pi) # needs sage.symbolic cos(1/42*pi) - sage: cos(-5*pi+1/42*pi) + sage: cos(-5*pi + 1/42*pi) # needs sage.symbolic -cos(1/42*pi) - sage: cos(pi-1/42*pi) + sage: cos(pi - 1/42*pi) # needs sage.symbolic -cos(1/42*pi) """ GinacFunction.__init__(self, 'cos', latex_name=r"\cos", @@ -197,12 +210,14 @@ def __init__(self): EXAMPLES:: - sage: tan(pi) - 0 sage: tan(3.1415) -0.0000926535900581913 sage: tan(3.1415/4) 0.999953674278156 + + sage: # needs sage.symbolic + sage: tan(pi) + 0 sage: tan(pi/4) 1 sage: tan(1/2) @@ -212,37 +227,37 @@ def __init__(self): We can prevent evaluation using the ``hold`` parameter:: - sage: tan(pi/4,hold=True) + sage: tan(pi/4, hold=True) # needs sage.symbolic tan(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = tan(pi/4,hold=True); a.simplify() + sage: a = tan(pi/4, hold=True); a.simplify() # needs sage.symbolic 1 If possible, the argument is also reduced modulo the period length `\pi`, and well-known identities are directly evaluated:: - sage: k = var('k', domain='integer') - sage: tan(1 + 2*k*pi) + sage: k = var('k', domain='integer') # needs sage.symbolic + sage: tan(1 + 2*k*pi) # needs sage.symbolic tan(1) - sage: tan(k*pi) + sage: tan(k*pi) # needs sage.symbolic 0 TESTS:: - sage: tan(x)._sympy_() + sage: tan(x)._sympy_() # needs sympy sage.symbolic tan(x) - sage: conjugate(tan(x)) + sage: conjugate(tan(x)) # needs sage.symbolic tan(conjugate(x)) sage: tan(complex(1,1)) # rel tol 1e-15 (0.2717525853195118+1.0839233273386946j) Check that :trac:`19791` is fixed:: - sage: tan(2+I).imag().n() + sage: tan(2+I).imag().n() # needs sage.symbolic 1.16673625724092 """ GinacFunction.__init__(self, 'tan', latex_name=r"\tan") @@ -258,6 +273,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: cot(pi/4) 1 sage: RR(cot(pi/4)) @@ -267,24 +283,25 @@ def __init__(self): sage: cot(0.5) 1.83048772171245 - sage: latex(cot(x)) + sage: latex(cot(x)) # needs sage.symbolic \cot\left(x\right) - sage: cot(x)._sympy_() + sage: cot(x)._sympy_() # needs sympy sage.symbolic cot(x) We can prevent evaluation using the ``hold`` parameter:: - sage: cot(pi/4,hold=True) + sage: cot(pi/4, hold=True) # needs sage.symbolic cot(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = cot(pi/4,hold=True); a.simplify() + sage: a = cot(pi/4, hold=True); a.simplify() # needs sage.symbolic 1 EXAMPLES:: + sage: # needs sage.symbolic sage: cot(pi/4) 1 sage: cot(x).subs(x==pi/4) @@ -294,7 +311,8 @@ def __init__(self): sage: cot(x) cot(x) - sage: n(cot(pi/4),100) + sage: # needs sage.symbolic + sage: n(cot(pi/4), 100) 1.0000000000000000000000000000 sage: float(cot(1)) 0.64209261593433... @@ -305,29 +323,29 @@ def __init__(self): TESTS:: - sage: cot(float(0)) + sage: cot(float(0)) # needs sage.symbolic Infinity - sage: cot(SR(0)) + sage: cot(SR(0)) # needs sage.symbolic Infinity - sage: cot(float(0.1)) + sage: cot(float(0.1)) # needs sage.symbolic 9.966644423259238 sage: type(_) <... 'float'> - sage: cot(float(0)) + sage: cot(float(0)) # needs sage.symbolic Infinity - sage: cot(SR(0)) + sage: cot(SR(0)) # needs sage.symbolic Infinity - sage: cot(float(0.1)) + sage: cot(float(0.1)) # needs sage.symbolic 9.966644423259238 sage: type(_) <... 'float'> Test complex input:: - sage: cot(complex(1,1)) # rel tol 1e-15 + sage: cot(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.21762156185440273-0.8680141428959249j) - sage: cot(1.+I) + sage: cot(1.+I) # needs sage.symbolic 0.217621561854403 - 0.868014142895925*I """ GinacFunction.__init__(self, 'cot', latex_name=r"\cot") @@ -336,9 +354,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: cot(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: cot(a) # needs numpy array([-0.45765755, -7.01525255, 0.86369115]) """ return 1.0 / tan(x) @@ -354,6 +372,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: sec(pi/4) sqrt(2) sage: sec(x).subs(x==pi/4) @@ -373,31 +392,32 @@ def __init__(self): sage: sec(0.5) 1.13949392732455 + sage: # needs sage.symbolic sage: bool(diff(sec(x), x) == diff(1/cos(x), x)) True sage: diff(sec(x), x) sec(x)*tan(x) sage: latex(sec(x)) \sec\left(x\right) - sage: sec(x)._sympy_() + sage: sec(x)._sympy_() # needs sympy sec(x) We can prevent evaluation using the ``hold`` parameter:: - sage: sec(pi/4,hold=True) + sage: sec(pi/4, hold=True) # needs sage.symbolic sec(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = sec(pi/4,hold=True); a.simplify() + sage: a = sec(pi/4, hold=True); a.simplify() # needs sage.symbolic sqrt(2) TESTS: Test complex input:: - sage: sec(complex(1,1)) # rel tol 1e-15 + sage: sec(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.49833703055518686+0.5910838417210451j) """ GinacFunction.__init__(self, 'sec', latex_name=r"\sec") @@ -406,9 +426,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: sec(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: sec(a) # needs numpy array([-2.40299796, -1.01010867, -1.52988566]) """ return 1 / cos(x) @@ -424,6 +444,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: csc(pi/4) sqrt(2) sage: csc(x).subs(x==pi/4) @@ -434,7 +455,7 @@ def __init__(self): csc(x) sage: RR(csc(pi/4)) 1.41421356237310 - sage: n(csc(pi/4),100) + sage: n(csc(pi/4), 100) 1.4142135623730950488016887242 sage: float(csc(pi/4)) 1.4142135623730951 @@ -443,31 +464,32 @@ def __init__(self): sage: csc(0.5) 2.08582964293349 + sage: # needs sage.symbolic sage: bool(diff(csc(x), x) == diff(1/sin(x), x)) True sage: diff(csc(x), x) -cot(x)*csc(x) sage: latex(csc(x)) \csc\left(x\right) - sage: csc(x)._sympy_() + sage: csc(x)._sympy_() # needs sympy csc(x) We can prevent evaluation using the ``hold`` parameter:: - sage: csc(pi/4,hold=True) + sage: csc(pi/4, hold=True) # needs sage.symbolic csc(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = csc(pi/4,hold=True); a.simplify() + sage: a = csc(pi/4,hold=True); a.simplify() # needs sage.symbolic sqrt(2) TESTS: Test complex input:: - sage: csc(complex(1,1)) # rel tol 1e-15 + sage: csc(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.6215180171704284-0.30393100162842646j) """ GinacFunction.__init__(self, 'csc', latex_name=r"\csc") @@ -476,9 +498,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: csc(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: csc(a) # needs numpy array([ 1.09975017, 7.0861674 , -1.32134871]) """ return 1 / sin(x) @@ -500,25 +522,26 @@ def __init__(self): sage: arcsin(0.5) 0.523598775598299 - sage: arcsin(1/2) + sage: arcsin(1/2) # needs sage.symbolic 1/6*pi - sage: arcsin(1 + 1.0*I) + sage: arcsin(1 + 1.0*I) # needs sage.symbolic 0.666239432492515 + 1.06127506190504*I We can delay evaluation using the ``hold`` parameter:: - sage: arcsin(0,hold=True) + sage: arcsin(0, hold=True) # needs sage.symbolic arcsin(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arcsin(0,hold=True); a.simplify() + sage: a = arcsin(0, hold=True); a.simplify() # needs sage.symbolic 0 ``conjugate(arcsin(x))==arcsin(conjugate(x))``, unless on the branch cuts which run along the real axis outside the interval [-1, +1].:: + sage: # needs sage.symbolic sage: conjugate(arcsin(x)) conjugate(arcsin(x)) sage: var('y', domain='positive') @@ -536,13 +559,13 @@ def __init__(self): TESTS:: - sage: arcsin(x)._sympy_() + sage: arcsin(x)._sympy_() # needs sympy sage.symbolic asin(x) - sage: arcsin(x).operator() + sage: arcsin(x).operator() # needs sage.symbolic arcsin - sage: asin(complex(1,1)) + sage: asin(complex(1,1)) # needs sage.rings.complex_double (0.6662394324925152+1.0612750619050357j) - sage: asin(SR(2.1)) + sage: asin(SR(2.1)) # needs sage.symbolic 1.57079632679490 - 1.37285914424258*I """ GinacFunction.__init__(self, 'arcsin', latex_name=r"\arcsin", @@ -563,27 +586,28 @@ def __init__(self): sage: arccos(0.5) 1.04719755119660 - sage: arccos(1/2) + sage: arccos(1/2) # needs sage.symbolic 1/3*pi - sage: arccos(1 + 1.0*I) + sage: arccos(1 + 1.0*I) # needs sage.symbolic 0.904556894302381 - 1.06127506190504*I - sage: arccos(3/4).n(100) + sage: arccos(3/4).n(100) # needs sage.symbolic 0.72273424781341561117837735264 We can delay evaluation using the ``hold`` parameter:: - sage: arccos(0,hold=True) + sage: arccos(0, hold=True) # needs sage.symbolic arccos(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arccos(0,hold=True); a.simplify() + sage: a = arccos(0, hold=True); a.simplify() # needs sage.symbolic 1/2*pi ``conjugate(arccos(x))==arccos(conjugate(x))``, unless on the branch cuts, which run along the real axis outside the interval [-1, +1].:: + sage: # needs sage.symbolic sage: conjugate(arccos(x)) conjugate(arccos(x)) sage: var('y', domain='positive') @@ -601,13 +625,13 @@ def __init__(self): TESTS:: - sage: arccos(x)._sympy_() + sage: arccos(x)._sympy_() # needs sympy sage.symbolic acos(x) - sage: arccos(x).operator() + sage: arccos(x).operator() # needs sage.symbolic arccos - sage: acos(complex(1,1)) + sage: acos(complex(1,1)) # needs sage.rings.complex_double (0.9045568943023814-1.0612750619050357j) - sage: acos(SR(2.1)) + sage: acos(SR(2.1)) # needs sage.symbolic 1.37285914424258*I """ GinacFunction.__init__(self, 'arccos', latex_name=r"\arccos", @@ -626,6 +650,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arctan(1/2) arctan(1/2) sage: RDF(arctan(1/2)) # rel tol 1e-15 @@ -637,18 +662,19 @@ def __init__(self): We can delay evaluation using the ``hold`` parameter:: - sage: arctan(0,hold=True) + sage: arctan(0, hold=True) # needs sage.symbolic arctan(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arctan(0,hold=True); a.simplify() + sage: a = arctan(0, hold=True); a.simplify() # needs sage.symbolic 0 ``conjugate(arctan(x))==arctan(conjugate(x))``, unless on the branch cuts which run along the imaginary axis outside the interval [-I, +I].:: + sage: # needs sage.symbolic sage: conjugate(arctan(x)) conjugate(arctan(x)) sage: var('y', domain='positive') @@ -668,18 +694,18 @@ def __init__(self): TESTS:: - sage: arctan(x)._sympy_() + sage: arctan(x)._sympy_() # needs sympy sage.symbolic atan(x) - sage: arctan(x).operator() + sage: arctan(x).operator() # needs sage.symbolic arctan - sage: atan(complex(1,1)) + sage: atan(complex(1,1)) # needs sage.rings.complex_double (1.0172219678978514+0.4023594781085251j) Check that :trac:`19918` is fixed:: - sage: arctan(-x).subs(x=oo) + sage: arctan(-x).subs(x=oo) # needs sage.symbolic -1/2*pi - sage: arctan(-x).subs(x=-oo) + sage: arctan(-x).subs(x=-oo) # needs sage.symbolic 1/2*pi """ GinacFunction.__init__(self, 'arctan', latex_name=r"\arctan", @@ -698,6 +724,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arccot(1/2) arccot(1/2) sage: RDF(arccot(1/2)) # abs tol 2e-16 @@ -715,24 +742,24 @@ def __init__(self): We can delay evaluation using the ``hold`` parameter:: - sage: arccot(1,hold=True) + sage: arccot(1, hold=True) # needs sage.symbolic arccot(1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arccot(1,hold=True); a.simplify() + sage: a = arccot(1, hold=True); a.simplify() # needs sage.symbolic 1/4*pi TESTS: Test complex input:: - sage: arccot(x)._sympy_() + sage: arccot(x)._sympy_() # needs sympy sage.symbolic acot(x) - sage: arccot(complex(1,1)) # rel tol 1e-15 + sage: arccot(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.5535743588970452-0.4023594781085251j) - sage: arccot(1.+I) + sage: arccot(1.+I) # needs sage.symbolic 0.553574358897045 - 0.402359478108525*I """ @@ -745,9 +772,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: arccot(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: arccot(a) # needs numpy array([0.46364761, 0.32175055, 0.24497866]) """ return math.pi / 2 - arctan(x) @@ -763,6 +790,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arccsc(2) arccsc(2) sage: RDF(arccsc(2)) # rel tol 1e-15 @@ -775,25 +803,25 @@ def __init__(self): arccsc(I + 1) sage: diff(acsc(x), x) -1/(sqrt(x^2 - 1)*x) - sage: arccsc(x)._sympy_() + sage: arccsc(x)._sympy_() # needs sympy acsc(x) We can delay evaluation using the ``hold`` parameter:: - sage: arccsc(1,hold=True) + sage: arccsc(1, hold=True) # needs sage.symbolic arccsc(1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arccsc(1,hold=True); a.simplify() + sage: a = arccsc(1, hold=True); a.simplify() # needs sage.symbolic 1/2*pi TESTS: Test complex input:: - sage: arccsc(complex(1,1)) # rel tol 1e-15 + sage: arccsc(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.45227844715119064-0.5306375309525178j) """ GinacFunction.__init__(self, 'arccsc', latex_name=r"\operatorname{arccsc}", @@ -805,9 +833,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: arccsc(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: arccsc(a) # needs numpy array([0.52359878, 0.33983691, 0.25268026]) """ return arcsin(1.0 / x) @@ -823,6 +851,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arcsec(2) arcsec(2) sage: arcsec(2.0) @@ -837,25 +866,25 @@ def __init__(self): arcsec(I + 1) sage: diff(asec(x), x) 1/(sqrt(x^2 - 1)*x) - sage: arcsec(x)._sympy_() + sage: arcsec(x)._sympy_() # needs sympy asec(x) We can delay evaluation using the ``hold`` parameter:: - sage: arcsec(1,hold=True) + sage: arcsec(1, hold=True) # needs sage.symbolic arcsec(1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arcsec(1,hold=True); a.simplify() + sage: a = arcsec(1, hold=True); a.simplify() # needs sage.symbolic 0 TESTS: Test complex input:: - sage: arcsec(complex(1,1)) # rel tol 1e-15 + sage: arcsec(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (1.118517879643706+0.5306375309525178j) """ GinacFunction.__init__(self, 'arcsec', latex_name=r"\operatorname{arcsec}", @@ -867,9 +896,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: arcsec(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: arcsec(a) # needs numpy array([1.04719755, 1.23095942, 1.31811607]) """ return arccos(1.0 / x) @@ -902,89 +931,91 @@ def __init__(self): Note the difference between the two functions:: - sage: arctan2(1,-1) + sage: arctan2(1, -1) # needs sage.symbolic 3/4*pi - sage: arctan(1/-1) + sage: arctan(1/-1) # needs sage.symbolic -1/4*pi This is consistent with Python and Maxima:: - sage: maxima.atan2(1,-1) + sage: maxima.atan2(1, -1) # needs sage.symbolic (3*%pi)/4 sage: math.atan2(1,-1) 2.356194490192345 More examples:: - sage: arctan2(1,0) + sage: arctan2(1, 0) # needs sage.symbolic 1/2*pi - sage: arctan2(2,3) + sage: arctan2(2, 3) # needs sage.symbolic arctan(2/3) - sage: arctan2(-1,-1) + sage: arctan2(-1, -1) # needs sage.symbolic -3/4*pi Of course we can approximate as well:: - sage: arctan2(-1/2,1).n(100) + sage: arctan2(-1/2, 1).n(100) # needs sage.symbolic -0.46364760900080611621425623146 - sage: arctan2(2,3).n(100) + sage: arctan2(2, 3).n(100) # needs sage.symbolic 0.58800260354756755124561108063 We can delay evaluation using the ``hold`` parameter:: - sage: arctan2(-1/2,1,hold=True) + sage: arctan2(-1/2, 1, hold=True) # needs sage.symbolic arctan2(-1/2, 1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: arctan2(-1/2,1,hold=True).simplify() + sage: arctan2(-1/2, 1, hold=True).simplify() # needs sage.symbolic -arctan(1/2) The function also works with numpy arrays as input:: + sage: # needs numpy sage: import numpy sage: a = numpy.linspace(1, 3, 3) sage: b = numpy.linspace(3, 6, 3) sage: atan2(a, b) array([0.32175055, 0.41822433, 0.46364761]) - sage: atan2(1,a) + sage: atan2(1,a) # needs numpy array([0.78539816, 0.46364761, 0.32175055]) - sage: atan2(a, 1) + sage: atan2(a, 1) # needs numpy array([0.78539816, 1.10714872, 1.24904577]) TESTS:: - sage: x,y = var('x,y') - sage: arctan2(y,x).operator() + sage: x,y = var('x,y') # needs sage.symbolic + sage: arctan2(y, x).operator() # needs sage.symbolic arctan2 Check if :trac:`8565` is fixed:: - sage: atan2(-pi,0) + sage: atan2(-pi, 0) # needs sage.symbolic -1/2*pi Check if :trac:`8564` is fixed:: - sage: arctan2(x,x)._sympy_() + sage: arctan2(x,x)._sympy_() # needs sympy sage.symbolic atan2(x, x) Check if numerical evaluation works :trac:`9913`:: - sage: arctan2(0, -log(2)).n() + sage: arctan2(0, -log(2)).n() # needs sage.symbolic 3.14159265358979 Check that atan2(0,0) returns NaN :trac:`21614`:: - sage: atan2(0,0) + sage: # needs sage.symbolic + sage: atan2(0, 0) NaN - sage: atan2(0,0).n() + sage: atan2(0, 0).n() NaN - sage: atan2(0,0,hold=True) + sage: atan2(0, 0, hold=True) arctan2(0, 0) - sage: atan2(0,0,hold=True).n() + sage: atan2(0, 0, hold=True).n() Traceback (most recent call last): ... RuntimeError: atan2(): division by zero @@ -992,7 +1023,7 @@ def __init__(self): Check if :trac:`10062` is fixed, this was caused by ``(I*I).is_positive()`` returning ``True``:: - sage: arctan2(0, I*I) + sage: arctan2(0, I*I) # needs sage.symbolic pi """ GinacFunction.__init__(self, 'arctan2', nargs=2, latex_name=r"\arctan", diff --git a/src/sage/functions/wigner.py b/src/sage/functions/wigner.py index 53d0b744f6a..af987c20084 100644 --- a/src/sage/functions/wigner.py +++ b/src/sage/functions/wigner.py @@ -23,10 +23,14 @@ # https://www.gnu.org/licenses/ # ********************************************************************** -from sage.rings.complex_mpfr import ComplexNumber +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.finite_rings.integer_mod import Mod -from sage.symbolic.constants import pi + +lazy_import('sage.rings.complex_mpfr', 'ComplexNumber') + +lazy_import('sage.symbolic.constants', 'pi') + # This list of precomputed factorials is needed to massively # accelerate future calculations of the various coefficients @@ -78,15 +82,15 @@ def wigner_3j(j_1, j_2, j_3, m_1, m_2, m_3, prec=None): EXAMPLES:: - sage: wigner_3j(2, 6, 4, 0, 0, 0) + sage: wigner_3j(2, 6, 4, 0, 0, 0) # needs sage.symbolic sqrt(5/143) sage: wigner_3j(2, 6, 4, 0, 0, 1) 0 - sage: wigner_3j(0.5, 0.5, 1, 0.5, -0.5, 0) + sage: wigner_3j(0.5, 0.5, 1, 0.5, -0.5, 0) # needs sage.symbolic sqrt(1/6) - sage: wigner_3j(40, 100, 60, -10, 60, -50) + sage: wigner_3j(40, 100, 60, -10, 60, -50) # needs sage.symbolic 95608/18702538494885*sqrt(21082735836735314343364163310/220491455010479533763) - sage: wigner_3j(2500, 2500, 5000, 2488, 2400, -4888, prec=64) + sage: wigner_3j(2500, 2500, 5000, 2488, 2400, -4888, prec=64) # needs sage.rings.real_mpfr 7.60424456883448589e-12 It is an error to have arguments that are not integer or half @@ -223,11 +227,11 @@ def clebsch_gordan(j_1, j_2, j_3, m_1, m_2, m_3, prec=None): EXAMPLES:: - sage: simplify(clebsch_gordan(3/2,1/2,2, 3/2,1/2,2)) + sage: simplify(clebsch_gordan(3/2,1/2,2, 3/2,1/2,2)) # needs sage.symbolic 1 - sage: clebsch_gordan(1.5,0.5,1, 1.5,-0.5,1) + sage: clebsch_gordan(1.5,0.5,1, 1.5,-0.5,1) # needs sage.symbolic 1/2*sqrt(3) - sage: clebsch_gordan(3/2,1/2,1, -1/2,1/2,0) + sage: clebsch_gordan(3/2,1/2,1, -1/2,1/2,0) # needs sage.symbolic -sqrt(3)*sqrt(1/6) .. NOTE:: @@ -275,7 +279,7 @@ def _big_delta_coeff(aa, bb, cc, prec=None): EXAMPLES:: sage: from sage.functions.wigner import _big_delta_coeff - sage: _big_delta_coeff(1,1,1) + sage: _big_delta_coeff(1,1,1) # needs sage.symbolic 1/2*sqrt(1/6) """ if int(aa + bb - cc) != (aa + bb - cc): @@ -325,7 +329,7 @@ def racah(aa, bb, cc, dd, ee, ff, prec=None): EXAMPLES:: - sage: racah(3,3,3,3,3,3) + sage: racah(3,3,3,3,3,3) # needs sage.symbolic -1/14 .. NOTE:: @@ -398,6 +402,7 @@ def wigner_6j(j_1, j_2, j_3, j_4, j_5, j_6, prec=None): EXAMPLES:: + sage: # needs sage.symbolic sage: wigner_6j(3,3,3,3,3,3) -1/14 sage: wigner_6j(5,5,5,5,5,5) @@ -497,23 +502,24 @@ def wigner_9j(j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9, prec=None): A couple of examples and test cases, note that for speed reasons a precision is given:: - sage: wigner_9j(1,1,1, 1,1,1, 1,1,0 ,prec=64) # ==1/18 + sage: # needs sage.symbolic + sage: wigner_9j(1,1,1, 1,1,1, 1,1,0, prec=64) # ==1/18 0.0555555555555555555 sage: wigner_9j(1,1,1, 1,1,1, 1,1,1) 0 - sage: wigner_9j(1,1,1, 1,1,1, 1,1,2 ,prec=64) # ==1/18 + sage: wigner_9j(1,1,1, 1,1,1, 1,1,2, prec=64) # ==1/18 0.0555555555555555556 - sage: wigner_9j(1,2,1, 2,2,2, 1,2,1 ,prec=64) # ==-1/150 + sage: wigner_9j(1,2,1, 2,2,2, 1,2,1, prec=64) # ==-1/150 -0.00666666666666666667 - sage: wigner_9j(3,3,2, 2,2,2, 3,3,2 ,prec=64) # ==157/14700 + sage: wigner_9j(3,3,2, 2,2,2, 3,3,2, prec=64) # ==157/14700 0.0106802721088435374 - sage: wigner_9j(3,3,2, 3,3,2, 3,3,2 ,prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) + sage: wigner_9j(3,3,2, 3,3,2, 3,3,2, prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) 0.00944247746651111739 - sage: wigner_9j(3,3,1, 3.5,3.5,2, 3.5,3.5,1 ,prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) + sage: wigner_9j(3,3,1, 3.5,3.5,2, 3.5,3.5,1, prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) 0.0110216678544351364 - sage: wigner_9j(100,80,50, 50,100,70, 60,50,100 ,prec=1000)*1.0 + sage: wigner_9j(100,80,50, 50,100,70, 60,50,100, prec=1000)*1.0 1.05597798065761e-7 - sage: wigner_9j(30,30,10, 30.5,30.5,20, 30.5,30.5,10 ,prec=1000)*1.0 # ==(80944680186359968990/95103769817469)*sqrt(1/682288158959699477295) + sage: wigner_9j(30,30,10, 30.5,30.5,20, 30.5,30.5,10, prec=1000)*1.0 # ==(80944680186359968990/95103769817469)*sqrt(1/682288158959699477295) 0.0000325841699408828 sage: wigner_9j(64,62.5,114.5, 61.5,61,112.5, 113.5,110.5,60, prec=1000)*1.0 -3.41407910055520e-39 @@ -529,7 +535,7 @@ def wigner_9j(j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9, prec=None): Traceback (most recent call last): ... ValueError: j values must be integer or half integer and fulfill the triangle relation - sage: wigner_9j(1,1,1, 0.5,1,1.5, 0.5,1,2.5,prec=64) + sage: wigner_9j(1,1,1, 0.5,1,1.5, 0.5,1,2.5,prec=64) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: j values must be integer or half integer and fulfill the triangle relation @@ -584,6 +590,7 @@ def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None): EXAMPLES:: + sage: # needs sage.symbolic sage: gaunt(1,0,1,1,0,-1) -1/2/sqrt(pi) sage: gaunt(1,0,1,1,0,0) diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index ee8962019ae..7174a80ece5 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -986,6 +986,177 @@ def poincare_polynomial(self): poincare = (-x)**self.dimension() * charpoly(-QQ(1)/x) return R(poincare) + @cached_method + def cocharacteristic_polynomial(self): + r""" + Return the cocharacteristic polynomial of ``self``. + + The cocharacteristic polynomial of a hyperplane arrangement `A` + is defined by + + .. MATH:: + + \Psi_A(z) := \sum_{X \in L} |\mu(B,X)| z^{\dim X}, + + where `L` is the intersection poset of `A`, `B` is the minimal + element of `L` (here, the `0` dimensional subspace), and + `\mu` is the Möbius function of `L`. + + OUTPUT: + + The cocharacteristic polynomial in `\ZZ[z]`. + + EXAMPLES:: + + sage: A = hyperplane_arrangements.coordinate(2) + sage: A.cocharacteristic_polynomial() + z^2 + 2*z + 1 + sage: B = hyperplane_arrangements.braid(3) + sage: B.cocharacteristic_polynomial() + 2*z^3 + 3*z^2 + z + + TESTS:: + + sage: I = hyperplane_arrangements.Ish(2) + sage: I.is_central() + False + sage: I.cocharacteristic_polynomial() + Traceback (most recent call last): + ... + ValueError: only defined for central hyperplane arrangements + """ + if not self.is_central(): + raise ValueError("only defined for central hyperplane arrangements") + + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + R = PolynomialRing(ZZ, 'z') + z = R.gen() + L = self.intersection_poset(element_label="subspace").dual() + B = L.minimal_elements()[0] + return R.sum(abs(L.moebius_function(B, X)) * z**X.dimension() + for X in L) + + @cached_method + def primitive_eulerian_polynomial(self): + r""" + Return the primitive Eulerian polynomial of ``self``. + + The primitive Eulerian polynomial of a hyperplane arrangement `A` + is defined [BHS2023]_ by + + .. MATH:: + + P_A(z) := \sum_{X \in L} |\mu(B,X)| (z - 1)^{\mathrm{codim} X}, + + where `L` is the intersection poset of `A`, `B` is the minimal + element of `L` (here, the `0` dimensional subspace), and + `\mu` is the Möbius function of `L`. + + OUTPUT: + + The primitive Eulerian polynomial in `\ZZ[z]`. + + EXAMPLES:: + + sage: A = hyperplane_arrangements.coordinate(2) + sage: A.primitive_eulerian_polynomial() + z^2 + sage: B = hyperplane_arrangements.braid(3) + sage: B.primitive_eulerian_polynomial() + z^2 + z + + sage: H = hyperplane_arrangements.Shi(['B',2]).cone() + sage: H.is_simplicial() + False + sage: H.primitive_eulerian_polynomial() + z^3 + 11*z^2 + 4*z + + sage: H = hyperplane_arrangements.graphical(graphs.CycleGraph(4)) + sage: H.primitive_eulerian_polynomial() + z^3 + 3*z^2 - z + + We verify Example 2.4 in [BHS2023]_ for `k = 2,3,4,5`:: + + sage: R. = HyperplaneArrangements(QQ) + sage: for k in range(2,6): + ....: H = R([x+j*y for j in range(k)]) + ....: H.primitive_eulerian_polynomial() + z^2 + z^2 + z + z^2 + 2*z + z^2 + 3*z + + We verify Equation (4) in [BHS2023]_ on some examples:: + + sage: R. = ZZ[] + sage: Arr = [hyperplane_arrangements.braid(n) for n in range(2,6)] + sage: all(R(A.cocharacteristic_polynomial()(1/(x-1)) * (x-1)^A.dimension()) + ....: == R(A.primitive_eulerian_polynomial()) for A in Arr) + True + + We compute types `H_3` and `F_4` in Table 1 of [BHS2023]_:: + + sage: W = CoxeterGroup(['H',3], implementation="matrix") + sage: A = HyperplaneArrangements(W.base_ring(), tuple(f'x{s}' for s in range(W.rank()))) + sage: H = A([[0] + list(r) for r in W.positive_roots()]) + sage: H.is_simplicial() + True + sage: H.primitive_eulerian_polynomial() + z^3 + 28*z^2 + 16*z + + sage: W = CoxeterGroup(['F',4], implementation="permutation") + sage: A = HyperplaneArrangements(QQ, tuple(f'x{s}' for s in range(W.rank()))) + sage: H = A([[0] + list(r) for r in W.positive_roots()]) + sage: H.primitive_eulerian_polynomial() # long time + z^4 + 116*z^3 + 220*z^2 + 48*z + + We verify Proposition 2.5 in [BHS2023]_ on the braid arrangement + `B_k` for `k = 2,3,4,5`:: + + sage: B = [hyperplane_arrangements.braid(k) for k in range(2,6)] + sage: all(H.is_simplicial() for H in B) + True + sage: all(c > 0 for H in B for c in H.primitive_eulerian_polynomial().coefficients()) + True + + We verify Example 9.4 in [BHS2023]_ showing a hyperplane arrangement + whose primitive Eulerian polynomial does not have real roots (in + general, the graphical arrangement of a cycle graph corresponds + to the arrangements in Example 9.4):: + + sage: H = hyperplane_arrangements.graphical(graphs.CycleGraph(5)) + sage: pep = H.primitive_eulerian_polynomial(); pep + z^4 + 6*z^3 - 4*z^2 + z + sage: pep.roots(QQbar) + [(-6.626418492719221?, 1), + (0, 1), + (0.3132092463596102? - 0.2298065541510677?*I, 1), + (0.3132092463596102? + 0.2298065541510677?*I, 1)] + sage: pep.roots(AA) + [(-6.626418492719221?, 1), (0, 1)] + + TESTS:: + + sage: I = hyperplane_arrangements.Ish(2) + sage: I.is_central() + False + sage: I.primitive_eulerian_polynomial() + Traceback (most recent call last): + ... + ValueError: only defined for central hyperplane arrangements + """ + if not self.is_central(): + raise ValueError("only defined for central hyperplane arrangements") + + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + R = PolynomialRing(ZZ, 'z') + z = R.gen() + L = self.intersection_poset(element_label="subspace").dual() + B = L.minimal_elements()[0] + n = self.dimension() + return R.sum(abs(L.moebius_function(B, X)) * (z - 1)**(n-X.dimension()) + for X in L) + def deletion(self, hyperplanes): r""" Return the hyperplane arrangement obtained by removing ``h``. diff --git a/src/sage/geometry/hyperplane_arrangement/library.py b/src/sage/geometry/hyperplane_arrangement/library.py index 83c4f80c325..4ec9f9fdbdf 100644 --- a/src/sage/geometry/hyperplane_arrangement/library.py +++ b/src/sage/geometry/hyperplane_arrangement/library.py @@ -5,12 +5,12 @@ :mod:`sage.geometry.hyperplane_arrangement.arrangement` for details about how to construct your own hyperplane arrangements. """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2013 David Perkinson # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.graphs.graph_generators import graphs from sage.matrix.constructor import matrix, random_matrix @@ -233,6 +233,86 @@ def coordinate(self, n, K=QQ, names=None): x = H.gens() return H(x) + def Coxeter(self, data, K=QQ, names=None): + r""" + Return the Coxeter arrangement. + + This generalizes the braid arrangements to crystallographic + root systems. + + INPUT: + + - ``data`` -- either an integer or a Cartan type (or coercible + into; see "CartanType") + + - ``K`` -- field (default:``QQ``) + + - ``names`` -- tuple of strings or ``None`` (default); the + variable names for the ambient space + + OUTPUT: + + - If ``data`` is an integer `n`, return the braid arrangement in + dimension `n`, i.e. the set of `n(n-1)` hyperplanes: + `\{ x_i - x_j = 0,1 : 1 \leq i \leq j \leq n \}`. This corresponds + to the Coxeter arrangement of Cartan type `A_{n-1}`. + + - If ``data`` is a Cartan type, return the Coxeter arrangement of given + type. + + The Coxeter arrangement of a given crystallographic + Cartan type is defined by the inner products + `\langle a,x \rangle = 0` where + `a \in \Phi^+` runs over positive roots of the root system `\Phi`. + + EXAMPLES:: + + sage: # needs sage.combinat + sage: hyperplane_arrangements.Coxeter(4) + Arrangement of 6 hyperplanes of dimension 4 and rank 3 + sage: hyperplane_arrangements.Coxeter("B4") + Arrangement of 16 hyperplanes of dimension 4 and rank 4 + sage: hyperplane_arrangements.Coxeter("A3") + Arrangement of 6 hyperplanes of dimension 4 and rank 3 + + If the Cartan type is not crystallographic, the Coxeter arrangement + is not implemented yet:: + + sage: hyperplane_arrangements.Coxeter("H3") + Traceback (most recent call last): + ... + NotImplementedError: Coxeter arrangements are not implemented for non crystallographic Cartan types + + The characteristic polynomial is pre-computed using the results + of Terao, see [Ath2000]_:: + + sage: # needs sage.combinat + sage: hyperplane_arrangements.Coxeter("A3").characteristic_polynomial() + x^3 - 6*x^2 + 11*x - 6 + """ + from sage.combinat.root_system.weyl_group import WeylGroup + if data in NN: + cartan_type = CartanType(["A", data - 1]) + else: + cartan_type = CartanType(data) + if not cartan_type.is_crystallographic(): + raise NotImplementedError("Coxeter arrangements are not implemented for non crystallographic Cartan types") + W = WeylGroup(cartan_type) + Ra = RootSystem(cartan_type).ambient_space() + PR = Ra.positive_roots() + d = Ra.dimension() + H = make_parent(K, d, names) + x = H.gens() + hyperplanes = [] + + for a in PR: + hyperplanes.append(sum(a[j] * x[j] for j in range(d))) + A = H(*hyperplanes) + x = polygen(QQ, 'x') + charpoly = prod(x - d + 1 for d in W.degrees()) + A.characteristic_polynomial.set_cache(charpoly) + return A + def G_semiorder(self, G, K=QQ, names=None): r""" Return the semiorder hyperplane arrangement of a graph. @@ -699,7 +779,7 @@ def Shi(self, data, K=QQ, names=None, m=1): x^3 - 54*x^2 + 972*x - 5832 """ if data in NN: - cartan_type = CartanType(["A",data-1]) + cartan_type = CartanType(["A", data - 1]) else: cartan_type = CartanType(data) if not cartan_type.is_crystallographic(): @@ -722,4 +802,5 @@ def Shi(self, data, K=QQ, names=None, m=1): A.characteristic_polynomial.set_cache(charpoly) return A + hyperplane_arrangements = HyperplaneArrangementLibrary() diff --git a/src/sage/geometry/integral_points.pxi b/src/sage/geometry/integral_points.pxi index c45f7f1cb2e..037efb41da8 100644 --- a/src/sage/geometry/integral_points.pxi +++ b/src/sage/geometry/integral_points.pxi @@ -545,13 +545,13 @@ cpdef rectangular_box_points(list box_min, list box_max, assert not (count_only and return_saturated) cdef int d = len(box_min) cdef int i, j - cdef list diameter = sorted([ (box_max[i]-box_min[i], i) for i in range(d) ], + cdef list diameter = sorted([(box_max[i]-box_min[i], i) for i in range(d)], reverse=True) cdef list diameter_value = [x[0] for x in diameter] cdef list diameter_index = [x[1] for x in diameter] # Construct the inverse permutation - cdef list orig_perm = list(xrange(len(diameter_index))) + cdef list orig_perm = list(range(len(diameter_index))) for i, j in enumerate(diameter_index): orig_perm[j] = i diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 701b8e43ee8..26c7d9a3819 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -398,6 +398,7 @@ def ReflexivePolytope(dim, n): else: raise NotImplementedError("only 2- and 3-dimensional reflexive polytopes are available!") + # Sequences of reflexive polytopes _rp = [None] * 4 @@ -5545,6 +5546,7 @@ def all_polars(polytopes): result.close() os.remove(result_name) + # Synonym for the above function all_facet_equations = all_polars diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 7e360658341..561ed76d70c 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -414,6 +414,7 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 sage: # optional - pynormaliz + sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d)),backend='normaliz') sage: hypercube(3).ehrhart_polynomial(engine='normaliz') diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd index bdd49225ff2..030c9defa45 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd @@ -8,7 +8,7 @@ from .polyhedron_face_lattice cimport PolyhedronFaceLattice @cython.final cdef class CombinatorialPolyhedron(SageObject): - cdef public dict __cached_methods + cdef public dict _cached_methods # Do not assume any of those attributes to be initialized, use the corresponding methods instead. cdef tuple _Vrep # the names of VRep, if they exist diff --git a/src/sage/geometry/triangulation/triangulations.cc b/src/sage/geometry/triangulation/triangulations.cc index 68e4efa75e1..8ea306d8f7c 100644 --- a/src/sage/geometry/triangulation/triangulations.cc +++ b/src/sage/geometry/triangulation/triangulations.cc @@ -117,7 +117,7 @@ triangulations_ptr init_triangulations compact_simplices seed; for (int i=0; inext_triangulation(); PyObject* py_triang = PyTuple_New(triang.size()); for (size_t i=0; i -#define PyInt_FromLong PyLong_FromLong -#define PyInt_AsLong PyLong_AsLong -#define PyInt_AS_LONG PyLong_AS_LONG class triangulations: public std::vector { diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index ff222837117..f158aaafd27 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -561,7 +561,7 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee'): Given a wrong algorithm:: - from sage.graphs.base.boost_graph import bandwidth_heuristics + sage: from sage.graphs.base.boost_graph import bandwidth_heuristics sage: bandwidth_heuristics(graphs.PathGraph(3), algorithm='tip top') Traceback (most recent call last): ... @@ -569,7 +569,7 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee'): Given a graph with no edges:: - from sage.graphs.base.boost_graph import bandwidth_heuristics + sage: from sage.graphs.base.boost_graph import bandwidth_heuristics sage: bandwidth_heuristics(Graph()) (0, []) sage: bandwidth_heuristics(graphs.RandomGNM(10,0)) # needs networkx @@ -686,6 +686,16 @@ cpdef min_spanning_tree(g, Traceback (most recent call last): ... TypeError: float() argument must be a string or a... number... + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)], weighted=True) + sage: E = min_spanning_tree(G, algorithm='Kruskal') + sage: sum(w for _, _, w in E) + 3 + sage: F = min_spanning_tree(G, algorithm='Prim') + sage: sum(w for _, _, w in F) + 3 """ from sage.graphs.graph import Graph @@ -719,9 +729,8 @@ cpdef min_spanning_tree(g, if result.size() != 2 * (n - 1): return [] - else: - edges = [(int_to_vertex[ result[2*i]], int_to_vertex[ result[2*i + 1]]) for i in range(n - 1)] - return [(min(e[0], e[1]), max(e[0], e[1]), g.edge_label(e[0], e[1])) for e in edges] + edges = [(int_to_vertex[ result[2*i]], int_to_vertex[ result[2*i + 1]]) for i in range(n - 1)] + return [(u, v, g.edge_label(u, v)) for u, v in edges] cpdef blocks_and_cut_vertices(g): diff --git a/src/sage/graphs/chrompoly.pyx b/src/sage/graphs/chrompoly.pyx index 441ba58643d..d0611a3df84 100644 --- a/src/sage/graphs/chrompoly.pyx +++ b/src/sage/graphs/chrompoly.pyx @@ -185,7 +185,7 @@ def chromatic_polynomial(G, return_tree_basis=False, algorithm='C', cache=None): # Breadth first search from 0: bfs_reorder[0] = 0 mpz_init(tot[0]) # sets to 0 - for i from 0 < i < nverts: + for i in range(1, nverts): bfs_reorder[i] = -1 mpz_init(tot[i]) # sets to 0 mpz_init(tot[nverts]) # sets to 0 @@ -230,12 +230,12 @@ def chromatic_polynomial(G, return_tree_basis=False, algorithm='C', cache=None): for i in range(nverts): mpz_clear(tot[i]) raise - for i from 0 <= i <= nverts: + for i in range(nverts + 1): mpz_init(coeffs[i]) # also sets them to 0 mpz_init(coeff) mpz_init_set_si(m, -1) # start with the zero polynomial: f(x) = 0 - for i from nverts >= i > 0: + for i in range(nverts, 0, -1): # nverts >= i > 0 if not mpz_sgn(tot[i]): continue mpz_neg(m, m) @@ -244,7 +244,7 @@ def chromatic_polynomial(G, return_tree_basis=False, algorithm='C', cache=None): # f += tot[i]*m*x*(x-1)**(i-1) mpz_addmul(coeffs[i], m, tot[i]) mpz_set_si(coeff, 1) - for j from 1 <= j < i: + for j in range(1, i): # an iterative method for binomial coefficients... mpz_mul_si(coeff, coeff, j-i) mpz_divexact_ui(coeff, coeff, j) @@ -254,13 +254,13 @@ def chromatic_polynomial(G, return_tree_basis=False, algorithm='C', cache=None): mpz_mul(coeff, coeff, m) coeffs_ZZ = [] cdef Integer c_ZZ - for i from 0 <= i <= nverts: + for i in range(nverts + 1): c_ZZ = Integer(0) mpz_set(c_ZZ.value, coeffs[i]) coeffs_ZZ.append(c_ZZ) f = R(coeffs_ZZ) - for i from 0 <= i <= nverts: + for i in range(nverts + 1): mpz_clear(tot[i]) mpz_clear(coeffs[i]) diff --git a/src/sage/graphs/comparability.pyx b/src/sage/graphs/comparability.pyx index 119cd892265..405b4ace2ff 100644 --- a/src/sage/graphs/comparability.pyx +++ b/src/sage/graphs/comparability.pyx @@ -677,7 +677,6 @@ def is_permutation(g, algorithm="greedy", certificate=False, check=True, ....: break """ - from sage.graphs.comparability import is_comparability if certificate: # First poset, we stop if it fails diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index a8e6e9997b1..d30d5e63efa 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -84,7 +84,6 @@ :meth:`~DiGraph.strongly_connected_components_subgraphs` | Return the strongly connected components as a list of subgraphs. :meth:`~DiGraph.strongly_connected_component_containing_vertex` | Return the strongly connected component containing a given vertex :meth:`~DiGraph.strongly_connected_components` | Return the list of strongly connected components. - :meth:`~DiGraph.immediate_dominators` | Return the immediate dominators of all vertices reachable from `root`. :meth:`~DiGraph.strong_articulation_points` | Return the strong articulation points of this digraph. diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index 4b664e3eb65..37416d428a8 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -219,7 +219,7 @@ def private_neighbors(G, vertex, dom): # Computation of minimum dominating sets # ============================================================================== -def dominating_sets(g, k=1, independent=False, total=False, +def dominating_sets(g, k=1, independent=False, total=False, connected=False, solver=None, verbose=0, *, integrality_tolerance=1e-3): r""" Return an iterator over the minimum distance-`k` dominating sets @@ -261,6 +261,9 @@ def dominating_sets(g, k=1, independent=False, total=False, - ``total`` -- boolean (default: ``False``); when ``True``, computes total dominating sets (see the See the :wikipedia:`Dominating_set`) + - ``connected`` -- boolean (default: ``False``); when ``True``, computes + connected dominating sets (see :wikipedia:`Connected_dominating_set`) + - ``solver`` -- string (default: ``None``); specify a Mixed Integer Linear Programming (MILP) solver to be used. If set to ``None``, the default one is used. For more information on MILP solvers and which default solver is @@ -338,6 +341,37 @@ def dominating_sets(g, k=1, independent=False, total=False, sage: next(g.dominating_sets()) [1] + Minimum connected dominating sets of the Peterson graph:: + + sage: G = graphs.PetersenGraph() + sage: G.dominating_set(total=True, value_only=True) + 4 + sage: sorted(G.dominating_sets(k=1, connected=True)) + [[0, 1, 2, 6], + [0, 1, 4, 5], + [0, 3, 4, 9], + [0, 5, 7, 8], + [1, 2, 3, 7], + [1, 6, 8, 9], + [2, 3, 4, 8], + [2, 5, 7, 9], + [3, 5, 6, 8], + [4, 6, 7, 9]] + + Subgraph induced by the dominating set is connected:: + + sage: G = graphs.PetersenGraph() + sage: all(G.subgraph(vertices=dom).is_connected() for dom in G.dominating_set(k=1, connected=True)) + True + + Minimum distance-k connected dominating sets of the Tietze graph:: + + sage: G = graphs.TietzeGraph() + sage: sorted(G.dominating_sets(k=2, connected=True)) + [[0, 9], [1, 0], [2, 3], [4, 3], [5, 6], [7, 6], [8, 0], [10, 3], [11, 6]] + sage: sorted(G.dominating_sets(k=3, connected=True)) + [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11]] + TESTS:: sage: g = Graph([(0, 1)]) @@ -395,6 +429,32 @@ def neighbors_iter(x): for u, v in g.edge_iterator(labels=None): p.add_constraint(b[u] + b[v], max=1) + if connected: + E = set(frozenset(e) for e in g.edge_iterator(labels=False)) + # edges used in the spanning tree + edge = p.new_variable(binary=True, name='e') + # relaxed edges to test for acyclicity + r_edge = p.new_variable(nonnegative=True, name='re') + + # 1. We want a tree + p.add_constraint(p.sum(edge[fe] for fe in E) + == p.sum(b[u] for u in g) - 1) + + # 2. An edge can be in the tree if its end vertices are selected + for fe in E: + u, v = fe + p.add_constraint(edge[fe] <= b[u]) + p.add_constraint(edge[fe] <= b[v]) + + # 3. Subtour elimination constraints + for fe in E: + u, v = fe + p.add_constraint(edge[fe] <= r_edge[u, v] + r_edge[v, u]) + + eps = 1 / (5 * Integer(g.order())) + for v in g: + p.add_constraint(p.sum(r_edge[u, v] for u in g.neighbor_iterator(v)), max=1 - eps) + # Minimizes the number of vertices used p.set_objective(p.sum(b[v] for v in g)) @@ -415,8 +475,7 @@ def neighbors_iter(x): # Prevent finding twice a solution p.add_constraint(p.sum(b[u] for u in dom) <= best - 1) - -def dominating_set(g, k=1, independent=False, total=False, value_only=False, +def dominating_set(g, k=1, independent=False, total=False, connected=False, value_only=False, solver=None, verbose=0, *, integrality_tolerance=1e-3): r""" Return a minimum distance-`k` dominating set of the graph. @@ -453,6 +512,9 @@ def dominating_set(g, k=1, independent=False, total=False, value_only=False, - ``total`` -- boolean (default: ``False``); when ``True``, computes a total dominating set (see the See the :wikipedia:`Dominating_set`) + - ``connected`` -- boolean (default: ``False``); when ``True``, computes a + connected dominating set (see :wikipedia:`Connected_dominating_set`) + - ``value_only`` -- boolean (default: ``False``); whether to only return the cardinality of the computed dominating set, or to return its list of vertices (default) @@ -517,7 +579,7 @@ def dominating_set(g, k=1, independent=False, total=False, value_only=False, [5, 2, 1] """ dom = next(dominating_sets(g, k=k, independent=independent, total=total, - solver=solver, verbose=verbose, + connected=connected, solver=solver, verbose=verbose, integrality_tolerance=integrality_tolerance)) return Integer(len(dom)) if value_only else dom diff --git a/src/sage/graphs/edge_connectivity.pyx b/src/sage/graphs/edge_connectivity.pyx index 02326437a54..014e46f7500 100644 --- a/src/sage/graphs/edge_connectivity.pyx +++ b/src/sage/graphs/edge_connectivity.pyx @@ -1197,7 +1197,6 @@ cdef class GabowEdgeConnectivity: raise ValueError("the value of the edge connectivity has not been " "properly computed. This may result from an interruption") - # # Packing arborescences # diff --git a/src/sage/graphs/generators/chessboard.py b/src/sage/graphs/generators/chessboard.py index 59517d128bb..dfe5b15b273 100644 --- a/src/sage/graphs/generators/chessboard.py +++ b/src/sage/graphs/generators/chessboard.py @@ -4,11 +4,11 @@ The methods defined here appear in :mod:`sage.graphs.graph_generators`. -- :meth:`BishopGraph ` -- :meth:`KingGraph ` -- :meth:`KnightGraph ` -- :meth:`QueenGraph ` -- :meth:`RookGraph ` +- :meth:`BishopGraph ` +- :meth:`KingGraph ` +- :meth:`KnightGraph ` +- :meth:`QueenGraph ` +- :meth:`RookGraph ` AUTHORS: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index bb73e4c487e..a090eb3f73d 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -912,7 +912,7 @@ def Balaban11Cage(embedding=1): sage: g3 = graphs.Balaban11Cage(embedding=3) # needs networkx sage: g1.show(figsize=[10,10]) # long time # needs sage.plot sage: g2.show(figsize=[10,10]) # long time # needs networkx sage.plot - sage: g3.show(figsize=[10,10]) # long time # needs sage.plot + sage: g3.show(figsize=[10,10]) # long time # needs networkx sage.plot Proof that the embeddings are the same graph:: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 2deb533f7f1..19cc35bfb0b 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -4704,17 +4704,23 @@ def min_spanning_tree(self, sage: len(g.min_spanning_tree()) 4 sage: weight = lambda e: 1 / ((e[0] + 1) * (e[1] + 1)) - sage: sorted(g.min_spanning_tree(weight_function=weight)) - [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] - sage: sorted(g.min_spanning_tree(weight_function=weight, - ....: algorithm='Kruskal_Boost')) - [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] + sage: E = g.min_spanning_tree(weight_function=weight) + sage: T = Graph(E) + sage: set(g) == set(T) and T.order() == T.size() + 1 and T.is_tree() + True + sage: sum(map(weight, E)) + 5/12 + sage: E = g.min_spanning_tree(weight_function=weight, + ....: algorithm='Kruskal_Boost') + sage: Graph(E).is_tree(); sum(map(weight, E)) + True + 5/12 sage: g = graphs.PetersenGraph() sage: g.allow_multiple_edges(True) sage: g.add_edges(g.edge_iterator()) - sage: sorted(g.min_spanning_tree()) - [(0, 1, None), (0, 4, None), (0, 5, None), (1, 2, None), (1, 6, None), - (3, 8, None), (5, 7, None), (5, 8, None), (6, 9, None)] + sage: T = Graph(g.min_spanning_tree()) + sage: set(g) == set(T) and T.order() == T.size() + 1 and T.is_tree() + True Boruvka's algorithm:: @@ -4725,15 +4731,13 @@ def min_spanning_tree(self, Prim's algorithm:: sage: g = graphs.CompleteGraph(5) - sage: sorted(g.min_spanning_tree(algorithm='Prim_edge', - ....: starting_vertex=2, weight_function=weight)) - [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_fringe', - ....: starting_vertex=2, weight_function=weight)) - [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] - sage: sorted(g.min_spanning_tree(weight_function=weight, - ....: algorithm='Prim_Boost')) - [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] + sage: for algo in ['Prim_edge', 'Prim_fringe', 'Prim_Boost']: + ....: E = g.min_spanning_tree(algorithm=algo, weight_function=weight) + ....: T = Graph(E) + ....: print(set(g) == set(T) and T.order() == T.size() + 1 and T.is_tree()) + True + True + True NetworkX algorithm:: @@ -4745,30 +4749,43 @@ def min_spanning_tree(self, sage: G = Graph([(0, 1, {'name': 'a', 'weight': 1}), ....: (0, 2, {'name': 'b', 'weight': 3}), ....: (1, 2, {'name': 'b', 'weight': 1})]) - sage: sorted(G.min_spanning_tree(weight_function=lambda e: e[2]['weight'])) + sage: sorted(G.min_spanning_tree(algorithm='Boruvka', + ....: weight_function=lambda e: e[2]['weight'])) [(0, 1, {'name': 'a', 'weight': 1}), (1, 2, {'name': 'b', 'weight': 1})] If the graph is not weighted, edge labels are not considered, even if they are numbers:: sage: g = Graph([(1, 2, 1), (1, 3, 2), (2, 3, 1)]) - sage: sorted(g.min_spanning_tree()) + sage: sorted(g.min_spanning_tree(algorithm='Boruvka')) [(1, 2, 1), (1, 3, 2)] In order to use weights, we need either to set variable ``weighted`` to ``True``, or to specify a weight function or set by_weight to ``True``:: sage: g.weighted(True) - sage: sorted(g.min_spanning_tree()) + sage: Graph(g.min_spanning_tree()).edges(sort=True) [(1, 2, 1), (2, 3, 1)] sage: g.weighted(False) - sage: sorted(g.min_spanning_tree()) + sage: Graph(g.min_spanning_tree()).edges(sort=True) [(1, 2, 1), (1, 3, 2)] - sage: sorted(g.min_spanning_tree(by_weight=True)) + sage: Graph(g.min_spanning_tree(by_weight=True)).edges(sort=True) + [(1, 2, 1), (2, 3, 1)] + sage: Graph(g.min_spanning_tree(weight_function=lambda e: e[2])).edges(sort=True) + [(1, 2, 1), (2, 3, 1)] + + Note that the order of the vertices on each edge is not guaranteed and + may differ from an algorithm to the other:: + + sage: g.weighted(True) + sage: sorted(g.min_spanning_tree()) + [(2, 1, 1), (3, 2, 1)] + sage: sorted(g.min_spanning_tree(algorithm='Boruvka')) [(1, 2, 1), (2, 3, 1)] - sage: sorted(g.min_spanning_tree(weight_function=lambda e: e[2])) + sage: Graph(g.min_spanning_tree()).edges(sort=True) [(1, 2, 1), (2, 3, 1)] + TESTS: Check that, if ``weight_function`` is not provided, then edge weights @@ -4776,21 +4793,21 @@ def min_spanning_tree(self, sage: g = Graph(weighted=True) sage: g.add_edges([[0, 1, 1], [1, 2, 1], [2, 0, 10]]) - sage: sorted(g.min_spanning_tree()) + sage: Graph(g.min_spanning_tree()).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Filter_Kruskal')) + sage: Graph(g.min_spanning_tree(algorithm='Filter_Kruskal')).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Kruskal_Boost')) + sage: Graph(g.min_spanning_tree(algorithm='Kruskal_Boost')).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_fringe')) + sage: Graph(g.min_spanning_tree(algorithm='Prim_fringe')).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_edge')) + sage: Graph(g.min_spanning_tree(algorithm='Prim_edge')).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_Boost')) + sage: Graph(g.min_spanning_tree(algorithm='Prim_Boost')).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='NetworkX')) # needs networkx + sage: Graph(g.min_spanning_tree(algorithm='Boruvka')).edges(sort=True) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Boruvka')) + sage: Graph(g.min_spanning_tree(algorithm='NetworkX')).edges(sort=True) # needs networkx [(0, 1, 1), (1, 2, 1)] Check that, if ``weight_function`` is provided, it overrides edge @@ -4798,29 +4815,27 @@ def min_spanning_tree(self, sage: g = Graph([[0, 1, 1], [1, 2, 1], [2, 0, 10]], weighted=True) sage: weight = lambda e: 3 - e[0] - e[1] - sage: sorted(g.min_spanning_tree(weight_function=weight)) + sage: Graph(g.min_spanning_tree(weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Filter_Kruskal', weight_function=weight)) + sage: Graph(g.min_spanning_tree(algorithm='Filter_Kruskal', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Kruskal_Boost', weight_function=weight)) + sage: Graph(g.min_spanning_tree(algorithm='Kruskal_Boost', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_fringe', weight_function=weight)) + sage: Graph(g.min_spanning_tree(algorithm='Prim_fringe', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_edge', weight_function=weight)) + sage: Graph(g.min_spanning_tree(algorithm='Prim_edge', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_Boost', weight_function=weight)) + sage: Graph(g.min_spanning_tree(algorithm='Prim_Boost', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)) # needs networkx - [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='Boruvka', weight_function=weight)) + sage: Graph(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)).edges(sort=True) # needs networkx [(0, 2, 10), (1, 2, 1)] If the graph is directed, it is transformed into an undirected graph:: sage: g = digraphs.Circuit(3) - sage: sorted(g.min_spanning_tree(weight_function=weight)) + sage: Graph(g.min_spanning_tree(weight_function=weight)).edges(sort=True) [(0, 2, None), (1, 2, None)] - sage: sorted(g.to_undirected().min_spanning_tree(weight_function=weight)) + sage: Graph(g.to_undirected().min_spanning_tree(weight_function=weight)).edges(sort=True) [(0, 2, None), (1, 2, None)] If at least an edge weight is not convertible to a float, an error is @@ -4841,6 +4856,17 @@ def min_spanning_tree(self, sage: graphs.EmptyGraph().min_spanning_tree() [] + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: E = G.min_spanning_tree(algorithm='Prim_Boost', by_weight=True) + sage: E = G.min_spanning_tree(algorithm='Prim_fringe', by_weight=True) + sage: E = G.min_spanning_tree(algorithm='Prim_edge', by_weight=True) + sage: E = G.min_spanning_tree(algorithm='Kruskal_Boost', by_weight=True) + sage: E = G.min_spanning_tree(algorithm='Filter_Kruskal', by_weight=True) + sage: E = G.min_spanning_tree(algorithm='Boruvka', by_weight=True) + sage: E = G.min_spanning_tree(algorithm='NetworkX', by_weight=True) # needs networkx """ if not self.order(): return [] @@ -5136,9 +5162,9 @@ def cycle_basis(self, output='vertex'): sage: [sorted(c) for c in G.cycle_basis()] # needs networkx [['Hey', 'Really ?', 'Wuuhuu'], [0, 2], [0, 1, 2]] sage: [sorted(c) for c in G.cycle_basis(output='edge')] # needs networkx - [[('Hey', 'Wuuhuu', None), - ('Really ?', 'Hey', None), - ('Wuuhuu', 'Really ?', None)], + [[('Hey', 'Really ?', None), + ('Really ?', 'Wuuhuu', None), + ('Wuuhuu', 'Hey', None)], [(0, 2, 'a'), (2, 0, 'b')], [(0, 2, 'b'), (1, 0, 'c'), (2, 1, 'd')]] @@ -5399,7 +5425,8 @@ def is_planar(self, on_embedding=None, kuratowski=False, set_embedding=False, se sage: k43 = graphs.CompleteBipartiteGraph(4, 3) sage: result = k43.is_planar(kuratowski=True); result - (False, Graph on 6 vertices) + (False, + Kuratowski subgraph of (Complete bipartite graph of order 4+3): Graph on 6 vertices) sage: result[1].is_isomorphic(graphs.CompleteBipartiteGraph(3, 3)) True @@ -5412,19 +5439,61 @@ def is_planar(self, on_embedding=None, kuratowski=False, set_embedding=False, se Traceback (most recent call last): ... NotImplementedError: cannot compute with embeddings of - multiple-edged or looped graphs + multiple-edged or looped graphs + sage: G.is_planar(set_embedding=True) + Traceback (most recent call last): + ... + NotImplementedError: cannot compute with embeddings of + multiple-edged or looped graphs + sage: G.is_planar(kuratowski=True) + (True, None) sage: G.is_planar(set_pos=True) + True + sage: sorted(G.get_pos().items()) + [(0, [0, 0]), (1, [0, 1])] + + Digraphs with multiple edges or loops or pairs of opposite arcs are + partially supported (:trac:`35152`):: + + sage: D = digraphs.Complete(3) + sage: D.is_planar() + True + sage: D.is_planar(set_pos=True) + True + sage: sorted(D.get_pos().items()) + [(0, [0, 1]), (1, [1, 1]), (2, [1, 0])] + sage: D.is_planar(on_embedding={}) Traceback (most recent call last): ... NotImplementedError: cannot compute with embeddings of - multiple-edged or looped graphs - sage: G.is_planar(set_embedding=True) + digraphs with pairs of opposite arcs + sage: D.is_planar(set_embedding=True) Traceback (most recent call last): ... NotImplementedError: cannot compute with embeddings of - multiple-edged or looped graphs - sage: G.is_planar(kuratowski=True) + digraphs with pairs of opposite arcs + sage: D.is_planar(kuratowski=True) + (True, None) + sage: D.allow_multiple_edges(True) + sage: D.add_edges(D.edges(sort=False)) + sage: D.allow_loops(True) + sage: D.add_edges((u, u) for u in D) + sage: D.is_planar() + True + sage: D.is_planar(kuratowski=True) (True, None) + sage: D.is_planar(set_pos=True) + True + sage: D.is_planar(set_embedding=True) + Traceback (most recent call last): + ... + NotImplementedError: cannot compute with embeddings of + multiple-edged or looped graphs + sage: D.is_planar(on_embedding={}) + Traceback (most recent call last): + ... + NotImplementedError: cannot compute with embeddings of + multiple-edged or looped graphs :: @@ -5485,31 +5554,35 @@ def is_planar(self, on_embedding=None, kuratowski=False, set_embedding=False, se if self.order() > 4 and self.size() > 3 * self.order() - 6: return False - if self.has_multiple_edges() or self.has_loops(): - if set_embedding or (on_embedding is not None) or set_pos: + if set_embedding or (on_embedding is not None): + # So far, working with embeddings is not working properly when a + # (di)graph has multiple edges or loops, or when a digraph has pairs + # of opposite arcs + if self.has_multiple_edges() or self.has_loops(): raise NotImplementedError("cannot compute with embeddings of multiple-edged or looped graphs") - else: - return self.to_simple().is_planar(kuratowski=kuratowski) + elif (self.is_directed() and + any(self.has_edge(v, u) for u, v in self.edge_iterator(labels=False))): + raise NotImplementedError("cannot compute with embeddings of digraphs with pairs of opposite arcs") if on_embedding is not None: self._check_embedding_validity(on_embedding, boolean=False) return (0 == self.genus(minimal=False, set_embedding=False, on_embedding=on_embedding)) + + # We take the underlying undirected and simple graph + G = self.to_simple(to_undirected=True, immutable=False) + # And check if it is planar + from sage.graphs.planarity import is_planar + planar = is_planar(G, kuratowski=kuratowski, set_pos=set_pos, set_embedding=set_embedding) + if kuratowski: + bool_result = planar[0] else: - from sage.graphs.planarity import is_planar - G = self.to_undirected() - if hasattr(G, '_immutable'): - G = copy(G) - planar = is_planar(G, kuratowski=kuratowski, set_pos=set_pos, set_embedding=set_embedding) - if kuratowski: - bool_result = planar[0] - else: - bool_result = planar - if bool_result: - if set_pos: - self._pos = G._pos - if set_embedding: - self._embedding = G._embedding - return planar + bool_result = planar + if bool_result: + if set_pos: + self._pos = G._pos + if set_embedding: + self._embedding = G._embedding + return planar def is_circular_planar(self, on_embedding=None, kuratowski=False, set_embedding=True, boundary=None, @@ -5591,7 +5664,7 @@ def is_circular_planar(self, on_embedding=None, kuratowski=False, sage: g439.is_circular_planar(boundary=[1, 2, 3, 4]) False sage: g439.is_circular_planar(kuratowski=True, boundary=[1, 2, 3, 4]) - (False, Graph on 8 vertices) + (False, Kuratowski subgraph of (): Graph on 8 vertices) sage: g439.is_circular_planar(kuratowski=True, boundary=[1, 2, 3]) (True, None) sage: g439.get_embedding() diff --git a/src/sage/graphs/graph_plot.py b/src/sage/graphs/graph_plot.py index 0a7dbb81fc6..7908454db54 100644 --- a/src/sage/graphs/graph_plot.py +++ b/src/sage/graphs/graph_plot.py @@ -168,8 +168,7 @@ 'Which graphviz layout program to use -- one of ' '"circo", "dot", "fdp", "neato", or "twopi".', 'by_component': - 'Whether to do the spring layout by connected component -- a boolean.', - } + 'Whether to do the spring layout by connected component -- a boolean.'} graphplot_options = layout_options.copy() @@ -225,8 +224,7 @@ 'graph_border': 'Whether or not to draw a frame around the graph.', 'edge_labels_background': - 'The color of the background of the edge labels.', - }) + 'The color of the background of the edge labels.'}) _PLOT_OPTIONS_TABLE = "" @@ -235,9 +233,7 @@ __doc__ = __doc__.format(PLOT_OPTIONS_TABLE=_PLOT_OPTIONS_TABLE) -DEFAULT_SHOW_OPTIONS = { - 'figsize' : (4, 4) - } +DEFAULT_SHOW_OPTIONS = {'figsize': (4, 4)} DEFAULT_PLOT_OPTIONS = { 'vertex_size' : 200, @@ -258,8 +254,7 @@ 'dist' : .075, 'max_dist' : 1.5, 'loop_size' : .075, - 'edge_labels_background' : 'white' - } + 'edge_labels_background' : 'white'} class GraphPlot(SageObject): @@ -582,7 +577,7 @@ def set_edges(self, **edge_options): Set edge plotting parameters for the ``GraphPlot`` object. This function is called by the constructor but can also be called to - update the vertex options of an existing ``GraphPlot`` object. + update the edge options of an existing ``GraphPlot`` object. Note that the changes are cumulative. EXAMPLES:: @@ -719,8 +714,8 @@ def set_edges(self, **edge_options): if 'edge_style' in self._options: from sage.plot.misc import get_matplotlib_linestyle eoptions['linestyle'] = get_matplotlib_linestyle( - self._options['edge_style'], - return_type='long') + self._options['edge_style'], + return_type='long') if 'edge_thickness' in self._options: eoptions['thickness'] = self._options['edge_thickness'] @@ -832,20 +827,20 @@ def set_edges(self, **edge_options): # Compute perpendicular bisector p1 = self._pos[a] p2 = self._pos[b] - m = ((p1[0] + p2[0])/2., (p1[1] + p2[1])/2.) # midpoint + m = ((p1[0] + p2[0]) / 2., (p1[1] + p2[1]) / 2.) # midpoint if not p1[1] == p2[1]: - s = (p1[0] - p2[0])/(p2[1] - p1[1]) # perp slope + s = (p1[0] - p2[0]) / (p2[1] - p1[1]) # perp slope def y(x): - return s*(x - m[0]) + m[1] # perp bisector line + return s * (x - m[0]) + m[1] # perp bisector line # f, g are functions to determine x-values of point # on line y at distance d from point m (on each side) def f(d): - return sqrt(d**2/(1. + s**2)) + m[0] + return sqrt(d**2 / (1. + s**2)) + m[0] def g(d): - return -sqrt(d**2/(1. + s**2)) + m[0] + return -sqrt(d**2 / (1. + s**2)) + m[0] odd_x = f even_x = g @@ -897,31 +892,31 @@ def even_xy(d): even_end = ph(even_xy(k), p2, vr)[1] self._plot_components['edges'].append( arrow(path=[[odd_start, odd_xy(k), odd_end]], - head=local_labels[2*i][2], zorder=1, - rgbcolor=local_labels[2*i][1], + head=local_labels[2 * i][2], zorder=1, + rgbcolor=local_labels[2 * i][1], **eoptions)) self._plot_components['edges'].append( arrow(path=[[even_start, even_xy(k), even_end]], - head=local_labels[2*i + 1][2], zorder=1, - rgbcolor=local_labels[2*i + 1][1], + head=local_labels[2 * i + 1][2], zorder=1, + rgbcolor=local_labels[2 * i + 1][1], **eoptions)) else: self._plot_components['edges'].append( bezier_path([[p1, odd_xy(k), p2]], zorder=1, - rgbcolor=local_labels[2*i][1], + rgbcolor=local_labels[2 * i][1], **eoptions)) self._plot_components['edges'].append( bezier_path([[p1, even_xy(k), p2]], zorder=1, - rgbcolor=local_labels[2*i + 1][1], + rgbcolor=local_labels[2 * i + 1][1], **eoptions)) if labels: j = k / 2.0 bg = self._options['edge_labels_background'] self._plot_components['edge_labels'].append( - text(local_labels[2*i][0], odd_xy(j), + text(local_labels[2 * i][0], odd_xy(j), background_color=bg)) self._plot_components['edge_labels'].append( - text(local_labels[2*i + 1][0], even_xy(j), + text(local_labels[2 * i + 1][0], even_xy(j), background_color=bg)) if len_local_labels % 2: # draw line for last odd @@ -941,7 +936,7 @@ def even_xy(d): bg = self._options['edge_labels_background'] self._plot_components['edge_labels'].append( text(str(edges_to_draw[a, b][0][0]), - [(C[0] + D[0])/2., (C[1] + D[1])/2.], + [(C[0] + D[0]) / 2., (C[1] + D[1]) / 2.], background_color=bg)) elif is_directed: self._plot_components['edges'].append( @@ -959,8 +954,8 @@ def even_xy(d): bg = self._options['edge_labels_background'] self._plot_components['edge_labels'].append( text(str(edges_to_draw[a, b][0][0]), - [(self._pos[a][0] + self._pos[b][0])/2., - (self._pos[a][1] + self._pos[b][1])/2.], + [(self._pos[a][0] + self._pos[b][0]) / 2., + (self._pos[a][1] + self._pos[b][1]) / 2.], background_color=bg)) def _polar_hack_for_multidigraph(self, A, B, VR): @@ -991,7 +986,6 @@ def _polar_hack_for_multidigraph(self, A, B, VR): sage: GP._polar_hack_for_multidigraph((int(0), int(1)), ....: (int(2), int(2)), .1) ([0.08..., 1.04...], [1.91..., 1.95...]) - """ D = [float(B[i] - A[i]) for i in range(2)] R = sqrt(D[0]**2 + D[1]**2) @@ -1415,7 +1409,7 @@ def plot(self, **kwds): sage: p = graphs.PetersenGraph().plot(egabrag='garbage') Traceback (most recent call last): ... - ValueError: Invalid input 'egabrag=garbage' + ValueError: invalid input 'egabrag=garbage' Make sure that no graphics primitive is clipped:: @@ -1441,7 +1435,7 @@ def plot(self, **kwds): # Check the arguments for o in options: if o not in graphplot_options and o not in G._extra_kwds: - raise ValueError("Invalid input '{}={}'".format(o, options[o])) + raise ValueError("invalid input '{}={}'".format(o, options[o])) for comp in self._plot_components.values(): if not isinstance(comp, list): @@ -1488,13 +1482,12 @@ def layout_tree(self, root, orientation): sage: T = Graph() sage: T.add_edges(G.min_spanning_tree(starting_vertex=0)) sage: T.show(layout='tree', tree_root=0) # indirect doctest - """ T = self._graph if not self._graph.is_tree(): - raise RuntimeError("Cannot use tree layout on this graph: " - "self.is_tree() returns False.") + raise RuntimeError("cannot use tree layout on this graph: " + "self.is_tree() returns False") children = {root: T.neighbors(root)} @@ -1544,7 +1537,7 @@ def slide(v, dx): if x < ox: slide(p, ox - x) x = ox - obstruction[y] = x+1 + obstruction[y] = x + 1 continue t = C.pop() diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index 147e2ba2778..e19c4a8103e 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -135,28 +135,28 @@ * - Apex - - :meth:`~Graph.is_apex()`, - :meth:`~Graph.apex_vertices()` + - :meth:`~sage.graphs.graph.Graph.is_apex`, + :meth:`~sage.graphs.graph.Graph.apex_vertices` * - AT_free - - :meth:`~Graph.is_asteroidal_triple_free` + - :meth:`~sage.graphs.graph.Graph.is_asteroidal_triple_free` * - Biconnected - - :meth:`~Graph.is_biconnected`, - :meth:`~GenericGraph.blocks_and_cut_vertices`, - :meth:`~GenericGraph.blocks_and_cuts_tree` + - :meth:`~sage.graphs.graph.Graph.is_biconnected`, + :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices`, + :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cuts_tree` * - BinaryTrees - :meth:`~sage.graphs.graph_generators.GraphGenerators.BalancedTree`, - :meth:`~Graph.is_tree` + :meth:`~sage.graphs.graph.Graph.is_tree` * - Bipartite - :meth:`~sage.graphs.graph_generators.GraphGenerators.BalancedTree`, - :meth:`~sage.graphs.graph.Graph.is_bipartite` + :meth:`~sage.graphs.generic_graph.GenericGraph.is_bipartite` * - Block @@ -212,7 +212,7 @@ * - Polyhedral - - :meth:`~sage.graphs.generic_graph.Graph.is_polyhedral` + - :meth:`~sage.graphs.graph.Graph.is_polyhedral` * - Split diff --git a/src/sage/graphs/matchpoly.pyx b/src/sage/graphs/matchpoly.pyx index e98cc8d6b63..22361379291 100644 --- a/src/sage/graphs/matchpoly.pyx +++ b/src/sage/graphs/matchpoly.pyx @@ -216,14 +216,14 @@ def matching_polynomial(G, complement=True, name=None): cdef int i, j, d cdef fmpz_poly_t pol - cdef nverts = G.num_verts() + cdef int nverts = G.num_verts() # Using Godsil's duality theorem when the graph is dense if complement and G.density() > 0.5: # this cutoff could probably be tuned f_comp = matching_polynomial(G.complement()).list() f = x.parent().zero() - for i from 0 <= i <= nverts / 2: # implicit floor + for i in range(nverts // 2 + 1): j = nverts - 2 * i f += complete_poly(j) * f_comp[j] * (-1)**i return f diff --git a/src/sage/graphs/planarity.pyx b/src/sage/graphs/planarity.pyx index 206095f00b2..1088a7659de 100644 --- a/src/sage/graphs/planarity.pyx +++ b/src/sage/graphs/planarity.pyx @@ -96,6 +96,7 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False): ....: assert (hasattr(G, '_pos') and G._pos is not None) == set_pos, (set_embedding, set_pos) """ + g._scream_if_not_simple() if set_pos and not g.is_connected(): raise ValueError("is_planar() cannot set vertex positions for a disconnected graph") @@ -118,9 +119,8 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False): # (planarity 3 uses 1-based array indexing, with 0 representing NIL) cdef int i cdef list listto = list(g) - cdef dict ffrom = {vvv: i + 1 for i, vvv in enumerate(listto)} - cdef dict to = {i + 1: vvv for i, vvv in enumerate(listto)} - g.relabel(ffrom) + cdef dict ffrom = {vvv: i for i, vvv in enumerate(listto, start=1)} + cdef dict to = {i: vvv for i, vvv in enumerate(listto, start=1)} cdef graphP theGraph theGraph = gp_New() @@ -129,7 +129,7 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False): if status != OK: raise RuntimeError("gp_InitGraph status is not ok") for u, v in g.edge_iterator(labels=False): - status = gp_AddEdge(theGraph, u, 0, v, 0) + status = gp_AddEdge(theGraph, ffrom[u], 0, ffrom[v], 0) if status == NOTOK: raise RuntimeError("gp_AddEdge status is not ok") elif status == NONEMBEDDABLE: @@ -141,15 +141,16 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False): break status = gp_Embed(theGraph, EMBEDFLAGS_PLANAR) - gp_SortVertices(theGraph) - - # Use to and from mappings to relabel vertices back from the set {1,...,n} - g.relabel(to) if status == NOTOK: raise RuntimeError("status is not ok") - elif status == NONEMBEDDABLE: + + gp_SortVertices(theGraph) + + if status == NONEMBEDDABLE: # Kuratowski subgraph isolator + if not kuratowski: + return False g_dict = {} from sage.graphs.graph import Graph for i in range(1, theGraph.N + 1): @@ -160,29 +161,30 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False): j = theGraph.E[j].link[1] if linked_list: g_dict[to[i]] = linked_list - G = Graph(g_dict) gp_Free(&theGraph) - if kuratowski: - return (False, G) - else: - return False - else: - if set_pos or set_embedding: - emb_dict = {} - for i in range(1, theGraph.N + 1): - linked_list = [] - j = theGraph.V[i].link[1] - while j: - linked_list.append(to[theGraph.E[j].neighbor]) - j = theGraph.E[j].link[1] - emb_dict[to[i]] = linked_list - if set_embedding: - g._embedding = emb_dict - if set_pos: - g.layout(layout='planar', save_pos=True, on_embedding=emb_dict) + G = g.__class__(data=g_dict, weighted=g._weighted, + loops=g.allows_loops(), + multiedges=g.allows_multiple_edges(), + name="Kuratowski subgraph of (%s)" % g.name()) + if g.get_pos(): + G.set_pos({u: g._pos[u] for u in g_dict}) + return (False, G) + + if set_pos or set_embedding: + emb_dict = {} + for i in range(1, theGraph.N + 1): + linked_list = [] + j = theGraph.V[i].link[1] + while j: + linked_list.append(to[theGraph.E[j].neighbor]) + j = theGraph.E[j].link[1] + emb_dict[to[i]] = linked_list + if set_embedding: + g._embedding = emb_dict + if set_pos: + g.layout(layout='planar', save_pos=True, on_embedding=emb_dict) - gp_Free(&theGraph) - if kuratowski: - return (True, None) - else: - return True + gp_Free(&theGraph) + if kuratowski: + return (True, None) + return True diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 08f151a65ad..7576a341701 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -241,6 +241,13 @@ def kruskal(G, by_weight=True, weight_function=None, check_weight=False, check=F Traceback (most recent call last): ... ValueError: the input graph must be undirected + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: E = kruskal(G, by_weight=True) + sage: sum(w for _, _, w in E) + 3 """ return list(kruskal_iterator(G, by_weight=by_weight, weight_function=weight_function, check_weight=check_weight, check=check)) @@ -313,6 +320,13 @@ def kruskal_iterator(G, by_weight=True, weight_function=None, check_weight=False Traceback (most recent call last): ... ValueError: the input graph must be undirected + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: E = list(kruskal_iterator(G, by_weight=True)) + sage: sum(w for _, _, w in E) + 3 """ from sage.graphs.graph import Graph if not isinstance(G, Graph): @@ -382,6 +396,14 @@ def kruskal_iterator_from_edges(edges, union_find, by_weight=True, sage: union_set = DisjointSet(G) sage: next(kruskal_iterator_from_edges(G.edges(sort=False), union_set, by_weight=G.weighted())) (1, 6, 10) + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: union_set = DisjointSet(G) + sage: E = list(kruskal_iterator_from_edges(G.edges(sort=False), union_set, by_weight=True)) + sage: sum(w for _, _, w in E) + 3 """ # We sort edges, as specified. if weight_function is not None: @@ -472,6 +494,15 @@ def filter_kruskal(G, threshold=10000, by_weight=True, weight_function=None, sage: filter_kruskal(Graph(2), check=True) [] + + TESTS: + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: E = filter_kruskal(G, by_weight=True) + sage: sum(w for _, _, w in E) + 3 """ return list(filter_kruskal_iterator(G, threshold=threshold, by_weight=by_weight, weight_function=weight_function, @@ -563,6 +594,13 @@ def filter_kruskal_iterator(G, threshold=10000, by_weight=True, weight_function= sage: len(list(filter_kruskal_iterator(graphs.HouseGraph(), threshold=1))) 4 + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: E = list(filter_kruskal_iterator(G, by_weight=True)) + sage: sum(w for _, _, w in E) + 3 """ from sage.graphs.graph import Graph if not isinstance(G, Graph): @@ -776,6 +814,13 @@ def boruvka(G, by_weight=True, weight_function=None, check_weight=True, check=Fa Traceback (most recent call last): ... ValueError: the input graph must be undirected + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: E = boruvka(G, by_weight=True) + sage: sum(w for _, _, w in E) + 3 """ from sage.graphs.graph import Graph if not isinstance(G, Graph): @@ -985,6 +1030,13 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct Traceback (most recent call last): ... ValueError: works only for non-empty connected graphs + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) + sage: T.is_tree() + True """ from sage.misc.prandom import randint from sage.misc.prandom import random @@ -1113,6 +1165,12 @@ def spanning_trees(g, labels=False): Traceback (most recent call last): ... ValueError: this method is for undirected graphs only + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph([(1, 2, 10), (1, 'a', 1), ('a', 'b', 1), ('b', 2, 1)]) + sage: len(list(G.spanning_trees(labels=False))) + 4 """ from sage.graphs.graph import Graph if not isinstance(g, Graph): @@ -1257,6 +1315,14 @@ def edge_disjoint_spanning_trees(G, k, by_weight=False, weight_function=None, ch Traceback (most recent call last): ... ValueError: this method is for undirected graphs only + + Check that the method is robust to incomparable vertices:: + + sage: G = Graph() + sage: G.add_clique([0, 1, 2, 'a', 'b']) + sage: F = G.edge_disjoint_spanning_trees(k=2) + sage: len(F) + 2 """ if G.is_directed(): raise ValueError("this method is for undirected graphs only") diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index ae7eee6f4ea..25e803cc5d8 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1070,25 +1070,25 @@ def is_polhill(int v, int k, int l, int mu): # We now define the P_{i,j}. see section 6. P = {} - P[0,1] = list(xrange((-1) + 1 , 2**(s-2)+1)) - P[1,1] = list(xrange((-1) + 2**(s-2)+2 , 2**(s-1)+1)) - P[2,1] = list(xrange((-1) + 2**(s-1)+2 , 2**(s-1)+2**(s-2)+1)) - P[3,1] = list(xrange((-1) + 2**(s-1)+2**(s-2)+2, 2**(s)+1)) - - P[0,2] = list(xrange((-1) + 2**(s-2)+2 , 2**(s-1)+2)) - P[1,2] = list(xrange((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+2)) - P[2,2] = list(xrange((-1) + 2**(s-1)+2**(s-2)+3, 2**(s)+1)) + [0] - P[3,2] = list(xrange((-1) + 2 , 2**(s-2)+1)) - - P[0,3] = list(xrange((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+3)) - P[1,3] = list(xrange((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + [0,1] - P[2,3] = list(xrange((-1) + 3 , 2**(s-2)+2)) - P[3,3] = list(xrange((-1) + 2**(s-2)+3 , 2**(s-1)+2)) - - P[0,4] = list(xrange((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) - P[1,4] = list(xrange((-1) + 3 , 2**(s-2)+1)) + [2**(s-1)+1,2**(s-1)+2**(s-2)+2] - P[2,4] = list(xrange((-1) + 2**(s-2)+3 , 2**(s-1)+1)) + [2**(s-1)+2**(s-2)+1,1] - P[3,4] = list(xrange((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+1)) + [2**(s-2)+1,0] + P[0,1] = list(range((-1) + 1 , 2**(s-2)+1)) + P[1,1] = list(range((-1) + 2**(s-2)+2 , 2**(s-1)+1)) + P[2,1] = list(range((-1) + 2**(s-1)+2 , 2**(s-1)+2**(s-2)+1)) + P[3,1] = list(range((-1) + 2**(s-1)+2**(s-2)+2, 2**(s)+1)) + + P[0,2] = list(range((-1) + 2**(s-2)+2 , 2**(s-1)+2)) + P[1,2] = list(range((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+2)) + P[2,2] = list(range((-1) + 2**(s-1)+2**(s-2)+3, 2**(s)+1)) + [0] + P[3,2] = list(range((-1) + 2 , 2**(s-2)+1)) + + P[0,3] = list(range((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+3)) + P[1,3] = list(range((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + [0,1] + P[2,3] = list(range((-1) + 3 , 2**(s-2)+2)) + P[3,3] = list(range((-1) + 2**(s-2)+3 , 2**(s-1)+2)) + + P[0,4] = list(range((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + P[1,4] = list(range((-1) + 3 , 2**(s-2)+1)) + [2**(s-1)+1,2**(s-1)+2**(s-2)+2] + P[2,4] = list(range((-1) + 2**(s-2)+3 , 2**(s-1)+1)) + [2**(s-1)+2**(s-2)+1,1] + P[3,4] = list(range((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+1)) + [2**(s-2)+1,0] R = {x: copy(P[x]) for x in P} @@ -1102,10 +1102,10 @@ def is_polhill(int v, int k, int l, int mu): # We now define the R_{i,j}. see *end* of section 6. - R[0,3] = list(xrange((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+2)) - R[1,3] = list(xrange((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + [0,1,2**(s-1)+2**(s-2)+2] - R[0,4] = list(xrange((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + [2**(s-1)+2**(s-2)+2] - R[1,4] = list(xrange((-1) + 3 , 2**(s-2)+1)) + [2**(s-1)+1] + R[0,3] = list(range((-1) + 2**(s-1)+3 , 2**(s-1)+2**(s-2)+2)) + R[1,3] = list(range((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + [0,1,2**(s-1)+2**(s-2)+2] + R[0,4] = list(range((-1) + 2**(s-1)+2**(s-2)+4, 2**(s)+1)) + [2**(s-1)+2**(s-2)+2] + R[1,4] = list(range((-1) + 3 , 2**(s-2)+1)) + [2**(s-1)+1] for x in R: R[x] = [K[i] for i in R[x]] @@ -2174,7 +2174,7 @@ def SRG_243_110_37_60(): from sage.coding.golay_code import GolayCode M = GolayCode(GF(3), False).generator_matrix() V = list(M.right_kernel()) - g = Graph([list(xrange(len(V))), lambda x, y: (V[x] - V[y]).hamming_weight() == 9]) + g = Graph([list(range(len(V))), lambda x, y: (V[x] - V[y]).hamming_weight() == 9]) g.name('Ternary Golay code') return g @@ -2649,7 +2649,6 @@ def SRG_126_50_13_24(): sage: G.is_strongly_regular(parameters=True) (126, 50, 13, 24) """ - from sage.graphs.strongly_regular_db import SRG_175_72_20_36 from sage.graphs.generators.smallgraphs import HoffmanSingletonGraph hs = HoffmanSingletonGraph() s = set(hs.vertices(sort=False)).difference(hs.neighbors(0) + [0]) diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index efa54bac7d1..a72ad3e180c 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -254,35 +254,38 @@ def word_problem(words, g, verbose=False): EXAMPLES:: - sage: G. = AbelianGroup(3,[2,3,4]); G + sage: # needs sage.libs.gap + sage: G. = AbelianGroup(3, [2,3,4]); G Multiplicative Abelian group isomorphic to C2 x C3 x C4 - sage: w = word_problem([a*b,a*c], b*c); w #random + sage: w = word_problem([a*b,a*c], b*c); w # random [[a*b, 1], [a*c, 1]] sage: prod([x^i for x,i in w]) == b*c True - sage: w = word_problem([a*c,c],a); w #random + sage: w = word_problem([a*c,c], a); w # random [[a*c, 1], [c, -1]] sage: prod([x^i for x,i in w]) == a True - sage: word_problem([a*c,c],a,verbose=True) #random + sage: word_problem([a*c,c], a, verbose=True) # random a = (a*c)^1*(c)^-1 [[a*c, 1], [c, -1]] :: - sage: A. = AbelianGroup(5,[4, 5, 5, 7, 8]) + sage: # needs sage.libs.gap + sage: A. = AbelianGroup(5, [4, 5, 5, 7, 8]) sage: b1 = a^3*b*c*d^2*e^5 sage: b2 = a^2*b*c^2*d^3*e^3 sage: b3 = a^7*b^3*c^5*d^4*e^4 sage: b4 = a^3*b^2*c^2*d^3*e^5 sage: b5 = a^2*b^4*c^2*d^4*e^5 - sage: w = word_problem([b1,b2,b3,b4,b5],e); w #random - [[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1], [a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]] + sage: w = word_problem([b1,b2,b3,b4,b5], e); w # random + [[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1], + [a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]] sage: prod([x^i for x,i in w]) == e True - sage: word_problem([a,b,c,d,e],e) + sage: word_problem([a,b,c,d,e], e) [[e, 1]] - sage: word_problem([a,b,c,d,e],b) + sage: word_problem([a,b,c,d,e], b) [[b, 1]] .. warning:: @@ -413,7 +416,7 @@ def AbelianGroup(n, gens_orders=None, names="f"): a^2*b^2*c^2*d^2 sage: d * b**2 * c**3 b^2*c^3*d - sage: F = AbelianGroup(3,[2]*3); F + sage: F = AbelianGroup(3, [2]*3); F Multiplicative Abelian group isomorphic to C2 x C2 x C2 sage: H = AbelianGroup([2,3], names="xy"); H Multiplicative Abelian group isomorphic to C2 x C3 @@ -447,7 +450,7 @@ def is_AbelianGroup(x): EXAMPLES:: sage: from sage.groups.abelian_gps.abelian_group import is_AbelianGroup - sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")); F + sage: F = AbelianGroup(5,[5,5,7,8,9], names=list("abcde")); F Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9 sage: is_AbelianGroup(F) True @@ -487,9 +490,9 @@ class AbelianGroup_class(UniqueRepresentation, AbelianGroupBase): sage: Z2xZ3.is_isomorphic(Z6) True - sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")); F + sage: F = AbelianGroup(5,[5,5,7,8,9], names=list("abcde")); F Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9 - sage: F = AbelianGroup(5,[2, 4, 12, 24, 120],names = list("abcde")); F + sage: F = AbelianGroup(5,[2, 4, 12, 24, 120], names=list("abcde")); F Multiplicative Abelian group isomorphic to C2 x C4 x C12 x C24 x C120 sage: F.elementary_divisors() (2, 4, 12, 24, 120) @@ -516,7 +519,7 @@ def __init__(self, generator_orders, names, category=None): TESTS:: - sage: G = AbelianGroup([0,5,0,7],names = list("abcd")); G + sage: G = AbelianGroup([0,5,0,7], names=list("abcd")); G Multiplicative Abelian group isomorphic to Z x C5 x Z x C7 sage: TestSuite(G).run() @@ -577,8 +580,8 @@ def is_subgroup(left, right): sage: G.is_subgroup(G) True - sage: H = G.subgroup([G.1]) - sage: H.is_subgroup(G) + sage: H = G.subgroup([G.1]) # needs sage.libs.gap + sage: H.is_subgroup(G) # needs sage.libs.gap True sage: G. = AbelianGroup(2) @@ -654,7 +657,7 @@ def __bool__(self) -> bool: EXAMPLES:: sage: T = AbelianGroup([2, 3]) - sage: bool(T) # indirect doctest + sage: bool(T) # indirect doctest True sage: bool(AbelianGroup([])) False @@ -683,11 +686,11 @@ def dual_group(self, names="X", base_ring=None): EXAMPLES:: sage: G = AbelianGroup([2]) - sage: G.dual_group() + sage: G.dual_group() # needs sage.rings.number_field Dual of Abelian Group isomorphic to Z/2Z over Cyclotomic Field of order 2 and degree 1 - sage: G.dual_group().gens() + sage: G.dual_group().gens() # needs sage.rings.number_field (X,) - sage: G.dual_group(names='Z').gens() + sage: G.dual_group(names='Z').gens() # needs sage.rings.number_field (Z,) sage: G.dual_group(base_ring=QQ) @@ -736,13 +739,13 @@ def elementary_divisors(self): EXAMPLES:: - sage: G = AbelianGroup(2,[2,3]) + sage: G = AbelianGroup(2, [2,3]) sage: G.elementary_divisors() (6,) sage: G = AbelianGroup(1, [6]) sage: G.elementary_divisors() (6,) - sage: G = AbelianGroup(2,[2,6]) + sage: G = AbelianGroup(2, [2,6]) sage: G Multiplicative Abelian group isomorphic to C2 x C6 sage: G.gens_orders() @@ -752,7 +755,7 @@ def elementary_divisors(self): sage: J = AbelianGroup([1,3,5,12]) sage: J.elementary_divisors() (3, 60) - sage: G = AbelianGroup(2,[0,6]) + sage: G = AbelianGroup(2, [0,6]) sage: G.elementary_divisors() (6, 0) sage: AbelianGroup([3,4,5]).elementary_divisors() @@ -845,12 +848,12 @@ def _libgap_(self): EXAMPLES:: sage: G = AbelianGroup([2,3,9]) - sage: libgap(G) + sage: libgap(G) # needs sage.libs.gap The result is cached:: - sage: libgap(G) is libgap(G) + sage: libgap(G) is libgap(G) # needs sage.libs.gap True Requires the optional ``gap_packages`` for infinite groups:: @@ -878,7 +881,7 @@ def _gap_init_(self): sage: G = AbelianGroup([2,3,9]) sage: G._gap_init_() 'AbelianGroup([2, 3, 9])' - sage: gap(G) + sage: gap(G) # needs sage.libs.gap Group( [ f1, f2, f3 ] ) Requires the optional ``gap_packages`` for infinite groups:: @@ -933,10 +936,10 @@ def gens(self): EXAMPLES:: - sage: F = AbelianGroup(5,[3,2],names='abcde') + sage: F = AbelianGroup(5, [3,2], names='abcde') sage: F.gens() (a, b, c, d, e) - sage: [ g.order() for g in F.gens() ] + sage: [g.order() for g in F.gens()] [+Infinity, +Infinity, +Infinity, 3, 2] """ return tuple( self.gen(i) for i in range(self.ngens()) ) @@ -1059,12 +1062,12 @@ def is_cyclic(self): (2, 4) sage: H.is_cyclic() False - sage: H.permutation_group().is_cyclic() + sage: H.permutation_group().is_cyclic() # needs sage.groups False sage: T = AbelianGroup([]) sage: T.is_cyclic() True - sage: T = AbelianGroup(1,[0]); T + sage: T = AbelianGroup(1, [0]); T Multiplicative Abelian group isomorphic to Z sage: T.is_cyclic() True @@ -1094,10 +1097,10 @@ def order(self): EXAMPLES:: - sage: G = AbelianGroup(2,[2,3]) + sage: G = AbelianGroup(2, [2,3]) sage: G.order() 6 - sage: G = AbelianGroup(3,[2,3,0]) + sage: G = AbelianGroup(3, [2,3,0]) sage: G.order() +Infinity """ @@ -1121,7 +1124,7 @@ def permutation_group(self): sage: G = AbelianGroup(2,[2,3]); G Multiplicative Abelian group isomorphic to C2 x C3 - sage: G.permutation_group() + sage: G.permutation_group() # needs sage.groups Permutation Group with generators [(3,4,5), (1,2)] TESTS: @@ -1198,27 +1201,29 @@ def subgroup(self, gensH, names="f"): INPUT: - ``gensH`` -- list of elements which are products of the - generators of the ambient abelian group G = self + generators of the ambient abelian group `G` = ``self`` EXAMPLES:: - sage: G. = AbelianGroup(3, [2,3,4]); G - Multiplicative Abelian group isomorphic to C2 x C3 x C4 - sage: H = G.subgroup([a*b,a]); H - Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a} - sage: H < G - True - sage: F = G.subgroup([a,b^2]) - sage: F - Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2} - sage: F.gens() - (a, b^2) - sage: F = AbelianGroup(5,[30,64,729],names = list("abcde")) - sage: a,b,c,d,e = F.gens() - sage: F.subgroup([a,b]) - Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b} - sage: F.subgroup([c,e]) - Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729 generated by {c, e} + sage: # needs sage.libs.gap + sage: G. = AbelianGroup(3, [2,3,4]); G + Multiplicative Abelian group isomorphic to C2 x C3 x C4 + sage: H = G.subgroup([a*b,a]); H + Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a} + sage: H < G + True + sage: F = G.subgroup([a,b^2]) + sage: F + Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2} + sage: F.gens() + (a, b^2) + sage: F = AbelianGroup(5, [30,64,729], names=list("abcde")) + sage: a,b,c,d,e = F.gens() + sage: F.subgroup([a,b]) + Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b} + sage: F.subgroup([c,e]) + Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729 + generated by {c, e} """ G = self gensH = tuple(gensH) @@ -1327,10 +1332,12 @@ def number_of_subgroups(self, order=None): EXAMPLES:: - sage: AbelianGroup([2,3]).number_of_subgroups() - 4 sage: AbelianGroup([2,0,0,3,0]).number_of_subgroups() +Infinity + + sage: # needs sage.combinat + sage: AbelianGroup([2,3]).number_of_subgroups() + 4 sage: AbelianGroup([2,4,8]).number_of_subgroups() 81 sage: AbelianGroup([2,4,8]).number_of_subgroups(order=4) @@ -1344,6 +1351,7 @@ def number_of_subgroups(self, order=None): TESTS:: + sage: # needs sage.combinat sage: AbelianGroup([]).number_of_subgroups() 1 sage: AbelianGroup([1,3,1]).number_of_subgroups() @@ -1352,7 +1360,7 @@ def number_of_subgroups(self, order=None): 0 sage: AbelianGroup([1,3,1]).number_of_subgroups(order=2) 0 - sage: AbelianGroup([1,3,0,1]).number_of_subgroups(order=3) + sage: AbelianGroup([1,3,0,1]).number_of_subgroups(order=3) # needs sage.libs.gap 1 sage: AbelianGroup([1,3,1]).number_of_subgroups(order=-2) Traceback (most recent call last): @@ -1442,12 +1450,12 @@ def subgroups(self, check=False): EXAMPLES:: - sage: AbelianGroup([2,3]).subgroups() + sage: AbelianGroup([2,3]).subgroups() # needs sage.libs.gap [Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2}, Multiplicative Abelian subgroup isomorphic to C2 generated by {f0}, Multiplicative Abelian subgroup isomorphic to C3 generated by {f1}, Trivial Abelian subgroup] - sage: len(AbelianGroup([2,4,8]).subgroups()) + sage: len(AbelianGroup([2,4,8]).subgroups()) # needs sage.libs.gap 81 TESTS:: @@ -1458,10 +1466,10 @@ def subgroups(self, check=False): Check that :trac:`14196` is fixed:: sage: B = AbelianGroup([1,2]) - sage: B.subgroups() + sage: B.subgroups() # needs sage.libs.gap [Multiplicative Abelian subgroup isomorphic to C2 generated by {f1}, Trivial Abelian subgroup] - sage: B.subgroups(check=True) + sage: B.subgroups(check=True) # needs sage.libs.gap [Multiplicative Abelian subgroup isomorphic to C2 generated by {f1}, Trivial Abelian subgroup] """ @@ -1525,10 +1533,10 @@ def subgroup_reduced(self, elts, verbose=False): EXAMPLES:: sage: G = AbelianGroup([4,4]) - sage: G.subgroup( [ G([1,0]), G([1,2]) ]) + sage: G.subgroup( [ G([1,0]), G([1,2]) ]) # needs sage.libs.gap Multiplicative Abelian subgroup isomorphic to C2 x C4 generated by {f0, f0*f1^2} - sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ]) + sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ]) # needs sage.libs.gap Multiplicative Abelian subgroup isomorphic to C2 x C4 generated by {f0^2*f1^2, f0^3} """ @@ -1559,6 +1567,7 @@ def torsion_subgroup(self, n=None): EXAMPLES:: + sage: # needs sage.libs.gap sage: G = AbelianGroup([2, 3]) sage: G.torsion_subgroup() Multiplicative Abelian subgroup isomorphic to C2 x C3 generated @@ -1577,7 +1586,7 @@ def torsion_subgroup(self, n=None): :: sage: G = AbelianGroup([2, 2*3, 2*3*5, 0, 2*3*5*7, 2*3*5*7*11]) - sage: G.torsion_subgroup(5) + sage: G.torsion_subgroup(5) # needs sage.libs.gap Multiplicative Abelian subgroup isomorphic to C5 x C5 x C5 generated by {f2^6, f4^42, f5^462} """ if n is None: @@ -1610,7 +1619,8 @@ def __init__(self, ambient, gens, names="f", category=None): """ EXAMPLES:: - sage: F = AbelianGroup(5,[30,64,729],names = list("abcde")) + sage: # needs sage.libs.gap + sage: F = AbelianGroup(5, [30,64,729], names=list("abcde")) sage: a,b,c,d,e = F.gens() sage: F.subgroup([a^3,b]) Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a^3, b} @@ -1622,11 +1632,11 @@ def __init__(self, ambient, gens, names="f", category=None): Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b*c} sage: F.subgroup([b*c, d]) Multiplicative Abelian subgroup isomorphic to C64 x Z generated by {b*c, d} - sage: F.subgroup([a*b, c^6, d],names=list("xyz")) + sage: F.subgroup([a*b, c^6, d], names=list("xyz")) Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d} sage: H. = F.subgroup([a*b, c^6, d]); H Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d} - sage: G = F.subgroup([a*b, c^6, d],names = list("xyz")); G + sage: G = F.subgroup([a*b, c^6, d], names=list("xyz")); G Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d} sage: x,y,z = G.gens() sage: x.order() @@ -1635,7 +1645,7 @@ def __init__(self, ambient, gens, names="f", category=None): 5 sage: z.order() 64 - sage: A = AbelianGroup(5,[3, 5, 5, 7, 8], names = "abcde") + sage: A = AbelianGroup(5, [3, 5, 5, 7, 8], names="abcde") sage: a,b,c,d,e = A.gens() sage: A.subgroup([a,b]) Multiplicative Abelian subgroup isomorphic to C3 x C5 generated by {a, b} @@ -1647,7 +1657,7 @@ def __init__(self, ambient, gens, names="f", category=None): Multiplicative Abelian subgroup isomorphic to C4 x C5 x C5 x C7 generated by {b, c, d, e^2} sage: B.gens_orders() (4, 5, 5, 7) - sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names = "abcd") + sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names="abcd") sage: a,b,c,d = A.gens() sage: B = A.subgroup([a^3,b,c,d]) sage: B.gens_orders() @@ -1656,7 +1666,7 @@ def __init__(self, ambient, gens, names="f", category=None): 24266473210027 sage: B.order() 24266473210027 - sage: A = AbelianGroup(4,[1008, 2003, 3001, 4001], names = "abcd") + sage: A = AbelianGroup(4, [1008, 2003, 3001, 4001], names="abcd") sage: a,b,c,d = A.gens() sage: B = A.subgroup([a^3,b,c,d]); B Multiplicative Abelian subgroup isomorphic @@ -1664,23 +1674,25 @@ def __init__(self, ambient, gens, names="f", category=None): Infinite groups can also be handled:: - sage: G = AbelianGroup([3,4,0], names = "abc") + sage: G = AbelianGroup([3,4,0], names="abc") sage: a,b,c = G.gens() - sage: F = G.subgroup([a, b^2, c]); F - Multiplicative Abelian subgroup isomorphic to C2 x C3 x Z generated by {a, b^2, c} + sage: F = G.subgroup([a, b^2, c]); F # needs sage.libs.gap + Multiplicative Abelian subgroup isomorphic to C2 x C3 x Z + generated by {a, b^2, c} - sage: F.gens_orders() + sage: F.gens_orders() # needs sage.libs.gap (2, 3, 0) - sage: F.gens() + sage: F.gens() # needs sage.libs.gap (a, b^2, c) - sage: F.order() + sage: F.order() # needs sage.libs.gap +Infinity Testing issue :trac:`18863`:: sage: G = AbelianGroup(5,[2]) - sage: G.subgroup([prod(g^k for g,k in zip(G.gens(),[1,-2,3,-4,5]))]) - Multiplicative Abelian subgroup isomorphic to Z generated by {f0*f1^-2*f2^3*f3^-4*f4} + sage: G.subgroup([prod(g^k for g,k in zip(G.gens(),[1,-2,3,-4,5]))]) # needs sage.libs.gap + Multiplicative Abelian subgroup isomorphic to Z + generated by {f0*f1^-2*f2^3*f3^-4*f4} """ from sage.libs.gap.libgap import libgap if not isinstance(ambient, AbelianGroup_class): @@ -1713,10 +1725,10 @@ def __contains__(self, x): EXAMPLES:: sage: G. = AbelianGroup(2) - sage: A = G.subgroup([a]) + sage: A = G.subgroup([a]) # needs sage.libs.gap sage: a in G True - sage: a in A + sage: a in A # needs sage.libs.gap True TESTS: @@ -1725,22 +1737,22 @@ def __contains__(self, x): sage: G. = AbelianGroup(2, [4, 576]) sage: Hgens = [a^2, a*b^2] - sage: H = G.subgroup(Hgens) - sage: [g in H for g in (a^3, b^2, b^3, a^3*b^2, "junk")] + sage: H = G.subgroup(Hgens) # needs sage.libs.gap + sage: [g in H for g in (a^3, b^2, b^3, a^3*b^2, "junk")] # needs sage.libs.gap [False, False, False, True, False] Check that :trac:`31507` is fixed:: sage: G = AbelianGroup(2, gens_orders=[16, 16]) sage: f0, f1 = G.gens() - sage: H = G.subgroup([f0*f1^3]) - sage: [g in H for g in (f0, f0*f1^2, f0*f1^3, f0*f1^4)] + sage: H = G.subgroup([f0*f1^3]) # needs sage.libs.gap + sage: [g in H for g in (f0, f0*f1^2, f0*f1^3, f0*f1^4)] # needs sage.libs.gap [False, False, True, False] sage: G. = AbelianGroup(2) sage: Hgens = [a*b, a*b^-1] - sage: H = G.subgroup(Hgens) - sage: b^2 in H + sage: H = G.subgroup(Hgens) # needs sage.libs.gap + sage: b^2 in H # needs sage.libs.gap True """ if not isinstance(x, AbelianGroupElement): @@ -1769,8 +1781,8 @@ def ambient_group(self): EXAMPLES:: sage: G. = AbelianGroup([2,3,4]) - sage: H = G.subgroup([a, b^2]) - sage: H.ambient_group() is G + sage: H = G.subgroup([a, b^2]) # needs sage.libs.gap + sage: H.ambient_group() is G # needs sage.libs.gap True """ return self._ambient_group @@ -1795,15 +1807,16 @@ def equals(left, right): sage: G = AbelianGroup(3, [2,3,4], names="abc"); G Multiplicative Abelian group isomorphic to C2 x C3 x C4 sage: a,b,c = G.gens() - sage: F = G.subgroup([a,b^2]); F + sage: F = G.subgroup([a,b^2]); F # needs sage.libs.gap Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2} - sage: F = AbelianGroup(2) sage: A = G.subgroup([a]) sage: B = G.subgroup([b]) @@ -1835,8 +1848,8 @@ def _repr_(self): sage: G. = AbelianGroup(2) sage: G._repr_() 'Multiplicative Abelian group isomorphic to Z x Z' - sage: A = G.subgroup([a]) - sage: A._repr_() + sage: A = G.subgroup([a]) # needs sage.libs.gap + sage: A._repr_() # needs sage.libs.gap 'Multiplicative Abelian subgroup isomorphic to Z generated by {a}' """ eldv = self._abinvs @@ -1859,10 +1872,10 @@ def gens(self): EXAMPLES:: sage: G. = AbelianGroup(2) - sage: A = G.subgroup([a]) + sage: A = G.subgroup([a]) # needs sage.libs.gap sage: G.gens() (a, b) - sage: A.gens() + sage: A.gens() # needs sage.libs.gap (a,) """ return self._gens @@ -1874,11 +1887,12 @@ def gen(self, n): EXAMPLES:: sage: G. = AbelianGroup(2) - sage: A = G.subgroup([a]) - sage: A.gen(0) + sage: A = G.subgroup([a]) # needs sage.libs.gap + sage: A.gen(0) # needs sage.libs.gap a """ return self._gens[n] + # We allow subclasses to override this, analogous to Element AbelianGroup_class.Subgroup = AbelianGroup_subgroup diff --git a/src/sage/groups/abelian_gps/abelian_group_element.py b/src/sage/groups/abelian_gps/abelian_group_element.py index 1b0c9cd590c..6ae81844f98 100644 --- a/src/sage/groups/abelian_gps/abelian_group_element.py +++ b/src/sage/groups/abelian_gps/abelian_group_element.py @@ -97,16 +97,16 @@ def as_permutation(self): EXAMPLES:: - sage: G = AbelianGroup(3,[2,3,4],names="abc"); G + sage: G = AbelianGroup(3, [2,3,4], names="abc"); G Multiplicative Abelian group isomorphic to C2 x C3 x C4 sage: a,b,c = G.gens() - sage: Gp = G.permutation_group(); Gp + sage: Gp = G.permutation_group(); Gp # needs sage.groups Permutation Group with generators [(6,7,8,9), (3,4,5), (1,2)] - sage: a.as_permutation() + sage: a.as_permutation() # needs sage.libs.gap (1,2) - sage: ap = a.as_permutation(); ap + sage: ap = a.as_permutation(); ap # needs sage.libs.gap (1,2) - sage: ap in Gp + sage: ap in Gp # needs sage.groups sage.libs.gap True """ from sage.libs.gap.libgap import libgap @@ -138,13 +138,14 @@ def word_problem(self, words): EXAMPLES:: - sage: G = AbelianGroup(2,[2,3], names="xy") + sage: # needs sage.libs.gap + sage: G = AbelianGroup(2, [2,3], names="xy") sage: x,y = G.gens() sage: x.word_problem([x,y]) [[x, 1]] sage: y.word_problem([x,y]) [[y, 1]] - sage: v = (y*x).word_problem([x,y]); v #random + sage: v = (y*x).word_problem([x,y]); v # random [[x, 1], [y, 1]] sage: prod([x^i for x,i in v]) == y*x True diff --git a/src/sage/groups/abelian_gps/dual_abelian_group.py b/src/sage/groups/abelian_gps/dual_abelian_group.py index 2d5441daaca..2ee86f7f423 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group.py @@ -25,6 +25,7 @@ sage: F = AbelianGroup(5, [2,5,7,8,9], names='abcde') sage: (a, b, c, d, e) = F.gens() + sage: # needs sage.rings.number_field sage: Fd = F.dual_group(names='ABCDE') sage: Fd.base_ring() Cyclotomic Field of order 2520 and degree 576 @@ -34,6 +35,7 @@ sage: A(b), A(c), A(d), A(e) (1, 1, 1, 1) + sage: # needs sage.rings.real_mpfr sage: Fd = F.dual_group(names='ABCDE', base_ring=CC) sage: A,B,C,D,E = Fd.gens() sage: A(a) # abs tol 1e-8 @@ -78,6 +80,7 @@ def is_DualAbelianGroup(x): EXAMPLES:: + sage: # needs sage.rings.number_field sage: from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroup sage: F = AbelianGroup(5,[3,5,7,8,9], names=list("abcde")) sage: Fd = F.dual_group() @@ -100,11 +103,12 @@ class DualAbelianGroup_class(UniqueRepresentation, AbelianGroupBase): EXAMPLES:: sage: F = AbelianGroup(5,[3,5,7,8,9], names="abcde") - sage: F.dual_group() + sage: F.dual_group() # needs sage.rings.number_field Dual of Abelian Group isomorphic to Z/3Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z over Cyclotomic Field of order 2520 and degree 576 + sage: F = AbelianGroup(4,[15,7,8,9], names="abcd") - sage: F.dual_group(base_ring=CC) + sage: F.dual_group(base_ring=CC) # needs sage.rings.real_mpfr Dual of Abelian Group isomorphic to Z/15Z x Z/7Z x Z/8Z x Z/9Z over Complex Field with 53 bits of precision """ @@ -117,7 +121,7 @@ def __init__(self, G, names, base_ring): EXAMPLES:: sage: F = AbelianGroup(5,[3,5,7,8,9], names="abcde") - sage: F.dual_group() + sage: F.dual_group() # needs sage.rings.number_field Dual of Abelian Group isomorphic to Z/3Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z over Cyclotomic Field of order 2520 and degree 576 """ @@ -174,12 +178,13 @@ def _repr_(self): EXAMPLES:: sage: F = AbelianGroup(5, [2,5,7,8,9], names='abcde') - sage: Fd = F.dual_group(names='ABCDE', base_ring=CyclotomicField(2*5*7*8*9)) - sage: Fd # indirect doctest + sage: Fd = F.dual_group(names='ABCDE', # needs sage.rings.number_field + ....: base_ring=CyclotomicField(2*5*7*8*9)) + sage: Fd # indirect doctest # needs sage.rings.number_field Dual of Abelian Group isomorphic to Z/2Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z over Cyclotomic Field of order 5040 and degree 1152 - sage: Fd = F.dual_group(names='ABCDE', base_ring=CC) - sage: Fd + sage: Fd = F.dual_group(names='ABCDE', base_ring=CC) # needs sage.rings.real_mpfr + sage: Fd # needs sage.rings.real_mpfr Dual of Abelian Group isomorphic to Z/2Z x Z/5Z x Z/7Z x Z/8Z x Z/9Z over Complex Field with 53 bits of precision """ @@ -202,8 +207,8 @@ def _latex_(self): EXAMPLES:: sage: F = AbelianGroup(3, [2]*3) - sage: Fd = F.dual_group() - sage: Fd._latex_() + sage: Fd = F.dual_group() # needs sage.rings.number_field + sage: Fd._latex_() # needs sage.rings.number_field '$\\mathrm{DualAbelianGroup}( AbelianGroup ( 3, (2, 2, 2) ) )$' """ return r"$\mathrm{DualAbelianGroup}( AbelianGroup ( %s, %s ) )$" % (self.ngens(), self.gens_orders()) @@ -215,12 +220,13 @@ def random_element(self): EXAMPLES:: sage: G = AbelianGroup([2,3,9]) - sage: Gd = G.dual_group(base_ring=CC) - sage: Gd.random_element().parent() is Gd + sage: Gd = G.dual_group(base_ring=CC) # needs sage.rings.real_mpfr + sage: Gd.random_element().parent() is Gd # needs sage.rings.real_mpfr True - sage: N = 43^2-1 - sage: G = AbelianGroup([N],names="a") + sage: # needs sage.rings.real_mpfr + sage: N = 43^2 - 1 + sage: G = AbelianGroup([N], names="a") sage: Gd = G.dual_group(names="A", base_ring=CC) sage: a, = G.gens() sage: A, = Gd.gens() @@ -243,7 +249,8 @@ def gen(self, i=0): EXAMPLES:: - sage: F = AbelianGroup(3,[1,2,3],names='a') + sage: # needs sage.rings.number_field + sage: F = AbelianGroup(3, [1,2,3], names='a') sage: Fd = F.dual_group(names="A") sage: Fd.0 1 @@ -270,8 +277,8 @@ def gens(self): EXAMPLES:: - sage: F = AbelianGroup([7,11]).dual_group() - sage: F.gens() + sage: F = AbelianGroup([7,11]).dual_group() # needs sage.rings.number_field + sage: F.gens() # needs sage.rings.number_field (X0, X1) """ n = self.group().ngens() @@ -284,8 +291,8 @@ def ngens(self): EXAMPLES:: sage: F = AbelianGroup([7]*100) - sage: Fd = F.dual_group() - sage: Fd.ngens() + sage: Fd = F.dual_group() # needs sage.rings.number_field + sage: Fd.ngens() # needs sage.rings.number_field 100 """ return self.group().ngens() @@ -301,8 +308,8 @@ def gens_orders(self): EXAMPLES:: sage: F = AbelianGroup([5]*1000) - sage: Fd = F.dual_group() - sage: invs = Fd.gens_orders(); len(invs) + sage: Fd = F.dual_group() # needs sage.rings.number_field + sage: invs = Fd.gens_orders(); len(invs) # needs sage.rings.number_field 1000 """ return self.group().gens_orders() @@ -316,8 +323,8 @@ def invariants(self): EXAMPLES:: sage: F = AbelianGroup([5]*1000) - sage: Fd = F.dual_group() - sage: invs = Fd.gens_orders(); len(invs) + sage: Fd = F.dual_group() # needs sage.rings.number_field + sage: invs = Fd.gens_orders(); len(invs) # needs sage.rings.number_field 1000 """ # TODO: deprecate @@ -331,9 +338,9 @@ def __contains__(self, X): sage: F = AbelianGroup(5,[2, 3, 5, 7, 8], names="abcde") sage: a,b,c,d,e = F.gens() - sage: Fd = F.dual_group(names = "ABCDE") - sage: A,B,C,D,E = Fd.gens() - sage: A*B^2*D^7 in Fd + sage: Fd = F.dual_group(names="ABCDE") # needs sage.rings.number_field + sage: A,B,C,D,E = Fd.gens() # needs sage.rings.number_field + sage: A*B^2*D^7 in Fd # needs sage.rings.number_field True """ return X.parent() == self and is_DualAbelianGroupElement(X) @@ -345,8 +352,8 @@ def order(self): EXAMPLES:: sage: G = AbelianGroup([2,3,9]) - sage: Gd = G.dual_group() - sage: Gd.order() + sage: Gd = G.dual_group() # needs sage.rings.number_field + sage: Gd.order() # needs sage.rings.number_field 54 """ G = self.group() @@ -359,10 +366,10 @@ def is_commutative(self): EXAMPLES:: sage: G = AbelianGroup([2,3,9]) - sage: Gd = G.dual_group() - sage: Gd.is_commutative() + sage: Gd = G.dual_group() # needs sage.rings.number_field + sage: Gd.is_commutative() # needs sage.rings.number_field True - sage: Gd.is_abelian() + sage: Gd.is_abelian() # needs sage.rings.number_field True """ return True @@ -375,8 +382,8 @@ def list(self): EXAMPLES:: sage: G = AbelianGroup([2,3], names="ab") - sage: Gd = G.dual_group(names="AB") - sage: Gd.list() + sage: Gd = G.dual_group(names="AB") # needs sage.rings.number_field + sage: Gd.list() # needs sage.rings.number_field (1, B, B^2, A, A*B, A*B^2) """ if not self.is_finite(): @@ -391,18 +398,21 @@ def __iter__(self): EXAMPLES:: sage: G = AbelianGroup([2,3], names="ab") - sage: Gd = G.dual_group(names="AB") - sage: [X for X in Gd] + sage: Gd = G.dual_group(names="AB") # needs sage.rings.number_field + sage: [X for X in Gd] # needs sage.rings.number_field [1, B, B^2, A, A*B, A*B^2] - sage: N = 43^2-1 - sage: G = AbelianGroup([N],names="a") + + sage: # needs sage.rings.real_mpfr + sage: N = 43^2 - 1 + sage: G = AbelianGroup([N], names="a") sage: Gd = G.dual_group(names="A", base_ring=CC) sage: a, = G.gens() sage: A, = Gd.gens() sage: x = a^(N/4) sage: y = a^(N/3) sage: z = a^(N/14) - sage: len([X for X in Gd if abs(X(x)-1)>0.01 and abs(X(y)-1)>0.01 and abs(X(z)-1)>0.01]) + sage: len([X for X in Gd + ....: if abs(X(x)-1)>0.01 and abs(X(y)-1)>0.01 and abs(X(z)-1)>0.01]) 880 """ yield from self.list() 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 685e4355780..407323d4f34 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -8,13 +8,13 @@ sage: F Multiplicative Abelian group isomorphic to C2 x C3 x C5 x C7 x C8 - sage: Fd = F.dual_group(names="ABCDE") - sage: Fd + sage: Fd = F.dual_group(names="ABCDE"); Fd # needs sage.rings.number_field Dual of Abelian Group isomorphic to Z/2Z x Z/3Z x Z/5Z x Z/7Z x Z/8Z over Cyclotomic Field of order 840 and degree 192 The elements of the dual group can be evaluated on elements of the original group:: + sage: # needs sage.rings.number_field sage: a,b,c,d,e = F.gens() sage: A,B,C,D,E = Fd.gens() sage: A*B^2*D^7 @@ -71,10 +71,10 @@ def is_DualAbelianGroupElement(x) -> bool: EXAMPLES:: sage: from sage.groups.abelian_gps.dual_abelian_group import is_DualAbelianGroupElement - sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")).dual_group() - sage: is_DualAbelianGroupElement(F) + sage: F = AbelianGroup(5, [5,5,7,8,9], names=list("abcde")).dual_group() # needs sage.rings.number_field + sage: is_DualAbelianGroupElement(F) # needs sage.rings.number_field False - sage: is_DualAbelianGroupElement(F.an_element()) + sage: is_DualAbelianGroupElement(F.an_element()) # needs sage.rings.number_field True """ return isinstance(x, DualAbelianGroupElement) @@ -96,6 +96,7 @@ def __call__(self, g): EXAMPLES:: + sage: # needs sage.rings.number_field sage: F = AbelianGroup(5, [2,3,5,7,8], names="abcde") sage: a,b,c,d,e = F.gens() sage: Fd = F.dual_group(names="ABCDE") @@ -117,7 +118,7 @@ def __call__(self, g): sage: a, = F.gens() sage: Fd = F.dual_group(names="A", base_ring=GF(29)) sage: A, = Fd.gens() - sage: A(a) + sage: A(a) # needs sage.libs.pari 16 """ F = self.parent().base_ring() @@ -146,7 +147,8 @@ def word_problem(self, words): EXAMPLES:: - sage: G = AbelianGroup(5,[3, 5, 5, 7, 8],names="abcde") + sage: # needs sage.rings.number_field + sage: G = AbelianGroup(5,[3, 5, 5, 7, 8], names="abcde") sage: Gd = G.dual_group(names="abcde") sage: a,b,c,d,e = Gd.gens() sage: u = a^3*b*c*d^2*e^5 diff --git a/src/sage/groups/abelian_gps/element_base.py b/src/sage/groups/abelian_gps/element_base.py index 00abd05eb8c..6a46bd7f444 100644 --- a/src/sage/groups/abelian_gps/element_base.py +++ b/src/sage/groups/abelian_gps/element_base.py @@ -48,9 +48,9 @@ class AbelianGroupElementBase(MultiplicativeGroupElement): EXAMPLES:: sage: F = AbelianGroup(3,[7,8,9]) - sage: Fd = F.dual_group(names="ABC") - sage: A,B,C = Fd.gens() - sage: A*B^-1 in Fd + sage: Fd = F.dual_group(names="ABC") # needs sage.rings.number_field + sage: A,B,C = Fd.gens() # needs sage.rings.number_field + sage: A*B^-1 in Fd # needs sage.rings.number_field True """ @@ -61,9 +61,9 @@ def __init__(self, parent, exponents): EXAMPLES:: sage: F = AbelianGroup(3,[7,8,9]) - sage: Fd = F.dual_group(names="ABC") - sage: A,B,C = Fd.gens() - sage: A*B^-1 in Fd + sage: Fd = F.dual_group(names="ABC") # needs sage.rings.number_field + sage: A,B,C = Fd.gens() # needs sage.rings.number_field + sage: A*B^-1 in Fd # needs sage.rings.number_field True Check that :issue:`35216` is fixed:: @@ -125,7 +125,7 @@ def _libgap_(self): TESTS:: sage: F. = AbelianGroup([7,8,9]) - sage: libgap(a**2 * c) * libgap(b * c**2) + sage: libgap(a**2 * c) * libgap(b * c**2) # needs sage.libs.gap f1^2*f2*f6 """ from sage.misc.misc_c import prod @@ -147,6 +147,7 @@ def list(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: F = AbelianGroup(5,[2, 3, 5, 7, 8], names="abcde") sage: a,b,c,d,e = F.gens() sage: Ad = F.dual_group(names="ABCDE") @@ -208,8 +209,8 @@ def _richcmp_(self, other, op): sage: a > b True - sage: Gd. = G.dual_group() - sage: A > B + sage: Gd. = G.dual_group() # needs sage.rings.number_field + sage: A > B # needs sage.rings.number_field True """ return richcmp(self._exponents, other._exponents, op) @@ -226,9 +227,9 @@ def order(self): EXAMPLES:: sage: F = AbelianGroup(3,[7,8,9]) - sage: Fd = F.dual_group() - sage: A,B,C = Fd.gens() - sage: (B*C).order() + sage: Fd = F.dual_group() # needs sage.rings.number_field + sage: A,B,C = Fd.gens() # needs sage.rings.number_field + sage: (B*C).order() # needs sage.rings.number_field 72 sage: F = AbelianGroup(3,[7,8,9]); F diff --git a/src/sage/groups/abelian_gps/values.py b/src/sage/groups/abelian_gps/values.py index e476176cb7d..3db117123f0 100644 --- a/src/sage/groups/abelian_gps/values.py +++ b/src/sage/groups/abelian_gps/values.py @@ -48,6 +48,7 @@ :meth:`~AbelianGroupWithValues_class.values_group`, so you can use the group elements instead of the values:: + sage: # needs sage.rings.number_field sage: CF3. = CyclotomicField(3) sage: Z3. = AbelianGroupWithValues([zeta], [3]) sage: Z3.values_group() @@ -159,6 +160,7 @@ class AbelianGroupWithValuesEmbedding(Morphism): EXAMPLES:: + sage: # needs sage.symbolic sage: Z4. = AbelianGroupWithValues([I], [4]) sage: embedding = Z4.values_embedding(); embedding Generic morphism: @@ -178,9 +180,9 @@ def __init__(self, domain, codomain): TESTS:: - sage: Z4 = AbelianGroupWithValues([I], [4]) + sage: Z4 = AbelianGroupWithValues([I], [4]) # needs sage.symbolic sage: from sage.groups.abelian_gps.values import AbelianGroupWithValuesEmbedding - sage: AbelianGroupWithValuesEmbedding(Z4, Z4.values_group()) + sage: AbelianGroupWithValuesEmbedding(Z4, Z4.values_group()) # needs sage.symbolic Generic morphism: From: Multiplicative Abelian group isomorphic to C4 To: Number Field in I with defining polynomial x^2 + 1 with I = 1*I @@ -203,6 +205,7 @@ def _call_(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: Z4. = AbelianGroupWithValues([I], [4]) sage: embedding = Z4.values_embedding() sage: embedding(g) @@ -417,7 +420,7 @@ def gen(self, i=0): EXAMPLES:: - sage: F = AbelianGroupWithValues([1,2,3,4,5], 5,[],names='a') + sage: F = AbelianGroupWithValues([1,2,3,4,5], 5, [], names='a') sage: F.0 a0 sage: F.0.value() @@ -473,8 +476,8 @@ def values_group(self): sage: G.values_group() Integer Ring - sage: Z4 = AbelianGroupWithValues([I], [4]) - sage: Z4.values_group() + sage: Z4 = AbelianGroupWithValues([I], [4]) # needs sage.symbolic + sage: Z4.values_group() # needs sage.symbolic Number Field in I with defining polynomial x^2 + 1 with I = 1*I """ return self._values_group @@ -489,8 +492,8 @@ def values_embedding(self): EXAMPLES:: - sage: Z4 = AbelianGroupWithValues([I], [4]) - sage: Z4.values_embedding() + sage: Z4 = AbelianGroupWithValues([I], [4]) # needs sage.symbolic + sage: Z4.values_embedding() # needs sage.symbolic Generic morphism: From: Multiplicative Abelian group isomorphic to C4 To: Number Field in I with defining polynomial x^2 + 1 with I = 1*I diff --git a/src/sage/groups/additive_abelian/additive_abelian_group.py b/src/sage/groups/additive_abelian/additive_abelian_group.py index de8c4a41656..358302ffd13 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_group.py +++ b/src/sage/groups/additive_abelian/additive_abelian_group.py @@ -450,7 +450,7 @@ def permutation_group(self): EXAMPLES:: sage: G = AdditiveAbelianGroup([2, 3]) - sage: G.permutation_group() + sage: G.permutation_group() # needs sage.groups Permutation Group with generators [(3,4,5), (1,2)] TESTS: diff --git a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py index 5d211f6383b..2a7496cb215 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py +++ b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py @@ -11,10 +11,10 @@ We create a toy example based on the Mordell-Weil group of an elliptic curve over `\QQ`:: + sage: # needs sage.schemes sage: E = EllipticCurve('30a2') sage: pts = [E(4,-7,1), E(7/4, -11/8, 1), E(3, -2, 1)] - sage: M = AdditiveAbelianGroupWrapper(pts[0].parent(), pts, [3, 2, 2]) - sage: M + sage: M = AdditiveAbelianGroupWrapper(pts[0].parent(), pts, [3, 2, 2]); M Additive abelian group isomorphic to Z/3 + Z/2 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - 19*x + 26 over Rational Field @@ -24,7 +24,7 @@ (0 : 1 : 0) sage: 3000000000000001 * M.0 (4 : -7 : 1) - sage: M == loads(dumps(M)) # known bug, see https://github.com/sagemath/sage/issues/11599#comment:7 + sage: M == loads(dumps(M)) # known bug (https://github.com/sagemath/sage/issues/11599#comment:7) True TESTS: @@ -33,7 +33,7 @@ sage: from sage.misc.verbose import set_verbose sage: set_verbose(2, 'additive_abelian_wrapper.py') - sage: 300001 * M.0 + sage: 300001 * M.0 # needs sage.schemes verbose 1 (...: additive_abelian_wrapper.py, discrete_exp) Calling discrete exp on (1, 0, 0) (4 : -7 : 1) sage: set_verbose(0, 'additive_abelian_wrapper.py') @@ -85,12 +85,13 @@ def __init__(self, domain): r""" EXAMPLES:: - sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) - sage: F = QQbar.coerce_map_from(G); F + sage: G = AdditiveAbelianGroupWrapper(QQbar, # needs sage.rings.number_field + ....: [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) + sage: F = QQbar.coerce_map_from(G); F # needs sage.rings.number_field Generic morphism: From: Additive abelian group isomorphic to Z + Z embedded in Algebraic Field To: Algebraic Field - sage: type(F) + sage: type(F) # needs sage.rings.number_field """ Morphism.__init__(self, domain.Hom(domain.universe())) @@ -99,13 +100,14 @@ def _call_(self, x): r""" TESTS:: + sage: # needs sage.schemes sage: E = EllipticCurve("65a1") sage: G = E.torsion_subgroup() sage: isinstance(G, sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapper) True sage: P1 = E([1,-1,1]) sage: P2 = E([0,1,0]) - sage: P1 in G # indirect doctest + sage: P1 in G # indirect doctest False sage: P2 in G True @@ -127,8 +129,9 @@ def __init__(self, parent, vector, element=None, check=False): EXAMPLES:: sage: from sage.groups.additive_abelian.additive_abelian_wrapper import AdditiveAbelianGroupWrapper - sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) - sage: G.0 # indirect doctest + sage: G = AdditiveAbelianGroupWrapper(QQbar, # needs sage.rings.number_field + ....: [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) + sage: G.0 # indirect doctest # needs sage.rings.number_field 1.414213562373095? """ addgp.AdditiveAbelianGroupElement.__init__(self, parent, vector, check) @@ -142,11 +145,11 @@ def element(self): EXAMPLES:: - sage: T = EllipticCurve('65a').torsion_subgroup().gen(0) - sage: T; type(T) + sage: T = EllipticCurve('65a').torsion_subgroup().gen(0) # needs sage.schemes + sage: T; type(T) # needs sage.schemes (0 : 0 : 1) - sage: T.element(); type(T.element()) + sage: T.element(); type(T.element()) # needs sage.schemes (0 : 0 : 1) """ @@ -160,8 +163,8 @@ def _repr_(self): EXAMPLES:: - sage: T = EllipticCurve('65a').torsion_subgroup().gen(0) - sage: repr(T) # indirect doctest + sage: T = EllipticCurve('65a').torsion_subgroup().gen(0) # needs sage.schemes + sage: repr(T) # indirect doctest # needs sage.schemes '(0 : 0 : 1)' """ return repr(self.element()) @@ -179,19 +182,22 @@ class AdditiveAbelianGroupWrapper(addgp.AdditiveAbelianGroup_fixed_gens): sage: G6 = AdditiveAbelianGroupWrapper(Zmod(42), [6], [7]); G6 Additive abelian group isomorphic to Z/7 embedded in Ring of integers modulo 42 sage: G = AdditiveAbelianGroupWrapper(Zmod(42), [21,14,6], [2,3,7]); G - Additive abelian group isomorphic to Z/2 + Z/3 + Z/7 embedded in Ring of integers modulo 42 + Additive abelian group isomorphic to Z/2 + Z/3 + Z/7 embedded in + Ring of integers modulo 42 sage: G.invariants() (42,) :: - sage: AdditiveAbelianGroupWrapper(QQbar, [sqrt(2), sqrt(3)], [0, 0]) + sage: AdditiveAbelianGroupWrapper(QQbar, [sqrt(2), sqrt(3)], [0, 0]) # needs sage.rings.number_field sage.symbolic Additive abelian group isomorphic to Z + Z embedded in Algebraic Field :: - sage: EllipticCurve(GF(419**2), [1,0]).abelian_group() # indirect doctest - Additive abelian group isomorphic to Z/420 + Z/420 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2 + sage: EllipticCurve(GF(419**2), [1,0]).abelian_group() # indirect doctest # needs sage.rings.finite_rings sage.schemes + Additive abelian group isomorphic to Z/420 + Z/420 embedded in + Abelian group of points on Elliptic Curve + defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2 """ Element = AdditiveAbelianGroupWrapperElement @@ -200,7 +206,8 @@ def __init__(self, universe, gens, invariants): r""" EXAMPLES:: - sage: AdditiveAbelianGroupWrapper(QQbar, [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) # indirect doctest + sage: AdditiveAbelianGroupWrapper(QQbar, # indirect doctest # needs sage.rings.number_field + ....: [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) Additive abelian group isomorphic to Z + Z embedded in Algebraic Field """ self._universe = universe @@ -217,8 +224,10 @@ def universe(self): EXAMPLES:: - sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) - sage: G.universe() + sage: G = AdditiveAbelianGroupWrapper(QQbar, # needs sage.rings.number_field + ....: [sqrt(QQbar(2)), sqrt(QQbar(3))], + ....: [0, 0]) + sage: G.universe() # needs sage.rings.number_field Algebraic Field """ return self._universe @@ -246,8 +255,9 @@ def _repr_(self): r""" EXAMPLES:: - sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) - sage: repr(G) # indirect doctest + sage: G = AdditiveAbelianGroupWrapper(QQbar, # needs sage.rings.number_field + ....: [sqrt(QQbar(2)), sqrt(QQbar(3))], [0, 0]) + sage: repr(G) # indirect doctest # needs sage.rings.number_field 'Additive abelian group isomorphic to Z + Z embedded in Algebraic Field' """ return addgp.AdditiveAbelianGroup_fixed_gens._repr_(self) + " embedded in " + self.universe()._repr_() @@ -283,10 +293,11 @@ def discrete_exp(self, v): EXAMPLES:: - sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(QQbar(2)), -1], [0, 0]) - sage: v = G.discrete_exp([3, 5]); v + sage: G = AdditiveAbelianGroupWrapper(QQbar, # needs sage.rings.number_field + ....: [sqrt(QQbar(2)), -1], [0, 0]) + sage: v = G.discrete_exp([3, 5]); v # needs sage.rings.number_field -0.7573593128807148? - sage: v.parent() is QQbar + sage: v.parent() is QQbar # needs sage.rings.number_field True This method is an inverse of :meth:`discrete_log`:: @@ -332,16 +343,17 @@ def discrete_log(self, x, gens=None): EXAMPLES:: sage: G = AdditiveAbelianGroup([2, 2*3, 2*3*5, 2*3*5*7, 2*3*5*7*11]) - sage: A = AdditiveAbelianGroupWrapper(G.0.parent(), G.gens(), [g.order() for g in G.gens()]) + sage: A = AdditiveAbelianGroupWrapper(G.0.parent(), G.gens(), + ....: [g.order() for g in G.gens()]) sage: A.discrete_log(A.discrete_exp([1,5,23,127,539])) (1, 5, 23, 127, 539) :: sage: x = polygen(ZZ, 'x') - sage: F. = GF(1009**2, modulus=x**2+11); E = EllipticCurve(j=F(940)) # optional - sage.rings.finite_rings - sage: P, Q = E(900*t + 228, 974*t + 185), E(1007*t + 214, 865*t + 802) # optional - sage.rings.finite_rings - sage: E.abelian_group().discrete_log(123 * P + 777 * Q, [P, Q]) # optional - sage.rings.finite_rings + sage: F. = GF(1009**2, modulus=x**2+11); E = EllipticCurve(j=F(940)) # needs sage.rings.finite_rings sage.schemes + sage: P, Q = E(900*t + 228, 974*t + 185), E(1007*t + 214, 865*t + 802) # needs sage.rings.finite_rings sage.schemes + sage: E.abelian_group().discrete_log(123 * P + 777 * Q, [P, Q]) # needs sage.rings.finite_rings sage.schemes (123, 777) :: @@ -357,8 +369,8 @@ def discrete_log(self, x, gens=None): :: - sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(2)], [0]) - sage: G.discrete_log(QQbar(2*sqrt(2))) + sage: G = AdditiveAbelianGroupWrapper(QQbar, [sqrt(2)], [0]) # needs sage.rings.number_field sage.symbolic + sage: G.discrete_log(QQbar(2*sqrt(2))) # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... NotImplementedError: No black-box discrete log for infinite abelian groups @@ -426,33 +438,43 @@ def torsion_subgroup(self, n=None): sage: A = AdditiveAbelianGroupWrapper(G.0.parent(), G.gens(), ords) sage: T = A.torsion_subgroup(5) sage: T - Additive abelian group isomorphic to Z/5 + Z/5 + Z/5 embedded in Additive abelian group isomorphic to Z/2 + Z/6 + Z/30 + Z + Z/210 + Z/2310 + Additive abelian group isomorphic to Z/5 + Z/5 + Z/5 embedded in + Additive abelian group isomorphic to Z/2 + Z/6 + Z/30 + Z + Z/210 + Z/2310 sage: T.gens() ((0, 0, 6, 0, 0, 0), (0, 0, 0, 0, 42, 0), (0, 0, 0, 0, 0, 462)) :: + sage: # needs sage.rings.finite_rings sage.schemes sage: E = EllipticCurve(GF(487^2), [311,205]) - sage: T = E.abelian_group().torsion_subgroup(42) - sage: T - Additive abelian group isomorphic to Z/42 + Z/6 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 311*x + 205 over Finite Field in z2 of size 487^2 + sage: T = E.abelian_group().torsion_subgroup(42); T + Additive abelian group isomorphic to Z/42 + Z/6 embedded in + Abelian group of points on Elliptic Curve + defined by y^2 = x^3 + 311*x + 205 over Finite Field in z2 of size 487^2 sage: [P.order() for P in T.gens()] [42, 6] :: + sage: # needs sage.schemes sage: E = EllipticCurve('574i1') sage: pts = [E(103,172), E(61,18)] sage: assert pts[0].order() == 7 and pts[1].order() == infinity - sage: M = AdditiveAbelianGroupWrapper(pts[0].parent(), pts, [7,0]) - sage: M - Additive abelian group isomorphic to Z/7 + Z embedded in Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field + sage: M = AdditiveAbelianGroupWrapper(pts[0].parent(), pts, [7,0]); M + Additive abelian group isomorphic to Z/7 + Z embedded in + Abelian group of points on Elliptic Curve defined by + y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field sage: M.torsion_subgroup() - Additive abelian group isomorphic to Z/7 embedded in Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field + Additive abelian group isomorphic to Z/7 embedded in + Abelian group of points on Elliptic Curve defined by + y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field sage: M.torsion_subgroup(7) - Additive abelian group isomorphic to Z/7 embedded in Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field + Additive abelian group isomorphic to Z/7 embedded in + Abelian group of points on Elliptic Curve defined by + y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field sage: M.torsion_subgroup(5) - Trivial group embedded in Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field + Trivial group embedded in Abelian group of points on Elliptic Curve + defined by y^2 + x*y + y = x^3 - x^2 - 19353*x + 958713 over Rational Field AUTHORS: @@ -493,7 +515,8 @@ def from_generators(gens, universe=None): sage: G = AdditiveAbelianGroup([15, 30, 45]) sage: gs = [G((1,2,3)), G((4,5,6)), G((7,7,7)), G((3,2,1))] sage: H = AdditiveAbelianGroupWrapper.from_generators(gs); H - Additive abelian group isomorphic to Z/90 + Z/15 embedded in Additive abelian group isomorphic to Z/15 + Z/30 + Z/45 + Additive abelian group isomorphic to Z/90 + Z/15 embedded in + Additive abelian group isomorphic to Z/15 + Z/30 + Z/45 sage: H.gens() ((12, 13, 14), (1, 26, 21)) @@ -552,12 +575,13 @@ def _discrete_log_pgroup(p, vals, aa, b): Check for :trac:`34716`:: + sage: # needs sage.rings.finite_rings sage.schemes sage: E = EllipticCurve(GF(487^2), [311,205]) sage: G = E.abelian_group().torsion_subgroup(42) sage: G.invariants() (6, 42) sage: P, Q = G.torsion_subgroup(6).gens() - sage: G.discrete_log(2*P + 3*Q, [P, Q]) # indirect doctest + sage: G.discrete_log(2*P + 3*Q, [P, Q]) # indirect doctest # needs sage.groups (2, 3) """ from itertools import product as iproduct @@ -748,6 +772,7 @@ def basis_from_generators(gens, ords=None): EXAMPLES:: + sage: # needs sage.groups sage.rings.finite_rings sage: from sage.groups.additive_abelian.additive_abelian_wrapper import basis_from_generators sage: E = EllipticCurve(GF(31337^6,'a'), j=37) sage: E.order() diff --git a/src/sage/groups/affine_gps/affine_group.py b/src/sage/groups/affine_gps/affine_group.py index 81074a3e50d..bfcdd282df1 100644 --- a/src/sage/groups/affine_gps/affine_group.py +++ b/src/sage/groups/affine_gps/affine_group.py @@ -129,11 +129,11 @@ class AffineGroup(UniqueRepresentation, Group): Some additional ways to create affine groups:: - sage: A = AffineSpace(2, GF(4,'a')); A # optional - sage.rings.finite_rings + sage: A = AffineSpace(2, GF(4,'a')); A # needs sage.rings.finite_rings Affine Space of dimension 2 over Finite Field in a of size 2^2 - sage: G = AffineGroup(A); G # optional - sage.rings.finite_rings + sage: G = AffineGroup(A); G # needs sage.rings.finite_rings Affine Group of degree 2 over Finite Field in a of size 2^2 - sage: G is AffineGroup(2,4) # shorthand # optional - sage.rings.finite_rings + sage: G is AffineGroup(2,4) # shorthand # needs sage.rings.finite_rings True sage: V = ZZ^3; V @@ -152,10 +152,10 @@ def __classcall__(cls, *args, **kwds): EXAMPLES:: - sage: A = AffineSpace(2, GF(4,'a')) # optional - sage.rings.finite_rings - sage: AffineGroup(A) is AffineGroup(2,4) # optional - sage.rings.finite_rings + sage: A = AffineSpace(2, GF(4,'a')) # needs sage.rings.finite_rings + sage: AffineGroup(A) is AffineGroup(2,4) # needs sage.rings.finite_rings True - sage: AffineGroup(A) is AffineGroup(2, GF(4,'a')) # optional - sage.rings.finite_rings + sage: AffineGroup(A) is AffineGroup(2, GF(4,'a')) # needs sage.rings.finite_rings True sage: A = AffineGroup(2, QQ) sage: V = QQ^2 @@ -202,10 +202,10 @@ def __init__(self, degree, ring): TESTS:: - sage: G = AffineGroup(2, GF(5)); G # optional - sage.rings.finite_rings + sage: G = AffineGroup(2, GF(5)); G Affine Group of degree 2 over Finite Field of size 5 - sage: TestSuite(G).run() # optional - sage.rings.finite_rings - sage: G.category() # optional - sage.rings.finite_rings + sage: TestSuite(G).run() + sage: G.category() Category of finite groups sage: Aff6 = AffineGroup(6, QQ) @@ -264,8 +264,8 @@ def _latex_(self): EXAMPLES:: - sage: G = AffineGroup(6, GF(5)) # optional - sage.rings.finite_rings - sage: latex(G) # optional - sage.rings.finite_rings + sage: G = AffineGroup(6, GF(5)) + sage: latex(G) \mathrm{Aff}_{6}(\Bold{F}_{5}) """ return "\\mathrm{Aff}_{%s}(%s)" % (self.degree(), @@ -277,7 +277,7 @@ def _repr_(self): EXAMPLES:: - sage: AffineGroup(6, GF(5)) # optional - sage.rings.finite_rings + sage: AffineGroup(6, GF(5)) Affine Group of degree 6 over Finite Field of size 5 """ return "Affine Group of degree %s over %s" % (self.degree(), @@ -289,7 +289,7 @@ def cardinality(self): EXAMPLES:: - sage: AffineGroup(6, GF(5)).cardinality() # optional - sage.rings.finite_rings + sage: AffineGroup(6, GF(5)).cardinality() 172882428468750000000000000000 sage: AffineGroup(6, ZZ).cardinality() +Infinity @@ -305,11 +305,11 @@ def degree(self): EXAMPLES:: - sage: G = AffineGroup(6, GF(5)) # optional - sage.rings.finite_rings - sage: g = G.an_element() # optional - sage.rings.finite_rings - sage: G.degree() # optional - sage.rings.finite_rings + sage: G = AffineGroup(6, GF(5)) + sage: g = G.an_element() + sage: G.degree() 6 - sage: G.degree() == g.A().nrows() == g.A().ncols() == g.b().degree() # optional - sage.rings.finite_rings + sage: G.degree() == g.A().nrows() == g.A().ncols() == g.b().degree() True """ return self._degree @@ -327,8 +327,8 @@ def matrix_space(self): EXAMPLES:: - sage: G = AffineGroup(3, GF(5)) # optional - sage.rings.finite_rings - sage: G.matrix_space() # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, GF(5)) + sage: G.matrix_space() Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5 """ d = self.degree() @@ -341,8 +341,8 @@ def vector_space(self): EXAMPLES:: - sage: G = AffineGroup(3, GF(5)) # optional - sage.rings.finite_rings - sage: G.vector_space() # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, GF(5)) + sage: G.vector_space() Vector space of dimension 3 over Finite Field of size 5 """ return FreeModule(self.base_ring(), self.degree()) @@ -371,8 +371,8 @@ def linear_space(self): EXAMPLES:: - sage: G = AffineGroup(3, GF(5)) # optional - sage.rings.finite_rings - sage: G.linear_space() # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, GF(5)) + sage: G.linear_space() Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 5 """ dp = self.degree() + 1 @@ -390,8 +390,8 @@ def linear(self, A): EXAMPLES:: - sage: G = AffineGroup(3, GF(5)) # optional - sage.rings.finite_rings - sage: G.linear([1,2,3,4,5,6,7,8,0]) # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, GF(5)) + sage: G.linear([1,2,3,4,5,6,7,8,0]) [1 2 3] [0] x |-> [4 0 1] x + [0] [2 3 0] [0] @@ -411,8 +411,8 @@ def translation(self, b): EXAMPLES:: - sage: G = AffineGroup(3, GF(5)) # optional - sage.rings.finite_rings - sage: G.translation([1,4,8]) # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, GF(5)) + sage: G.translation([1,4,8]) [1 0 0] [1] x |-> [0 1 0] x + [4] [0 0 1] [3] @@ -440,12 +440,12 @@ def reflection(self, v): EXAMPLES:: - sage: G = AffineGroup(3, QQ) # optional - sage.rings.finite_rings - sage: G.reflection([1,0,0]) # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, QQ) + sage: G.reflection([1,0,0]) [-1 0 0] [0] x |-> [ 0 1 0] x + [0] [ 0 0 1] [0] - sage: G.reflection([3,4,-5]) # optional - sage.rings.finite_rings + sage: G.reflection([3,4,-5]) [ 16/25 -12/25 3/5] [0] x |-> [-12/25 9/25 4/5] x + [0] [ 3/5 4/5 0] [0] @@ -464,13 +464,13 @@ def random_element(self): EXAMPLES:: - sage: G = AffineGroup(4, GF(3)) # optional - sage.rings.finite_rings - sage: G.random_element() # random # optional - sage.rings.finite_rings + sage: G = AffineGroup(4, GF(3)) + sage: G.random_element() # random [2 0 1 2] [1] [2 1 1 2] [2] x |-> [1 0 2 2] x + [2] [1 1 1 1] [2] - sage: G.random_element() in G # optional - sage.rings.finite_rings + sage: G.random_element() in G True """ A = self._GL.random_element() @@ -484,8 +484,8 @@ def _an_element_(self): TESTS:: - sage: G = AffineGroup(4,5) # optional - sage.rings.finite_rings - sage: G.an_element() in G # optional - sage.rings.finite_rings + sage: G = AffineGroup(4,5) + sage: G.an_element() in G True """ A = self._GL.an_element() @@ -498,8 +498,8 @@ def some_elements(self): EXAMPLES:: - sage: G = AffineGroup(4,5) # optional - sage.rings.finite_rings - sage: G.some_elements() # optional - sage.rings.finite_rings + sage: G = AffineGroup(4,5) + sage: G.some_elements() [ [2 0 0 0] [1] [0 1 0 0] [0] x |-> [0 0 1 0] x + [0] @@ -512,7 +512,7 @@ def some_elements(self): [0 1 0 0] [...] x |-> [0 0 1 0] x + [...] [0 0 0 1] [...]] - sage: all(v.parent() is G for v in G.some_elements()) # optional - sage.rings.finite_rings + sage: all(v.parent() is G for v in G.some_elements()) True sage: G = AffineGroup(2,QQ) diff --git a/src/sage/groups/affine_gps/euclidean_group.py b/src/sage/groups/affine_gps/euclidean_group.py index b88b4f741ac..07349c40292 100644 --- a/src/sage/groups/affine_gps/euclidean_group.py +++ b/src/sage/groups/affine_gps/euclidean_group.py @@ -121,11 +121,11 @@ class EuclideanGroup(AffineGroup): Some additional ways to create Euclidean groups:: - sage: A = AffineSpace(2, GF(4,'a')); A # optional - sage.rings.finite_rings + sage: A = AffineSpace(2, GF(4,'a')); A # needs sage.rings.finite_rings Affine Space of dimension 2 over Finite Field in a of size 2^2 - sage: G = EuclideanGroup(A); G # optional - sage.rings.finite_rings + sage: G = EuclideanGroup(A); G # needs sage.rings.finite_rings Euclidean Group of degree 2 over Finite Field in a of size 2^2 - sage: G is EuclideanGroup(2,4) # shorthand # optional - sage.rings.finite_rings + sage: G is EuclideanGroup(2,4) # shorthand # needs sage.rings.finite_rings True sage: V = ZZ^3; V @@ -144,9 +144,9 @@ class EuclideanGroup(AffineGroup): sage: V = QQ^6 sage: E6 is EuclideanGroup(V) True - sage: G = EuclideanGroup(2, GF(5)); G # optional - sage.rings.finite_rings + sage: G = EuclideanGroup(2, GF(5)); G Euclidean Group of degree 2 over Finite Field of size 5 - sage: TestSuite(G).run() # optional - sage.rings.finite_rings + sage: TestSuite(G).run() REFERENCES: @@ -195,8 +195,8 @@ def _latex_(self): r""" EXAMPLES:: - sage: G = EuclideanGroup(6, GF(5)) # optional - sage.rings.finite_rings - sage: latex(G) # optional - sage.rings.finite_rings + sage: G = EuclideanGroup(6, GF(5)) + sage: latex(G) \mathrm{E}_{6}(\Bold{F}_{5}) """ return "\\mathrm{E}_{%s}(%s)"%(self.degree(), self.base_ring()._latex_()) @@ -207,7 +207,7 @@ def _repr_(self): EXAMPLES:: - sage: EuclideanGroup(6, GF(5)) # optional - sage.rings.finite_rings + sage: EuclideanGroup(6, GF(5)) Euclidean Group of degree 6 over Finite Field of size 5 """ return "Euclidean Group of degree %s over %s"%(self.degree(), self.base_ring()) @@ -218,18 +218,18 @@ def random_element(self): EXAMPLES:: - sage: G = EuclideanGroup(4, GF(3)) # optional - sage.rings.finite_rings - sage: G.random_element() # random # optional - sage.rings.finite_rings + sage: G = EuclideanGroup(4, GF(3)) + sage: G.random_element() # random [2 1 2 1] [1] [1 2 2 1] [0] x |-> [2 2 2 2] x + [1] [1 1 2 2] [2] - sage: G.random_element() in G # optional - sage.rings.finite_rings + sage: G.random_element() in G True TESTS:: - sage: G.random_element().A().is_unitary() # optional - sage.rings.finite_rings + sage: G.random_element().A().is_unitary() True """ while True: diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index 48126ba64a8..74d8b684bbb 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -78,13 +78,13 @@ class AffineGroupElement(MultiplicativeGroupElement): EXAMPLES:: - sage: G = AffineGroup(2, GF(3)) # optional - sage.rings.finite_rings - sage: g = G.random_element() # optional - sage.rings.finite_rings - sage: type(g) # optional - sage.rings.finite_rings + sage: G = AffineGroup(2, GF(3)) + sage: g = G.random_element() + sage: type(g) - sage: G(g.matrix()) == g # optional - sage.rings.finite_rings + sage: G(g.matrix()) == g True - sage: G(2) # optional - sage.rings.finite_rings + sage: G(2) [2 0] [0] x |-> [0 2] x + [0] @@ -108,9 +108,9 @@ def __init__(self, parent, A, b=0, convert=True, check=True): TESTS:: - sage: G = AffineGroup(4, GF(5)) # optional - sage.rings.finite_rings - sage: g = G.random_element() # optional - sage.rings.finite_rings - sage: TestSuite(g).run() # optional - sage.rings.finite_rings + sage: G = AffineGroup(4, GF(5)) + sage: g = G.random_element() + sage: TestSuite(g).run() """ try: A = A.matrix() @@ -181,29 +181,29 @@ def matrix(self): EXAMPLES:: - sage: G = AffineGroup(3, GF(7)) # optional - sage.rings.finite_rings - sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12]) # optional - sage.rings.finite_rings - sage: g # optional - sage.rings.finite_rings + sage: G = AffineGroup(3, GF(7)) + sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12]) + sage: g [1 2 3] [3] x |-> [4 5 6] x + [4] [0 1 0] [5] - sage: g.matrix() # optional - sage.rings.finite_rings + sage: g.matrix() [1 2 3|3] [4 5 6|4] [0 1 0|5] [-----+-] [0 0 0|1] - sage: parent(g.matrix()) # optional - sage.rings.finite_rings + sage: parent(g.matrix()) Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 7 - sage: g.matrix() == matrix(g) # optional - sage.rings.finite_rings + sage: g.matrix() == matrix(g) True Composition of affine group elements equals multiplication of the matrices:: - sage: g1 = G.random_element() # optional - sage.rings.finite_rings - sage: g2 = G.random_element() # optional - sage.rings.finite_rings - sage: g1.matrix() * g2.matrix() == (g1*g2).matrix() # optional - sage.rings.finite_rings + sage: g1 = G.random_element() + sage: g2 = G.random_element() + sage: g1.matrix() * g2.matrix() == (g1*g2).matrix() True """ A = self._A @@ -332,13 +332,13 @@ def _mul_(self, other): EXAMPLES:: - sage: G = AffineGroup(2, GF(3)) # optional - sage.rings.finite_rings - sage: g = G([1,1, 0,1], [0,1]) # optional - sage.rings.finite_rings - sage: h = G([1,1, 0,1], [1,2]) # optional - sage.rings.finite_rings - sage: g*h # optional - sage.rings.finite_rings + sage: G = AffineGroup(2, GF(3)) + sage: g = G([1,1, 0,1], [0,1]) + sage: h = G([1,1, 0,1], [1,2]) + sage: g*h [1 2] [0] x |-> [0 1] x + [0] - sage: g.matrix() * h.matrix() == (g*h).matrix() # optional - sage.rings.finite_rings + sage: g.matrix() * h.matrix() == (g*h).matrix() True """ parent = self.parent() @@ -395,8 +395,8 @@ def __call__(self, v): sage: M = matrix(3, [-1, -2, 0, 0, 0, 1, -2, 1, -1]) sage: v = vector(QQ,(1,2,3)) sage: f = F(M, v) - sage: cube = polytopes.cube() - sage: f(cube) + 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 """ @@ -432,16 +432,16 @@ def _act_on_(self, x, self_on_left): EXAMPLES:: - sage: G = AffineGroup(2, GF(3)) # optional - sage.rings.finite_rings - sage: g = G([1,2,3,4], [5,6]) # optional - sage.rings.finite_rings - sage: g # optional - sage.rings.finite_rings + sage: G = AffineGroup(2, GF(3)) + sage: g = G([1,2,3,4], [5,6]) + sage: g [1 2] [2] x |-> [0 1] x + [0] - sage: v = vector(GF(3), [1,-1]); v # optional - sage.rings.finite_rings + sage: v = vector(GF(3), [1,-1]); v (1, 2) - sage: g*v # optional - sage.rings.finite_rings + sage: g*v (1, 2) - sage: g*v == g.A() * v + g.b() # optional - sage.rings.finite_rings + sage: g*v == g.A() * v + g.b() True """ if self_on_left: @@ -455,18 +455,18 @@ def __invert__(self): EXAMPLES:: - sage: G = AffineGroup(2, GF(3)) # optional - sage.rings.finite_rings - sage: g = G([1,2,3,4], [5,6]) # optional - sage.rings.finite_rings - sage: g # optional - sage.rings.finite_rings + sage: G = AffineGroup(2, GF(3)) + sage: g = G([1,2,3,4], [5,6]) + sage: g [1 2] [2] x |-> [0 1] x + [0] - sage: ~g # optional - sage.rings.finite_rings + sage: ~g [1 1] [1] x |-> [0 1] x + [0] - sage: g * g.inverse() # indirect doctest # optional - sage.rings.finite_rings + sage: g * g.inverse() # indirect doctest [1 0] [0] x |-> [0 1] x + [0] - sage: g * g.inverse() == g.inverse() * g == G(1) # optional - sage.rings.finite_rings + sage: g * g.inverse() == g.inverse() * g == G(1) True """ parent = self.parent() diff --git a/src/sage/groups/artin.py b/src/sage/groups/artin.py index 0e91205c8e1..4387e503ba7 100644 --- a/src/sage/groups/artin.py +++ b/src/sage/groups/artin.py @@ -12,7 +12,7 @@ - Travis Scrimshaw (2018-02-05): Initial version """ -#**************************************************************************** +# **************************************************************************** # Copyright (C) 2018 Travis Scrimshaw # # This program is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ -#***************************************************************************** +# ***************************************************************************** from sage.misc.cachefunc import cached_method from sage.groups.free_group import FreeGroup @@ -39,6 +39,7 @@ class ArtinGroupElement(FinitelyPresentedGroupElement): EXAMPLES:: + sage: # needs sage.rings.number_field sage: A. = ArtinGroup(['B',3]) sage: A Artin group of type ['B', 3] @@ -57,9 +58,9 @@ def _latex_(self): TESTS:: - sage: A = ArtinGroup(['B',3]) - sage: b = A([1, 2, 3, -1, 2, -3]) - sage: b._latex_() + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: b = A([1, 2, 3, -1, 2, -3]) # needs sage.rings.number_field + sage: b._latex_() # needs sage.rings.number_field '\\sigma_{1}\\sigma_{2}\\sigma_{3}\\sigma_{1}^{-1}\\sigma_{2}\\sigma_{3}^{-1}' sage: B = BraidGroup(4) @@ -80,6 +81,7 @@ def exponent_sum(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: A = ArtinGroup(['E',6]) sage: b = A([1, 4, -3, 2]) sage: b.exponent_sum() @@ -103,26 +105,56 @@ def coxeter_group_element(self, W=None): Return the corresponding Coxeter group element under the natural projection. + INPUT: + + - ``W`` -- (default: ``self.parent().coxeter_group()``) the image Coxeter group + OUTPUT: - A permutation. + An element of the Coxeter group ``W``. EXAMPLES:: - sage: A. = ArtinGroup(['B',3]) + sage: # needs sage.rings.number_field + sage: B. = ArtinGroup(['B',3]) sage: b = s1 * s2 / s3 / s2 - sage: b.coxeter_group_element() + sage: b1 = b.coxeter_group_element(); b1 [ 1 -1 0] [ 2 -1 0] [ a -a 1] sage: b.coxeter_group_element().reduced_word() [1, 2, 3, 2] + sage: A. = ArtinGroup(['A',3]) + sage: c = s1 * s2 *s3 + sage: c1 = c.coxeter_group_element(); c1 + [4, 1, 2, 3] + sage: c1.reduced_word() + [3, 2, 1] + sage: c.coxeter_group_element(W=SymmetricGroup(4)) + (1,4,3,2) + sage: A. = BraidGroup(4) + sage: c = s1 * s2 * s3^-1 + sage: c0 = c.coxeter_group_element(); c0 + [4, 1, 2, 3] + sage: c1 = c.coxeter_group_element(W=SymmetricGroup(4)); c1 + (1,4,3,2) + + From an element of the Coxeter group it is possible to recover + the image by the standard section to the Artin group:: + + sage: B(b1) + s1*s2*s3*s2 + sage: A(c0) + s1*s2*s3 + sage: A(c0) == A(c1) + True """ if W is None: W = self.parent().coxeter_group() s = W.simple_reflections() - I = W.index_set() - return W.prod(s[I[abs(i)-1]] for i in self.Tietze()) + In = W.index_set() + return W.prod(s[In[abs(i)-1]] for i in self.Tietze()) + class FiniteTypeArtinGroupElement(ArtinGroupElement): """ @@ -134,6 +166,7 @@ def _richcmp_(self, other, op): TESTS:: + sage: # needs sage.rings.number_field sage: A = ArtinGroup(['B',3]) sage: x = A([1, 2, 1]) sage: y = A([2, 1, 2]) @@ -162,6 +195,7 @@ def __hash__(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: B. = ArtinGroup(['B',3]) sage: hash(s1*s3) == hash(s3*s1) True @@ -189,6 +223,7 @@ def left_normal_form(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: A = ArtinGroup(['B',3]) sage: A([1]).left_normal_form() (1, s1) @@ -208,7 +243,7 @@ def left_normal_form(self): sage: B = BraidGroup(4) sage: b = B([1, 2, 3, -1, 2, -3]) sage: b.left_normal_form() - (s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1, s0*s1*s2*s1*s0, s0*s2*s1) + (s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1, s0*s1*s2*s1*s0, s0*s2*s1) sage: c = B([1]) sage: c.left_normal_form() (1, s0) @@ -230,6 +265,7 @@ def _left_normal_form_coxeter(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: A = ArtinGroup(['E',6]) sage: A([2, -4, 2, 3, 1, 3, 2, 1, -2])._left_normal_form_coxeter() ( @@ -257,11 +293,11 @@ def _left_normal_form_coxeter(self): delta = 0 Delta = self.parent().coxeter_group().long_element() sr = self.parent().coxeter_group().simple_reflections() - l = self.Tietze() - if l == (): + tz = self.Tietze() + if tz == (): return (0,) form = [] - for i in l: + for i in tz: if i > 0: form.append(sr[i]) else: @@ -294,6 +330,7 @@ def _left_normal_form_coxeter(self): delta -= 1 return tuple([-delta] + form) + class ArtinGroup(FinitelyPresentedGroup): r""" An Artin group. @@ -345,9 +382,9 @@ class ArtinGroup(FinitelyPresentedGroup): EXAMPLES:: - sage: A. = ArtinGroup(['B',3]); A + sage: A. = ArtinGroup(['B',3]); A # needs sage.rings.number_field Artin group of type ['B', 3] - sage: ArtinGroup(['B',3]) + sage: ArtinGroup(['B',3]) # needs sage.rings.number_field Artin group of type ['B', 3] The input must always include the Coxeter data, but the ``names`` @@ -355,11 +392,11 @@ class ArtinGroup(FinitelyPresentedGroup): the explicit names of the generators. Otherwise the default prefix of ``'s'`` is used:: - sage: ArtinGroup(['B',2]).generators() + sage: ArtinGroup(['B',2]).generators() # needs sage.rings.number_field (s1, s2) - sage: ArtinGroup(['B',2], 'g').generators() + sage: ArtinGroup(['B',2], 'g').generators() # needs sage.rings.number_field (g1, g2) - sage: ArtinGroup(['B',2], 'x,y').generators() + sage: ArtinGroup(['B',2], 'x,y').generators() # needs sage.rings.number_field (x, y) REFERENCES: @@ -377,26 +414,28 @@ def __classcall_private__(cls, coxeter_data, names=None): TESTS:: + sage: # needs sage.rings.number_field sage: A1 = ArtinGroup(['B',3]) sage: A2 = ArtinGroup(['B',3], 's') sage: A3 = ArtinGroup(['B',3], ['s1','s2','s3']) sage: A1 is A2 and A2 is A3 True + sage: # needs sage.rings.number_field sage: A1 = ArtinGroup(['B',2], 'a,b') sage: A2 = ArtinGroup([[1,4],[4,1]], 'a,b') sage: A3. = ArtinGroup('B2') sage: A1 is A2 and A2 is A3 True - sage: ArtinGroup(['A',3]) is BraidGroup(4, 's1,s2,s3') + sage: ArtinGroup(['A',3]) is BraidGroup(4, 's1,s2,s3') # needs sage.rings.number_field True sage: G = graphs.PathGraph(3) sage: CM = CoxeterMatrix([[1,-1,2],[-1,1,-1],[2,-1,1]], index_set=G.vertices(sort=True)) - sage: A = groups.misc.Artin(CM) - sage: Ap = groups.misc.RightAngledArtin(G, 's') - sage: A is Ap + sage: A = groups.misc.Artin(CM) # needs sage.rings.number_field + sage: Ap = groups.misc.RightAngledArtin(G, 's') # needs sage.rings.number_field + sage: A is Ap # needs sage.rings.number_field True """ coxeter_data = CoxeterMatrix(coxeter_data) @@ -427,6 +466,7 @@ def __init__(self, coxeter_matrix, names): TESTS:: + sage: # needs sage.rings.number_field sage: A = ArtinGroup(['D',4]) sage: TestSuite(A).run() sage: A = ArtinGroup(['B',3], ['x','y','z']) @@ -437,12 +477,12 @@ def __init__(self, coxeter_matrix, names): rels = [] # Generate the relations based on the Coxeter graph I = coxeter_matrix.index_set() - for ii,i in enumerate(I): - for j in I[ii+1:]: - m = coxeter_matrix[i,j] + for ii, i in enumerate(I): + for j in I[ii + 1:]: + m = coxeter_matrix[i, j] if m == Infinity: # no relation continue - elt = [i,j]*m + elt = [i, j] * m for ind in range(m, 2*m): elt[ind] = -elt[ind] rels.append(free_group(elt)) @@ -454,9 +494,9 @@ def _repr_(self): TESTS:: - sage: ArtinGroup(['B',3]) + sage: ArtinGroup(['B',3]) # needs sage.rings.number_field Artin group of type ['B', 3] - sage: ArtinGroup(['D',4], 'g') + sage: ArtinGroup(['D',4], 'g') # needs sage.rings.number_field Artin group of type ['D', 4] """ try: @@ -481,8 +521,8 @@ def cardinality(self): sage: G.cardinality() +Infinity - sage: A = ArtinGroup(['A',1]) - sage: A.cardinality() + sage: A = ArtinGroup(['A',1]) # needs sage.rings.number_field + sage: A.cardinality() # needs sage.rings.number_field +Infinity """ from sage.rings.infinity import Infinity @@ -506,8 +546,8 @@ def as_permutation_group(self): ... ValueError: the group is infinite - sage: A = ArtinGroup(['D',4], 'g') - sage: A.as_permutation_group() + sage: A = ArtinGroup(['D',4], 'g') # needs sage.rings.number_field + sage: A.as_permutation_group() # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the group is infinite @@ -520,8 +560,8 @@ def coxeter_type(self): EXAMPLES:: - sage: A = ArtinGroup(['D',4]) - sage: A.coxeter_type() + sage: A = ArtinGroup(['D',4]) # needs sage.rings.number_field + sage: A.coxeter_type() # needs sage.rings.number_field Coxeter type of ['D', 4] """ return self._coxeter_group.coxeter_type() @@ -532,8 +572,8 @@ def coxeter_matrix(self): EXAMPLES:: - sage: A = ArtinGroup(['B',3]) - sage: A.coxeter_matrix() + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: A.coxeter_matrix() # needs sage.rings.number_field [1 3 2] [3 1 4] [2 4 1] @@ -546,8 +586,8 @@ def coxeter_group(self): EXAMPLES:: - sage: A = ArtinGroup(['D',4]) - sage: A.coxeter_group() + sage: A = ArtinGroup(['D',4]) # needs sage.rings.number_field + sage: A.coxeter_group() # needs sage.rings.number_field Finite Coxeter group over Integer Ring with Coxeter matrix: [1 3 2 2] [3 1 3 3] @@ -566,8 +606,8 @@ def index_set(self): EXAMPLES:: - sage: A = ArtinGroup(['E',7]) - sage: A.index_set() + sage: A = ArtinGroup(['E',7]) # needs sage.rings.number_field + sage: A.index_set() # needs sage.rings.number_field (1, 2, 3, 4, 5, 6, 7) """ return self._coxeter_group.index_set() @@ -576,8 +616,8 @@ def _element_constructor_(self, x): """ TESTS:: - sage: A = ArtinGroup(['B',3]) - sage: A([2,1,-2,3,3,3,1]) + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: A([2,1,-2,3,3,3,1]) # needs sage.rings.number_field s2*s1*s2^-1*s3^3*s1 """ if x in self._coxeter_group: @@ -591,8 +631,8 @@ def an_element(self): EXAMPLES:: - sage: A = ArtinGroup(['B',2]) - sage: A.an_element() + sage: A = ArtinGroup(['B',2]) # needs sage.rings.number_field + sage: A.an_element() # needs sage.rings.number_field s1 """ return self.gen(0) @@ -603,14 +643,14 @@ def some_elements(self): EXAMPLES:: - sage: A = ArtinGroup(['B',3]) - sage: A.some_elements() + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: A.some_elements() # needs sage.rings.number_field [s1, s1*s2*s3, (s1*s2*s3)^3] """ rank = self.coxeter_matrix().rank() elements_list = [self.gen(0)] elements_list.append(self.prod(self.gens())) - elements_list.append(elements_list[-1] ** min(rank,3)) + elements_list.append(elements_list[-1] ** min(rank, 3)) return elements_list def _standard_lift_Tietze(self, w): @@ -624,8 +664,8 @@ def _standard_lift_Tietze(self, w): EXAMPLES:: - sage: A = ArtinGroup(['B',3]) - sage: A._standard_lift_Tietze(A.coxeter_group().long_element()) + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: A._standard_lift_Tietze(A.coxeter_group().long_element()) # needs sage.rings.number_field [3, 2, 3, 1, 2, 3, 1, 2, 1] """ return w.reduced_word() @@ -642,14 +682,14 @@ def _standard_lift(self, w): EXAMPLES:: - sage: A = ArtinGroup(['B',3]) - sage: A._standard_lift(A.coxeter_group().long_element()) + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: A._standard_lift(A.coxeter_group().long_element()) # needs sage.rings.number_field s3*(s2*s3*s1)^2*s2*s1 sage: B = BraidGroup(5) sage: P = Permutation([5, 3, 1, 2, 4]) sage: B._standard_lift(P) - s0*s1*s0*s2*s1*s3 + s0*s1*s2*s3*s0*s1 """ return self(self._standard_lift_Tietze(w)) @@ -671,7 +711,7 @@ class FiniteTypeArtinGroup(ArtinGroup): EXAMPLES:: - sage: ArtinGroup(['E',7]) + sage: ArtinGroup(['E',7]) # needs sage.rings.number_field Artin group of type ['E', 7] Since the word problem for finite-type Artin groups is solvable, their @@ -684,15 +724,15 @@ class FiniteTypeArtinGroup(ArtinGroup): ....: for w in Words(alphabet=group.gens(), length=length): ....: ret.add(prod(w)) ....: return ret - sage: A = ArtinGroup(['B',3]) - sage: GA = A.cayley_graph(elements=ball(A, 4), generators=A.gens()); GA + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: GA = A.cayley_graph(elements=ball(A, 4), generators=A.gens()); GA # needs sage.rings.number_field Digraph on 32 vertices Since the Artin group has nontrivial relations, this graph contains less vertices than the one associated to the free group (which is a tree):: sage: F = FreeGroup(3) - sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF + sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF # needs sage.combinat Digraph on 40 vertices """ def delta(self): @@ -701,17 +741,17 @@ def delta(self): EXAMPLES:: - sage: A = ArtinGroup(['B',3]) - sage: A.delta() + sage: A = ArtinGroup(['B',3]) # needs sage.rings.number_field + sage: A.delta() # needs sage.rings.number_field s3*(s2*s3*s1)^2*s2*s1 - sage: A = ArtinGroup(['G',2]) - sage: A.delta() + sage: A = ArtinGroup(['G',2]) # needs sage.rings.number_field + sage: A.delta() # needs sage.rings.number_field (s2*s1)^3 sage: B = BraidGroup(5) sage: B.delta() - s0*s1*s0*s2*s1*s0*s3*s2*s1*s0 + s0*s1*s2*s3*s0*s1*s2*s0*s1*s0 """ return self._standard_lift(self._coxeter_group.long_element()) diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index f4ad632b332..8d6c062bd63 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -67,27 +67,33 @@ # https://www.gnu.org/licenses/ ############################################################################## -from sage.rings.integer import Integer -from sage.rings.integer_ring import IntegerRing +from itertools import combinations +from sage.categories.action import Action +from sage.categories.groups import Groups +from sage.combinat.permutation import Permutation +from sage.combinat.permutation import Permutations +from sage.combinat.subset import Subsets +from sage.features import PythonModule +from sage.groups.artin import FiniteTypeArtinGroup, FiniteTypeArtinGroupElement +from sage.groups.finitely_presented import FinitelyPresentedGroup +from sage.groups.finitely_presented import GroupMorphismWithGensImages +from sage.groups.free_group import FreeGroup, is_FreeGroup +from sage.functions.generalized import sign +from sage.groups.perm_gps.permgroup_named import SymmetricGroup +from sage.groups.perm_gps.permgroup_named import SymmetricGroupElement +from sage.knots.knot import Knot +from sage.libs.gap.libgap import libgap +from sage.matrix.constructor import identity_matrix, matrix from sage.misc.lazy_attribute import lazy_attribute from sage.misc.lazy_import import lazy_import from sage.misc.cachefunc import cached_method from sage.misc.misc_c import prod -from sage.categories.groups import Groups -from sage.groups.free_group import FreeGroup, is_FreeGroup -from sage.groups.perm_gps.permgroup_named import SymmetricGroup +from sage.rings.integer import Integer +from sage.rings.integer_ring import IntegerRing from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing -from sage.matrix.constructor import identity_matrix, matrix -from sage.combinat.permutation import Permutations -from sage.combinat.subset import Subsets -from sage.categories.action import Action -from sage.knots.knot import Knot from sage.sets.set import Set -from sage.groups.finitely_presented import FinitelyPresentedGroup -from sage.groups.artin import FiniteTypeArtinGroup, FiniteTypeArtinGroupElement +from sage.structure.element import Expression from sage.structure.richcmp import richcmp, rich_to_bool -from sage.features import PythonModule - lazy_import('sage.libs.braiding', ['leftnormalform', 'rightnormalform', 'centralizer', 'supersummitset', 'greatestcommondivisor', @@ -446,11 +452,20 @@ def permutation(self, W=None): sage: B. = BraidGroup() sage: S = SymmetricGroup(4) sage: b = s0*s1/s2/s1 - sage: b.permutation(W=S) + sage: c0 = b.permutation(W=S); c0 (1,4,2) - sage: c = b.permutation(W=Permutations(4)); c + sage: c1 = b.permutation(W=Permutations(4)); c1 [4, 1, 3, 2] - sage: c == b.permutation() + sage: c1 == b.permutation() + True + + The canonical section from the symmetric group to the braid group + (sending a permutation to its associated permutation braid) + can be recovered:: + + sage: B(c0) + s0*s1*s2*s1 + sage: B(c0) == B(c1) True """ return self.coxeter_group_element(W) @@ -505,14 +520,14 @@ def plot(self, color='rainbow', orientation='bottom-top', gap=0.05, aspect_ratio False sage: B = BraidGroup(4, 's') sage: b = B([1, 2, 3, 1, 2, 1]) - sage: b.plot() + sage: b.plot() # needs sage.plot Graphics object consisting of 30 graphics primitives - sage: b.plot(color=["red", "blue", "red", "blue"]) + sage: b.plot(color=["red", "blue", "red", "blue"]) # needs sage.plot Graphics object consisting of 30 graphics primitives sage: B. = BraidGroup(3) sage: b = t^-1*s^2 - sage: b.plot(orientation="left-right", color="red") + sage: b.plot(orientation="left-right", color="red") # needs sage.plot Graphics object consisting of 12 graphics primitives """ from sage.plot.bezier_path import bezier_path @@ -606,11 +621,11 @@ def plot3d(self, color='rainbow'): sage: B = BraidGroup(4, 's') sage: b = B([1, 2, 3, 1, 2, 1]) - sage: b.plot3d() + sage: b.plot3d() # needs sage.plot sage.symbolic Graphics3d Object - sage: b.plot3d(color="red") + sage: b.plot3d(color="red") # needs sage.plot sage.symbolic Graphics3d Object - sage: b.plot3d(color=["red", "blue", "red", "blue"]) + sage: b.plot3d(color=["red", "blue", "red", "blue"]) # needs sage.plot sage.symbolic Graphics3d Object """ from sage.plot.plot3d.shapes2 import bezier3d @@ -812,8 +827,8 @@ def links_gould_matrix(self, symbolics=False): Univariate Quotient Polynomial Ring in Yrbar over Multivariate Laurent Polynomial Ring in s0r, s1r over Integer Ring with modulus Yr^2 + s0r^2*s1r^2 - s0r^2 - s1r^2 + 1 - sage: HopfLGs = Hopf.links_gould_matrix(symbolics=True) - sage: HopfLGs.base_ring() + sage: HopfLGs = Hopf.links_gould_matrix(symbolics=True) # needs sage.symbolic + sage: HopfLGs.base_ring() # needs sage.symbolic Symbolic Ring """ rep = self.parent()._links_gould_representation(symbolics=symbolics) @@ -864,8 +879,8 @@ def links_gould_polynomial(self, varnames=None, use_symbolics=False): varnames = 't0, t1' rep = self.parent()._links_gould_representation(symbolics=use_symbolics) - l = len(rep) - mu = rep[l-1] # quantum trace factor + ln = len(rep) + mu = rep[ln - 1] # quantum trace factor M = mu * self.links_gould_matrix(symbolics=use_symbolics) d1, d2 = M.dimensions() e = d1//4 @@ -873,13 +888,13 @@ def links_gould_polynomial(self, varnames=None, use_symbolics=False): R = LaurentPolynomialRing(ZZ, varnames) # partial quantum trace according to I. Marin section 2.5 - part_trace = matrix(B, 4, 4, lambda i, j: sum(M[e*i+ k, e*j+k] for k in range(e))) - ptemp = part_trace[0,0] # part_trace == psymb*M.parent().one() + part_trace = matrix(B, 4, 4, lambda i, j: sum(M[e * i + k, e * j + k] for k in range(e))) + ptemp = part_trace[0, 0] # part_trace == psymb*M.parent().one() if use_symbolics: v1, v2 = R.variable_names() pstr = str(ptemp._sympy_().simplify()) pstr = pstr.replace('t0', v1).replace('t1', v2) - F = R.fraction_field() # to make coercion work + F = R.fraction_field() # to make coercion work return R(F(pstr)) else: ltemp = ptemp.lift().constant_coefficient() @@ -1016,15 +1031,15 @@ def _jones_polynomial(self): sage: B = BraidGroup(9) sage: b = B([1, 2, 3, 4, 5, 6, 7, 8]) - sage: b.jones_polynomial() + sage: b.jones_polynomial() # needs sage.symbolic 1 sage: B = BraidGroup(2) sage: b = B([]) - sage: b._jones_polynomial + sage: b._jones_polynomial # needs sage.symbolic -A^-2 - A^2 sage: b = B([-1, -1, -1]) - sage: b._jones_polynomial + sage: b._jones_polynomial # needs sage.symbolic -A^-16 + A^-12 + A^-4 """ trace = self.markov_trace(normalized=False) @@ -1072,25 +1087,26 @@ def jones_polynomial(self, variab=None, skein_normalization=False): sage: B = BraidGroup(9) sage: b = B([1, 2, 3, 4, 5, 6, 7, 8]) - sage: b.jones_polynomial() + sage: b.jones_polynomial() # needs sage.symbolic 1 Two unlinked unknots:: sage: B = BraidGroup(2) sage: b = B([]) - sage: b.jones_polynomial() + sage: b.jones_polynomial() # needs sage.symbolic -sqrt(t) - 1/sqrt(t) The Hopf link:: sage: B = BraidGroup(2) sage: b = B([-1,-1]) - sage: b.jones_polynomial() + sage: b.jones_polynomial() # needs sage.symbolic -1/sqrt(t) - 1/t^(5/2) Different representations of the trefoil and one of its mirror:: + sage: # needs sage.symbolic sage: B = BraidGroup(2) sage: b = B([-1, -1, -1]) sage: b.jones_polynomial(skein_normalization=True) @@ -1115,7 +1131,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False): sage: B = BraidGroup(4) sage: b11n42 = B([1, -2, 3, -2, 3, -2, -2, -1, 2, -3, -3, 2, 2]) sage: b11n34 = B([1, 1, 2, -3, 2, -3, 1, -2, -2, -3, -3]) - sage: bool(b11n42.jones_polynomial() == b11n34.jones_polynomial()) + sage: bool(b11n42.jones_polynomial() == b11n34.jones_polynomial()) # needs sage.symbolic True """ if skein_normalization: @@ -1124,12 +1140,14 @@ def jones_polynomial(self, variab=None, skein_normalization=False): else: return self._jones_polynomial(variab) else: - from sage.symbolic.ring import SR from sage.rings.integer_ring import ZZ if variab is None: variab = 't' + if not isinstance(variab, Expression): + from sage.symbolic.ring import SR + variab = SR(variab) # We force the result to be in the symbolic ring because of the expand - return self._jones_polynomial(SR(variab)**(ZZ(1)/ZZ(4))).expand() + return self._jones_polynomial(variab**(ZZ(1)/ZZ(4))).expand() @cached_method def _enhanced_states(self): @@ -1322,8 +1340,6 @@ def _annular_khovanov_complex_cached(self, qagrad, ring=None): sage: B = BraidGroup(3) sage: B([1,2,1,2])._annular_khovanov_complex_cached((5,-1)).homology() {1: Z, 2: Z, 3: 0} - - """ from sage.homology.chain_complex import ChainComplex if ring is None: @@ -1492,16 +1508,16 @@ def left_normal_form(self, algorithm='libbraiding'): (1,) sage: b = B([-2, 2, -4, -4, 4, -5, -1, 4, -1, 1]) sage: L1 = b.left_normal_form(); L1 - (s0^-1*s1^-1*s2^-1*s3^-1*s4^-1*s0^-1*s1^-1*s2^-1*s3^-1*s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1, - s0*s2*s1*s0*s3*s2*s1*s0*s4*s3*s2*s1, - s3) + (s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1*s4^-1*s3^-1*s2^-1*s1^-1*s0^-1, + s0*s2*s1*s0*s3*s2*s1*s0*s4*s3*s2*s1, + s3) sage: L1 == b.left_normal_form() True sage: B([1]).left_normal_form(algorithm='artin') (1, s0) sage: B([-3]).left_normal_form(algorithm='artin') - (s0^-1*s1^-1*s2^-1*s3^-1*s4^-1*s0^-1*s1^-1*s2^-1*s3^-1*s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1, - s0*s1*s0*s2*s1*s3*s2*s1*s0*s4*s3*s2*s1*s0) + (s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1*s4^-1*s3^-1*s2^-1*s1^-1*s0^-1, + s0*s1*s2*s3*s4*s0*s1*s2*s3*s1*s2*s0*s1*s0) sage: B = BraidGroup(3) sage: B([1,2,-1]).left_normal_form() (s0^-1*s1^-1*s0^-1, s1*s0, s0*s1) @@ -1509,9 +1525,9 @@ def left_normal_form(self, algorithm='libbraiding'): (s0*s1*s0,) """ if algorithm == 'libbraiding': - l = leftnormalform(self) + lnf = leftnormalform(self) B = self.parent() - return tuple([B.delta()**l[0][0]] + [B(b) for b in l[1:]] ) + return tuple([B.delta()**lnf[0][0]] + [B(b) for b in lnf[1:]]) elif algorithm == 'artin': return FiniteTypeArtinGroupElement.left_normal_form.f(self) raise ValueError("invalid algorithm") @@ -1552,11 +1568,11 @@ def _left_normal_form_coxeter(self): delta = 0 Delta = self.parent()._coxeter_group.long_element() sr = self.parent()._coxeter_group.simple_reflections() - l = self.Tietze() - if not l: + tz = self.Tietze() + if not tz: return (0,) form = [] - for i in l: + for i in tz: if i > 0: form.append(sr[i]) else: @@ -1604,9 +1620,9 @@ def right_normal_form(self): sage: b.right_normal_form() (s1*s0, s0*s2, 1) """ - l = rightnormalform(self) + rnf = rightnormalform(self) B = self.parent() - return tuple([B(b) for b in l[:-1]] + [B.delta()**l[-1][0]]) + return tuple([B(b) for b in rnf[:-1]] + [B.delta()**rnf[-1][0]]) def centralizer(self): """ @@ -1620,9 +1636,9 @@ def centralizer(self): [s1*s0*s2*s1, s0*s2] """ - l = centralizer(self) + c = centralizer(self) B = self.parent() - return [B._element_from_libbraiding(b) for b in l] + return [B._element_from_libbraiding(b) for b in c] def super_summit_set(self): """ @@ -1634,14 +1650,14 @@ def super_summit_set(self): sage: b = B([1, 2, -1, -2, -2, 1]) sage: b.super_summit_set() [s0^-1*s1^-1*s0^-2*s1^2*s0^2, - (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] + (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] """ - l = supersummitset(self) + sss = supersummitset(self) B = self.parent() - return [B._element_from_libbraiding(b) for b in l] + return [B._element_from_libbraiding(b) for b in sss] def gcd(self, other): """ @@ -1721,8 +1737,8 @@ def conjugating_braid(self, other): True sage: d1 * a / d1 == c False - sage: l = sage.groups.braid.conjugatingbraid(a,c) - sage: d1 == B._element_from_libbraiding(l) + sage: l = sage.groups.braid.conjugatingbraid(a,c) # needs sage.groups + sage: d1 == B._element_from_libbraiding(l) # needs sage.groups True sage: b = B([2, 2, 2, 2, 1]) sage: c = b * a / b @@ -1735,20 +1751,20 @@ def conjugating_braid(self, other): False sage: d1 s1^2*s0^2*s1^2*s0 - sage: l = sage.groups.braid.conjugatingbraid(a,c) - sage: d2 = B._element_from_libbraiding(l) - sage: len(d2.Tietze()) + sage: l = sage.groups.braid.conjugatingbraid(a,c) # needs sage.groups + sage: d2 = B._element_from_libbraiding(l) # needs sage.groups + sage: len(d2.Tietze()) # needs sage.groups 13 sage: c.conjugating_braid(b) is None True """ - l = conjugatingbraid(self, other) - if not l: + cb = conjugatingbraid(self, other) + if not cb: return None else: B = self.parent() - l[0][0] %= 2 - return B._element_from_libbraiding(l) + cb[0][0] %= 2 + return B._element_from_libbraiding(cb) def is_conjugated(self, other): """ @@ -1769,8 +1785,8 @@ def is_conjugated(self, other): sage: c.is_conjugated(b) False """ - l = conjugatingbraid(self, other) - return bool(l) + cb = conjugatingbraid(self, other) + return bool(cb) def pure_conjugating_braid(self, other): r""" @@ -1857,7 +1873,7 @@ def pure_conjugating_braid(self, other): if p3 not in S.subgroup(LP): return None P = p3.word_problem(list(LP), display=False, as_list=True) - b1 = prod(LP[S(a)] ** b for a,b in P) + b1 = prod(LP[S(a)] ** b for a, b in P) b0 = b1 * b0 n0 = len(b0.Tietze()) L = leftnormalform(b0) @@ -1879,17 +1895,17 @@ def ultra_summit_set(self): [[s0*s1*s0^2, (s0*s1)^2]] sage: a.ultra_summit_set() [[(s0^-1*s1^-1*s0^-1)^2*s1^3*s0^2*s1^3, - (s0^-1*s1^-1*s0^-1)^2*s1^2*s0^2*s1^4, - (s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^5, - s0^-1*s1^-1*s0^-2*s1^5*s0, - (s0^-1*s1^-1*s0^-1)^2*s1^5*s0^2*s1, - (s0^-1*s1^-1*s0^-1)^2*s1^4*s0^2*s1^2], - [s0^-1*s1^-1*s0^-2*s1^-1*s0^2*s1^2*s0^3, - s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^2*s0^4, - s0^-1*s1^-1*s0^-2*s1*s0^5, - (s0^-1*s1^-1*s0^-1)^2*s1*s0^6*s1, - s0^-1*s1^-1*s0^-2*s1^-1*s0^4*s1^2*s0, - s0^-1*s1^-1*s0^-2*s1^-1*s0^3*s1^2*s0^2]] + (s0^-1*s1^-1*s0^-1)^2*s1^2*s0^2*s1^4, + (s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^5, + s0^-1*s1^-1*s0^-2*s1^5*s0, + (s0^-1*s1^-1*s0^-1)^2*s1^5*s0^2*s1, + (s0^-1*s1^-1*s0^-1)^2*s1^4*s0^2*s1^2], + [s0^-1*s1^-1*s0^-2*s1^-1*s0^2*s1^2*s0^3, + s0^-1*s1^-1*s0^-2*s1^-1*s0*s1^2*s0^4, + s0^-1*s1^-1*s0^-2*s1*s0^5, + (s0^-1*s1^-1*s0^-1)^2*s1*s0^6*s1, + s0^-1*s1^-1*s0^-2*s1^-1*s0^4*s1^2*s0, + s0^-1*s1^-1*s0^-2*s1^-1*s0^3*s1^2*s0^2]] """ uss = ultrasummitset(self) B = self.parent() @@ -2110,19 +2126,19 @@ def deformed_burau_matrix(self, variab='q'): """ R = LaurentPolynomialRing(IntegerRing(), variab) n = self.strands() - m = len(self.Tietze()) + tz = self.Tietze() + m = len(tz) from sage.algebras.free_algebra import FreeAlgebra - alg = FreeAlgebra(R, m*3, [f'{s}p_{i}' - for i in range(m) if self.Tietze()[i] > 0 - for s in 'bca'] - + [f'{s}m_{i}' - for i in range(m) if self.Tietze()[i] < 0 - for s in 'bca']) - gen_indices = ([i for i in range(m) if self.Tietze()[i] > 0] - + [i for i in range(m) if self.Tietze()[i] < 0]) + alg = FreeAlgebra(R, m*3, + [f'{s}p_{i}' for i in range(m) if tz[i] > 0 + for s in 'bca'] + + [f'{s}m_{i}' for i in range(m) if tz[i] < 0 + for s in 'bca']) + gen_indices = ([i for i in range(m) if tz[i] > 0] + + [i for i in range(m) if tz[i] < 0]) M = identity_matrix(alg, n) - for k, i in enumerate(self.Tietze()): + for k, i in enumerate(tz): A = identity_matrix(alg, n) gen_index = gen_indices.index(k) b, c, a = alg.gens()[3*gen_index:3*gen_index+3] @@ -2469,8 +2485,8 @@ def eps_monom(q_tuple): ret_q *= prod(prod(1 - q**(N - 1 - q_tuple[3*i + 1] - h) for h in range(q_tuple[3*i + 2])) for i in range(self._minus_begin//3)) - ret_q *= prod(prod(1 - q**(q_tuple[3*j + 1] + l + 1 - N) - for l in range(q_tuple[3*j + 2])) + ret_q *= prod(prod(1 - q**(q_tuple[3*j + 1] + k + 1 - N) + for k in range(q_tuple[3*j + 2])) for j in range(self._minus_begin//3, len(q_tuple)//3)) return ret_q @@ -2561,10 +2577,10 @@ def __init__(self, names): d*f*d^-1*f^-1, e*f*e*f^-1*e^-1*f^-1) - sage: BraidGroup([]) - Traceback (most recent call last): - ... - ValueError: the number of strands must be at least 2 + sage: BraidGroup([]) + Traceback (most recent call last): + ... + ValueError: the number of strands must be at least 2 """ n = len(names) # n is the number of generators, not the number of strands @@ -2613,7 +2629,7 @@ def _repr_(self): TESTS:: sage: B1 = BraidGroup(5) - sage: B1 # indirect doctest + sage: B1 # indirect doctest Braid group on 5 strands """ return "Braid group on %s strands" % self._nstrands @@ -2678,7 +2694,14 @@ def _element_constructor_(self, x): sage: B = BraidGroup(4) sage: B([1, 2, 3]) # indirect doctest s0*s1*s2 - """ + sage: p = Permutation([3,1,2,4]); B(p) + s0*s1 + sage: q = SymmetricGroup(4)((1,2)); B(q) + s0 + """ + if not isinstance(x, (tuple, list)): + if isinstance(x, (SymmetricGroupElement, Permutation)): + x = self._standard_lift_Tietze(x) return self.element_class(self, x) def an_element(self): @@ -2732,7 +2755,7 @@ def _standard_lift_Tietze(self, p): OUTPUT: - The lexicographically smallest word that represents the braid, + A shortest word that represents the braid, in Tietze list form. EXAMPLES:: @@ -2740,22 +2763,11 @@ def _standard_lift_Tietze(self, p): sage: B = BraidGroup(5) sage: P = Permutation([5, 3, 1, 2, 4]) sage: B._standard_lift_Tietze(P) - (1, 2, 1, 3, 2, 4) - """ - if not p.length(): - return () - pl = p - l = [] - while pl.length(): - i = 1 - while i < max(pl): - if pl(i) > pl(i+1): - l.append(i) - pl = self._coxeter_group.simple_reflection(i) * pl - i = 1 - else: - i += 1 - return tuple(l) + (1, 2, 3, 4, 1, 2) + """ + G = SymmetricGroup(self.strands()) + pl = G(p) + return tuple(pl.reduced_word()) @cached_method def _links_gould_representation(self, symbolics=False): @@ -2788,7 +2800,7 @@ def _links_gould_representation(self, symbolics=False): """ from sage.matrix.constructor import matrix n = self.strands() - d = 4 # dimension of the natural module + d = 4 # dimension of the natural module from sage.matrix.special import diagonal_matrix if symbolics: from sage.symbolic.ring import SR as BR @@ -2805,7 +2817,7 @@ def _links_gould_representation(self, symbolics=False): LR = LaurentPolynomialRing(ZZ, 's0r, s1r') PR = PolynomialRing(LR, 'Yr') s0r, s1r, Yr = PR.gens_dict_recursive().values() - pqr = Yr**2 + (s0r**2-1)*(s1r**2 -1) + pqr = Yr**2 + (s0r**2 - 1) * (s1r**2 - 1) BR = PR.quotient_ring(pqr) s0 = BR(s0r) s1 = BR(s1r) @@ -2819,12 +2831,12 @@ def _links_gould_representation(self, symbolics=False): if n == 2: # R-Matrix taken from I. Marin R = matrix(BR, {(0, 0): t0, (1, 4): s0, (2, 8): s0, (3, 12): 1, - (4, 1): s0, (4, 4): t0 - 1, (5, 5): -1, (6, 6): t0*t1 - 1, - (6, 9): -s0*s1, (6, 12): -Y*s0*s1, (7, 13): s1, (8, 2): s0, - (8, 8): t0 - 1, (9, 6): -s0*s1, (9, 12): Y, (10, 10): -1, - (11, 14): s1, (12, 3): 1, (12, 6): -Y*s0*s1, (12, 9): Y, - (12, 12): -(t0 - 1)*(t1 - 1), (13, 7): s1, (13, 13): t1 - 1, - (14, 11): s1, (14, 14): t1 - 1, (15, 15): t1}, sparse=sparse) + (4, 1): s0, (4, 4): t0 - 1, (5, 5): -1, (6, 6): t0*t1 - 1, + (6, 9): -s0*s1, (6, 12): -Y*s0*s1, (7, 13): s1, (8, 2): s0, + (8, 8): t0 - 1, (9, 6): -s0*s1, (9, 12): Y, (10, 10): -1, + (11, 14): s1, (12, 3): 1, (12, 6): -Y*s0*s1, (12, 9): Y, + (12, 12): -(t0 - 1)*(t1 - 1), (13, 7): s1, (13, 13): t1 - 1, + (14, 11): s1, (14, 14): t1 - 1, (15, 15): t1}, sparse=sparse) RI = (~t0 + ~t1)*(1 + R) - ~t0*~t1*(R + R**2) - 1 # quantum trace operator on two fold tensor space @@ -2901,58 +2913,58 @@ def _LKB_matrix_(self, braid, variab): for i in braid[1:]: A = A*self._LKB_matrix_((i,), variab) return A - l = list(Set(range(n)).subsets(2)) + n2 = [set(X) for X in combinations(range(n), 2)] R = LaurentPolynomialRing(IntegerRing(), variab) q = R.gens()[0] t = R.gens()[1] if not braid: - return identity_matrix(R, len(l), sparse=True) - A = matrix(R, len(l), sparse=True) + return identity_matrix(R, len(n2), sparse=True) + A = matrix(R, len(n2), sparse=True) if braid[0] > 0: - i = braid[0]-1 - for m in range(len(l)): - j = min(l[m]) - k = max(l[m]) + i = braid[0] - 1 + for m in range(len(n2)): + j = min(n2[m]) + k = max(n2[m]) if i == j-1: - A[l.index(Set([i, k])), m] = q - A[l.index(Set([i, j])), m] = q*q-q - A[l.index(Set([j, k])), m] = 1-q + A[n2.index(Set([i, k])), m] = q + A[n2.index(Set([i, j])), m] = q*q-q + A[n2.index(Set([j, k])), m] = 1-q elif i == j and not j == k-1: - A[l.index(Set([j, k])), m] = 0 - A[l.index(Set([j+1, k])), m] = 1 + A[n2.index(Set([j, k])), m] = 0 + A[n2.index(Set([j+1, k])), m] = 1 elif k-1 == i and not k-1 == j: - A[l.index(Set([j, i])), m] = q - A[l.index(Set([j, k])), m] = 1-q - A[l.index(Set([i, k])), m] = (1-q)*q*t + A[n2.index(Set([j, i])), m] = q + A[n2.index(Set([j, k])), m] = 1-q + A[n2.index(Set([i, k])), m] = (1-q)*q*t elif i == k: - A[l.index(Set([j, k])), m] = 0 - A[l.index(Set([j, k+1])), m] = 1 + A[n2.index(Set([j, k])), m] = 0 + A[n2.index(Set([j, k+1])), m] = 1 elif i == j and j == k-1: - A[l.index(Set([j, k])), m] = -t*q*q + A[n2.index(Set([j, k])), m] = -t*q*q else: - A[l.index(Set([j, k])), m] = 1 + A[n2.index(Set([j, k])), m] = 1 return A else: i = -braid[0]-1 - for m in range(len(l)): - j = min(l[m]) - k = max(l[m]) + for m in range(len(n2)): + j = min(n2[m]) + k = max(n2[m]) if i == j-1: - A[l.index(Set([j-1, k])), m] = 1 + A[n2.index(Set([j-1, k])), m] = 1 elif i == j and not j == k-1: - A[l.index(Set([j+1, k])), m] = q**(-1) - A[l.index(Set([j, k])), m] = 1-q**(-1) - A[l.index(Set([j, j+1])), m] = t**(-1)*q**(-1)-t**(-1)*q**(-2) + A[n2.index(Set([j+1, k])), m] = q**(-1) + A[n2.index(Set([j, k])), m] = 1-q**(-1) + A[n2.index(Set([j, j+1])), m] = t**(-1)*q**(-1)-t**(-1)*q**(-2) elif k-1 == i and not k-1 == j: - A[l.index(Set([j, k-1])), m] = 1 + A[n2.index(Set([j, k-1])), m] = 1 elif i == k: - A[l.index(Set([j, k+1])), m] = q**(-1) - A[l.index(Set([j, k])), m] = 1-q**(-1) - A[l.index(Set([k, k+1])), m] = -q**(-1)+q**(-2) + A[n2.index(Set([j, k+1])), m] = q**(-1) + A[n2.index(Set([j, k])), m] = 1-q**(-1) + A[n2.index(Set([k, k+1])), m] = -q**(-1)+q**(-2) elif i == j and j == k-1: - A[l.index(Set([j, k])), m] = -t**(-1)*q**(-2) + A[n2.index(Set([j, k])), m] = -t**(-1)*q**(-2) else: - A[l.index(Set([j, k])), m] = 1 + A[n2.index(Set([j, k])), m] = 1 return A def dimension_of_TL_space(self, drain_size): @@ -2981,11 +2993,11 @@ def dimension_of_TL_space(self, drain_size): The direct sum of endomorphism spaces of these vector spaces make up the entire Temperley--Lieb algebra:: - sage: import sage.combinat.diagram_algebras as da + sage: import sage.combinat.diagram_algebras as da # needs sage.combinat sage: B = BraidGroup(6) sage: dimensions = [B.dimension_of_TL_space(d)**2 for d in [0, 2, 4, 6]] sage: total_dim = sum(dimensions) - sage: total_dim == len(list(da.temperley_lieb_diagrams(6))) # long time + sage: total_dim == len(list(da.temperley_lieb_diagrams(6))) # long time, needs sage.combinat True """ n = self.strands() @@ -3364,7 +3376,7 @@ def _element_from_libbraiding(self, nf): sage: B = BraidGroup(5) sage: B._element_from_libbraiding([[-2], [2, 1], [1, 2], [2, 1]]) - (s0^-1*s1^-1*s2^-1*s3^-1*s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^2*s0 + (s0^-1*s1^-1*s0^-1*s2^-1*s1^-1*s0^-1*s3^-1*s2^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^2*s0 sage: B._element_from_libbraiding([[0]]) 1 """ @@ -3397,6 +3409,96 @@ def mirror_involution(self): gens_mirr = [~g for g in self.gens()] return self.hom(gens_mirr, check=False) + def presentation_two_generators(self, isomorphisms=False): + r""" + Construct a finitely presented group isomorphic to ``self`` with only two generators. + + INPUT: + + - ``isomorphism`` -- boolean (default ``False``); if ``True``, then an isomorphism + from ``self`` and the isomorphic group and its inverse is also returned + + EXAMPLES:: + + sage: B = BraidGroup(3) + sage: B.presentation_two_generators() + Finitely presented group < x0, x1 | x1^3*x0^-2 > + sage: B = BraidGroup(4) + sage: G, hom1, hom2 = B.presentation_two_generators(isomorphisms=True) + sage: G + Finitely presented group < x0, x1 | x1^4*x0^-3, x0*x1*x0*x1^-2*x0^-1*x1^3*x0^-1*x1^-2 > + sage: hom1(B.gen(0)) + x0*x1^-1 + sage: hom1(B.gen(1)) + x1*x0*x1^-2 + sage: hom1(B.gen(2)) + x1^2*x0*x1^-3 + sage: all(hom2(hom1(a)) == a for a in B.gens()) + True + sage: all(hom2(a) == B.one() for a in G.relations()) + True + """ + n = self.strands() + F = FreeGroup(2, "x") + rel = [n * (2,) + (n - 1) * (-1,)] + rel += [(1,) + (j - 1) * (2,) + (1,) + j * (-2,) + (-1,) + (j + 1) * (2,) + (-1,) + j * (-2,) + for j in range(2, n - 1)] + G = F / rel + if not isomorphisms: + return G + a1 = (1, -2) + L1 = [j * (2,) + a1 + j * (-2,) for j in range(n - 1)] + h1 = self.hom(codomain=G, im_gens=[G(a) for a in L1], check=False) + a2 = tuple(range(1, n)) + L2 = [(1,) + a2, a2] + h2 = G.hom(codomain=self, im_gens=[self(a) for a in L2], check=False) + return (G, h1, h2) + + def epimorphisms(self, H): + r""" + Return the epimorphisms from ``self`` to ``H``, up to automorphism of `H` passing + through the :meth:`two generator presentation + ` of ``self``. + + INPUT: + + - `H` -- another group + + EXAMPLES:: + + sage: B = BraidGroup(5) + sage: B.epimorphisms(SymmetricGroup(5)) + [Generic morphism: + From: Braid group on 5 strands + To: Symmetric group of order 5! as a permutation group + Defn: s0 |--> (1,5) + s1 |--> (4,5) + s2 |--> (3,4) + s3 |--> (2,3)] + + ALGORITHM: + + Uses libgap's GQuotients function. + """ + G, hom1, hom2 = self.presentation_two_generators(isomorphisms=True) + from sage.misc.misc_c import prod + HomSpace = self.Hom(H) + G0g = libgap(self) + Gg = libgap(G) + Hg = libgap(H) + gquotients = Gg.GQuotients(Hg) + hom1g = libgap.GroupHomomorphismByImagesNC(G0g, Gg, [libgap(hom1(u)) for u in self.gens()]) + g0quotients = [hom1g * h for h in gquotients] + res = [] + # the following closure is needed to attach a specific value of quo to + # each function in the different morphisms + fmap = lambda tup: (lambda a: H(prod(tup[abs(i)-1]**sign(i) for i in a.Tietze()))) + for quo in g0quotients: + tup = tuple(H(quo.ImageElm(i.gap()).sage()) for i in self.gens()) + fhom = GroupMorphismWithGensImages(HomSpace, fmap(tup)) + res.append(fhom) + return res + def BraidGroup(n=None, names='s'): """ @@ -3441,14 +3543,14 @@ def BraidGroup(n=None, names='s'): ....: ret.add(prod(w)) ....: return ret sage: B = BraidGroup(4) - sage: GB = B.cayley_graph(elements=ball(B, 4), generators=B.gens()); GB + sage: GB = B.cayley_graph(elements=ball(B, 4), generators=B.gens()); GB # needs sage.combinat sage.graphs Digraph on 31 vertices Since the braid group has nontrivial relations, this graph contains less vertices than the one associated to the free group (which is a tree):: sage: F = FreeGroup(3) - sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF + sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF # needs sage.combinat sage.graphs Digraph on 40 vertices TESTS:: diff --git a/src/sage/groups/cactus_group.py b/src/sage/groups/cactus_group.py index 9a481cc783c..a12fbb88563 100644 --- a/src/sage/groups/cactus_group.py +++ b/src/sage/groups/cactus_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.number_field r""" Cactus Groups @@ -970,7 +971,7 @@ def gens(self): sage: gen == b True """ - from sage.functions.other import factorial + from sage.arith.misc import factorial J = self.ambient() G = J.gens() one = J.one() diff --git a/src/sage/groups/class_function.py b/src/sage/groups/class_function.py index 08d69ce57b0..c788a596809 100644 --- a/src/sage/groups/class_function.py +++ b/src/sage/groups/class_function.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.number_field r""" Class functions of groups. @@ -27,10 +28,12 @@ from sage.structure.richcmp import richcmp, richcmp_method from sage.interfaces.gap import gap from sage.rings.integer import Integer -from sage.rings.number_field.number_field import CyclotomicField from sage.libs.gap.element import GapElement from sage.libs.gap.libgap import libgap from sage.libs.gap.element import GapElement as LibGapElement +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.rings.number_field.number_field', 'CyclotomicField') # TODO: # @@ -712,7 +715,8 @@ def restrict(self, H): Character of Symmetric group of order 5! as a permutation group sage: H = G.subgroup([(1,2,3), (1,2), (4,5)]) sage: chi.restrict(H) - Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of (Symmetric group of order 5! as a permutation group) + Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of + (Symmetric group of order 5! as a permutation group) sage: chi.restrict(H).values() [3, -3, -3, -1, 0, 0] """ @@ -738,7 +742,8 @@ def induct(self, G): sage: G = SymmetricGroup(5) sage: H = G.subgroup([(1,2,3), (1,2), (4,5)]) sage: xi = H.trivial_character(); xi - Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of (Symmetric group of order 5! as a permutation group) + Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of + (Symmetric group of order 5! as a permutation group) sage: xi.induct(G) Character of Symmetric group of order 5! as a permutation group sage: xi.induct(G).values() @@ -1331,7 +1336,7 @@ def values(self): EXAMPLES:: sage: G = GL(2,3) - sage: [x.values() for x in G.irreducible_characters()] #random + sage: [x.values() for x in G.irreducible_characters()] # random [[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, -1, -1, -1], [2, -1, 2, -1, 2, 0, 0, 0], @@ -1409,7 +1414,8 @@ def restrict(self, H): Character of Symmetric group of order 5! as a permutation group sage: H = G.subgroup([(1,2,3), (1,2), (4,5)]) sage: chi.restrict(H) - Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of (Symmetric group of order 5! as a permutation group) + Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of + (Symmetric group of order 5! as a permutation group) sage: chi.restrict(H).values() [3, -3, -3, -1, 0, 0] """ @@ -1440,7 +1446,8 @@ def induct(self, G): sage: G = SymmetricGroup(5) sage: H = G.subgroup([(1,2,3), (1,2), (4,5)]) sage: xi = H.trivial_character(); xi - Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of (Symmetric group of order 5! as a permutation group) + Character of Subgroup generated by [(4,5), (1,2), (1,2,3)] of + (Symmetric group of order 5! as a permutation group) sage: xi.induct(G) Character of Symmetric group of order 5! as a permutation group sage: xi.induct(G).values() diff --git a/src/sage/groups/conjugacy_classes.py b/src/sage/groups/conjugacy_classes.py index fd79d60ee5b..4ad8200ef23 100644 --- a/src/sage/groups/conjugacy_classes.py +++ b/src/sage/groups/conjugacy_classes.py @@ -24,7 +24,7 @@ sage: G = SymmetricGroup(4) sage: g = G((1,2,3,4)) - sage: G.conjugacy_class(g) + sage: G.conjugacy_class(g) # needs sage.combinat Conjugacy class of cycle type [4] in Symmetric group of order 4! as a permutation group Conjugacy classes for groups of matrices:: @@ -90,7 +90,7 @@ def __init__(self, group, element): sage: ConjugacyClass(G,g) Conjugacy class of (1,2,3,4) in Symmetric group of order 4! as a permutation group - sage: TestSuite(G).run() + sage: TestSuite(G).run() # needs sage.rings.number_field """ self._parent = group self._representative = element @@ -432,6 +432,7 @@ def cardinality(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: W = WeylGroup(['C',6]) sage: cc = W.conjugacy_class(W.an_element()) sage: cc.cardinality() @@ -449,6 +450,7 @@ def __contains__(self, g): TESTS:: + sage: # needs sage.rings.number_field sage: W = WeylGroup(['C',6]) sage: g0,g1,g2,g3,g4,g5 = W.gens() sage: cc = W.conjugacy_class(g0) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index f49293e9924..e8cb4a4e19f 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -80,19 +80,22 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +from enum import Enum + +import sage.rings.abc + from sage.categories.groups import Groups from sage.categories.shephard_groups import ShephardGroups -from sage.misc.cachefunc import cached_method -from sage.libs.gap.element import GapElement from sage.groups.free_group import FreeGroup from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement from sage.groups.braid import BraidGroup +from sage.misc.cachefunc import cached_method from sage.rings.integer import Integer -from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField -from sage.rings.number_field.number_field import CyclotomicField -from sage.rings.finite_rings.finite_field_constructor import GF -from enum import Enum +try: + from sage.libs.gap.element import GapElement +except ImportError: + GapElement = () ############################################################################## @@ -386,13 +389,15 @@ def burau_matrix(self, root_bur=None, domain=None, characteristic=None, sage: C3. = CubicBraidGroup(3) sage: ele = c1*c2*c1 + + sage: # needs sage.rings.number_field sage: BuMa = ele.burau_matrix(); BuMa [ -zeta3 1 zeta3] [ -zeta3 zeta3 + 1 0] [ 1 0 0] sage: BuMa.base_ring() Cyclotomic Field of order 3 and degree 2 - sage: BuMa == ele.burau_matrix(characteristic = 0) + sage: BuMa == ele.burau_matrix(characteristic=0) True sage: BuMa = ele.burau_matrix(domain=QQ); BuMa [-t + 1 1 t - 1] @@ -400,18 +405,21 @@ def burau_matrix(self, root_bur=None, domain=None, characteristic=None, [ 1 0 0] sage: BuMa.base_ring() Number Field in t with defining polynomial t^2 - t + 1 - sage: BuMa = ele.burau_matrix(domain = QQ[I, sqrt(3)]); BuMa + sage: BuMa = ele.burau_matrix(domain = QQ[I, sqrt(3)]); BuMa # needs sage.symbolic [ 1/2*sqrt3*I + 1/2 1 -1/2*sqrt3*I - 1/2] [ 1/2*sqrt3*I + 1/2 -1/2*sqrt3*I + 1/2 0] [ 1 0 0] - sage: BuMa.base_ring() + sage: BuMa.base_ring() # needs sage.symbolic Number Field in I with defining polynomial x^2 + 1 over its base field + sage: BuMa = ele.burau_matrix(characteristic=7); BuMa [3 1 4] [3 5 0] [1 0 0] sage: BuMa.base_ring() Finite Field of size 7 + + sage: # needs sage.rings.finite_rings sage: BuMa = ele.burau_matrix(characteristic=2); BuMa [t + 1 1 t + 1] [t + 1 t 0] @@ -431,6 +439,8 @@ def burau_matrix(self, root_bur=None, domain=None, characteristic=None, [ 1 0 0] sage: BuMa.base_ring() Finite Field in t of size 5^2 + + sage: # needs sage.rings.number_field sage: BuMa, BuMaAd, H = ele.burau_matrix(reduced='unitary'); BuMa [ 0 zeta12^3] [zeta12^3 0] @@ -438,10 +448,11 @@ def burau_matrix(self, root_bur=None, domain=None, characteristic=None, True sage: BuMa.base_ring() Cyclotomic Field of order 12 and degree 4 - sage: BuMa, BuMaAd, H = ele.burau_matrix(domain = QQ[I, sqrt(3)], reduced='unitary'); BuMa + sage: BuMa, BuMaAd, H = ele.burau_matrix(domain=QQ[I, sqrt(3)], # needs sage.symbolic + ....: reduced='unitary'); BuMa [0 I] [I 0] - sage: BuMa.base_ring() + sage: BuMa.base_ring() # needs sage.symbolic Number Field in I with defining polynomial x^2 + 1 over its base field """ braid = self.braid() @@ -460,7 +471,7 @@ def burau_matrix(self, root_bur=None, domain=None, characteristic=None, burau_ori, burau_ori_adj, herm_form_ori = burau_ori if domain is not None: - if isinstance(domain, UniversalCyclotomicField): + if isinstance(domain, sage.rings.abc.UniversalCyclotomicField): if root_bur is None: if unitary: root_bur = domain.gen(12) @@ -504,11 +515,13 @@ def find_root(domain): 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 if unitary: domain = CyclotomicField(12) else: domain = CyclotomicField(3) else: + from sage.rings.finite_rings.finite_field_constructor import GF domain = GF(characteristic) root_bur = find_root(domain) domain = root_bur.parent() @@ -628,13 +641,15 @@ class CubicBraidGroup(FinitelyPresentedGroup): #I Forcing finiteness test True sage: U3.as_classical_group() - Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), + (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) sage: C3.as_classical_group() Subgroup with 2 generators ( [ E(3)^2 0] [ 1 -E(12)^7] [-E(12)^7 1], [ 0 E(3)^2] - ) of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to positive definite hermitian form + ) of General Unitary Group of degree 2 over Universal Cyclotomic Field + with respect to positive definite hermitian form [-E(12)^7 + E(12)^11 -1] [ -1 -E(12)^7 + E(12)^11] @@ -805,9 +820,9 @@ def _repr_(self): Assion group on 2 strands of type U """ if self._cbg_type == CubicBraidGroup.type.Coxeter: - return "Cubic Braid group on %s strands"%(self.strands()) + return "Cubic Braid group on %s strands" % (self.strands()) else: - return "Assion group on %s strands of type %s"%(self.strands() ,self._cbg_type.value) + return "Assion group on %s strands of type %s" % (self.strands() ,self._cbg_type.value) def index_set(self): r""" @@ -901,7 +916,7 @@ def _internal_test_attached_group(self, attached_group, tester): elem = self.an_element() att_grp_elem = attached_group(elem) if self.is_finite() and self.strands() <= 7: # not realistic for larger number of strands - att_grp_elem_back= self(att_grp_elem) + att_grp_elem_back = self(att_grp_elem) tester.assertEqual(att_grp_elem_back, elem) return @@ -963,12 +978,19 @@ def _test_matrix_group(self, **options): sage: CBG2._test_matrix_group() """ tester = self._tester(**options) + + MatDEF = self.as_matrix_group() + self._internal_test_attached_group(MatDEF, tester) + + try: + from sage.rings.finite_rings.finite_field_constructor import GF + except ImportError: + return + F3 = GF(3) r63 = F3(2) F4 = GF(4) r64 = F4.gen() - MatDEF = self.as_matrix_group() - self._internal_test_attached_group(MatDEF, tester) if self._cbg_type != CubicBraidGroup.type.AssionU or self.strands() < 5: # not well defined else-wise matrix_grpF3 = self.as_matrix_group(root_bur=r63) @@ -1161,14 +1183,14 @@ def create_sympl_realization(self, m): # computing a hyperbolic decomposition basis with respect # to the invariant bilinear form. # ----------------------------------------------------------- - xbas =[bas[mhalf -i -1] for i in range(mhalf)] - ybas =[bas[mhalf +i] for i in range(mhalf)] + xbas = [bas[mhalf - i - 1] for i in range(mhalf)] + ybas = [bas[mhalf + i] for i in range(mhalf)] # ----------------------------------------------------------- # computing the List of transvection vectors according to # the Assion paper, page 292. # ----------------------------------------------------------- - transvections =[xbas[0]] # t_1 = x_1 + transvections = [xbas[0]] # t_1 = x_1 for i in range(mhalf-1): transvections.append(ybas[i]) # t_{2i} = y_i transvections.append(xbas[i] + xbas[i+1]) # t_{2i+1} = x_j + x_(j+1) @@ -1234,26 +1256,26 @@ def create_unitary_realization(self, m): # computing a orthonormal basis with respect # to the invariant bilinear form. # ----------------------------------------------------------- - xbas =[] + xbas = [] for i in range(m): if 2*i == m-1: xbas.append(bas[i]) else: - xbas.append(a*bas[i] + a.frobenius()*bas[m-1 -i]) + xbas.append(a*bas[i] + a.frobenius()*bas[m-1 - i]) # ----------------------------------------------------------- # computing the List of transvection vectors according to # Assion paper, page 293. # ----------------------------------------------------------- - transvections =[xbas[0]] # t_1 = x_1 + transvections = [xbas[0]] # t_1 = x_1 if m > 1: transvections.append(xbas[0]+xbas[1]+xbas[2]) # t_2 = x_1 + x_2 + x_3 for j in range(mthird): pos = 3*(j+1)-1 transvections.append(xbas[pos-1]) # t_{3i} = x_{3i-1} - if pos +1 < 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: + 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} # ----------------------------------------------------------- @@ -1264,7 +1286,7 @@ def create_unitary_realization(self, m): def transvec2mat(v, bas=bas, bform=bform, fact=a): # note x does not change under conjugation, since it belongs to standard basis - t = [x + fact *(x * bform * v.conjugate()) * v for x in bas] + t = [x + fact * (x * bform * v.conjugate()) * v for x in bas] return matrix(F, t) # ------------------------------------------------------------------------------ @@ -1317,6 +1339,8 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): # now 1 + 2*cos(\pi/6)*i\theta = 1 + sqrt(3)*(-sqrt(3)/2 + I/2) = 1- 3/2 + sqrt(3)I/2 = z12^4 = - ~z12^2 # finally: Coxeter's Realization is the unitary Burau representation of Squier for s = ~z12 # ----------------------------------------------------------------------------------------------- + from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField + UCF = UniversalCyclotomicField() z12 = UCF.gen(12) classical_group = self.as_matrix_group(root_bur=~z12, domain=UCF, reduced='unitary') @@ -1464,6 +1488,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: C5 = CubicBraidGroup(5) sage: C5Mch5 = C5.as_matrix_group(characteristic=5); C5Mch5 Matrix group over Finite Field in t of size 5^2 with 4 generators ( @@ -1641,10 +1666,12 @@ def as_classical_group(self, embedded=False): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: U3 = AssionGroupU(3) sage: U3Cl = U3.as_classical_group(); U3Cl - Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] - of (The projective general unitary group of degree 3 over Finite Field of size 2) + Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), + (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of + (The projective general unitary group of degree 3 over Finite Field of size 2) sage: U3Clemb = U3.as_classical_group(embedded=True); U3Clemb Subgroup with 2 generators ( [0 0 a] [a + 1 a a] @@ -1668,6 +1695,8 @@ def as_classical_group(self, embedded=False): General Unitary Group of degree 3 over Finite Field in a of size 2^2 sage: U3Clemb.ambient() == U4Cl True + + sage: # needs sage.rings.number_field sage: C4 = CubicBraidGroup(4) sage: C4Cl = C4.as_classical_group(); C4Cl Subgroup with 3 generators ( @@ -1678,7 +1707,8 @@ def as_classical_group(self, embedded=False): [ 1 0 0] [ 0 1 -E(12)^7] [ 0 0 E(3)^2] - ) of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to positive definite hermitian form + ) of General Unitary Group of degree 3 over Universal Cyclotomic Field + with respect to positive definite hermitian form [-E(12)^7 + E(12)^11 -1 0] [ -1 -E(12)^7 + E(12)^11 -1] [ 0 -1 -E(12)^7 + E(12)^11] @@ -1726,27 +1756,29 @@ def as_reflection_group(self): EXAMPLES:: - sage: C3. = CubicBraidGroup(3) # optional - gap3 - sage: R3 = C3.as_reflection_group(); R3 # optional - gap3 + sage: # optional - gap3 + sage: C3. = CubicBraidGroup(3) + sage: R3 = C3.as_reflection_group(); R3 Irreducible complex reflection group of rank 2 and type ST4 - sage: R3.cartan_matrix() # optional - gap3 + sage: R3.cartan_matrix() [-2*E(3) - E(3)^2 E(3)^2] [ -E(3)^2 -2*E(3) - E(3)^2] - sage: R3.simple_roots() # optional - gap3 + sage: R3.simple_roots() Finite family {1: (0, -2*E(3) - E(3)^2), 2: (2*E(3)^2, E(3)^2)} - sage: R3.simple_coroots() # optional - gap3 + sage: R3.simple_coroots() Finite family {1: (0, 1), 2: (1/3*E(3) - 1/3*E(3)^2, 1/3*E(3) - 1/3*E(3)^2)} Conversion maps:: - sage: r = R3.an_element() # optional - gap3 - sage: cr = C3(r); cr # optional - gap3 + sage: # optional - gap3 + sage: r = R3.an_element() + sage: cr = C3(r); cr c1*c2 - sage: mr = r.matrix(); mr # optional - gap3 + sage: mr = r.matrix(); mr [ 1/3*E(3) - 1/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2] [-2/3*E(3) + 2/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2] - sage: C3Cl = C3.as_classical_group() # optional - gap3 - sage: C3Cl(cr) # optional - gap3 + sage: C3Cl = C3.as_classical_group() + sage: C3Cl(cr) [ E(3)^2 -E(4)] [-E(12)^7 0] @@ -1756,13 +1788,14 @@ def as_reflection_group(self): the classical group due to different hermitian forms for the unitary groups they live in:: - sage: C4 = CubicBraidGroup(4) # optional - gap3 - sage: R4 = C4.as_reflection_group() # optional - gap3 - sage: R4.invariant_form() # optional - gap3 + sage: # optional - gap3 + sage: C4 = CubicBraidGroup(4) + sage: R4 = C4.as_reflection_group() + sage: R4.invariant_form() [1 0 0] [0 1 0] [0 0 1] - sage: _ == C4.classical_invariant_form() # optional - gap3 + sage: _ == C4.classical_invariant_form() False """ # ------------------------------------------------------------------------------- @@ -1895,7 +1928,8 @@ def centralizing_element(self, embedded=False): sage: U3 = AssionGroupU(3); U3 Assion group on 3 strands of type U sage: U3Cl = U3.as_classical_group(); U3Cl - Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), + (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) sage: c = U3.centralizing_element(); c (1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15) diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 6a6efb98ad8..bd980632a74 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -135,6 +135,7 @@ from sage.libs.gap.libgap import libgap from sage.libs.gap.element import GapElement from sage.misc.cachefunc import cached_method +from sage.groups.free_group import FreeGroup from sage.groups.free_group import FreeGroupElement from sage.functions.generalized import sign from sage.matrix.constructor import matrix @@ -642,7 +643,7 @@ def rules(self): bfg = self._monoid_isomorphism.PreImagesRepresentative(bfpmon) btz = bfg.UnderlyingElement().TietzeWordAbstractWord(self._free_group.gap().GeneratorsOfGroup()) bf = self._free_group(btz.sage()) - dic[af]=bf + dic[af] = bf return dic def is_confluent(self): @@ -825,7 +826,7 @@ def _repr_(self): """ gens = ', '.join(self.variable_names()) rels = ', '.join([ str(r) for r in self.relations() ]) - return 'Finitely presented group ' + '< '+ gens + ' | ' + rels + ' >' + return 'Finitely presented group ' + '< ' + gens + ' | ' + rels + ' >' def _latex_(self): """ @@ -1111,7 +1112,7 @@ def direct_product(self, H, reduced=False, new_names=True): name_itr = _lexi_gen() # Python generator for lexicographical variable names gen_names = [next(name_itr) for i in GAP_gens] else: - gen_names= [str(g) for g in self.gens()] + [str(g) for g in H.gens()] + gen_names = [str(g) for g in self.gens()] + [str(g) for g in H.gens()] # Build the direct product in Sage for better variable names ret_F = FreeGroup(gen_names) ret_rls = tuple([ret_F(rel_word.TietzeWordAbstractWord(GAP_gens).sage()) @@ -1312,10 +1313,10 @@ def _element_constructor_(self, *args, **kwds): sage: H([1, 2, 1, -2]) # indirect doctest a*b*a*b^-1 """ - if len(args)!=1: + if len(args) != 1: return self.element_class(self, *args, **kwds) x = args[0] - if x==1: + if x == 1: return self.one() try: P = x.parent() @@ -1426,6 +1427,35 @@ def simplified(self): """ return self.simplification_isomorphism().codomain() + def sorted_presentation(self): + """ + Return the same presentation with the relations sorted to ensure equality. + + OUTPUT: + + A new finitely presented group with the relations sorted. + + EXAMPLES:: + + sage: G = FreeGroup(2) / [(1, 2, -1, -2), ()]; G + Finitely presented group < x0, x1 | x0*x1*x0^-1*x1^-1, 1 > + sage: G.sorted_presentation() + Finitely presented group < x0, x1 | 1, x1^-1*x0^-1*x1*x0 > + """ + F = FreeGroup(self.ngens()) + L0 = [r.Tietze() for r in self.relations()] + L1 = [] + for rel in L0: + C = [rel] + for j in range(len(rel) - 1): + C.append(rel[j + 1:] + rel[:j + 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 + def epimorphisms(self, H): r""" Return the epimorphisms from `self` to `H`, up to automorphism of `H`. diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py index 177f7908895..4f5e211a51f 100644 --- a/src/sage/groups/finitely_presented_named.py +++ b/src/sage/groups/finitely_presented_named.py @@ -196,7 +196,7 @@ def FinitelyGeneratedAbelianPresentation(int_list): invariants = FGP_Module(ZZ**(len(int_list)), col_sp).invariants() name_gen = _lexi_gen() F = FreeGroup([next(name_gen) for i in invariants]) - ret_rls = [F([i+1])**invariants[i] for i in range(len(invariants)) if invariants[i]!=0] + ret_rls = [F([i+1])**invariants[i] for i in range(len(invariants)) if invariants[i] != 0] # Build commutator relations gen_pairs = [[F.gen(i),F.gen(j)] for i in range(F.ngens()-1) for j in range(i+1,F.ngens())] @@ -285,7 +285,7 @@ def commutator(a, b): # Third set of relations: [z, yi] = 1 r3 = [commutator(z, y[i]) for i in range(n)] # Fourth set of relations: [xi, yi] = 1 for i != j - r4 = [commutator(x[i], y[j]) for i in range(n) for j in range(n) if i!=j] + r4 = [commutator(x[i], y[j]) for i in range(n) for j in range(n) if i != j] rls = r1 + r2 + r3 + r4 from sage.sets.primes import Primes @@ -548,7 +548,7 @@ def BinaryDihedralPresentation(n): TESTS:: - sage: for n in range(3, 9): + sage: for n in range(3, 9): # needs sage.modules ....: P = groups.presentation.BinaryDihedral(n) ....: M = groups.matrix.BinaryDihedral(n) ....: assert P.is_isomorphic(M) @@ -574,7 +574,7 @@ def CactusPresentation(n): EXAMPLES:: - sage: J3 = groups.presentation.Cactus(3); J3 + sage: J3 = groups.presentation.Cactus(3); J3 # needs sage.graphs Finitely presented group < s12, s13, s23 | s12^2, s13^2, s23^2, s13*s12*s13^-1*s23^-1, s13*s23*s13^-1*s12^-1 > """ diff --git a/src/sage/groups/fqf_orthogonal.py b/src/sage/groups/fqf_orthogonal.py index 32a434d3bd9..3d0c79ed7c3 100644 --- a/src/sage/groups/fqf_orthogonal.py +++ b/src/sage/groups/fqf_orthogonal.py @@ -8,19 +8,20 @@ EXAMPLES:: - sage: L = IntegralLattice("A2").twist(2) - sage: T = L.discriminant_group() - sage: Oq = T.orthogonal_group() + sage: L = IntegralLattice("A2").twist(2) # needs sage.graphs + sage: T = L.discriminant_group() # needs sage.graphs + sage: Oq = T.orthogonal_group() # needs sage.graphs The isometries act on elements of their domain:: - sage: g = Oq(matrix(ZZ, 2, [0, 3, 1, 2])) - sage: T.gen(0) * g + sage: g = Oq(matrix(ZZ, 2, [0, 3, 1, 2])) # needs sage.graphs + sage: T.gen(0) * g # needs sage.graphs (0, 3) Isometries are represented with respect to the Smith form generators of `T`:: + sage: # needs sage.graphs sage: L = IntegralLattice("A2").twist(2).direct_sum(IntegralLattice('U')) sage: T = L.discriminant_group().normal_form() sage: OT = T.orthogonal_group() @@ -216,6 +217,7 @@ def _element_constructor_(self, x, check=True): EXAMPLES:: + sage: # needs sage.graphs sage: L = IntegralLattice("A2").twist(2).direct_sum(IntegralLattice("A2")) sage: q = L.discriminant_group() sage: OL = L.orthogonal_group() @@ -230,18 +232,19 @@ def _element_constructor_(self, x, check=True): Note that the following does not work since it may lead to ambiguities, see :trac:`30669`:: - sage: Oq(f.matrix()) + sage: Oq(f.matrix()) # needs sage.graphs Traceback (most recent call last): ... ValueError: ... But a matrix in the covering works:: - sage: fbar == Oq(fbar.matrix()) + sage: fbar == Oq(fbar.matrix()) # needs sage.graphs True TESTS:: + sage: # needs sage.graphs sage: all(x*f==x*fbar for x in q.gens()) True sage: L = IntegralLattice("A2").twist(3) @@ -377,7 +380,7 @@ def _repr_(self): [ 0 2/3] generated by 2 elements """ - return "Group of isometries of \n%s\ngenerated by %s elements"%(self.invariant_form(), len(self.gens())) + return "Group of isometries of \n%s\ngenerated by %s elements" % (self.invariant_form(), len(self.gens())) class ActionOnFqf(Action): r""" @@ -544,7 +547,7 @@ def orbits(G, L): raise ValueError("torsion quadratic modules are not isometric") n = len(A.smith_form_gens()) # separating the different primes here would speed things up - b_cand = [[b for b in B if b.q()==a.q() and b.order() == a.order()] for a in A.smith_form_gens()] + b_cand = [[b for b in B if b.q() == a.q() and b.order() == a.order()] for a in A.smith_form_gens()] G = B.orthogonal_group(tuple()) ambient = G.ambient() @@ -566,7 +569,7 @@ def orbits(G, L): a = A.smith_form_gens()[i] card = ZZ.prod(A.smith_form_gen(k).order() for k in range(i+1)) for b in b_cand[i]: - if all(b.b(f[k])==a.b(A.smith_form_gens()[k]) for k in range(i)): + if all(b.b(f[k]) == a.b(A.smith_form_gens()[k]) for k in range(i)): fnew = f + [b] # check that the elements of fnew are independent if B.submodule(fnew).cardinality() == card: diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index 0c51deafc64..6f3c4400779 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -89,11 +89,11 @@ def is_FreeGroup(x): EXAMPLES:: sage: from sage.groups.free_group import is_FreeGroup - sage: is_FreeGroup('a string') + sage: is_FreeGroup('a string') # needs sage.combinat False sage: is_FreeGroup(FreeGroup(0)) True - sage: is_FreeGroup(FreeGroup(index_set=ZZ)) + sage: is_FreeGroup(FreeGroup(index_set=ZZ)) # needs sage.combinat True """ if isinstance(x, FreeGroup_class): @@ -213,20 +213,20 @@ def __init__(self, parent, x): l = x.Tietze() except AttributeError: l = list(x) - if len(l)>0: + if len(l) > 0: if min(l) < -parent.ngens() or parent.ngens() < max(l): raise ValueError('generators not in the group') if 0 in l: raise ValueError('zero does not denote a generator') - i=0 - while i0: - i=i-1 + if i > 0: + i = i-1 else: - i=i+1 + i = i+1 AbstractWordTietzeWord = libgap.eval('AbstractWordTietzeWord') x = AbstractWordTietzeWord(l, parent.gap().GeneratorsOfGroup()) ElementLibGAP.__init__(self, parent, x) @@ -645,9 +645,9 @@ def FreeGroup(n=None, names='x', index_set=None, abelian=False, **kwds): We give two examples using the ``index_set`` option:: - sage: FreeGroup(index_set=ZZ) + sage: FreeGroup(index_set=ZZ) # needs sage.combinat Free group indexed by Integer Ring - sage: FreeGroup(index_set=ZZ, abelian=True) + sage: FreeGroup(index_set=ZZ, abelian=True) # needs sage.combinat Free abelian group indexed by Integer Ring TESTS:: @@ -788,7 +788,7 @@ def _repr_(self): sage: G._repr_() 'Free Group on generators {a, b}' """ - return 'Free Group on generators {'+ ', '.join(self.variable_names()) + '}' + return 'Free Group on generators {' + ', '.join(self.variable_names()) + '}' def rank(self): """ @@ -870,10 +870,10 @@ def _element_constructor_(self, *args, **kwds): ... TypeError: 'sage.rings.integer.Integer' object is not iterable """ - if len(args)!=1: + if len(args) != 1: return self.element_class(self, *args, **kwds) x = args[0] - if x==1 or x == [] or x == (): + if x == 1 or x == [] or x == (): return self.one() try: P = x.parent() @@ -885,7 +885,7 @@ def _element_constructor_(self, *args, **kwds): return self([i.sign()*(self._names.index(P._names[abs(i)-1])+1) for i in x.Tietze()]) else: - raise ValueError('generators of %s not in the group'%x) + raise ValueError('generators of %s not in the group' % x) return self.element_class(self, x, **kwds) def abelian_invariants(self): diff --git a/src/sage/groups/galois_group.py b/src/sage/groups/galois_group.py index d4023125644..ed9e6d61bd4 100644 --- a/src/sage/groups/galois_group.py +++ b/src/sage/groups/galois_group.py @@ -31,9 +31,9 @@ def _alg_key(self, algorithm=None, recompute=False): sage: from sage.groups.galois_group import _alg_key sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group() - sage: _alg_key(G, algorithm="pari", recompute=True) + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: _alg_key(G, algorithm="pari", recompute=True) # needs sage.rings.number_field 'pari' """ if recompute: @@ -55,9 +55,9 @@ def _default_algorithm(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group() - sage: G._default_algorithm + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: G._default_algorithm # needs sage.rings.number_field 'pari' """ return NotImplemented @@ -74,9 +74,9 @@ def _gcdata(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 - 2) - sage: G = K.galois_group() - sage: G._gcdata + sage: K. = NumberField(x^3 - 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: G._gcdata # needs sage.rings.number_field (Number Field in ac with defining polynomial x^6 + 108, Ring morphism: From: Number Field in a with defining polynomial x^3 - 2 @@ -91,6 +91,7 @@ def _get_algorithm(self, algorithm): EXAMPLES:: + sage: # needs sage.rings.number_field sage: R. = ZZ[] sage: K. = NumberField(x^3 + 2*x + 2) sage: G = K.galois_group() @@ -109,9 +110,9 @@ def _galois_closure(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group(names='b') - sage: G._galois_closure + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group(names='b') # needs sage.rings.number_field + sage: G._galois_closure # needs sage.rings.number_field Number Field in b with defining polynomial x^6 + 12*x^4 + 36*x^2 + 140 """ return self._gcdata[0] @@ -122,6 +123,7 @@ def splitting_field(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') sage: K = NumberField(x^3 - x + 1, 'a') sage: K.galois_group(names='b').splitting_field() @@ -139,9 +141,9 @@ def _gc_map(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group(names='b') - sage: G._gc_map + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group(names='b') # needs sage.rings.number_field + sage: G._gc_map # needs sage.rings.number_field Ring morphism: From: Number Field in a with defining polynomial x^3 + 2*x + 2 To: Number Field in b with defining polynomial x^6 + 12*x^4 + 36*x^2 + 140 @@ -162,9 +164,9 @@ def _field(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group() - sage: G._field + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: G._field # needs sage.rings.number_field Number Field in a with defining polynomial x^3 + 2*x + 2 """ return NotImplemented @@ -177,9 +179,9 @@ def _repr_(self): sage: from sage.groups.galois_group import GaloisGroup_perm sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group() - sage: GaloisGroup_perm._repr_(G) + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: GaloisGroup_perm._repr_(G) # needs sage.rings.number_field 'Galois group of x^3 + 2*x + 2' """ f = self._field.defining_polynomial() @@ -193,6 +195,7 @@ def top_field(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: R. = ZZ[] sage: K. = NumberField(x^3 + 2*x + 2) sage: L = K.galois_closure('b') @@ -212,6 +215,7 @@ def _field_degree(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: R. = ZZ[] sage: K. = NumberField(x^3 + 2*x + 2) sage: L. = K.extension(x^2 + 3*a^2 + 8) @@ -229,11 +233,11 @@ def _field_degree(self): This behavior may change in the future:: - sage: GL._field_degree + sage: GL._field_degree # needs sage.rings.number_field 6 - sage: GL.transitive_label() + sage: GL.transitive_label() # needs sage.rings.number_field '6T2' - sage: GL + sage: GL # needs sage.rings.number_field Galois group 6T2 ([3]2) with order 6 of x^2 + 3*a^2 + 8 """ try: @@ -249,9 +253,9 @@ def transitive_label(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^8 - x^5 + x^4 - x^3 + 1) - sage: G = K.galois_group() - sage: G.transitive_label() + sage: K. = NumberField(x^8 - x^5 + x^4 - x^3 + 1) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: G.transitive_label() # needs sage.rings.number_field '8T44' """ return "%sT%s" % (self._field_degree, self.transitive_number()) @@ -263,10 +267,10 @@ def is_galois(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^8 - x^5 + x^4 - x^3 + 1) - sage: G = K.galois_group() + sage: K. = NumberField(x^8 - x^5 + x^4 - x^3 + 1) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field sage: from sage.groups.galois_group import GaloisGroup_perm - sage: GaloisGroup_perm.is_galois(G) + sage: GaloisGroup_perm.is_galois(G) # needs sage.rings.number_field False """ return self.order() == self._field_degree @@ -283,6 +287,7 @@ def _ambient_group(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') sage: L. = NumberField(x^4 + 1) sage: G = L.galois_group() @@ -309,6 +314,7 @@ def fixed_field(self, name=None, polred=None, threshold=None): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: k. = GF(3^12) sage: g = k.galois_group()([8]) sage: k0, embed = g.fixed_field() @@ -323,11 +329,12 @@ def _gcdata(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') sage: L. = NumberField(x^4 + 1) sage: G = L.galois_group() sage: H = G.decomposition_group(L.primes_above(3)[0]) - sage: H.splitting_field() # indirect doctest + sage: H.splitting_field() # indirect doctest Number Field in a with defining polynomial x^4 + 1 """ return self._ambient_group._gcdata @@ -355,9 +362,9 @@ def transitive_number(self, algorithm=None, recompute=False): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group() - sage: G.transitive_number() + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: G.transitive_number() # needs sage.rings.number_field 2 """ @@ -371,9 +378,9 @@ def _gens(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^5-2) - sage: G = K.galois_group(gc_numbering=False) - sage: G._gens + sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field + sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field + sage: G._gens # needs sage.rings.number_field [(1,2,3,5), (1,4,3,2,5)] """ return NotImplemented @@ -383,9 +390,9 @@ def __init__(self, field, algorithm=None, names=None, gc_numbering=False): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^3 + 2*x + 2) - sage: G = K.galois_group() - sage: TestSuite(G).run() + sage: K. = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field + sage: G = K.galois_group() # needs sage.rings.number_field + sage: TestSuite(G).run() # needs sage.rings.number_field """ self._field = field self._default_algorithm = algorithm @@ -413,8 +420,9 @@ def _deg(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: R. = ZZ[] - sage: K. = NumberField(x^5-2) + sage: K. = NumberField(x^5 - 2) sage: G = K.galois_group(gc_numbering=False); G Galois group 5T3 (5:4) with order 20 of x^5 - 2 sage: G._deg @@ -437,8 +445,9 @@ def _domain(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: R. = ZZ[] - sage: K. = NumberField(x^5-2) + sage: K. = NumberField(x^5 - 2) sage: G = K.galois_group(gc_numbering=False); G Galois group 5T3 (5:4) with order 20 of x^5 - 2 sage: G._domain @@ -456,9 +465,9 @@ def _domain_to_gap(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^5-2) - sage: G = K.galois_group(gc_numbering=False) - sage: G._domain_to_gap[5] + sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field + sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field + sage: G._domain_to_gap[5] # needs sage.rings.number_field 5 """ return dict((key, i+1) for i, key in enumerate(self._domain)) @@ -471,9 +480,9 @@ def _domain_from_gap(self): EXAMPLES:: sage: R. = ZZ[] - sage: K. = NumberField(x^5-2) - sage: G = K.galois_group(gc_numbering=True) - sage: G._domain_from_gap[20] + sage: K. = NumberField(x^5 - 2) # needs sage.rings.number_field + sage: G = K.galois_group(gc_numbering=True) # needs sage.rings.number_field + sage: G._domain_from_gap[20] # needs sage.rings.number_field 20 """ return dict((i+1, key) for i, key in enumerate(self._domain)) @@ -484,7 +493,7 @@ def ngens(self): EXAMPLES:: - sage: QuadraticField(-23, 'a').galois_group().ngens() + sage: QuadraticField(-23, 'a').galois_group().ngens() # needs sage.rings.number_field 1 """ return len(self._gens) @@ -499,7 +508,7 @@ def __init__(self, field, generator_orders, algorithm=None, gen_names='sigma'): TESTS:: - sage: TestSuite(GF(9).galois_group()).run() + sage: TestSuite(GF(9).galois_group()).run() # needs sage.rings.finite_rings """ self._field = field self._default_algorithm = algorithm @@ -513,7 +522,7 @@ def is_galois(self): EXAMPLES:: - sage: GF(9).galois_group().is_galois() + sage: GF(9).galois_group().is_galois() # needs sage.rings.finite_rings True """ return True @@ -525,7 +534,7 @@ def _gcdata(self): EXAMPLES:: - sage: GF(3^2).galois_group()._gcdata + sage: GF(3^2).galois_group()._gcdata # needs sage.rings.finite_rings (Finite Field in z2 of size 3^2, Identity endomorphism of Finite Field in z2 of size 3^2) """ @@ -537,11 +546,12 @@ def permutation_group(self): r""" Return a permutation group giving the action on the roots of a defining polynomial. - This is the regular representation for the abelian group, which is not necessarily the smallest degree permutation representation. + This is the regular representation for the abelian group, which is + not necessarily the smallest degree permutation representation. EXAMPLES:: - sage: GF(3^10).galois_group().permutation_group() + sage: GF(3^10).galois_group().permutation_group() # needs sage.rings.finite_rings Permutation Group with generators [(1,2,3,4,5,6,7,8,9,10)] """ return PermutationGroup(gap_group=self._gap_().RegularActionHomomorphism().Image()) @@ -573,11 +583,11 @@ def transitive_number(self, algorithm=None, recompute=False): EXAMPLES:: - sage: GF(2^8).galois_group().transitive_number() + sage: GF(2^8).galois_group().transitive_number() # needs sage.rings.finite_rings 1 - sage: GF(3^32).galois_group().transitive_number() + sage: GF(3^32).galois_group().transitive_number() # needs sage.rings.finite_rings 33 - sage: GF(2^60).galois_group().transitive_number() + sage: GF(2^60).galois_group().transitive_number() # needs sage.rings.finite_rings Traceback (most recent call last): ... NotImplementedError: transitive database only computed up to degree 47 @@ -597,9 +607,9 @@ def signature(self): EXAMPLES:: - sage: GF(3^2).galois_group().signature() + sage: GF(3^2).galois_group().signature() # needs sage.rings.finite_rings -1 - sage: GF(3^3).galois_group().signature() + sage: GF(3^3).galois_group().signature() # needs sage.rings.finite_rings 1 """ return ZZ(1) if (self._field.degree() % 2) else ZZ(-1) @@ -622,5 +632,6 @@ class GaloisSubgroup_ab(AbelianGroup_subgroup, _SubGaloisMixin): """ pass + GaloisGroup_perm.Subgroup = GaloisSubgroup_perm GaloisGroup_ab.Subgroup = GaloisSubgroup_ab diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index 33e92d43ca5..17deee71ef6 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -5,15 +5,15 @@ groups, including additive and multiplicative groups. In all cases the group operation is specified by a parameter -'operation', which is a string either one of the set of -multiplication_names or addition_names specified below, or 'other'. -In the latter case, the caller must provide an identity, inverse() and -op() functions. +``operation``, which is a string either one of the set of +``multiplication_names`` or ``addition_names`` specified below, or other. +In the latter case, the caller must provide an identity, ``inverse()`` and +``op()`` functions. :: - multiplication_names = ( 'multiplication', 'times', 'product', '*') - addition_names = ( 'addition', 'plus', 'sum', '+') + multiplication_names = ('multiplication', 'times', 'product', '*') + addition_names = ('addition', 'plus', 'sum', '+') Also included are a generic function for computing multiples (or @@ -25,14 +25,16 @@ - Discrete logs:: + sage: # needs sage.rings.finite_rings sage: K = GF(3^6,'b') sage: b = K.gen() sage: a = b^210 - sage: discrete_log(a, b, K.order()-1) + sage: discrete_log(a, b, K.order() - 1) 210 - Linear relation finder:: + sage: # needs sage.rings.finite_rings sage: F. = GF(3^6,'a') sage: a.multiplicative_order().factor() 2^3 * 7 * 13 @@ -45,18 +47,20 @@ - Orders of elements:: + sage: # needs sage.rings.finite_rings sage: from sage.groups.generic import order_from_multiple, order_from_bounds sage: k. = GF(5^5) sage: b = a^4 - sage: order_from_multiple(b,5^5-1,operation='*') + sage: order_from_multiple(b, 5^5 - 1, operation='*') 781 - sage: order_from_bounds(b,(5^4,5^5),operation='*') + sage: order_from_bounds(b, (5^4, 5^5), operation='*') 781 Some examples in the group of points of an elliptic curve over a finite field: - Discrete logs:: + sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes sage: F = GF(37^2,'a') sage: E = EllipticCurve(F,[1,1]) sage: F. = GF(37^2,'a') @@ -66,11 +70,12 @@ 672 sage: Q = 39*P; Q (36*a + 32 : 5*a + 12 : 1) - sage: discrete_log(Q,P,P.order(),operation='+') + sage: discrete_log(Q, P, P.order(), operation='+') 39 - Linear relation finder:: + sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes sage: F. = GF(3^6,'a') sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1]) sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2 , 0) @@ -82,10 +87,11 @@ - Orders of elements:: + sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes sage: from sage.groups.generic import order_from_multiple, order_from_bounds sage: k. = GF(5^5) sage: E = EllipticCurve(k,[2,4]) - sage: P = E(3*a^4 + 3*a , 2*a + 1 ) + sage: P = E(3*a^4 + 3*a, 2*a + 1) sage: M = E.cardinality(); M 3227 sage: plist = M.prime_factors() @@ -134,36 +140,37 @@ def multiple(a, n, operation='*', identity=None, inverse=None, op=None): EXAMPLES:: - sage: multiple(2,5) + sage: multiple(2, 5) 32 - sage: multiple(RealField()('2.5'),4) + sage: multiple(RealField()('2.5'), 4) # needs sage.rings.real_mpfr 39.0625000000000 - sage: multiple(2,-3) + sage: multiple(2, -3) 1/8 - sage: multiple(2,100,'+') == 100*2 + sage: multiple(2, 100, '+') == 100*2 True - sage: multiple(2,100) == 2**100 + sage: multiple(2, 100) == 2**100 True - sage: multiple(2,-100,) == 2**-100 + sage: multiple(2, -100,) == 2**-100 True - sage: R.=ZZ[] - sage: multiple(x,100) + sage: R. = ZZ[] + sage: multiple(x, 100) x^100 - sage: multiple(x,100,'+') + sage: multiple(x, 100, '+') 100*x - sage: multiple(x,-10) + sage: multiple(x, -10) 1/x^10 Idempotence is detected, making the following fast:: - sage: multiple(1,10^1000) + sage: multiple(1, 10^1000) 1 + sage: # needs sage.schemes sage: E = EllipticCurve('389a1') sage: P = E(-1,1) - sage: multiple(P,10,'+') + sage: multiple(P, 10, '+') (645656132358737542773209599489/22817025904944891235367494656 : 525532176124281192881231818644174845702936831/3446581505217248068297884384990762467229696 : 1) - sage: multiple(P,-10,'+') + sage: multiple(P, -10, '+') (645656132358737542773209599489/22817025904944891235367494656 : -528978757629498440949529703029165608170166527/3446581505217248068297884384990762467229696 : 1) """ from operator import inv, mul, neg, add @@ -247,14 +254,14 @@ class multiples: EXAMPLES:: - sage: list(multiples(1,10)) + sage: list(multiples(1, 10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - sage: list(multiples(1,10,100)) + sage: list(multiples(1, 10, 100)) [100, 101, 102, 103, 104, 105, 106, 107, 108, 109] - sage: E = EllipticCurve('389a1') - sage: P = E(-1,1) - sage: for Q in multiples(P,5): print((Q, Q.height()/P.height())) + sage: E = EllipticCurve('389a1') # needs sage.schemes + sage: P = E(-1,1) # needs sage.schemes + sage: for Q in multiples(P, 5): print((Q, Q.height()/P.height())) # needs sage.schemes ((0 : 1 : 0), 0.000000000000000) ((-1 : 1 : 1), 1.00000000000000) ((10/9 : -35/27 : 1), 4.00000000000000) @@ -262,22 +269,23 @@ class multiples: ((47503/16641 : 9862190/2146689 : 1), 16.0000000000000) sage: R. = ZZ[] - sage: list(multiples(x,5)) + sage: list(multiples(x, 5)) [0, x, 2*x, 3*x, 4*x] - sage: list(multiples(x,5,operation='*')) + sage: list(multiples(x, 5, operation='*')) [1, x, x^2, x^3, x^4] - sage: list(multiples(x,5,indexed=True)) + sage: list(multiples(x, 5, indexed=True)) [(0, 0), (1, x), (2, 2*x), (3, 3*x), (4, 4*x)] - sage: list(multiples(x,5,indexed=True,operation='*')) + sage: list(multiples(x, 5, indexed=True, operation='*')) [(0, 1), (1, x), (2, x^2), (3, x^3), (4, x^4)] - sage: for i,y in multiples(x,5,indexed=True): print("%s times %s = %s"%(i,x,y)) + sage: for i,y in multiples(x, 5, indexed=True): print("%s times %s = %s"%(i,x,y)) 0 times x = 0 1 times x = x 2 times x = 2*x 3 times x = 3*x 4 times x = 4*x - sage: for i,n in multiples(3,5,indexed=True,operation='*'): print("3 to the power %s = %s" % (i,n)) + sage: for i,n in multiples(3, 5, indexed=True, operation='*'): + ....: print("3 to the power %s = %s" % (i,n)) 3 to the power 0 = 1 3 to the power 1 = 3 3 to the power 2 = 9 @@ -286,26 +294,25 @@ class multiples: """ def __init__(self, P, n, P0=None, indexed=False, operation='+', op=None): """ - Create a multiples iterator + Create a multiples iterator. INPUT: - - ``P`` - step value: any Sage object on which a binary - operation is defined - - ``n`` - number of multiples: non-negative integer + - ``P`` -- step value: any Sage object on which a binary operation is defined + - ``n`` -- number of multiples: non-negative integer - ``P0`` - offset (default 0): Sage object which can be 'added' to P - - ``indexed`` - boolean (default False) + - ``indexed`` -- boolean (default ``False``) - If ``indexed==False`` then the iterator delivers ``P0+i*P`` + If ``indexed==False``, then the iterator delivers ``P0+i*P`` (if ``operation=='+'``) or ``P0*P**i`` (if ``operation=='*'``), for ``i`` in ``range(n)``. If ``indexed==True`` then the iterator delivers tuples - ``(i,P0+i*P)`` or ``(i,P0*P**i)``. + ``(i, P0+i*P)`` or ``(i, P0*P**i)``. - - ``operation`` - string: '+' (default ) or '*' or `other`. + - ``operation`` -- string: ``'+'`` (the default) or ``'*'`` or other. - If `other`, a function ``op()`` must be supplied (a function + If other, a function ``op()`` must be supplied (a function of 2 arguments) defining the group binary operation; also ``P0`` must be supplied. """ @@ -377,18 +384,18 @@ def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): INPUT: - - ``a`` - group element - - ``b`` - group element - - ``bounds`` - a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper`` - - ``operation`` - string: '*', '+', 'other' - - ``identity`` - the identity element of the group - - ``inverse()`` - function of 1 argument ``x`` returning inverse of ``x`` + - ``a`` -- group element + - ``b`` -- group element + - ``bounds`` -- a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper`` + - ``operation`` -- string: ``'*'``, ``'+'``, other + - ``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 OUTPUT: An integer `n` such that `a^n = b` (or `na = b`). If no - such `n` exists, this function raises a ValueError exception. + 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 @@ -403,27 +410,29 @@ def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): sage: from sage.groups.generic import bsgs sage: b = Mod(2,37); a = b^20 - sage: bsgs(b, a, (0,36)) + sage: bsgs(b, a, (0, 36)) 20 - sage: p = next_prime(10^20) - sage: a = Mod(2,p); b = a^(10^25) - sage: bsgs(a, b, (10^25-10^6,10^25+10^6)) == 10^25 + sage: p = next_prime(10^20) # needs sage.libs.pari + sage: a = Mod(2,p); b = a^(10^25) # needs sage.libs.pari + sage: bsgs(a, b, (10^25 - 10^6, 10^25 + 10^6)) == 10^25 # needs sage.libs.pari True + sage: # needs sage.rings.finite_rings sage: K = GF(3^6,'b') sage: a = K.gen() sage: b = a^210 - sage: bsgs(a, b, (0,K.order()-1)) + sage: bsgs(a, b, (0, K.order() - 1)) 210 - sage: K. = CyclotomicField(230) - sage: w = z^500 - sage: bsgs(z,w,(0,229)) + sage: K. = CyclotomicField(230) # needs sage.rings.number_field + sage: w = z^500 # needs sage.rings.number_field + sage: bsgs(z, w, (0, 229)) # needs sage.rings.number_field 40 An additive example in an elliptic curve group:: + sage: # needs sage.rings.finite_rings sage.schemes sage: F. = GF(37^5) sage: E = EllipticCurve(F, [1,1]) sage: P = E.lift_x(a); P @@ -431,7 +440,7 @@ def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): This will return a multiple of the order of P:: - sage: bsgs(P,P.parent()(0),Hasse_bounds(F.order()),operation='+') + sage: bsgs(P, P.parent()(0), Hasse_bounds(F.order()), operation='+') # needs sage.rings.finite_rings sage.schemes 69327408 AUTHOR: @@ -513,9 +522,9 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No to compute it - ``operation`` -- a string (default: ``'*'``) denoting whether we are in an additive group or a multiplicative one - - ``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 + - ``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 - ``hash_function`` -- having an efficient hash function is critical for this algorithm (see examples) @@ -527,11 +536,12 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No EXAMPLES:: - sage: F. = GF(2^13) - sage: g = F.gen() - sage: discrete_log_rho(g^1234, g) + sage: F. = GF(2^13) # needs sage.rings.finite_rings + sage: g = F.gen() # needs sage.rings.finite_rings + sage: discrete_log_rho(g^1234, g) # needs sage.rings.finite_rings 1234 + sage: # needs sage.rings.finite_rings sage.schemes sage: F. = GF(37^5) sage: E = EllipticCurve(F, [1,1]) sage: G = (3*31*2^4)*E.lift_x(a) @@ -540,33 +550,36 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No It also works with matrices:: - sage: A = matrix(GF(50021),[[10577,23999,28893],[14601,41019,30188],[3081,736,27092]]) - sage: discrete_log_rho(A^1234567, A) + sage: A = matrix(GF(50021), [[10577, 23999, 28893], # needs sage.rings.finite_rings + ....: [14601, 41019, 30188], + ....: [3081, 736, 27092]]) + sage: discrete_log_rho(A^1234567, A) # needs sage.rings.finite_rings 1234567 Beware, the order must be prime:: sage: I = IntegerModRing(171980) - sage: discrete_log_rho(I(2), I(3)) + sage: discrete_log_rho(I(2), I(3)) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: for Pollard rho algorithm the order of the group must be prime - If it fails to find a suitable logarithm, it raises a ``ValueError``:: + If it fails to find a suitable logarithm, it raises a :class:`ValueError`:: sage: I = IntegerModRing(171980) - sage: discrete_log_rho(I(31002),I(15501)) + sage: discrete_log_rho(I(31002), I(15501)) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: Pollard rho algorithm failed to find a logarithm The main limitation on the hash function is that we don't want to have - `hash(x*y) = hash(x) + hash(y)`:: + ``hash(x*y) == hash(x) + hash(y)``:: + sage: # needs sage.libs.pari sage: I = IntegerModRing(next_prime(2^23)) sage: def test(): ....: try: - ....: discrete_log_rho(I(123456),I(1),operation='+') + ....: discrete_log_rho(I(123456), I(1), operation='+') ....: except Exception: ....: print("FAILURE") sage: test() # random failure @@ -574,7 +587,8 @@ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=No If this happens, we can provide a better hash function:: - sage: discrete_log_rho(I(123456),I(1),operation='+', hash_function=lambda x: hash(x*x)) + sage: discrete_log_rho(I(123456), I(1), operation='+', # needs sage.libs.pari + ....: hash_function=lambda x: hash(x*x)) 123456 AUTHOR: @@ -673,21 +687,21 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i INPUT: - - ``a`` - group element - - ``base`` - group element (the base) - - ``ord`` - integer (multiple of order of base, or ``None``) - - ``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 - - ``algorithm`` - string denoting what algorithm to use for prime-order logarithms: 'bsgs', 'rho', 'lambda' + - ``a`` -- group element + - ``base`` -- group element (the base) + - ``ord`` -- integer (multiple of order of base, or ``None``) + - ``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 + - ``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 + given by ``identity``, inverse of ``x`` by ``inverse(x)``, and group operation on ``x``, ``y`` by ``op(x,y)``. - If operation is '*' or '+' then the other + If operation is ``'*'`` or ``'+'``, then the other arguments are provided automatically; otherwise they must be provided by the caller. @@ -697,13 +711,13 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i assuming that ``ord`` is a multiple of the order of the base `b`. If ``ord`` is not specified, an attempt is made to compute it. - If no such `n` exists, this function raises a ``ValueError`` exception. + If no such `n` exists, this function raises a :class:`ValueError` exception. .. warning:: - If ``x`` has a log method, it is likely to be vastly faster + 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 - `n`, use its log method instead! + `n`, use its ``log`` method instead! ALGORITHM: Pohlig-Hellman, Baby step giant step, Pollard's lambda/kangaroo, and Pollard's rho. @@ -716,10 +730,11 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i sage: discrete_log(a, b, bounds=(10, 100)) 20 - sage: K = GF(3^6,'b') + sage: # needs sage.rings.finite_rings + sage: K = GF(3^6, 'b') sage: b = K.gen() sage: a = b^210 - sage: discrete_log(a, b, K.order()-1) + sage: discrete_log(a, b, K.order() - 1) 210 sage: b = Mod(1,37); x = Mod(2,37) @@ -735,63 +750,66 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i See :trac:`2356`:: - sage: F. = GF(121) - sage: v = w^120 - sage: v.log(w) + sage: F. = GF(121) # needs sage.rings.finite_rings + sage: v = w^120 # needs sage.rings.finite_rings + sage: v.log(w) # needs sage.rings.finite_rings 0 - sage: K. = CyclotomicField(230) - sage: w = z^50 - sage: discrete_log(w,z) + sage: K. = CyclotomicField(230) # needs sage.rings.number_field + sage: w = z^50 # needs sage.rings.number_field + sage: discrete_log(w, z) # needs sage.rings.number_field 50 An example where the order is infinite: note that we must give an upper bound here:: + sage: # needs sage.rings.number_field sage: K. = QuadraticField(23) - sage: eps = 5*a-24 # a fundamental unit + sage: eps = 5*a - 24 # a fundamental unit sage: eps.multiplicative_order() +Infinity sage: eta = eps^100 - sage: discrete_log(eta,eps,bounds=(0,1000)) + sage: discrete_log(eta, eps, bounds=(0,1000)) 100 In this case we cannot detect negative powers:: - sage: eta = eps^(-3) - sage: discrete_log(eta,eps,bounds=(0,100)) + sage: eta = eps^(-3) # needs sage.rings.number_field + sage: discrete_log(eta,eps,bounds=(0,100)) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: no discrete log of -11515*a - 55224 found to base 5*a - 24 But we can invert the base (and negate the result) instead:: - sage: - discrete_log(eta^-1,eps,bounds=(0,100)) + sage: -discrete_log(eta^-1, eps, bounds=(0,100)) # needs sage.rings.number_field -3 An additive example: elliptic curve DLOG:: + sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes sage: F = GF(37^2,'a') - sage: E = EllipticCurve(F,[1,1]) + sage: E = EllipticCurve(F, [1,1]) sage: F. = GF(37^2,'a') - sage: E = EllipticCurve(F,[1,1]) - sage: P = E(25*a + 16 , 15*a + 7 ) + sage: E = EllipticCurve(F, [1,1]) + sage: P = E(25*a + 16, 15*a + 7) sage: P.order() 672 sage: Q = 39*P; Q (36*a + 32 : 5*a + 12 : 1) - sage: discrete_log(Q,P,P.order(),operation='+') + sage: discrete_log(Q, P, P.order(), operation='+') 39 An example of big smooth group:: + sage: # needs sage.rings.finite_rings sage: F. = GF(2^63) sage: g = F.gen() sage: u = g**123456789 sage: discrete_log(u,g) 123456789 - The above examples also work when the 'rho' and 'lambda' algorithms are used:: + The above examples also work when the ``'rho'`` and ``'lambda'`` algorithms are used:: sage: b = Mod(2,37); a = b^20 sage: discrete_log(a, b, algorithm='rho') @@ -800,6 +818,7 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i sage: discrete_log(a, b, algorithm='lambda', bounds=(10, 100)) 20 + sage: # needs sage.rings.finite_rings sage: K = GF(3^6,'b') sage: b = K.gen() sage: a = b^210 @@ -817,22 +836,24 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i ... ValueError: no discrete log of 2 found to base 1 - sage: F=GF(37^2,'a') - sage: E=EllipticCurve(F,[1,1]) - sage: F.=GF(37^2,'a') - sage: E=EllipticCurve(F,[1,1]) - sage: P=E(25*a + 16 , 15*a + 7 ) + sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes + sage: F = GF(37^2,'a') + sage: E = EllipticCurve(F, [1,1]) + sage: F. = GF(37^2,'a') + sage: E = EllipticCurve(F, [1,1]) + sage: P = E(25*a + 16, 15*a + 7) sage: P.order() 672 - sage: Q=39*P; Q + sage: Q = 39*P; Q (36*a + 32 : 5*a + 12 : 1) - sage: discrete_log(Q,P,P.order(),operation='+',algorithm='lambda') + sage: discrete_log(Q, P, P.order(), operation='+', algorithm='lambda') 39 + sage: # needs sage.rings.finite_rings sage: F. = GF(2^63) sage: g = F.gen() sage: u = g**123456789 - sage: discrete_log(u,g,algorithm='rho') + sage: discrete_log(u, g, algorithm='rho') 123456789 TESTS: @@ -849,8 +870,8 @@ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, i sage: kwargs = {'operation': '+'} sage: kwargs['algorithm'] = choice(['bsgs', 'rho', 'lambda']) sage: if randrange(2): - ....: lo = randrange(-order, sol+1) - ....: hi = randrange(sol+1, 2*order) + ....: lo = randrange(-order, sol + 1) + ....: hi = randrange(sol + 1, 2*order) ....: assert lo <= sol <= hi ....: kwargs['bounds'] = (lo, hi) sage: try: @@ -973,10 +994,11 @@ def discrete_log_lambda(a, base, bounds, operation='*', identity=None, inverse=N EXAMPLES:: - sage: F. = GF(2^63) - sage: discrete_log_lambda(a^1234567, a, (1200000,1250000)) + sage: F. = GF(2^63) # needs sage.rings.finite_rings + sage: discrete_log_lambda(a^1234567, a, (1200000,1250000)) # needs sage.rings.finite_rings 1234567 + sage: # needs sage.rings.finite_rings sage.schemes sage: F. = GF(37^5) sage: E = EllipticCurve(F, [1,1]) sage: P = E.lift_x(a); P @@ -984,12 +1006,14 @@ def discrete_log_lambda(a, base, bounds, operation='*', identity=None, inverse=N This will return a multiple of the order of P:: - sage: discrete_log_lambda(P.parent()(0), P, Hasse_bounds(F.order()), operation='+') + sage: discrete_log_lambda(P.parent()(0), P, Hasse_bounds(F.order()), # needs sage.rings.finite_rings sage.schemes + ....: operation='+') 69327408 - sage: K. = GF(89**5) + sage: K. = GF(89**5) # needs sage.rings.finite_rings sage: hs = lambda x: hash(x) + 15 - sage: discrete_log_lambda(a**(89**3 - 3), a, (89**2, 89**4), operation = '*', hash_function = hs) # long time (10s on sage.math, 2011) + sage: discrete_log_lambda(a**(89**3 - 3), # long time (10s on sage.math, 2011), needs sage.rings.finite_rings + ....: a, (89**2, 89**4), operation='*', hash_function=hs) 704966 AUTHOR: @@ -1082,25 +1106,27 @@ def linear_relation(P, Q, operation='+', identity=None, inverse=None, op=None): An additive example (in an elliptic curve group):: + sage: # needs sage.rings.finite_rings sage.schemes sage: F. = GF(3^6,'a') - sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a,a^4 + a^3 + 2*a + 1]) - sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2 , 0) - sage: Q = E(2*a^3 + 2*a^2 + 2*a , a^3 + 2*a^2 + 1) - sage: linear_relation(P,Q,'+') + sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1]) + sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2, 0) + sage: Q = E(2*a^3 + 2*a^2 + 2*a, a^3 + 2*a^2 + 1) + sage: linear_relation(P, Q, '+') (1, 2) sage: P == 2*Q True A multiplicative example (in a finite field's multiplicative group):: + sage: # needs sage.rings.finite_rings sage: F. = GF(3^6,'a') sage: a.multiplicative_order().factor() 2^3 * 7 * 13 sage: b = a^7 sage: c = a^13 - sage: linear_relation(b,c,'*') + sage: linear_relation(b, c, '*') (13, 7) - sage: b^13==c^7 + sage: b^13 == c^7 True """ Z = integer_ring.ZZ @@ -1164,16 +1190,16 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True, INPUT: - - ``P`` - a Sage object which is a group element; - - ``m`` - a Sage integer which is a multiple of the order of ``P``, + - ``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``); - - ``check`` - a Boolean (default:True), indicating whether we check if ``m`` + - ``check`` -- a Boolean (default: ``True``), indicating whether we check if ``m`` really is a multiple of the order; - - ``factorization`` - the factorization of ``m``, or ``None`` in which + - ``factorization`` -- the factorization of ``m``, or ``None`` in which case this function will need to factor ``m``; - - ``plist`` - a list of the prime factors of ``m``, or ``None`` - kept for compatibility only, + - ``plist`` -- a list of the prime factors of ``m``, or ``None`` - kept for compatibility only, prefer the use of ``factorization``; - - ``operation`` - string: '+' (default) or '*'. + - ``operation`` -- string: ``'+'`` (default) or ``'*'``. .. note:: @@ -1183,12 +1209,16 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True, EXAMPLES:: sage: from sage.groups.generic import order_from_multiple + + sage: # needs sage.rings.finite_rings sage: k. = GF(5^5) sage: b = a^4 - sage: order_from_multiple(b,5^5-1,operation='*') + sage: order_from_multiple(b, 5^5 - 1, operation='*') 781 - sage: E = EllipticCurve(k,[2,4]) - sage: P = E(3*a^4 + 3*a , 2*a + 1 ) + + sage: # needs sage.rings.finite_rings sage.schemes + sage: E = EllipticCurve(k, [2,4]) + sage: P = E(3*a^4 + 3*a, 2*a + 1) sage: M = E.cardinality(); M 3227 sage: F = M.factor() @@ -1198,18 +1228,22 @@ def order_from_multiple(P, m, plist=None, factorization=None, check=True, sage: order_from_multiple(Q, M, factorization=F, operation='+') 7 + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(230) sage: w = z^50 - sage: order_from_multiple(w,230,operation='*') + sage: order_from_multiple(w, 230, operation='*') 23 + sage: # needs sage.rings.finite_rings sage: F = GF(2^1279,'a') - sage: n = F.cardinality()-1 # Mersenne prime - sage: order_from_multiple(F.random_element(),n,factorization=[(n,1)],operation='*') == n + sage: n = F.cardinality() - 1 # Mersenne prime + sage: order_from_multiple(F.random_element(), n, + ....: factorization=[(n,1)], operation='*') == n True + sage: # needs sage.rings.finite_rings sage: K. = GF(3^60) - sage: order_from_multiple(a, 3^60-1, operation='*', check=False) + sage: order_from_multiple(a, 3^60 - 1, operation='*', check=False) 42391158275216203514294433200 """ Z = integer_ring.ZZ @@ -1294,21 +1328,21 @@ def order_from_bounds(P, bounds, d=None, operation='+', INPUT: - - ``P`` - a Sage object which is a group element + - ``P`` -- a Sage object which is a group element - - ``bounds`` - a 2-tuple ``(lb,ub)`` such that ``m*P=0`` (or + - ``bounds`` -- a 2-tuple ``(lb,ub)`` such that ``m*P=0`` (or ``P**m=1``) for some ``m`` with ``lb<=m<=ub``. - - ``d`` - (optional) a positive integer; only ``m`` which are + - ``d`` -- (optional) a positive integer; only ``m`` which are multiples of this will be considered. - - ``operation`` - string: '+' (default ) or '*' or other. + - ``operation`` -- string: ``'+'`` (default ) or ``'*'`` or other. If other, the following must be supplied: - - ``identity``: the identity element for the group; - - ``inverse()``: a function of one argument giving the inverse + - ``identity`` -- the identity element for the group; + - ``inverse()`` -- a function of one argument giving the inverse of a group element; - - ``op()``: a function of 2 arguments defining the group binary + - ``op()`` -- a function of 2 arguments defining the group binary operation. @@ -1321,12 +1355,16 @@ def order_from_bounds(P, bounds, d=None, operation='+', EXAMPLES:: sage: from sage.groups.generic import order_from_bounds + + sage: # needs sage.rings.finite_rings sage: k. = GF(5^5) sage: b = a^4 - sage: order_from_bounds(b,(5^4,5^5),operation='*') + sage: order_from_bounds(b, (5^4, 5^5), operation='*') 781 - sage: E = EllipticCurve(k,[2,4]) - sage: P = E(3*a^4 + 3*a , 2*a + 1 ) + + sage: # needs sage.rings.finite_rings sage.schemes + sage: E = EllipticCurve(k, [2,4]) + sage: P = E(3*a^4 + 3*a, 2*a + 1) sage: bounds = Hasse_bounds(5^5) sage: Q = E(0,2) sage: order_from_bounds(Q, bounds, operation='+') @@ -1334,9 +1372,10 @@ def order_from_bounds(P, bounds, d=None, operation='+', sage: order_from_bounds(P, bounds, 7, operation='+') 3227 - sage: K.=CyclotomicField(230) + sage: # needs sage.rings.number_field + sage: K. = CyclotomicField(230) sage: w = z^50 - sage: order_from_bounds(w,(200,250),operation='*') + sage: order_from_bounds(w, (200, 250), operation='*') 23 """ from operator import mul, add @@ -1378,15 +1417,14 @@ def merge_points(P1, P2, operation='+', - ``P1`` -- a pair `(g_1,n_1)` where `g_1` is a group element of order `n_1` - ``P2`` -- a pair `(g_2,n_2)` where `g_2` is a group element of order `n_2` - - ``operation`` -- string: '+' (default ) or '*' or other. If + - ``operation`` -- string: ``'+'`` (default) or ``'*'`` or other. If other, the following must be supplied: - - ``identity``: the identity element for the group; - - ``inverse()``: a function of one argument giving the inverse - of a group element; - - ``op()``: a function of 2 arguments defining the group - binary operation. - + - ``identity`` -- the identity element for the group; + - ``inverse()`` -- a function of one argument giving the inverse + of a group element; + - ``op()`` -- a function of 2 arguments defining the group + binary operation. OUTPUT: @@ -1394,28 +1432,30 @@ def merge_points(P1, P2, operation='+', EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: from sage.groups.generic import merge_points - sage: F.=GF(3^6,'a') + sage: F. = GF(3^6,'a') sage: b = a^7 sage: c = a^13 sage: ob = (3^6-1)//7 sage: oc = (3^6-1)//13 - sage: merge_points((b,ob),(c,oc),operation='*') + sage: merge_points((b,ob), (c,oc), operation='*') (a^4 + 2*a^3 + 2*a^2, 728) - sage: d,od = merge_points((b,ob),(c,oc),operation='*') + sage: d, od = merge_points((b,ob), (c,oc), operation='*') sage: od == d.multiplicative_order() True - sage: od == lcm(ob,oc) + sage: od == lcm(ob, oc) True - sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a,a^4 + a^3 + 2*a + 1]) - sage: P = E(2*a^5 + 2*a^4 + a^3 + 2 , a^4 + a^3 + a^2 + 2*a + 2) + sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes + sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1]) + sage: P = E(2*a^5 + 2*a^4 + a^3 + 2, a^4 + a^3 + a^2 + 2*a + 2) sage: P.order() 7 - sage: Q = E(2*a^5 + 2*a^4 + 1 , a^5 + 2*a^3 + 2*a + 2 ) + sage: Q = E(2*a^5 + 2*a^4 + 1, a^5 + 2*a^3 + 2*a + 2) sage: Q.order() 4 - sage: R,m = merge_points((P,7),(Q,4), operation='+') + sage: R, m = merge_points((P,7), (Q,4), operation='+') sage: R.order() == m True sage: m == lcm(7,4) @@ -1466,12 +1506,12 @@ def structure_description(G, latex=False): INPUT: - - ``latex`` -- a boolean (default: ``False``). If ``True`` return a + - ``latex`` -- a boolean (default: ``False``). If ``True``, return a LaTeX formatted string. OUTPUT: - - string + string .. WARNING:: @@ -1483,6 +1523,7 @@ def structure_description(G, latex=False): EXAMPLES:: + sage: # needs sage.groups sage: G = CyclicPermutationGroup(6) sage: G.structure_description() 'C6' @@ -1495,26 +1536,26 @@ def structure_description(G, latex=False): This method is mainly intended for small groups or groups with few normal subgroups. Even then there are some surprises:: - sage: D3 = DihedralGroup(3) - sage: D3.structure_description() + sage: D3 = DihedralGroup(3) # needs sage.groups + sage: D3.structure_description() # needs sage.groups 'S3' We use the Sage notation for the degree of dihedral groups:: - sage: D4 = DihedralGroup(4) - sage: D4.structure_description() + sage: D4 = DihedralGroup(4) # needs sage.groups + sage: D4.structure_description() # needs sage.groups 'D4' Works for finitely presented groups (:trac:`17573`):: - sage: F. = FreeGroup() - sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1] - sage: G.structure_description() + sage: F. = FreeGroup() # needs sage.groups + sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1] # needs sage.groups + sage: G.structure_description() # needs sage.groups 'C7' And matrix groups (:trac:`17573`):: - sage: groups.matrix.GL(4,2).structure_description() + sage: groups.matrix.GL(4,2).structure_description() # needs sage.libs.gap sage.modules 'A8' """ import re diff --git a/src/sage/groups/group.pyx b/src/sage/groups/group.pyx index 872d5c509d7..cd2521e3478 100644 --- a/src/sage/groups/group.pyx +++ b/src/sage/groups/group.pyx @@ -35,9 +35,9 @@ def is_Group(x): EXAMPLES:: - sage: F. = FreeGroup() + sage: F. = FreeGroup() # needs sage.combinat sage: from sage.groups.group import is_Group - sage: is_Group(F) + sage: is_Group(F) # needs sage.combinat True sage: is_Group("a string") False @@ -87,7 +87,7 @@ cdef class Group(Parent): sage: G = Group(category=Groups()) # todo: do the same test with some subcategory of Groups when there will exist one sage: G.category() Category of groups - sage: G = Group(category = CommutativeAdditiveGroups()) + sage: G = Group(category=CommutativeAdditiveGroups()) Traceback (most recent call last): ... ValueError: (Category of commutative additive groups,) is not a subcategory of Category of groups @@ -96,6 +96,7 @@ cdef class Group(Parent): Check for :trac:`8119`:: + sage: # needs sage.groups sage: G = SymmetricGroup(2) sage: h = hash(G) sage: G.rename('S2') @@ -139,7 +140,7 @@ cdef class Group(Parent): EXAMPLES:: - sage: SL(2, 7).is_commutative() # optional - sage.rings.finite_rings + sage: SL(2, 7).is_commutative() # needs sage.modules sage.rings.finite_rings False """ return self.is_abelian() @@ -161,8 +162,8 @@ cdef class Group(Parent): TESTS:: - sage: H = SL(2, QQ) - sage: H.order() + sage: H = SL(2, QQ) # needs sage.modules + sage: H.order() # needs sage.modules +Infinity """ try: @@ -211,8 +212,8 @@ cdef class Group(Parent): EXAMPLES:: - sage: G = AbelianGroup([2,3,4,5]) # optional - sage.groups - sage: G.an_element() # optional - sage.groups + sage: G = AbelianGroup([2,3,4,5]) # needs sage.groups + sage: G.an_element() # needs sage.groups f0*f1*f2*f3 """ return self.prod(self.gens()) diff --git a/src/sage/groups/group_exp.py b/src/sage/groups/group_exp.py index 4f3d27a8def..ffae5e73cb2 100644 --- a/src/sage/groups/group_exp.py +++ b/src/sage/groups/group_exp.py @@ -357,4 +357,5 @@ def group_generators(self): raise AttributeError("Additive group has no method 'gens'") return tuple([self(x) for x in additive_generators]) + GroupExp_Class.Element = GroupExpElement diff --git a/src/sage/groups/group_semidirect_product.py b/src/sage/groups/group_semidirect_product.py index 3ac629b9411..1805dbbc53a 100644 --- a/src/sage/groups/group_semidirect_product.py +++ b/src/sage/groups/group_semidirect_product.py @@ -33,7 +33,8 @@ def _repr_(self): sage: def twist(x,y): ....: return y - sage: GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), WeylGroup(['A',3],prefix="t"),twist) # indirect doctest + sage: GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), # indirect doctest + ....: WeylGroup(['A',3],prefix="t"), twist) Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) acting on Weyl Group of type ['A', 3] @@ -67,6 +68,7 @@ def __invert__(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: L = RootSystem(['A',2]).root_lattice() sage: from sage.groups.group_exp import GroupExp sage: EL = GroupExp()(L) @@ -95,6 +97,7 @@ def to_opposite(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: L = RootSystem(['A',2]).root_lattice(); L Root lattice of the Root system of type ['A', 2] sage: from sage.groups.group_exp import GroupExp @@ -117,7 +120,10 @@ def to_opposite(self): sage: g.to_opposite() t[-2*alpha[1]] * s1*s2 sage: g.to_opposite().parent() - Semidirect product of Multiplicative form of Root lattice of the Root system of type ['A', 2] acted upon by Weyl Group of type ['A', 2] (as a matrix group acting on the root lattice) + Semidirect product of + Multiplicative form of Root lattice of the Root system of type ['A', 2] + acted upon by Weyl Group of type ['A', 2] + (as a matrix group acting on the root lattice) """ par = self.parent() Gop = par.opposite_semidirect_product() @@ -141,7 +147,7 @@ class GroupSemidirectProduct(CartesianProduct): - ``prefix0`` -- (default: ``None``) optional string - ``prefix1`` -- (default: ``None``) optional string - ``print_tuple`` -- ``True`` or ``False`` (default: ``False``) - - ``category`` -- A category (default: Groups()) + - ``category`` -- A category (default: ``Groups()``) A semidirect product of groups `G` and `H` is a group structure on the Cartesian product `G \times H` whose product agrees with that @@ -207,10 +213,10 @@ class GroupSemidirectProduct(CartesianProduct): sage: G = GL(2,QQ) sage: V = QQ^2 - sage: EV = GroupExp()(V) # make a multiplicative version of V + sage: EV = GroupExp()(V) # make a multiplicative version of V sage: def twist(g,v): ....: return EV(g*v.value) - sage: H = GroupSemidirectProduct(G, EV, twist=twist, prefix1 = 't'); H + sage: H = GroupSemidirectProduct(G, EV, twist=twist, prefix1='t'); H Semidirect product of General Linear Group of degree 2 over Rational Field acting on Multiplicative form of Vector space of dimension 2 over Rational Field @@ -218,11 +224,13 @@ class GroupSemidirectProduct(CartesianProduct): t[(1, 0)] sage: x^2 t[(2, 0)] + + sage: # needs sage.rings.number_field sage: cartan_type = CartanType(['A',2]) sage: W = WeylGroup(cartan_type, prefix="s") sage: def twist(w,v): ....: return w*v*(~w) - sage: WW = GroupSemidirectProduct(W,W, twist=twist, print_tuple=True) + sage: WW = GroupSemidirectProduct(W, W, twist=twist, print_tuple=True) sage: s = Family(cartan_type.index_set(), lambda i: W.simple_reflection(i)) sage: y = WW((s[1],s[2])); y (s1, s2) @@ -247,7 +255,8 @@ def __init__(self, G, H, twist=None, act_to_right=True, prefix0=None, ....: return y sage: import __main__ sage: __main__.twist = twist - sage: G = GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), WeylGroup(['A',3],prefix="t"),twist) + sage: G = GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), + ....: WeylGroup(['A',3],prefix="t"), twist) sage: TestSuite(G).run() The ``__main__`` business is a trick to pass the pickling test. @@ -289,7 +298,8 @@ def act_to_right(self): sage: def twist(x,y): ....: return y - sage: GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), WeylGroup(['A',3],prefix="t"),twist).act_to_right() + sage: GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), + ....: WeylGroup(['A',3],prefix="t"), twist).act_to_right() True """ return self._act_to_right @@ -302,7 +312,8 @@ def _repr_(self): sage: def twist(x,y): ....: return y - sage: GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), WeylGroup(['A',3],prefix="t"),twist) # indirect doctest + sage: GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), # indirect doctest + ....: WeylGroup(['A',3],prefix="t"), twist) Semidirect product of Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) acting on Weyl Group of type ['A', 3] (as a matrix group acting on the ambient space) @@ -324,7 +335,8 @@ def _element_constructor_(self, x): ....: return y sage: import __main__ sage: __main__.twist = twist - sage: g = GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), WeylGroup(['A',3],prefix="t"),twist).an_element() + sage: g = GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), + ....: WeylGroup(['A',3],prefix="t"), twist).an_element() sage: TestSuite(g).run() """ def type_error(): @@ -354,10 +366,10 @@ def one(self): sage: G = GL(2,QQ) sage: V = QQ^2 - sage: EV = GroupExp()(V) # make a multiplicative version of V + sage: EV = GroupExp()(V) # make a multiplicative version of V sage: def twist(g,v): ....: return EV(g*v.value) - sage: one = GroupSemidirectProduct(G, EV, twist=twist, prefix1 = 't').one(); one + sage: one = GroupSemidirectProduct(G, EV, twist=twist, prefix1='t').one(); one 1 sage: one.cartesian_projection(0) [1 0] @@ -378,7 +390,7 @@ def group_generators(self): sage: import __main__ sage: __main__.twist = twist sage: EZ = GroupExp()(ZZ) - sage: GroupSemidirectProduct(EZ,EZ,twist,print_tuple=True).group_generators() + sage: GroupSemidirectProduct(EZ, EZ, twist, print_tuple=True).group_generators() ((1, 0), (0, 1)) """ def has_gens(G): @@ -404,10 +416,10 @@ def product(self, x, y): sage: G = GL(2,QQ) sage: V = QQ^2 - sage: EV = GroupExp()(V) # make a multiplicative version of V + sage: EV = GroupExp()(V) # make a multiplicative version of V sage: def twist(g,v): ....: return EV(g*v.value) - sage: S = GroupSemidirectProduct(G, EV, twist=twist, prefix1 = 't') + sage: S = GroupSemidirectProduct(G, EV, twist=twist, prefix1='t') sage: g = G([[2,1],[3,1]]); g [2 1] [3 1] @@ -442,7 +454,8 @@ def opposite_semidirect_product(self): sage: G = GL(2,QQ) sage: L = QQ^2 sage: EL = GroupExp()(L) - sage: H = GroupSemidirectProduct(G, EL, twist = lambda g,v: EL(g*v.value), prefix1 = 't'); H + sage: H = GroupSemidirectProduct(G, EL, prefix1='t', + ....: twist=lambda g,v: EL(g*v.value)); H Semidirect product of General Linear Group of degree 2 over Rational Field acting on Multiplicative form of Vector space of dimension 2 over Rational Field @@ -479,7 +492,8 @@ def construction(self): sage: def twist(x,y): ....: return y - sage: H = GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), WeylGroup(['A',3],prefix="t"), twist) + sage: H = GroupSemidirectProduct(WeylGroup(['A',2],prefix="s"), + ....: WeylGroup(['A',3],prefix="t"), twist) sage: H.construction() """ return None diff --git a/src/sage/groups/groups_catalog.py b/src/sage/groups/groups_catalog.py index 47e6e230508..a95ffaefb4a 100644 --- a/src/sage/groups/groups_catalog.py +++ b/src/sage/groups/groups_catalog.py @@ -101,9 +101,13 @@ # groups.presentation - free groups with relations # groups.symmetries - permutation groups of regular solids, or similar -from sage.groups.matrix_gps import catalog as matrix -from sage.groups.perm_gps import permutation_groups_catalog as permutation -from sage.groups.misc_gps import misc_groups_catalog as misc -from sage.groups.affine_gps import catalog as affine -from sage.groups.lie_gps import catalog as lie -from sage.groups import finitely_presented_catalog as presentation +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.groups.matrix_gps', 'catalog', as_='matrix') +lazy_import('sage.groups.perm_gps', 'permutation_groups_catalog', as_='permutation') +lazy_import('sage.groups.misc_gps', 'misc_groups_catalog', as_='misc') +lazy_import('sage.groups.affine_gps', 'catalog', as_='affine') +lazy_import('sage.groups', 'finitely_presented_catalog', as_='presentation') +lazy_import('sage.groups.lie_gps', 'catalog', as_='lie') + +del lazy_import diff --git a/src/sage/groups/indexed_free_group.py b/src/sage/groups/indexed_free_group.py index 0cbcf9b8a2d..287ab021b1d 100644 --- a/src/sage/groups/indexed_free_group.py +++ b/src/sage/groups/indexed_free_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat """ Indexed Free Groups diff --git a/src/sage/groups/kernel_subgroup.py b/src/sage/groups/kernel_subgroup.py index 024e8f47b3b..605778784e4 100644 --- a/src/sage/groups/kernel_subgroup.py +++ b/src/sage/groups/kernel_subgroup.py @@ -94,8 +94,8 @@ def defining_morphism(self): EXAMPLES:: - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.defining_morphism() + sage: PJ3 = groups.misc.PureCactus(3) # needs sage.rings.number_field + sage: PJ3.defining_morphism() # needs sage.rings.number_field Conversion via _from_cactus_group_element map: From: Cactus Group with 3 fruit To: Symmetric group of order 3! as a permutation group @@ -109,8 +109,8 @@ def ambient(self): EXAMPLES:: - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.ambient() + sage: PJ3 = groups.misc.PureCactus(3) # needs sage.rings.number_field + sage: PJ3.ambient() # needs sage.rings.number_field Cactus Group with 3 fruit """ return self._morphism.domain() @@ -121,8 +121,8 @@ def _an_element_(self): EXAMPLES:: - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.an_element() + sage: PJ3 = groups.misc.PureCactus(3) # needs sage.rings.number_field + sage: PJ3.an_element() # needs sage.rings.number_field 1 """ return self.element_class(self, self.ambient().one()) @@ -133,8 +133,8 @@ def lift(self, x): EXAMPLES:: - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.lift(PJ3.an_element()).parent() + sage: PJ3 = groups.misc.PureCactus(3) # needs sage.rings.number_field + sage: PJ3.lift(PJ3.an_element()).parent() # needs sage.rings.number_field Cactus Group with 3 fruit """ return x.value @@ -145,6 +145,7 @@ def retract(self, x): EXAMPLES:: + sage: # needs sage.rings.number_field sage: J3 = groups.misc.Cactus(3) sage: s12,s13,s23 = J3.group_generators() sage: PJ3 = groups.misc.PureCactus(3) @@ -161,6 +162,7 @@ def _element_constructor_(self, x): EXAMPLES:: + sage: # needs sage.rings.number_field sage: J3 = groups.misc.Cactus(3) sage: s12,s13,s23 = J3.group_generators() sage: PJ3 = groups.misc.PureCactus(3) @@ -200,6 +202,7 @@ def _mul_(self, other): EXAMPLES:: + sage: # needs sage.rings.number_field sage: J3 = groups.misc.Cactus(3) sage: s12,s13,s23 = J3.group_generators() sage: PJ3 = groups.misc.PureCactus(3) @@ -215,6 +218,7 @@ def __invert__(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: J3 = groups.misc.Cactus(3) sage: s12,s13,s23 = J3.group_generators() sage: PJ3 = groups.misc.PureCactus(3) diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 6fb27280d8b..e2da04e9ed3 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules """ Mix-in Class for GAP-based Groups @@ -250,8 +251,8 @@ def conjugacy_classes_representatives(self): EXAMPLES:: - sage: G = SU(3,GF(2)) - sage: len(G.conjugacy_classes_representatives()) + sage: G = SU(3,GF(2)) # needs sage.rings.finite_rings + sage: len(G.conjugacy_classes_representatives()) # needs sage.rings.finite_rings 16 sage: G = GL(2,GF(3)) @@ -261,7 +262,7 @@ def conjugacy_classes_representatives(self): [0 1], [1 1], [0 2], [1 2], [1 0], [1 2], [1 1], [0 1] ) - sage: len(GU(2,GF(5)).conjugacy_classes_representatives()) + sage: len(GU(2,GF(5)).conjugacy_classes_representatives()) # needs sage.rings.finite_rings 36 :: @@ -338,8 +339,8 @@ class function on the conjugacy classes, in that order. EXAMPLES:: sage: G = GL(2,GF(3)) - sage: chi = G.class_function(range(8)) - sage: list(chi) + sage: chi = G.class_function(range(8)) # needs sage.rings.number_field + sage: list(chi) # needs sage.rings.number_field [0, 1, 2, 3, 4, 5, 6, 7] """ from sage.groups.class_function import ClassFunction_libgap @@ -356,8 +357,8 @@ def center(self): EXAMPLES:: - sage: G = SU(3, GF(2)) - sage: G.center() + sage: G = SU(3, GF(2)) # needs sage.rings.finite_rings + sage: G.center() # needs sage.rings.finite_rings Subgroup with 1 generators ( [a 0 0] [0 a 0] @@ -374,7 +375,7 @@ def center(self): [0 2 0] [0 0 2] ) of General Linear Group of degree 3 over Finite Field of size 3 - sage: GU(3, GF(2)).center() + sage: GU(3, GF(2)).center() # needs sage.rings.finite_rings Subgroup with 1 generators ( [a + 1 0 0] [ 0 a + 1 0] @@ -477,7 +478,8 @@ def subgroups(self): sage: G = groups.matrix.GL(2, 2) sage: G.subgroups() - [Subgroup with 0 generators () of General Linear Group of degree 2 over Finite Field of size 2, + [Subgroup with 0 generators () + of General Linear Group of degree 2 over Finite Field of size 2, Subgroup with 1 generators ( [0 1] [1 0] @@ -522,7 +524,8 @@ def conjugacy_classes_subgroups(self): sage: G = groups.matrix.GL(2,2) sage: G.conjugacy_classes_subgroups() - [Subgroup with 0 generators () of General Linear Group of degree 2 over Finite Field of size 2, + [Subgroup with 0 generators () + of General Linear Group of degree 2 over Finite Field of size 2, Subgroup with 1 generators ( [1 1] [0 1] @@ -622,10 +625,10 @@ def intersection(self, other): [-2 -1 2] [ 0 0 1] ) of Matrix group over Rational Field with 2 generators ( - [ 0 1/2 0] [ 0 1/2 0] - [ 2 0 0] [ -2 -1 2] - [ 0 0 1], [ 0 0 1] - ) + [ 0 1/2 0] [ 0 1/2 0] + [ 2 0 0] [ -2 -1 2] + [ 0 0 1], [ 0 0 1] + ) sage: GL(3,ZZ).intersection(G) Subgroup with 1 generators ( [ 1 0 0] @@ -633,11 +636,12 @@ def intersection(self, other): [ 0 0 1] ) of General Linear Group of degree 3 over Integer Ring sage: G.intersection(SL(3,ZZ)) - Subgroup with 0 generators () of Matrix group over Rational Field with 2 generators ( - [ 0 1/2 0] [ 0 1/2 0] - [ 2 0 0] [ -2 -1 2] - [ 0 0 1], [ 0 0 1] - ) + Subgroup with 0 generators () + of Matrix group over Rational Field with 2 generators ( + [ 0 1/2 0] [ 0 1/2 0] + [ 2 0 0] [ -2 -1 2] + [ 0 0 1], [ 0 0 1] + ) """ G = self.gap() H = other.gap() @@ -656,7 +660,7 @@ def irreducible_characters(self): EXAMPLES:: sage: G = GL(2,2) - sage: G.irreducible_characters() + sage: G.irreducible_characters() # needs sage.rings.number_field (Character of General Linear Group of degree 2 over Finite Field of size 2, Character of General Linear Group of degree 2 over Finite Field of size 2, Character of General Linear Group of degree 2 over Finite Field of size 2) @@ -691,7 +695,7 @@ def character(self, values): EXAMPLES:: sage: G = MatrixGroup(AlternatingGroup(4)) - sage: G.character([1]*len(G.conjugacy_classes_representatives())) + sage: G.character([1]*len(G.conjugacy_classes_representatives())) # needs sage.rings.number_field Character of Matrix group over Integer Ring with 12 generators :: @@ -714,7 +718,7 @@ def trivial_character(self): EXAMPLES:: - sage: MatrixGroup(SymmetricGroup(3)).trivial_character() + sage: MatrixGroup(SymmetricGroup(3)).trivial_character() # needs sage.rings.number_field Character of Matrix group over Integer Ring with 6 generators :: @@ -742,10 +746,10 @@ def character_table(self): EXAMPLES:: - sage: MatrixGroup(SymmetricGroup(2)).character_table() + sage: MatrixGroup(SymmetricGroup(2)).character_table() # needs sage.rings.number_field [ 1 -1] [ 1 1] - sage: MatrixGroup(SymmetricGroup(3)).character_table() + sage: MatrixGroup(SymmetricGroup(3)).character_table() # needs sage.rings.number_field [ 1 1 -1] [ 2 -1 0] [ 1 1 1] @@ -797,7 +801,7 @@ def random_element(self): True sage: F = GF(5); MS = MatrixSpace(F,2,2) - sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])] + sage: gens = [MS([[1,2],[-1,1]]), MS([[1,1],[0,1]])] sage: G = MatrixGroup(gens) sage: G.random_element() # random [1 3] diff --git a/src/sage/groups/libgap_morphism.py b/src/sage/groups/libgap_morphism.py index 93f33bf68a4..f1a47fcb279 100644 --- a/src/sage/groups/libgap_morphism.py +++ b/src/sage/groups/libgap_morphism.py @@ -108,7 +108,7 @@ class GroupMorphism_libgap(Morphism): [1 0] [1 1] sage: F = GF(7); MS = MatrixSpace(F,2,2) - sage: F.multiplicative_generator() + sage: F.multiplicative_generator() # needs sage.libs.pari 3 sage: G = MatrixGroup([MS([3,0,0,1])]) sage: a = G.gens()[0]^2 @@ -136,7 +136,7 @@ class GroupMorphism_libgap(Morphism): sage: F = GF(7); MS = MatrixSpace(F,2,2) - sage: F.multiplicative_generator() + sage: F.multiplicative_generator() # needs sage.libs.pari 3 sage: G = MatrixGroup([MS([3,0,0,1])]) sage: a = G.gens()[0]^2 @@ -151,7 +151,7 @@ class GroupMorphism_libgap(Morphism): ) sage: F = GF(7); MS = MatrixSpace(F,2,2) - sage: F.multiplicative_generator() + sage: F.multiplicative_generator() # needs sage.libs.pari 3 sage: G = MatrixGroup([MS([3,0,0,1])]) sage: a = G.gens()[0]^2 @@ -212,6 +212,7 @@ class GroupMorphism_libgap(Morphism): sage: phi(G.one()).parent() General Linear Group of degree 3 over Finite Field of size 3 + sage: # needs sage.symbolic sage: MS = MatrixSpace(SR, 2, 2) sage: G = MatrixGroup([MS(1), MS([1,2,3,4])]) sage: G.Hom(G) @@ -400,12 +401,15 @@ def pushforward(self, J, *args, **kwds): a sage: x.parent() Finitely presented group < a, b | a, b^3 > + + sage: # needs sage.rings.finite_rings sage: G = GU(3,2) sage: P = PGU(3,2) sage: pr = Hom(G, P).natural_map() sage: GS = G.subgroup([G.gen(0)]) sage: pr.pushforward(GS) - Subgroup generated by [(3,4,5)(10,18,14)(11,19,15)(12,20,16)(13,21,17)] of (The projective general unitary group of degree 3 over Finite Field of size 2) + Subgroup generated by [(3,4,5)(10,18,14)(11,19,15)(12,20,16)(13,21,17)] of + (The projective general unitary group of degree 3 over Finite Field of size 2) """ dom = self.domain() codom = self.codomain() @@ -546,9 +550,9 @@ def preimage(self, S): phi = self.gap() from sage.groups.perm_gps.permgroup import PermutationGroup_generic if not isinstance(S, (ParentLibGAP, PermutationGroup_generic)): - raise TypeError("%s must be a GAP or permutation group of %s"%(S, self)) + raise TypeError("%s must be a GAP or permutation group of %s" % (S, self)) if not self.codomain().gap().IsSubgroup(S.gap()).sage(): - raise ValueError("%s must be a subgroup of %s"%(S, self)) + raise ValueError("%s must be a subgroup of %s" % (S, self)) preimage = phi.PreImage(S.gap()) return self.domain()._subgroup_constructor(preimage) @@ -564,6 +568,7 @@ def section(self): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: G = GU(3,2) sage: P = PGU(3,2) sage: pr = Hom(G, P).natural_map() @@ -644,6 +649,7 @@ def _element_constructor_(self, x, check=True, **options): A group homomorphism between a finitely presented group and a subgroup of a permutation group:: + sage: # needs sage.rings.finite_rings sage: PG = PGU(6,2) sage: g, h = PG.gens() sage: p1 = h^-3*(h^-1*g^-1)^2*h*g*h^2*g^-1*h^2*g*h^-5*g^-1 diff --git a/src/sage/groups/matrix_gps/binary_dihedral.py b/src/sage/groups/matrix_gps/binary_dihedral.py index c8813eeabd4..ccce9eeb17b 100644 --- a/src/sage/groups/matrix_gps/binary_dihedral.py +++ b/src/sage/groups/matrix_gps/binary_dihedral.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap sage.modules sage.rings.number_field """ Binary Dihedral Groups diff --git a/src/sage/groups/matrix_gps/coxeter_group.py b/src/sage/groups/matrix_gps/coxeter_group.py index 66a877c61ac..27d65a55a37 100644 --- a/src/sage/groups/matrix_gps/coxeter_group.py +++ b/src/sage/groups/matrix_gps/coxeter_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs """ Coxeter Groups As Matrix Groups @@ -19,23 +20,19 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation +import sage.rings.abc + from sage.categories.coxeter_groups import CoxeterGroups from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix from sage.groups.matrix_gps.finitely_generated import FinitelyGeneratedMatrixGroup_generic from sage.groups.matrix_gps.group_element import MatrixGroupElement_generic from sage.matrix.args import SparseEntry from sage.matrix.matrix_space import MatrixSpace - -import sage.rings.abc +from sage.misc.cachefunc import cached_method from sage.rings.integer_ring import ZZ from sage.rings.infinity import infinity -from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField -from sage.rings.number_field.number_field import QuadraticField - -from sage.misc.cachefunc import cached_method - from sage.sets.family import Family +from sage.structure.unique_representation import UniqueRepresentation class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_generic): @@ -82,8 +79,8 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene We can create Coxeter groups from Coxeter matrices:: - sage: W = CoxeterGroup([[1, 6, 3], [6, 1, 10], [3, 10, 1]]) - sage: W + sage: # needs sage.rings.number_field + sage: W = CoxeterGroup([[1, 6, 3], [6, 1, 10], [3, 10, 1]]); W Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [ 1 6 3] [ 6 1 10] @@ -102,6 +99,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene [ 0 1 0] [ 1 E(20) - E(20)^9 -1] ) + sage: m = matrix([[1,3,3,3], [3,1,3,2], [3,3,1,2], [3,2,2,1]]) sage: W = CoxeterGroup(m) sage: W.gens() @@ -143,7 +141,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene [3 1 3 2] [3 3 1 2] [3 2 2 1] - sage: CoxeterGroup([[1,4],[4,1]], base_ring=QQ) + sage: CoxeterGroup([[1,4],[4,1]], base_ring=QQ) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert sqrt(2) to a rational @@ -152,6 +150,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene graphs, we can input a Coxeter graph. Following the standard convention, edges with no label (i.e. labelled by ``None``) are treated as 3:: + sage: # needs sage.rings.number_field sage: G = Graph([(0,3,None), (1,3,15), (2,3,7), (0,1,3)]) sage: W = CoxeterGroup(G); W Coxeter group over Universal Cyclotomic Field with Coxeter matrix: @@ -166,6 +165,7 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene Because there currently is no class for `\ZZ \cup \{ \infty \}`, labels of `\infty` are given by `-1` in the Coxeter matrix:: + sage: # needs sage.rings.number_field sage: G = Graph([(0,1,None), (1,2,4), (0,2,oo)]) sage: W = CoxeterGroup(G) sage: W.coxeter_matrix() @@ -176,16 +176,14 @@ class CoxeterMatrixGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_gene We can also create Coxeter groups from Cartan types using the ``implementation`` keyword:: - sage: W = CoxeterGroup(['D',5], implementation="reflection") - sage: W + sage: W = CoxeterGroup(['D',5], implementation="reflection"); W Finite Coxeter group over Integer Ring with Coxeter matrix: [1 3 2 2 2] [3 1 3 2 2] [2 3 1 3 3] [2 2 3 1 2] [2 2 3 2 1] - sage: W = CoxeterGroup(['H',3], implementation="reflection") - sage: W + sage: W = CoxeterGroup(['H',3], implementation="reflection"); W # needs sage.rings.number_field Finite Coxeter group over Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? with Coxeter matrix: @@ -219,6 +217,7 @@ def __classcall_private__(cls, data, base_ring=None, index_set=None): if data.is_simply_laced(): base_ring = ZZ elif data.is_finite(): + from sage.rings.number_field.number_field import QuadraticField letter = data.coxeter_type().cartan_type().type() if letter in ['B', 'C', 'F']: base_ring = QuadraticField(2) @@ -227,8 +226,10 @@ def __classcall_private__(cls, data, base_ring=None, index_set=None): elif letter == 'H': base_ring = QuadraticField(5) else: + from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField base_ring = UniversalCyclotomicField() else: + from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField base_ring = UniversalCyclotomicField() return super().__classcall__(cls, data, base_ring, data.index_set()) @@ -240,6 +241,8 @@ def __init__(self, coxeter_matrix, base_ring, index_set): sage: W = CoxeterGroup([[1,3,2],[3,1,3],[2,3,1]]) sage: TestSuite(W).run() # long time + + sage: # needs sage.rings.number_field sage: W = CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]], base_ring=QQbar) sage: TestSuite(W).run() # long time sage: W = CoxeterGroup([[1,3,2],[3,1,6],[2,6,1]]) @@ -251,6 +254,8 @@ def __init__(self, coxeter_matrix, base_ring, index_set): sage: CoxeterGroup(['D',4], base_ring=QQ).category() Category of finite irreducible coxeter groups + + sage: # needs sage.rings.number_field sage: CoxeterGroup(['H',4], base_ring=QQbar).category() Category of finite irreducible coxeter groups sage: F = CoxeterGroups().Finite() @@ -274,8 +279,8 @@ def __init__(self, coxeter_matrix, base_ring, index_set): MS = MatrixSpace(base_ring, n, sparse=True) one = MS.one() # FIXME: Hack because there is no ZZ \cup \{ \infty \}: -1 represents \infty - E = UniversalCyclotomicField().gen - if base_ring is UniversalCyclotomicField(): + if isinstance(base_ring, sage.rings.abc.UniversalCyclotomicField): + E = base_ring.gen def val(x): if x == -1: @@ -283,6 +288,9 @@ def val(x): else: return E(2 * x) + ~E(2 * x) elif isinstance(base_ring, sage.rings.abc.NumberField_quadratic): + from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField + + E = UniversalCyclotomicField().gen def val(x): if x == -1: @@ -332,7 +340,7 @@ def _repr_(self): EXAMPLES:: - sage: CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]]) + sage: CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]]) # needs sage.rings.number_field Finite Coxeter group over Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? with Coxeter matrix: [1 3 2] [3 1 4] @@ -349,6 +357,7 @@ def _coerce_map_from_(self, P): EXAMPLES:: + sage: # needs sage.combinat sage: W = CoxeterGroup(["A",4]) sage: W2 = WeylGroup(["A",4]) sage: W._coerce_map_from_(W2) @@ -374,7 +383,7 @@ def coxeter_matrix(self): sage: W.coxeter_matrix() [1 3] [3 1] - sage: W = CoxeterGroup(['H',3]) + sage: W = CoxeterGroup(['H',3]) # needs sage.rings.number_field sage: W.coxeter_matrix() [1 3 2] [3 1 5] @@ -400,7 +409,7 @@ def bilinear_form(self): EXAMPLES:: sage: W = CoxeterGroup(['D',4]) - sage: W.bilinear_form() + sage: W.bilinear_form() # needs sage.symbolic [ 1 -1/2 0 0] [-1/2 1 -1/2 -1/2] [ 0 -1/2 1 0] @@ -414,6 +423,7 @@ def is_finite(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: [l for l in range(2, 9) if ....: CoxeterGroup([[1,3,2],[3,1,l],[2,l,1]]).is_finite()] [2, 3, 4, 5] @@ -468,6 +478,7 @@ def order(self): EXAMPLES:: + sage: # needs sage.rings.number_field sage: W = CoxeterGroup([[1,3],[3,1]]) sage: W.order() 6 @@ -581,6 +592,8 @@ def positive_roots(self): sage: W = CoxeterGroup(['A',3], implementation='reflection') sage: W.positive_roots() ((1, 0, 0), (1, 1, 0), (0, 1, 0), (1, 1, 1), (0, 1, 1), (0, 0, 1)) + + sage: # needs sage.rings.number_field sage: W = CoxeterGroup(['I',5], implementation='reflection') sage: W.positive_roots() ((1, 0), @@ -637,6 +650,8 @@ def roots(self): (-1, -1, -1), (0, -1, -1), (0, 0, -1)) + + sage: # needs sage.rings.number_field sage: W = CoxeterGroup(['I',5], implementation='reflection') sage: len(W.roots()) 10 @@ -677,7 +692,7 @@ def fundamental_weights(self): EXAMPLES:: sage: W = CoxeterGroup(['A',3], implementation='reflection') - sage: W.fundamental_weights() + sage: W.fundamental_weights() # needs sage.symbolic Finite family {1: (3/2, 1, 1/2), 2: (1, 2, 1), 3: (1/2, 1, 3/2)} """ simple_weights = self.bilinear_form().inverse() @@ -694,7 +709,7 @@ def fundamental_weight(self, i): EXAMPLES:: sage: W = CoxeterGroup(['A',3], implementation='reflection') - sage: W.fundamental_weight(1) + sage: W.fundamental_weight(1) # needs sage.symbolic (3/2, 1, 1/2) """ return self.fundamental_weights()[i] diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index 874b6b72d7b..d0ec214bb3b 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -6,10 +6,10 @@ EXAMPLES:: - sage: F = GF(3) # optional - sage.rings.finite_rings - sage: gens = [matrix(F, 2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens) # optional - sage.rings.finite_rings - sage: G.conjugacy_classes_representatives() # optional - sage.rings.finite_rings + sage: F = GF(3) + sage: gens = [matrix(F, 2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])] + sage: G = MatrixGroup(gens) + sage: G.conjugacy_classes_representatives() ( [1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2] [0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0] @@ -161,37 +161,37 @@ def QuaternionMatrixGroupGF3(): is the product of `I` and `J`. :: sage: from sage.groups.matrix_gps.finitely_generated import QuaternionMatrixGroupGF3 - sage: Q = QuaternionMatrixGroupGF3() # optional - sage.rings.finite_rings - sage: Q.order() # optional - sage.rings.finite_rings + sage: Q = QuaternionMatrixGroupGF3() + sage: Q.order() 8 - sage: aye = Q.gens()[0]; aye # optional - sage.rings.finite_rings + sage: aye = Q.gens()[0]; aye [1 1] [1 2] - sage: jay = Q.gens()[1]; jay # optional - sage.rings.finite_rings + sage: jay = Q.gens()[1]; jay [2 1] [1 1] - sage: kay = aye*jay; kay # optional - sage.rings.finite_rings + sage: kay = aye*jay; kay [0 2] [1 0] TESTS:: - sage: groups.matrix.QuaternionGF3() # optional - sage.rings.finite_rings + sage: groups.matrix.QuaternionGF3() # needs sage.modules sage.rings.finite_rings Matrix group over Finite Field of size 3 with 2 generators ( [1 1] [2 1] [1 2], [1 1] ) - sage: Q = QuaternionMatrixGroupGF3() # optional - sage.rings.finite_rings - sage: QP = Q.as_permutation_group() # optional - sage.rings.finite_rings - sage: QP.is_isomorphic(QuaternionGroup()) # optional - sage.rings.finite_rings + sage: Q = QuaternionMatrixGroupGF3() + sage: QP = Q.as_permutation_group() + sage: QP.is_isomorphic(QuaternionGroup()) True - sage: H = DihedralGroup(4) # optional - sage.groups sage.rings.finite_rings - sage: H.order() # optional - sage.groups sage.rings.finite_rings + sage: H = DihedralGroup(4) # needs sage.groups + sage: H.order() # needs sage.groups 8 - sage: QP.is_abelian(), H.is_abelian() # optional - sage.groups sage.rings.finite_rings + sage: QP.is_abelian(), H.is_abelian() # needs sage.groups (False, False) - sage: QP.is_isomorphic(H) # optional - sage.groups sage.rings.finite_rings + sage: QP.is_isomorphic(H) # needs sage.groups False """ from sage.rings.finite_rings.finite_field_constructor import FiniteField @@ -216,9 +216,9 @@ def MatrixGroup(*gens, **kwds): EXAMPLES:: - sage: F = GF(5) # optional - sage.rings.finite_rings - sage: gens = [matrix(F, 2, [1,2, -1,1]), matrix(F,2, [1,1, 0,1])] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens); G # optional - sage.rings.finite_rings + sage: F = GF(5) + sage: gens = [matrix(F, 2, [1,2, -1,1]), matrix(F,2, [1,1, 0,1])] + sage: G = MatrixGroup(gens); G Matrix group over Finite Field of size 5 with 2 generators ( [1 2] [1 1] [4 1], [0 1] @@ -230,8 +230,8 @@ def MatrixGroup(*gens, **kwds): matrices over the finite field, so creates that matrix group there:: - sage: gens = [matrix(2, [1,2, -1,1]), matrix(GF(7), 2, [1,1, 0,1]), 2] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens); G # optional - sage.rings.finite_rings + sage: gens = [matrix(2, [1,2, -1,1]), matrix(GF(7), 2, [1,1, 0,1]), 2] + sage: G = MatrixGroup(gens); G Matrix group over Finite Field of size 7 with 3 generators ( [1 2] [1 1] [2 0] [6 1], [0 1], [0 2] @@ -244,12 +244,12 @@ def MatrixGroup(*gens, **kwds): ... ValueError: each generator must be an invertible matrix - sage: F = GF(5); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: MatrixGroup([MS.0]) # optional - sage.rings.finite_rings + sage: F = GF(5); MS = MatrixSpace(F, 2, 2) + sage: MatrixGroup([MS.0]) Traceback (most recent call last): ... ValueError: each generator must be an invertible matrix - sage: MatrixGroup([MS.0], check=False) # works formally but is mathematical nonsense # optional - sage.rings.finite_rings + sage: MatrixGroup([MS.0], check=False) # works formally but is mathematical nonsense Matrix group over Finite Field of size 5 with 1 generators ( [1 0] [0 0] @@ -319,15 +319,16 @@ class FinitelyGeneratedMatrixGroup_generic(MatrixGroup_generic): """ TESTS:: - sage: m1 = matrix(SR, [[1,2], [3,4]]) # optional - sage.symbolic - sage: m2 = matrix(SR, [[1,3], [-1,0]]) # optional - sage.symbolic - sage: MatrixGroup(m1) == MatrixGroup(m1) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: m1 = matrix(SR, [[1,2], [3,4]]) + sage: m2 = matrix(SR, [[1,3], [-1,0]]) + sage: MatrixGroup(m1) == MatrixGroup(m1) True - sage: MatrixGroup(m1) == MatrixGroup(m1.change_ring(QQ)) # optional - sage.symbolic + sage: MatrixGroup(m1) == MatrixGroup(m1.change_ring(QQ)) False - sage: MatrixGroup(m1) == MatrixGroup(m2) # optional - sage.symbolic + sage: MatrixGroup(m1) == MatrixGroup(m2) False - sage: MatrixGroup(m1, m2) == MatrixGroup(m2, m1) # optional - sage.symbolic + sage: MatrixGroup(m1, m2) == MatrixGroup(m2, m1) False sage: m1 = matrix(QQ, [[1,2], [3,4]]) @@ -339,9 +340,9 @@ class FinitelyGeneratedMatrixGroup_generic(MatrixGroup_generic): sage: MatrixGroup(m1, m2) == MatrixGroup(m2, m1) False - sage: G = GL(2, GF(3)) # optional - sage.rings.finite_rings - sage: H = G.as_matrix_group() # optional - sage.rings.finite_rings - sage: H == G, G == H # optional - sage.rings.finite_rings + sage: G = GL(2, GF(3)) + sage: H = G.as_matrix_group() + sage: H == G, G == H (True, True) """ @@ -351,11 +352,12 @@ def __init__(self, degree, base_ring, generator_matrices, category=None): EXAMPLES:: - sage: m1 = matrix(SR, [[1,2], [3,4]]) # optional - sage.symbolic - sage: m2 = matrix(SR, [[1,3], [-1,0]]) # optional - sage.symbolic - sage: G = MatrixGroup(m1, m2) # optional - sage.symbolic - sage: TestSuite(G).run() # optional - sage.symbolic - sage: type(G) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: m1 = matrix(SR, [[1,2], [3,4]]) + sage: m2 = matrix(SR, [[1,3], [-1,0]]) + sage: G = MatrixGroup(m1, m2) + sage: TestSuite(G).run() + sage: type(G) sage: from sage.groups.matrix_gps.finitely_generated import \ @@ -377,24 +379,24 @@ def gens(self): EXAMPLES:: - sage: F = GF(3); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens) # optional - sage.rings.finite_rings - sage: gens[0] in G # optional - sage.rings.finite_rings + sage: F = GF(3); MS = MatrixSpace(F, 2, 2) + sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])] + sage: G = MatrixGroup(gens) + sage: gens[0] in G True - sage: gens = G.gens() # optional - sage.rings.finite_rings - sage: gens[0] in G # optional - sage.rings.finite_rings + sage: gens = G.gens() + sage: gens[0] in G True - sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])] # optional - sage.rings.finite_rings + sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])] - sage: F = GF(5); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: G = MatrixGroup([MS(1), MS([1,2, 3,4])]) # optional - sage.rings.finite_rings - sage: G # optional - sage.rings.finite_rings + sage: F = GF(5); MS = MatrixSpace(F, 2, 2) + sage: G = MatrixGroup([MS(1), MS([1,2, 3,4])]) + sage: G Matrix group over Finite Field of size 5 with 2 generators ( [1 0] [1 2] [0 1], [3 4] ) - sage: G.gens() # optional - sage.rings.finite_rings + sage: G.gens() ( [1 0] [1 2] [0 1], [3 4] @@ -413,13 +415,13 @@ def gen(self, i): EXAMPLES:: - sage: H = GL(2, GF(3)) # optional - sage.rings.finite_rings - sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]]) # optional - sage.rings.finite_rings - sage: G = H.subgroup([h1, h2]) # optional - sage.rings.finite_rings - sage: G.gen(0) # optional - sage.rings.finite_rings + sage: H = GL(2, GF(3)) + sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]]) + sage: G = H.subgroup([h1, h2]) + sage: G.gen(0) [1 0] [2 1] - sage: G.gen(0).matrix() == h1.matrix() # optional - sage.rings.finite_rings + sage: G.gen(0).matrix() == h1.matrix() True """ return self.gens()[i] @@ -434,10 +436,10 @@ def ngens(self): EXAMPLES:: - sage: H = GL(2, GF(3)) # optional - sage.rings.finite_rings - sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]]) # optional - sage.rings.finite_rings - sage: G = H.subgroup([h1, h2]) # optional - sage.rings.finite_rings - sage: G.ngens() # optional - sage.rings.finite_rings + sage: H = GL(2, GF(3)) + sage: h1, h2 = H([[1,0], [2,1]]), H([[1,1], [0,1]]) + sage: G = H.subgroup([h1, h2]) + sage: G.ngens() 2 """ return len(self._gens_matrix) @@ -455,10 +457,11 @@ def __reduce__(self): Check that :trac:`22128` is fixed:: - sage: R = MatrixSpace(SR, 2) # optional - sage.symbolic - sage: G = MatrixGroup([R([[1, 1], [0, 1]])]) # optional - sage.symbolic - sage: G.register_embedding(R) # optional - sage.symbolic - sage: loads(dumps(G)) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: R = MatrixSpace(SR, 2) + sage: G = MatrixGroup([R([[1, 1], [0, 1]])]) + sage: G.register_embedding(R) + sage: loads(dumps(G)) Matrix group over Symbolic Ring with 1 generators ( [1 1] [0 1] @@ -470,10 +473,11 @@ def _test_matrix_generators(self, **options): """ EXAMPLES:: - sage: m1 = matrix(SR, [[1,2], [3,4]]) # optional - sage.symbolic - sage: m2 = matrix(SR, [[1,3], [-1,0]]) # optional - sage.symbolic - sage: G = MatrixGroup(m1, m2) # optional - sage.symbolic - sage: G._test_matrix_generators() # optional - sage.symbolic + sage: # needs sage.symbolic + sage: m1 = matrix(SR, [[1,2], [3,4]]) + sage: m2 = matrix(SR, [[1,3], [-1,0]]) + sage: G = MatrixGroup(m1, m2) + sage: G._test_matrix_generators() """ tester = self._tester(**options) for g,h in zip(self.gens(), MatrixGroup(self.gens()).gens()): diff --git a/src/sage/groups/matrix_gps/finitely_generated_gap.py b/src/sage/groups/matrix_gps/finitely_generated_gap.py index a171742b60a..5864f64afd3 100644 --- a/src/sage/groups/matrix_gps/finitely_generated_gap.py +++ b/src/sage/groups/matrix_gps/finitely_generated_gap.py @@ -34,10 +34,8 @@ from sage.modules.free_module_element import vector from sage.rings.fraction_field import FractionField from sage.rings.integer_ring import ZZ -from sage.rings.number_field.number_field import CyclotomicField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.power_series_ring import PowerSeriesRing -from sage.rings.qqbar import QQbar from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence @@ -179,10 +177,11 @@ def as_permutation_group(self, algorithm=None, seed=None): Check that :trac:`25706` still works after :trac:`26903`:: + sage: # needs sage.libs.pari sage: MG = GU(3,2).as_matrix_group() sage: PG = MG.as_permutation_group() sage: mg = MG.an_element() - sage: PG(mg).order() # particular element depends on the set of GAP packages installed + sage: PG(mg).order() # particular element depends on the set of GAP packages installed 6 """ # Note that the output of IsomorphismPermGroup() depends on @@ -211,14 +210,14 @@ def module_composition_factors(self, algorithm=None): sage: F = GF(3); MS = MatrixSpace(F,4,4) sage: M = MS(0) - sage: M[0,1]=1;M[1,2]=1;M[2,3]=1;M[3,0]=1 + sage: M[0,1] = 1; M[1,2] = 1; M[2,3] = 1; M[3,0] = 1 sage: G = MatrixGroup([M]) sage: G.module_composition_factors() [(Finite Field of size 3, 1, True), (Finite Field of size 3, 1, True), (Finite Field of size 3, 2, True)] sage: F = GF(7); MS = MatrixSpace(F,2,2) - sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])] + sage: gens = [MS([[0,1],[-1,0]]), MS([[1,1],[2,3]])] sage: G = MatrixGroup(gens) sage: G.module_composition_factors() [(Finite Field of size 7, 2, True)] @@ -272,20 +271,22 @@ def invariant_generators(self): sage: F = GF(7); MS = MatrixSpace(F,2,2) sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])] sage: G = MatrixGroup(gens) - sage: G.invariant_generators() + sage: G.invariant_generators() # needs sage.libs.singular [x1^7*x2 - x1*x2^7, x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12, x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18] sage: q = 4; a = 2 sage: MS = MatrixSpace(QQ, 2, 2) - sage: gen1 = [[1/a,(q-1)/a],[1/a, -1/a]]; gen2 = [[1,0],[0,-1]]; gen3 = [[-1,0],[0,1]] - sage: G = MatrixGroup([MS(gen1),MS(gen2),MS(gen3)]) + sage: gen1 = [[1/a, (q-1)/a], [1/a, -1/a]] + sage: gen2 = [[1,0], [0,-1]]; gen3 = [[-1,0], [0,1]] + sage: G = MatrixGroup([MS(gen1), MS(gen2), MS(gen3)]) sage: G.cardinality() 12 - sage: G.invariant_generators() + sage: G.invariant_generators() # needs sage.libs.singular [x1^2 + 3*x2^2, x1^6 + 15*x1^4*x2^2 + 15*x1^2*x2^4 + 33*x2^6] + sage: # needs sage.rings.number_field sage: F = CyclotomicField(8) sage: z = F.gen() sage: a = z+1/z @@ -294,7 +295,7 @@ def invariant_generators(self): sage: g1 = MS([[1/a, 1/a], [1/a, -1/a]]) sage: g2 = MS([[-b, 0], [0, b]]) sage: G = MatrixGroup([g1,g2]) - sage: G.invariant_generators() + sage: G.invariant_generators() # needs sage.libs.singular [x1^4 + 2*x1^2*x2^2 + x2^4, x1^5*x2 - x1*x2^5, x1^8 + 28/9*x1^6*x2^2 + 70/9*x1^4*x2^4 + 28/9*x1^2*x2^6 + x2^8] @@ -442,13 +443,14 @@ def molien_series(self, chi=None, return_series=True, prec=20, variable='t'): Traceback (most recent call last): ... NotImplementedError: only implemented for finite groups - sage: MatrixGroup(matrix(GF(3),2,2,[1,1,0,1])).molien_series() + sage: MatrixGroup(matrix(GF(3),2,2,[1,1,0,1])).molien_series() # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: characteristic cannot divide group order Tetrahedral Group:: + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(4) sage: Tetra = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0]) sage: Tetra.molien_series(prec=30) @@ -466,12 +468,12 @@ def molien_series(self, chi=None, return_series=True, prec=20, variable='t'): :: + sage: # needs sage.groups sage.rings.number_field sage: S3 = MatrixGroup(SymmetricGroup(3)) sage: mol = S3.molien_series(prec=10); mol 1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 10*t^8 + 12*t^9 + O(t^10) sage: mol.parent() Power Series Ring in t over Integer Ring - sage: mol = S3.molien_series(prec=oo); mol 1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + O(t^7) sage: mol.parent() @@ -479,28 +481,32 @@ def molien_series(self, chi=None, return_series=True, prec=20, variable='t'): Octahedral Group:: + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(8) - sage: a = v-v^3 #sqrt(2) + sage: a = v - v^3 # sqrt(2) sage: i = v^2 - sage: Octa = MatrixGroup([(-1+i)/2, (-1+i)/2, (1+i)/2, (-1-i)/2], + sage: Octa = MatrixGroup([(-1+i)/2, (-1+i)/2, (1+i)/2, (-1-i)/2], # needs sage.symbolic ....: [(1+i)/a, 0, 0, (1-i)/a]) - sage: Octa.molien_series(prec=30) + sage: Octa.molien_series(prec=30) # needs sage.symbolic 1 + t^8 + t^12 + t^16 + t^18 + t^20 + 2*t^24 + t^26 + t^28 + O(t^30) Icosahedral Group:: + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(10) sage: z5 = v^2 sage: i = z5^5 - sage: a = 2*z5^3 + 2*z5^2 + 1 #sqrt(5) + sage: a = 2*z5^3 + 2*z5^2 + 1 #sqrt(5) sage: Ico = MatrixGroup([[z5^3,0, 0,z5^2], ....: [0,1, -1,0], - ....: [(z5^4-z5)/a, (z5^2-z5^3)/a, (z5^2-z5^3)/a, -(z5^4-z5)/a]]) + ....: [(z5^4-z5)/a, (z5^2-z5^3)/a, + ....: (z5^2-z5^3)/a, -(z5^4-z5)/a]]) sage: Ico.molien_series(prec=40) 1 + t^12 + t^20 + t^24 + t^30 + t^32 + t^36 + O(t^40) :: + sage: # needs sage.groups sage.rings.number_field sage: G = MatrixGroup(CyclicPermutationGroup(3)) sage: chi = G.character(G.character_table()[1]) sage: G.molien_series(chi, prec=10) @@ -509,15 +515,18 @@ def molien_series(self, chi=None, return_series=True, prec=20, variable='t'): :: + sage: # needs sage.groups sage.rings.number_field sage: K = GF(5) sage: S = MatrixGroup(SymmetricGroup(4)) - sage: G = MatrixGroup([matrix(K, 4, 4, [K(y) for u in m.list() for y in u]) + sage: G = MatrixGroup([matrix(K, 4, 4, + ....: [K(y) for u in m.list() for y in u]) ....: for m in S.gens()]) sage: G.molien_series(return_series=False) 1/(t^10 - t^9 - t^8 + 2*t^5 - t^2 - t + 1) :: + sage: # needs sage.rings.number_field sage: i = GF(7)(3) sage: G = MatrixGroup([[i^3,0, 0,-i^3], [i^2,0, 0,-i^2]]) sage: chi = G.character(G.character_table()[4]) @@ -554,6 +563,7 @@ def molien_series(self, chi=None, return_series=True, prec=20, variable='t'): w = F.roots(ring=R.algebraic_closure(), multiplicities=False)[0] # don't need to extend further in this case since the order of # the roots of unity in the character divide the order of the group + from sage.rings.number_field.number_field import CyclotomicField L = CyclotomicField(N, 'v') v = L.gen() # construct Molien series @@ -627,11 +637,12 @@ def reynolds_operator(self, poly, chi=None): sage: S3 = MatrixGroup(SymmetricGroup(3)) sage: R. = QQ[] sage: f = x*y*z^3 - sage: S3.reynolds_operator(f) + sage: S3.reynolds_operator(f) # needs sage.rings.number_field 1/3*x^3*y*z + 1/3*x*y^3*z + 1/3*x*y*z^3 :: + sage: # needs sage.groups sage.rings.number_field sage: G = MatrixGroup(CyclicPermutationGroup(4)) sage: chi = G.character(G.character_table()[3]) sage: K. = CyclotomicField(4) @@ -645,6 +656,7 @@ def reynolds_operator(self, poly, chi=None): :: + sage: # needs sage.groups sage.rings.number_field sage: K. = CyclotomicField(4) sage: G = MatrixGroup(CyclicPermutationGroup(3)) sage: chi = G.character(G.character_table()[1]) @@ -659,6 +671,7 @@ def reynolds_operator(self, poly, chi=None): :: + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(4) sage: Tetra = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0]) sage: chi = Tetra.character(Tetra.character_table()[4]) @@ -678,6 +691,7 @@ def reynolds_operator(self, poly, chi=None): :: + sage: # needs sage.groups sage.rings.number_field sage: G = MatrixGroup(DihedralGroup(4)) sage: chi = G.character(G.character_table()[1]) sage: R. = QQ[] @@ -705,10 +719,10 @@ def reynolds_operator(self, poly, chi=None): sage: i = GF(7)(3) sage: G = MatrixGroup([[i^3,0, 0,-i^3], [i^2,0, 0,-i^2]]) - sage: chi = G.character(G.character_table()[4]) + sage: chi = G.character(G.character_table()[4]) # needs sage.rings.number_field sage: R. = GF(7)[] sage: f = w^5*x + x^6 - sage: G.reynolds_operator(f, chi) + sage: G.reynolds_operator(f, chi) # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: nontrivial characters not implemented for characteristic > 0 @@ -717,6 +731,7 @@ def reynolds_operator(self, poly, chi=None): :: + sage: # needs sage.rings.finite_rings sage: K = GF(3^2,'t') sage: G = MatrixGroup([matrix(K, 2, 2, [0,K.gen(), 1,0])]) sage: R. = GF(3)[] @@ -725,6 +740,7 @@ def reynolds_operator(self, poly, chi=None): :: + sage: # needs sage.rings.finite_rings sage: K = GF(3^2,'t') sage: G = MatrixGroup([matrix(GF(3), 2, 2, [0,1, 1,0])]) sage: R. = K[] @@ -738,6 +754,7 @@ def reynolds_operator(self, poly, chi=None): C = FractionField(self.base_ring()) if chi is None: # then this is the trivial character if R.characteristic() == 0: + from sage.rings.qqbar import QQbar # non-modular case if C == QQbar or R == QQbar: L = QQbar @@ -770,6 +787,7 @@ def reynolds_operator(self, poly, chi=None): # non-trivial character case K = chi.values()[0].parent() if R.characteristic() == 0: + from sage.rings.qqbar import QQbar # extend base_ring to compositum if C == QQbar or K == QQbar or R == QQbar: L = QQbar @@ -831,6 +849,7 @@ def invariants_of_degree(self, deg, chi=None, R=None): EXAMPLES:: + sage: # needs sage.groups sage.rings.number_field sage: Gr = MatrixGroup(SymmetricGroup(2)) sage: sorted(Gr.invariants_of_degree(3)) [x0^2*x1 + x0*x1^2, x0^3 + x1^3] @@ -840,6 +859,7 @@ def invariants_of_degree(self, deg, chi=None, R=None): :: + sage: # needs sage.groups sage.rings.number_field sage: R. = QQ[] sage: Gr = MatrixGroup(DihedralGroup(3)) sage: ct = Gr.character_table() @@ -852,11 +872,12 @@ def invariants_of_degree(self, deg, chi=None, R=None): sage: i = GF(7)(3) sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]]) - sage: G.invariants_of_degree(25) + sage: G.invariants_of_degree(25) # needs sage.rings.number_field [] :: + sage: # needs sage.groups sage: G = MatrixGroup(SymmetricGroup(5)) sage: R = QQ['x,y'] sage: G.invariants_of_degree(3, R=R) @@ -866,6 +887,7 @@ def invariants_of_degree(self, deg, chi=None, R=None): :: + sage: # needs sage.groups sage.rings.number_field sage: K. = CyclotomicField(4) sage: G = MatrixGroup(CyclicPermutationGroup(3)) sage: chi = G.character(G.character_table()[1]) @@ -878,6 +900,7 @@ def invariants_of_degree(self, deg, chi=None, R=None): :: + sage: # needs sage.groups sage.rings.number_field sage: S3 = MatrixGroup(SymmetricGroup(3)) sage: chi = S3.character(S3.character_table()[0]) sage: sorted(S3.invariants_of_degree(5, chi=chi)) @@ -907,13 +930,14 @@ def invariants_of_degree(self, deg, chi=None, R=None): def _new_invariant_is_linearly_independent(F, invariants): """ - EXAMPLES :: + EXAMPLES:: + sage: gens = [matrix(QQ, [[-1,1],[-1,0]]), matrix(QQ, [[0,1],[1,0]])] sage: G = MatrixGroup(gens) - sage: s = Sequence(G.invariants_of_degree(14)) - sage: s.coefficient_matrix()[0].rank() + sage: s = Sequence(G.invariants_of_degree(14)) # needs sage.rings.number_field + sage: s.coefficient_matrix()[0].rank() # needs sage.rings.number_field 3 - sage: len(s) + sage: len(s) # needs sage.rings.number_field 3 """ if len(invariants)==0: diff --git a/src/sage/groups/matrix_gps/group_element.pyx b/src/sage/groups/matrix_gps/group_element.pyx index 4e57798b384..2764e33a7a8 100644 --- a/src/sage/groups/matrix_gps/group_element.pyx +++ b/src/sage/groups/matrix_gps/group_element.pyx @@ -3,15 +3,15 @@ Matrix Group Elements EXAMPLES:: - sage: F = GF(3); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens); G # optional - sage.rings.finite_rings + sage: F = GF(3); MS = MatrixSpace(F, 2, 2) + sage: gens = [MS([[1,0], [0,1]]), MS([[1,1], [0,1]])] + sage: G = MatrixGroup(gens); G Matrix group over Finite Field of size 3 with 2 generators ( [1 0] [1 1] [0 1], [0 1] ) - sage: g = G([[1,1], [0,1]]) # optional - sage.rings.finite_rings - sage: h = G([[1,2], [0,1]]) # optional - sage.rings.finite_rings - sage: g*h # optional - sage.rings.finite_rings + sage: g = G([[1,1], [0,1]]) + sage: h = G([[1,2], [0,1]]) + sage: g*h [1 0] [0 1] @@ -19,7 +19,7 @@ You cannot add two matrices, since this is not a group operation. You can coerce matrices back to the matrix space and add them there:: - sage: g + h # optional - sage.rings.finite_rings + sage: g + h Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for +: @@ -32,14 +32,14 @@ there:: [0 1], [0 1] )' - sage: g.matrix() + h.matrix() # optional - sage.rings.finite_rings + sage: g.matrix() + h.matrix() [2 0] [0 2] Similarly, you cannot multiply group elements by scalars but you can do it with the underlying matrices:: - sage: 2*g # optional - sage.rings.finite_rings + sage: 2*g Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: 'Integer Ring' @@ -105,8 +105,8 @@ cpdef is_MatrixGroupElement(x): sage: is_MatrixGroupElement('helloooo') False - sage: G = GL(2,3) # optional - sage.rings.finite_rings - sage: is_MatrixGroupElement(G.an_element()) # optional - sage.rings.finite_rings + sage: G = GL(2,3) + sage: is_MatrixGroupElement(G.an_element()) True """ return isinstance(x, (MatrixGroupElement_generic, MatrixGroupElement_gap)) @@ -137,8 +137,8 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element(); g # optional - sage.combinat + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # needs sage.graphs + sage: g = W.an_element(); g # needs sage.graphs [ 0 0 -1] [ 1 0 -1] [ 0 1 -1] @@ -149,9 +149,9 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): TESTS:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element() # optional - sage.combinat - sage: TestSuite(g).run() # optional - sage.combinat + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # needs sage.graphs + sage: g = W.an_element() # needs sage.graphs + sage: TestSuite(g).run() # needs sage.graphs """ if convert: M = parent.matrix_space()(M) @@ -172,9 +172,9 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): r""" TESTS:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element() # optional - sage.combinat - sage: hash(g) # optional - sage.combinat + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # needs sage.graphs + sage: g = W.an_element() # needs sage.graphs + sage: hash(g) # needs sage.graphs 660522311176098153 # 64-bit -606138007 # 32-bit """ @@ -186,9 +186,9 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): TESTS:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element() # optional - sage.combinat - sage: loads(g.dumps()) == g # optional - sage.combinat + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # needs sage.graphs + sage: g = W.an_element() # needs sage.graphs + sage: loads(g.dumps()) == g # needs sage.graphs True """ return (_unpickle_generic_element, (self.parent(), self._matrix,)) @@ -199,8 +199,8 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: W.an_element() # optional - sage.combinat + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # needs sage.graphs + sage: W.an_element() # needs sage.graphs [ 0 0 -1] [ 1 0 -1] [ 0 1 -1] @@ -211,9 +211,9 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): r""" EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element() # optional - sage.combinat - sage: latex(g) # optional - sage.combinat + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # needs sage.graphs + sage: g = W.an_element() # needs sage.graphs + sage: latex(g) # needs sage.graphs \left(\begin{array}{rrr} 0 & 0 & -1 \\ 1 & 0 & -1 \\ @@ -226,13 +226,14 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): """ EXAMPLES:: - sage: W = CoxeterGroup(['A',4], base_ring=ZZ) # optional - sage.combinat - sage: g = W.gen(0) # optional - sage.combinat - sage: g * vector([1,1,1,1]) # optional - sage.combinat + sage: # needs sage.combinat sage.libs.gap + sage: W = CoxeterGroup(['A',4], base_ring=ZZ) + sage: g = W.gen(0) + sage: g * vector([1,1,1,1]) (0, 1, 1, 1) - sage: v = vector([3,2,1,-1]) # optional - sage.combinat - sage: g = W.gen(1) # optional - sage.combinat - sage: v * g == v * g.matrix() # indirect doctest # optional - sage.combinat + sage: v = vector([3,2,1,-1]) + sage: g = W.gen(1) + sage: v * g == v * g.matrix() # indirect doctest True """ if not is_MatrixGroupElement(x) and x not in self.parent().base_ring(): @@ -248,16 +249,17 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): """ EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element() # optional - sage.combinat - sage: TestSuite(g).run() # optional - sage.combinat - sage: h = W.gen(0) * W.gen(1) * W.gen(2) # optional - sage.combinat - sage: g == h # optional - sage.combinat + sage: # needs sage.combinat sage.libs.gap + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) + sage: g = W.an_element() + sage: TestSuite(g).run() + sage: h = W.gen(0) * W.gen(1) * W.gen(2) + sage: g == h True - sage: a = W.gen(0) # optional - sage.combinat - sage: a == g # optional - sage.combinat + sage: a = W.gen(0) + sage: a == g False - sage: a != g # optional - sage.combinat + sage: a != g True """ cdef MatrixGroupElement_generic x = self @@ -270,13 +272,14 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.gen(0) # optional - sage.combinat - sage: g # optional - sage.combinat + sage: # needs sage.combinat sage.libs.gap + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) + sage: g = W.gen(0) + sage: g [-1 1 0] [ 0 1 0] [ 0 0 1] - sage: g.list() # optional - sage.combinat + sage: g.list() [[-1, 1, 0], [0, 1, 0], [0, 0, 1]] """ return [r.list() for r in self._matrix.rows()] @@ -291,19 +294,20 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.gen(0) # optional - sage.combinat - sage: g.matrix() # optional - sage.combinat + sage: # needs sage.combinat sage.libs.gap + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) + sage: g = W.gen(0) + sage: g.matrix() [-1 1 0] [ 0 1 0] [ 0 0 1] - sage: parent(g.matrix()) # optional - sage.combinat + sage: parent(g.matrix()) Full MatrixSpace of 3 by 3 dense matrices over Integer Ring Matrices have extra functionality that matrix group elements do not have:: - sage: g.matrix().charpoly('t') # optional - sage.combinat + sage: g.matrix().charpoly('t') # needs sage.combinat sage.libs.gap t^3 - t^2 - t + 1 """ return self._matrix @@ -314,9 +318,9 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A', 3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.gen(0) # optional - sage.combinat - sage: matrix(RDF, g) # optional - sage.combinat + sage: W = CoxeterGroup(['A', 3], base_ring=ZZ) # needs sage.graphs + sage: g = W.gen(0) # needs sage.graphs + sage: matrix(RDF, g) # needs sage.graphs [-1.0 1.0 0.0] [ 0.0 1.0 0.0] [ 0.0 0.0 1.0] @@ -330,10 +334,11 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.gen(0) # optional - sage.combinat - sage: h = W.an_element() # optional - sage.combinat - sage: g * h # optional - sage.combinat + sage: # needs sage.combinat sage.libs.gap + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) + sage: g = W.gen(0) + sage: h = W.an_element() + sage: g * h [ 1 0 0] [ 1 0 -1] [ 0 1 -1] @@ -351,14 +356,14 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3]) # optional - sage.combinat - sage: g = W.gen(0) # optional - sage.combinat - sage: g.is_one() # optional - sage.combinat + sage: # needs sage.graphs + sage: W = CoxeterGroup(['A',3]) + sage: g = W.gen(0) + sage: g.is_one() False - - sage: W.an_element().is_one() # optional - sage.combinat + sage: W.an_element().is_one() False - sage: W.one().is_one() # optional - sage.combinat + sage: W.one().is_one() True """ return self._matrix.is_one() @@ -371,22 +376,24 @@ cdef class MatrixGroupElement_generic(MultiplicativeGroupElement): EXAMPLES:: - sage: W = CoxeterGroup(['A',3], base_ring=ZZ) # optional - sage.combinat - sage: g = W.an_element() # optional - sage.combinat - sage: ~g # optional - sage.combinat + sage: # needs sage.combinat sage.libs.gap + sage: W = CoxeterGroup(['A',3], base_ring=ZZ) + sage: g = W.an_element() + sage: ~g [-1 1 0] [-1 0 1] [-1 0 0] - sage: g * ~g == W.one() # optional - sage.combinat + sage: g * ~g == W.one() True - sage: ~g * g == W.one() # optional - sage.combinat + sage: ~g * g == W.one() True - sage: W = CoxeterGroup(['B',3]) # optional - sage.combinat sage.rings.number_field - sage: W.base_ring() # optional - sage.combinat sage.rings.number_field + sage: # needs sage.combinat sage.libs.gap sage.rings.number_field + sage: W = CoxeterGroup(['B',3]) + sage: W.base_ring() Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? - sage: g = W.an_element() # optional - sage.combinat sage.rings.number_field - sage: ~g # optional - sage.combinat sage.rings.number_field + sage: g = W.an_element() + sage: ~g [-1 1 0] [-1 0 a] [-a 0 1] @@ -413,12 +420,13 @@ def _unpickle_generic_element(G, mat): EXAMPLES:: - sage: m1 = matrix(SR, [[1,2], [3,4]]) # optional - sage.symbolic - sage: m2 = matrix(SR, [[1,3], [-1,0]]) # optional - sage.symbolic - sage: G = MatrixGroup(m1, m2) # optional - sage.symbolic - sage: m = G.an_element() # optional - sage.symbolic - sage: from sage.groups.matrix_gps.group_element import _unpickle_generic_element # optional - sage.symbolic - sage: _unpickle_generic_element(G, m.matrix()) == m # optional - sage.symbolic + sage: # needs sage.symbolic + sage: m1 = matrix(SR, [[1,2], [3,4]]) + sage: m2 = matrix(SR, [[1,3], [-1,0]]) + sage: G = MatrixGroup(m1, m2) + sage: m = G.an_element() + sage: from sage.groups.matrix_gps.group_element import _unpickle_generic_element + sage: _unpickle_generic_element(G, m.matrix()) == m True """ return G.element_class(G, mat, False, False) diff --git a/src/sage/groups/matrix_gps/group_element_gap.pyx b/src/sage/groups/matrix_gps/group_element_gap.pyx index c26ddebde71..b07c0f01a44 100644 --- a/src/sage/groups/matrix_gps/group_element_gap.pyx +++ b/src/sage/groups/matrix_gps/group_element_gap.pyx @@ -223,7 +223,7 @@ cdef class MatrixGroupElement_gap(ElementLibGAP): sage: F = GF(3); MS = MatrixSpace(F,2,2) sage: G = MatrixGroup([MS([1,1,0,1])]) sage: g = G.gen(0) - sage: M = matrix(GF(9), g); M; parent(M) + sage: M = matrix(GF(9), g); M; parent(M) # needs sage.rings.finite_rings [1 1] [0 1] Full MatrixSpace of 2 by 2 dense matrices over Finite Field in z2 of size 3^2 diff --git a/src/sage/groups/matrix_gps/heisenberg.py b/src/sage/groups/matrix_gps/heisenberg.py index 17705a55cde..8a262ddf1c7 100644 --- a/src/sage/groups/matrix_gps/heisenberg.py +++ b/src/sage/groups/matrix_gps/heisenberg.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap sage.modules """ Heisenberg Group diff --git a/src/sage/groups/matrix_gps/isometries.py b/src/sage/groups/matrix_gps/isometries.py index 3810a80cadc..cbc88ccb184 100644 --- a/src/sage/groups/matrix_gps/isometries.py +++ b/src/sage/groups/matrix_gps/isometries.py @@ -8,9 +8,8 @@ EXAMPLES:: - sage: L = IntegralLattice("D4") - sage: O = L.orthogonal_group() - sage: O + sage: L = IntegralLattice("D4") # needs sage.graphs + sage: O = L.orthogonal_group(); O # needs sage.graphs Group of isometries with 3 generators ( [0 0 0 1] [ 1 1 0 0] [ 1 0 0 0] [0 1 0 0] [ 0 0 1 0] [-1 -1 -1 -1] @@ -20,9 +19,9 @@ Basic functionality is provided by GAP:: - sage: O.cardinality() + sage: O.cardinality() # needs sage.graphs 1152 - sage: len(O.conjugacy_classes_representatives()) + sage: len(O.conjugacy_classes_representatives()) # needs sage.graphs 25 AUTHORS: diff --git a/src/sage/groups/matrix_gps/linear.py b/src/sage/groups/matrix_gps/linear.py index 8dc29267923..d13904dec51 100644 --- a/src/sage/groups/matrix_gps/linear.py +++ b/src/sage/groups/matrix_gps/linear.py @@ -9,22 +9,22 @@ General Linear Group of degree 1 over Integer Ring sage: GL(100, RR) General Linear Group of degree 100 over Real Field with 53 bits of precision - sage: GL(3, GF(49,'a')) # optional - sage.rings.finite_rings + sage: GL(3, GF(49,'a')) # needs sage.rings.finite_rings General Linear Group of degree 3 over Finite Field in a of size 7^2 sage: SL(2, ZZ) Special Linear Group of degree 2 over Integer Ring - sage: G = SL(2, GF(3)); G # optional - sage.rings.finite_rings + sage: G = SL(2, GF(3)); G Special Linear Group of degree 2 over Finite Field of size 3 - sage: G.is_finite() # optional - sage.rings.finite_rings + sage: G.is_finite() True - sage: G.conjugacy_classes_representatives() # optional - sage.rings.finite_rings + sage: G.conjugacy_classes_representatives() ( [1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2] [0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0] ) - sage: G = SL(6, GF(5)) # optional - sage.rings.finite_rings - sage: G.gens() # optional - sage.rings.finite_rings + sage: G = SL(6, GF(5)) + sage: G.gens() ( [2 0 0 0 0 0] [4 0 0 0 0 1] [0 3 0 0 0 0] [4 0 0 0 0 0] @@ -93,14 +93,14 @@ def GL(n, R, var='a'): EXAMPLES:: - sage: G = GL(6, GF(5)) # optional - sage.rings.finite_rings - sage: G.order() # optional - sage.rings.finite_rings + sage: G = GL(6, GF(5)) + sage: G.order() 11064475422000000000000000 - sage: G.base_ring() # optional - sage.rings.finite_rings + sage: G.base_ring() Finite Field of size 5 - sage: G.category() # optional - sage.rings.finite_rings + sage: G.category() Category of finite groups - sage: TestSuite(G).run() # optional - sage.rings.finite_rings + sage: TestSuite(G).run() sage: G = GL(6, QQ) sage: G.category() @@ -109,34 +109,34 @@ def GL(n, R, var='a'): Here is the Cayley graph of (relatively small) finite General Linear Group:: - sage: g = GL(2,3) # optional - sage.rings.finite_rings - sage: d = g.cayley_graph(); d # optional - sage.graphs sage.rings.finite_rings + sage: g = GL(2,3) + sage: d = g.cayley_graph(); d # needs sage.graphs Digraph on 48 vertices - sage: d.plot(color_by_label=True, vertex_size=0.03, # long time # optional - sage.graphs sage.rings.finite_rings sage.plot + sage: d.plot(color_by_label=True, vertex_size=0.03, # long time # needs sage.graphs sage.plot ....: vertex_labels=False) Graphics object consisting of 144 graphics primitives - sage: d.plot3d(color_by_label=True) # long time # optional - sage.graphs sage.rings.finite_rings sage.plot + sage: d.plot3d(color_by_label=True) # long time # needs sage.graphs sage.plot Graphics3d Object :: - sage: F = GF(3); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: gens = [MS([[2,0], [0,1]]), MS([[2,1], [2,0]])] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens) # optional - sage.rings.finite_rings - sage: G.order() # optional - sage.rings.finite_rings + sage: F = GF(3); MS = MatrixSpace(F, 2, 2) + sage: gens = [MS([[2,0], [0,1]]), MS([[2,1], [2,0]])] + sage: G = MatrixGroup(gens) + sage: G.order() 48 - sage: G.cardinality() # optional - sage.rings.finite_rings + sage: G.cardinality() 48 - sage: H = GL(2,F) # optional - sage.rings.finite_rings - sage: H.order() # optional - sage.rings.finite_rings + sage: H = GL(2,F) + sage: H.order() 48 - sage: H == G # optional - sage.rings.finite_rings + sage: H == G True - sage: H.gens() == G.gens() # optional - sage.rings.finite_rings + sage: H.gens() == G.gens() True - sage: H.as_matrix_group() == H # optional - sage.rings.finite_rings + sage: H.as_matrix_group() == H True - sage: H.gens() # optional - sage.rings.finite_rings + sage: H.gens() ( [2 0] [2 1] [0 1], [2 0] @@ -144,11 +144,11 @@ def GL(n, R, var='a'): TESTS:: - sage: groups.matrix.GL(2, 3) # optional - sage.groups sage.rings.finite_rings + sage: groups.matrix.GL(2, 3) General Linear Group of degree 2 over Finite Field of size 3 - sage: groups.matrix.GL(1, ZZ).category() # optional - sage.groups + sage: groups.matrix.GL(1, ZZ).category() Category of groups - sage: groups.matrix.GL(1, QQ).category() # optional - sage.groups + sage: groups.matrix.GL(1, QQ).category() Category of infinite groups """ degree, ring = normalize_args_vectorspace(n, R, var='a') @@ -207,15 +207,15 @@ def SL(n, R, var='a'): EXAMPLES:: - sage: SL(3, GF(2)) # optional - sage.rings.finite_rings + sage: SL(3, GF(2)) Special Linear Group of degree 3 over Finite Field of size 2 - sage: G = SL(15, GF(7)); G # optional - sage.rings.finite_rings + sage: G = SL(15, GF(7)); G Special Linear Group of degree 15 over Finite Field of size 7 - sage: G.category() # optional - sage.rings.finite_rings + sage: G.category() Category of finite groups - sage: G.order() # optional - sage.rings.finite_rings + sage: G.order() 1956712595698146962015219062429586341124018007182049478916067369638713066737882363393519966343657677430907011270206265834819092046250232049187967718149558134226774650845658791865745408000000 - sage: len(G.gens()) # optional - sage.rings.finite_rings + sage: len(G.gens()) 2 sage: G = SL(2, ZZ); G Special Linear Group of degree 2 over Integer Ring @@ -285,8 +285,8 @@ def _check_matrix(self, x, *args): EXAMPLES:: - sage: G = SL(2, GF(5)) # optional - sage.rings.finite_rings - sage: G._check_matrix(G.an_element().matrix()) # optional - sage.rings.finite_rings + sage: G = SL(2, GF(5)) + sage: G._check_matrix(G.an_element().matrix()) """ if self._special: if x.determinant() != 1: diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index 526c86695b0..c0c22456320 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -5,14 +5,14 @@ Loading, saving, ... works:: - sage: G = GL(2,5); G # optional - sage.rings.finite_rings + sage: G = GL(2,5); G General Linear Group of degree 2 over Finite Field of size 5 - sage: TestSuite(G).run() # optional - sage.rings.finite_rings + sage: TestSuite(G).run() - sage: g = G.1; g # optional - sage.rings.finite_rings + sage: g = G.1; g [4 1] [4 0] - sage: TestSuite(g).run() # optional - sage.rings.finite_rings + sage: TestSuite(g).run() We test that :trac:`9437` is fixed:: @@ -107,9 +107,9 @@ class MatrixGroup_base(Group): TESTS:: - sage: G = SO(3, GF(11)); G # optional - sage.rings.finite_rings + sage: G = SO(3, GF(11)); G Special Orthogonal Group of degree 3 over Finite Field of size 11 - sage: G.category() # optional - sage.rings.finite_rings + sage: G.category() Category of finite groups """ _ambient = None # internal attribute to register the ambient group in case this instance is a subgroup @@ -137,9 +137,9 @@ def _check_matrix(self, x, *args): EXAMPLES:: - sage: G = SU(2, GF(5)); F = G.base_ring() # this is GF(5^2,'a') # optional - sage.rings.finite_rings - sage: G._check_matrix(identity_matrix(F, 2)) # optional - sage.rings.finite_rings - sage: G._check_matrix(matrix(F, [[1,1], [0,1]])) # optional - sage.rings.finite_rings + sage: G = SU(2, GF(5)); F = G.base_ring() # this is GF(5^2,'a') # needs sage.rings.finite_rings + sage: G._check_matrix(identity_matrix(F, 2)) # needs sage.rings.finite_rings + sage: G._check_matrix(matrix(F, [[1,1], [0,1]])) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: matrix must be unitary with respect to the hermitian form @@ -158,8 +158,8 @@ def as_matrix_group(self): EXAMPLES:: - sage: G = SU(4, GF(5)) # optional - sage.rings.finite_rings - sage: G.as_matrix_group() # optional - sage.rings.finite_rings + sage: G = SU(4, GF(5)) # needs sage.rings.finite_rings + sage: G.as_matrix_group() # needs sage.rings.finite_rings Matrix group over Finite Field in a of size 5^2 with 2 generators ( [ a 0 0 0] [ 1 0 4*a + 3 0] [ 0 2*a + 3 0 0] [ 1 0 0 0] @@ -167,8 +167,8 @@ def as_matrix_group(self): [ 0 0 0 3*a], [ 0 3*a + 1 0 0] ) - sage: G = GO(3,GF(5)) # optional - sage.rings.finite_rings - sage: G.as_matrix_group() # optional - sage.rings.finite_rings + sage: G = GO(3,GF(5)) + sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 2 generators ( [2 0 0] [0 1 0] [0 3 0] [1 4 4] @@ -191,22 +191,24 @@ def subgroup(self, generators, check=True): EXAMPLES:: - sage: UCF = UniversalCyclotomicField() # optional - sage.rings.number_field - sage: G = GL(3, UCF) # optional - sage.rings.number_field - sage: e3 = UCF.gen(3); e5 = UCF.gen(5) # optional - sage.rings.number_field - sage: m = matrix(UCF, 3,3, [[e3, 1, 0], [0, e5, 7],[4, 3, 2]]) # optional - sage.rings.number_field - sage: S = G.subgroup([m]); S # optional - sage.rings.number_field + sage: # needs sage.libs.gap sage.rings.number_field + sage: UCF = UniversalCyclotomicField() + sage: G = GL(3, UCF) + sage: e3 = UCF.gen(3); e5 = UCF.gen(5) + sage: m = matrix(UCF, 3,3, [[e3, 1, 0], [0, e5, 7],[4, 3, 2]]) + sage: S = G.subgroup([m]); S Subgroup with 1 generators ( [E(3) 1 0] [ 0 E(5) 7] [ 4 3 2] ) of General Linear Group of degree 3 over Universal Cyclotomic Field - sage: CF3 = CyclotomicField(3) # optional - sage.rings.number_field - sage: G = GL(3, CF3) # optional - sage.rings.number_field - sage: e3 = CF3.gen() # optional - sage.rings.number_field - sage: m = matrix(CF3, 3,3, [[e3, 1, 0], [0, ~e3, 7],[4, 3, 2]]) # optional - sage.rings.number_field - sage: S = G.subgroup([m]); S # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: CF3 = CyclotomicField(3) + sage: G = GL(3, CF3) + sage: e3 = CF3.gen() + sage: m = matrix(CF3, 3,3, [[e3, 1, 0], [0, ~e3, 7],[4, 3, 2]]) + sage: S = G.subgroup([m]); S Subgroup with 1 generators ( [ zeta3 1 0] [ 0 -zeta3 - 1 7] @@ -215,8 +217,8 @@ def subgroup(self, generators, check=True): TESTS:: - sage: TestSuite(G).run() # optional - sage.rings.number_field - sage: TestSuite(S).run() # optional - sage.rings.number_field + sage: TestSuite(G).run() # needs sage.rings.number_field + sage: TestSuite(S).run() # needs sage.rings.number_field """ try: test = self.is_finite() @@ -265,10 +267,10 @@ def _repr_(self): EXAMPLES:: - sage: F = GF(5); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: gens = [MS([[1,2], [-1,1]]), MS([[1,1], [0,1]])] # optional - sage.rings.finite_rings - sage: G = MatrixGroup(gens) # optional - sage.rings.finite_rings - sage: G # optional - sage.rings.finite_rings + sage: F = GF(5); MS = MatrixSpace(F, 2, 2) + sage: gens = [MS([[1,2], [-1,1]]), MS([[1,1], [0,1]])] + sage: G = MatrixGroup(gens) + sage: G Matrix group over Finite Field of size 5 with 2 generators ( [1 2] [1 1] [4 1], [0 1] @@ -276,11 +278,12 @@ def _repr_(self): case of being a subgroup:: - sage: CF3 = CyclotomicField(3) # optional - sage.rings.number_field - sage: G = GL(2, CF3) # optional - sage.rings.number_field - sage: e3 = CF3.gen() # optional - sage.rings.number_field - sage: m = matrix(CF3, 2, 2, [[e3, 1], [0, ~e3]]) # optional - sage.rings.number_field - sage: S = G.subgroup([m]); S # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: CF3 = CyclotomicField(3) + sage: G = GL(2, CF3) + sage: e3 = CF3.gen() + sage: m = matrix(CF3, 2, 2, [[e3, 1], [0, ~e3]]) + sage: S = G.subgroup([m]); S Subgroup with 1 generators ( [ zeta3 1] [ 0 -zeta3 - 1] @@ -313,8 +316,8 @@ def _repr_option(self, key): EXAMPLES:: - sage: SO3 = groups.matrix.SO(3, QQ) # optional - sage.groups - sage: SO3._repr_option('element_ascii_art') # optional - sage.groups + sage: SO3 = groups.matrix.SO(3, QQ) # needs sage.groups sage.modules + sage: SO3._repr_option('element_ascii_art') # needs sage.groups sage.modules True """ if key == 'element_ascii_art': @@ -325,9 +328,9 @@ def _latex_(self): r""" EXAMPLES:: - sage: MS = MatrixSpace(GF(5), 2, 2) # optional - sage.rings.finite_rings - sage: G = MatrixGroup(MS([[1,2], [-1,1]]), MS([[1,1], [0,1]])) # optional - sage.rings.finite_rings - sage: latex(G) # optional - sage.rings.finite_rings + sage: MS = MatrixSpace(GF(5), 2, 2) + sage: G = MatrixGroup(MS([[1,2], [-1,1]]), MS([[1,1], [0,1]])) + sage: latex(G) \left\langle \left(\begin{array}{rr} 1 & 2 \\ 4 & 1 @@ -355,19 +358,19 @@ def sign_representation(self, base_ring=None, side="twosided"): EXAMPLES:: sage: G = GL(2, QQ) - sage: V = G.sign_representation() # optional - sage.combinat - sage: e = G.an_element() # optional - sage.combinat - sage: e # optional - sage.combinat + sage: V = G.sign_representation() + sage: e = G.an_element() + sage: e [1 0] [0 1] - sage: V._default_sign(e) # optional - sage.combinat + sage: V._default_sign(e) 1 - sage: m2 = V.an_element() # optional - sage.combinat - sage: m2 # optional - sage.combinat + sage: m2 = V.an_element() + sage: m2 2*B['v'] - sage: m2*e # optional - sage.combinat + sage: m2*e 2*B['v'] - sage: m2*e*e # optional - sage.combinat + sage: m2*e*e 2*B['v'] """ if base_ring is None: @@ -432,7 +435,7 @@ def degree(self): EXAMPLES:: - sage: SU(5,5).degree() # optional - sage.rings.finite_rings + sage: SU(5,5).degree() # needs sage.rings.finite_rings 5 """ return self._deg @@ -447,11 +450,11 @@ def matrix_space(self): EXAMPLES:: - sage: F = GF(5); MS = MatrixSpace(F, 2, 2) # optional - sage.rings.finite_rings - sage: G = MatrixGroup([MS(1), MS([1,2,3,4])]) # optional - sage.rings.finite_rings - sage: G.matrix_space() # optional - sage.rings.finite_rings + sage: F = GF(5); MS = MatrixSpace(F, 2, 2) + sage: G = MatrixGroup([MS(1), MS([1,2,3,4])]) + sage: G.matrix_space() Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5 - sage: G.matrix_space() is MS # optional - sage.rings.finite_rings + sage: G.matrix_space() is MS True """ return MatrixSpace(self.base_ring(), self.degree()) @@ -476,11 +479,11 @@ def __richcmp__(self, other, op): EXAMPLES:: - sage: G = GL(2,3) # optional - sage.rings.finite_rings - sage: H = MatrixGroup(G.gens()) # optional - sage.rings.finite_rings - sage: H == G # optional - sage.rings.finite_rings + sage: G = GL(2,3) + sage: H = MatrixGroup(G.gens()) + sage: H == G True - sage: G == H # optional - sage.rings.finite_rings + sage: G == H True sage: MS = MatrixSpace(QQ, 2, 2) @@ -492,11 +495,12 @@ def __richcmp__(self, other, op): TESTS:: - sage: G = groups.matrix.GL(4,2) # optional - sage.groups sage.rings.finite_rings - sage: H = MatrixGroup(G.gens()) # optional - sage.groups sage.rings.finite_rings - sage: G == H # optional - sage.groups sage.rings.finite_rings + sage: # needs sage.groups sage.rings.finite_rings + sage: G = groups.matrix.GL(4,2) + sage: H = MatrixGroup(G.gens()) + sage: G == H True - sage: G != H # optional - sage.groups sage.rings.finite_rings + sage: G != H False """ if not is_MatrixGroup(other): diff --git a/src/sage/groups/matrix_gps/matrix_group_gap.py b/src/sage/groups/matrix_gps/matrix_group_gap.py index b4c06acbd0f..9205951ccdd 100644 --- a/src/sage/groups/matrix_gps/matrix_group_gap.py +++ b/src/sage/groups/matrix_gps/matrix_group_gap.py @@ -154,8 +154,8 @@ def __iter__(self): infinite groups can be dealt with:: sage: import itertools - sage: W = WeylGroup(["A",3,1]) - sage: list(itertools.islice(W, int(4))) + sage: W = WeylGroup(["A",3,1]) # needs sage.rings.number_field + sage: list(itertools.islice(W, int(4))) # needs sage.rings.number_field [ [1 0 0 0] [-1 1 0 1] [ 1 0 0 0] [ 1 0 0 0] [0 1 0 0] [ 0 1 0 0] [ 1 -1 1 0] [ 0 1 0 0] @@ -238,6 +238,7 @@ def subgroup(self, generators, check=True): EXAMPLES:: + sage: # needs sage.rings.number_field sage: UCF = UniversalCyclotomicField() sage: G = GL(3, UCF) sage: e3 = UCF.gen(3); e5 = UCF.gen(5) @@ -249,6 +250,7 @@ def subgroup(self, generators, check=True): [ 4 3 2] ) of General Linear Group of degree 3 over Universal Cyclotomic Field + sage: # needs sage.rings.number_field sage: CF3 = CyclotomicField(3) sage: G = GL(3, CF3) sage: e3 = CF3.gen() @@ -262,15 +264,17 @@ def subgroup(self, generators, check=True): TESTS:: - sage: TestSuite(G).run() - sage: TestSuite(S).run() + sage: TestSuite(G).run() # needs sage.rings.number_field + sage: TestSuite(S).run() # needs sage.rings.number_field + sage: # needs sage.rings.number_field sage: W = CoxeterGroup(['I',7]) sage: s = W.simple_reflections() sage: G = W.subgroup([s[1]]) sage: G.category() Category of finite groups + sage: # needs sage.rings.number_field sage: W = WeylGroup(['A',2]) sage: s = W.simple_reflections() sage: G = W.subgroup([s[1]]) diff --git a/src/sage/groups/matrix_gps/morphism.py b/src/sage/groups/matrix_gps/morphism.py index 9805161d016..e2fc2e0fd59 100644 --- a/src/sage/groups/matrix_gps/morphism.py +++ b/src/sage/groups/matrix_gps/morphism.py @@ -42,6 +42,7 @@ def to_libgap(x): from sage.libs.gap.libgap import libgap return libgap(x) + lazy_import('sage.groups.libgap_morphism', 'GroupMorphism_libgap', 'MatrixGroupMorphism_im_gens', deprecation=25444) diff --git a/src/sage/groups/matrix_gps/named_group.py b/src/sage/groups/matrix_gps/named_group.py index 08717dd7110..4568c43d326 100644 --- a/src/sage/groups/matrix_gps/named_group.py +++ b/src/sage/groups/matrix_gps/named_group.py @@ -8,17 +8,17 @@ sage: SL(2, ZZ) Special Linear Group of degree 2 over Integer Ring - sage: G = SL(2, GF(3)); G # optional - sage.rings.finite_rings + sage: G = SL(2, GF(3)); G Special Linear Group of degree 2 over Finite Field of size 3 - sage: G.is_finite() # optional - sage.rings.finite_rings + sage: G.is_finite() True - sage: G.conjugacy_classes_representatives() # optional - sage.rings.finite_rings + sage: G.conjugacy_classes_representatives() ( [1 0] [0 2] [0 1] [2 0] [0 2] [0 1] [0 2] [0 1], [1 1], [2 1], [0 2], [1 2], [2 2], [1 0] ) - sage: G = SL(6, GF(5)) # optional - sage.rings.finite_rings - sage: G.gens() # optional - sage.rings.finite_rings + sage: G = SL(6, GF(5)) + sage: G.gens() ( [2 0 0 0 0 0] [4 0 0 0 0 1] [0 3 0 0 0 0] [4 0 0 0 0 0] @@ -83,12 +83,12 @@ def normalize_args_vectorspace(*args, **kwds): TESTS:: sage: from sage.groups.matrix_gps.named_group import normalize_args_vectorspace - sage: A = AffineSpace(2, GF(4,'a')); A # optional - sage.rings.finite_rings + sage: A = AffineSpace(2, GF(4,'a')); A # needs sage.rings.finite_rings Affine Space of dimension 2 over Finite Field in a of size 2^2 - sage: normalize_args_vectorspace(A) # optional - sage.rings.finite_rings + sage: normalize_args_vectorspace(A) # needs sage.rings.finite_rings (2, Finite Field in a of size 2^2) - sage: normalize_args_vectorspace(2,4) # shorthand # optional - sage.rings.finite_rings + sage: normalize_args_vectorspace(2,4) # shorthand # needs sage.rings.finite_rings (2, Finite Field in a of size 2^2) sage: V = ZZ^3; V @@ -150,12 +150,12 @@ def normalize_args_invariant_form(R, d, invariant_form): TESTS:: sage: from sage.groups.matrix_gps.named_group import normalize_args_invariant_form - sage: CF3 = CyclotomicField(3) # optional - sage.rings.number_field - sage: m = normalize_args_invariant_form(CF3, 3, (1,2,3,0,2,0,0,2,1)); m # optional - sage.rings.number_field + sage: CF3 = CyclotomicField(3) # needs sage.rings.number_field + sage: m = normalize_args_invariant_form(CF3, 3, (1,2,3,0,2,0,0,2,1)); m # needs sage.rings.number_field [1 2 3] [0 2 0] [0 2 1] - sage: m.base_ring() == CF3 # optional - sage.rings.number_field + sage: m.base_ring() == CF3 # needs sage.rings.number_field True sage: normalize_args_invariant_form(ZZ, 3, (1,2,3,0,2,0,0,2)) @@ -288,15 +288,16 @@ def __richcmp__(self, other, op): EXAMPLES:: - sage: G = GL(2,3) # optional - sage.rings.finite_rings - sage: G == MatrixGroup(G.gens()) # optional - sage.rings.finite_rings + sage: G = GL(2,3) + sage: G == MatrixGroup(G.gens()) True - sage: G = groups.matrix.GL(4,2) # optional - sage.rings.finite_rings - sage: H = MatrixGroup(G.gens()) # optional - sage.rings.finite_rings - sage: G == H # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: G = groups.matrix.GL(4,2) # needs sage.modules + sage: H = MatrixGroup(G.gens()) + sage: G == H True - sage: G != H # optional - sage.rings.finite_rings + sage: G != H False """ return MatrixGroup_generic.__richcmp__(self, other, op) diff --git a/src/sage/groups/matrix_gps/orthogonal.py b/src/sage/groups/matrix_gps/orthogonal.py index 694401d6d31..b05be536955 100644 --- a/src/sage/groups/matrix_gps/orthogonal.py +++ b/src/sage/groups/matrix_gps/orthogonal.py @@ -33,13 +33,13 @@ EXAMPLES:: - sage: GO(3,7) # optional - sage.rings.finite_rings + sage: GO(3,7) General Orthogonal Group of degree 3 over Finite Field of size 7 - sage: G = SO(4, GF(7), 1); G # optional - sage.rings.finite_rings + sage: G = SO(4, GF(7), 1); G Special Orthogonal Group of degree 4 and form parameter 1 over Finite Field of size 7 - sage: G.random_element() # random # optional - sage.rings.finite_rings + sage: G.random_element() # random [4 3 5 2] [6 6 4 0] [0 4 6 0] @@ -47,14 +47,14 @@ TESTS:: - sage: G = GO(3, GF(5)) # optional - sage.rings.finite_rings - sage: latex(G) # optional - sage.rings.finite_rings + sage: G = GO(3, GF(5)) + sage: latex(G) \text{GO}_{3}(\Bold{F}_{5}) - sage: G = SO(3, GF(5)) # optional - sage.rings.finite_rings - sage: latex(G) # optional - sage.rings.finite_rings + sage: G = SO(3, GF(5)) + sage: latex(G) \text{SO}_{3}(\Bold{F}_{5}) - sage: G = SO(4, GF(5), 1) # optional - sage.rings.finite_rings - sage: latex(G) # optional - sage.rings.finite_rings + sage: G = SO(4, GF(5), 1) + sage: latex(G) \text{SO}_{4}(\Bold{F}_{5}, +) AUTHORS: @@ -121,13 +121,13 @@ def normalize_args_e(degree, ring, e): TESTS:: sage: from sage.groups.matrix_gps.orthogonal import normalize_args_e - sage: normalize_args_e(2, GF(3), +1) # optional - sage.rings.finite_rings + sage: normalize_args_e(2, GF(3), +1) 1 - sage: normalize_args_e(3, GF(3), 0) # optional - sage.rings.finite_rings + sage: normalize_args_e(3, GF(3), 0) 0 - sage: normalize_args_e(3, GF(3), +1) # optional - sage.rings.finite_rings + sage: normalize_args_e(3, GF(3), +1) 0 - sage: normalize_args_e(2, GF(3), 0) # optional - sage.rings.finite_rings + sage: normalize_args_e(2, GF(3), 0) Traceback (most recent call last): ... ValueError: must have e=-1 or e=1 for even degree @@ -154,14 +154,14 @@ def _OG(n, R, special, e=0, var='a', invariant_form=None): Check that :trac:`26028` is fixed:: - sage: GO(3,25).order() # indirect doctest # optional - sage.rings.finite_rings + sage: GO(3,25).order() # indirect doctest # needs sage.rings.finite_rings 31200 Check that :trac:`28054` is fixed:: - sage: G = SO(2, GF(3), -1) # optional - sage.rings.finite_rings - sage: m = G.invariant_form() # optional - sage.rings.finite_rings - sage: G2 = SO(2, GF(3), 1, invariant_form=m) # optional - sage.rings.finite_rings + sage: G = SO(2, GF(3), -1) + sage: m = G.invariant_form() + sage: G2 = SO(2, GF(3), 1, invariant_form=m) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP @@ -268,11 +268,11 @@ def GO(n, R, e=0, var='a', invariant_form=None): EXAMPLES:: - sage: GO(3, GF(7)) # optional - sage.rings.finite_rings + sage: GO(3, GF(7)) General Orthogonal Group of degree 3 over Finite Field of size 7 - sage: GO(3, GF(7)).order() # optional - sage.rings.finite_rings + sage: GO(3, GF(7)).order() 672 - sage: GO(3, GF(7)).gens() # optional - sage.rings.finite_rings + sage: GO(3, GF(7)).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] @@ -294,13 +294,13 @@ def GO(n, R, e=0, var='a', invariant_form=None): [0 1 0] [1 0 0] [0 0 3] - sage: pm = Permutation([2,3,1]).to_matrix() # optional - sage.combinat - sage: g = GO3(pm); g in GO3; g # optional - sage.combinat + sage: pm = Permutation([2,3,1]).to_matrix() + sage: g = GO3(pm); g in GO3; g True [0 0 1] [1 0 0] [0 1 0] - sage: GO3m(pm) # optional - sage.combinat + sage: GO3m(pm) Traceback (most recent call last): ... TypeError: matrix must be orthogonal with respect to the symmetric form @@ -375,19 +375,18 @@ def SO(n, R, e=None, var='a', invariant_form=None): EXAMPLES:: - sage: G = SO(3,GF(5)) # optional - sage.rings.finite_rings - sage: G # optional - sage.rings.finite_rings + sage: G = SO(3,GF(5)); G Special Orthogonal Group of degree 3 over Finite Field of size 5 - sage: G = SO(3,GF(5)) # optional - sage.rings.finite_rings - sage: G.gens() # optional - sage.rings.finite_rings + sage: G = SO(3,GF(5)) + sage: G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) - sage: G = SO(3,GF(5)) # optional - sage.rings.finite_rings - sage: G.as_matrix_group() # optional - sage.rings.finite_rings + sage: G = SO(3,GF(5)) + sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] @@ -396,27 +395,28 @@ def SO(n, R, e=None, var='a', invariant_form=None): Using the ``invariant_form`` option:: - sage: CF3 = CyclotomicField(3); e3 = CF3.gen() # optional - sage.rings.number_field - sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3,2,0], [0,0,1]]) # optional - sage.rings.number_field - sage: SO3 = SO(3, CF3) # optional - sage.rings.number_field - sage: SO3m = SO(3, CF3, invariant_form=m) # optional - sage.rings.number_field - sage: SO3 == SO3m # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: CF3 = CyclotomicField(3); e3 = CF3.gen() + sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3,2,0], [0,0,1]]) + sage: SO3 = SO(3, CF3) + sage: SO3m = SO(3, CF3, invariant_form=m) + sage: SO3 == SO3m False - sage: SO3.invariant_form() # optional - sage.rings.number_field + sage: SO3.invariant_form() [1 0 0] [0 1 0] [0 0 1] - sage: SO3m.invariant_form() # optional - sage.rings.number_field + sage: SO3m.invariant_form() [ 1 zeta3 0] [zeta3 2 0] [ 0 0 1] - sage: pm = Permutation([2,3,1]).to_matrix() # optional - sage.combinat - sage: g = SO3(pm); g in SO3; g # optional - sage.combinat sage.rings.number_field + sage: pm = Permutation([2,3,1]).to_matrix() + sage: g = SO3(pm); g in SO3; g True [0 0 1] [1 0 0] [0 1 0] - sage: SO3m(pm) # optional - sage.combinat sage.rings.number_field + sage: SO3m(pm) Traceback (most recent call last): ... TypeError: matrix must be orthogonal with respect to the symmetric form @@ -424,7 +424,7 @@ def SO(n, R, e=None, var='a', invariant_form=None): [zeta3 2 0] [ 0 0 1] - sage: SO(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]]) # optional - sage.combinat sage.rings.number_field + sage: SO(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP @@ -433,8 +433,8 @@ def SO(n, R, e=None, var='a', invariant_form=None): TESTS:: - sage: TestSuite(SO3m).run() # optional - sage.rings.number_field - sage: groups.matrix.SO(2, 3, e=1) # optional - sage.rings.number_field + sage: TestSuite(SO3m).run() # needs sage.rings.number_field + sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2 and form parameter 1 over Finite Field of size 3 """ return _OG(n, R, True, e=e, var=var, invariant_form=invariant_form) @@ -450,20 +450,21 @@ class OrthogonalMatrixGroup_generic(NamedMatrixGroup_generic): EXAMPLES:: - sage: G = GO(3, GF(7)); G # optional - sage.rings.finite_rings + sage: G = GO(3, GF(7)); G General Orthogonal Group of degree 3 over Finite Field of size 7 - sage: latex(G) # optional - sage.rings.finite_rings + sage: latex(G) \text{GO}_{3}(\Bold{F}_{7}) - sage: G = SO(3, GF(5)); G # optional - sage.rings.finite_rings + sage: G = SO(3, GF(5)); G Special Orthogonal Group of degree 3 over Finite Field of size 5 - sage: latex(G) # optional - sage.rings.finite_rings + sage: latex(G) \text{SO}_{3}(\Bold{F}_{5}) - sage: CF3 = CyclotomicField(3); e3 = CF3.gen() # optional - sage.rings.number_field - sage: m = matrix(CF3, 3,3, [[1,e3,0],[e3,2,0],[0,0,1]]) # optional - sage.rings.number_field - sage: G = SO(3, CF3, invariant_form=m) # optional - sage.rings.number_field - sage: latex(G) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: CF3 = CyclotomicField(3); e3 = CF3.gen() + sage: m = matrix(CF3, 3,3, [[1,e3,0],[e3,2,0],[0,0,1]]) + sage: G = SO(3, CF3, invariant_form=m) + sage: latex(G) \text{SO}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to non positive definite symmetric form }\left(\begin{array}{rrr} 1 & \zeta_{3} & 0 \\ \zeta_{3} & 2 & 0 \\ @@ -482,10 +483,10 @@ def invariant_bilinear_form(self): EXAMPLES:: - sage: GO(2,3,+1).invariant_bilinear_form() # optional - sage.rings.finite_rings + sage: GO(2,3,+1).invariant_bilinear_form() [0 1] [1 0] - sage: GO(2,3,-1).invariant_bilinear_form() # optional - sage.rings.finite_rings + sage: GO(2,3,-1).invariant_bilinear_form() [2 1] [1 1] sage: G = GO(4, QQ) @@ -527,8 +528,8 @@ def _check_matrix(self, x, *args): EXAMPLES:: - sage: G = GO(4, GF(5), +1) # optional - sage.rings.finite_rings - sage: G._check_matrix(G.an_element().matrix()) # optional - sage.rings.finite_rings + sage: G = GO(4, GF(5), +1) + sage: G._check_matrix(G.an_element().matrix()) """ if self._special and x.determinant() != 1: raise TypeError('matrix must have determinant one') diff --git a/src/sage/groups/matrix_gps/symplectic.py b/src/sage/groups/matrix_gps/symplectic.py index aad18def93b..3a7e7258fe9 100644 --- a/src/sage/groups/matrix_gps/symplectic.py +++ b/src/sage/groups/matrix_gps/symplectic.py @@ -3,17 +3,17 @@ EXAMPLES:: - sage: G = Sp(4, GF(7)); G # optional - sage.rings.finite_rings + sage: G = Sp(4, GF(7)); G Symplectic Group of degree 4 over Finite Field of size 7 - sage: g = prod(G.gens()); g # optional - sage.rings.finite_rings + sage: g = prod(G.gens()); g [3 0 3 0] [1 0 0 0] [0 1 0 1] [0 2 0 0] - sage: m = g.matrix() # optional - sage.rings.finite_rings - sage: m * G.invariant_form() * m.transpose() == G.invariant_form() # optional - sage.rings.finite_rings + sage: m = g.matrix() + sage: m * G.invariant_form() * m.transpose() == G.invariant_form() True - sage: G.order() # optional - sage.rings.finite_rings + sage: G.order() 276595200 AUTHORS: @@ -82,13 +82,13 @@ def Sp(n, R, var='a', invariant_form=None): EXAMPLES:: - sage: Sp(4, 5) # optional - sage.rings.finite_rings + sage: Sp(4, 5) Symplectic Group of degree 4 over Finite Field of size 5 sage: Sp(4, IntegerModRing(15)) Symplectic Group of degree 4 over Ring of integers modulo 15 - sage: Sp(3, GF(7)) # optional - sage.rings.finite_rings + sage: Sp(3, GF(7)) Traceback (most recent call last): ... ValueError: the degree must be even @@ -110,14 +110,14 @@ def Sp(n, R, var='a', invariant_form=None): [ 0 0 0 2] [-1 0 0 0] [ 0 -2 0 0] - sage: pm = Permutation([2,1,4,3]).to_matrix() # optional - sage.combinat - sage: g = Sp4(pm); g in Sp4; g # optional - sage.combinat + sage: pm = Permutation([2,1,4,3]).to_matrix() + sage: g = Sp4(pm); g in Sp4; g True [0 1 0 0] [1 0 0 0] [0 0 0 1] [0 0 1 0] - sage: Sp4m(pm) # optional - sage.combinat + sage: Sp4m(pm) Traceback (most recent call last): ... TypeError: matrix must be symplectic with respect to the alternating form @@ -126,7 +126,7 @@ def Sp(n, R, var='a', invariant_form=None): [-1 0 0 0] [ 0 -2 0 0] - sage: Sp(4,3, invariant_form=[[0,0,0,1],[0,0,1,0],[0,2,0,0], [2,0,0,0]]) # optional - sage.rings.finite_rings + sage: Sp(4,3, invariant_form=[[0,0,0,1],[0,0,1,0],[0,2,0,0], [2,0,0,0]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP @@ -135,11 +135,11 @@ def Sp(n, R, var='a', invariant_form=None): sage: TestSuite(Sp4).run() sage: TestSuite(Sp4m).run() - sage: groups.matrix.Sp(2, 3) # optional - sage.rings.finite_rings + sage: groups.matrix.Sp(2, 3) # needs sage.modules sage.rings.finite_rings Symplectic Group of degree 2 over Finite Field of size 3 - sage: G = Sp(4,5) # optional - sage.rings.finite_rings - sage: TestSuite(G).run() # optional - sage.rings.finite_rings + sage: G = Sp(4,5) + sage: TestSuite(G).run() """ degree, ring = normalize_args_vectorspace(n, R, var=var) if degree % 2: @@ -181,9 +181,9 @@ class SymplecticMatrixGroup_generic(NamedMatrixGroup_generic): EXAMPLES:: - sage: Sp43 = Sp(4,3); Sp43 # optional - sage.rings.finite_rings + sage: Sp43 = Sp(4,3); Sp43 Symplectic Group of degree 4 over Finite Field of size 3 - sage: latex(Sp43) # optional - sage.rings.finite_rings + sage: latex(Sp43) \text{Sp}_{4}(\Bold{F}_{3}) sage: Sp4m = Sp(4, QQ, invariant_form=(0, 0, 1, 0, 0, 0, 0, 2, @@ -239,8 +239,8 @@ def _check_matrix(self, x, *args): EXAMPLES:: - sage: G = Sp(4, GF(5)) # optional - sage.rings.finite_rings - sage: G._check_matrix(G.an_element().matrix()) # optional - sage.rings.finite_rings + sage: G = Sp(4, GF(5)) + sage: G._check_matrix(G.an_element().matrix()) """ F = self.invariant_form() if x * F * x.transpose() != F: diff --git a/src/sage/groups/matrix_gps/symplectic_gap.py b/src/sage/groups/matrix_gps/symplectic_gap.py index adeefea218f..96bf1fb5a75 100644 --- a/src/sage/groups/matrix_gps/symplectic_gap.py +++ b/src/sage/groups/matrix_gps/symplectic_gap.py @@ -27,7 +27,7 @@ class SymplecticMatrixGroup_gap(SymplecticMatrixGroup_generic, NamedMatrixGroup_ EXAMPLES:: - sage: Sp(2,4) + sage: Sp(2,4) # needs sage.rings.finite_rings Symplectic Group of degree 2 over Finite Field in a of size 2^2 sage: latex(Sp(4,5)) diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py index 8d8a4d23491..22dd25b1a4b 100644 --- a/src/sage/groups/matrix_gps/unitary.py +++ b/src/sage/groups/matrix_gps/unitary.py @@ -6,18 +6,19 @@ EXAMPLES:: - sage: G = SU(3,5) # optional - sage.rings.finite_rings - sage: G.order() # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: G = SU(3,5) + sage: G.order() 378000 - sage: G # optional - sage.rings.finite_rings + sage: G Special Unitary Group of degree 3 over Finite Field in a of size 5^2 - sage: G.gens() # optional - sage.rings.finite_rings + sage: G.gens() ( [ a 0 0] [4*a 4 1] [ 0 2*a + 2 0] [ 4 4 0] [ 0 0 3*a], [ 1 0 0] ) - sage: G.base_ring() # optional - sage.rings.finite_rings + sage: G.base_ring() Finite Field in a of size 5^2 AUTHORS: @@ -76,7 +77,7 @@ def finite_field_sqrt(ring): EXAMPLES:: sage: from sage.groups.matrix_gps.unitary import finite_field_sqrt - sage: finite_field_sqrt(GF(4, 'a')) # optional - sage.rings.finite_rings + sage: finite_field_sqrt(GF(4, 'a')) # needs sage.rings.finite_rings 2 """ if not isinstance(ring, FiniteField): @@ -99,7 +100,7 @@ def _UG(n, R, special, var='a', invariant_form=None): TESTS:: - sage: GU(3,25).order() # indirect doctest # optional - sage.rings.finite_rings + sage: GU(3,25).order() # indirect doctest # needs sage.rings.finite_rings 3961191000000 """ prefix = 'General' @@ -192,9 +193,9 @@ def GU(n, R, var='a', invariant_form=None): EXAMPLES:: - sage: G = GU(3, 7); G # optional - sage.rings.finite_rings + sage: G = GU(3, 7); G # needs sage.rings.finite_rings General Unitary Group of degree 3 over Finite Field in a of size 7^2 - sage: G.gens() # optional - sage.rings.finite_rings + sage: G.gens() # needs sage.rings.finite_rings ( [ a 0 0] [6*a 6 1] [ 0 1 0] [ 6 6 0] @@ -203,10 +204,10 @@ def GU(n, R, var='a', invariant_form=None): sage: GU(2, QQ) General Unitary Group of degree 2 over Rational Field - sage: G = GU(3, 5, var='beta') # optional - sage.rings.finite_rings - sage: G.base_ring() # optional - sage.rings.finite_rings + sage: G = GU(3, 5, var='beta') # needs sage.rings.finite_rings + sage: G.base_ring() # needs sage.rings.finite_rings Finite Field in beta of size 5^2 - sage: G.gens() # optional - sage.rings.finite_rings + sage: G.gens() # needs sage.rings.finite_rings ( [ beta 0 0] [4*beta 4 1] [ 0 1 0] [ 4 4 0] @@ -215,27 +216,28 @@ def GU(n, R, var='a', invariant_form=None): Using the ``invariant_form`` option:: - sage: UCF = UniversalCyclotomicField(); e5 = UCF.gen(5) # optional - sage.rings.number_field - sage: m = matrix(UCF, 3, 3, [[1,e5,0], [e5.conjugate(),2,0], [0,0,1]]) # optional - sage.rings.number_field - sage: G = GU(3, UCF) # optional - sage.rings.number_field - sage: Gm = GU(3, UCF, invariant_form=m) # optional - sage.rings.number_field - sage: G == Gm # optional - sage.rings.number_field + sage: # needs sage.libs.gap sage.rings.number_field + sage: UCF = UniversalCyclotomicField(); e5 = UCF.gen(5) + sage: m = matrix(UCF, 3, 3, [[1,e5,0], [e5.conjugate(),2,0], [0,0,1]]) + sage: G = GU(3, UCF) + sage: Gm = GU(3, UCF, invariant_form=m) + sage: G == Gm False - sage: G.invariant_form() # optional - sage.rings.number_field + sage: G.invariant_form() [1 0 0] [0 1 0] [0 0 1] - sage: Gm.invariant_form() # optional - sage.rings.number_field + sage: Gm.invariant_form() [ 1 E(5) 0] [E(5)^4 2 0] [ 0 0 1] - sage: pm = Permutation((1,2,3)).to_matrix() # optional - sage.combinat sage.rings.number_field - sage: g = G(pm); g in G; g # optional - sage.combinat sage.rings.number_field + sage: pm = Permutation((1,2,3)).to_matrix() + sage: g = G(pm); g in G; g # needs sage.combinat True [0 0 1] [1 0 0] [0 1 0] - sage: Gm(pm) # optional - sage.combinat sage.rings.number_field + sage: Gm(pm) # needs sage.combinat Traceback (most recent call last): ... TypeError: matrix must be unitary with respect to the hermitian form @@ -243,7 +245,7 @@ def GU(n, R, var='a', invariant_form=None): [E(5)^4 2 0] [ 0 0 1] - sage: GU(3, 3, invariant_form=[[1,0,0], [0,2,0], [0,0,1]]) # optional - sage.rings.number_field + sage: GU(3, 3, invariant_form=[[1,0,0], [0,2,0], [0,0,1]]) # needs sage.libs.pari Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP @@ -255,8 +257,8 @@ def GU(n, R, var='a', invariant_form=None): TESTS:: - sage: TestSuite(G).run() # optional - sage.rings.number_field - sage: groups.matrix.GU(2, 3) # optional - sage.groups sage.rings.finite_rings + sage: TestSuite(G).run() # needs sage.libs.gap sage.rings.number_field + sage: groups.matrix.GU(2, 3) # needs sage.groups sage.rings.finite_rings General Unitary Group of degree 2 over Finite Field in a of size 3^2 """ return _UG(n, R, False, var=var, invariant_form=invariant_form) @@ -305,35 +307,36 @@ def SU(n, R, var='a', invariant_form=None): EXAMPLES:: - sage: SU(3,5) # optional - sage.rings.finite_rings + sage: SU(3,5) # needs sage.rings.finite_rings Special Unitary Group of degree 3 over Finite Field in a of size 5^2 - sage: SU(3, GF(5)) # optional - sage.rings.finite_rings + sage: SU(3, GF(5)) # needs sage.rings.finite_rings Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3, QQ) Special Unitary Group of degree 3 over Rational Field Using the ``invariant_form`` option:: - sage: CF3 = CyclotomicField(3); e3 = CF3.gen() # optional - sage.rings.number_field - sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3.conjugate(),2,0], [0,0,1]]) # optional - sage.rings.number_field - sage: G = SU(3, CF3) # optional - sage.rings.number_field - sage: Gm = SU(3, CF3, invariant_form=m) # optional - sage.rings.number_field - sage: G == Gm # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: CF3 = CyclotomicField(3); e3 = CF3.gen() + sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3.conjugate(),2,0], [0,0,1]]) + sage: G = SU(3, CF3) + sage: Gm = SU(3, CF3, invariant_form=m) + sage: G == Gm False - sage: G.invariant_form() # optional - sage.rings.number_field + sage: G.invariant_form() [1 0 0] [0 1 0] [0 0 1] - sage: Gm.invariant_form() # optional - sage.rings.number_field + sage: Gm.invariant_form() [ 1 zeta3 0] [-zeta3 - 1 2 0] [ 0 0 1] - sage: pm = Permutation((1,2,3)).to_matrix() # optional - sage.combinat sage.rings.number_field - sage: G(pm) # optional - sage.combinat sage.rings.number_field + sage: pm = Permutation((1,2,3)).to_matrix() + sage: G(pm) # needs sage.combinat [0 0 1] [1 0 0] [0 1 0] - sage: Gm(pm) # optional - sage.combinat sage.rings.number_field + sage: Gm(pm) # needs sage.combinat Traceback (most recent call last): ... TypeError: matrix must be unitary with respect to the hermitian form @@ -341,15 +344,15 @@ def SU(n, R, var='a', invariant_form=None): [-zeta3 - 1 2 0] [ 0 0 1] - sage: SU(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]]) # optional - sage.rings.finite_rings + sage: SU(3, 5, invariant_form=[[1,0,0], [0,2,0], [0,0,3]]) # needs sage.rings.finite_rings Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP TESTS:: - sage: TestSuite(Gm).run() # optional - sage.rings.number_field - sage: groups.matrix.SU(2, 3) # optional - sage.rings.finite_rings + sage: TestSuite(Gm).run() # needs sage.rings.number_field + sage: groups.matrix.SU(2, 3) # needs sage.modules sage.rings.finite_rings Special Unitary Group of degree 2 over Finite Field in a of size 3^2 """ return _UG(n, R, True, var=var, invariant_form=invariant_form) @@ -365,20 +368,21 @@ class UnitaryMatrixGroup_generic(NamedMatrixGroup_generic): EXAMPLES:: - sage: G = GU(3, GF(7)); G # optional - sage.rings.finite_rings + sage: G = GU(3, GF(7)); G # needs sage.rings.finite_rings General Unitary Group of degree 3 over Finite Field in a of size 7^2 - sage: latex(G) # optional - sage.rings.finite_rings + sage: latex(G) # needs sage.rings.finite_rings \text{GU}_{3}(\Bold{F}_{7^{2}}) - sage: G = SU(3, GF(5)); G # optional - sage.rings.finite_rings + sage: G = SU(3, GF(5)); G # needs sage.rings.finite_rings Special Unitary Group of degree 3 over Finite Field in a of size 5^2 - sage: latex(G) # optional - sage.rings.finite_rings + sage: latex(G) # needs sage.rings.finite_rings \text{SU}_{3}(\Bold{F}_{5^{2}}) - sage: CF3 = CyclotomicField(3); e3 = CF3.gen() # optional - sage.rings.number_field - sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3.conjugate(),2,0], [0,0,1]]) # optional - sage.rings.number_field - sage: G = SU(3, CF3, invariant_form=m) # optional - sage.rings.number_field - sage: latex(G) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: CF3 = CyclotomicField(3); e3 = CF3.gen() + sage: m = matrix(CF3, 3, 3, [[1,e3,0], [e3.conjugate(),2,0], [0,0,1]]) + sage: G = SU(3, CF3, invariant_form=m) + sage: latex(G) \text{SU}_{3}(\Bold{Q}(\zeta_{3}))\text{ with respect to positive definite hermitian form }\left(\begin{array}{rrr} 1 & \zeta_{3} & 0 \\ -\zeta_{3} - 1 & 2 & 0 \\ @@ -420,10 +424,11 @@ def _check_matrix(self, x, *args): EXAMPLES:: - sage: G = GU(2, GF(5)) # optional - sage.rings.finite_rings - sage: G._check_matrix(G.an_element().matrix()) # optional - sage.rings.finite_rings - sage: G = SU(2, GF(5)) # optional - sage.rings.finite_rings - sage: G._check_matrix(G.an_element().matrix()) # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: G = GU(2, GF(5)) + sage: G._check_matrix(G.an_element().matrix()) + sage: G = SU(2, GF(5)) + sage: G._check_matrix(G.an_element().matrix()) """ if self._special and x.determinant() != 1: raise TypeError('matrix must have determinant one') diff --git a/src/sage/groups/matrix_gps/unitary_gap.py b/src/sage/groups/matrix_gps/unitary_gap.py index 02b0456decb..0aa547f32e2 100644 --- a/src/sage/groups/matrix_gps/unitary_gap.py +++ b/src/sage/groups/matrix_gps/unitary_gap.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings r""" Unitary Groups `GU(n,q)` and `SU(n,q)` with GAP """ diff --git a/src/sage/groups/misc_gps/argument_groups.py b/src/sage/groups/misc_gps/argument_groups.py index d6128ee7fdb..1c949a57f51 100644 --- a/src/sage/groups/misc_gps/argument_groups.py +++ b/src/sage/groups/misc_gps/argument_groups.py @@ -191,13 +191,13 @@ def _eq_(self, other): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: C(I) == C(I) + sage: C(I) == C(I) # needs sage.symbolic True As we do not have normalization in :class:`ArgumentByElement`, then following, although equal, is not equal:: - sage: C(I) == C(2*I) + sage: C(I) == C(2*I) # needs sage.symbolic False """ return self._element_ == other._element_ @@ -256,12 +256,12 @@ def _act_on_(self, other, is_left): :: sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup - sage: C = ArgumentByElementGroup(SR) - sage: C(-1) * 4 + sage: C = ArgumentByElementGroup(SR) # needs sage.symbolic + sage: C(-1) * 4 # needs sage.symbolic -4 sage: _.parent() Symbolic Ring - sage: 4 * C(-1) + sage: 4 * C(-1) # needs sage.symbolic -4 sage: _.parent() Symbolic Ring @@ -704,10 +704,10 @@ def _element_constructor_(self, data, exponent=None, **kwds): sage: U(exponent=1/3) zeta3 - sage: C. = CyclotomicField(6) - sage: z, U(z) + sage: C. = CyclotomicField(6) # needs sage.rings.number_field + sage: z, U(z) # needs sage.rings.number_field (z, zeta6) - sage: z^2, U(z^2) + sage: z^2, U(z^2) # needs sage.rings.number_field (z - 1, zeta3) sage: U(ZZ(-1)) @@ -805,12 +805,12 @@ def _create_element_in_extension_(self, exponent): sage: from sage.groups.misc_gps.argument_groups import UnitCircleGroup, RootsOfUnityGroup sage: C = UnitCircleGroup(QQ) - sage: C._create_element_in_extension_(2.12).parent() + sage: C._create_element_in_extension_(2.12).parent() # needs sage.rings.number_field Unit Circle Group with Exponents in Real Field with 53 bits of precision modulo ZZ sage: U = RootsOfUnityGroup() - sage: U._create_element_in_extension_(2.12).parent() + sage: U._create_element_in_extension_(2.12).parent() # needs sage.rings.number_field Unit Circle Group with Exponents in Real Field with 53 bits of precision modulo ZZ """ @@ -1070,7 +1070,7 @@ def __init__(self, parent, element, normalize=True): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: C(1+2*I) # indirect doctest + sage: C(1+2*I) # indirect doctest # needs sage.symbolic e^(I*arg(1.00000000000000 + 2.00000000000000*I)) """ super().__init__(parent, element, normalize=normalize) @@ -1108,7 +1108,7 @@ def _repr_(self): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: C(2+3*I) # indirect doctest + sage: C(2+3*I) # indirect doctest # needs sage.symbolic e^(I*arg(2.00000000000000 + 3.00000000000000*I)) """ return 'e^(I*arg({}))'.format(self._element_) @@ -1131,7 +1131,7 @@ def _symbolic_(self, R=None): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(ZZ) - sage: C(-2)._symbolic_() + sage: C(-2)._symbolic_() # needs sage.symbolic -1 sage: _.parent() Symbolic Ring @@ -1153,7 +1153,7 @@ def _mul_(self, other): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: C(I) * C(1 + I) # indirect doctest + sage: C(I) * C(1 + I) # indirect doctest # needs sage.symbolic e^(I*arg(-1.00000000000000 + 1.00000000000000*I)) """ P = self.parent() @@ -1168,12 +1168,12 @@ def __pow__(self, exponent): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: C(I)^5 # indirect doctest + sage: C(I)^5 # indirect doctest # needs sage.symbolic e^(I*arg(1.00000000000000*I)) sage: _.parent() Unit Circle Group with Argument of Elements in Complex Field with 53 bits of precision - sage: C(1+I)^3 # indirect doctest + sage: C(1+I)^3 # indirect doctest # needs sage.symbolic e^(I*arg(-2.00000000000000 + 2.00000000000000*I)) sage: _.parent() Unit Circle Group with Argument of Elements in @@ -1208,7 +1208,7 @@ def __invert__(self): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: ~C(I) # indirect doctest + sage: ~C(I) # indirect doctest # needs sage.symbolic e^(I*arg(-1.00000000000000*I)) """ P = self.parent() @@ -1233,7 +1233,7 @@ class ArgumentByElementGroup(AbstractArgumentGroup): sage: C = ArgumentByElementGroup(CC); C Unit Circle Group with Argument of Elements in Complex Field with 53 bits of precision - sage: C(1 + 2*I) + sage: C(1 + 2*I) # needs sage.symbolic e^(I*arg(1.00000000000000 + 2.00000000000000*I)) """ @@ -1283,7 +1283,7 @@ def _element_constructor_(self, data, **kwds): sage: from sage.groups.misc_gps.argument_groups import ArgumentByElementGroup sage: C = ArgumentByElementGroup(CC) - sage: C(1 + 2*I) # indirect doctest + sage: C(1 + 2*I) # indirect doctest # needs sage.symbolic e^(I*arg(1.00000000000000 + 2.00000000000000*I)) sage: C(1) e^(I*arg(1.00000000000000)) @@ -1545,7 +1545,7 @@ def _act_on_(self, other, is_left): -4.00000000000000 sage: _.parent() Complex Field with 53 bits of precision - sage: S(-1) * SR.var('x') + sage: S(-1) * SR.var('x') # needs sage.symbolic -x sage: _.parent() Symbolic Ring @@ -1760,9 +1760,10 @@ class ArgumentGroupFactory(UniqueFactory): sage: from sage.groups.misc_gps.argument_groups import ArgumentGroup - sage: ArgumentGroup('UU') + sage: ArgumentGroup('UU') # needs sage.rings.number_field Group of Roots of Unity + sage: # needs sage.rings.number_field sage: ArgumentGroup(ZZ) Sign Group sage: ArgumentGroup(QQ) @@ -1772,19 +1773,19 @@ class ArgumentGroupFactory(UniqueFactory): sage: ArgumentGroup(AA) Sign Group - sage: ArgumentGroup(RR) + sage: ArgumentGroup(RR) # needs sage.rings.number_field Sign Group - sage: ArgumentGroup('Arg_RR') + sage: ArgumentGroup('Arg_RR') # needs sage.rings.number_field Sign Group - sage: ArgumentGroup(RIF) + sage: ArgumentGroup(RIF) # needs sage.rings.real_interval_field Sign Group sage: ArgumentGroup(RBF) Sign Group - sage: ArgumentGroup(CC) + sage: ArgumentGroup(CC) # needs sage.rings.number_field Unit Circle Group with Exponents in Real Field with 53 bits of precision modulo ZZ - sage: ArgumentGroup('Arg_CC') + sage: ArgumentGroup('Arg_CC') # needs sage.rings.number_field Unit Circle Group with Exponents in Real Field with 53 bits of precision modulo ZZ sage: ArgumentGroup(CIF) @@ -1794,7 +1795,7 @@ class ArgumentGroupFactory(UniqueFactory): Unit Circle Group with Exponents in Real ball field with 53 bits of precision modulo ZZ - sage: ArgumentGroup(CyclotomicField(3)) + sage: ArgumentGroup(CyclotomicField(3)) # needs sage.rings.number_field Unit Circle Group with Argument of Elements in Cyclotomic Field of order 3 and degree 2 """ @@ -1813,6 +1814,7 @@ def create_key_and_extra_args(self, sage: from sage.groups.misc_gps.argument_groups import ArgumentGroup + sage: # needs sage.rings.number_field sage: ArgumentGroup(specification='UU') Group of Roots of Unity sage: ArgumentGroup('UU') is ArgumentGroup(exponents=QQ) # indirect doctest @@ -1887,7 +1889,7 @@ def create_object(self, version, key, **kwds): TESTS:: sage: from sage.groups.misc_gps.argument_groups import ArgumentGroup - sage: ArgumentGroup('UU') # indirect doctest + sage: ArgumentGroup('UU') # indirect doctest # needs sage.rings.number_field Group of Roots of Unity """ cls, args = key diff --git a/src/sage/groups/misc_gps/imaginary_groups.py b/src/sage/groups/misc_gps/imaginary_groups.py index ff2d34ddade..41fe79f9959 100644 --- a/src/sage/groups/misc_gps/imaginary_groups.py +++ b/src/sage/groups/misc_gps/imaginary_groups.py @@ -81,9 +81,9 @@ def imag(self): sage: from sage.groups.misc_gps.imaginary_groups import ImaginaryGroup sage: J = ImaginaryGroup(ZZ) - sage: J(I).imag() + sage: J(I).imag() # needs sage.symbolic 1 - sage: imag_part(J(I)) # indirect doctest + sage: imag_part(J(I)) # indirect doctest # needs sage.symbolic 1 """ return self._imag_ @@ -96,9 +96,9 @@ def real(self): sage: from sage.groups.misc_gps.imaginary_groups import ImaginaryGroup sage: J = ImaginaryGroup(ZZ) - sage: J(I).real() + sage: J(I).real() # needs sage.symbolic 0 - sage: real_part(J(I)) # indirect doctest + sage: real_part(J(I)) # indirect doctest # needs sage.symbolic 0 """ return self.parent().base().zero() @@ -111,7 +111,7 @@ def __hash__(self): sage: from sage.groups.misc_gps.imaginary_groups import ImaginaryGroup sage: J = ImaginaryGroup(ZZ) - sage: hash(J(I)) # indirect doctest, random + sage: hash(J(I)) # indirect doctest, random # needs sage.symbolic 42 """ return hash((self.parent(), self._imag_)) @@ -247,9 +247,9 @@ class ImaginaryGroup(UniqueRepresentation, Parent): 0 sage: J(imag=100) 100*I - sage: J(3*I) + sage: J(3*I) # needs sage.symbolic 3*I - sage: J(1+2*I) + sage: J(1 + 2*I) # needs sage.symbolic Traceback (most recent call last): ... ValueError: 2*I + 1 is not in @@ -393,6 +393,7 @@ def _element_constructor_(self, data, imag=None): sage: J(imag=100) 100*I + sage: # needs sage.symbolic sage: J(3*I) 3*I sage: J(1+2*I) diff --git a/src/sage/groups/old.pyx b/src/sage/groups/old.pyx index 92b69af07db..761034cff65 100644 --- a/src/sage/groups/old.pyx +++ b/src/sage/groups/old.pyx @@ -47,6 +47,7 @@ cdef class Group(sage.structure.parent.Parent): Check for :trac:`8119`:: + sage: # needs sage.groups sage: G = SymmetricGroup(2) sage: h = hash(G) sage: G.rename('S2') @@ -120,7 +121,7 @@ cdef class Group(sage.structure.parent.Parent): EXAMPLES:: - sage: SL(2, 7).is_commutative() + sage: SL(2, 7).is_commutative() # needs sage.libs.gap sage.modules False """ return self.is_abelian() diff --git a/src/sage/groups/pari_group.py b/src/sage/groups/pari_group.py index c54cd4885df..bbcb1c0a6c9 100644 --- a/src/sage/groups/pari_group.py +++ b/src/sage/groups/pari_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.pari r""" PARI Groups diff --git a/src/sage/groups/perm_gps/constructor.py b/src/sage/groups/perm_gps/constructor.py index 73dc5f94c41..5a130eb19be 100644 --- a/src/sage/groups/perm_gps/constructor.py +++ b/src/sage/groups/perm_gps/constructor.py @@ -23,10 +23,15 @@ from sage.misc.sage_eval import sage_eval from sage.misc.lazy_import import lazy_import from sage.interfaces.gap import GapElement -from sage.libs.pari.all import pari_gen from sage.libs.gap.element import GapElement_Permutation + lazy_import('sage.combinat.permutation', ['Permutation', 'from_cycles']) +try: + from sage.libs.pari.all import pari_gen +except ImportError: + pari_gen = () + def PermutationGroupElement(g, parent=None, check=True): r""" @@ -156,8 +161,8 @@ def standardize_generator(g, convert_dict=None, as_cycles=False): INPUT: - - ``g`` -- a list, tuple, string, GapElement, - PermutationGroupElement, Permutation + - ``g`` -- a :class:`list`, :class:`tuple`, :class:`string`, :class:`GapElement`, + :class:`PermutationGroupElement`, or :class:`Permutation` - ``convert_dict`` -- (optional) a dictionary used to convert the points to a number compatible with GAP diff --git a/src/sage/groups/perm_gps/cubegroup.py b/src/sage/groups/perm_gps/cubegroup.py index e23d072de58..128d3beb480 100644 --- a/src/sage/groups/perm_gps/cubegroup.py +++ b/src/sage/groups/perm_gps/cubegroup.py @@ -191,7 +191,8 @@ def polygon_plot3d(points, tilt=30, turn=30, **kwargs): EXAMPLES:: sage: from sage.groups.perm_gps.cubegroup import polygon_plot3d,green - sage: P = polygon_plot3d([[1,3,1],[2,3,1],[2,3,2],[1,3,2],[1,3,1]],rgbcolor=green) + sage: P = polygon_plot3d([[1,3,1],[2,3,1],[2,3,2],[1,3,2],[1,3,1]], # needs sage.plot + ....: rgbcolor=green) """ rot = rotation_list(tilt, turn) points2 = [(xproj(x, y, z, rot), yproj(x, y, z, rot)) @@ -288,13 +289,14 @@ def create_poly(face, color): EXAMPLES:: sage: from sage.groups.perm_gps.cubegroup import create_poly, red - sage: create_poly('ur', red) + sage: create_poly('ur', red) # needs sage.plot Graphics object consisting of 1 graphics primitive """ return polygon(face_polys[face], rgbcolor=color) #################################################### + singmaster_indices = { 1: "ulb", 2: "ub", @@ -491,7 +493,7 @@ def plot3d_cubie(cnt, clrs): sage: from sage.groups.perm_gps.cubegroup import plot3d_cubie, blue, red, green sage: clrF = blue; clrU = red; clrR = green - sage: P = plot3d_cubie([1/2,1/2,1/2],[clrF,clrU,clrR]) + sage: P = plot3d_cubie([1/2,1/2,1/2],[clrF,clrU,clrR]) # needs sage.plot """ half = QQ((1, 2)) x = cnt[0] - half @@ -954,11 +956,11 @@ def plot_cube(self, mv, title=True, colors=[lpurple, yellow, red, green, orange, EXAMPLES:: sage: rubik = CubeGroup() - sage: P = rubik.plot_cube("R^2*U^2*R^2*U^2*R^2*U^2", title = False) + sage: P = rubik.plot_cube("R^2*U^2*R^2*U^2*R^2*U^2", title=False) # needs sage.plot sage: # (R^2U^2)^3 permutes 2 pairs of edges (uf,ub)(fr,br) - sage: P = rubik.plot_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") + sage: P = rubik.plot_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") # needs sage.plot sage: # the superflip (in 20f* moves) - sage: P = rubik.plot_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") + sage: P = rubik.plot_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") # needs sage.plot sage: # "superflip+4 spot" (in 26q* moves) """ g = self.parse(mv) @@ -991,8 +993,8 @@ def plot3d_cube(self, mv, title=True): EXAMPLES:: sage: rubik = CubeGroup() - sage: P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") - sage: P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") + sage: P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") # needs sage.plot + sage: P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") # needs sage.plot """ g = self.parse(mv) state = self.facets(g) @@ -1180,6 +1182,7 @@ def cubie_faces(): return cubies + cubie_face_list = cubie_faces() @@ -1194,7 +1197,7 @@ class RubiksCube(SageObject): EXAMPLES:: sage: C = RubiksCube().move("R U R'") - sage: C.show3d() + sage: C.show3d() # needs sage.plot :: @@ -1212,7 +1215,7 @@ class RubiksCube(SageObject): | 37 bottom 21 | | 35 47 24 | +--------------+ - sage: C.show() + sage: C.show() # needs sage.plot sage: C.solve(algorithm='gap') # long time 'L*R' sage: C == RubiksCube("L*R") @@ -1315,7 +1318,7 @@ def plot(self): EXAMPLES:: sage: C = RubiksCube("R*U") - sage: C.plot() + sage: C.plot() # needs sage.plot Graphics object consisting of 55 graphics primitives """ return self._group.plot_cube(self._state) @@ -1327,7 +1330,7 @@ def show(self): EXAMPLES:: sage: C = RubiksCube("R*U") - sage: C.show() + sage: C.show() # needs sage.plot """ self.plot().show() @@ -1346,7 +1349,7 @@ def cubie(self, size, gap, x, y, z, colors, stickers=True): EXAMPLES:: sage: C = RubiksCube("R*U") - sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3) + sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3) # needs sage.plot Graphics3d Object """ sides = cubie_face_list[x,y,z] @@ -1366,7 +1369,7 @@ def plot3d(self, stickers=True): EXAMPLES:: sage: C = RubiksCube("R*U") - sage: C.plot3d() + sage: C.plot3d() # needs sage.plot Graphics3d Object """ while len(self.colors) < 7: @@ -1389,7 +1392,7 @@ def show3d(self): EXAMPLES:: sage: C = RubiksCube("R*U") - sage: C.show3d() + sage: C.show3d() # needs sage.plot """ return self.plot3d().show() 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 d174874194f..04d978afef3 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 @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups r""" Automorphism groups and canonical labels @@ -282,8 +283,8 @@ def coset_rep(list perm=[0,1,2,3,4,5], list gens=[[1,2,3,4,5,0]]): output = get_aut_gp_and_can_lab( perm, part, n, &all_children_are_equivalent_trivial, &refine_and_return_invariant_trivial, &compare_perms, 1, group, NULL, NULL) SC_order(output.group, 0, I.value) assert I == 1 - r_inv = list(xrange(n)) - for i from 0 <= i < n: + r_inv = list(range(n)) + for i in range(n): r_inv[output.relabeling[i]] = i label = [perm[r_inv[i]] for i in range(n)] PS_dealloc(part) 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 b6567fb3dc9..c3b87a3bc1f 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx +++ b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx @@ -73,7 +73,7 @@ cdef OP_string(OrbitPartition *OP): """ cdef i,j s = "" - for i from 0 <= i < OP.degree: + for i in range(OP.degree): s += " " j = OP_find(OP, i) s += "%d -> %d"%(i, j) @@ -133,7 +133,7 @@ def OP_represent(int n, merges, perm): print("Allocation passed.") print("Checking that each element reports itself as its root.") good = True - for i from 0 <= i < n: + for i in range(n): if not OP_find(OP, i) == i: print("Failed at i = %d!" % i) good = False @@ -145,7 +145,7 @@ def OP_represent(int n, merges, perm): print("Merged %d and %d." % (i, j)) print("Done merging.") print("Finding:") - for i from 0 <= i < n: + for i in range(n): j = OP_find(OP, i) s = "%d -> %d"%(i, j) if i == j: @@ -159,13 +159,13 @@ def OP_represent(int n, merges, perm): OP_dealloc(OP) return print("Allocation passed.") - for i from 0 <= i < n: + for i in range(n): gamma[i] = perm[i] print("Merging permutation: %s" % perm) OP_merge_list_perm(OP, gamma) print("Done merging.") print("Finding:") - for i from 0 <= i < n: + for i in range(n): j = OP_find(OP, i) s = "%d -> %d"%(i, j) if i == j: @@ -207,7 +207,7 @@ cdef void PS_unit_partition(PartitionStack *PS): """ cdef int i, n = PS.degree PS.depth = 0 - for i from 0 <= i < n-1: + for i in range(n - 1): PS.entries[i] = i PS.levels[i] = n PS.entries[n-1] = n-1 @@ -243,14 +243,14 @@ cdef PartitionStack *PS_from_list(list L): null pointer in the case of an allocation failure. """ cdef int cell, i, num_cells = len(L), cur_start = 0, cur_len, n = 0 - for cell from 0 <= cell < num_cells: + for cell in range(num_cells): n += len(L[cell]) cdef PartitionStack *PS = PS_new(n, 0) if PS is NULL: return NULL - for cell from 0 <= cell < num_cells: + for cell in range(num_cells): cur_len = len(L[cell]) - for i from 0 <= i < cur_len: + for i in range(cur_len): PS.entries[cur_start + i] = L[cell][i] PS.levels[cur_start + i] = n PS_move_min_to_front(PS, cur_start, cur_start+cur_len-1) @@ -267,7 +267,7 @@ cdef PS_print(PartitionStack *PS): Print a visual representation of PS. """ cdef int i - for i from 0 <= i <= PS.depth: + for i in range(PS.depth + 1): PS_print_partition(PS, i) cdef PS_print_partition(PartitionStack *PS, int k): @@ -275,7 +275,7 @@ cdef PS_print_partition(PartitionStack *PS, int k): Print the partition at depth k. """ s = '(' - for i from 0 <= i < PS.degree: + for i in range(PS.degree): s += str(PS.entries[i]) if PS.levels[i] <= k: s += '|' @@ -340,7 +340,7 @@ cdef int PS_all_new_cells(PartitionStack *PS, bitset_t** nonsingletons_ptr): if end != n: if PS.levels[end] == PS.depth: bitset_zero(scratch) - for i from beg <= i <= end: + for i in range(beg, end + 1): bitset_set(scratch, PS.entries[i]) count +=1 nonsingletons = sig_realloc(nonsingletons, count * sizeof(bitset_t)) @@ -368,7 +368,7 @@ cdef int PS_find_element(PartitionStack *PS, bitset_t b, int x) except -1: """ cdef int i, location, n = PS.degree bitset_zero(b) - for i from 0 <= i < n: + for i in range(n): if PS.entries[i] == x: location = i break @@ -472,7 +472,7 @@ def PS_represent(partition, splits): PS_print(PS) print("Checking that entries are in order and correct level.") good = True - for i from 0 <= i < n-1: + for i in range(n - 1): if not (PS.entries[i] == i and PS.levels[i] == n): print("Failed at i = %d!" % i) print(PS.entries[i], PS.levels[i], i, n) @@ -487,11 +487,11 @@ def PS_represent(partition, splits): print("Everything seems in order, deallocating.") PS_dealloc(PS) print("Deallocated.") - print("Creating PartitionStack from partition %s."%partition) + print("Creating PartitionStack from partition %s." % partition) PS = PS_from_list(partition) print("PartitionStack's data:") - print("entries -> %s"%[PS.entries[i] for i from 0 <= i < n]) - print("levels -> %s"%[PS.levels[i] for i from 0 <= i < n]) + print("entries -> %s"%[PS.entries[i] for i in range(n)]) + print("levels -> %s"%[PS.levels[i] for i in range(n)]) print("depth = %d, degree = %d" % (PS.depth,PS.degree)) PS_print(PS) print("Checking PS_is_discrete:") @@ -499,7 +499,7 @@ def PS_represent(partition, splits): print("Checking PS_num_cells:") print(PS_num_cells(PS)) print("Checking PS_is_mcr, min cell reps are:") - L = [PS.entries[i] for i from 0 <= i < n if PS_is_mcr(PS, i)] + L = [PS.entries[i] for i in range(n) if PS_is_mcr(PS, i)] print(L) print("Checking PS_is_fixed, fixed elements are:") print([PS.entries[l] for l in L if PS_is_fixed(PS, l)]) @@ -508,7 +508,7 @@ def PS_represent(partition, splits): PS_print(PS2) print("Checking for consistency.") good = True - for i from 0 <= i < n: + for i in range(n): if PS.entries[i] != PS2.entries[i] or PS.levels[i] != PS2.levels[i]: print("Failed at i = %d!"%i) good = False @@ -527,7 +527,7 @@ def PS_represent(partition, splits): print("Getting permutation from PS2->PS:") gamma = sig_malloc(n * sizeof(int)) PS_get_perm_from(PS, PS2, gamma) - print([gamma[i] for i from 0 <= i < n]) + print([gamma[i] for i in range(n)]) sig_free(gamma) print("Finding first smallest:") bitset_init(b, n) @@ -609,7 +609,7 @@ cdef StabilizerChain *SC_new(int n, bint init_gens=True): SC.base_orbits = int_ptrs + 2*n SC.parents = int_ptrs + 3*n SC.labels = int_ptrs + 4*n - for i from 0 <= i < n: + for i in range(n): SC.base_orbits[i] = int_array SC.parents[i] = int_array + n SC.labels[i] = int_array + 2*n @@ -617,7 +617,7 @@ cdef StabilizerChain *SC_new(int n, bint init_gens=True): # second level allocations if init_gens: - for i from 0 <= i < n: + for i in range(n): SC.array_size[i] = default_num_gens SC.generators[i] = sig_malloc( default_num_gens*n * sizeof(int) ) SC.gen_inverses[i] = sig_malloc( default_num_gens*n * sizeof(int) ) @@ -654,7 +654,7 @@ cdef inline void SC_dealloc(StabilizerChain *SC): if SC is not NULL: n = SC.degree if SC.generators is not NULL: - for i from 0 <= i < n: + for i in range(n): sig_free(SC.generators[i]) sig_free(SC.gen_inverses[i]) sig_free(SC.generators) # frees int_ptrs @@ -675,29 +675,29 @@ cdef StabilizerChain *SC_symmetric_group(int n): if SC is NULL: return NULL SC.base_size = n-1 - for i from 0 <= i < n-1: + for i in range(n - 1): SC.array_size[i] = n-i-1 SC.array_size[n-1] = default_num_gens - for i from 0 <= i < n: + for i in range(n): SC.generators[i] = sig_malloc( SC.array_size[i]*n * sizeof(int) ) SC.gen_inverses[i] = sig_malloc( SC.array_size[i]*n * sizeof(int) ) if SC.generators[i] is NULL or SC.gen_inverses[i] is NULL: SC_dealloc(SC) return NULL cdef int *id_perm = SC.perm_scratch - for i from 0 <= i < n: + for i in range(n): id_perm[i] = i - for i from 0 <= i < n-1: + for i in range(n - 1): b = i SC.orbit_sizes[i] = n-i SC.num_gens[i] = n-i-1 - for j from 0 <= j < i: + for j in range(i): SC.parents[i][j] = -1 - for j from 0 <= j < n-i: + for j in range(n - i): SC.base_orbits[i][j] = i+j SC.parents[i][i+j] = b SC.labels[i][i+j] = j - for j from 0 <= j < n-i-1: + for j in range(n - i - 1): #j-th generator sends i+j+1 to b memcpy(SC.generators[i] + n*j, id_perm, n * sizeof(int) ) SC.generators[i][n*j + i+j+1] = b @@ -716,31 +716,31 @@ cdef StabilizerChain *SC_alternating_group(int n): if SC is NULL: return NULL SC.base_size = n-2 - for i from 0 <= i < n-2: + for i in range(n - 2): SC.array_size[i] = n-i-1 SC.array_size[n-2] = default_num_gens SC.array_size[n-1] = default_num_gens - for i from 0 <= i < n: + for i in range(n): SC.generators[i] = sig_malloc( SC.array_size[i]*n * sizeof(int) ) SC.gen_inverses[i] = sig_malloc( SC.array_size[i]*n * sizeof(int) ) if SC.generators[i] is NULL or SC.gen_inverses[i] is NULL: SC_dealloc(SC) return NULL cdef int *id_perm = SC.perm_scratch - for i from 0 <= i < n: + for i in range(n): id_perm[i] = i - for i from 0 <= i < n-2: + for i in range(n - 2): b = i SC.orbit_sizes[i] = n-i SC.num_gens[i] = n-i-2 - for j from 0 <= j < i: + for j in range(i): SC.parents[i][j] = -1 - for j from 0 <= j < n-i: + for j in range(n - i): SC.base_orbits[i][j] = i+j SC.parents[i][i+j] = b SC.labels[i][i+j] = j SC.labels[i][n-1] = -(n-i-2) - for j from 0 <= j < n-i-2: + for j in range(n - i - 2): #j-th generator sends i+j+1 to b, i+j+2 to i+j+1, and b to i+j+2 memcpy(SC.generators[i] + n*j, id_perm, n * sizeof(int) ) SC.generators[i][n*j + i+j+1] = b @@ -795,14 +795,14 @@ cdef StabilizerChain *SC_copy(StabilizerChain *SC, int level): if SCC is NULL: return NULL level = min(level, SC.base_size) - for i from 0 <= i < level: + for i in range(level): SCC.generators[i] = sig_malloc( SC.array_size[i]*n * sizeof(int) ) SCC.gen_inverses[i] = sig_malloc( SC.array_size[i]*n * sizeof(int) ) if SCC.generators[i] is NULL or SCC.gen_inverses[i] is NULL: SC_dealloc(SCC) return NULL SCC.array_size[i] = SC.array_size[i] - for i from level <= i < n: + for i in range(level, n): SCC.generators[i] = sig_malloc( default_num_gens*n * sizeof(int) ) SCC.gen_inverses[i] = sig_malloc( default_num_gens*n * sizeof(int) ) if SCC.generators[i] is NULL or SCC.gen_inverses[i] is NULL: @@ -818,11 +818,11 @@ cdef int SC_copy_nomalloc(StabilizerChain *SC_dest, StabilizerChain *SC, int lev SC_dest.base_size = level memcpy(SC_dest.orbit_sizes, SC.orbit_sizes, 2*n * sizeof(int) ) # copies orbit_sizes, num_gens memcpy(SC_dest.base_orbits[0], SC.base_orbits[0], 3*n*n * sizeof(int) ) # copies base_orbits, parents, labels - for i from 0 <= i < level: + for i in range(level): if SC.num_gens[i] > SC_dest.array_size[i]: if SC_realloc_gens(SC_dest, i, max(SC.num_gens[i], 2*SC_dest.array_size[i])): return 1 - memcpy(SC_dest.generators[i], SC.generators[i], SC.num_gens[i]*n * sizeof(int) ) + memcpy(SC_dest.generators[i], SC.generators[i], SC.num_gens[i]*n * sizeof(int) ) memcpy(SC_dest.gen_inverses[i], SC.gen_inverses[i], SC.num_gens[i]*n * sizeof(int) ) return 0 @@ -830,12 +830,17 @@ cdef SC_print_level(StabilizerChain *SC, int level): cdef int i, j, n = SC.degree if level < SC.base_size: print('/ level {}'.format(level)) - print('| orbit {}'.format([SC.base_orbits[level][i] for i from 0 <= i < SC.orbit_sizes[level]])) - print('| parents {}'.format([SC.parents [level][i] for i from 0 <= i < n])) - print('| labels {}'.format([SC.labels [level][i] for i from 0 <= i < n])) + print('| orbit {}'.format([SC.base_orbits[level][i] + for i in range(SC.orbit_sizes[level])])) + print('| parents {}'.format([SC.parents[level][i] for i in range(n)])) + print('| labels {}'.format([SC.labels[level][i] for i in range(n)])) print('|') - print('| generators {}'.format([[SC.generators [level][n*i + j] for j from 0 <= j < n] for i from 0 <= i < SC.num_gens[level]])) - print(r'\ inverses {}'.format([[SC.gen_inverses[level][n*i + j] for j from 0 <= j < n] for i from 0 <= i < SC.num_gens[level]])) + print('| generators {}'.format([[SC.generators[level][n*i + j] + for j in range(n)] + for i in range(SC.num_gens[level])])) + print(r'\ inverses {}'.format([[SC.gen_inverses[level][n*i + j] + for j in range(n)] + for i in range(SC.num_gens[level])])) else: print('/ level {}'.format(level)) print('|') @@ -863,7 +868,7 @@ cdef StabilizerChain *SC_new_base(StabilizerChain *SC, int *base, int base_len): cdef int SC_new_base_nomalloc(StabilizerChain *SC_dest, StabilizerChain *SC, int *base, int base_len): cdef int i, n = SC.degree SC_dest.base_size = 0 - for i from 0 <= i < base_len: + for i in range(base_len): SC_add_base_point(SC_dest, base[i]) if SC_update(SC_dest, SC, 0): SC_dealloc(SC_dest) @@ -887,14 +892,14 @@ cdef int SC_update(StabilizerChain *dest, StabilizerChain *source, int level): break i += 1 else: - for b from 0 <= b < dest.degree: + for b in range(dest.degree): if perm[b] != b: break else: continue SC_add_base_point(dest, b) first_moved = i - for i from level <= i <= first_moved: + for i in range(level, first_moved + 1): if SC_insert_and_sift(dest, i, perm, 1, 0): # don't sift! mpz_clear(dst_order) mpz_clear(src_order) @@ -922,7 +927,7 @@ cdef StabilizerChain *SC_insert_base_point(StabilizerChain *SC, int level, int p if NEW is NULL: return NULL SC_add_base_point(NEW, p) - for i from level <= i < SC.base_size: + for i in range(level, SC.base_size): b = SC.base_orbits[i][0] if b != p: SC_add_base_point(NEW, b) @@ -935,7 +940,7 @@ cdef int SC_insert_base_point_nomalloc(StabilizerChain *SC_dest, StabilizerChain cdef int i, b, n = SC.degree SC_copy_nomalloc(SC_dest, SC, level) SC_add_base_point(SC_dest, p) - for i from level <= i < SC.base_size: + for i in range(level, SC.base_size): b = SC.base_orbits[i][0] if b != p: SC_add_base_point(SC_dest, b) @@ -957,7 +962,7 @@ cdef int SC_re_tree(StabilizerChain *SC, int level, int *perm, int x): if SC.array_size[level] == SC.num_gens[level]: if SC_realloc_gens(SC, level, 2*SC.array_size[level]): return 1 - cdef int *new_gen = SC.generators [level] + n*SC.num_gens[level] + cdef int *new_gen = SC.generators[level] + n*SC.num_gens[level] cdef int *new_gen_inv = SC.gen_inverses[level] + n*SC.num_gens[level] # new generator is perm^(-1) * (path from x to base) (left to right composition) @@ -968,7 +973,7 @@ cdef int SC_re_tree(StabilizerChain *SC, int level, int *perm, int x): # now that we have our generators, regenerate the tree, breadth-first b = SC.base_orbits[level][0] - for i from 0 <= i < n: + for i in range(n): SC.parents[level][i] = -1 SC.parents[level][b] = b i = 0 @@ -979,7 +984,7 @@ cdef int SC_re_tree(StabilizerChain *SC, int level, int *perm, int x): gen_inv = SC.gen_inverses[level] + n*gen_index SC_scan(SC, level, x, gen_index, gen_inv, 1) for gen_index from 0 <= gen_index < SC.num_gens[level]: - gen = SC.generators [level] + n*gen_index + gen = SC.generators[level] + n*gen_index SC_scan(SC, level, x, gen_index, gen, -1) i += 1 return 0 @@ -1224,6 +1229,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, TESTS:: + sage: # needs sage.groups sage: from sage.groups.perm_gps.partn_ref.data_structures import SC_test_list_perms sage: limit = 10^7 sage: def test_Sn_on_m_points(n, m, gap, contains): @@ -1234,7 +1240,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: test_Sn_on_m_points(i,i,1,0) sage: for i in range(2,9): ....: test_Sn_on_m_points(i,i,0,1) - sage: for i in range(2,9): # long time + sage: for i in range(2,9): # long time ....: test_Sn_on_m_points(i,i,1,1) sage: test_Sn_on_m_points(8,8,1,1) sage: def test_stab_chain_fns_1(n, gap, contains): @@ -1258,7 +1264,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: test_stab_chain_fns_2(n, 1, 0) sage: for n in range(2,11): ....: test_stab_chain_fns_2(n, 0, 1) - sage: for n in range(2,11): # long time + sage: for n in range(2,11): # long time ....: test_stab_chain_fns_2(n, 1, 1) sage: test_stab_chain_fns_2(11, 1, 1) sage: def test_stab_chain_fns_3(n, gap, contains): @@ -1269,7 +1275,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: test_stab_chain_fns_3(n, 1, 0) sage: for n in range(2,20): ....: test_stab_chain_fns_3(n, 0, 1) - sage: for n in range(2,14): # long time + sage: for n in range(2,14): # long time ....: test_stab_chain_fns_3(n, 1, 1) sage: test_stab_chain_fns_3(20, 1, 1) sage: def test_stab_chain_fns_4(n, g, gap, contains): @@ -1279,19 +1285,19 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: shuffle(perm) ....: perms.append(perm) ....: SC_test_list_perms(perms, n, limit, gap, 0, contains) - sage: for n in range(4,9): # long time + sage: for n in range(4,9): # long time ....: test_stab_chain_fns_4(n, 1, 1, 0) ....: test_stab_chain_fns_4(n, 2, 1, 0) ....: test_stab_chain_fns_4(n, 2, 1, 0) ....: test_stab_chain_fns_4(n, 2, 1, 0) ....: test_stab_chain_fns_4(n, 2, 1, 0) ....: test_stab_chain_fns_4(n, 3, 1, 0) - sage: for n in range(4,9): # not tested, known bug (see :trac:`32187`) + sage: for n in range(4,9): # known bug (see :trac:`32187`), not tested ....: test_stab_chain_fns_4(n, 1, 0, 1) ....: for j in range(6): ....: test_stab_chain_fns_4(n, 2, 0, 1) ....: test_stab_chain_fns_4(n, 3, 0, 1) - sage: for n in range(4,8): # long time + sage: for n in range(4,8): # long time ....: test_stab_chain_fns_4(n, 1, 1, 1) ....: test_stab_chain_fns_4(n, 2, 1, 1) ....: test_stab_chain_fns_4(n, 2, 1, 1) @@ -1307,12 +1313,12 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: shuffle(perm2) ....: perm2 = list(range(m)) + perm2 ....: SC_test_list_perms([perm1, perm2], n, limit, gap, 0, contains) - sage: for n in [4..9]: # long time + sage: for n in [4..9]: # long time ....: for _ in range(2): ....: test_stab_chain_fns_5(n, 1, 0) - sage: for n in [4..8]: # long time + sage: for n in [4..8]: # long time ....: test_stab_chain_fns_5(n, 0, 1) - sage: for n in [4..9]: # long time + sage: for n in [4..9]: # long time ....: test_stab_chain_fns_5(n, 1, 1) sage: def random_perm(x): ....: shuffle(x) @@ -1323,7 +1329,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: perm = sum([random_perm(list(range(i*(n//m),min(n,(i+1)*(n//m))))) for i in range(m)], []) ....: perms.append(perm) ....: SC_test_list_perms(perms, m*(n//m), limit, gap, 0, contains) - sage: for m in range(2,9): # long time + sage: for m in range(2,9): # long time ....: for n in range(m,3*m): ....: for k in range(1,3): ....: test_stab_chain_fns_6(m,n,k, 1, 0) @@ -1353,7 +1359,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, sage: for n in [6..30]: ....: test_stab_chain_fns_7(n, 1, 0, 1) ....: test_stab_chain_fns_7(n, 0, 0, 1) - sage: for n in [6..14]: # long time + sage: for n in [6..14]: # long time ....: test_stab_chain_fns_7(n, 1, 1, 1) ....: test_stab_chain_fns_7(n, 0, 1, 1) sage: test_stab_chain_fns_7(20, 1, 1, 1) @@ -1570,7 +1576,7 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, print('element {}'.format(permy)) print('GAP says it is an element, SC_contains(modify=1) does not') raise AssertionError - permy = list(xrange(1, n + 1)) + permy = list(range(1, n + 1)) shuffle(permy) gap_says = (PermutationGroupElement(permy) in G) for j from 0 <= j < n: 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 56a97f6ece4..e3c7bc75f05 100644 --- a/src/sage/groups/perm_gps/partn_ref/double_coset.pyx +++ b/src/sage/groups/perm_gps/partn_ref/double_coset.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups r""" Double cosets 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 3616decd7e4..56e4a062d02 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.modules sage.rings.finite_rings """ Partition backtrack functions for binary codes 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 17ddfce42db..5046a718853 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx @@ -87,7 +87,7 @@ def isomorphic(G1, G2, partn, ordering2, dig, use_indicator_function, sparse=Fal n = G_in.num_verts() elif n != G_in.num_verts(): return False - if G_in.vertices(sort=True) != list(xrange(n)): + if G_in.vertices(sort=True) != list(range(n)): G_in = copy(G_in) to = G_in.relabel(return_map=True) frm = {} @@ -98,7 +98,7 @@ def isomorphic(G1, G2, partn, ordering2, dig, use_indicator_function, sparse=Fal else: if first: partition = partn - to = list(xrange(n)) + to = list(range(n)) frm = to if sparse: G = SparseGraph(n) @@ -304,7 +304,10 @@ def search_tree(G_in, partition, lab=True, dig=False, dict_rep=False, certificat ....: if bde.has_arc(i,j): ....: bdg.add_edge(i,j) sage: a, b.graph6_string() - ([[0, 19, 3, 2, 6, 5, 4, 17, 18, 11, 10, 9, 13, 12, 16, 15, 14, 7, 8, 1], [0, 1, 8, 9, 13, 14, 7, 6, 2, 3, 19, 18, 17, 4, 5, 15, 16, 12, 11, 10], [1, 8, 9, 10, 11, 12, 13, 14, 7, 6, 2, 3, 4, 5, 15, 16, 17, 18, 19, 0]], 'S?[PG__OQ@?_?_?P?CO?_?AE?EC?Ac?@O') + ([[0, 19, 3, 2, 6, 5, 4, 17, 18, 11, 10, 9, 13, 12, 16, 15, 14, 7, 8, 1], + [0, 1, 8, 9, 13, 14, 7, 6, 2, 3, 19, 18, 17, 4, 5, 15, 16, 12, 11, 10], + [1, 8, 9, 10, 11, 12, 13, 14, 7, 6, 2, 3, 4, 5, 15, 16, 17, 18, 19, 0]], + 'S?[PG__OQ@?_?_?P?CO?_?AE?EC?Ac?@O') sage: a == asp True sage: a == ade @@ -389,7 +392,7 @@ def search_tree(G_in, partition, lab=True, dig=False, dict_rep=False, certificat if isinstance(G_in, GenericGraph): loops = G_in.has_loops() n = G_in.num_verts() - if G_in.vertices(sort=False) != list(xrange(n)): + if G_in.vertices(sort=False) != list(range(n)): G_in = copy(G_in) to = G_in.relabel(return_map=True) frm = {} @@ -851,7 +854,7 @@ def random_tests(num=10, n_max=60, perms_per_graph=5): print(H.graph6_string()) print(perm) return - isom = isomorphic(G, H, [list(xrange(n))], list(xrange(n)), 0, 1) + isom = isomorphic(G, H, [list(range(n))], list(range(n)), 0, 1) if not isom or G.relabel(isom, inplace=False) != H: print("isom FAILURE: graph6-") print(H.graph6_string()) @@ -876,7 +879,7 @@ def random_tests(num=10, n_max=60, perms_per_graph=5): print(E.dig6_string()) print(perm) return - isom = isomorphic(D, E, [list(xrange(n))], list(xrange(n)), 1, 1) + isom = isomorphic(D, E, [list(range(n))], list(range(n)), 1, 1) if not isom or D.relabel(isom, inplace=False) != E: print("isom FAILURE: dig6-") print(E.dig6_string()) @@ -887,6 +890,7 @@ def random_tests(num=10, n_max=60, perms_per_graph=5): num_graphs += 2 print("All passed: %d random tests on %d graphs." % (num_tests, num_graphs)) + def orbit_partition(gamma, list_perm=False): r""" Assuming that G is a graph on vertices 0,1,...,n-1, and gamma is an @@ -903,6 +907,7 @@ def orbit_partition(gamma, list_perm=False): EXAMPLES:: + sage: # needs sage.groups sage: from sage.groups.perm_gps.partn_ref.refinement_graphs import orbit_partition sage: G = graphs.PetersenGraph() sage: S = SymmetricGroup(10) @@ -1294,7 +1299,7 @@ def generate_dense_graphs_edge_addition(int n, bint loops, G=None, depth=None, 34 156 1044 - sage: generate_dense_graphs_edge_addition(8,0) # long time - about 14 seconds at 2.4 GHz + sage: generate_dense_graphs_edge_addition(8,0) # long time (about 14 seconds at 2.4 GHz) 12346 """ @@ -1563,7 +1568,7 @@ def generate_dense_graphs_vert_addition(int n, base_G=None, 53 209 1253 - sage: generate_dense_graphs_vert_addition(8) # long time + sage: generate_dense_graphs_vert_addition(8) # long time 13599 TESTS:: 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 04aed5a296b..7affe0cd965 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx @@ -383,7 +383,7 @@ def sets_isom_py(generators, set1, set2): set2 = set(set2) if not generators: if set1 == set2: - return list(xrange(max(set1) + 1)) + return list(range(max(set1) + 1)) else: return False @@ -800,7 +800,6 @@ def sets_modulo_perm_group(list generators, int max_size, sage: X = sets_modulo_perm_group([[0,2,1,4,3,5,8,7,6],[8,7,6,3,5,4,2,1,0]], 9) sage: len(X) 74 - """ cdef list out_list = [] cdef int i @@ -809,7 +808,7 @@ def sets_modulo_perm_group(list generators, int max_size, if len(generators) == 0: ll = [] for i in range(max_size,-1,-1): - ll.append(list(xrange(i))) + ll.append(list(range(i))) return ll cdef int n = len(generators[0]), n_gens = len(generators) cdef iterator *subset_iterator diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 6e59f4f4b84..130c0960361 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- r""" Permutation groups @@ -287,6 +286,7 @@ def PermutationGroup(gens=None, *args, **kwds): We can also make permutation groups from PARI groups:: + sage: # needs sage.libs.pari sage: H = pari('x^4 - 2*x^3 - 2*x + 1').polgalois() sage: G = PariGroup(H, 4); G PARI group [8, -1, 3, "D(4)"] of degree 4 @@ -295,7 +295,7 @@ def PermutationGroup(gens=None, *args, **kwds): sage: H.gens() ((1,2,3,4), (1,3)) - We can also create permutation groups whose generators are Gap + We can also create permutation groups whose generators are GAP permutation objects:: sage: p = gap('(1,2)(3,7)(4,6)(5,8)'); p @@ -335,10 +335,10 @@ def PermutationGroup(gens=None, *args, **kwds): We can create a permutation group from a group action:: sage: a = lambda x: (2*x) % 7 - sage: H = PermutationGroup(action=a, domain=range(7)) - sage: H.orbits() + sage: H = PermutationGroup(action=a, domain=range(7)) # needs sage.combinat + sage: H.orbits() # needs sage.libs.pari ((0,), (1, 2, 4), (3, 6, 5)) - sage: H.gens() + sage: H.gens() # needs sage.libs.pari ((1,2,4), (3,6,5)) Note that we provide generators for the acting group. The @@ -362,7 +362,9 @@ def PermutationGroup(gens=None, *args, **kwds): i.e., in bijection with integer partitions:: sage: a = lambda g, x: g*x*g^-1 - sage: [len(PermutationGroup(SymmetricGroup(n).gens(), action=a, domain=SymmetricGroup(n)).orbits()) for n in range(1, 8)] + sage: [len(PermutationGroup(SymmetricGroup(n).gens(), action=a, # needs sage.combinat + ....: domain=SymmetricGroup(n)).orbits()) + ....: for n in range(1, 8)] [1, 2, 3, 5, 7, 11, 15] TESTS:: @@ -427,7 +429,8 @@ class PermutationGroup_generic(FiniteGroup): sage: G Permutation Group with generators [(3,4), (1,2,3)(4,5)] sage: G.center() - Subgroup generated by [()] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) + Subgroup generated by [()] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) sage: G.group_id() [120, 34] sage: n = G.order(); n @@ -614,14 +617,14 @@ def _has_natural_domain(self): 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 ``self._gap_string`` attribute. EXAMPLES: The ``_gap_init_`` method shows how you would define the Sage ``PermutationGroup_generic`` - object in Gap:: + object in GAP:: sage: A4 = PermutationGroup([[(1,2,3)],[(2,3,4)]]); A4 Permutation Group with generators [(2,3,4), (1,2,3)] @@ -633,7 +636,7 @@ def _gap_init_(self): @cached_method def gap(self): r""" - this method from :class:`sage.groups.libgap_wrapper.ParentLibGAP` is added in order to achieve + This method from :class:`sage.groups.libgap_wrapper.ParentLibGAP` is added in order to achieve compatibility and have :class:`sage.groups.libgap_morphism.GroupHomset_libgap` work for permutation groups, as well @@ -643,7 +646,7 @@ def gap(self): EXAMPLES:: - sage: P8=PSp(8,3) + sage: P8 = PSp(8,3) sage: P8.gap() sage: gap(P8) == P8.gap() @@ -666,6 +669,7 @@ def gap(self): the following test shows, that support for the ``self._libgap`` attribute is needed in the constructor of the class:: + sage: # needs sage.libs.pari sage: PG = PGU(6,2) sage: g, h = PG.gens() sage: p1 = h^-3*(h^-1*g^-1)^2*h*g*h^2*g^-1*h^2*g*h^-5*g^-1 @@ -740,7 +744,7 @@ def __richcmp__(self, right, op): The comparison extends the subgroup relation. Hence, it is first checked whether one of the groups is subgroup of the other. If this is not the - case then the ordering is whatever it is in Gap. + case then the ordering is whatever it is in GAP. .. NOTE:: @@ -762,9 +766,9 @@ def __richcmp__(self, right, op): sage: H1 = PermutationGroup([[(1,2)],[(5,6)]]) sage: H2 = PermutationGroup([[(3,4)]]) sage: H3 = PermutationGroup([[(1,2)]]) - sage: H1 < H2 # according to Gap's ordering + sage: H1 < H2 # according to GAP's ordering True - sage: H2 < H3 # according to Gap's ordering + sage: H2 < H3 # according to GAP's ordering True sage: H3 < H1 # since H3 is a subgroup of H1 True @@ -850,7 +854,8 @@ def _element_constructor_(self, x, check=True): sage: G([(1,2)]) Traceback (most recent call last): ... - ValueError: permutation [(1, 2)] not in Permutation Group with generators [(1,2,3,4)] + ValueError: permutation [(1, 2)] not in + Permutation Group with generators [(1,2,3,4)] TESTS: @@ -923,6 +928,7 @@ def _coerce_map_from_(self, G): If this permutation group has been constructed via ``as_permutation_group`` method (from finite matrix groups):: + sage: # needs sage.libs.pari sage: MG = GU(3,2).as_matrix_group() sage: PG = MG.as_permutation_group() sage: f = PG._coerce_map_from_(MG) @@ -1166,11 +1172,11 @@ def iteration(self, algorithm="SGS"): - ``algorithm`` -- (default: ``"SGS"``) either - * ``"SGS"`` - using strong generating system - * ``"BFS"`` - a breadth first search on the Cayley graph with - respect to ``self.gens()`` - * ``"DFS"`` - a depth first search on the Cayley graph with - respect to ``self.gens()`` + * ``"SGS"`` -- using strong generating system + * ``"BFS"`` -- a breadth first search on the Cayley graph with + respect to ``self.gens()`` + * ``"DFS"`` -- a depth first search on the Cayley graph with + respect to ``self.gens()`` .. NOTE:: @@ -1312,7 +1318,7 @@ def gens_small(self): def gen(self, i=None): r""" - Return the i-th generator of ``self``; that is, the i-th element of + Return the `i`-th generator of ``self``; that is, the `i`-th element of the list ``self.gens()``. The argument `i` may be omitted if there is only one generator (but @@ -1367,8 +1373,7 @@ def one(self): EXAMPLES:: sage: G = PermutationGroup([[(1,2,3),(4,5)]]) - sage: e = G.identity() # indirect doctest - sage: e + sage: e = G.identity(); e # indirect doctest () sage: g = G.gen(0) sage: g*e @@ -1531,13 +1536,13 @@ def representative_action(self,x,y): INPUT: - - ``x,y`` -- two elements of the domain. + - ``x``, ``y`` -- two elements of the domain. EXAMPLES:: sage: G = groups.permutation.Cyclic(14) - sage: g = G.representative_action(1,10) - sage: all(g(x) == 1+((x+9-1)%14) for x in G.domain()) + sage: g = G.representative_action(1, 10) + sage: all(g(x) == 1 + ((x+9-1)%14) for x in G.domain()) True TESTS:: @@ -1657,7 +1662,7 @@ def orbit(self, point, action="OnPoints"): Action of `S_4` (on a nonstandard domain) on tuples of sets:: sage: S4 = PermutationGroup([ [('c','d')], [('a','c')], [('a','b')] ]) - sage: orb = S4.orbit((('a','c'),('b','d')),"OnTuplesSets") + sage: orb = S4.orbit((('a','c'),('b','d')), "OnTuplesSets") sage: expect = (({'a', 'c'}, {'b', 'd'}), ({'a', 'd'}, {'c', 'b'}), ....: ({'c', 'b'}, {'a', 'd'}), ({'b', 'd'}, {'a', 'c'}), ....: ({'c', 'd'}, {'a', 'b'}), ({'a', 'b'}, {'c', 'd'})) @@ -1668,7 +1673,8 @@ def orbit(self, point, action="OnPoints"): sage: S4 = PermutationGroup([ [((11,(12,13)),'d')], ....: [((12,(12,11)),(11,(12,13)))], [((12,(12,11)),'b')] ]) - sage: orb = S4.orbit((( (11,(12,13)), (12,(12,11))),('b','d')),"OnTuplesSets") + sage: orb = S4.orbit((( (11,(12,13)), (12,(12,11))),('b','d')), + ....: "OnTuplesSets") sage: expect = (({(11, (12, 13)), (12, (12, 11))}, {'b', 'd'}), ....: ({'d', (12, (12, 11))}, {(11, (12, 13)), 'b'}), ....: ({(11, (12, 13)), 'b'}, {'d', (12, (12, 11))}), @@ -1755,9 +1761,9 @@ def stabilizer(self, point, action="OnPoints"): - ``point`` -- a point of the :meth:`domain`, or a set of points depending on the value of ``action``. - - ``action`` (string; default ``"OnPoints"``) -- should the group be + - ``action`` -- (string; default ``"OnPoints"``) should the group be considered to act on points (``action="OnPoints"``) or on sets of - points (``action="OnSets"``) ? In the latter case, the first argument + points (``action="OnSets"``)? In the latter case, the first argument must be a subset of :meth:`domain`. EXAMPLES:: @@ -1848,8 +1854,8 @@ def base(self, seed=None): INPUT: - ``seed`` (optional, default: ``None``), if given must be a - subset of the domain of `base`. When used, an attempt to - create a base containing all or part of `seed` will be + subset of the domain of a base. When used, an attempt to + create a base containing all or part of ``seed`` will be made. EXAMPLES:: @@ -1915,10 +1921,10 @@ def strong_generating_system(self, base_of_group=None, implementation="sage"): - ``implementation`` -- (default: ``"sage"``) either - * ``"sage"`` - use the direct implementation in Sage + * ``"sage"`` -- use the direct implementation in Sage - * ``"gap"`` - if used, the ``base_of_group`` must be ``None`` - and the computation is directly performed in GAP + * ``"gap"`` -- if used, the ``base_of_group`` must be ``None`` + and the computation is directly performed in GAP OUTPUT: @@ -2140,7 +2146,7 @@ def _order(self): # This special case only works with more than 1 generator. if not gens or len(gens) < 2: return None - # Special case: certain subgroups of the symmetric group for which Gap reports + # Special case: certain subgroups of the symmetric group for which GAP reports # generators of the form ((1, 2), (1, 3), ...) # This means that this group is isomorphic to a smaller symmetric group # S_n, where n is the number of generators supported. @@ -2188,7 +2194,8 @@ def _order(self): def order(self): """ Return the number of elements of this group. - See also: G.degree() + + See also: :meth:`degree`. EXAMPLES:: @@ -2202,7 +2209,7 @@ def order(self): sage: G.order() 1 - ``cardinality`` is just an alias:: + :meth:`cardinality` is just an alias:: sage: PermutationGroup([(1,2,3)]).cardinality() 3 @@ -2255,8 +2262,9 @@ def group_id(self): def id(self): """ - (Same as ``self.group_id()``.) Return the ID code of this group, which - is a list of two integers. + Return the ID code of this group, which is a list of two integers. + + Same as :meth:`group_id`. EXAMPLES:: @@ -2273,7 +2281,7 @@ def group_primitive_id(self): OUTPUT: A positive integer, following GAP's conventions. A - ``ValueError`` is raised if the group is not primitive. + :class:`ValueError` is raised if the group is not primitive. EXAMPLES:: @@ -2307,10 +2315,12 @@ def center(self): sage: G = PermutationGroup([[(1,2,3,4)]]) sage: G.center() - Subgroup generated by [(1,2,3,4)] of (Permutation Group with generators [(1,2,3,4)]) + Subgroup generated by [(1,2,3,4)] of + (Permutation Group with generators [(1,2,3,4)]) sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]]) sage: G.center() - Subgroup generated by [()] of (Permutation Group with generators [(1,2), (1,2,3,4)]) + Subgroup generated by [()] of + (Permutation Group with generators [(1,2), (1,2,3,4)]) """ return self.subgroup(gap_group=self._libgap_().Center()) @@ -2325,9 +2335,12 @@ def socle(self): sage: G = SymmetricGroup(4) sage: G.socle() - Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of (Symmetric group of order 4! as a permutation group) + Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of + (Symmetric group of order 4! as a permutation group) sage: G.socle().socle() - Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of (Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of (Symmetric group of order 4! as a permutation group)) + Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of + (Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] + of (Symmetric group of order 4! as a permutation group)) """ return self.subgroup(gap_group=self._gap_().Socle()) @@ -2342,10 +2355,12 @@ def frattini_subgroup(self): sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]]) sage: G.frattini_subgroup() - Subgroup generated by [(1,3)(2,4)] of (Permutation Group with generators [(2,4), (1,2,3,4)]) + Subgroup generated by [(1,3)(2,4)] of + (Permutation Group with generators [(2,4), (1,2,3,4)]) sage: G = SymmetricGroup(4) sage: G.frattini_subgroup() - Subgroup generated by [()] of (Symmetric group of order 4! as a permutation group) + Subgroup generated by [()] of + (Symmetric group of order 4! as a permutation group) """ return self.subgroup(gap_group=self._libgap_().FrattiniSubgroup()) @@ -2361,10 +2376,12 @@ def fitting_subgroup(self): sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]]) sage: G.fitting_subgroup() - Subgroup generated by [(2,4), (1,2,3,4), (1,3)] of (Permutation Group with generators [(2,4), (1,2,3,4)]) + Subgroup generated by [(2,4), (1,2,3,4), (1,3)] of + (Permutation Group with generators [(2,4), (1,2,3,4)]) sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]]) sage: G.fitting_subgroup() - Subgroup generated by [(1,2)(3,4), (1,3)(2,4)] of (Permutation Group with generators [(1,2), (1,2,3,4)]) + Subgroup generated by [(1,2)(3,4), (1,3)(2,4)] of + (Permutation Group with generators [(1,2), (1,2,3,4)]) """ return self.subgroup(gap_group=self._libgap_().FittingSubgroup()) @@ -2380,10 +2397,12 @@ def solvable_radical(self): sage: G = SymmetricGroup(4) sage: G.solvable_radical() - Subgroup generated by [(1,2), (1,2,3,4)] of (Symmetric group of order 4! as a permutation group) + Subgroup generated by [(1,2), (1,2,3,4)] of + (Symmetric group of order 4! as a permutation group) sage: G = SymmetricGroup(5) sage: G.solvable_radical() - Subgroup generated by [()] of (Symmetric group of order 5! as a permutation group) + Subgroup generated by [()] of + (Symmetric group of order 5! as a permutation group) """ return self.subgroup(gap_group=self._libgap_().RadicalGroup()) @@ -2489,7 +2508,7 @@ def conjugate(self, g): INPUT: - - ``g`` - a permutation group element, or an object that converts + - ``g`` -- a permutation group element, or an object that converts to a permutation group element, such as a list of integers or a string of cycles. @@ -2583,28 +2602,27 @@ def direct_product(self, other, maps=True): INPUT: - - ``self, other`` - permutation groups + - ``self``, ``other`` -- permutation groups OUTPUT: - - ``D`` - a direct product of the inputs, returned as + - ``D`` -- a direct product of the inputs, returned as a permutation group as well - - ``iota1`` - an embedding of ``self`` into ``D`` + - ``iota1`` -- an embedding of ``self`` into ``D`` - - ``iota2`` - an embedding of ``other`` into ``D`` + - ``iota2`` -- an embedding of ``other`` into ``D`` - - ``pr1`` - the projection of ``D`` onto ``self`` (giving a - splitting 1 - other - D - self - 1) + - ``pr1`` -- the projection of ``D`` onto ``self`` (giving a + splitting ``1 - other - D - self - 1``) - - ``pr2`` - the projection of ``D`` onto ``other`` (giving a - splitting 1 - self - D - other - 1) + - ``pr2`` -- the projection of ``D`` onto ``other`` (giving a + splitting ``1 - self - D - other - 1``) EXAMPLES:: sage: G = CyclicPermutationGroup(4) - sage: D = G.direct_product(G,False) - sage: D + sage: D = G.direct_product(G, False); D Permutation Group with generators [(5,6,7,8), (1,2,3,4)] sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G) sage: D; iota1; iota2; pr1; pr2 @@ -2657,22 +2675,22 @@ def semidirect_product(self, N, mapping, check=True): naturally embeds as a normal subgroup of the returned semidirect product. - - ``mapping`` - A pair of lists that together define a - homomorphism, `\phi :` self `\rightarrow` Aut(N), by giving, + - ``mapping`` -- A pair of lists that together define a + homomorphism, `\phi :` ``self`` `\rightarrow` Aut(``N``), by giving, in the second list, the images of the generators of ``self`` in the order given in the first list. - - ``check`` - A boolean that, if set to False, will skip the + - ``check`` -- A boolean that, if set to ``False``, will skip the initial tests which are made on ``mapping``. This may be beneficial for large ``N``, since in such cases the injectivity test can be - expensive. Set to True by default. + expensive. Set to ``True`` by default. OUTPUT: The semidirect product of ``self`` and ``N`` defined by the action of ``self`` on ``N`` given in ``mapping`` (note that a - homomorphism from A to the automorphism group of B is - equivalent to an action of A on the B's underlying set). The + homomorphism from `A` to the automorphism group of `B` is + equivalent to an action of `A` on `B`'s underlying set). The semidirect product of two groups, `H` and `N`, is a construct similar to the direct product in so far as the elements are the Cartesian product of the elements of `H` and the elements @@ -2739,7 +2757,8 @@ def semidirect_product(self, N, mapping, check=True): sage: S1.is_isomorphic(DiCyclicGroup(6)) False sage: S1.center() - Subgroup generated by [(1,3)(2,4)] of (Permutation Group with generators [(5,6,7), (1,2,3,4)(6,7), (1,3)]) + Subgroup generated by [(1,3)(2,4)] of + (Permutation Group with generators [(5,6,7), (1,2,3,4)(6,7), (1,3)]) sage: len(S1.conjugacy_classes_representatives()) 9 @@ -2855,7 +2874,8 @@ def holomorph(self): sage: A.is_abelian() False sage: A.center() - Subgroup generated by [()] of (Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)]) + Subgroup generated by [()] of + (Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)]) sage: A Permutation Group with generators [(5,6,7,8,9), (1,2,4,3)(6,7,9,8)] @@ -2903,14 +2923,15 @@ def subgroup(self, gens=None, gap_group=None, domain=None, category=None, canoni sage: G = PermutationGroup([(1,2,3),(3,4,5)]) sage: g = G((1,2,3)) sage: G.subgroup([g]) - Subgroup generated by [(1,2,3)] of (Permutation Group with generators [(3,4,5), (1,2,3)]) + Subgroup generated by [(1,2,3)] of + (Permutation Group with generators [(3,4,5), (1,2,3)]) """ return self.Subgroup(self, gens=gens, gap_group=gap_group, domain=None, category=category, canonicalize=canonicalize, check=check) def _subgroup_constructor(self, libgap_group): """ - this method is added for compatibility reason with the + This method is added for compatibility reason with the :meth:`sage.groups.libgap_wrapper.ParentLibGAP_subgroup_constructor` and for usage in :class:`sage.groups.libgap_morphism.GroupMorphism_libgap` @@ -2921,10 +2942,11 @@ def _subgroup_constructor(self, libgap_group): OUTPUT: - the corresponding subgroup of self as an instance of this class + The corresponding subgroup of ``self`` as an instance of this class EXAMPLES:: + sage: # needs sage.libs.pari sage: G = PGU(3,2); G The projective general unitary group of degree 3 over Finite Field of size 2 sage: g1, g2 = G.gens() @@ -2933,7 +2955,8 @@ def _subgroup_constructor(self, libgap_group): sage: type(Hgap) sage: H = G._subgroup_constructor(Hgap); H - Subgroup generated by [(1,6,21,12,20,17)(2,10,15,9,11,5)(3,14,8)(4,18)(7,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) + Subgroup generated by [(1,6,21,12,20,17)(2,10,15,9,11,5)(3,14,8)(4,18)(7,16)] of + (The projective general unitary group of degree 3 over Finite Field of size 2) """ gens = [gen.sage() for gen in libgap_group.GeneratorsOfGroup()] return self.subgroup(gens=gens, gap_group=libgap_group) @@ -2947,15 +2970,15 @@ def as_finitely_presented_group(self, reduced=False): INPUT: - - ``reduced`` -- Default ``False``, if ``True`` :meth:`FinitelyPresentedGroup.simplified + - ``reduced`` -- (default ``False``) if ``True``, :meth:`FinitelyPresentedGroup.simplified ` 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``. + Finite presentation of ``self``, obtained by taking the image + of the isomorphism returned by the GAP function ``IsomorphismFpGroupByGenerators``. ALGORITHM: @@ -2982,9 +3005,10 @@ def as_finitely_presented_group(self, reduced=False): We can attempt to reduce the output presentation:: - sage: PermutationGroup(['(1,2,3,4,5)','(1,3,5,2,4)']).as_finitely_presented_group() + sage: H = PermutationGroup(['(1,2,3,4,5)', '(1,3,5,2,4)']) + sage: H.as_finitely_presented_group() Finitely presented group < a, b | b^-2*a^-1, b*a^-2 > - sage: PermutationGroup(['(1,2,3,4,5)','(1,3,5,2,4)']).as_finitely_presented_group(reduced=True) + sage: H.as_finitely_presented_group(reduced=True) Finitely presented group < a | a^5 > TESTS:: @@ -3080,11 +3104,11 @@ def commutator(self, other=None): INPUT: - - ``other`` - default: ``None`` - a permutation group. + - ``other`` -- (default: ``None``) a permutation group. OUTPUT: - Let `G` denote ``self``. If ``other`` is ``None`` then this method + Let `G` denote ``self``. If ``other`` is ``None``, then this method returns the subgroup of `G` generated by the set of commutators, .. MATH:: @@ -3277,8 +3301,7 @@ def homology(self, n, p=0): `H_7(S_5, \ZZ / 2 \ZZ)`, `H_7(S_5, \ZZ / 3 \ZZ)`, and `H_7(S_5, \ZZ / 5 \ZZ)`, respectively. To compute the - `2`-part of `H_7(S_5, \ZZ)`, use the ``homology_part`` - function. + `2`-part of `H_7(S_5, \ZZ)`, use the method :meth:`homology_part`. EXAMPLES:: @@ -3352,7 +3375,7 @@ def character_table(self): sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3)]]) sage: G.order() 12 - sage: G.character_table() + sage: G.character_table() # needs sage.rings.number_field [ 1 1 1 1] [ 1 -zeta3 - 1 zeta3 1] [ 1 zeta3 -zeta3 - 1 1] @@ -3367,7 +3390,7 @@ def character_table(self): sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) sage: G.order() 8 - sage: G.character_table() + sage: G.character_table() # needs sage.rings.number_field [ 1 1 1 1 1] [ 1 -1 -1 1 1] [ 1 -1 1 -1 1] @@ -3379,6 +3402,7 @@ def character_table(self): :: + sage: # needs sage.rings.number_field sage: SymmetricGroup(2).character_table() [ 1 -1] [ 1 1] @@ -3395,7 +3419,10 @@ def character_table(self): [ 4 2 0 1 -1 0 -1] [ 1 1 1 1 1 1 1] sage: list(AlternatingGroup(6).character_table()) - [(1, 1, 1, 1, 1, 1, 1), (5, 1, 2, -1, -1, 0, 0), (5, 1, -1, 2, -1, 0, 0), (8, 0, -1, -1, 0, zeta5^3 + zeta5^2 + 1, -zeta5^3 - zeta5^2), (8, 0, -1, -1, 0, -zeta5^3 - zeta5^2, zeta5^3 + zeta5^2 + 1), (9, 1, 0, 0, 1, -1, -1), (10, -2, 1, 1, 0, 0, 0)] + [(1, 1, 1, 1, 1, 1, 1), (5, 1, 2, -1, -1, 0, 0), (5, 1, -1, 2, -1, 0, 0), + (8, 0, -1, -1, 0, zeta5^3 + zeta5^2 + 1, -zeta5^3 - zeta5^2), + (8, 0, -1, -1, 0, -zeta5^3 - zeta5^2, zeta5^3 + zeta5^2 + 1), + (9, 1, 0, 0, 1, -1, -1), (10, -2, 1, 1, 0, 0, 0)] Suppose that you have a class function `f(g)` on `G` and you know the values `v_1, \ldots, v_n` on @@ -3438,8 +3465,8 @@ def irreducible_characters(self): EXAMPLES:: - sage: irr = SymmetricGroup(3).irreducible_characters() - sage: [x.values() for x in irr] + sage: irr = SymmetricGroup(3).irreducible_characters() # needs sage.rings.number_field + sage: [x.values() for x in irr] # needs sage.rings.number_field [[1, -1, 1], [2, 0, -1], [1, 1, 1]] """ return [ClassFunction_libgap(self, irr) for irr in self._libgap_().Irr()] @@ -3450,7 +3477,7 @@ def trivial_character(self): EXAMPLES:: - sage: SymmetricGroup(3).trivial_character() + sage: SymmetricGroup(3).trivial_character() # needs sage.rings.number_field Character of Symmetric group of order 3! as a permutation group """ values = [1]*self._libgap_().NrConjugacyClasses().sage() @@ -3466,7 +3493,7 @@ def character(self, values): sage: G = AlternatingGroup(4) sage: n = len(G.conjugacy_classes_representatives()) - sage: G.character([1]*n) + sage: G.character([1]*n) # needs sage.rings.number_field Character of Alternating group of order 4!/2 as a permutation group """ return ClassFunction_libgap(self, values) @@ -3489,13 +3516,13 @@ def conjugacy_classes_representatives(self): :: sage: G = SymmetricGroup(5) - sage: G.conjugacy_classes_representatives() + sage: G.conjugacy_classes_representatives() # needs sage.combinat [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)] :: sage: S = SymmetricGroup(['a','b','c']) - sage: S.conjugacy_classes_representatives() + sage: S.conjugacy_classes_representatives() # needs sage.combinat [(), ('a','b'), ('a','b','c')] AUTHORS: @@ -3515,25 +3542,36 @@ def conjugacy_classes_subgroups(self): EXAMPLES:: sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) - sage: cl = G.conjugacy_classes_subgroups() - sage: cl - [Subgroup generated by [()] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(1,2)(3,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(1,3)(2,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(2,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(2,4), (1,3)(2,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(1,2,3,4), (1,3)(2,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), - Subgroup generated by [(2,4), (1,2)(3,4), (1,4)(2,3)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])] + sage: cl = G.conjugacy_classes_subgroups(); cl + [Subgroup generated by [()] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(1,2)(3,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(1,3)(2,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(2,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(1,2)(3,4), (1,4)(2,3)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(2,4), (1,3)(2,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(1,2,3,4), (1,3)(2,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]), + Subgroup generated by [(2,4), (1,2)(3,4), (1,4)(2,3)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)])] :: sage: G = SymmetricGroup(3) sage: G.conjugacy_classes_subgroups() - [Subgroup generated by [()] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(2,3)] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(1,2,3)] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(2,3), (1,2,3)] of (Symmetric group of order 3! as a permutation group)] + [Subgroup generated by [()] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(2,3)] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(1,2,3)] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(2,3), (1,2,3)] of + (Symmetric group of order 3! as a permutation group)] AUTHORS: @@ -3575,19 +3613,30 @@ def subgroups(self): sage: G = SymmetricGroup(3) sage: G.subgroups() - [Subgroup generated by [()] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(2,3)] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(1,2)] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(1,3)] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(1,2,3)] of (Symmetric group of order 3! as a permutation group), - Subgroup generated by [(2,3), (1,2,3)] of (Symmetric group of order 3! as a permutation group)] + [Subgroup generated by [()] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(2,3)] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(1,2)] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(1,3)] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(1,2,3)] of + (Symmetric group of order 3! as a permutation group), + Subgroup generated by [(2,3), (1,2,3)] of + (Symmetric group of order 3! as a permutation group)] sage: G = CyclicPermutationGroup(14) sage: G.subgroups() - [Subgroup generated by [()] of (Cyclic group of order 14 as a permutation group), - Subgroup generated by [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)] of (Cyclic group of order 14 as a permutation group), - Subgroup generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)] of (Cyclic group of order 14 as a permutation group), - Subgroup generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14), (1,3,5,7,9,11,13)(2,4,6,8,10,12,14)] of (Cyclic group of order 14 as a permutation group)] + [Subgroup generated by [()] of + (Cyclic group of order 14 as a permutation group), + Subgroup generated by [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)] of + (Cyclic group of order 14 as a permutation group), + Subgroup generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)] of + (Cyclic group of order 14 as a permutation group), + Subgroup generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14), + (1,3,5,7,9,11,13)(2,4,6,8,10,12,14)] of + (Cyclic group of order 14 as a permutation group)] AUTHOR: @@ -3636,9 +3685,9 @@ def has_regular_subgroup(self, return_group=False): INPUT: - - ``return_group`` (boolean) -- If ``return_group = True``, a regular + - ``return_group`` -- (boolean) If ``True``, a regular subgroup is returned if there is one, and ``None`` if there isn't. - When ``return_group = False`` (default), only a boolean indicating + When ``return_group=False`` (default), only a boolean indicating whether such a group exists is returned instead. EXAMPLES: @@ -3648,8 +3697,9 @@ def has_regular_subgroup(self, return_group=False): sage: S4 = groups.permutation.Symmetric(4) sage: S4.has_regular_subgroup() True - sage: S4.has_regular_subgroup(return_group = True) # random - Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,3)(2,4), (1,4)(2,3)] + sage: S4.has_regular_subgroup(return_group=True) # random + Subgroup of (Symmetric group of order 4! as a permutation group) + generated by [(1,3)(2,4), (1,4)(2,3)] But the automorphism group of Petersen's graph does not:: @@ -3682,7 +3732,7 @@ def blocks_all(self, representatives=True): INPUT: - - ``representative`` (boolean) -- whether to return all possible block + - ``representative`` -- (boolean) whether to return all possible block systems of imprimitivity or only one of their representatives (the block can be obtained from its representative set `S` by computing the orbit of `S` under ``self``). @@ -3698,13 +3748,13 @@ def blocks_all(self, representatives=True): * A list of length (#number of different block systems) of - * block systems, each of them being defined as + * block systems, each of them being defined as - * If ``representatives = True`` : a list of representatives of - each set of the block system + * If ``representatives=True``: a list of representatives of + each set of the block system - * If ``representatives = False`` : a partition of the elements - defining an imprimitivity block. + * If ``representatives=False``: a partition of the elements + defining an imprimitivity block. .. SEEALSO:: @@ -3729,7 +3779,8 @@ def blocks_all(self, representatives=True): Now the full block:: sage: sorted(ag.blocks_all(representatives = False)[0]) - [[0, 15], [1, 16], [2, 12], [3, 13], [4, 9], [5, 10], [6, 11], [7, 18], [8, 17], [14, 19]] + [[0, 15], [1, 16], [2, 12], [3, 13], [4, 9], + [5, 10], [6, 11], [7, 18], [8, 17], [14, 19]] TESTS:: @@ -3754,13 +3805,13 @@ def cosets(self, S, side='right'): INPUT: - - ``S`` - a subgroup of ``self``. An error is raised + - ``S`` -- a subgroup of ``self``. An error is raised if ``S`` is not a subgroup. - - ``side`` - default: 'right' - determines if right cosets or + - ``side`` -- (default: ``'right'``) Determines if right cosets or left cosets are returned. ``side`` refers to where the representative is placed in the products forming the cosets - and thus allowable values are only 'right' and 'left'. + and thus allowable values are only ``'right'`` and ``'left'``. OUTPUT: @@ -3947,13 +3998,16 @@ def normalizer(self, g): sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) sage: g = G([(1,3)]) sage: G.normalizer(g) - Subgroup generated by [(2,4), (1,3)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + Subgroup generated by [(2,4), (1,3)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) sage: g = G([(1,2,3,4)]) sage: G.normalizer(g) - Subgroup generated by [(2,4), (1,2,3,4), (1,3)(2,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + Subgroup generated by [(2,4), (1,2,3,4), (1,3)(2,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) sage: H = G.subgroup([G([(1,2,3,4)])]) sage: G.normalizer(H) - Subgroup generated by [(2,4), (1,2,3,4), (1,3)(2,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + Subgroup generated by [(2,4), (1,2,3,4), (1,3)(2,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) """ return self.subgroup(gap_group=self._libgap_().Normalizer(g)) @@ -3966,13 +4020,16 @@ def centralizer(self, g): sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) sage: g = G([(1,3)]) sage: G.centralizer(g) - Subgroup generated by [(2,4), (1,3)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + Subgroup generated by [(2,4), (1,3)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) sage: g = G([(1,2,3,4)]) sage: G.centralizer(g) - Subgroup generated by [(1,2,3,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + Subgroup generated by [(1,2,3,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) sage: H = G.subgroup([G([(1,2,3,4)])]) sage: G.centralizer(H) - Subgroup generated by [(1,2,3,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + Subgroup generated by [(1,2,3,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) """ return self.subgroup(gap_group=self._libgap_().Centralizer(g)) @@ -4080,9 +4137,9 @@ def isomorphism_to(self, right): INPUT: - - ``self`` - this group + - ``self`` -- this group - - ``right`` - a permutation group + - ``right`` -- a permutation group OUTPUT: @@ -4133,9 +4190,9 @@ def is_isomorphic(self, right): INPUT: - - ``self`` - this group + - ``self`` -- this group - - ``right`` - a permutation group + - ``right`` -- a permutation group OUTPUT: @@ -4243,7 +4300,7 @@ def is_polycyclic(self): Return ``True`` if this group is polycyclic. A group is polycyclic if it has a subnormal series with cyclic factors. (For finite groups, this is the same as if the group is solvable - see - ``is_solvable``.) + :meth:`is_solvable`.) EXAMPLES:: @@ -4574,13 +4631,17 @@ def composition_series(self): sage: set_random_seed(0) sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) sage: G.composition_series() - [Subgroup generated by [(3,4), (1,2,3)(4,5)] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), - Subgroup generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), - Subgroup generated by [()] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] + [Subgroup generated by [(3,4), (1,2,3)(4,5)] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), + Subgroup generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), + Subgroup generated by [()] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]]) sage: CS = G.composition_series() sage: CS[3] - Subgroup generated by [()] of (Permutation Group with generators [(1,2), (1,2,3)(4,5)]) + Subgroup generated by [()] of + (Permutation Group with generators [(1,2), (1,2,3)(4,5)]) """ libgap.set_seed() CS = self._libgap_().CompositionSeries() @@ -4601,8 +4662,10 @@ def derived_series(self): sage: set_random_seed(0) sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) sage: G.derived_series() - [Subgroup generated by [(3,4), (1,2,3)(4,5)] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), - Subgroup generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] + [Subgroup generated by [(3,4), (1,2,3)(4,5)] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), + Subgroup generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] """ libgap.set_seed() DS = self._libgap_().DerivedSeries() @@ -4623,8 +4686,10 @@ def lower_central_series(self): sage: set_random_seed(0) sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) sage: G.lower_central_series() - [Subgroup generated by [(3,4), (1,2,3)(4,5)] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), - Subgroup generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] + [Subgroup generated by [(3,4), (1,2,3)(4,5)] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)]), + Subgroup generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] """ libgap.set_seed() LCS = self._libgap_().LowerCentralSeriesOfGroup() @@ -4701,11 +4766,11 @@ def molien_series(self): R(str(dd).replace("_1", ""))) def normal_subgroups(self): - """ + r""" Return the normal subgroups of this group as a (sorted in increasing order) list of permutation groups. - The normal subgroups of `H = PSL(2,7) \\times PSL(2,7)` are + The normal subgroups of `H = PSL(2,7) \times PSL(2,7)` are `1`, two copies of `PSL(2,7)` and `H` itself, as the following example shows. @@ -4740,10 +4805,10 @@ def poincare_series(self, p=2, n=10): EXAMPLES:: sage: G = SymmetricGroup(5) - sage: G.poincare_series(2,10) # optional - gap_package_hap + sage: G.poincare_series(2, 10) # optional - gap_package_hap (x^2 + 1)/(x^4 - x^3 - x + 1) sage: G = SymmetricGroup(3) - sage: G.poincare_series(2,10) # optional - gap_package_hap + sage: G.poincare_series(2, 10) # optional - gap_package_hap -1/(x - 1) AUTHORS: @@ -4777,9 +4842,11 @@ def sylow_subgroup(self, p): sage: G = PermutationGroup(['(1,2,3)', '(2,3)']) sage: G.sylow_subgroup(2) - Subgroup generated by [(2,3)] of (Permutation Group with generators [(2,3), (1,2,3)]) + Subgroup generated by [(2,3)] of + (Permutation Group with generators [(2,3), (1,2,3)]) sage: G.sylow_subgroup(5) - Subgroup generated by [()] of (Permutation Group with generators [(2,3), (1,2,3)]) + Subgroup generated by [()] of + (Permutation Group with generators [(2,3), (1,2,3)]) TESTS: @@ -4804,7 +4871,8 @@ def upper_central_series(self): sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) sage: G.upper_central_series() - [Subgroup generated by [()] of (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] + [Subgroup generated by [()] of + (Permutation Group with generators [(3,4), (1,2,3)(4,5)])] """ libgap.set_seed() UCS = self._libgap_().UpperCentralSeriesOfGroup() @@ -4846,7 +4914,8 @@ class PermutationGroup_subgroup(PermutationGroup_generic): sage: gens = G.gens() sage: H = DihedralGroup(4) sage: H.subgroup(gens) - Subgroup generated by [(1,2,3,4)] of (Dihedral group of order 8 as a permutation group) + Subgroup generated by [(1,2,3,4)] of + (Dihedral group of order 8 as a permutation group) sage: K = H.subgroup(gens) sage: K.list() [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)] @@ -4863,18 +4932,18 @@ def __init__(self, ambient, gens=None, gap_group=None, domain=None, INPUT: - - ``ambient`` - the ambient group from which to construct this + - ``ambient`` -- the ambient group from which to construct this subgroup - - ``gens`` - the generators of the subgroup + - ``gens`` -- the generators of the subgroup - - ``gap_group`` - a GAP permutation group contained in the ambient group; - constructed from ``gens`` if not given. + - ``gap_group`` -- a GAP permutation group contained in the ambient group; + constructed from ``gens`` if not given. - - ``check`` - ``True``: checks if ``gens`` are indeed elements of the + - ``check`` -- ``True``: checks if ``gens`` are indeed elements of the ambient group - - ``canonicalize`` - boolean (default: ``True``); if ``True``, sort + - ``canonicalize`` -- boolean (default: ``True``); if ``True``, sort generators and remove duplicates EXAMPLES: @@ -5078,7 +5147,8 @@ def is_normal(self, other=None): sage: S = SymmetricGroup(['a','b','c']) sage: H = S.subgroup([('a', 'b', 'c')]); H - Subgroup generated by [('a','b','c')] of (Symmetric group of order 3! as a permutation group) + Subgroup generated by [('a','b','c')] of + (Symmetric group of order 3! as a permutation group) sage: H.is_normal() True @@ -5087,6 +5157,7 @@ def is_normal(self, other=None): other = self.ambient_group() return PermutationGroup_generic.is_normal(self, other) + # Allow for subclasses to use a different subgroup class PermutationGroup_generic.Subgroup = PermutationGroup_subgroup @@ -5100,9 +5171,9 @@ class PermutationGroup_action(PermutationGroup_generic): sage: n = 3 sage: a = lambda x: SetPartition([[e % n + 1 for e in b] for b in x]) - sage: S = SetPartitions(n) - sage: G = PermutationGroup(action=a, domain=S) - sage: G.orbits() + sage: S = SetPartitions(n) # needs sage.combinat + sage: G = PermutationGroup(action=a, domain=S) # needs sage.combinat + sage: G.orbits() # needs sage.combinat (({{1}, {2}, {3}},), ({{1, 2}, {3}}, {{1}, {2, 3}}, {{1, 3}, {2}}), ({{1, 2, 3}},)) @@ -5111,13 +5182,14 @@ class PermutationGroup_action(PermutationGroup_generic): sage: a = lambda g, x: g*x*g^-1 sage: S = SymmetricGroup(3) - sage: G = PermutationGroup(S.gens(), action=a, domain=S) - sage: G.orbits() + sage: G = PermutationGroup(S.gens(), action=a, domain=S) # needs sage.combinat + sage: G.orbits() # needs sage.combinat (((),), ((1,3,2), (1,2,3)), ((2,3), (1,3), (1,2))) The trivial action of the symmetric group:: - sage: PermutationGroup(SymmetricGroup(3).gens(), action=lambda g, x: x, domain=[1]) + sage: PermutationGroup(SymmetricGroup(3).gens(), # needs sage.combinat + ....: action=lambda g, x: x, domain=[1]) Permutation Group with generators [()] """ def __init__(self, gens, action, domain, gap_group=None, category=None, canonicalize=None): @@ -5147,8 +5219,8 @@ def __init__(self, gens, action, domain, gap_group=None, category=None, canonica EXAMPLES:: sage: a = lambda x: (2*x) % 7 - sage: G = PermutationGroup(action=a, domain=range(7)) - sage: G.orbits() + sage: G = PermutationGroup(action=a, domain=range(7)) # needs sage.combinat + sage: G.orbits() # needs sage.combinat ((0,), (1, 2, 4), (3, 6, 5)) """ @@ -5188,11 +5260,12 @@ def orbits(self): EXAMPLES:: sage: a = lambda x: (2*x) % 7 - sage: G = PermutationGroup(action=a, domain=range(7)) - sage: G.orbits() + sage: G = PermutationGroup(action=a, domain=range(7)) # needs sage.combinat + sage: G.orbits() # needs sage.combinat ((0,), (1, 2, 4), (3, 6, 5)) """ return self._orbits + from sage.misc.rest_index_of_methods import gen_rest_table_index __doc__ = __doc__.format(METHODS_OF_PermutationGroup_generic=gen_rest_table_index(PermutationGroup_generic)) diff --git a/src/sage/groups/perm_gps/permgroup_element.pxd b/src/sage/groups/perm_gps/permgroup_element.pxd index a2ac8f20eaa..0a584745f96 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pxd +++ b/src/sage/groups/perm_gps/permgroup_element.pxd @@ -22,7 +22,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cpdef PermutationGroupElement _generate_new_GAP(self, old) cpdef _gap_list(self) cpdef domain(self) - cdef public __custom_name + cdef public _SageObject__custom_name cpdef list _act_on_list_on_position(self, list x) cpdef ClonableIntArray _act_on_array_on_position(self, ClonableIntArray x) cpdef ETuple _act_on_etuple_on_position(self, ETuple x) diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index efc5e502cc0..2522b5c346d 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -115,19 +115,21 @@ from libc.stdlib cimport qsort from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free from cpython.list cimport * -from cypari2.gen cimport Gen +try: + from cypari2.gen import Gen +except ImportError: + Gen = () from sage.ext.stdsage cimport HAS_DICTIONARY -from sage.rings.integer_ring import ZZ +from sage.interfaces.abc import GpElement from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ from sage.rings.polynomial.multi_polynomial import MPolynomial from sage.rings.polynomial.polynomial_element import Polynomial -from sage.structure.element import is_Matrix -from sage.matrix.matrix_space import MatrixSpace from sage.sets.finite_enumerated_set import FiniteEnumeratedSet -from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool from sage.structure.coerce cimport coercion_model -from sage.interfaces.abc import GpElement +from sage.structure.element import is_Matrix +from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool import sage.interfaces.abc @@ -151,8 +153,8 @@ cdef int etuple_index_cmp(const void * a, const void * b) nogil: return (( a)[0] > ( b)[0]) - (( a)[0] < ( b)[0]) def make_permgroup_element(G, x): - """ - Returns a PermutationGroupElement given the permutation group + r""" + Return a :class:`PermutationGroupElement` given the permutation group ``G`` and the permutation ``x`` in list notation. This is function is used when unpickling old (pre-domain) versions @@ -171,8 +173,8 @@ def make_permgroup_element(G, x): return make_permgroup_element_v2(G, x, domain) def make_permgroup_element_v2(G, x, domain): - """ - Returns a PermutationGroupElement given the permutation group + r""" + Return a :class:`PermutationGroupElement` given the permutation group ``G``, the permutation ``x`` in list notation, and the domain ``domain`` of the permutation group. @@ -198,8 +200,8 @@ def make_permgroup_element_v2(G, x, domain): return G.element_class(x, G, check=False) def is_PermutationGroupElement(x): - """ - Returns True if ``x`` is a PermutationGroupElement. + r""" + Return ``True`` if ``x`` is a :class:`PermutationGroupElement`. EXAMPLES:: @@ -211,13 +213,12 @@ def is_PermutationGroupElement(x): return isinstance(x, PermutationGroupElement) cdef class PermutationGroupElement(MultiplicativeGroupElement): - """ + r""" An element of a permutation group. EXAMPLES:: - sage: G = PermutationGroup(['(1,2,3)(4,5)']) - sage: G + sage: G = PermutationGroup(['(1,2,3)(4,5)']); G Permutation Group with generators [(1,2,3)(4,5)] sage: g = G.random_element() sage: g in G @@ -262,7 +263,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): There are several ways to define a permutation group element: - Define a permutation group `G`, then use - ``G.gens()`` and multiplication \* to construct + ``G.gens()`` and multiplication ``*`` to construct elements. - Define a permutation group `G`, then use, e.g., @@ -278,9 +279,9 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): - ``g`` -- defines element - ``parent`` -- defines parent group (``g`` must be in - parent if specified, or a ``TypeError`` is raised) + parent if specified, or a :class:`TypeError` is raised) - - ``check`` - bool (default: ``True``); if ``False`` assumes ``g`` + - ``check`` -- bool (default: ``True``); if ``False`` assumes ``g`` is a gap element in parent (if specified) @@ -310,8 +311,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): :: - sage: g = G([(1,2),(3,5,6)]) - sage: g + sage: g = G([(1,2),(3,5,6)]); g (1,2)(3,5,6) sage: g.parent() Permutation Group with generators [(1,2)(3,4), (3,4,5,6)] @@ -328,15 +328,14 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): True We can also make a permutation group element directly using the - ``PermutationGroupElement`` command. Note that the + :class:`PermutationGroupElement` command. Note that the parent is then the full symmetric group `S_n`, where `n` is the largest integer that is moved by the permutation. :: - sage: k = PermutationGroupElement('(1,2)(3,5,6)') - sage: k + sage: k = PermutationGroupElement('(1,2)(3,5,6)'); k (1,2)(3,5,6) sage: k.parent() Symmetric group of order 6! as a permutation group @@ -368,11 +367,11 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): sage: S = SymmetricGroup(5) sage: S(Permutation([5,1,4,3,2])) (1,5,2)(3,4) - sage: S(gp.Vecsmall([5,1,4,3,2])) + sage: S(gp.Vecsmall([5,1,4,3,2])) # needs sage.libs.pari (1,5,2)(3,4) sage: S(gap.PermList([5,1,4,3,2])) (1,5,2)(3,4) - sage: S(pari.Vecsmall([5,1,4,3,2])) + sage: S(pari.Vecsmall([5,1,4,3,2])) # needs sage.libs.pari (1,5,2)(3,4) sage: S(libgap.PermList([5,1,4,3,2])) (1,5,2)(3,4) @@ -794,7 +793,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def __reduce__(self): - """ + r""" Returns a function and its arguments needed to create this permutation group element. This is used in pickling. @@ -828,7 +827,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return other def _gap_(self, gap=None): - """ + r""" TESTS:: sage: g = PermutationGroupElement([(1,2,3),(4,5)]); g @@ -854,12 +853,14 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): sage: S(p_libgap) == p True + sage: # needs sage.rings.finite_rings sage: P = PGU(8,2) sage: p, q = P.gens() sage: p_libgap = p.gap() TESTS:: + sage: # needs sage.rings.finite_rings sage: P = PGU(8,2) sage: p, q = P.gens() sage: p_pexpect = gap(p) @@ -899,7 +900,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): gap = _libgap_ def _gap_init_(self): - """ + r""" Returns a GAP string representation for this PermutationGroupElement. @@ -911,9 +912,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): """ return 'PermList(%s)' % self._gap_list() - def _repr_(self): - """ + r""" Return string representation of this permutation. EXAMPLES: @@ -956,8 +956,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): for cycle in self.cycle_tuples()) def __getitem__(self, i): - """ - Return the ith permutation cycle in the disjoint cycle + r""" + Return the ``i``-th permutation cycle in the disjoint cycle representation of self. INPUT: @@ -978,7 +978,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return self.cycles()[i] cpdef _richcmp_(self, other, int op): - """ + r""" Compare group elements ``self`` and ``other``. EXAMPLES:: @@ -1024,7 +1024,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return rich_to_bool(op, 0) def __call__(self, i): - """ + r""" Returns 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. @@ -1046,7 +1046,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): :: - sage: g(x) + sage: g(x) # needs sage.symbolic Traceback (most recent call last): ... ValueError: must be in the domain or a list, tuple or string @@ -1087,7 +1087,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return from_gap[i] cpdef list _act_on_list_on_position(self, list x): - """ + r""" Returns the right action of ``self`` on the list ``x``. This is the action on positions. @@ -1115,7 +1115,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return [ x[self.perm[i]] for i in range(self.n) ] cpdef ClonableIntArray _act_on_array_on_position(self, ClonableIntArray x): - """ + r""" Returns the right action of ``self`` on the ClonableIntArray ``x``. This is the action on positions. @@ -1299,7 +1299,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return coercion_model.bin_op(left, right, operator.mul) cpdef _mul_(left, _right): - """ + r""" EXAMPLES:: sage: S = SymmetricGroup(['a', 'b']) @@ -1316,7 +1316,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return prod cpdef PermutationGroupElement _generate_new(self, list v): - """ + r""" Generate a new permutation group element with the same parent as ``self`` from ``v``. @@ -1334,7 +1334,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return new cpdef PermutationGroupElement _generate_new_GAP(self, lst_in): - """ + r""" Generate a new permutation group element with the same parent as ``self`` from the GAP list ``lst_in``. @@ -1367,7 +1367,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return new def __invert__(self): - """ + r""" Return the inverse of this permutation. EXAMPLES:: @@ -1385,7 +1385,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return inv cpdef _gap_list(self): - """ + r""" Returns this permutation in list notation compatible with the GAP numbering. @@ -1409,7 +1409,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return [self.perm[i]+1 for i from 0 <= i < self.n] def _gap_cycle_string(self): - """ + r""" Returns a cycle string for this permutation compatible with the GAP numbering. @@ -1433,8 +1433,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return Permutation(self._gap_list()).cycle_string() cpdef domain(self): - """ - Returns the domain of self. + r""" + Return the domain of ``self``. EXAMPLES:: @@ -1466,7 +1466,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return [from_gap[self.perm[i]+1] for i from 0 <= i < self.n] def __hash__(self): - """ + r""" Return a hash for this permutation. EXAMPLES:: @@ -1495,8 +1495,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return ans def tuple(self): - """ - Return tuple of images of the domain under self. + r""" + Return tuple of images of the domain under ``self``. EXAMPLES:: @@ -1517,8 +1517,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return tuple([from_gap[self.perm[i]+1] for i in range(self.n)]) def dict(self): - """ - Returns a dictionary associating each element of the domain with its + r""" + Return a dictionary associating each element of the domain with its image. EXAMPLES:: @@ -1541,7 +1541,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return {e:from_gap[self.perm[i-1]+1] for e,i in to_gap.iteritems()} def multiplicative_order(self): - """ + r""" Return the order of this group element, which is the smallest positive integer `n` for which `g^n = 1`. @@ -1551,13 +1551,14 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): sage: s.multiplicative_order() 6 - ``order`` is just an alias for ``multiplicative_order``:: + :meth:`order` is just an alias for :meth:`multiplicative_order`:: sage: s.order() 6 TESTS:: + sage: # needs sage.libs.pari sage: prod(primes(150)) 1492182350939279320058875736615841068547583863326864530410 sage: L = [tuple(range(sum(primes(p))+1, sum(primes(p))+1+p)) for p in primes(150)] @@ -1593,7 +1594,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def inverse(self): r""" - Returns the inverse permutation. + Return the inverse permutation. OUTPUT: @@ -1625,7 +1626,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def sign(self): r""" - Returns the sign of self, which is `(-1)^{s}`, where + Return the sign of ``self``, which is `(-1)^{s}`, where `s` is the number of swaps. EXAMPLES:: @@ -1661,8 +1662,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def orbit(self, n, bint sorted=True): - """ - Returns the orbit of the integer `n` under this group + r""" + Return the orbit of the integer `n` under this group element, as a sorted list. EXAMPLES:: @@ -1705,8 +1706,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return from_gap[n] def cycles(self): - """ - Return self as a list of disjoint cycles. + r""" + Return ``self`` as a list of disjoint cycles. EXAMPLES:: @@ -1740,13 +1741,13 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return L def cycle_tuples(self, singletons=False): - """ - Return self as a list of disjoint cycles, represented as tuples + r""" + Return ``self`` as a list of disjoint cycles, represented as tuples rather than permutation group elements. INPUT: - - ``singletons`` - boolean (default: False) whether or not consider the + - ``singletons`` -- boolean (default: ``False``) whether or not consider the cycle that correspond to fixed point EXAMPLES:: @@ -1799,10 +1800,10 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return L def cycle_string(self, singletons=False): - """ + r""" Return string representation of this permutation. - EXAMPLES:: + EXAMPLES:: sage: g = PermutationGroupElement([(1,2,3),(4,5)]) sage: g.cycle_string() @@ -1820,29 +1821,30 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): def cycle_type(self, singletons=True, as_list=False): r""" - Return the partition that gives the cycle type of ``g`` as an element of - ``self``. + Return the partition that gives the cycle type of ``self`` as an element of + its parent. INPUT: - ``g`` -- an element of the permutation group ``self.parent()`` - - ``singletons`` -- ``True`` or ``False`` depending on whether on or not + - ``singletons`` -- ``True`` or ``False`` depending on whether or not trivial cycles should be counted (default: ``True``) - ``as_list`` -- ``True`` or ``False`` depending on whether the cycle - type should be returned as a ``list`` or as a :class:`Partition` + type should be returned as a :class:`list` or as a :class:`Partition` (default: ``False``) OUTPUT: - A :class:`Partition`, or list if ``is_list`` is ``True``, - giving the cycle type of ``g`` + 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. + If speed is a concern, then ``as_list=True`` should be used. EXAMPLES:: + sage: # needs sage.combinat sage: G = DihedralGroup(3) sage: [g.cycle_type() for g in G] [[1, 1, 1], [3], [3], [2, 1], [2, 1], [2, 1]] @@ -1870,11 +1872,11 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): INPUT: - ``i`` -- an element of the index set - - ``side`` -- "left" or "right" (default: "right") - - ``positive`` -- a boolean (default: False) + - ``side`` -- ``"left"`` or ``"right"`` (default: ``"right"``) + - ``positive`` -- a boolean (default: ``False``) Returns whether ``self`` has a left (resp. right) descent at - position ``i``. If ``positive`` is True, then test for a non + position ``i``. If ``positive`` is ``True``, then test for a non descent instead. Beware that, since permutations are acting on the right, the @@ -1891,13 +1893,13 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): False sage: s = S.simple_reflections() sage: x = s[1]*s[2] - sage: x.has_descent(1, side = "right") + sage: x.has_descent(1, side="right") False - sage: x.has_descent(2, side = "right") + sage: x.has_descent(2, side="right") True - sage: x.has_descent(1, side = "left") + sage: x.has_descent(1, side="left") True - sage: x.has_descent(2, side = "left") + sage: x.has_descent(2, side="left") False sage: S._test_has_descent() @@ -1924,9 +1926,9 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return (to_gap[self(i)] > to_gap[self(i1)]) is not positive def matrix(self): - """ - Returns deg x deg permutation matrix associated to the permutation - self + r""" + Return a deg `\times` deg permutation matrix associated to the permutation + ``self``. EXAMPLES:: @@ -1939,6 +1941,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): [0 0 0 0 1] [0 0 0 1 0] """ + from sage.matrix.matrix_space import MatrixSpace M = MatrixSpace(ZZ, self.n, self.n, sparse=True) cdef int i entries = {} @@ -1947,7 +1950,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return M(entries) def word_problem(self, words, display=True, as_list=False): - """ + r""" Try to solve the word problem for ``self``. INPUT: @@ -1979,8 +1982,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): This function does not solve the word problem in Sage. Rather it pushes it over to GAP, which has optimized algorithms for the word problem. Essentially, this function is a wrapper for the GAP - functions "EpimorphismFromFreeGroup" and - "PreImagesRepresentative". + functions ``EpimorphismFromFreeGroup`` and + ``PreImagesRepresentative``. EXAMPLES:: @@ -2045,11 +2048,11 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cdef class SymmetricGroupElement(PermutationGroupElement): - """ + r""" An element of the symmetric group. """ def absolute_length(self): - """ + r""" Return the absolute length of ``self``. The absolute length is the size minus the number of its disjoint @@ -2063,14 +2066,14 @@ cdef class SymmetricGroupElement(PermutationGroupElement): EXAMPLES:: sage: S = SymmetricGroup(3) - sage: [x.absolute_length() for x in S] + sage: [x.absolute_length() for x in S] # needs sage.combinat [0, 2, 2, 1, 1, 1] """ from sage.combinat.permutation import Permutation return Permutation(self).absolute_length() def has_left_descent(self, i): - """ + r""" Return whether `i` is a left descent of ``self``. EXAMPLES:: @@ -2084,7 +2087,7 @@ cdef class SymmetricGroupElement(PermutationGroupElement): cdef bint is_valid_permutation(int* perm, int n): - """ + r""" This is used in the __init__ method. Returns True iff the first n elements of perm are literally a diff --git a/src/sage/groups/perm_gps/permgroup_morphism.py b/src/sage/groups/perm_gps/permgroup_morphism.py index 917ddd01865..0a86068790b 100644 --- a/src/sage/groups/perm_gps/permgroup_morphism.py +++ b/src/sage/groups/perm_gps/permgroup_morphism.py @@ -15,7 +15,8 @@ sage: g = G([(1,2,3,4)]) sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())) sage: phi.image(G) - Subgroup generated by [(1,2,3,4)] of (Dihedral group of order 8 as a permutation group) + Subgroup generated by [(1,2,3,4)] of + (Dihedral group of order 8 as a permutation group) sage: phi.kernel() Subgroup generated by [()] of (Cyclic group of order 4 as a permutation group) sage: phi.image(g) @@ -42,11 +43,11 @@ class PermutationGroupMorphism(Morphism): - """ + r""" A set-theoretic map between PermutationGroups. """ def _repr_type(self): - """ + r""" Return the type of this morphism. This is used for printing the morphism. @@ -61,7 +62,7 @@ def _repr_type(self): return "Permutation group" def kernel(self): - """ + r""" Return the kernel of this homomorphism as a permutation group. EXAMPLES:: @@ -71,7 +72,8 @@ def kernel(self): sage: g = G([(1,2,3,4)]) sage: phi = PermutationGroupMorphism_im_gens(G, H, [1]) sage: phi.kernel() - Subgroup generated by [(1,2,3,4)] of (Cyclic group of order 4 as a permutation group) + Subgroup generated by [(1,2,3,4)] of + (Cyclic group of order 4 as a permutation group) :: @@ -85,9 +87,10 @@ def kernel(self): return self.domain().subgroup(gap_group=self._gap_().Kernel()) def image(self, J): - """ - J must be a subgroup of G. Computes the subgroup of H which is the - image of J. + r""" + Compute the subgroup of the codomain `H` which is the image of `J`. + + `J` must be a subgroup of the domain `G`. EXAMPLES:: @@ -96,7 +99,8 @@ def image(self, J): sage: g = G([(1,2,3,4)]) sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())) sage: phi.image(G) - Subgroup generated by [(1,2,3,4)] of (Dihedral group of order 8 as a permutation group) + Subgroup generated by [(1,2,3,4)] of + (Dihedral group of order 8 as a permutation group) sage: phi.image(g) (1,2,3,4) @@ -107,12 +111,14 @@ def image(self, J): sage: H = D[0] sage: pr1 = D[3] sage: pr1.image(G) - Subgroup generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)] of (The projective special linear group of degree 2 over Finite Field of size 7) + Subgroup generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)] of + (The projective special linear group of degree 2 over Finite Field of size 7) sage: G.is_isomorphic(pr1.image(G)) True Check that :trac:`28324` is fixed:: + sage: # needs sage.rings.number_field sage: R. = QQ[] sage: f = x^4 + x^2 - 3 sage: L. = f.splitting_field() @@ -134,9 +140,9 @@ def image(self, J): return H.subgroup(gap_group=G) def __call__(self, g): - """ - Some python code for wrapping GAP's Images function but only for - permutation groups. This returns an error if g is not in G. + r""" + Some python code for wrapping GAP's ``Images`` function but only for + permutation groups. This raises an error if g is not in G. EXAMPLES:: @@ -157,18 +163,18 @@ class PermutationGroupMorphism_id(PermutationGroupMorphism): class PermutationGroupMorphism_from_gap(PermutationGroupMorphism): def __init__(self, G, H, gap_hom): - """ + r""" This is a Python trick to allow Sage programmers to create a group homomorphism using GAP using very general constructions. An example of its usage is in the direct_product instance method of the - PermutationGroup_generic class in permgroup.py. + :class:`PermutationGroup_generic` class in permgroup.py. Basic syntax: - PermutationGroupMorphism_from_gap(domain_group, - range_group,'phi:=gap_hom_command;','phi') And don't forget the - line: from sage.groups.perm_gps.permgroup_morphism import - PermutationGroupMorphism_from_gap in your program. + ``PermutationGroupMorphism_from_gap(domain_group, + range_group, 'phi:=gap_hom_command;', 'phi')``. And don't forget the + line: ``from sage.groups.perm_gps.permgroup_morphism import + PermutationGroupMorphism_from_gap`` in your program. EXAMPLES:: @@ -177,7 +183,8 @@ def __init__(self, G, H, gap_hom): sage: H = G.subgroup([G([(1,2,3,4)])]) sage: PermutationGroupMorphism_from_gap(H, G, gap.Identity) Permutation group morphism: - From: Subgroup generated by [(1,2,3,4)] of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) + From: Subgroup generated by [(1,2,3,4)] of + (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) To: Permutation Group with generators [(1,2)(3,4), (1,2,3,4)] Defn: Identity """ @@ -187,7 +194,7 @@ def __init__(self, G, H, gap_hom): self._gap_hom = gap_hom def _repr_defn(self): - """ + r""" Return the definition of this morphism. This is used when printing the morphism. @@ -204,7 +211,7 @@ def _repr_defn(self): return str(self._gap_hom).replace('\n', '') def _gap_(self, gap=None): - """ + r""" Return a GAP version of this morphism. EXAMPLES:: @@ -219,7 +226,7 @@ def _gap_(self, gap=None): return self._gap_hom def __call__(self, g): - """ + r""" Some python code for wrapping GAP's Images function but only for permutation groups. This returns an error if g is not in G. @@ -237,8 +244,8 @@ def __call__(self, g): class PermutationGroupMorphism_im_gens(PermutationGroupMorphism): def __init__(self, G, H, gens=None): - """ - Some python code for wrapping GAP's GroupHomomorphismByImages + r""" + Some python code for wrapping GAP's ``GroupHomomorphismByImages`` function but only for permutation groups. Can be expensive if G is large. This returns "fail" if gens does not generate self or if the map does not extend to a group homomorphism, self - other. @@ -273,7 +280,7 @@ def __init__(self, G, H, gens=None): self._images = [H(img) for img in gens] def _repr_defn(self): - """ + r""" Return the definition of this morphism. This is used when printing the morphism. @@ -289,7 +296,7 @@ def _repr_defn(self): return "%s -> %s" % (list(self.domain().gens()), self._images) def _gap_(self): - """ + r""" Return a GAP representation of this morphism. EXAMPLES:: @@ -305,8 +312,8 @@ def _gap_(self): def is_PermutationGroupMorphism(f) -> bool: - """ - Return True if the argument ``f`` is a PermutationGroupMorphism. + r""" + Return ``True`` if the argument ``f`` is a :class:`PermutationGroupMorphism`. EXAMPLES:: diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index 7b3d4947f75..75e26765b3a 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -3,65 +3,64 @@ You can construct the following permutation groups: --- SymmetricGroup, `S_n` of order `n!` (n can also be a list `X` of distinct - positive integers, in which case it returns `S_X`) +- :class:`SymmetricGroup`, `S_n` of order `n!` (`n` can also be a list `X` of distinct + positive integers, in which case it returns `S_X`) --- AlternatingGroup, `A_n` of order `n!/2` (n can also be a list `X` - of distinct positive integers, in which case it returns - `A_X`) +- :class:`AlternatingGroup`, `A_n` of order `n!/2` (n can also be a list `X` + of distinct positive integers, in which case it returns `A_X`) --- DihedralGroup, `D_n` of order `2n` +- :class:`DihedralGroup`, `D_n` of order `2n` --- GeneralDihedralGroup, `Dih(G)`, where G is an abelian group +- :class:`GeneralDihedralGroup`, `Dih(G)`, where `G` is an abelian group --- CyclicPermutationGroup, `C_n` of order `n` +- :class:`CyclicPermutationGroup`, `C_n` of order `n` --- DiCyclicGroup, nonabelian groups of order `4m` with a unique element of order 2 +- :class:`DiCyclicGroup`, nonabelian groups of order `4m` with a unique element of order 2 --- TransitiveGroup, `n^{th}` transitive group of degree `d` - from the GAP tables of transitive groups +- :class:`TransitiveGroup`, `n`-th` transitive group of degree `d` + from the GAP tables of transitive groups --- TransitiveGroups(d), TransitiveGroups(), set of all of the above +- ``TransitiveGroups(d)``, ``TransitiveGroups()``, set of all of the above --- PrimitiveGroup, `n^{th}` primitive group of degree `d` - from the GAP tables of primitive groups +- :class:`PrimitiveGroup`, `n`-th` primitive group of degree `d` + from the GAP tables of primitive groups --- PrimitiveGroups(d), PrimitiveGroups(), set of all of the above +- ``PrimitiveGroups(d)``, ``PrimitiveGroups()``, set of all of the above --- MathieuGroup(degree), Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24. +- ``MathieuGroup(degree)``, Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24. --- KleinFourGroup, subgroup of `S_4` of order `4` which is not `C_2 \times C_2` +- :class:`KleinFourGroup`, subgroup of `S_4` of order `4` which is not `C_2 \times C_2` --- QuaternionGroup, non-abelian group of order `8`, `\{\pm 1, \pm I, \pm J, \pm K\}` +- :class:`QuaternionGroup`, non-abelian group of order `8`, `\{\pm 1, \pm I, \pm J, \pm K\}` --- SplitMetacyclicGroup, nonabelian groups of order `p^m` with cyclic -subgroups of index p +- :class:`SplitMetacyclicGroup`, nonabelian groups of order `p^m` with cyclic + subgroups of index p --- SemidihedralGroup, nonabelian 2-groups with cyclic subgroups of index 2 +- :class:`SemidihedralGroup`, nonabelian 2-groups with cyclic subgroups of index 2 --- PGL(n,q), projective general linear group of `n\times n` matrices over - the finite field GF(q) +- ``PGL(n,q)``, projective general linear group of `n\times n` matrices over + the finite field `\GF(q)` --- PSL(n,q), projective special linear group of `n\times n` matrices over - the finite field GF(q) +- ``PSL(n,q)``, projective special linear group of `n\times n` matrices over + the finite field `\GF(q)` --- PSp(2n,q), projective symplectic linear group of `2n\times 2n` matrices - over the finite field GF(q) +- ``PSp(2n,q)``, projective symplectic linear group of `2n\times 2n` matrices + over the finite field `\GF(q)` --- PSU(n,q), projective special unitary group of `n \times n` matrices having - coefficients in the finite field `GF(q^2)` that respect a - fixed nondegenerate sesquilinear form, of determinant 1. +- ``PSU(n,q)``, projective special unitary group of `n \times n` matrices having + coefficients in the finite field `\GF(q^2)` that respect a + fixed nondegenerate sesquilinear form, of determinant 1. --- PGU(n,q), projective general unitary group of `n\times n` matrices having - coefficients in the finite field `GF(q^2)` that respect a - fixed nondegenerate sesquilinear form, modulo the centre. +- ``PGU(n,q)``, projective general unitary group of `n\times n` matrices having + coefficients in the finite field `\GF(q^2)` that respect a + fixed nondegenerate sesquilinear form, modulo the centre. --- SuzukiGroup(q), Suzuki group over GF(q), `^2 B_2(2^{2k+1}) = Sz(2^{2k+1})`. +- ``SuzukiGroup(q)``, Suzuki group over `\GF(q)`, `^2 B_2(2^{2k+1}) = Sz(2^{2k+1})`. --- ComplexReflectionGroup, the complex reflection group `G(m, p, n)` or - the exceptional complex reflection group `G_m` +- :class:`ComplexReflectionGroup`, the complex reflection group `G(m, p, n)` or + the exceptional complex reflection group `G_m` --- SmallPermutationGroup, a permutation realization of an group specified by its GAP id. +- :class:`SmallPermutationGroup`, a permutation realization of a group specified by its GAP id. AUTHOR: @@ -148,7 +147,7 @@ def __classcall__(cls, *args, **kwds): class PermutationGroup_symalt(PermutationGroup_unique): """ This is a class used to factor out some of the commonality - in the SymmetricGroup and AlternatingGroup classes. + in the :class:`SymmetricGroup` and :class:`AlternatingGroup` classes. """ @staticmethod @@ -251,9 +250,9 @@ def __init__(self, domain=None): TESTS:: - sage: TestSuite(SymmetricGroup(0)).run() - sage: TestSuite(SymmetricGroup(1)).run() - sage: TestSuite(SymmetricGroup(3)).run() + sage: TestSuite(SymmetricGroup(0)).run() # needs sage.rings.number_field + sage: TestSuite(SymmetricGroup(1)).run() # needs sage.rings.number_field + sage: TestSuite(SymmetricGroup(3)).run() # needs sage.rings.number_field """ from sage.categories.finite_weyl_groups import FiniteWeylGroups from sage.categories.finite_permutation_groups import FinitePermutationGroups @@ -339,14 +338,14 @@ def _coerce_map_from_(self, G): EXAMPLES:: - sage: J3 = groups.misc.Cactus(3) + sage: J3 = groups.misc.Cactus(3) # needs sage.rings.number_field sage: S5 = SymmetricGroup(5) - sage: S5.coerce_map_from(J3) + sage: S5.coerce_map_from(J3) # needs sage.rings.number_field Conversion via _from_cactus_group_element map: From: Cactus Group with 3 fruit To: Symmetric group of order 5! as a permutation group sage: S2 = SymmetricGroup(2) - sage: S2._coerce_map_from_(J3) is None + sage: S2._coerce_map_from_(J3) is None # needs sage.rings.number_field True """ from sage.groups.cactus_group import CactusGroup @@ -360,6 +359,7 @@ def _from_cactus_group_element(self, x): EXAMPLES:: + sage: # needs sage.rings.number_field sage: J3 = groups.misc.Cactus(3) sage: s12,s13,s23 = J3.gens() sage: elt = s12*s23*s13 @@ -392,7 +392,7 @@ def coxeter_matrix(self): EXAMPLES:: - sage: A = SymmetricGroup([2,3,7,'a']); A.coxeter_matrix() + sage: A = SymmetricGroup([2,3,7,'a']); A.coxeter_matrix() # needs sage.graphs [1 3 2] [3 1 3] [2 3 1] @@ -401,7 +401,7 @@ def coxeter_matrix(self): def simple_reflection(self, i): r""" - For `i` in the index set of ``self``, this returns the + For `i` in the index set of ``self``, return the elementary transposition `s_i = (i,i+1)`. EXAMPLES:: @@ -439,11 +439,13 @@ def young_subgroup(self, comp): sage: S = SymmetricGroup(8) sage: c = Composition([2,2,2,2]) sage: S.young_subgroup(c) - Subgroup generated by [(7,8), (5,6), (3,4), (1,2)] of (Symmetric group of order 8! as a permutation group) + Subgroup generated by [(7,8), (5,6), (3,4), (1,2)] of + (Symmetric group of order 8! as a permutation group) sage: S = SymmetricGroup(['a','b','c']) sage: S.young_subgroup([2,1]) - Subgroup generated by [('a','b')] of (Symmetric group of order 3! as a permutation group) + Subgroup generated by [('a','b')] of + (Symmetric group of order 3! as a permutation group) sage: Y = S.young_subgroup([2,2,2,2,2]) Traceback (most recent call last): @@ -483,10 +485,10 @@ def major_index(self, parameter=None): EXAMPLES:: sage: S4 = SymmetricGroup(4) - sage: S4.major_index() + sage: S4.major_index() # needs sage.combinat q^6 + 3*q^5 + 5*q^4 + 6*q^3 + 5*q^2 + 3*q + 1 sage: K. = QQ[] - sage: S4.major_index(t) + sage: S4.major_index(t) # needs sage.combinat t^6 + 3*t^5 + 5*t^4 + 6*t^3 + 5*t^2 + 3*t + 1 """ from sage.combinat.q_analogues import q_factorial @@ -505,14 +507,14 @@ def conjugacy_classes_representatives(self): EXAMPLES:: sage: G = SymmetricGroup(5) - sage: G.conjugacy_classes_representatives() + sage: G.conjugacy_classes_representatives() # needs sage.combinat [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)] :: sage: S = SymmetricGroup(['a','b','c']) - sage: S.conjugacy_classes_representatives() + sage: S.conjugacy_classes_representatives() # needs sage.combinat [(), ('a','b'), ('a','b','c')] TESTS: @@ -520,10 +522,10 @@ def conjugacy_classes_representatives(self): Check some border cases:: sage: S = SymmetricGroup(0) - sage: S.conjugacy_classes_representatives() + sage: S.conjugacy_classes_representatives() # needs sage.combinat [()] sage: S = SymmetricGroup(1) - sage: S.conjugacy_classes_representatives() + sage: S.conjugacy_classes_representatives() # needs sage.combinat [()] """ from sage.combinat.partition import Partitions_n @@ -539,7 +541,7 @@ def conjugacy_classes_iterator(self): EXAMPLES:: sage: G = SymmetricGroup(5) - sage: list(G.conjugacy_classes_iterator()) == G.conjugacy_classes() + sage: list(G.conjugacy_classes_iterator()) == G.conjugacy_classes() # needs sage.combinat True """ from sage.combinat.partition import Partitions_n @@ -555,7 +557,7 @@ def conjugacy_classes(self): EXAMPLES:: sage: G = SymmetricGroup(5) - sage: G.conjugacy_classes() + sage: G.conjugacy_classes() # needs sage.combinat [Conjugacy class of cycle type [1, 1, 1, 1, 1] in Symmetric group of order 5! as a permutation group, Conjugacy class of cycle type [2, 1, 1, 1] in @@ -590,7 +592,7 @@ def conjugacy_class(self, g): sage: G = SymmetricGroup(5) sage: g = G((1,2,3,4)) - sage: G.conjugacy_class(g) + sage: G.conjugacy_class(g) # needs sage.combinat Conjugacy class of cycle type [4, 1] in Symmetric group of order 5! as a permutation group """ @@ -614,37 +616,37 @@ def algebra(self, base_ring, category=None): EXAMPLES:: sage: S4 = SymmetricGroup(4) - sage: S4.algebra(QQ) + sage: S4.algebra(QQ) # needs sage.combinat Symmetric group algebra of order 4 over Rational Field sage: S3 = SymmetricGroup([1,2,3]) - sage: A = S3.algebra(QQ); A + sage: A = S3.algebra(QQ); A # needs sage.combinat Symmetric group algebra of order 3 over Rational Field sage: a = S3.an_element(); a (2,3) - sage: A(a) + sage: A(a) # needs sage.combinat (2,3) We illustrate the choice of the category:: - sage: A.category() + sage: A.category() # needs sage.combinat Join of Category of coxeter group algebras over Rational Field and Category of finite group algebras over Rational Field and Category of finite dimensional cellular algebras with basis over Rational Field - sage: A = S3.algebra(QQ, category=Semigroups()) - sage: A.category() + sage: A = S3.algebra(QQ, category=Semigroups()) # needs sage.combinat + sage: A.category() # needs sage.combinat Category of finite dimensional unital cellular semigroup algebras over Rational Field In the following case, a usual group algebra is returned:: sage: S = SymmetricGroup([2,3,5]) - sage: S.algebra(QQ) + sage: S.algebra(QQ) # needs sage.combinat Algebra of Symmetric group of order 3! as a permutation group over Rational Field sage: a = S.an_element(); a (3,5) - sage: S.algebra(QQ)(a) + sage: S.algebra(QQ)(a) # needs sage.combinat (3,5) """ from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra @@ -725,11 +727,11 @@ def _gap_init_(self, gap=None): class CyclicPermutationGroup(PermutationGroup_unique): def __init__(self, n): """ - A cyclic group of order n, as a permutation group. + A cyclic group of order `n`, as a permutation group. INPUT: - n -- a positive integer + - ``n`` -- a positive integer .. note:: @@ -774,7 +776,7 @@ def _repr_(self): def is_commutative(self): """ - Return True if this group is commutative. + Return ``True`` if this group is commutative. EXAMPLES:: @@ -786,7 +788,7 @@ def is_commutative(self): def is_abelian(self): """ - Return True if this group is abelian. + Return ``True`` if this group is abelian. EXAMPLES:: @@ -798,7 +800,7 @@ def is_abelian(self): def as_AbelianGroup(self): """ - Returns the corresponding Abelian Group instance. + Return the corresponding :class:`AbelianGroup` instance. EXAMPLES:: @@ -819,7 +821,7 @@ class DiCyclicGroup(PermutationGroup_unique): INPUT: - - n -- a positive integer, two or greater + - ``n`` -- a positive integer, two or greater OUTPUT: @@ -1127,7 +1129,7 @@ class QuaternionGroup(DiCyclicGroup): OUTPUT: The quaternion group of order 8, as a permutation group. - See the ``DiCyclicGroup`` class for a generalization of this + See the :class:`DiCyclicGroup` class for a generalization of this construction. .. note:: @@ -1198,7 +1200,7 @@ class GeneralDihedralGroup(PermutationGroup_generic): INPUT: - - ``factors`` - a list of the sizes of the cyclic factors of the + - ``factors`` -- a list of the sizes of the cyclic factors of the abelian group being dihedralized (this will be sorted once entered) @@ -1266,7 +1268,7 @@ class GeneralDihedralGroup(PermutationGroup_generic): If two nonidentical input lists generate isomorphic abelian groups, then they will generate identical groups (with each direct factor broken up into its prime factors), but they will still have - distinct descriptions. Note that If `gcd(n,m)=1`, then `C_n \times + distinct descriptions. Note that if `\gcd(n,m)=1`, then `C_n \times C_m \cong C_{nm}`, while the general dihedral groups generated by isomorphic abelian groups should be themselves isomorphic. :: @@ -1433,7 +1435,8 @@ def __init__(self, n): sage: DihedralGroup(5).gens() ((1,2,3,4,5), (1,5)(2,4)) sage: sorted(DihedralGroup(5)) - [(), (2,5)(3,4), (1,2)(3,5), (1,2,3,4,5), (1,3)(4,5), (1,3,5,2,4), (1,4)(2,3), (1,4,2,5,3), (1,5,4,3,2), (1,5)(2,4)] + [(), (2,5)(3,4), (1,2)(3,5), (1,2,3,4,5), (1,3)(4,5), (1,3,5,2,4), + (1,4)(2,3), (1,4,2,5,3), (1,5,4,3,2), (1,5)(2,4)] sage: G = DihedralGroup(6) sage: G.order() @@ -1644,7 +1647,7 @@ def __init__(self, m): INPUT: - - ``m`` - a positive integer; the power of 2 that is the + - ``m`` -- a positive integer; the power of 2 that is the group's order OUTPUT: @@ -1754,11 +1757,11 @@ def __init__(self, n): INPUT: - n -- a positive integer in {9, 10, 11, 12, 21, 22, 23, 24}. + - ``n`` -- a positive integer in {9, 10, 11, 12, 21, 22, 23, 24}. OUTPUT: - the Mathieu group of degree n, as a permutation group + the Mathieu group of degree `n`, as a permutation group .. note:: @@ -1766,8 +1769,7 @@ def __init__(self, n): EXAMPLES:: - sage: G = MathieuGroup(12) - sage: G + sage: G = MathieuGroup(12); G Mathieu group of degree 12 and order 95040 as a permutation group TESTS:: @@ -1807,13 +1809,13 @@ def __init__(self, d, n): INPUT: - - d -- non-negative integer; the degree - - n -- positive integer; the index of the group in the GAP database, + - ``d`` -- non-negative integer; the degree + - ``n`` -- positive integer; the index of the group in the GAP database, starting at 1 OUTPUT: - the n-th transitive group of degree d + the `n`-th transitive group of degree `d` .. note:: @@ -1847,7 +1849,8 @@ def __init__(self, d, n): sage: TransitiveGroup(32,1) Traceback (most recent call last): ... - NotImplementedError: only the transitive groups of degree at most 31 are available in GAP's database + NotImplementedError: only the transitive groups of degree at most 31 + are available in GAP's database TESTS:: @@ -1915,7 +1918,7 @@ def TransitiveGroups(d=None): - ``d`` -- an integer (optional) - Returns the set of all transitive groups of a given degree + 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 transitive groups up to isomorphisms. @@ -1937,7 +1940,8 @@ def TransitiveGroups(d=None): sage: TransitiveGroups(32).cardinality() Traceback (most recent call last): ... - NotImplementedError: only the transitive groups of degree at most 31 are available in GAP's database + NotImplementedError: only the transitive groups of degree at most 31 + are available in GAP's database """ if d is None: @@ -2167,7 +2171,8 @@ def cardinality(self): sage: TransitiveGroups(32).cardinality() Traceback (most recent call last): ... - NotImplementedError: only the transitive groups of degree at most 31 are available in GAP's database + NotImplementedError: only the transitive groups of degree at most 31 + are available in GAP's database TESTS:: @@ -2617,18 +2622,18 @@ def matrix_degree(self): class PGL(PermutationGroup_plg): def __init__(self, n, q, name='a'): - """ - The projective general linear groups over GF(q). + r""" + The projective general linear groups over `\GF(q)`. INPUT: - - n -- positive integer; the degree - - q -- prime power; the size of the ground field - - name -- (default: 'a') variable name of indeterminate of finite field GF(q) + - ``n`` -- positive integer; the degree + - ``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) + PGL(`n`, `q`) .. note:: @@ -2645,7 +2650,7 @@ def __init__(self, n, q, name='a'): sage: G.order() 24 - sage: G = PGL(2, 9, 'b'); G + sage: G = PGL(2, 9, 'b'); G # needs sage.rings.finite_rings Permutation Group with generators [(3,10,9,8,4,7,6,5), (1,2,4)(5,6,8)(7,9,10)] sage: G.base_ring() Finite Field in b of size 3^2 @@ -2679,18 +2684,18 @@ def __str__(self): class PSL(PermutationGroup_plg): def __init__(self, n, q, name='a'): - """ - The projective special linear groups over GF(q). + r""" + The projective special linear groups over `\GF(q)`. INPUT: - - n -- positive integer; the degree - - 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) + - ``n`` -- positive integer; the degree + - ``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: - the group PSL(n,q) + the group PSL(`n`, `q`) .. note:: @@ -2709,11 +2714,11 @@ def __init__(self, n, q, name='a'): We create two groups over nontrivial finite fields:: - sage: G = PSL(2, 4, 'b'); G + sage: G = PSL(2, 4, 'b'); G # needs sage.rings.finite_rings Permutation Group with generators [(3,4,5), (1,2,3)] sage: G.base_ring() Finite Field in b of size 2^2 - sage: G = PSL(2, 8); G + sage: G = PSL(2, 8); G # needs sage.rings.finite_rings Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)] sage: G.base_ring() Finite Field in a of size 2^3 @@ -2766,7 +2771,7 @@ def __str__(self): def ramification_module_decomposition_hurwitz_curve(self): r""" Helps compute the decomposition of the ramification module - for the Hurwitz curves X (over CC say) with automorphism group + for the Hurwitz curves X (over `\CC` say) with automorphism group G = PSL(2,q), q a "Hurwitz prime" (ie, p is `\pm 1 \pmod 7`). Using this computation and Borne's formula helps determine the G-module structure of the RR spaces of equivariant @@ -2779,9 +2784,11 @@ def ramification_module_decomposition_hurwitz_curve(self): Here IrrRepns(G) = [pi_1,...,pi_n] (in the order listed in the output of self.character_table()). - REFERENCE: David Joyner, Amy Ksir, Roger Vogeler, - "Group representations on Riemann-Roch spaces of some - Hurwitz curves," preprint, 2006. + REFERENCE: + + David Joyner, Amy Ksir, Roger Vogeler, + "Group representations on Riemann-Roch spaces of some + Hurwitz curves," preprint, 2006. EXAMPLES:: @@ -2813,7 +2820,7 @@ def ramification_module_decomposition_hurwitz_curve(self): return mults.sage() def ramification_module_decomposition_modular_curve(self): - """ + r""" Helps compute the decomposition of the ramification module for the modular curve X(p) (over CC say) with automorphism group G = PSL(2,q), q a prime > 5. Using this computation and Borne's formula helps determine the @@ -2859,18 +2866,18 @@ def ramification_module_decomposition_modular_curve(self): class PSp(PermutationGroup_plg): def __init__(self, n, q, name='a'): - """ - The projective symplectic linear groups over GF(q). + r""" + The projective symplectic linear groups over `\GF(q)`. INPUT: - - n -- positive integer; the degree - - q -- prime power; the size of the ground field - - name -- (default: 'a') variable name of indeterminate of finite field GF(q) + - ``n`` -- positive integer; the degree + - ``q`` -- prime power; the size of the ground field + - ``name`` -- (default: ``'a'``) variable name of indeterminate of finite field `\GF(q)` OUTPUT: - PSp(n,q) + PSp(`n`, `q`) .. note:: @@ -2891,7 +2898,7 @@ def __init__(self, n, q, name='a'): sage: G.base_ring() Finite Field of size 3 - sage: G = PSp(2, 8, name='alpha'); G + sage: G = PSp(2, 8, name='alpha'); G # needs sage.rings.finite_rings Permutation Group with generators [(3,8,6,4,9,7,5), (1,2,3)(4,7,5)(6,9,8)] sage: G.base_ring() Finite Field in alpha of size 2^3 @@ -2929,7 +2936,7 @@ def field_of_definition(self): """ EXAMPLES:: - sage: PSU(2,3).field_of_definition() + sage: PSU(2,3).field_of_definition() # needs sage.rings.finite_rings Finite Field in a of size 3^2 """ return self._field_of_definition @@ -2937,8 +2944,8 @@ def field_of_definition(self): class PSU(PermutationGroup_pug): def __init__(self, n, q, name='a'): - """ - The projective special unitary groups over GF(q). + r""" + The projective special unitary groups over `\GF(q)`. INPUT: @@ -2956,17 +2963,17 @@ def __init__(self, n, q, name='a'): EXAMPLES:: - sage: PSU(2,3) + sage: PSU(2,3) # needs sage.rings.finite_rings The projective special unitary group of degree 2 over Finite Field of size 3 - sage: G = PSU(2, 8, name='alpha'); G + sage: G = PSU(2, 8, name='alpha'); G # needs sage.rings.finite_rings The projective special unitary group of degree 2 over Finite Field in alpha of size 2^3 - sage: G.base_ring() + sage: G.base_ring() # needs sage.rings.finite_rings Finite Field in alpha of size 2^3 TESTS:: - sage: groups.permutation.PSU(2, 3) + sage: groups.permutation.PSU(2, 3) # needs sage.rings.finite_rings The projective special unitary group of degree 2 over Finite Field of size 3 """ id = 'PSU(%s,%s)' % (n, q) @@ -2980,7 +2987,7 @@ def _repr_(self): """ EXAMPLES:: - sage: PSU(2,3) + sage: PSU(2,3) # needs sage.rings.finite_rings The projective special unitary group of degree 2 over Finite Field of size 3 """ @@ -2989,18 +2996,18 @@ def _repr_(self): class PGU(PermutationGroup_pug): def __init__(self, n, q, name='a'): - """ - The projective general unitary groups over GF(q). + r""" + The projective general unitary groups over `\GF(q)`. INPUT: - - n -- positive integer; the degree - - q -- prime power; the size of the ground field - - name -- (default: 'a') variable name of indeterminate of finite field GF(q) + - ``n`` -- positive integer; the degree + - ``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) + PGU(`n`, `q`) .. note:: @@ -3008,17 +3015,18 @@ def __init__(self, n, q, name='a'): EXAMPLES:: - sage: PGU(2,3) + sage: PGU(2,3) # needs sage.rings.finite_rings The projective general unitary group of degree 2 over Finite Field of size 3 - sage: G = PGU(2, 8, name='alpha'); G - The projective general unitary group of degree 2 over Finite Field in alpha of size 2^3 - sage: G.base_ring() + sage: G = PGU(2, 8, name='alpha'); G # needs sage.rings.finite_rings + The projective general unitary group of degree 2 + over Finite Field in alpha of size 2^3 + sage: G.base_ring() # needs sage.rings.finite_rings Finite Field in alpha of size 2^3 TESTS:: - sage: groups.permutation.PGU(2, 3) + sage: groups.permutation.PGU(2, 3) # needs sage.rings.finite_rings The projective general unitary group of degree 2 over Finite Field of size 3 """ id = 'PGU(%s,%s)' % (n, q) @@ -3032,7 +3040,7 @@ def _repr_(self): """ EXAMPLES:: - sage: PGU(2,3) + sage: PGU(2,3) # needs sage.rings.finite_rings The projective general unitary group of degree 2 over Finite Field of size 3 """ @@ -3042,22 +3050,22 @@ def _repr_(self): class SuzukiGroup(PermutationGroup_unique): def __init__(self, q, name='a'): r""" - The Suzuki group over GF(q), + The Suzuki group over `\GF(q)`, `^2 B_2(2^{2k+1}) = Sz(2^{2k+1})`. - A wrapper for the GAP function SuzukiGroup. + A wrapper for the GAP function ``SuzukiGroup``. INPUT: - - q -- 2^n, an odd power of 2; the size of the ground - field. (Strictly speaking, n should be greater than 1, or - else this group os not simple.) - - name -- (default: 'a') variable name of indeterminate of - finite field GF(q) + - ``q`` -- `2^n`, an odd power of 2; the size of the ground + field. (Strictly speaking, `n` should be greater than 1, or + else this group is not simple.) + - ``name`` -- (default: ``'a'``) variable name of indeterminate of + finite field `\GF(q)` OUTPUT: - - A Suzuki group. + A Suzuki group. .. note:: @@ -3065,12 +3073,13 @@ def __init__(self, q, name='a'): EXAMPLES:: - sage: SuzukiGroup(8) + sage: SuzukiGroup(8) # needs sage.rings.finite_rings Permutation Group with generators [(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64), (1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,56)] - sage: print(SuzukiGroup(8)) + sage: print(SuzukiGroup(8)) # needs sage.rings.finite_rings The Suzuki group over Finite Field in a of size 2^3 + sage: # needs sage.rings.finite_rings sage: G = SuzukiGroup(32, name='alpha') sage: G.order() 32537600 @@ -3081,7 +3090,7 @@ def __init__(self, q, name='a'): TESTS:: - sage: groups.permutation.Suzuki(8) + sage: groups.permutation.Suzuki(8) # needs sage.rings.finite_rings Permutation Group with generators [(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64), (1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,56)] @@ -3102,8 +3111,8 @@ def base_ring(self): """ EXAMPLES:: - sage: G = SuzukiGroup(32, name='alpha') - sage: G.base_ring() + sage: G = SuzukiGroup(32, name='alpha') # needs sage.rings.finite_rings + sage: G.base_ring() # needs sage.rings.finite_rings Finite Field in alpha of size 2^5 """ return self._base_ring @@ -3112,8 +3121,8 @@ def __str__(self): """ EXAMPLES:: - sage: G = SuzukiGroup(32, name='alpha') - sage: print(G) + 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 """ @@ -3469,9 +3478,9 @@ class SmallPermutationGroup(PermutationGroup_generic): Group of order 12 and GAP Id 4 as a permutation group sage: G.gens() ((1,2)(3,5)(4,10)(6,8)(7,12)(9,11), - (1,3)(2,5)(4,7)(6,9)(8,11)(10,12), - (1,4,8)(2,6,10)(3,7,11)(5,9,12)) - sage: G.character_table() + (1,3)(2,5)(4,7)(6,9)(8,11)(10,12), + (1,4,8)(2,6,10)(3,7,11)(5,9,12)) + sage: G.character_table() # needs sage.rings.number_field [ 1 1 1 1 1 1] [ 1 -1 -1 1 1 -1] [ 1 -1 1 1 -1 1] @@ -3479,15 +3488,19 @@ class SmallPermutationGroup(PermutationGroup_generic): [ 2 0 -2 -1 0 1] [ 2 0 2 -1 0 -1] sage: def numgps(n): return ZZ(libgap.NumberSmallGroups(n)) - sage: all(SmallPermutationGroup(n,k).id()==[n,k] for n in [1..64] for k in [1..numgps(n)]) + sage: all(SmallPermutationGroup(n,k).id() == [n,k] + ....: for n in [1..64] for k in [1..numgps(n)]) True sage: H = SmallPermutationGroup(6,1) sage: H.is_abelian() False sage: [H.centralizer(g) for g in H.conjugacy_classes_representatives()] - [Subgroup generated by [(1,2)(3,6)(4,5), (1,3,5)(2,4,6)] of (Group of order 6 and GAP Id 1 as a permutation group), - Subgroup generated by [(1,2)(3,6)(4,5)] of (Group of order 6 and GAP Id 1 as a permutation group), - Subgroup generated by [(1,3,5)(2,4,6), (1,5,3)(2,6,4)] of (Group of order 6 and GAP Id 1 as a permutation group)] + [Subgroup generated by [(1,2)(3,6)(4,5), (1,3,5)(2,4,6)] of + (Group of order 6 and GAP Id 1 as a permutation group), + Subgroup generated by [(1,2)(3,6)(4,5)] of + (Group of order 6 and GAP Id 1 as a permutation group), + Subgroup generated by [(1,3,5)(2,4,6), (1,5,3)(2,6,4)] of + (Group of order 6 and GAP Id 1 as a permutation group)] """ def __init__(self, order, gap_id): @@ -3528,10 +3541,10 @@ def gap_small_group(self): r""" Return the GAP small group object corresponding to ``self``. - GAP realizes some small groups as PermutationGroup, others as PcGroups + GAP realizes some small groups as ``PermutationGroup``, others as ``PcGroups`` (polycyclic groups). The :class:`SmallPermutationGroup` class always - returns a PermutationGroup, but in the process of creating this group - a GAP SmallGroup is generated. This method returns that group. + returns a ``PermutationGroup``, but in the process of creating this group + a GAP ``SmallGroup`` is generated. This method returns that group. EXAMPLES:: diff --git a/src/sage/groups/perm_gps/symgp_conjugacy_class.py b/src/sage/groups/perm_gps/symgp_conjugacy_class.py index d6112df67af..5a8d5f435fa 100644 --- a/src/sage/groups/perm_gps/symgp_conjugacy_class.py +++ b/src/sage/groups/perm_gps/symgp_conjugacy_class.py @@ -28,8 +28,8 @@ def __init__(self, domain, part): sage: G = SymmetricGroup(5) sage: g = G([(1,2), (3,4,5)]) - sage: C = G.conjugacy_class(Partition([3,2])) - sage: type(C._part) + sage: C = G.conjugacy_class(Partition([3,2])) # needs sage.combinat + sage: type(C._part) # needs sage.combinat """ P = Partitions_n(len(domain)) @@ -44,7 +44,7 @@ def _repr_(self): EXAMPLES:: sage: G = SymmetricGroup(4) - sage: G.conjugacy_class(Partition([4])) + sage: G.conjugacy_class(Partition([4])) # needs sage.combinat Conjugacy class of cycle type [4] in Symmetric group of order 4! as a permutation group """ @@ -59,9 +59,9 @@ def __eq__(self, other): sage: G = SymmetricGroup(5) sage: g = G([(1,2), (3,4,5)]) - sage: C = G.conjugacy_class(Partition([3,2])) - sage: Cp = G.conjugacy_class(g) - sage: C == Cp + sage: C = G.conjugacy_class(Partition([3,2])) # needs sage.combinat + sage: Cp = G.conjugacy_class(g) # needs sage.combinat + sage: C == Cp # needs sage.combinat True """ if not isinstance(other, SymmetricGroupConjugacyClassMixin): @@ -76,9 +76,9 @@ def __ne__(self, other): sage: G = SymmetricGroup(5) sage: g = G([(1,3), (2,4,5)]) - sage: C = G.conjugacy_class(Partition([3,2])) - sage: Cp = G.conjugacy_class(g) - sage: C != Cp + sage: C = G.conjugacy_class(Partition([3,2])) # needs sage.combinat + sage: Cp = G.conjugacy_class(g) # needs sage.combinat + sage: C != Cp # needs sage.combinat False """ return not (self == other) @@ -91,7 +91,7 @@ def partition(self): sage: G = SymmetricGroup(5) sage: g = G([(1,2), (3,4,5)]) - sage: C = G.conjugacy_class(g) + sage: C = G.conjugacy_class(g) # needs sage.combinat """ return self._part @@ -111,6 +111,7 @@ def __init__(self, group, part): EXAMPLES:: + sage: # needs sage.combinat sage: G = SymmetricGroup(5) sage: g = G([(1,2), (3,4,5)]) sage: C = G.conjugacy_class(g) @@ -133,8 +134,8 @@ def __iter__(self): EXAMPLES:: sage: G = SymmetricGroup(4) - sage: C = G.conjugacy_class(Partition([3,1])) - sage: for x in C: x + sage: C = G.conjugacy_class(Partition([3,1])) # needs sage.combinat + sage: for x in C: x # needs sage.combinat (2,3,4) (2,4,3) (1,2,3) @@ -160,9 +161,9 @@ def set(self): sage: G = SymmetricGroup(3) sage: g = G((1,2)) - sage: C = G.conjugacy_class(g) + sage: C = G.conjugacy_class(g) # needs sage.combinat sage: S = [(2,3), (1,2), (1,3)] - sage: C.set() == Set(G(x) for x in S) + sage: C.set() == Set(G(x) for x in S) # needs sage.combinat True """ if not self._set: @@ -186,6 +187,7 @@ def __init__(self, P, part): EXAMPLES:: + sage: # needs sage.combinat sage: G = Permutations(5) sage: g = G([2, 1, 4, 5, 3]) sage: C = G.conjugacy_class(g) @@ -208,8 +210,8 @@ def __iter__(self): EXAMPLES:: sage: G = Permutations(4) - sage: C = G.conjugacy_class(Partition([3,1])) - sage: for x in C: x + sage: C = G.conjugacy_class(Partition([3,1])) # needs sage.combinat + sage: for x in C: x # needs sage.combinat [1, 3, 4, 2] [1, 4, 2, 3] [2, 3, 1, 4] @@ -235,9 +237,9 @@ def set(self): sage: G = Permutations(3) sage: g = G([2, 1, 3]) - sage: C = G.conjugacy_class(g) + sage: C = G.conjugacy_class(g) # needs sage.combinat sage: S = [[1, 3, 2], [2, 1, 3], [3, 2, 1]] - sage: C.set() == Set(G(x) for x in S) + sage: C.set() == Set(G(x) for x in S) # needs sage.combinat True """ if not self._set: @@ -272,9 +274,9 @@ def default_representative(part, G): EXAMPLES:: - sage: from sage.groups.perm_gps.symgp_conjugacy_class import default_representative + sage: from sage.groups.perm_gps.symgp_conjugacy_class import default_representative # needs sage.combinat sage: S = SymmetricGroup(4) - sage: for p in Partitions(4): + sage: for p in Partitions(4): # needs sage.combinat ....: print(default_representative(p, S)) (1,2,3,4) (1,2,3) @@ -312,8 +314,8 @@ def conjugacy_class_iterator(part, S=None): EXAMPLES:: - sage: from sage.groups.perm_gps.symgp_conjugacy_class import conjugacy_class_iterator - sage: for p in conjugacy_class_iterator([2,2]): print(p) + sage: from sage.groups.perm_gps.symgp_conjugacy_class import conjugacy_class_iterator # needs sage.combinat + sage: for p in conjugacy_class_iterator([2,2]): print(p) # needs sage.combinat [(1, 2), (3, 4)] [(1, 4), (2, 3)] [(1, 3), (2, 4)] @@ -321,7 +323,7 @@ def conjugacy_class_iterator(part, S=None): In order to get permutations, one just has to wrap:: sage: S = SymmetricGroup(5) - sage: for p in conjugacy_class_iterator([3,2]): print(S(p)) + sage: for p in conjugacy_class_iterator([3,2]): print(S(p)) # needs sage.combinat (1,3)(2,4,5) (1,3)(2,5,4) (1,2)(3,4,5) @@ -334,15 +336,15 @@ def conjugacy_class_iterator(part, S=None): the conjugacy class:: sage: s = lambda p: sum(1 for _ in conjugacy_class_iterator(p)) - sage: all(s(p) == p.conjugacy_class_size() for p in Partitions(5)) + sage: all(s(p) == p.conjugacy_class_size() for p in Partitions(5)) # needs sage.combinat True It is also possible to specify any underlying set:: - sage: it = conjugacy_class_iterator([2,2,2], 'abcdef') - sage: sorted(flatten(next(it))) + sage: it = conjugacy_class_iterator([2,2,2], 'abcdef') # needs sage.combinat + sage: sorted(flatten(next(it))) # needs sage.combinat ['a', 'b', 'c', 'd', 'e', 'f'] - sage: all(len(x) == 2 for x in next(it)) + sage: all(len(x) == 2 for x in next(it)) # needs sage.combinat True """ n = sum(part) diff --git a/src/sage/groups/raag.py b/src/sage/groups/raag.py index 736430e8af2..4bd3787d484 100644 --- a/src/sage/groups/raag.py +++ b/src/sage/groups/raag.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.graphs sage.rings.number_field r""" Right-Angled Artin Groups diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx index d84683ce5ee..ae9ce18efb1 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings r""" Elements of a semimonomial transformation group @@ -9,13 +10,13 @@ the semidirect product of the monomial transformation group of degree `n` The multiplication of two elements `(\phi, \pi, \alpha)(\psi, \sigma, \beta)` with - - `\phi, \psi \in {R^{\times}}^n` +- `\phi, \psi \in {R^{\times}}^n` - - `\pi, \sigma \in S_n` (with the multiplication `\pi\sigma` - done from left to right (like in GAP) -- - that is, `(\pi\sigma)(i) = \sigma(\pi(i))` for all `i`.) +- `\pi, \sigma \in S_n` (with the multiplication `\pi\sigma` + done from left to right (like in GAP) -- + that is, `(\pi\sigma)(i) = \sigma(\pi(i))` for all `i`.) - - `\alpha, \beta \in Aut(R)` +- `\alpha, \beta \in Aut(R)` is defined by @@ -114,7 +115,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): ((2*a + 1, 1, 2, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1) sage: S(g) ((2, a, 1, 2); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) - sage: S(1) # the one element in the group + sage: S(1) # the one element in the group ((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) """ def __init__(self, parent, v, perm, alpha): @@ -127,7 +128,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): sage: F. = GF(9) sage: S = SemimonomialTransformationGroup(F, 4) - sage: g = S(v = [2, a, 1, 2]) #indirect doctest + sage: g = S(v = [2, a, 1, 2]) #indirect doctest """ MultiplicativeGroupElement.__init__(self, parent) self.v = tuple(v) @@ -152,7 +153,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): sage: F. = GF(9) sage: s = SemimonomialTransformationGroup(F, 4).an_element() - sage: t = copy(s) #indirect doctest + sage: t = copy(s) # indirect doctest sage: t is s False sage: t == s @@ -203,7 +204,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): sage: F. = GF(9) sage: s = SemimonomialTransformationGroup(F, 4).an_element() - sage: s*s #indirect doctest + sage: s*s # indirect doctest ((a, 2*a + 1, 1, 1); (1,3)(2,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) """ cdef SemimonomialTransformation right = _right @@ -223,7 +224,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): sage: F. = GF(9) sage: S = SemimonomialTransformationGroup(F, 4) sage: s = S.an_element() - sage: s*s**(-1) == S(1) # indirect doctest + sage: s*s**(-1) == S(1) # indirect doctest True """ cdef i @@ -240,7 +241,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): EXAMPLES:: sage: F. = GF(9) - sage: SemimonomialTransformationGroup(F, 4).an_element() # indirect doctest + sage: SemimonomialTransformationGroup(F, 4).an_element() # indirect doctest ((a, 1, 1, 1); (1,4,3,2), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1) """ return "(%s; %s, %s)"%(self.v, self.perm.cycle_string(), @@ -254,9 +255,9 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): sage: F. = GF(9) sage: g = SemimonomialTransformationGroup(F, 4).gens() - sage: g[0] > g[1] # indirect doctest + sage: g[0] > g[1] # indirect doctest True - sage: g[1] != g[2] # indirect doctest + sage: g[1] != g[2] # indirect doctest True """ cdef SemimonomialTransformation right = _right diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py b/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py index 78c485bfc02..40bbed2c6bb 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation_group.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings r""" Semimonomial transformation group @@ -105,13 +106,17 @@ class SemimonomialTransformationGroup(FiniteGroup, UniqueRepresentation): sage: g = S(v = [2, a, 1, 2]) sage: h = S(perm = Permutation('(1,2,3,4)'), autom=F.hom([a**3])) sage: g*h - ((2, a, 1, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1) + ((2, a, 1, 2); (1,2,3,4), + Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1) sage: h*g - ((2*a + 1, 1, 2, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1) + ((2*a + 1, 1, 2, 2); (1,2,3,4), + Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1) sage: S(g) - ((2, a, 1, 2); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) + ((2, a, 1, 2); (), + Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) sage: S(1) - ((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) + ((1, 1, 1, 1); (), + Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a) """ Element = SemimonomialTransformation @@ -256,7 +261,7 @@ def _an_element_(self): EXAMPLES:: sage: F. = GF(4) - sage: SemimonomialTransformationGroup(F, 3).an_element() # indirect doctest + sage: SemimonomialTransformationGroup(F, 3).an_element() # indirect doctest ((a, 1, 1); (1,3,2), Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a + 1) """ R = self.base_ring() @@ -275,9 +280,9 @@ def __contains__(self, item) -> bool: sage: F. = GF(4) sage: S = SemimonomialTransformationGroup(F, 3) - sage: 1 in S # indirect doctest + sage: 1 in S # indirect doctest True - sage: a in S # indirect doctest + sage: a in S # indirect doctest False """ try: @@ -294,11 +299,14 @@ def gens(self) -> tuple: sage: F. = GF(4) sage: SemimonomialTransformationGroup(F, 3).gens() - (((a, 1, 1); (), Ring endomorphism of Finite Field in a of size 2^2 - Defn: a |--> a), ((1, 1, 1); (1,2,3), Ring endomorphism of Finite Field in a of size 2^2 - Defn: a |--> a), ((1, 1, 1); (1,2), Ring endomorphism of Finite Field in a of size 2^2 - Defn: a |--> a), ((1, 1, 1); (), Ring endomorphism of Finite Field in a of size 2^2 - Defn: a |--> a + 1)) + (((a, 1, 1); (), + Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a), + ((1, 1, 1); (1,2,3), + Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a), + ((1, 1, 1); (1,2), + Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a), + ((1, 1, 1); (), + Ring endomorphism of Finite Field in a of size 2^2 Defn: a |--> a + 1)) """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup R = self.base_ring() @@ -349,7 +357,7 @@ def _get_action_(self, X, op, self_on_left): sage: s*v # indirect doctest (0, 1, 0) sage: M = MatrixSpace(F, 3).one() - sage: s*M # indirect doctest + sage: s*M # indirect doctest [ 0 1 0] [ 0 0 1] [a + 1 0 0] @@ -376,7 +384,7 @@ def _repr_(self) -> str: EXAMPLES:: sage: F. = GF(4) - sage: SemimonomialTransformationGroup(F, 3) # indirect doctest + sage: SemimonomialTransformationGroup(F, 3) # indirect doctest Semimonomial transformation group over Finite Field in a of size 2^2 of degree 3 """ return ('Semimonomial transformation group over %s' % self.base_ring() + @@ -389,7 +397,7 @@ def _latex_(self) -> str: EXAMPLES:: sage: F. = GF(4) - sage: latex(SemimonomialTransformationGroup(F, 3)) # indirect doctest + sage: latex(SemimonomialTransformationGroup(F, 3)) # indirect doctest \left(\Bold{F}_{2^{2}}^3\wr\langle (1,2,3), (1,2) \rangle \right) \rtimes \operatorname{Aut}(\Bold{F}_{2^{2}}) """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -470,7 +478,7 @@ def __init__(self, G, M, check=True): sage: F. = GF(4) sage: s = SemimonomialTransformationGroup(F, 3).an_element() sage: M = MatrixSpace(F, 3).one() - sage: s*M # indirect doctest + sage: s*M # indirect doctest [ 0 1 0] [ 0 0 1] [a + 1 0 0] @@ -497,7 +505,7 @@ def _act_(self, a, b): sage: F. = GF(4) sage: s = SemimonomialTransformationGroup(F, 3).an_element() sage: M = MatrixSpace(F, 3).one() - sage: s*M # indirect doctest + sage: s*M # indirect doctest [ 0 1 0] [ 0 0 1] [a + 1 0 0] diff --git a/src/sage/homology/chain_complex_morphism.py b/src/sage/homology/chain_complex_morphism.py index b3f284342bd..2a182b24cdc 100644 --- a/src/sage/homology/chain_complex_morphism.py +++ b/src/sage/homology/chain_complex_morphism.py @@ -423,7 +423,7 @@ def __mul__(self, x): [2] Before :trac:`19065`, the following multiplication produced a - ``KeyError`` because `f` was not explicitly defined in degree 2:: + :class:`KeyError` because `f` was not explicitly defined in degree 2:: sage: C0 = ChainComplex({0: zero_matrix(ZZ, 0, 1)}) sage: C1 = ChainComplex({1: zero_matrix(ZZ, 0, 1)}) diff --git a/src/sage/homology/homology_group.py b/src/sage/homology/homology_group.py index 8db8a47e568..8d86d477ad8 100644 --- a/src/sage/homology/homology_group.py +++ b/src/sage/homology/homology_group.py @@ -165,6 +165,8 @@ def HomologyGroup(n, base_ring, invfac=None): Multiplicative Abelian group isomorphic to Z x Z x Z x Z sage: HomologyGroup(4, ZZ) Z x Z x Z x Z + + sage: # needs sage.libs.flint (otherwise timeout) sage: HomologyGroup(100, ZZ) Z^100 """ diff --git a/src/sage/interacts/library_cython.pyx b/src/sage/interacts/library_cython.pyx index 5f0ff8e7d96..37e75a16e7d 100644 --- a/src/sage/interacts/library_cython.pyx +++ b/src/sage/interacts/library_cython.pyx @@ -28,6 +28,7 @@ cpdef julia(ff_j, z, int iterations): TESTS:: + sage: # needs sage.symbolic sage: from sage.interacts.library_cython import julia sage: z = var('z') sage: c_real, c_imag = 1, 1 @@ -55,6 +56,7 @@ cpdef mandel(ff_m, z, int iterations): TESTS:: + sage: # needs sage.symbolic sage: from sage.interacts.library_cython import mandel sage: z, c = var('z, c') sage: f = symbolic_expression(z**2 + c).function(z,c) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index fe4637a7b19..939a142aa70 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -275,7 +275,7 @@ def _read_in_file_command(self, filename): # For some reason this trivial comp # keeps certain random freezes from occurring. Do not remove this. # The space before the \n is also important. - return ')read %s \n'%filename + return ')read %s \n' % filename def _quit_string(self): """ @@ -384,11 +384,11 @@ def set(self, var, value): '2' """ - cmd = '%s := %s'%(var, value) + cmd = '%s := %s' % (var, value) out = self._eval_line(cmd, reformat=False) if out.find("error") != -1: - raise TypeError("Error executing code in Axiom\nCODE:\n\t%s\nAxiom ERROR:\n\t%s"%(cmd, out)) + raise TypeError("Error executing code in Axiom\nCODE:\n\t%s\nAxiom ERROR:\n\t%s" % (cmd, out)) def get(self, var): r""" @@ -565,7 +565,7 @@ def __call__(self, x): """ self._check_valid() P = self.parent() - return P('%s(%s)'%(self.name(), x)) + return P('%s(%s)' % (self.name(), x)) def _richcmp_(self, other, op): """ @@ -601,11 +601,11 @@ def _richcmp_(self, other, op): """ P = self.parent() - if 'true' in P.eval("(%s = %s) :: Boolean"%(self.name(),other.name())): + if 'true' in P.eval("(%s = %s) :: Boolean" % (self.name(),other.name())): return rich_to_bool(op, 0) - elif 'true' in P.eval("(%s < %s) :: Boolean"%(self.name(), other.name())): + elif 'true' in P.eval("(%s < %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, -1) - elif 'true' in P.eval("(%s > %s) :: Boolean"%(self.name(),other.name())): + elif 'true' in P.eval("(%s > %s) :: Boolean" % (self.name(),other.name())): return rich_to_bool(op, 1) return NotImplemented @@ -635,7 +635,7 @@ def __len__(self): 6 """ P = self._check_valid() - s = P.eval('# %s '%self.name()) + s = P.eval('# %s ' % self.name()) i = s.rfind('Type') return int(s[:i-1]) @@ -667,9 +667,9 @@ def __getitem__(self, n): raise IndexError("index out of range") P = self._check_valid() if not isinstance(n, tuple): - return P.new('%s(%s)'%(self._name, n)) + return P.new('%s(%s)' % (self._name, n)) else: - return P.new('%s(%s)'%(self._name, str(n)[1:-1])) + return P.new('%s(%s)' % (self._name, str(n)[1:-1])) def comma(self, *args): """ @@ -733,7 +733,7 @@ def as_type(self, type): """ P = self._check_valid() type = P(type) - return P.new("%s :: %s"%(self.name(), type.name())) + return P.new("%s :: %s" % (self.name(), type.name())) def unparsed_input_form(self): """ @@ -750,7 +750,7 @@ def unparsed_input_form(self): """ P = self._check_valid() - s = P.eval('unparse(%s::InputForm)'%self._name) + s = P.eval('unparse(%s::InputForm)' % self._name) if 'translation error' in s or 'Cannot convert' in s: raise NotImplementedError s = multiple_replace({'\r\n':'', # fix stupid Fortran-ish @@ -855,7 +855,7 @@ def _sage_(self): #If all else fails, try using the unparsed input form try: import sage.misc.sage_eval - vars=sage.symbolic.ring.var(str(self.variables())[1:-1]) + vars = sage.symbolic.ring.var(str(self.variables())[1:-1]) if isinstance(vars,tuple): return sage.misc.sage_eval.sage_eval(self.unparsed_input_form(), locals={str(x):x for x in vars}) else: @@ -916,6 +916,7 @@ def __init__(self, object, name): name = name[:-2] + "!" FunctionElement.__init__(self, object, name) + AxiomFunctionElement = PanAxiomFunctionElement @@ -936,6 +937,7 @@ def __init__(self, parent, name): name = name[:-2] + "!" ExpectFunction.__init__(self, parent, name) + AxiomExpectFunction = PanAxiomExpectFunction diff --git a/src/sage/interfaces/four_ti_2.py b/src/sage/interfaces/four_ti_2.py index 79a07dcdad4..1f5a6beb559 100644 --- a/src/sage/interfaces/four_ti_2.py +++ b/src/sage/interfaces/four_ti_2.py @@ -176,7 +176,7 @@ def write_array(self, array, nrows, ncols, filename): sage: four_ti_2.write_array([[1,2,3],[3,4,5]], 2, 3, "test_file") """ f = open(os.path.join(self.directory(), filename), 'w') - f.write("%s %s\n"%(nrows, ncols)) + f.write("%s %s\n" % (nrows, ncols)) for row in array: f.write(" ".join(map(str, row))) f.write("\n") @@ -444,7 +444,7 @@ def ppi(self, n): """ self.call('ppi', f'{n} 2> /dev/null') - return self.read_matrix('ppi%s.gra'%n) + return self.read_matrix('ppi%s.gra' % n) def circuits(self, mat=None, project=None): r""" diff --git a/src/sage/interfaces/frobby.py b/src/sage/interfaces/frobby.py index 17c7f06f05f..aab3bd9b58f 100644 --- a/src/sage/interfaces/frobby.py +++ b/src/sage/interfaces/frobby.py @@ -168,14 +168,14 @@ def hilbert(self, monomial_ideal): """ frobby_input = self._ideal_to_string(monomial_ideal) frobby_output = self('hilbert', input=frobby_input) - ring=monomial_ideal.ring() - lines=frobby_output.split('\n') - if lines[-1]=='': + ring = monomial_ideal.ring() + lines = frobby_output.split('\n') + if lines[-1] == '': lines.pop(-1) - if lines[-1]=='(coefficient)': + if lines[-1] == '(coefficient)': lines.pop(-1) lines.pop(0) - resul=0 + resul = 0 for l in lines: lis = [int(_) for _ in l.split()] resul += lis[0]+prod([ring.gen(i)**lis[i+1] for i in range(len(lis)-1)]) @@ -206,9 +206,9 @@ def associated_primes(self, monomial_ideal): """ frobby_input = self._ideal_to_string(monomial_ideal) frobby_output = self('assoprimes', input=frobby_input) - lines=frobby_output.split('\n') + lines = frobby_output.split('\n') lines.pop(0) - if lines[-1]=='': + if lines[-1] == '': lines.pop(-1) lists = [[int(_) for _ in a.split()] for a in lines] @@ -334,10 +334,10 @@ def _parse_ideals(self, string, ring): lines.pop(0) matrices.append('1 '+str(ring.ngens())+'\n'+'0 '*ring.ngens()+'\n') else: - nrows=int(lines[0].split()[0]) - nmatrix=lines.pop(0)+'\n' + nrows = int(lines[0].split()[0]) + nmatrix = lines.pop(0)+'\n' for i in range(nrows): - nmatrix+=lines.pop(0)+'\n' + nmatrix += lines.pop(0)+'\n' matrices.append(nmatrix) def to_ideal(exps): @@ -466,5 +466,6 @@ def _monomial_to_string(self, monomial): strings = [str(exponents[var]) for var in range(len(exponents))] return ' '.join(strings) + '\n' + # This singleton instance is what should be used outside this file. frobby = Frobby() diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 44900d525c8..61f38af2d26 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -222,10 +222,11 @@ # suppress unaligned access to 0x..., ip=0x... warnings gap_cmd = 'prctl --unaligned=silent ' + gap_cmd + def gap_command(use_workspace_cache=True, local=True): if use_workspace_cache: if local: - return "%s -L %s"%(gap_cmd, WORKSPACE), False + return "%s -L %s" % (gap_cmd, WORKSPACE), False else: # TO DO: Use remote workspace return gap_cmd, False @@ -442,7 +443,7 @@ def load_package(self, pkg, verbose=False): print("Loading GAP package {}".format(pkg)) x = self.eval('LoadPackage("{}")'.format(pkg)) if x == 'fail': - raise RuntimeError("Error loading Gap package "+str(pkg)+". "+ + raise RuntimeError("Error loading Gap package "+str(pkg)+". " + "You may want to install gap_packages SPKG.") def eval(self, x, newlines=False, strip=True, split_lines=True, **kwds): @@ -501,7 +502,7 @@ def eval(self, x, newlines=False, strip=True, split_lines=True, **kwds): #it is occurring in a string. If it is not in a string, we #strip off the comment. if not split_lines: - input_line=str(x) + input_line = str(x) else: input_line = "" for line in str(x).rstrip().split('\n'): @@ -527,10 +528,10 @@ def _execute_line(self, line, wait_for_prompt=True, expect_eof=False): raise RuntimeError("Passing commands this long to gap would hang") E.sendline(line) except OSError: - raise RuntimeError("Error evaluating %s in %s"%(line, self)) + raise RuntimeError("Error evaluating %s in %s" % (line, self)) if not wait_for_prompt: return (b'',b'') - if len(line)==0: + if len(line) == 0: return (b'',b'') try: terminal_echo = [] # to be discarded @@ -565,23 +566,23 @@ def _execute_line(self, line, wait_for_prompt=True, expect_eof=False): break elif x == 9: # @m finished running a child pass # there is no need to do anything - elif x==10: #@n normal output line + elif x == 10: #@n normal output line current_outputs = normal_outputs - elif x==11: #@r echoing input + elif x == 11: #@r echoing input current_outputs = terminal_echo - elif x==12: #@sN shouldn't happen + elif x == 12: #@sN shouldn't happen warnings.warn("this should never happen") - elif x==13: #@w GAP is trying to send a Window command + elif x == 13: #@w GAP is trying to send a Window command warnings.warn("this should never happen") - elif x ==14: #@x seems to be safely ignorable + elif x == 14: #@x seems to be safely ignorable pass elif x == 15:#@z GAP starting a subprocess pass # there is no need to do anything except pexpect.EOF: if not expect_eof: - raise RuntimeError("Unexpected EOF from %s executing %s"%(self,line)) + raise RuntimeError("Unexpected EOF from %s executing %s" % (self,line)) except IOError: - raise RuntimeError("IO Error from %s executing %s"%(self,line)) + raise RuntimeError("IO Error from %s executing %s" % (self,line)) return (b"".join(normal_outputs), b"".join(error_outputs)) def _keyboard_interrupt(self): @@ -602,7 +603,7 @@ def _keyboard_interrupt(self): 2 """ self.quit() - raise KeyboardInterrupt("Ctrl-c pressed while running %s"%self) + raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self) def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if_needed=True): r""" @@ -687,7 +688,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if self.quit() gap_reset_workspace() error = error.replace('\r','') - raise RuntimeError("%s produced error output\n%s\n executing %s"%(self, error,line)) + raise RuntimeError("%s produced error output\n%s\n executing %s" % (self, error,line)) if not normal: return '' @@ -725,7 +726,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if except KeyboardInterrupt: self._keyboard_interrupt() - raise KeyboardInterrupt("Ctrl-c pressed while running %s"%self) + raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self) def unbind(self, var): """ @@ -744,7 +745,7 @@ def unbind(self, var): Error, Variable: 'x' must have a value ... """ - self.eval('Unbind(%s)'%var) + self.eval('Unbind(%s)' % var) self.clear(var) def _contains(self, v1, v2): @@ -761,7 +762,7 @@ def _contains(self, v1, v2): sage: 2 in gap('Integers') True """ - return self.eval('%s in %s'%(v1,v2)) == "true" + return self.eval('%s in %s' % (v1,v2)) == "true" def _true_symbol(self): """ @@ -865,8 +866,8 @@ def function_call(self, function, args=None, kwds=None): #value, then that value will be in 'last', otherwise it will #be the marker. marker = '__SAGE_LAST__:="__SAGE_LAST__";;' - cmd = "%s(%s);;"%(function, ",".join([s.name() for s in args]+ - ['%s=%s'%(key,value.name()) for key, value in kwds.items()])) + cmd = "%s(%s);;" % (function, ",".join([s.name() for s in args] + + ['%s=%s' % (key,value.name()) for key, value in kwds.items()])) if len(marker) + len(cmd) <= self._eval_using_file_cutoff: # We combine the two commands so we only run eval() once and the # only output would be from the second command @@ -977,9 +978,9 @@ def __len__(self): it is false """ P = self.parent() - if P.eval('%s = true'%self.name()) == 'true': + if P.eval('%s = true' % self.name()) == 'true': return 1 - elif P.eval('%s = false'%self.name()) == 'true': + elif P.eval('%s = false' % self.name()) == 'true': return 0 else: return int(self.Length()) @@ -1037,7 +1038,6 @@ def _matrix_(self, R): entries = [[R(self[r,c]) for c in range(1,m+1)] for r in range(1,n+1)] return M(entries) -############ class Gap(Gap_generic): r""" @@ -1145,7 +1145,7 @@ def _next_var_name(self): del self._available_vars[0] return v self.__seq += 1 - return r'\$sage%s'%self.__seq + return r'\$sage%s' % self.__seq def _start(self): """ @@ -1270,7 +1270,7 @@ def save_workspace(self): from sage.misc.temporary_file import atomic_write with atomic_write(WORKSPACE) as f: f.close() - self.eval('SaveWorkspace("%s");'%(f.name), allow_use_file=False) + self.eval('SaveWorkspace("%s");' % (f.name), allow_use_file=False) # Todo -- this -- but there is a tricky "when does it end" issue! # Maybe do via a file somehow? @@ -1356,14 +1356,14 @@ def get(self, var, use_file=False): tmp = self._local_tmpfile() if os.path.exists(tmp): os.unlink(tmp) - self.eval('PrintTo("%s", %s);'%(tmp,var), strip=False) + self.eval('PrintTo("%s", %s);' % (tmp,var), strip=False) with open(tmp) as f: r = f.read() r = r.strip().replace("\\\n","") os.unlink(tmp) return r else: - return self.eval('Print(%s);'%var, newlines=False) + return self.eval('Print(%s);' % var, newlines=False) def _pre_interact(self): """ @@ -1390,7 +1390,7 @@ def _eval_line_using_file(self, line): if j >= 0 and j < i: i = -1 if i == -1: - line0 = 'Print( %s );'%line.rstrip().rstrip(';') + line0 = 'Print( %s );' % line.rstrip().rstrip(';') try: # this is necessary, since Print requires something as input, and some functions (e.g., Read) return nothing. return Expect._eval_line_using_file(self, line0) except RuntimeError: @@ -1465,8 +1465,6 @@ def _tab_completion(self): return [n for n in names if n[0] in string.ascii_letters] -############ - def gap_reset_workspace(max_workspace_size=None, verbose=False): r""" Call this to completely reset the GAP workspace, which is used by @@ -1564,7 +1562,7 @@ def _latex_(self): """ P = self._check_valid() try: - s = P.eval('LaTeXObj(%s)'%self.name()) + s = P.eval('LaTeXObj(%s)' % self.name()) s = s.replace('\\\\','\\').replace('"','') s = s.replace('%\\n',' ') return s @@ -1587,7 +1585,7 @@ def _tab_completion(self): True """ P = self.parent() - v = P.eval(r'\$SAGE.OperationsAdmittingFirstArgument(%s)'%self.name()) + v = P.eval(r'\$SAGE.OperationsAdmittingFirstArgument(%s)' % self.name()) v = v.replace('Tester(','').replace('Setter(','').replace(')','').replace('\n', '') v = v.split(',') v = [ oper.split('"')[1] for oper in v ] @@ -1765,10 +1763,10 @@ def intmod_gap_to_sage(x): return Mod(Integer(m.group(1)), Integer(m.group(2))) raise ValueError("Unable to convert Gap element '%s'" % s) -############# gap = Gap() + def reduce_load_GAP(): """ Returns the GAP interface object defined in sage.interfaces.gap. diff --git a/src/sage/interfaces/gap3.py b/src/sage/interfaces/gap3.py index 78d05035cbf..beef28e562a 100644 --- a/src/sage/interfaces/gap3.py +++ b/src/sage/interfaces/gap3.py @@ -490,7 +490,7 @@ def help(self, topic, pager=True): elif x == 10: # matched @n (normal input mode); it seems we're done break - elif x==11: + elif x == 11: # matched @r (echoing input); skip to end of line E.expect_list(self._compiled_small_pattern) @@ -743,7 +743,7 @@ def _latex_(self): """ gap3_session = self._check_valid() try: - s = gap3_session.eval('FormatLaTeX(%s)'%self.name()) + s = gap3_session.eval('FormatLaTeX(%s)' % self.name()) s = s.replace('\\\\','\\').replace('"','') s = s.replace('%\\n',' ') return s diff --git a/src/sage/interfaces/genus2reduction.py b/src/sage/interfaces/genus2reduction.py index 6fa64b68cca..eeb63fcb939 100644 --- a/src/sage/interfaces/genus2reduction.py +++ b/src/sage/interfaces/genus2reduction.py @@ -160,17 +160,17 @@ def _repr_(self): if self.Q == 0: yterm = '' else: - yterm = '+ (%s)*y '%self.Q + yterm = '+ (%s)*y ' % self.Q s = 'Reduction data about this proper smooth genus 2 curve:\n' - s += '\ty^2 %s= %s\n'%(yterm, self.P) + s += '\ty^2 %s= %s\n' % (yterm, self.P) if self.Qmin: - s += 'A Minimal Equation:\n\ty^2 + (%s)y = %s\n'%(self.Qmin, self.Pmin) + s += 'A Minimal Equation:\n\ty^2 + (%s)y = %s\n' % (self.Qmin, self.Pmin) else: - s += 'A Minimal Equation:\n\ty^2 = %s\n'%self.Pmin - s += 'Minimal Discriminant: %s\n'%self.minimal_disc - s += 'Conductor: %s\n'%self.conductor - s += 'Local Data:\n%s'%self._local_data_str() + s += 'A Minimal Equation:\n\ty^2 = %s\n' % self.Pmin + s += 'Minimal Discriminant: %s\n' % self.minimal_disc + s += 'Conductor: %s\n' % self.conductor + s += 'Local Data:\n%s' % self._local_data_str() return s def _local_data_str(self): @@ -178,7 +178,7 @@ def _local_data_str(self): D = self.local_data K = sorted(D.keys()) for p in K: - s += 'p=%s\n%s\n'%(p, D[p]) + s += 'p=%s\n%s\n' % (p, D[p]) s = '\t' + '\n\t'.join(s.strip().split('\n')) return s @@ -217,7 +217,7 @@ def divisors_to_string(divs): # Next divisor is different or we are done? Print current one if s: s += "x" - s += "(%s)"%divs[i] + s += "(%s)" % divs[i] if n > 1: s += "^%s" % n n = 0 @@ -457,6 +457,7 @@ def __call__(self, Q, P): def __reduce__(self): return _reduce_load_genus2reduction, tuple([]) + # An instance genus2reduction = Genus2reduction() diff --git a/src/sage/interfaces/gnuplot.py b/src/sage/interfaces/gnuplot.py index b423866fd15..76841963721 100644 --- a/src/sage/interfaces/gnuplot.py +++ b/src/sage/interfaces/gnuplot.py @@ -99,7 +99,7 @@ def plot(self, cmd, file=None, verbose=True, reset=True): print("Saving plot to %s" % file) self(cmd) time.sleep(0.1) - os.system('mv %s %s 2>/dev/null'%(tmp, file)) + os.system('mv %s %s 2>/dev/null' % (tmp, file)) time.sleep(0.1) self('set terminal x11') @@ -110,7 +110,7 @@ def plot3d(self, f, xmin=-1, xmax=1, ymin=-1, ymax=1, zmin=-1, zmax=1, if title is None: title = str(f) f = f.replace('^','**') - cmd=""" + cmd = """ set xlabel "%s" set ylabel "%s" set key top @@ -125,7 +125,7 @@ def plot3d(self, f, xmin=-1, xmax=1, ymin=-1, ymax=1, zmin=-1, zmax=1, #show pm3d #show palette splot %s - """%(xlabel, ylabel, + """ % (xlabel, ylabel, xmin, xmax, ymin, ymax, #zmin, zmax, samples, isosamples, title, f) @@ -163,7 +163,7 @@ def plot3d_parametric(self, f='cos(u)*(3 + v*cos(u/2)), sin(u)*(3 + v*cos(u/2)), """ if title is None: title = str(f) - cmd=""" + cmd = """ set key top set border 4095 set samples %s @@ -187,6 +187,7 @@ def interact(self, cmd): def console(self): gnuplot_console() + # An instance gnuplot = Gnuplot() diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index f8237d3ad94..78f94269ff4 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -324,7 +324,7 @@ def _coerce_from_special_method(self, x): If no such method is defined, raises an AttributeError instead of a TypeError. """ - s = '_%s_'%self.name() + s = '_%s_' % self.name() if s == '_maxima_lib_': s = '_maxima_' if s == '_pari_': @@ -375,11 +375,11 @@ def _coerce_impl(self, x, use_special=True): A.append(w.name()) z.append(w) X = ','.join(A) - r = self.new('%s%s%s'%(self._left_list_delim(), X, self._right_list_delim())) + r = self.new('%s%s%s' % (self._left_list_delim(), X, self._right_list_delim())) r.__sage_list = z # do this to avoid having the entries of the list be garbage collected return r - raise TypeError("unable to coerce element into %s"%self.name()) + raise TypeError("unable to coerce element into %s" % self.name()) def new(self, code): return self(code) @@ -412,14 +412,14 @@ def _true_symbol(self): try: return self.__true_symbol except AttributeError: - self.__true_symbol = self.get('1 %s 1'%self._equality_symbol()) + self.__true_symbol = self.get('1 %s 1' % self._equality_symbol()) return self.__true_symbol def _false_symbol(self): try: return self.__false_symbol except AttributeError: - self.__false_symbol = self.get('1 %s 2'%self._equality_symbol()) + self.__false_symbol = self.get('1 %s 2' % self._equality_symbol()) return self.__false_symbol def _lessthan_symbol(self): @@ -470,7 +470,7 @@ def set(self, var, value): """ Set the variable var to the given value. """ - cmd = '%s%s%s;'%(var,self._assign_symbol(), value) + cmd = '%s%s%s;' % (var,self._assign_symbol(), value) self.eval(cmd) def get(self, var): @@ -509,7 +509,7 @@ def _next_var_name(self): del self._available_vars[0] return v self.__seq += 1 - return "sage%s"%self.__seq + return "sage%s" % self.__seq def _create(self, value, name=None): name = self._next_var_name() if name is None else name @@ -612,7 +612,7 @@ def function_call(self, function, args=None, kwds=None): self._check_valid_function_name(function) s = self._function_call_string(function, [s.name() for s in args], - ['%s=%s'%(key,value.name()) for key, value in kwds.items()]) + ['%s=%s' % (key,value.name()) for key, value in kwds.items()]) return self.new(s) def _function_call_string(self, function, args, kwds): @@ -624,7 +624,7 @@ def _function_call_string(self, function, args, kwds): sage: maxima._function_call_string('diff', ['f(x)', 'x'], []) 'diff(f(x),x)' """ - return "%s(%s)"%(function, ",".join(list(args) + list(kwds))) + return "%s(%s)" % (function, ",".join(list(args) + list(kwds))) def call(self, function_name, *args, **kwds): return self.function_call(function_name, args, kwds) @@ -962,18 +962,18 @@ def _richcmp_(self, other, op): """ P = self._check_valid() try: - if P.eval("%s %s %s"%(self.name(), P._equality_symbol(), + if P.eval("%s %s %s" % (self.name(), P._equality_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, 0) except RuntimeError: pass try: - if P.eval("%s %s %s"%(self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol(): + if P.eval("%s %s %s" % (self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, -1) except RuntimeError: pass try: - if P.eval("%s %s %s"%(self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol(): + if P.eval("%s %s %s" % (self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, 1) except Exception: pass @@ -1004,7 +1004,7 @@ def _check_valid(self): try: P = self.parent() if P is None: - raise ValueError("The %s session in which this object was defined is no longer running."%P.name()) + raise ValueError("The %s session in which this object was defined is no longer running." % P.name()) except AttributeError: raise ValueError("The session in which this object was defined is no longer running.") return P @@ -1169,11 +1169,8 @@ def __repr__(self): s = cr else: s = self._repr_() - if self._name in s: - try: - s = s.replace(self._name, getattr(self, '__custom_name')) - except AttributeError: - pass + if self._name in s and self.get_custom_name() is not None: + s = s.replace(self._name, self.get_custom_name()) if cr: self._cached_repr = s return s @@ -1288,14 +1285,14 @@ def attribute(self, attrname): -122023936/161051 """ P = self._check_valid() - return P('%s.%s'%(self.name(), attrname)) + return P('%s.%s' % (self.name(), attrname)) def __getitem__(self, n): P = self._check_valid() if not isinstance(n, tuple): - return P.new('%s[%s]'%(self._name, n)) + return P.new('%s[%s]' % (self._name, n)) else: - return P.new('%s[%s]'%(self._name, str(n)[1:-1])) + return P.new('%s[%s]' % (self._name, str(n)[1:-1])) def __int__(self): """ @@ -1432,7 +1429,7 @@ def name(self, new_name=None): def gen(self, n): P = self._check_valid() - return P.new('%s.%s'%(self._name, int(n))) + return P.new('%s.%s' % (self._name, int(n))) def _operation(self, operation, other=None): r""" @@ -1469,9 +1466,9 @@ def _operation(self, operation, other=None): """ P = self._check_valid() if other is None: - cmd = '%s %s'%(operation, self._name) + cmd = '%s %s' % (operation, self._name) else: - cmd = '%s %s %s'%(self._name, operation, other._name) + cmd = '%s %s %s' % (self._name, operation, other._name) try: return P.new(cmd) except Exception as msg: diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py index 6660a14e1cc..a68e53e2d85 100644 --- a/src/sage/interfaces/jmoldata.py +++ b/src/sage/interfaces/jmoldata.py @@ -165,12 +165,12 @@ def export_image(self, datafile = cygwin.cygpath(datafile, 'w') launchscript = "" - if (datafile_cmd!='script'): + if (datafile_cmd != 'script'): launchscript = "load " launchscript = launchscript + datafile imagescript = 'write {} {!r}\n'.format(image_type, target_native) - size_arg = "%sx%s" %(figsize*100,figsize*100) + size_arg = "%sx%s" % (figsize*100,figsize*100) # Scratch file for Jmol errors scratchout = tmp_filename(ext=".txt") with open(scratchout, 'w') as jout: diff --git a/src/sage/interfaces/lisp.py b/src/sage/interfaces/lisp.py index c4d8542a5ed..3d6e620c4d1 100644 --- a/src/sage/interfaces/lisp.py +++ b/src/sage/interfaces/lisp.py @@ -136,7 +136,7 @@ def eval(self, code, strip=True, **kwds): x.append(M.strip()) self.__in_seq = s except TypeError as s: - return 'error evaluating "%s":\n%s'%(code,s) + return 'error evaluating "%s":\n%s' % (code,s) return '\n'.join(x) def _an_element_impl(self): @@ -165,10 +165,10 @@ def set(self, var, value): sage: lisp.eval('x') '2' """ - cmd = '(setq %s %s)'%(var, value) + cmd = '(setq %s %s)' % (var, value) out = self.eval(cmd) if '***' in out: - raise TypeError("Error executing code in Sage\nCODE:\n\t%s\nSAGE ERROR:\n\t%s"%(cmd, out)) + raise TypeError("Error executing code in Sage\nCODE:\n\t%s\nSAGE ERROR:\n\t%s" % (cmd, out)) def get(self, var): """ @@ -202,7 +202,7 @@ def _synchronize(self): E = self._expect r = random.randrange(2147483647) s = str(r+1) - cmd = "(+ 1 %s)"%r + cmd = "(+ 1 %s)" % r E.sendline(cmd) E.expect(s) E.expect(self._prompt) @@ -410,9 +410,9 @@ def _richcmp_(self, other, op): if parent(other) is not P: other = P(other) - if P.eval('(= %s %s)'%(self.name(), other.name())) == P._true_symbol(): + if P.eval('(= %s %s)' % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, 0) - elif P.eval('(< %s %s)'%(self.name(), other.name())) == P._true_symbol(): + elif P.eval('(< %s %s)' % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, -1) else: return rich_to_bool(op, 1) @@ -454,7 +454,7 @@ def _sub_(self, right): -1 """ P = self._check_valid() - return P.new('(- %s %s)'%(self._name, right._name)) + return P.new('(- %s %s)' % (self._name, right._name)) def _mul_(self, right): """ @@ -465,7 +465,7 @@ def _mul_(self, right): 2 """ P = self._check_valid() - return P.new('(* %s %s)'%(self._name, right._name)) + return P.new('(* %s %s)' % (self._name, right._name)) def _div_(self, right): """ @@ -476,7 +476,7 @@ def _div_(self, right): 1/2 """ P = self._check_valid() - return P.new('(/ %s %s)'%(self._name, right._name)) + return P.new('(/ %s %s)' % (self._name, right._name)) def __pow__(self, n): """ @@ -537,6 +537,7 @@ def is_LispElement(x): return isinstance(x, LispElement) + # An instance lisp = Lisp() @@ -550,6 +551,7 @@ def reduce_load_Lisp(): """ return lisp + import os def lisp_console(): """ diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index 58ec79a48ee..1d575b4ff7c 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -845,7 +845,7 @@ def new_from(self, type, value): """ type = self(type) value = self(value) - return self.new("new %s from %s"%(type.name(), value.name())) + return self.new("new %s from %s" % (type.name(), value.name())) def _macaulay2_input_ring(self, base_ring, vars, order='GRevLex'): """ @@ -972,13 +972,13 @@ def external_string(self): 'QQ(monoid[x..y, Degrees => {2:1}, Heft => {1}, MonomialOrder => VerticalList{MonomialSize => 32, GRevLex => {2:1}, Position => Up}, DegreeRank => 1])' """ P = self._check_valid() - code = 'toExternalString(%s)'%self.name() + code = 'toExternalString(%s)' % self.name() X = P.eval(code, strip=True) if 'stdio:' in X: if 'to external string' in X: - return P.eval('%s'%self.name()) - raise RuntimeError("Error evaluating Macaulay2 code.\nIN:%s\nOUT:%s"%(code, X)) + return P.eval('%s' % self.name()) + raise RuntimeError("Error evaluating Macaulay2 code.\nIN:%s\nOUT:%s" % (code, X)) s = multiple_replace({'\r':'', '\n':' '}, X) return s @@ -1050,7 +1050,7 @@ def __len__(self): """ self._check_valid() # we use str instead of repr to avoid wrapping - return int(str(self.parent()("#%s"%self.name()))) + return int(str(self.parent()("#%s" % self.name()))) def __getitem__(self, n): """ @@ -1062,7 +1062,7 @@ def __getitem__(self, n): """ self._check_valid() n = self.parent()(n) - return self.parent().new('%s # %s'%(self.name(), n.name())) + return self.parent().new('%s # %s' % (self.name(), n.name())) def __setitem__(self, index, value): """ @@ -1077,7 +1077,7 @@ def __setitem__(self, index, value): P = self.parent() index = P(index) value = P(value) - res = P.eval("%s # %s = %s"%(self.name(), index.name(), value.name())) + res = P.eval("%s # %s = %s" % (self.name(), index.name(), value.name())) if "assignment attempted to element of immutable list" in res: raise TypeError("item assignment not supported") @@ -1095,7 +1095,7 @@ def __call__(self, x): self._check_valid() P = self.parent() r = P(x) - return P('%s %s'%(self.name(), r.name())) + return P('%s %s' % (self.name(), r.name())) def __floordiv__(self, x): """ @@ -1119,10 +1119,10 @@ def __floordiv__(self, x): """ if isinstance(x, (list, tuple)): y = self.parent(x) - z = self.parent().new('%s // matrix{%s}'%(self.name(), y.name())) + z = self.parent().new('%s // matrix{%s}' % (self.name(), y.name())) return list(z.entries().flatten()) else: - return self.parent().new('%s // %s'%(self.name(), x.name())) + return self.parent().new('%s // %s' % (self.name(), x.name())) def __mod__(self, x): """ @@ -1148,10 +1148,10 @@ def __mod__(self, x): """ if isinstance(x, (list, tuple)): y = self.parent(x) - return self.parent().new('%s %% matrix{%s}'%(self.name(), y.name())) + return self.parent().new('%s %% matrix{%s}' % (self.name(), y.name())) if not isinstance(x, Macaulay2Element): x = self.parent(x) - return self.parent().new('%s %% %s'%(self.name(), x.name())) + return self.parent().new('%s %% %s' % (self.name(), x.name())) def __bool__(self): """ @@ -1219,7 +1219,7 @@ def structure_sheaf(self): """ from sage.misc.superseded import deprecation deprecation(27848, 'The function `structure_sheaf` is deprecated. Use `self.sheaf()` instead.') - return self.parent()('OO_%s'%self.name()) + return self.parent()('OO_%s' % self.name()) def substitute(self, *args, **kwds): """ @@ -1300,7 +1300,7 @@ def cls(self): Ring """ - return self.parent()("class %s"%self.name()) + return self.parent()("class %s" % self.name()) def after_print_text(self): r""" @@ -1356,7 +1356,7 @@ def _operator(self, opstr, x): """ parent = self.parent() x = parent(x) - return parent("%s%s%s"%(self.name(), opstr, x.name())) + return parent("%s%s%s" % (self.name(), opstr, x.name())) def sharp(self, x): """ @@ -1683,7 +1683,7 @@ def _sage_(self): try: return sage_eval(repr_str) except Exception: - raise NotImplementedError("cannot convert %s to a Sage object"%repr_str) + raise NotImplementedError("cannot convert %s to a Sage object" % repr_str) to_sage = deprecated_function_alias(27848, ExpectElement.sage) @@ -1854,6 +1854,7 @@ def is_Macaulay2Element(x): return isinstance(x, Macaulay2Element) + # An instance macaulay2 = Macaulay2() diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index 4ff6477107f..b7a0ac20d03 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -1885,9 +1885,7 @@ def __getattr__(self, attrname): """ INPUT: - - - ``attrname`` - string - + - ``attrname`` -- string OUTPUT: a Magma function partially evaluated with self as the first input. @@ -1895,8 +1893,8 @@ def __getattr__(self, attrname): .. note:: If the input ``attrname`` starts with an underscore, an - AttributeError is raised so that the actual Python _ method/value - can be accessed. + :class:`AttributeError` is raised so that the actual + Python _ method/value can be accessed. EXAMPLES:: @@ -2751,7 +2749,6 @@ def ideal(self, gens): """ return self.parent().bar_call(self, 'ideal', gens, nvals=1) -########################################################################### magma = Magma() diff --git a/src/sage/interfaces/magma_free.py b/src/sage/interfaces/magma_free.py index 70f196a0fb2..d01d291c337 100644 --- a/src/sage/interfaces/magma_free.py +++ b/src/sage/interfaces/magma_free.py @@ -42,7 +42,7 @@ def magma_free_eval(code, strip=True, columns=0): processPath = "/xml/calculator.xml" refererPath = "/calc/" refererUrl = "http://%s%s" % ( server, refererPath) - code = "SetColumns(%s);\n"%columns + code + code = "SetColumns(%s);\n" % columns + code params = urlencode({'input':code}) headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "Accept: text/html, application/xml, application/xhtml+xml", "Referer": refererUrl} diff --git a/src/sage/interfaces/matlab.py b/src/sage/interfaces/matlab.py index a2678b4dbcc..24c40a3647c 100644 --- a/src/sage/interfaces/matlab.py +++ b/src/sage/interfaces/matlab.py @@ -356,6 +356,7 @@ def set(self, i, j, x): z = P(x) P.eval('{0}({1},{2}) = {3}'.format(self.name(), i, j, z.name())) + # An instance matlab = Matlab() diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index 959e75459a2..c55f9797ef2 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -887,7 +887,7 @@ def _batch(self, s, batchload=True): sage: maxima._batch('10003;',batchload=False) '...batch...10003...' """ - filename = '%s-%s'%(self._local_tmpfile(),randrange(2147483647)) + filename = '%s-%s' % (self._local_tmpfile(),randrange(2147483647)) F = open(filename, 'w') F.write(s) F.close() @@ -897,13 +897,13 @@ def _batch(self, s, batchload=True): tmp_to_use = filename if batchload: - cmd = 'batchload("%s");'%tmp_to_use + cmd = 'batchload("%s");' % tmp_to_use else: - cmd = 'batch("%s");'%tmp_to_use + cmd = 'batch("%s");' % tmp_to_use r = randrange(2147483647) s = str(r+1) - cmd = "%s1+%s;\n"%(cmd,r) + cmd = "%s1+%s;\n" % (cmd,r) self._sendline(cmd) self._expect_expr(s) @@ -969,7 +969,7 @@ def _error_msg(self, cmd, out): Maxima ERROR: Principal Value """ - raise TypeError("Error executing code in Maxima\nCODE:\n\t%s\nMaxima ERROR:\n\t%s"%(cmd, out.replace('-- an error. To debug this try debugmode(true);',''))) + raise TypeError("Error executing code in Maxima\nCODE:\n\t%s\nMaxima ERROR:\n\t%s" % (cmd, out.replace('-- an error. To debug this try debugmode(true);',''))) ########################################### # Direct access to underlying lisp interpreter. @@ -989,7 +989,7 @@ def lisp(self, cmd): 19 ( """ - self._eval_line(':lisp %s\n""'%cmd, allow_use_file=False, + self._eval_line(':lisp %s\n""' % cmd, allow_use_file=False, wait_for_prompt=False, reformat=False, error_check=False) self._expect_expr('(%i)') return self._before() @@ -1016,7 +1016,7 @@ def set(self, var, value): """ if not isinstance(value, str): raise TypeError - cmd = '%s : %s$'%(var, value.rstrip(';')) + cmd = '%s : %s$' % (var, value.rstrip(';')) if len(cmd) > self.__eval_using_file_cutoff: self._batch(cmd, batchload=True) else: @@ -1196,7 +1196,7 @@ def display2d(self, onscreen=True): P = self.parent() with gc_disabled(): P._eval_line('display2d : true$') - s = P._eval_line('disp(%s)$'%self.name(), reformat=False) + s = P._eval_line('disp(%s)$' % self.name(), reformat=False) P._eval_line('display2d : false$') s = s.strip('\r\n') diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index aecfcba5e23..9fe624a7f02 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -131,7 +131,7 @@ def chdir(self, dir): sage: maxima.chdir('/') """ - self.lisp('(ext::cd "%s")'%dir) + self.lisp('(ext::cd "%s")' % dir) ########################################### # Interactive help @@ -291,7 +291,7 @@ def completions(self, s, verbose=True): # create NAME-IMPL, without the leading $). This causes # name-impl to show up in $APROPOS. We remove it. # https://sourceforge.net/p/maxima/bugs/3643/ - cmd_list = self._eval_line('apropos("%s")'%s, error_check=False) + cmd_list = self._eval_line('apropos("%s")' % s, error_check=False) cmd_list = cmd_list.replace(' ', '').replace('\n', '').replace('\\ - ','-').replace('\\-','-') cmd_list = [x for x in cmd_list[1:-1].split(',') if x[0] != '?' and not x.endswith('-impl')] return [x for x in cmd_list if x.find(s) == 0] @@ -322,7 +322,7 @@ def _commands(self, verbose=True): return self.__commands except AttributeError: self.__commands = sum( - [self.completions(chr(65+n), verbose=verbose)+ + [self.completions(chr(65+n), verbose=verbose) + self.completions(chr(97+n), verbose=verbose) for n in range(26)], []) return self.__commands @@ -826,12 +826,12 @@ def plot3d_parametric(self, r, vars, urange, vrange, options=None): umax = urange[1] vmin = vrange[0] vmax = vrange[1] - cmd = 'plot3d([%s, %s, %s], [%s, %s, %s], [%s, %s, %s]'%( + cmd = 'plot3d([%s, %s, %s], [%s, %s, %s], [%s, %s, %s]' % ( r[0], r[1], r[2], vars[0], umin, umax, vars[1], vmin, vmax) if options is None: cmd += ')' else: - cmd += ', %s)'%options + cmd += ', %s)' % options self(cmd) def de_solve(self, de, vars, ics=None): @@ -861,18 +861,18 @@ def de_solve(self, de, vars, ics=None): y = -...%e^-1*(5*%e^x-3*%e*x-3*%e)... """ if not isinstance(vars, str): - str_vars = '%s, %s'%(vars[1], vars[0]) + str_vars = '%s, %s' % (vars[1], vars[0]) else: str_vars = vars - self.eval('depends(%s)'%str_vars) + self.eval('depends(%s)' % str_vars) m = self(de) - a = 'ode2(%s, %s)'%(m.name(), str_vars) + a = 'ode2(%s, %s)' % (m.name(), str_vars) if ics is not None: if len(ics) == 3: - cmd = "ic2("+a+",%s=%s,%s=%s,diff(%s,%s)=%s);"%(vars[0],ics[0], vars[1],ics[1], vars[1], vars[0], ics[2]) + cmd = "ic2("+a+",%s=%s,%s=%s,diff(%s,%s)=%s);" % (vars[0],ics[0], vars[1],ics[1], vars[1], vars[0], ics[2]) return self(cmd) if len(ics) == 2: - return self("ic1("+a+",%s=%s,%s=%s);"%(vars[0],ics[0], vars[1],ics[1])) + return self("ic1("+a+",%s=%s,%s=%s);" % (vars[0],ics[0], vars[1],ics[1])) return self(a+";") def de_solve_laplace(self, de, vars, ics=None): @@ -921,10 +921,10 @@ def de_solve_laplace(self, de, vars, ics=None): if not (ics is None): d = len(ics) for i in range(0,d-1): - ic = 'atvalue(diff(%s(%s), %s, %s), %s = %s, %s)'%( + ic = 'atvalue(diff(%s(%s), %s, %s), %s = %s, %s)' % ( vars[1], vars[0], vars[0], i, vars[0], ics[0], ics[1+i]) self.eval(ic) - return self('desolve(%s, %s(%s))'%(de, vars[1], vars[0])) + return self('desolve(%s, %s(%s))' % (de, vars[1], vars[0])) def solve_linear(self, eqns,vars): """ @@ -1026,11 +1026,11 @@ def plot_list(self, ptsx, ptsy, options=None): sage: opts='[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "zeta.eps"]' sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested """ - cmd = 'plot2d([discrete,%s, %s]'%(ptsx, ptsy) + cmd = 'plot2d([discrete,%s, %s]' % (ptsx, ptsy) if options is None: cmd += ')' else: - cmd += ', %s)'%options + cmd += ', %s)' % options self(cmd) def plot_multilist(self, pts_list, options=None): @@ -1074,7 +1074,7 @@ def plot_multilist(self, pts_list, options=None): for i in range(n): if i < n-1: cmd = cmd+'[discrete,'+str(pts_list[i][0])+','+str(pts_list[i][1])+'],' - if i==n-1: + if i == n-1: cmd = cmd+'[discrete,'+str(pts_list[i][0])+','+str(pts_list[i][1])+']]' if options is None: self('plot2d('+cmd+')') @@ -1182,11 +1182,11 @@ def _richcmp_(self, other, op): # are what Maxima needs P = self.parent() try: - if P.eval("is (%s < %s)"%(self.name(), other.name())) == P._true_symbol(): + if P.eval("is (%s < %s)" % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, -1) - elif P.eval("is (%s > %s)"%(self.name(), other.name())) == P._true_symbol(): + elif P.eval("is (%s > %s)" % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, 1) - elif P.eval("is (%s = %s)"%(self.name(), other.name())) == P._true_symbol(): + elif P.eval("is (%s = %s)" % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, 0) except TypeError: pass @@ -1608,7 +1608,7 @@ def __float__(self): try: return float(repr(self.numer())) except ValueError: - raise TypeError("unable to coerce '%s' to float"%repr(self)) + raise TypeError("unable to coerce '%s' to float" % repr(self)) def __len__(self): """ @@ -1625,7 +1625,7 @@ def __len__(self): 6 """ P = self._check_valid() - return int(P.eval('length(%s)'%self.name())) + return int(P.eval('length(%s)' % self.name())) def dot(self, other): """ @@ -1646,7 +1646,7 @@ def dot(self, other): """ P = self._check_valid() Q = P(other) - return P('%s . %s'%(self.name(), Q.name())) + return P('%s . %s' % (self.name(), Q.name())) def __getitem__(self, n): r""" @@ -1678,7 +1678,7 @@ def __getitem__(self, n): """ n = int(n) if n < 0 or n >= len(self): - raise IndexError("n = (%s) must be between %s and %s"%(n, 0, len(self)-1)) + raise IndexError("n = (%s) must be between %s and %s" % (n, 0, len(self)-1)) # If you change the n+1 to n below, better change __iter__ as well. return InterfaceElement.__getitem__(self, n+1) @@ -1740,7 +1740,7 @@ def comma(self, args): """ self._check_valid() P = self.parent() - return P('%s, %s'%(self.name(), args)) + return P('%s, %s' % (self.name(), args)) def _latex_(self): r""" @@ -1849,10 +1849,10 @@ def _matrix_(self, R): from sage.matrix.matrix_space import MatrixSpace self._check_valid() P = self.parent() - nrows = int(P.eval('length(%s)'%self.name())) + nrows = int(P.eval('length(%s)' % self.name())) if nrows == 0: return MatrixSpace(R, 0, 0)(0) - ncols = int(P.eval('length(%s[1])'%self.name())) + ncols = int(P.eval('length(%s[1])' % self.name())) M = MatrixSpace(R, nrows, ncols) s = self.str().replace('matrix','').replace(',',"','").\ replace("]','[","','").replace('([',"['").replace('])',"']") @@ -1920,12 +1920,12 @@ def _operation(self, operation, other=None): P = self._check_valid() if other is None: - cmd = '%s %s'%(operation, self._name) + cmd = '%s %s' % (operation, self._name) elif isinstance(other, P._object_function_class()): fself = P.function('', repr(self)) return fself._operation(operation, other) else: - cmd = '%s %s %s'%(self._name, operation, other._name) + cmd = '%s %s %s' % (self._name, operation, other._name) try: return P.new(cmd) except Exception as msg: @@ -2026,8 +2026,8 @@ def __call__(self, *args): """ P = self._check_valid() if len(args) == 1: - args = '(%s)'%args - return P('%s%s'%(self.name(), args)) + args = '(%s)' % args + return P('%s%s' % (self.name(), args)) def _repr_(self): """ @@ -2132,7 +2132,7 @@ def integral(self, var): """ var = str(var) P = self._check_valid() - f = P('integrate(%s(%s), %s)'%(self.name(), + f = P('integrate(%s(%s), %s)' % (self.name(), self.arguments(split=False), var)) args = self.arguments() diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index cd1be891872..211018e52cc 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -222,14 +222,14 @@ # See trac # 6818. init_code.append('nolabels : true') for l in init_code: - ecl_eval("#$%s$"%l) + ecl_eval("#$%s$" % l) # To get more debug information uncomment the next line # should allow to do this through a method #ecl_eval("(setf *standard-output* original-standard-output)") # This is the main function (ECL object) used for evaluation # This returns an EclObject -maxima_eval=ecl_eval(""" +maxima_eval = ecl_eval(""" (defun maxima-eval( form ) (with-$error (meval form))) """) @@ -240,27 +240,27 @@ # Here we define several useful ECL/Maxima objects # The Maxima string function can change the structure of its input #maxprint=EclObject("$STRING") -maxprint=EclObject(r"""(defun mstring-for-sage (form) +maxprint = EclObject(r"""(defun mstring-for-sage (form) (coerce (mstring form) 'string))""").eval() -meval=EclObject("MEVAL") -msetq=EclObject("MSETQ") -mlist=EclObject("MLIST") -mequal=EclObject("MEQUAL") -cadadr=EclObject("CADADR") - -max_integrate=EclObject("$INTEGRATE") -max_sum=EclObject("$SUM") -max_simplify_sum=EclObject("$SIMPLIFY_SUM") -max_prod=EclObject("$PRODUCT") -max_simplify_prod=EclObject("$SIMPLIFY_PRODUCT") -max_ratsimp=EclObject("$RATSIMP") -max_limit=EclObject("$LIMIT") -max_tlimit=EclObject("$TLIMIT") -max_plus=EclObject("$PLUS") -max_minus=EclObject("$MINUS") -max_use_grobner=EclObject("$USE_GROBNER") -max_to_poly_solve=EclObject("$TO_POLY_SOLVE") -max_at=EclObject("%AT") +meval = EclObject("MEVAL") +msetq = EclObject("MSETQ") +mlist = EclObject("MLIST") +mequal = EclObject("MEQUAL") +cadadr = EclObject("CADADR") + +max_integrate = EclObject("$INTEGRATE") +max_sum = EclObject("$SUM") +max_simplify_sum = EclObject("$SIMPLIFY_SUM") +max_prod = EclObject("$PRODUCT") +max_simplify_prod = EclObject("$SIMPLIFY_PRODUCT") +max_ratsimp = EclObject("$RATSIMP") +max_limit = EclObject("$LIMIT") +max_tlimit = EclObject("$TLIMIT") +max_plus = EclObject("$PLUS") +max_minus = EclObject("$MINUS") +max_use_grobner = EclObject("$USE_GROBNER") +max_to_poly_solve = EclObject("$TO_POLY_SOLVE") +max_at = EclObject("%AT") def stdout_to_string(s): r""" @@ -284,7 +284,7 @@ def stdout_to_string(s): '2\n\n' """ return ecl_eval(r"""(with-output-to-string (*standard-output*) - (maxima-eval #$%s$))"""%s).python()[1:-1] + (maxima-eval #$%s$))""" % s).python()[1:-1] def max_to_string(s): r""" @@ -305,7 +305,8 @@ def max_to_string(s): """ return maxprint(s).python()[1:-1] -my_mread=ecl_eval(""" + +my_mread = ecl_eval(""" (defun my-mread (cmd) (caddr (mread (make-string-input-stream cmd)))) """) @@ -326,7 +327,7 @@ def parse_max_string(s): sage: parse_max_string('1+1') """ - return my_mread('"%s;"'%s) + return my_mread('"%s;"' % s) class MaximaLib(MaximaAbstract): """ @@ -457,9 +458,9 @@ def _eval_line(self, line, locals=None, reformat=True, **kwds): """ result = '' while line: - ind_dollar=line.find("$") - ind_semi=line.find(";") - if ind_dollar == -1 or (ind_semi >=0 and ind_dollar > ind_semi): + ind_dollar = line.find("$") + ind_semi = line.find(";") + if ind_dollar == -1 or (ind_semi >= 0 and ind_dollar > ind_semi): if ind_semi == -1: statement = line line = '' @@ -467,7 +468,7 @@ def _eval_line(self, line, locals=None, reformat=True, **kwds): statement = line[:ind_semi] line = line[ind_semi+1:] if statement: - result = ((result + '\n') if result else '') + max_to_string(maxima_eval("#$%s$"%statement)) + result = ((result + '\n') if result else '') + max_to_string(maxima_eval("#$%s$" % statement)) else: statement = line[:ind_dollar] line = line[ind_dollar+1:] @@ -525,7 +526,7 @@ def set(self, var, value): """ if not isinstance(value, str): raise TypeError - cmd = '%s : %s$'%(var, value.rstrip(';')) + cmd = '%s : %s$' % (var, value.rstrip(';')) self.eval(cmd) def clear(self, var): @@ -549,8 +550,8 @@ def clear(self, var): 'xxxxx' """ try: - self.eval('kill(%s)$'%var) - ecl_eval("(unintern '$%s)"%var) + self.eval('kill(%s)$' % var) + ecl_eval("(unintern '$%s)" % var) except (TypeError, AttributeError): pass @@ -571,7 +572,7 @@ def get(self, var): sage: maxima_lib.get('xxxxx') '2' """ - s = self.eval('%s;'%var) + s = self.eval('%s;' % var) return s def _create(self, value, name=None): @@ -616,7 +617,7 @@ def _create(self, value, name=None): name = self._next_var_name() if name is None else name try: if isinstance(value,EclObject): - maxima_eval([[msetq],cadadr("#$%s$#$"%name),value]) + maxima_eval([[msetq],cadadr("#$%s$#$" % name),value]) else: self.set(name, value) except RuntimeError as error: @@ -1050,7 +1051,7 @@ def _missing_assumption(self,errstr): k = errstr.find(' ',jj+1) outstr = "Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume("\ - + errstr[jj+1:k] +">0)', see `assume?` for more details)\n" + errstr + + errstr[jj+1:k] + ">0)', see `assume?` for more details)\n" + errstr outstr = outstr.replace('_SAGE_VAR_','') raise ValueError(outstr) @@ -1109,7 +1110,7 @@ def ecl(self): try: return self._ecl except AttributeError: - self._ecl=maxima_eval("#$%s$"%self._name) + self._ecl = maxima_eval("#$%s$" % self._name) return self._ecl def to_poly_solve(self,vars,options=""): @@ -1135,10 +1136,10 @@ def to_poly_solve(self,vars,options=""): [[x == pi*z...]] """ if options.find("use_grobner=true") != -1: - cmd=EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars), + cmd = EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars), [[mequal],max_use_grobner,True]]) else: - cmd=EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars)]) + cmd = EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars)]) return self.parent()(maxima_eval(cmd)) def display2d(self, onscreen=True): @@ -1165,7 +1166,7 @@ def display2d(self, onscreen=True): self._check_valid() P = self.parent() P._eval_line('display2d : true$') - s = stdout_to_string('disp(%s)'%self.name()) + s = stdout_to_string('disp(%s)' % self.name()) #s = P._eval_line('disp(%s)$'%self.name()) P._eval_line('display2d : false$') s = s.strip('\r\n') @@ -1215,17 +1216,17 @@ def reduce_load_MaximaLib(): from sage.rings.number_field.number_field_element_base import NumberFieldElement_base from sage.symbolic.operators import FDerivativeOperator, add_vararg, mul_vararg -car=EclObject("car") -cdr=EclObject("cdr") -caar=EclObject("caar") -cadr=EclObject("cadr") -cddr=EclObject("cddr") -caddr=EclObject("caddr") -caaadr=EclObject("caaadr") -cadadr=EclObject("cadadr") -meval=EclObject("meval") -NIL=EclObject("NIL") -lisp_length=EclObject("length") +car = EclObject("car") +cdr = EclObject("cdr") +caar = EclObject("caar") +cadr = EclObject("cadr") +cddr = EclObject("cddr") +caddr = EclObject("caddr") +caaadr = EclObject("caaadr") +cadadr = EclObject("cadadr") +meval = EclObject("meval") +NIL = EclObject("NIL") +lisp_length = EclObject("length") # Dictionaries for standard operators sage_op_dict = { @@ -1278,12 +1279,13 @@ def sage_rat(x,y): """ return x/y -mplus=EclObject("MPLUS") -mtimes=EclObject("MTIMES") -rat=EclObject("RAT") -max_op_dict[mplus]=add_vararg -max_op_dict[mtimes]=mul_vararg -max_op_dict[rat]=sage_rat + +mplus = EclObject("MPLUS") +mtimes = EclObject("MTIMES") +rat = EclObject("RAT") +max_op_dict[mplus] = add_vararg +max_op_dict[mtimes] = mul_vararg +max_op_dict[rat] = sage_rat # Here we build dictionaries for operators needing special conversions. @@ -1363,9 +1365,9 @@ def mqapply_to_sage(expr): mlist_to_sage(car(cdr(cdr(cdr(expr))))), max_to_sr(car(cdr(cdr(cdr(cdr(expr))))))) else: - op=max_to_sr(cadr(expr)) - max_args=cddr(expr) - args=[max_to_sr(a) for a in max_args] + op = max_to_sr(cadr(expr)) + max_args = cddr(expr) + args = [max_to_sr(a) for a in max_args] return op(*args) def mdiff_to_sage(expr): @@ -1434,13 +1436,13 @@ def max_at_to_sage(expr): sage: max_at_to_sage(a.ecl()) f(1, y, z) """ - arg=max_to_sr(expr.cadr()) - subsarg=caddr(expr) - if caar(subsarg)==mlist: - subsvalues=dict( (v.lhs(),v.rhs()) for v in max_to_sr(subsarg)) + arg = max_to_sr(expr.cadr()) + subsarg = caddr(expr) + if caar(subsarg) == mlist: + subsvalues = dict( (v.lhs(),v.rhs()) for v in max_to_sr(subsarg)) else: - v=max_to_sr(subsarg) - subsvalues=dict([(v.lhs(),v.rhs())]) + v = max_to_sr(subsarg) + subsvalues = dict([(v.lhs(),v.rhs())]) return SR(arg).subs(subsvalues) def dummy_integrate(expr): @@ -1524,24 +1526,24 @@ def max_pochhammer_to_sage(expr): max_pochhammer: max_pochhammer_to_sage } -special_sage_to_max={ +special_sage_to_max = { sage.functions.log.polylog : lambda N,X : [[mqapply],[[max_li, max_array],N],X], sage.functions.gamma.psi1 : lambda X : [[mqapply],[[max_psi, max_array],0],X], sage.functions.gamma.psi2 : lambda N,X : [[mqapply],[[max_psi, max_array],N],X], - sage.functions.log.lambert_w : lambda N,X : [[max_lambert_w], X] if N==EclObject(0) else [[mqapply],[[max_lambert_w, max_array],N],X], + sage.functions.log.lambert_w : lambda N,X : [[max_lambert_w], X] if N == EclObject(0) else [[mqapply],[[max_lambert_w, max_array],N],X], sage.functions.log.harmonic_number : lambda N,X : [[max_harmo],X,N], sage.functions.hypergeometric.hypergeometric : lambda A, B, X : [[mqapply],[[max_hyper, max_array],lisp_length(A.cdr()),lisp_length(B.cdr())],A,B,X] } # Dictionaries for symbols -sage_sym_dict={} -max_sym_dict={} +sage_sym_dict = {} +max_sym_dict = {} # Generic conversion functions -max_i=EclObject("$%I") +max_i = EclObject("$%I") def pyobject_to_max(obj): r""" Convert a (simple) Python object into a Maxima object. @@ -1637,13 +1639,13 @@ def sr_to_max(expr): # _symbol0=1. See trac #12796. Note that we cannot use # SR.temp_var here since two conversions of the same # expression have to be equal. - temp_args = [SR.symbol("_symbol%s"%i) for i in range(len(args))] + temp_args = [SR.symbol("_symbol%s" % i) for i in range(len(args))] f = sr_to_max(op.function()(*temp_args)) params = op.parameter_set() deriv_max = [[mdiff],f] for i in set(params): deriv_max.extend([sr_to_max(temp_args[i]), EclObject(params.count(i))]) - at_eval=sr_to_max([temp_args[i]==args[i] for i in range(len(args))]) + at_eval = sr_to_max([temp_args[i] == args[i] for i in range(len(args))]) return EclObject([[max_at],deriv_max,at_eval]) f = sr_to_max(op.function()(*args)) @@ -1683,6 +1685,7 @@ def sr_to_max(expr): except TypeError: return maxima(expr).ecl() + # This goes from EclObject to SR from sage.symbolic.expression import symbol_table max_to_pynac_table = symbol_table['maxima'] @@ -1715,7 +1718,7 @@ def max_to_sr(expr): True """ if expr.consp(): - op_max=caar(expr) + op_max = caar(expr) if op_max in special_max_to_sage: return special_max_to_sage[op_max](expr) if op_max not in max_op_dict: @@ -1729,8 +1732,8 @@ def max_to_sr(expr): op = sage_expr.operator() if op in sage_op_dict: raise RuntimeError("Encountered operator mismatch in maxima-to-sr translation") - max_op_dict[op_max]=op - sage_op_dict[op]=op_max + max_op_dict[op_max] = op + sage_op_dict[op] = op_max else: op = max_op_dict[op_max] max_args = cdr(expr) diff --git a/src/sage/interfaces/mupad.py b/src/sage/interfaces/mupad.py index 8a101ab0995..956de696806 100644 --- a/src/sage/interfaces/mupad.py +++ b/src/sage/interfaces/mupad.py @@ -264,11 +264,11 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, global seq seq += 1 - START = '__start__(%s+1)'%seq - END = '__end__(%s+1)'%seq - line = '%s; %s; %s;'%(START, line, END) - START = '__start__(%s)'%(seq+1) - END = '__end__(%s)'%(seq+1) + START = '__start__(%s+1)' % seq + END = '__end__(%s+1)' % seq + line = '%s; %s; %s;' % (START, line, END) + START = '__start__(%s)' % (seq+1) + END = '__end__(%s)' % (seq+1) E = self._expect E.sendline(line) @@ -276,7 +276,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, z = E.before i = z.find(START) if i == -1: - raise RuntimeError("%s\nError evaluating code in MuPAD"%z) + raise RuntimeError("%s\nError evaluating code in MuPAD" % z) z = z[i+len(START)+2:] z = z.rstrip().rstrip(END).rstrip('"').rstrip().strip('\n').strip('\r').strip('\n').replace('\\\r\n','') i = z.find('Error: ') @@ -294,7 +294,7 @@ def cputime(self, t=None): if t is None: return float(str(self('time()')))/1000 else: - return float(str(self('time() - %s'%float(t))))/1000 + return float(str(self('time() - %s' % float(t))))/1000 def set(self, var, value): """ @@ -306,7 +306,7 @@ def set(self, var, value): sage: mupad.get('a').strip() # optional - mupad '4' """ - cmd = '%s:=%s:'%(var,value) + cmd = '%s:=%s:' % (var,value) out = self.eval(cmd) i = out.find('Error: ') if i != -1: @@ -323,7 +323,7 @@ def get(self, var): '4' """ - s = self.eval('%s'%var) + s = self.eval('%s' % var) i = s.find('=') return s[i+1:] @@ -425,7 +425,7 @@ def completions(self, string, strip=False): sage: mupad.completions('linal') # optional - mupad ['linalg'] """ - res = self.eval('_pref(Complete)("%s")'%string).strip() + res = self.eval('_pref(Complete)("%s")' % string).strip() res = res.replace('\n', '').split(',') res = [s.strip().strip('"') for s in res] res = [s for s in res if not s.endswith('::')] @@ -507,7 +507,7 @@ def __getattr__(self, attrname): else: return self.__dict__[attrname] name = self._name+"::"+attrname - if P.eval('type(%s)'%name) == "DOM_DOMAIN": + if P.eval('type(%s)' % name) == "DOM_DOMAIN": return MupadElement(P, name) else: return MupadFunctionElement(self._obj, name) @@ -538,7 +538,7 @@ def __call__(self, *args): s[1, 1, 1] """ P = self._obj.parent() - if P.eval('type(%s)'%(self._obj.name())).strip() == "DOM_DOMAIN": + if P.eval('type(%s)' % (self._obj.name())).strip() == "DOM_DOMAIN": return P.function_call(self._name, list(args)) else: return P.function_call(self._name, [self._obj] + list(args)) @@ -572,8 +572,8 @@ def __getattr__(self, attrname): name = self._name + "::" + attrname try: - if P.eval('type(%s::%s)'%(self.name(),attrname)).strip() == "DOM_DOMAIN": - return P.new("%s::%s"%(self.name(),attrname)) + if P.eval('type(%s::%s)' % (self.name(),attrname)).strip() == "DOM_DOMAIN": + return P.new("%s::%s" % (self.name(),attrname)) else: return MupadFunctionElement(self, name) except RuntimeError as err: @@ -605,7 +605,7 @@ def _latex_(self): """ self._check_valid() P = self.parent() - s = P._eval_line('generate::TeX(%s)'%self.name()) + s = P._eval_line('generate::TeX(%s)' % self.name()) s = s.replace('\\\\','\\').strip().strip('"') return s @@ -638,6 +638,7 @@ def __len__(self): """ return mupad.nops(self) + # An instance mupad = Mupad() diff --git a/src/sage/interfaces/mwrank.py b/src/sage/interfaces/mwrank.py index ae65d0ffea0..35d73277109 100644 --- a/src/sage/interfaces/mwrank.py +++ b/src/sage/interfaces/mwrank.py @@ -67,6 +67,7 @@ def Mwrank(options="", server=None, server_tmpdir=None): instances[options] = weakref.ref(X) return X + import re # regex matching '[a1,a2,a3,a4,a6]', no spaces, each ai a possibly signed integer AINVS_LIST_RE = re.compile(r'\[[+-]?(\d+)(,[+-]?\d+){4}]') @@ -87,7 +88,8 @@ def validate_mwrank_input(s): OUTPUT: - For valid input, a string of the form '[a1,a2,a3,a4,a6]'. For invalid input a ValueError is raised. + For valid input, a string of the form '[a1,a2,a3,a4,a6]'. + For invalid input a :class:`ValueError` is raised. EXAMPLES: @@ -124,7 +126,7 @@ def validate_mwrank_input(s): """ if isinstance(s,(list,tuple)): from sage.rings.integer_ring import ZZ - if len(s)!=5: + if len(s) != 5: raise ValueError("%s is not valid input to mwrank (should have 5 entries)" % s) try: ai = [ZZ(a) for a in s] diff --git a/src/sage/interfaces/octave.py b/src/sage/interfaces/octave.py index f8f426c67e6..a1a9ba50582 100644 --- a/src/sage/interfaces/octave.py +++ b/src/sage/interfaces/octave.py @@ -294,18 +294,18 @@ def _eval_line(self, line, reformat=True, allow_use_file=False, return '' if self._expect is None: self._start() - if allow_use_file and len(line)>3000: + if allow_use_file and len(line) > 3000: return self._eval_line_using_file(line) try: E = self._expect # debug # self._synchronize(cmd='1+%s\n') - verbose("in = '%s'"%line,level=3) + verbose("in = '%s'" % line,level=3) E.sendline(line) E.expect(self._prompt) out = bytes_to_str(E.before) # debug - verbose("out = '%s'"%out,level=3) + verbose("out = '%s'" % out,level=3) except EOF: if self._quit_string() in line: return '' @@ -321,7 +321,7 @@ def _eval_line(self, line, reformat=True, allow_use_file=False, return '' def _keyboard_interrupt(self): - print("CntrlC: Interrupting %s..."%self) + print("CntrlC: Interrupting %s..." % self) if self._restart_on_ctrlc: try: self._expect.close(force=1) @@ -411,7 +411,7 @@ def set(self, var, value): cmd = '%s=%s;' % (var, value) out = self.eval(cmd) if out.find("error") != -1 or out.find("Error") != -1: - raise TypeError("Error executing code in Octave\nCODE:\n\t%s\nOctave ERROR:\n\t%s"%(cmd, out)) + raise TypeError("Error executing code in Octave\nCODE:\n\t%s\nOctave ERROR:\n\t%s" % (cmd, out)) def get(self, var): """ @@ -423,7 +423,7 @@ def get(self, var): sage: octave.get('x') # optional - octave ' 2' """ - s = self.eval('%s'%var) + s = self.eval('%s' % var) i = s.find('=') return s[i+1:] @@ -578,11 +578,11 @@ def de_system_plot(self, f, ics, trange): """ eqn1 = f[0].replace('x','x(1)').replace('y','x(2)') eqn2 = f[1].replace('x','x(1)').replace('y','x(2)') - fcn = "function xdot = f(x,t) xdot(1) = %s; xdot(2) = %s; endfunction"%(eqn1, eqn2) + fcn = "function xdot = f(x,t) xdot(1) = %s; xdot(2) = %s; endfunction" % (eqn1, eqn2) self.eval(fcn) - x0_eqn = "x0 = [%s; %s]"%(ics[0], ics[1]) + x0_eqn = "x0 = [%s; %s]" % (ics[0], ics[1]) self.eval(x0_eqn) - t_eqn = "t = linspace(%s, %s, 200)'"%(trange[0], trange[1]) + t_eqn = "t = linspace(%s, %s, 200)'" % (trange[0], trange[1]) self.eval(t_eqn) x_eqn = 'x = lsode("f",x0,t);' self.eval(x_eqn) @@ -808,6 +808,7 @@ def _sage_(self): else: raise NotImplementedError('octave type is not recognized') + # An instance octave = Octave() diff --git a/src/sage/interfaces/psage.py b/src/sage/interfaces/psage.py index f00d0612703..b64a0b15c5f 100644 --- a/src/sage/interfaces/psage.py +++ b/src/sage/interfaces/psage.py @@ -74,7 +74,7 @@ def _repr_(self): A running non-blocking (parallel) instance of Sage (number ...) """ - return 'A running non-blocking (parallel) instance of Sage (number %s)'%(self._number) + return 'A running non-blocking (parallel) instance of Sage (number %s)' % (self._number) def _unlock(self): self._locked = False @@ -124,7 +124,7 @@ def __del__(self): pass if not (self._expect is None): - cmd = 'kill -9 %s'%self._expect.pid + cmd = 'kill -9 %s' % self._expect.pid os.system(cmd) def eval(self, x, strip=True, **kwds): @@ -158,7 +158,7 @@ def set(self, var, value): """ Set the variable var to the given value. """ - cmd = '%s=%s'%(var,value) + cmd = '%s=%s' % (var,value) self._send_nowait(cmd) time.sleep(0.02) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index f54c8e181d7..b6b657515bc 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -660,7 +660,8 @@ def _qepcad_cmd(memcells=None): memcells_arg = '+N%s' % memcells else: memcells_arg = '' - return "env qe=%s qepcad %s"%(SAGE_LOCAL, memcells_arg) + return "env qe=%s qepcad %s" % (SAGE_LOCAL, memcells_arg) + _command_info_cache = None @@ -834,7 +835,7 @@ def __init__(self, formula, self._cell_cache = {} if verbose: - logfile=sys.stdout + logfile = sys.stdout varlist = None if vars is not None: @@ -1319,14 +1320,14 @@ def _function_call(self, name, args): name = name.replace('_', '-') args = [str(_) for _ in args] pre_phase = self.phase() - result = self._eval_line('%s %s'%(name, ' '.join(args))) + result = self._eval_line('%s %s' % (name, ' '.join(args))) post_phase = self.phase() if len(result) and post_phase != 'EXITED': return AsciiArtString(result) if pre_phase != post_phase: if post_phase == 'EXITED' and name != 'quit': return self.answer() - return AsciiArtString("QEPCAD object has moved to phase '%s'"%post_phase) + return AsciiArtString("QEPCAD object has moved to phase '%s'" % post_phase) def _format_cell_index(a): """ diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index e068c324b13..575646f2365 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -45,7 +45,7 @@ def register_spawned_process(pid, cmd=''): # This is safe, since only this process writes to this file. try: with open(sage_spawned_process_file(), 'a') as o: - o.write('%s %s\n'%(pid, cmd)) + o.write('%s %s\n' % (pid, cmd)) except IOError: pass else: diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index 7d18f1e467e..068e65a2096 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -287,7 +287,7 @@ lazy_import("rpy2.robjects.help", "Package") lazy_import("rpy2", "rinterface") -COMMANDS_CACHE = '%s/r_commandlist.sobj'%DOT_SAGE +COMMANDS_CACHE = '%s/r_commandlist.sobj' % DOT_SAGE #there is a mirror network, but lets take #1 for now RRepositoryURL = "http://cran.r-project.org/" @@ -596,8 +596,8 @@ def _start(self): # pager needed to replace help view from less to printout # option device= is for plotting, is set to x11, NULL would be better? self.eval('options(pager="cat",device="png")') - self.eval('options(repos="%s")'%RRepositoryURL) - self.eval('options(CRAN="%s")'%RRepositoryURL) + self.eval('options(repos="%s")' % RRepositoryURL) + self.eval('options(CRAN="%s")' % RRepositoryURL) # don't abort on errors, just raise them! # necessary for non-interactive execution @@ -683,8 +683,8 @@ def install_packages(self, package_name): ... Please restart Sage in order to use 'aaMI'. """ - cmd = """options(repos="%s"); install.packages("%s")"""%(RRepositoryURL, package_name) - os.system("time echo '%s' | R --vanilla"%cmd) + cmd = """options(repos="%s"); install.packages("%s")""" % (RRepositoryURL, package_name) + os.system("time echo '%s' | R --vanilla" % cmd) print("Please restart Sage in order to use '%s'." % package_name) def _repr_(self): @@ -744,7 +744,7 @@ def _read_in_file_command(self, filename): sage: r._read_in_file_command('file.txt') # optional - rpy2 'file=file("file.txt",open="r")\nsource(file)' """ - return 'file=file("%s",open="r")\nsource(file)'%filename + return 'file=file("%s",open="r")\nsource(file)' % filename def read(self, filename): r""" @@ -788,7 +788,7 @@ def _source(self, s): """ if s[-2:] == "()": s = s[-2:] - return self.eval('%s'%s) + return self.eval('%s' % s) def source(self, s): """ @@ -891,7 +891,7 @@ def available_packages(self): sage: len(ap) > 20 # optional - internet # optional - rpy2 True """ - p = self.new('available.packages("%s/src/contrib")'%RRepositoryURL) + p = self.new('available.packages("%s/src/contrib")' % RRepositoryURL) s = str(p).splitlines()[1:] v = [x.split()[0].strip("'") for x in s] return v @@ -1071,7 +1071,7 @@ def function_call(self, function, args=None, kwds=None): """ args, kwds = self._convert_args_kwds(args, kwds) self._check_valid_function_name(function) - return self.new("%s(%s)"%(function, ",".join([s.name() for s in args] + + return self.new("%s(%s)" % (function, ",".join([s.name() for s in args] + [self._sage_to_r_name(key)+'='+kwds[key].name() for key in kwds ] ))) def call(self, function_name, *args, **kwds): @@ -1117,7 +1117,7 @@ def set(self, var, value): '[1] 5' """ - cmd = '%s <- %s'%(var,value) + cmd = '%s <- %s' % (var,value) out = self.eval(cmd) def get(self, var): @@ -1136,7 +1136,7 @@ def get(self, var): sage: r.get('a') # optional - rpy2 '[1] 2' """ - return self.eval('%s'%var) + return self.eval('%s' % var) def na(self): """ @@ -1195,7 +1195,7 @@ def _commands(self): if lib.find("package:") != 0: continue #only packages - raw = self('objects("%s")'%lib)._sage_() + raw = self('objects("%s")' % lib)._sage_() #TODO are there others? many of them are shortcuts or #should be done on another level, like selections in lists @@ -1508,7 +1508,7 @@ def __len__(self): sage: len(x) # optional - rpy2 5 """ - return self.parent()('length(%s)'%self.name()).sage() + return self.parent()('length(%s)' % self.name()).sage() def __getattr__(self, attrname): """ @@ -1589,11 +1589,11 @@ def __getitem__(self, n): P = self._check_valid() if isinstance(n, str): n = n.replace('self', self._name) - return P.new('%s[%s]'%(self._name, n)) + return P.new('%s[%s]' % (self._name, n)) elif parent(n) is P: # the key is RElement itself - return P.new('%s[%s]'%(self._name, n.name())) + return P.new('%s[%s]' % (self._name, n.name())) elif not isinstance(n,tuple): - return P.new('%s[%s]'%(self._name, n)) + return P.new('%s[%s]' % (self._name, n)) else: L = [] for i in range(len(n)): @@ -1601,7 +1601,7 @@ def __getitem__(self, n): L.append(n[i].name()) else: L.append(str(n[i])) - return P.new('%s[%s]'%(self._name, ','.join(L))) + return P.new('%s[%s]' % (self._name, ','.join(L))) def __bool__(self): """ @@ -1646,7 +1646,7 @@ def _comparison(self, other, symbol): """ P = self.parent() other = P(other) - return P('%s %s %s'%(self.name(), symbol, other.name())) + return P('%s %s %s' % (self.name(), symbol, other.name())) def __eq__(self, other): """ @@ -1791,7 +1791,7 @@ def dot_product(self, other): P = self._check_valid() Q = P(other) # the R operator is %*% for matrix multiplication - return P('%s %%*%% %s'%(self.name(), Q.name())) + return P('%s %%*%% %s' % (self.name(), Q.name())) def _sage_(self): r""" @@ -2030,6 +2030,7 @@ def is_RElement(x): return isinstance(x, RElement) + # An instance of R r = R() @@ -2045,6 +2046,7 @@ def reduce_load_R(): """ return r + import os def r_console(): """ diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 75ab263a53e..54c28f55598 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -349,10 +349,10 @@ def set(self, var, value): sage: scilab.get('a') # optional - scilab '\n \n 123.' """ - cmd = '%s=%s;'%(var,value) + cmd = '%s=%s;' % (var,value) out = self.eval(cmd) if out.find("error") != -1: - raise TypeError("Error executing code in Scilab\nCODE:\n\t%s\nScilab ERROR:\n\t%s"%(cmd, out)) + raise TypeError("Error executing code in Scilab\nCODE:\n\t%s\nScilab ERROR:\n\t%s" % (cmd, out)) def get(self, var): """ @@ -365,7 +365,7 @@ def get(self, var): sage: scilab.get('b') # optional - scilab '\n \n 124.' """ - s = self.eval('%s'%var) + s = self.eval('%s' % var) i = s.find('=') return s[i+1:] @@ -509,7 +509,8 @@ def set(self, i, j, x): """ P = self._check_valid() z = P(x) - P.eval('%s(%s,%s) = %s'%(self.name(), i, j, z.name())) + P.eval('%s(%s,%s) = %s' % (self.name(), i, j, z.name())) + # An instance scilab = Scilab() diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index b15cc1c602c..c4fb1261288 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -604,8 +604,7 @@ def eval(self, x, allow_semicolon=True, strip=True, **kwds): sage: i = singular.ideal(['x^2','y^2','z^2']) sage: s = i.std() sage: singular.eval('hilb(%s)'%(s.name())) - '// 1 t^0\n// -3 t^2\n// 3 t^4\n// -1 t^6\n\n// 1 t^0\n// - 3 t^1\n// 3 t^2\n// 1 t^3\n// dimension (affine) = 0\n// + '...// dimension (affine) = 0\n// degree (affine) = 8' :: @@ -613,15 +612,7 @@ def eval(self, x, allow_semicolon=True, strip=True, **kwds): sage: from sage.misc.verbose import set_verbose sage: set_verbose(1) sage: o = singular.eval('hilb(%s)'%(s.name())) - // 1 t^0 - // -3 t^2 - // 3 t^4 - // -1 t^6 - // 1 t^0 - // 3 t^1 - // 3 t^2 - // 1 t^3 - // dimension (affine) = 0 + ...// dimension (affine) = 0 // degree (affine) = 8 This is mainly useful if this method is called implicitly. Because @@ -631,15 +622,7 @@ def eval(self, x, allow_semicolon=True, strip=True, **kwds): :: sage: o = s.hilb() - // 1 t^0 - // -3 t^2 - // 3 t^4 - // -1 t^6 - // 1 t^0 - // 3 t^1 - // 3 t^2 - // 1 t^3 - // dimension (affine) = 0 + ...// dimension (affine) = 0 // degree (affine) = 8 // ** right side is not a datum, assignment ignored ... @@ -681,7 +664,7 @@ def eval(self, x, allow_semicolon=True, strip=True, **kwds): # "Segment fault" is not a typo: # Singular actually does use that string if s.find("error occurred") != -1 or s.find("Segment fault") != -1: - raise SingularError('Singular error:\n%s'%s) + raise SingularError('Singular error:\n%s' % s) if get_verbose() > 0: for line in s.splitlines(): @@ -720,8 +703,8 @@ def set(self, type, name, value): '0' """ - cmd = ''.join('if(defined(%s)){kill %s;};'%(v,v) for v in self.__to_clear) - cmd += '%s %s=%s;'%(type, name, value) + cmd = ''.join('if(defined(%s)){kill %s;};' % (v,v) for v in self.__to_clear) + cmd += '%s %s=%s;' % (type, name, value) self.__to_clear = [] self.eval(cmd) @@ -735,7 +718,7 @@ def get(self, var): sage: singular.get('x') '2' """ - return self.eval('print(%s);'%var) + return self.eval('print(%s);' % var) def clear(self, var): """ @@ -860,13 +843,13 @@ def cputime(self, t=None): 0.02 """ if t: - return float(self.eval('timer-(%d)'%(int(1000*t))))/1000.0 + return float(self.eval('timer-(%d)' % (int(1000*t))))/1000.0 else: return float(self.eval('timer'))/1000.0 - ################################################################### + ########################################################### # Singular libraries - ################################################################### + ########################################################### def lib(self, lib, reload=False): """ Load the Singular library named lib. @@ -890,9 +873,9 @@ def lib(self, lib, reload=False): LIB = lib load = lib - ################################################################### + ########################################################## # constructors - ################################################################### + ########################################################## def ideal(self, *gens): """ Return the ideal generated by gens. @@ -1058,9 +1041,9 @@ def matrix(self, nrows, ncols, entries=None): """ name = self._next_var_name() if entries is None: - self.eval('matrix %s[%s][%s]'%(name, nrows, ncols)) + self.eval('matrix %s[%s][%s]' % (name, nrows, ncols)) else: - self.eval('matrix %s[%s][%s] = %s'%(name, nrows, ncols, entries)) + self.eval('matrix %s[%s][%s] = %s' % (name, nrows, ncols, entries)) return SingularElement(self, None, name, True) def ring(self, char=0, vars='(x)', order='lp', check=None): @@ -1417,8 +1400,8 @@ def _repr_(self): """ s = super(SingularElement, self)._repr_() if self._name in s: - if (not hasattr(self, "__custom_name")) and self.type() == 'matrix': - s = self.parent().eval('pmat(%s,20)'%(self.name())) + if self.get_custom_name() is None and self.type() == 'matrix': + s = self.parent().eval('pmat(%s,20)' % (self.name())) return s def __copy__(self): @@ -1459,13 +1442,13 @@ def __copy__(self): 0, y,0, x*y,0,0 """ - if (self.type()=='ring') or (self.type()=='qring'): + if (self.type() == 'ring') or (self.type() == 'qring'): # Problem: singular has no clean method to produce # a copy of a ring/qring. We use ringlist, but this # is only possible if we make self the active ring, # use ringlist, and switch back to the previous # base ring. - br=self.parent().current_ring() + br = self.parent().current_ring() self.set_ring() OUT = (self.ringlist()).ring() br.set_ring() @@ -1525,9 +1508,9 @@ def __setitem__(self, n, value): if len(n) != 2: raise ValueError("If n (=%s) is a tuple, it must be a 2-tuple" % n) x, y = n - P.eval('%s[%s,%s] = %s'%(self.name(), x, y, value.name())) + P.eval('%s[%s,%s] = %s' % (self.name(), x, y, value.name())) else: - P.eval('%s[%s] = %s'%(self.name(), n, value.name())) + P.eval('%s[%s] = %s' % (self.name(), n, value.name())) def __bool__(self): """ @@ -1651,7 +1634,7 @@ def sage_global_ring(self): singular = self.parent() charstr = singular.eval('charstr(basering)').split(',',1) from sage.rings.integer_ring import ZZ - is_extension = len(charstr)==2 + is_extension = len(charstr) == 2 if charstr[0] in ['integer', 'ZZ']: br = ZZ is_extension = False @@ -1665,7 +1648,7 @@ def sage_global_ring(self): prec = singular.eval('ringlist(basering)[1][2][1]') br = RealField(ceil((ZZ(prec)+1)/log(2,10))) is_extension = False - elif charstr[0]=='complex': + elif charstr[0] == 'complex': from sage.rings.complex_mpfr import ComplexField from sage.functions.other import ceil from sage.misc.functional import log @@ -1695,7 +1678,7 @@ def sage_global_ring(self): if is_short != '0': singular.eval('short=0') minpoly = ZZ[charstr[1]](singular.eval('minpoly')) - singular.eval('short=%s'%is_short) + singular.eval('short=%s' % is_short) else: minpoly = ZZ[charstr[1]](minpoly) BR = br.extension(minpoly,names=charstr[1]) @@ -1709,7 +1692,7 @@ def sage_global_ring(self): # Meanwhile Singulars quotient rings are also of 'ring' type, not 'qring' as it was in the past. # To find out if a singular ring is a quotient ring or not checking for ring type does not help # and instead of that we check if the quotient ring is zero or not: - if (singular.eval('ideal(basering)==0')=='1'): + if (singular.eval('ideal(basering)==0') == '1'): return PolynomialRing(BR, names=singular.eval('varstr(basering)'), order=termorder_from_singular(singular)) P = PolynomialRing(BR, names=singular.eval('varstr(basering)'), order=termorder_from_singular(singular)) return P.quotient(singular('ringlist(basering)[4]')._sage_(P), names=singular.eval('varstr(basering)')) @@ -1839,15 +1822,15 @@ def sage_poly(self, R=None, kcache=None): # as we know what to expect. is_short = self.parent().eval('short') - if is_short!='0': + if is_short != '0': self.parent().eval('short=0') if isinstance(R, MPolynomialRing_libsingular): out = R(self) - self.parent().eval('short=%s'%is_short) + self.parent().eval('short=%s' % is_short) return out singular_poly_list = self.parent().eval("string(coef(%s,%s))" % ( self.name(),variable_str)).split(",") - self.parent().eval('short=%s'%is_short) + self.parent().eval('short=%s' % is_short) else: if isinstance(R, MPolynomialRing_libsingular): return R(self) @@ -1881,19 +1864,19 @@ def sage_poly(self, R=None, kcache=None): variables = [var.split("^") for var in monomial.split("*") ] for e in variables: var = e[0] - if len(e)==int(2): + if len(e) == int(2): power = int(e[1]) else: - power=1 - exp[var_dict[var]]=power + power = 1 + exp[var_dict[var]] = power if kcache is None: - sage_repr[ETuple(exp,ngens)]=k(singular_poly_list[coeff_start+i]) + sage_repr[ETuple(exp,ngens)] = k(singular_poly_list[coeff_start+i]) else: elem = singular_poly_list[coeff_start+i] if elem not in kcache: kcache[elem] = k( elem ) - sage_repr[ETuple(exp,ngens)]= kcache[elem] + sage_repr[ETuple(exp,ngens)] = kcache[elem] return R(sage_repr) @@ -1907,7 +1890,7 @@ def sage_poly(self, R=None, kcache=None): if monomial not in ['1', '(1.000e+00)']: term = monomial.split("^") - if len(term)==int(2): + if len(term) == int(2): exp = int(term[1]) else: exp = int(1) @@ -1918,7 +1901,7 @@ def sage_poly(self, R=None, kcache=None): elem = singular_poly_list[coeff_start+i] if elem not in kcache: kcache[elem] = k( elem ) - sage_repr[ exp ]= kcache[elem] + sage_repr[ exp ] = kcache[elem] return R(sage_repr) @@ -1958,14 +1941,14 @@ def sage_matrix(self, R, sparse=True): #this is slow for x in range(nrows): for y in range(ncols): - A[x,y]=self[x+1,y+1].sage_poly(R) + A[x,y] = self[x+1,y+1].sage_poly(R) return A A = Matrix(R, nrows, ncols, sparse=sparse) #this is slow for x in range(nrows): for y in range(ncols): - A[x,y]=R(self[x+1,y+1]) + A[x,y] = R(self[x+1,y+1]) return A @@ -2044,9 +2027,9 @@ def _sage_(self, R=None): """ typ = self.type() - if typ=='poly': + if typ == 'poly': return self.sage_poly(R) - elif typ=='int': + elif typ == 'int': return sage.rings.integer.Integer(repr(self)) elif typ == 'module': return self.sage_matrix(R,sparse=True) @@ -2166,7 +2149,7 @@ def sage_structured_str_list(self): sage: RL.sage_structured_str_list() ['0', ['x', 'y'], [['dp', '1,\n1'], ['C', '0']], '0'] """ - if not (self.type()=='list'): + if not (self.type() == 'list'): return str(self) return [X.sage_structured_str_list() for X in self] @@ -2435,10 +2418,10 @@ def get_docstring(name): except KeyError: return "" -################################## singular = Singular() + def reduce_load_Singular(): """ EXAMPLES:: diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index 6dd359d9e36..6053d2519e4 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -891,4 +891,5 @@ def help(self, use_pager=True): """ deprecation(34066, "type 'sage.interfaces.tachyon?' for help") + tachyon_rt = TachyonRT() diff --git a/src/sage/interfaces/tests.py b/src/sage/interfaces/tests.py index 559855d9f85..8c760c2a2c0 100644 --- a/src/sage/interfaces/tests.py +++ b/src/sage/interfaces/tests.py @@ -51,14 +51,14 @@ def manyvars(s, num=70000, inlen=1, step=2000): Test that > 65,000 variable names works in each system. """ print("Testing -- %s" % s) - t = '"%s"'%('9'*int(inlen)) + t = '"%s"' % ('9'*int(inlen)) try: t = cputime() w = walltime() v = [] for i in range(num): - if i%step==0: - sys.stdout.write('%s '%i) + if i % step == 0: + sys.stdout.write('%s ' % i) sys.stdout.flush() v.append(s(t)) print('\nsuccess -- time = cpu: %s, wall: %s' % (cputime(t), diff --git a/src/sage/interfaces/tides.py b/src/sage/interfaces/tides.py index bb48e4a2fd8..765b8bd3cb4 100644 --- a/src/sage/interfaces/tides.py +++ b/src/sage/interfaces/tides.py @@ -156,9 +156,9 @@ def subexpressions_list(f, pars=None): F = symbolic_expression([i(*variables) for i in f]).function(*varpar) lis = flatten([fast_callable(i,vars=varpar).op_list() for i in F], max_level=1) stack = [] - const =[] - stackcomp=[] - detail=[] + const = [] + stackcomp = [] + detail = [] for i in lis: if i[0] == 'load_arg': stack.append(varpar[i[1]]) @@ -166,76 +166,76 @@ def subexpressions_list(f, pars=None): if i[1] in NN: basis = stack[-1] for j in range(i[1]-1): - a=stack.pop(-1) + a = stack.pop(-1) detail.append(('mul', a, basis)) stack.append(a*basis) stackcomp.append(stack[-1]) else: detail.append(('pow',stack[-1],i[1])) - stack[-1]=stack[-1]**i[1] + stack[-1] = stack[-1]**i[1] stackcomp.append(stack[-1]) elif i[0] == 'load_const': const.append(i[1]) stack.append(i[1]) elif i == 'mul': - a=stack.pop(-1) - b=stack.pop(-1) + a = stack.pop(-1) + b = stack.pop(-1) detail.append(('mul', a, b)) stack.append(a*b) stackcomp.append(stack[-1]) elif i == 'div': - a=stack.pop(-1) - b=stack.pop(-1) + a = stack.pop(-1) + b = stack.pop(-1) detail.append(('div', a, b)) stack.append(b/a) stackcomp.append(stack[-1]) elif i == 'add': - a=stack.pop(-1) - b=stack.pop(-1) + a = stack.pop(-1) + b = stack.pop(-1) detail.append(('add',a,b)) stack.append(a+b) stackcomp.append(stack[-1]) elif i == 'pow': - a=stack.pop(-1) - b=stack.pop(-1) + a = stack.pop(-1) + b = stack.pop(-1) detail.append(('pow', b, a)) stack.append(b**a) stackcomp.append(stack[-1]) - elif i[0] == 'py_call' and str(i[1])=='log': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'log': + a = stack.pop(-1) detail.append(('log', a)) stack.append(log(a)) stackcomp.append(stack[-1]) - elif i[0] == 'py_call' and str(i[1])=='exp': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'exp': + a = stack.pop(-1) detail.append(('exp', a)) stack.append(exp(a)) stackcomp.append(stack[-1]) - elif i[0] == 'py_call' and str(i[1])=='sin': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'sin': + a = stack.pop(-1) detail.append(('sin', a)) detail.append(('cos', a)) stackcomp.append(sin(a)) stackcomp.append(cos(a)) stack.append(sin(a)) - elif i[0] == 'py_call' and str(i[1])=='cos': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'cos': + a = stack.pop(-1) detail.append(('sin', a)) detail.append(('cos', a)) stackcomp.append(sin(a)) stackcomp.append(cos(a)) stack.append(cos(a)) - elif i[0] == 'py_call' and str(i[1])=='tan': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'tan': + a = stack.pop(-1) b = sin(a) c = cos(a) detail.append(('sin', a)) @@ -246,8 +246,8 @@ def subexpressions_list(f, pars=None): stackcomp.append(b/c) stack.append(b/c) - elif i[0] == 'py_call' and str(i[1])=='arctan': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'arctan': + a = stack.pop(-1) detail.append(('mul', a, a)) detail.append(('add', 1, a*a)) detail.append(('atan', a)) @@ -256,12 +256,12 @@ def subexpressions_list(f, pars=None): stackcomp.append(arctan(a)) stack.append(arctan(a)) - elif i[0] == 'py_call' and str(i[1])=='arcsin': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'arcsin': + a = stack.pop(-1) detail.append(('mul', a, a)) detail.append(('mul', -1, a*a)) detail.append(('add', 1, -a*a)) - detail.append(('pow', 1- a*a, 0.5)) + detail.append(('pow', 1 - a*a, 0.5)) detail.append(('asin', a)) stackcomp.append(a*a) stackcomp.append(-a*a) @@ -270,12 +270,12 @@ def subexpressions_list(f, pars=None): stackcomp.append(arcsin(a)) stack.append(arcsin(a)) - elif i[0] == 'py_call' and str(i[1])=='arccos': - a=stack.pop(-1) + elif i[0] == 'py_call' and str(i[1]) == 'arccos': + a = stack.pop(-1) detail.append(('mul', a, a)) detail.append(('mul', -1, a*a)) detail.append(('add', 1, -a*a)) - detail.append(('pow', 1- a*a, 0.5)) + detail.append(('pow', 1 - a*a, 0.5)) detail.append(('mul', -1, sqrt(1-a*a))) detail.append(('acos', a)) stackcomp.append(a*a) @@ -287,7 +287,7 @@ def subexpressions_list(f, pars=None): stack.append(arccos(a)) elif i[0] == 'py_call' and 'sqrt' in str(i[1]): - a=stack.pop(-1) + a = stack.pop(-1) detail.append(('pow', a, 0.5)) stackcomp.append(sqrt(a)) stack.append(sqrt(a)) @@ -334,13 +334,13 @@ def remove_repeated(l1, l2): """ for i in range(len(l1)-1): - j=i+1 - while j sage: a - + sage: ecl_eval("(setf *read-default-float-format* 'double-float)") sage: a - + Tuples are translated to dotted lists:: diff --git a/src/sage/libs/eclib/constructor.py b/src/sage/libs/eclib/constructor.py index 19c39739b02..d8881077a75 100644 --- a/src/sage/libs/eclib/constructor.py +++ b/src/sage/libs/eclib/constructor.py @@ -44,7 +44,7 @@ def CremonaModularSymbols(level, sign=0, cuspidal=False, verbose=0): sage: M Cremona Modular Symbols space of dimension 7 for Gamma_0(43) of weight 2 with sign 0 - The input must be valid or a ValueError is raised:: + The input must be valid or a :class:`ValueError` is raised:: sage: M = CremonaModularSymbols(-1) Traceback (most recent call last): diff --git a/src/sage/libs/eclsig.h b/src/sage/libs/eclsig.h index e249ccf6874..005b2d99d0b 100644 --- a/src/sage/libs/eclsig.h +++ b/src/sage/libs/eclsig.h @@ -45,7 +45,11 @@ static inline void ecl_sig_off(void) sig_off(); } +#if ECL_VERSION_NUMBER < 230909 #define ecl_mpz_from_bignum(obj) ((obj)->big.big_num) +#else +#define ecl_mpz_from_bignum(obj) ecl_bignum(obj) +#endif cl_object ecl_bignum_from_mpz(mpz_t num) { diff --git a/src/sage/libs/flint/fmpz_poly.pyx b/src/sage/libs/flint/fmpz_poly.pyx index 8811ccf3a51..74915b37612 100644 --- a/src/sage/libs/flint/fmpz_poly.pyx +++ b/src/sage/libs/flint/fmpz_poly.pyx @@ -27,7 +27,7 @@ from sage.arith.long cimport pyobject_to_long from sage.cpython.string cimport char_to_str, str_to_bytes from sage.structure.sage_object cimport SageObject from sage.rings.integer cimport Integer -from sage.libs.flint.fmpz_poly cimport * + cdef class Fmpz_poly(SageObject): diff --git a/src/sage/libs/flint/qsieve.pyx b/src/sage/libs/flint/qsieve.pyx index 780d6f5c150..7d93d41f4cc 100644 --- a/src/sage/libs/flint/qsieve.pyx +++ b/src/sage/libs/flint/qsieve.pyx @@ -7,7 +7,6 @@ been absorbed into flint. from cysignals.signals cimport sig_on, sig_off from sage.libs.flint.fmpz cimport fmpz_t, fmpz_init, fmpz_set_mpz from sage.libs.flint.fmpz_factor cimport * -from sage.libs.flint.qsieve cimport * from sage.rings.integer cimport Integer diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index 1dc53c81f67..478caf9f9d0 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -720,7 +720,7 @@ cdef class GapElement(RingElement): ... AttributeError: 'some_name' does not define a GAP function """ - if name in ('__dict__', '_getAttributeNames', '__custom_name', 'keys'): + if name in ('__dict__', '_getAttributeNames', '_SageObject__custom_name', 'keys'): raise AttributeError('Python special name, not a GAP function.') try: proxy = make_GapElement_MethodProxy\ diff --git a/src/sage/libs/gap/gap_includes.pxd b/src/sage/libs/gap/gap_includes.pxd index 840b8a0042e..1ed4378a6c7 100644 --- a/src/sage/libs/gap/gap_includes.pxd +++ b/src/sage/libs/gap/gap_includes.pxd @@ -144,3 +144,18 @@ cdef extern from "gap/stringobj.h" nogil: bint IS_STRING(Obj obj) bint IsStringConv(Obj obj) Obj NEW_STRING(Int) + + +cdef extern from "" nogil: + """ + /* Hack: Cython 3.0 automatically includes , which + * defines several macros that collides with enum definitions in + * gap/objects.h. We need to include the header explicitly and + * undefine these macros. + */ + #undef T_INT + #undef T_STRING + #undef T_CHAR + #undef T_BOOL + """ + pass diff --git a/src/sage/libs/giac/giac.pyx b/src/sage/libs/giac/giac.pyx index a78e2199725..c5f738eadc0 100644 --- a/src/sage/libs/giac/giac.pyx +++ b/src/sage/libs/giac/giac.pyx @@ -1266,11 +1266,10 @@ cdef class Pygen(GiacMethods_base): GIAC_archive( encstring23(filename), (self).gptr[0], context_ptr) sig_off() - - # NB: with giac <= 1.2.3-57 redim doesn't have a non evaluated for so Pygen('redim') fails. # hence replacement for redim: - def redim(self,a,b=None): + + def redim(self, a, b=None): """ Increase the size of a matrix when possible, otherwise return self. @@ -1677,11 +1676,11 @@ cdef class Pygen(GiacMethods_base): xyplot=[[(u.real())._double,(u.im())._double] for u in l] - if (xyscat != []): - result=scatter_plot(xyscat) + if xyscat: + result = scatter_plot(xyscat) else: - result=line(xyplot) + result = line(xyplot) sig_off() return result @@ -1695,11 +1694,11 @@ cdef class Pygen(GiacMethods_base): # # # # # # # # # # # # # # # # # # # # # # # # # # - def __richcmp__( self, other,op): + def __richcmp__(self, other, op): if not isinstance(other, Pygen): - other=Pygen(other) + other = Pygen(other) if not isinstance(self, Pygen): - self=Pygen(self) + self = Pygen(self) sig_on() result= giacgenrichcmp((self).gptr[0],(other).gptr[0], op, context_ptr ) sig_off() @@ -1708,10 +1707,11 @@ cdef class Pygen(GiacMethods_base): # # Some attributes of the gen class: # + property _type: def __get__(self): sig_on() - result=self.gptr.type + result = self.gptr.type sig_off() return result @@ -1723,30 +1723,27 @@ cdef class Pygen(GiacMethods_base): sig_off() return result - - property _val: # immediate int (type _INT_) """ immediate int value of an _INT_ type gen. """ def __get__(self): - if(self._type == 0): + if self._type == 0: sig_on() - result=self.gptr.val + result = self.gptr.val sig_off() return result else: raise TypeError("cannot convert non _INT_ giac gen") - property _double: # immediate double (type _DOUBLE_) """ immediate conversion to float for a gen of _DOUBLE_ type. """ def __get__(self): - if(self._type == 1): + if self._type == 1: sig_on() - result=self.gptr._DOUBLE_val + result = self.gptr._DOUBLE_val sig_off() return result else: @@ -1756,8 +1753,6 @@ cdef class Pygen(GiacMethods_base): def __get__(self): return self._help() - - ################################################### # Add the others methods ################################################### @@ -1767,30 +1762,22 @@ cdef class Pygen(GiacMethods_base): # # def __getattr__(self, name): # return GiacMethods[str(name)](self) - ## + # test - #test def giacAiry_Ai(self, *args): - cdef gen result=GIAC_Airy_Ai(self.gptr[0], context_ptr) + cdef gen result = GIAC_Airy_Ai(self.gptr[0], context_ptr) return _wrap_gen(result) def giacifactor(self, *args): cdef gen result sig_on() - result=GIAC_eval(self.gptr[0], 1, context_ptr) - result=GIAC_ifactor(result, context_ptr) + result = GIAC_eval(self.gptr[0], 1, context_ptr) + result = GIAC_ifactor(result, context_ptr) sig_off() return _wrap_gen(result) - - - - - - -## ################################################################ # A wrapper from a cpp element of type giac gen to create # # the Python object # diff --git a/src/sage/libs/gmp/pylong.pyx b/src/sage/libs/gmp/pylong.pyx index 2f7ed35be9d..d5993cca5a5 100644 --- a/src/sage/libs/gmp/pylong.pyx +++ b/src/sage/libs/gmp/pylong.pyx @@ -26,7 +26,6 @@ AUTHORS: from cpython.object cimport Py_SIZE -from cpython.int cimport PyInt_FromLong from cpython.long cimport PyLong_FromLong from cpython.longintrepr cimport _PyLong_New, py_long, digit, PyLong_SHIFT from .mpz cimport * @@ -85,7 +84,7 @@ cdef mpz_get_pyintlong(mpz_srcptr z): if the value is too large. """ if mpz_fits_slong_p(z): - return PyInt_FromLong(mpz_get_si(z)) + return PyLong_FromLong(mpz_get_si(z)) return mpz_get_pylong_large(z) diff --git a/src/sage/libs/lcalc/lcalc_Lfunction.pxd b/src/sage/libs/lcalc/lcalc_Lfunction.pxd index 5edf0844f3e..1d595180a6f 100644 --- a/src/sage/libs/lcalc/lcalc_Lfunction.pxd +++ b/src/sage/libs/lcalc/lcalc_Lfunction.pxd @@ -99,19 +99,19 @@ cdef extern from "lcalc_sage.h": ################ # strange bug, I can't compile without this trick ??? -# it's only used in __typedN +# it's only used in _typedN ctypedef double Double cdef class Lfunction: cdef void *thisptr - cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r) - cdef c_Complex __value(self,c_Complex s,int derivative) - cdef c_Complex __hardy_z_function(self,c_Complex s) - cdef int __compute_rank(self) + cdef void _init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r) + cdef c_Complex _value(self,c_Complex s,int derivative) + cdef c_Complex _hardy_z_function(self,c_Complex s) + cdef int _compute_rank(self) #strange bug, replacing Double with double gives me a compile error - cdef Double __typedN(self, double T) - cdef void __find_zeros_v(self, double T1, double T2, double stepsize,doublevec *result) - cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) + cdef Double _typedN(self, double T) + cdef void _find_zeros_v(self, double T1, double T2, double stepsize,doublevec *result) + cdef int _find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec* result) cdef str _repr diff --git a/src/sage/libs/lcalc/lcalc_Lfunction.pyx b/src/sage/libs/lcalc/lcalc_Lfunction.pyx index 6e9005c502b..7b871ed049f 100644 --- a/src/sage/libs/lcalc/lcalc_Lfunction.pyx +++ b/src/sage/libs/lcalc/lcalc_Lfunction.pyx @@ -99,7 +99,7 @@ cdef class Lfunction: tmpc=CCC(residue[i]) r[i+1] = new_Complex(mpfr_get_d(tmpc.__re, MPFR_RNDN), mpfr_get_d(tmpc.__im, MPFR_RNDN)) - self.__init_fun(NAME, what_type, dirichlet_coefficient, Period, q, w, A, g, l, n_poles, p, r) + self._init_fun(NAME, what_type, dirichlet_coefficient, Period, q, w, A, g, l, n_poles, p, r) if name: name += ': ' @@ -180,7 +180,7 @@ cdef class Lfunction: """ cdef ComplexNumber complexified_s = CCC(s) cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re, MPFR_RNDN), mpfr_get_d(complexified_s.__im, MPFR_RNDN)) - cdef c_Complex result = self.__value(z, derivative) + cdef c_Complex result = self._value(z, derivative) return CCC(result.real(),result.imag()) def hardy_z_function(self, s): @@ -223,7 +223,7 @@ cdef class Lfunction: #This takes s -> .5 + I*s cdef ComplexNumber complexified_s = CCC(0.5)+ CCC(0,1)*CCC(s) cdef c_Complex z = new_Complex(mpfr_get_d(complexified_s.__re, MPFR_RNDN), mpfr_get_d(complexified_s.__im, MPFR_RNDN)) - cdef c_Complex result = self.__hardy_z_function(z) + cdef c_Complex result = self._hardy_z_function(z) return CCC(result.real(),result.imag()) @@ -249,9 +249,9 @@ cdef class Lfunction: 3 """ - return self.__compute_rank() + return self._compute_rank() - def __N(self, T): + def _N(self, T): """ Compute the number of zeroes upto height `T` using the formula for `N(T)` with the error of `S(T)`. Please do not use this. It is only @@ -262,12 +262,12 @@ cdef class Lfunction: sage: from sage.libs.lcalc.lcalc_Lfunction import * sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="complex") - sage: L.__N(10) # abs tol 1e-8 + sage: L._N(10) # abs tol 1e-8 4.0 """ cdef RealNumber real_T=RRR(T) cdef double double_T = mpfr_get_d(real_T.value, MPFR_RNDN) - cdef double res_d = self.__typedN(double_T) + cdef double res_d = self._typedN(double_T) return RRR(res_d) def find_zeros(self, T1, T2, stepsize): @@ -323,7 +323,7 @@ cdef class Lfunction: cdef RealNumber real_T2 = RRR(T2) cdef RealNumber real_stepsize = RRR(stepsize) sig_on() - self.__find_zeros_v( mpfr_get_d(real_T1.value, MPFR_RNDN), mpfr_get_d(real_T2.value, MPFR_RNDN), mpfr_get_d(real_stepsize.value, MPFR_RNDN),&result) + self._find_zeros_v( mpfr_get_d(real_T1.value, MPFR_RNDN), mpfr_get_d(real_T2.value, MPFR_RNDN), mpfr_get_d(real_stepsize.value, MPFR_RNDN),&result) sig_off() i=result.size() returnvalue = [] @@ -399,7 +399,7 @@ cdef class Lfunction: cdef const char* message_stamp = "" cdef doublevec result sig_on() - self.__find_zeros(count, start, max_refine, rank, message_stamp, &result) + self._find_zeros(count, start, max_refine, rank, message_stamp, &result) sig_off() returnvalue = [] for i in range(result.size()): @@ -408,25 +408,25 @@ cdef class Lfunction: return returnvalue # Needs to be overriden - cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): + cdef void _init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): raise NotImplementedError - cdef c_Complex __value(self,c_Complex s,int derivative): + cdef c_Complex _value(self,c_Complex s,int derivative): raise NotImplementedError - cdef c_Complex __hardy_z_function(self,c_Complex s): + cdef c_Complex _hardy_z_function(self,c_Complex s): raise NotImplementedError - cdef int __compute_rank(self): + cdef int _compute_rank(self): raise NotImplementedError - cdef double __typedN(self,double T): + cdef double _typedN(self,double T): raise NotImplementedError - cdef void __find_zeros_v(self,double T1, double T2, double stepsize, doublevec *result): + cdef void _find_zeros_v(self,double T1, double T2, double stepsize, doublevec *result): raise NotImplementedError - cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + cdef int _find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): raise NotImplementedError ############################################################################## @@ -497,7 +497,7 @@ cdef class Lfunction_I(Lfunction): self._repr += " with integer Dirichlet coefficients" # override - cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): + cdef void _init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): cdef int N = len(dirichlet_coeff) cdef Integer tmpi cdef int * coeffs = new_ints(N+1) #lcalc ignores 0the coefficient @@ -507,22 +507,22 @@ cdef class Lfunction_I(Lfunction): self.thisptr=new_c_Lfunction_I(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r) del_ints(coeffs) - cdef inline c_Complex __value(self,c_Complex s,int derivative): + cdef inline c_Complex _value(self,c_Complex s,int derivative): return ((self.thisptr)).value(s, derivative, "pure") - cdef inline c_Complex __hardy_z_function(self,c_Complex s): + cdef inline c_Complex _hardy_z_function(self,c_Complex s): return ((self.thisptr)).value(s, 0, "rotated pure") - cdef int __compute_rank(self): + cdef int _compute_rank(self): return ((self.thisptr)).compute_rank() - cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): + cdef void _find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): (self.thisptr).find_zeros_v(T1,T2,stepsize,result[0]) - cdef double __typedN(self, double T): + cdef double _typedN(self, double T): return (self.thisptr).N(T) - cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + cdef int _find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) # debug tools @@ -633,7 +633,7 @@ cdef class Lfunction_D(Lfunction): self._repr += " with real Dirichlet coefficients" # override - cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): + cdef void _init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): cdef int i cdef RealNumber tmpr cdef int N = len(dirichlet_coeff) @@ -644,23 +644,23 @@ cdef class Lfunction_D(Lfunction): self.thisptr=new_c_Lfunction_D(NAME, what_type, N, coeffs, Period, q, w, A, g, l, n_poles, p, r) del_doubles(coeffs) - cdef inline c_Complex __value(self,c_Complex s,int derivative): + cdef inline c_Complex _value(self,c_Complex s,int derivative): return ((self.thisptr)).value(s, derivative, "pure") - cdef inline c_Complex __hardy_z_function(self,c_Complex s): + cdef inline c_Complex _hardy_z_function(self,c_Complex s): return ((self.thisptr)).value(s, 0, "rotated pure") - cdef inline int __compute_rank(self): + cdef inline int _compute_rank(self): return ((self.thisptr)).compute_rank() - cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): + cdef void _find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): (self.thisptr).find_zeros_v(T1,T2,stepsize,result[0]) - cdef double __typedN(self, double T): + cdef double _typedN(self, double T): return (self.thisptr).N(T) - cdef int __find_zeros(self, long count, long start,double max_refine, int rank, const char* message_stamp, doublevec *result): + cdef int _find_zeros(self, long count, long start,double max_refine, int rank, const char* message_stamp, doublevec *result): (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) # debug tools @@ -773,7 +773,7 @@ cdef class Lfunction_C: self._repr += " with complex Dirichlet coefficients" # override - cdef void __init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): + cdef void _init_fun(self, char *NAME, int what_type, dirichlet_coeff, long long Period, double q, c_Complex w, int A, double *g, c_Complex *l, int n_poles, c_Complex *p, c_Complex *r): cdef int i cdef int N = len(dirichlet_coeff) cdef ComplexNumber tmpc @@ -788,24 +788,24 @@ cdef class Lfunction_C: del_Complexes(coeffs) - cdef inline c_Complex __value(self,c_Complex s,int derivative): + cdef inline c_Complex _value(self,c_Complex s,int derivative): return ((self.thisptr)).value(s, derivative, "pure") - cdef inline c_Complex __hardy_z_function(self,c_Complex s): + cdef inline c_Complex _hardy_z_function(self,c_Complex s): return ((self.thisptr)).value(s, 0,"rotated pure") - cdef inline int __compute_rank(self): + cdef inline int _compute_rank(self): return ((self.thisptr)).compute_rank() - cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): + cdef void _find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): (self.thisptr).find_zeros_v(T1,T2,stepsize,result[0]) - cdef double __typedN(self, double T): + cdef double _typedN(self, double T): return (self.thisptr).N(T) - cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + cdef int _find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) # debug tools @@ -873,24 +873,24 @@ cdef class Lfunction_Zeta(Lfunction): self.thisptr = new_c_Lfunction_Zeta() self._repr = "The Riemann zeta function" - cdef inline c_Complex __value(self,c_Complex s,int derivative): + cdef inline c_Complex _value(self,c_Complex s,int derivative): return ((self.thisptr)).value(s, derivative, "pure") - cdef inline c_Complex __hardy_z_function(self,c_Complex s): + cdef inline c_Complex _hardy_z_function(self,c_Complex s): return ((self.thisptr)).value(s, 0, "rotated pure") - cdef inline int __compute_rank(self): + cdef inline int _compute_rank(self): return ((self.thisptr)).compute_rank() - cdef void __find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): + cdef void _find_zeros_v(self, double T1, double T2, double stepsize, doublevec *result): (self.thisptr).find_zeros_v(T1,T2,stepsize,result[0]) - cdef double __typedN(self, double T): + cdef double _typedN(self, double T): return (self.thisptr).N(T) - cdef int __find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): + cdef int _find_zeros(self, long count, long start, double max_refine, int rank, const char* message_stamp, doublevec *result): (self.thisptr).find_zeros(count, start, max_refine, rank, message_stamp, result) def __dealloc__(self): diff --git a/src/sage/libs/linkages/padics/Polynomial_ram.pxi b/src/sage/libs/linkages/padics/Polynomial_ram.pxi index 1ac51f1211f..e0584ecb8ad 100644 --- a/src/sage/libs/linkages/padics/Polynomial_ram.pxi +++ b/src/sage/libs/linkages/padics/Polynomial_ram.pxi @@ -55,16 +55,16 @@ cdef inline bint creduce(celement out, celement a, long prec, PowComputer_ prime """ cdef celement ared = a % prime_pow.modulus if ared is a and out is not a: - out.__coeffs = ared.__coeffs[:] + out._coeffs = ared._coeffs[:] else: - out.__coeffs = ared.__coeffs + out._coeffs = ared._coeffs cdef long coeff_prec = prec / prime_pow.e + 1 cdef long break_pt = prec % prime_pow.e - for i in range(len(out.__coeffs)): + for i in range(len(out._coeffs)): if i == break_pt: coeff_prec -= 1 - out.__coeffs[i] = out.__coeffs[i].add_bigoh(coeff_prec) - out.__normalize() + out._coeffs[i] = out._coeffs[i].add_bigoh(coeff_prec) + out._normalize() return out == 0 cdef inline bint creduce_small(celement out, celement a, long prec, PowComputer_ prime_pow) except -1: @@ -116,7 +116,7 @@ cdef inline long cvaluation(celement a, long prec, PowComputer_ prime_pow) excep higher. """ - C = a.__coeffs + C = a._coeffs if not C: return prec cdef long ret = maxordp @@ -161,7 +161,7 @@ cdef inline int cshift(celement shifted, celement rem, celement a, long n, long v = cvaluation(a, prec, prime_pow) notrunc = (v >= -n) if notrunc: - rem.__coeffs = [] + rem._coeffs = [] return cshift_notrunc(shifted, a, n, prec, prime_pow, reduce_afterward) if v > 0: b = prime_pow.poly_ring(0) @@ -185,7 +185,7 @@ cdef inline int cshift(celement shifted, celement rem, celement a, long n, long if reduce_afterward: creduce(shifted, a, prec, prime_pow) else: - shifted.__coeffs = a.__coeffs[:] + shifted._coeffs = a._coeffs[:] cdef inline int cshift_notrunc(celement out, celement a, long n, long prec, PowComputer_ prime_pow, bint reduce_afterward) except -1: r""" @@ -236,7 +236,7 @@ cdef inline int cshift_notrunc(celement out, celement a, long n, long prec, PowC if reduce_afterward: creduce(out, a, prec, prime_pow) else: - out.__coeffs = a.__coeffs[:] + out._coeffs = a._coeffs[:] cdef inline int cinvert(celement out, celement a, long prec, PowComputer_ prime_pow) except -1: r""" @@ -253,7 +253,7 @@ cdef inline int cinvert(celement out, celement a, long prec, PowComputer_ prime_ - ``prime_pow`` -- the ``PowComputer`` for the ring """ - out.__coeffs = prime_pow.invert(a, prec).__coeffs + out._coeffs = prime_pow.invert(a, prec)._coeffs creduce(out, out, prec, prime_pow) cdef inline int cdivunit(celement out, celement a, celement b, long prec, PowComputer_ prime_pow) except -1: @@ -335,7 +335,7 @@ cdef inline cexpansion_next(celement value, expansion_mode mode, long curpower, # the following is specific to the ramified over unramified case. modp_rep, term = value[0]._modp_rep(mode == smallest_mode) if term: - value.__coeffs[0] -= modp_rep + value._coeffs[0] -= modp_rep cshift_notrunc(value, value, -1, curpower, prime_pow, False) return term @@ -354,10 +354,10 @@ cdef inline cexpansion_getitem(celement value, long m, PowComputer_ prime_pow): while m >= 0: modp_rep, term = value[0]._modp_rep() if m: - if len(value.__coeffs): - value.__coeffs[0] -= modp_rep + if len(value._coeffs): + value._coeffs[0] -= modp_rep else: - value.__coeffs.append(-modp_rep) + value._coeffs.append(-modp_rep) cshift_notrunc(value, value, -1, 1, prime_pow, False) m -= 1 return term @@ -379,9 +379,9 @@ cdef int cteichmuller(celement out, celement value, long prec, PowComputer_ prim """ if value[0].valuation() > 0: - out.__coeffs = [] + out._coeffs = [] else: - out.__coeffs = [value[0].parent().teichmuller(value[0])] + out._coeffs = [value[0].parent().teichmuller(value[0])] cdef list ccoefficients(celement x, long valshift, long prec, PowComputer_ prime_pow): """ diff --git a/src/sage/libs/linkages/padics/Polynomial_shared.pxi b/src/sage/libs/linkages/padics/Polynomial_shared.pxi index 495dc6b0848..367bbc2f33d 100644 --- a/src/sage/libs/linkages/padics/Polynomial_shared.pxi +++ b/src/sage/libs/linkages/padics/Polynomial_shared.pxi @@ -106,7 +106,7 @@ cdef inline int ccmp(celement a, celement b, long prec, bint reduce_a, bint redu if not (reduce_a or reduce_b): return 0 if a == b else 1 csub(prime_pow.tmp_ccmp_a, a, b, prec, prime_pow) - coeffs = prime_pow.tmp_ccmp_a.__coeffs + coeffs = prime_pow.tmp_ccmp_a._coeffs cdef long i, coeff_prec, break_pt if prime_pow.e == 1: for i in range(prime_pow.tmp_ccmp_a.degree()+1): @@ -186,9 +186,9 @@ cdef inline int cneg(celement out, celement a, long prec, PowComputer_ prime_pow """ cdef celement ma = -a if ma is a: - out.__coeffs = ma.__coeffs[:] + out._coeffs = ma._coeffs[:] else: - out.__coeffs = ma.__coeffs + out._coeffs = ma._coeffs cdef inline int cadd(celement out, celement a, celement b, long prec, PowComputer_ prime_pow) except -1: r""" @@ -211,9 +211,9 @@ cdef inline int cadd(celement out, celement a, celement b, long prec, PowCompute """ cdef celement sm = a + b if sm is a or sm is b: - out.__coeffs = sm.__coeffs[:] + out._coeffs = sm._coeffs[:] else: - out.__coeffs = sm.__coeffs + out._coeffs = sm._coeffs cdef inline int csub(celement out, celement a, celement b, long prec, PowComputer_ prime_pow) except -1: r""" @@ -236,9 +236,9 @@ cdef inline int csub(celement out, celement a, celement b, long prec, PowCompute """ cdef celement df = a - b if df is a or df is b: - out.__coeffs = df.__coeffs[:] + out._coeffs = df._coeffs[:] else: - out.__coeffs = df.__coeffs + out._coeffs = df._coeffs cdef inline int cmul(celement out, celement a, celement b, long prec, PowComputer_ prime_pow) except -1: r""" @@ -261,9 +261,9 @@ cdef inline int cmul(celement out, celement a, celement b, long prec, PowCompute """ cdef celement pd = a*b if pd is a or pd is b: - out.__coeffs = pd.__coeffs[:] + out._coeffs = pd._coeffs[:] else: - out.__coeffs = pd.__coeffs + out._coeffs = pd._coeffs cdef inline int csetone(celement out, PowComputer_ prime_pow) except -1: r""" @@ -276,7 +276,7 @@ cdef inline int csetone(celement out, PowComputer_ prime_pow) except -1: - ``prime_pow`` -- the ``PowComputer`` for the ring """ - out.__coeffs = [prime_pow.base_ring(1)] + out._coeffs = [prime_pow.base_ring(1)] cdef inline int csetzero(celement out, PowComputer_ prime_pow) except -1: r""" @@ -289,7 +289,7 @@ cdef inline int csetzero(celement out, PowComputer_ prime_pow) except -1: - ``prime_pow`` -- the ``PowComputer`` for the ring """ - out.__coeffs = [] + out._coeffs = [] cdef inline bint cisone(celement a, PowComputer_ prime_pow) except -1: r""" @@ -330,7 +330,7 @@ cdef inline int ccopy(celement out, celement a, PowComputer_ prime_pow) except - - ``prime_pow`` -- the ``PowComputer`` for the ring """ - out.__coeffs = a.__coeffs[:] + out._coeffs = a._coeffs[:] cdef inline cpickle(celement a, PowComputer_ prime_pow): r""" @@ -343,7 +343,7 @@ cdef inline cpickle(celement a, PowComputer_ prime_pow): - ``prime_pow`` the ``PowComputer`` for the ring """ - return a.__coeffs + return a._coeffs cdef inline int cunpickle(celement out, x, PowComputer_ prime_pow) except -1: r""" @@ -358,7 +358,7 @@ cdef inline int cunpickle(celement out, x, PowComputer_ prime_pow) except -1: - ``prime_pow`` -- the ``PowComputer`` for the ring """ - out.__coeffs = x + out._coeffs = x cdef inline long chash(celement a, long ordp, long prec, PowComputer_ prime_pow) except -1: r""" @@ -413,9 +413,9 @@ cdef int cconv(celement out, x, long prec, long valshift, PowComputer_ prime_pow else: xx = prime_pow.poly_ring(x) if xx is x: - out.__coeffs = xx.__coeffs[:] + out._coeffs = xx._coeffs[:] else: - out.__coeffs = xx.__coeffs + out._coeffs = xx._coeffs if valshift > 0: cshift_notrunc(out, out, -valshift, prec, prime_pow, True) elif valshift == 0: @@ -458,12 +458,12 @@ cdef inline long cconv_mpz_t(celement out, mpz_t x, long prec, bint absolute, Po mpz_set(n.value, x) if n: - out.__coeffs = [prime_pow.base_ring(n)] + out._coeffs = [prime_pow.base_ring(n)] if not absolute: valuation = cremove(out, out, prec, prime_pow) creduce(out, out, prec, prime_pow) else: - out.__coeffs = [] + out._coeffs = [] return valuation @@ -492,12 +492,12 @@ cdef inline int cconv_mpz_t_out(mpz_t out, celement x, long valshift, long prec, else: prime_pow.powhelper_cconv_out = x - if len(prime_pow.powhelper_cconv_out.__coeffs) == 0: + if len(prime_pow.powhelper_cconv_out._coeffs) == 0: mpz_set_ui(out, 0) - elif len(prime_pow.powhelper_cconv_out.__coeffs) == 1: + elif len(prime_pow.powhelper_cconv_out._coeffs) == 1: # recursively let the underlying polynomial convert the constant # coefficient to an integer (if possible) - n = ZZ(prime_pow.powhelper_cconv_out.__coeffs[0]) + n = ZZ(prime_pow.powhelper_cconv_out._coeffs[0]) mpz_set(out, n.value) else: raise ValueError("cannot convert to integer") @@ -532,7 +532,7 @@ cdef inline long cconv_mpq_t(celement out, mpq_t x, long prec, bint absolute, Po """ cdef Rational r = PY_NEW(Rational) mpq_set(r.value, x) - out.__coeffs = [prime_pow.base_ring(r)] + out._coeffs = [prime_pow.base_ring(r)] if not absolute: return cremove(out, out, prec, prime_pow) @@ -565,12 +565,12 @@ cdef inline int cconv_mpq_t_out(mpq_t out, celement x, long valshift, long prec, else: prime_pow.powhelper_cconv_out = x - if len(prime_pow.powhelper_cconv_out.__coeffs) == 0: + if len(prime_pow.powhelper_cconv_out._coeffs) == 0: mpq_set_ui(out, 0, 1) - elif len(prime_pow.powhelper_cconv_out.__coeffs) == 1: + elif len(prime_pow.powhelper_cconv_out._coeffs) == 1: # recursively let the underlying polynomial convert the constant # coefficient to a rational (if possible) - c = QQ(prime_pow.powhelper_cconv_out.__coeffs[0]) + c = QQ(prime_pow.powhelper_cconv_out._coeffs[0]) mpq_set(out, c.value) else: raise ValueError("cannot convert to rational") diff --git a/src/sage/libs/mpmath/ext_impl.pyx b/src/sage/libs/mpmath/ext_impl.pyx index 97a9ad39b9e..2d8d2470273 100644 --- a/src/sage/libs/mpmath/ext_impl.pyx +++ b/src/sage/libs/mpmath/ext_impl.pyx @@ -25,7 +25,6 @@ See if :trac:`15118` is fixed:: # http://www.gnu.org/licenses/ #***************************************************************************** -from cpython.int cimport * from cpython.long cimport * from cpython.float cimport * from cpython.complex cimport * diff --git a/src/sage/libs/mpmath/ext_libmp.pyx b/src/sage/libs/mpmath/ext_libmp.pyx index 5216650e9d3..5dccf596a91 100644 --- a/src/sage/libs/mpmath/ext_libmp.pyx +++ b/src/sage/libs/mpmath/ext_libmp.pyx @@ -4,6 +4,7 @@ Faster versions of some key functions in mpmath.libmp from .ext_impl cimport * from sage.libs.gmp.all cimport * +# the next line is used by mpmath from .ext_impl import exp_fixed, cos_sin_fixed, log_int_fixed # Note: not thread-safe @@ -12,6 +13,7 @@ cdef MPF tmp2 MPF_init(&tmp1) MPF_init(&tmp2) + def mpf_add(tuple x, tuple y, int prec=0, str rnd='d'): cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -21,6 +23,7 @@ def mpf_add(tuple x, tuple y, int prec=0, str rnd='d'): MPF_add(&tmp1, &tmp1, &tmp2, opts) return MPF_to_tuple(&tmp1) + def mpf_sub(tuple x, tuple y, int prec=0, str rnd='d'): cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -30,6 +33,7 @@ def mpf_sub(tuple x, tuple y, int prec=0, str rnd='d'): MPF_sub(&tmp1, &tmp1, &tmp2, opts) return MPF_to_tuple(&tmp1) + def mpf_mul(tuple x, tuple y, int prec=0, str rnd='d'): cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -39,6 +43,7 @@ def mpf_mul(tuple x, tuple y, int prec=0, str rnd='d'): MPF_mul(&tmp1, &tmp1, &tmp2, opts) return MPF_to_tuple(&tmp1) + def mpf_div(tuple x, tuple y, int prec, str rnd='d'): cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -48,9 +53,10 @@ def mpf_div(tuple x, tuple y, int prec, str rnd='d'): MPF_div(&tmp1, &tmp1, &tmp2, opts) return MPF_to_tuple(&tmp1) + def mpf_sqrt(tuple x, int prec, str rnd='d'): """ - Computes sqrt(x) with mpf value tuples. + Compute sqrt(x) with mpf value tuples. EXAMPLES:: @@ -59,7 +65,6 @@ def mpf_sqrt(tuple x, int prec, str rnd='d'): sage: y = mpf_sqrt(x, 53, 'n') sage: to_float(y) 1.4142135623730951 - """ if x[0]: import mpmath.libmp as libmp @@ -71,9 +76,10 @@ def mpf_sqrt(tuple x, int prec, str rnd='d'): MPF_sqrt(&tmp1, &tmp1, opts) return MPF_to_tuple(&tmp1) + def mpf_log(tuple x, int prec, str rnd='d'): """ - Computes log(x) with mpf value tuples. + Compute log(x) with mpf value tuples. EXAMPLES:: @@ -82,7 +88,6 @@ def mpf_log(tuple x, int prec, str rnd='d'): sage: y = mpf_log(x, 53, 'n') sage: to_float(y) 0.6931471805599453 - """ if x[0]: import mpmath.libmp as libmp @@ -94,9 +99,10 @@ def mpf_log(tuple x, int prec, str rnd='d'): MPF_log(&tmp1, &tmp1, opts) return MPF_to_tuple(&tmp1) + def mpf_exp(tuple x, int prec, str rnd='d'): """ - Computes exp(x) with mpf value tuples. + Compute exp(x) with mpf value tuples. EXAMPLES:: @@ -105,7 +111,6 @@ def mpf_exp(tuple x, int prec, str rnd='d'): sage: z = mpf_exp(x, 53, 'n') sage: to_float(z) 7.38905609893065 - """ cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -114,9 +119,10 @@ def mpf_exp(tuple x, int prec, str rnd='d'): MPF_exp(&tmp1, &tmp1, opts) return MPF_to_tuple(&tmp1) + def mpf_cos(tuple x, int prec, str rnd='d'): """ - Computes cos(x) with mpf value tuples. + Compute cos(x) with mpf value tuples. EXAMPLES:: @@ -125,7 +131,6 @@ def mpf_cos(tuple x, int prec, str rnd='d'): sage: y = mpf_cos(x, 53, 'n') sage: to_float(y) 0.5403023058681398 - """ cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -134,9 +139,10 @@ def mpf_cos(tuple x, int prec, str rnd='d'): MPF_cos(&tmp1, &tmp1, opts) return MPF_to_tuple(&tmp1) + def mpf_sin(tuple x, int prec, str rnd='d'): """ - Computes sin(x) with mpf value tuples. + Compute sin(x) with mpf value tuples. EXAMPLES:: @@ -145,7 +151,6 @@ def mpf_sin(tuple x, int prec, str rnd='d'): sage: y = mpf_sin(x, 53, 'n') sage: to_float(y) 0.8414709848078965 - """ cdef MPopts opts MPF_set_tuple(&tmp1, x) @@ -154,9 +159,10 @@ def mpf_sin(tuple x, int prec, str rnd='d'): MPF_sin(&tmp1, &tmp1, opts) return MPF_to_tuple(&tmp1) + def mpc_sqrt(tuple z, int prec, str rnd='d'): """ - Computes sqrt(z) with mpc value tuples. + Compute sqrt(z) with mpc value tuples. EXAMPLES:: @@ -176,9 +182,10 @@ def mpc_sqrt(tuple z, int prec, str rnd='d'): MPF_complex_sqrt(&tmp1, &tmp2, &tmp1, &tmp2, opts) return MPF_to_tuple(&tmp1), MPF_to_tuple(&tmp2) + def mpc_exp(tuple z, int prec, str rnd='d'): """ - Computes exp(z) with mpc value tuples. + Compute exp(z) with mpc value tuples. EXAMPLES:: @@ -198,9 +205,10 @@ def mpc_exp(tuple z, int prec, str rnd='d'): MPF_complex_exp(&tmp1, &tmp2, &tmp1, &tmp2, opts) return MPF_to_tuple(&tmp1), MPF_to_tuple(&tmp2) + def mpf_pow(tuple x, tuple y, int prec, str rnd='d'): """ - Computes x ^ y with mpf value tuples. + Compute x ^ y with mpf value tuples. EXAMPLES:: diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 7b907f0d603..845c85234a6 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -14,7 +14,6 @@ context class, and related utilities. # http://www.gnu.org/licenses/ #***************************************************************************** -from cpython.int cimport * from cpython.long cimport * from cpython.float cimport * from cpython.complex cimport * diff --git a/src/sage/libs/ntl/ntl_ZZX.pyx b/src/sage/libs/ntl/ntl_ZZX.pyx index 891a28d0fb1..34fd47a8527 100644 --- a/src/sage/libs/ntl/ntl_ZZX.pyx +++ b/src/sage/libs/ntl/ntl_ZZX.pyx @@ -997,7 +997,7 @@ cdef class ntl_ZZX(): sage: f.trace_list() [5, 0, -6, 0, 10] - The input polynomial must be monic or a ValueError is raised:: + The input polynomial must be monic or a :class:`ValueError` is raised:: sage: f = ntl.ZZX([1,2,0,3,0,2]) sage: f.trace_list() diff --git a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx index 7d2d4bae905..c12df77c2f0 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx @@ -389,8 +389,9 @@ cdef class ntl_ZZ_pEX(): there exist polynomials q, r in ZZ_pE[X] such that a = b*q + r, deg(r) < deg(b). This function returns r. - If p is not prime or the modulus is not irreducible, this function may raise a - RuntimeError due to division by a noninvertible element of ZZ_p. + If p is not prime or the modulus is not irreducible, this + function may raise a :class:`RuntimeError` due to division by + a noninvertible element of ZZ_p. EXAMPLES:: @@ -1078,7 +1079,7 @@ cdef class ntl_ZZ_pEX(): # sage: f.trace_list() # [5, 0, 14, 0, 10] # - # The input polynomial must be monic or a ValueError is raised:: + # The input polynomial must be monic or a :class:`ValueError` is raised:: # # sage: c=ntl.ZZ_pContext(ntl.ZZ(20)) # sage: f = c.ZZ_pX([1,2,0,3,0,2] diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index a8c0666ebc3..4ad48fb3496 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -417,8 +417,8 @@ cdef class ntl_ZZ_pX(): in ZZ_p[X] such that a = b*q + r, deg(r) < deg(b). This function returns r. - If p is not prime this function may raise a RuntimeError due to division by a noninvertible - element of ZZ_p. + If p is not prime this function may raise a :class:`RuntimeError` + due to division by a noninvertible element of ZZ_p. EXAMPLES:: @@ -1236,7 +1236,7 @@ cdef class ntl_ZZ_pX(): sage: f.trace_list() [5, 0, 14, 0, 10] - The input polynomial must be monic or a ValueError is raised:: + The input polynomial must be monic or a :class:`ValueError` is raised:: sage: c = ntl.ZZ_pContext(20) sage: f = ntl.ZZ_pX([1,2,0,3,0,2],c) diff --git a/src/sage/libs/ntl/ntl_lzz_p.pyx b/src/sage/libs/ntl/ntl_lzz_p.pyx index 161d0782bc2..af86b9bcf69 100644 --- a/src/sage/libs/ntl/ntl_lzz_p.pyx +++ b/src/sage/libs/ntl/ntl_lzz_p.pyx @@ -89,19 +89,19 @@ cdef class ntl_zz_p(): #self.c.restore_c() ## This was done in __new__ if isinstance(a, IntegerMod_int): - if (self.c.p == (a).__modulus.int32): ## this is slow + if (self.c.p == (a)._modulus.int32): ## this is slow self.x = (a).ivalue else: raise ValueError("Mismatched modulus for converting to zz_p.") elif isinstance(a, IntegerMod_int64): - if (self.c.p == (a).__modulus.int64): ## this is slow + if (self.c.p == (a)._modulus.int64): ## this is slow self.x = (a).ivalue else: raise ValueError("Mismatched modulus for converting to zz_p.") elif isinstance(a, IntegerMod_gmp): - if (p_sage == (a).__modulus.sageInteger): ## this is slow + if (p_sage == (a)._modulus.sageInteger): ## this is slow self.x = mpz_get_si((a).value) else: raise ValueError("Mismatched modulus for converting to zz_p.") diff --git a/src/sage/libs/ntl/ntl_lzz_pX.pyx b/src/sage/libs/ntl/ntl_lzz_pX.pyx index 24b503a9a62..7d19cc55e37 100644 --- a/src/sage/libs/ntl/ntl_lzz_pX.pyx +++ b/src/sage/libs/ntl/ntl_lzz_pX.pyx @@ -108,17 +108,17 @@ cdef class ntl_zz_pX(): a = ls[i] if isinstance(a, IntegerMod_int): - if (self.c.p == (a).__modulus.int32): ## this is slow + if (self.c.p == (a)._modulus.int32): ## this is slow zz_pX_SetCoeff_long(self.x, i, (a).ivalue) else: raise ValueError("Mismatched modulus for converting to zz_pX.") elif isinstance(a, IntegerMod_int64): - if (self.c.p == (a).__modulus.int64): ## this is slow + if (self.c.p == (a)._modulus.int64): ## this is slow zz_pX_SetCoeff_long(self.x, i, (a).ivalue) else: raise ValueError("Mismatched modulus for converting to zz_pX.") elif isinstance(a, IntegerMod_gmp): - if (p_sage == (a).__modulus.sageInteger): ## this is slow + if (p_sage == (a)._modulus.sageInteger): ## this is slow zz_pX_SetCoeff_long(self.x, i, mpz_get_si((a).value)) else: raise ValueError("Mismatched modulus for converting to zz_pX.") diff --git a/src/sage/libs/pari/__init__.py b/src/sage/libs/pari/__init__.py index ba4c5ad0efd..95b93560892 100644 --- a/src/sage/libs/pari/__init__.py +++ b/src/sage/libs/pari/__init__.py @@ -202,4 +202,5 @@ def _get_pari_instance(): return P + pari = _get_pari_instance() diff --git a/src/sage/libs/singular/function.pyx b/src/sage/libs/singular/function.pyx index f40346d1fd0..c597c63aafe 100644 --- a/src/sage/libs/singular/function.pyx +++ b/src/sage/libs/singular/function.pyx @@ -1241,32 +1241,22 @@ cdef class SingularFunction(SageObject): sage: I = Ideal([x^3*y^2 + 3*x^2*y^2*z + y^3*z^2 + z^5]) sage: I = Ideal(I.groebner_basis()) sage: hilb = sage.libs.singular.function_factory.ff.hilb - sage: hilb(I) # Singular will print // ** _ is no standard basis - // ** _ is no standard basis - // 1 t^0 - // -1 t^5 - - // 1 t^0 - // 1 t^1 - // 1 t^2 - // 1 t^3 - // 1 t^4 - // dimension (proj.) = 1 - // degree (proj.) = 5 + sage: from sage.misc.sage_ostools import redirection + sage: out = tmp_filename() + sage: with redirection(sys.stdout, open(out, 'w')): + ....: hilb(I) # Singular will print // ** _ is no standard basis + sage: with open(out) as f: + ....: 'is no standard basis' in f.read() + True So we tell Singular that ``I`` is indeed a Groebner basis:: - sage: hilb(I,attributes={I:{'isSB':1}}) # no complaint from Singular - // 1 t^0 - // -1 t^5 - - // 1 t^0 - // 1 t^1 - // 1 t^2 - // 1 t^3 - // 1 t^4 - // dimension (proj.) = 1 - // degree (proj.) = 5 + sage: out = tmp_filename() + sage: with redirection(sys.stdout, open(out, 'w')): + ....: hilb(I,attributes={I:{'isSB':1}}) # no complaint from Singular + sage: with open(out) as f: + ....: 'is no standard basis' in f.read() + False TESTS: diff --git a/src/sage/logic/propcalc.py b/src/sage/logic/propcalc.py index 2ff45801bf0..2533cdac702 100644 --- a/src/sage/logic/propcalc.py +++ b/src/sage/logic/propcalc.py @@ -310,5 +310,6 @@ def consistent(*formulas): # if conjunction is a contradiction, the formulas are inconsistent return not conjunction.is_contradiction() + # define function ``valid_consequence`` for backward compatibility valid_consequence = deprecated_function_alias(28052, boolformula.is_consequence) diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py index bb3f6cc42f5..b19177da9e5 100644 --- a/src/sage/manifolds/manifold.py +++ b/src/sage/manifolds/manifold.py @@ -2720,8 +2720,9 @@ def set_simplify_function(self, simplifying_func, method=None): chart.calculus_method().set_simplify_function(simplifying_func, method=method) -############################################################################## -## Constructor function + +########################################################### +# Constructor function _manifold_id = Integer(0) diff --git a/src/sage/manifolds/subsets/pullback.py b/src/sage/manifolds/subsets/pullback.py index 46584303772..b28365601f8 100644 --- a/src/sage/manifolds/subsets/pullback.py +++ b/src/sage/manifolds/subsets/pullback.py @@ -494,7 +494,7 @@ def _coord_def(map, codomain_subset): - ``codomain_subset`` - if ``map`` is a :class:`ScalarField`, an instance of :class:`RealSet`; if ``map`` is a :class:`Chart`, the relative interior of a polyhedron. - For other inputs, a ``NotImplementedError`` will be raised. + For other inputs, a :class:`NotImplementedError` will be raised. OUTPUT: diff --git a/src/sage/manifolds/utilities.py b/src/sage/manifolds/utilities.py index 852dd0be1f1..c66d54e774e 100644 --- a/src/sage/manifolds/utilities.py +++ b/src/sage/manifolds/utilities.py @@ -1357,4 +1357,5 @@ def exterior_derivative(form): """ return form.exterior_derivative() + xder = exterior_derivative diff --git a/src/sage/matrix/action.pyx b/src/sage/matrix/action.pyx index 48bbd1159d6..5c6296a1c35 100644 --- a/src/sage/matrix/action.pyx +++ b/src/sage/matrix/action.pyx @@ -209,23 +209,23 @@ cdef class MatrixMatrixAction(MatrixMulAction): Respects compatible subdivisions:: - sage: M = matrix(5, 5, prime_range(100)) - sage: M.subdivide(2,3); M + sage: M = matrix(5, 5, prime_range(100)) # needs sage.libs.pari + sage: M.subdivide(2, 3); M # needs sage.libs.pari [ 2 3 5| 7 11] [13 17 19|23 29] [--------+-----] [31 37 41|43 47] [53 59 61|67 71] [73 79 83|89 97] - sage: N = matrix(5,2,[n^2 for n in range(10)]) - sage: N.subdivide(3,1); N + sage: N = matrix(5, 2, [n^2 for n in range(10)]) + sage: N.subdivide(3, 1); N [ 0| 1] [ 4| 9] [16|25] [--+--] [36|49] [64|81] - sage: M*N + sage: M*N # needs sage.libs.pari [ 1048| 1388] [ 3056| 4117] [-----+-----] @@ -235,7 +235,7 @@ cdef class MatrixMatrixAction(MatrixMulAction): Note that this is just like block matrix multiplication:: - sage: M.subdivision(0,0) * N.subdivision(0,0) + M.subdivision(0,1) * N.subdivision(1,0) + sage: M.subdivision(0,0) * N.subdivision(0,0) + M.subdivision(0,1) * N.subdivision(1,0) # needs sage.libs.pari [1048] [3056] @@ -249,7 +249,7 @@ cdef class MatrixMatrixAction(MatrixMulAction): [16|25] [36|49] [64|81] - sage: M*N + sage: M*N # needs sage.libs.pari [ 1048 1388] [ 3056 4117] [ 5360 7303] diff --git a/src/sage/matrix/args.pyx b/src/sage/matrix/args.pyx index f52780e8b95..c5a121743a5 100644 --- a/src/sage/matrix/args.pyx +++ b/src/sage/matrix/args.pyx @@ -83,7 +83,7 @@ cdef class SparseEntry: sage: from sage.matrix.args import SparseEntry sage: SparseEntry(123, 456, "abc") SparseEntry(123, 456, 'abc') - sage: SparseEntry(1/3, 2/3, x) + sage: SparseEntry(1/3, 2/3, x) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert rational 1/3 to an integer @@ -176,8 +176,10 @@ cdef class MatrixArgs: [3.141592653589793 0.0] [ 0.0 3.141592653589793] - sage: ma = MatrixArgs(2, 2, entries=pi); ma.finalized(); ma.matrix() - + sage: ma = MatrixArgs(2, 2, entries=pi); ma.finalized() # needs sage.symbolic + + sage: ma.matrix() # needs sage.symbolic [pi 0] [ 0 pi] sage: ma = MatrixArgs(ZZ, 2, 2, entries={(0,0):7}); ma.finalized(); ma.matrix() @@ -192,18 +194,27 @@ cdef class MatrixArgs: [1 2] [3 4] - sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")); ma.finalized(); ma.matrix() - + + sage: # needs sage.libs.pari + sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")); ma.finalized() + + sage: ma.matrix() [1 2] [3 4] - sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("[1,2,3,4]")); ma.finalized(); ma.matrix() - + sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("[1,2,3,4]")); ma.finalized() + + sage: ma.matrix() [1 2] [3 4] - sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("3/5")); ma.finalized(); ma.matrix() - + sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("3/5")); ma.finalized() + + sage: ma.matrix() [3/5 0] [ 0 3/5] + sage: ma = MatrixArgs(entries=matrix(2,2)); ma.finalized(); ma.matrix() @@ -217,26 +228,37 @@ cdef class MatrixArgs: > [1 2] [3 4] + + sage: # needs numpy sage: from numpy import array - sage: ma = MatrixArgs(array([[1,2],[3,4]])); ma.finalized(); ma.matrix() - + sage: ma = MatrixArgs(array([[1,2],[3,4]])); ma.finalized() + + sage: ma.matrix() [1 2] [3 4] - sage: ma = MatrixArgs(array([[1.,2.],[3.,4.]])); ma.finalized(); ma.matrix() - + sage: ma = MatrixArgs(array([[1.,2.],[3.,4.]])); ma.finalized() + + sage: ma.matrix() [1.0 2.0] [3.0 4.0] - sage: ma = MatrixArgs(RealField(20), array([[1.,2.],[3.,4.]])); ma.finalized(); ma.matrix() - + sage: ma = MatrixArgs(RealField(20), array([[1.,2.],[3.,4.]])); ma.finalized() + + sage: ma.matrix() [1.0000 2.0000] [3.0000 4.0000] - sage: ma = MatrixArgs(graphs.CycleGraph(3)); ma.finalized(); ma.matrix() - + + sage: # needs sage.graphs + sage: ma = MatrixArgs(graphs.CycleGraph(3)); ma.finalized() + + sage: ma.matrix() [0 1 1] [1 0 1] [1 1 0] @@ -458,8 +480,8 @@ cdef class MatrixArgs: Sparse examples:: - sage: ma = MatrixArgs(3, 3, pi) - sage: list(ma.iter(sparse=True)) + sage: ma = MatrixArgs(3, 3, pi) # needs sage.symbolic + sage: list(ma.iter(sparse=True)) # needs sage.symbolic [SparseEntry(0, 0, pi), SparseEntry(1, 1, pi), SparseEntry(2, 2, pi)] sage: ma = MatrixArgs(2, 3) sage: list(ma.iter(sparse=True)) @@ -717,7 +739,6 @@ cdef class MatrixArgs: """ self.finalize() - cdef long i cdef list L if self.typ == MA_ENTRIES_SEQ_FLAT and not convert: # Try to re-use existing list @@ -766,7 +787,6 @@ cdef class MatrixArgs: """ self.finalize() - R = self.base cdef dict D = {} for t in self.iter(convert, True): se = t @@ -819,11 +839,11 @@ cdef class MatrixArgs: EXAMPLES:: sage: from sage.matrix.args import MatrixArgs - sage: MatrixArgs(pi).finalized() + sage: MatrixArgs(pi).finalized() # needs sage.symbolic Traceback (most recent call last): ... TypeError: the dimensions of the matrix must be specified - sage: MatrixArgs(RR, pi).finalized() + sage: MatrixArgs(RR, pi).finalized() # needs sage.symbolic Traceback (most recent call last): ... TypeError: the dimensions of the matrix must be specified @@ -1222,6 +1242,7 @@ cdef class MatrixArgs: Check that :trac:`26655` is fixed:: + sage: # needs sage.rings.finite_rings sage: F. = GF(9) sage: M = MatrixSpace(F, 2, 2) sage: A = M([[1, a], [0, 1]]) @@ -1232,11 +1253,11 @@ cdef class MatrixArgs: Constructing a matrix from a PARI ``t_VEC`` or ``t_COL`` with ``t_VEC`` or ``t_COL`` elements is currently not supported:: - sage: M(pari([1, a, 0, 1])) + sage: M(pari([1, a, 0, 1])) # needs sage.libs.pari sage.rings.finite_rings Traceback (most recent call last): ... NameError: name 'a' is not defined - sage: M(pari([[1, a], [0, 1]])) + sage: M(pari([[1, a], [0, 1]])) # needs sage.libs.pari sage.rings.finite_rings Traceback (most recent call last): ... NameError: name 'a' is not defined @@ -1351,7 +1372,7 @@ cpdef MatrixArgs MatrixArgs_init(space, entries): sage: from sage.matrix.args import MatrixArgs_init sage: S = MatrixSpace(GF(2), 2, 4) - sage: ma = MatrixArgs_init(S, {(1,3):7}) + sage: ma = MatrixArgs_init(S, {(1, 3): 7}) sage: M = ma.matrix(); M [0 0 0 0] [0 0 0 1] diff --git a/src/sage/matrix/benchmark.py b/src/sage/matrix/benchmark.py index 51fad23a874..97117632584 100644 --- a/src/sage/matrix/benchmark.py +++ b/src/sage/matrix/benchmark.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.flint """ Benchmarks for matrices @@ -18,13 +19,14 @@ """ from .constructor import random_matrix, Matrix +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.misc.timing import cputime from cysignals.alarm import AlarmInterrupt, alarm, cancel_alarm -from sage.interfaces.magma import magma +lazy_import('sage.interfaces.magma', 'magma') verbose = False diff --git a/src/sage/matrix/berlekamp_massey.py b/src/sage/matrix/berlekamp_massey.py index 716ed428745..a6fe70c50e6 100644 --- a/src/sage/matrix/berlekamp_massey.py +++ b/src/sage/matrix/berlekamp_massey.py @@ -55,11 +55,11 @@ def berlekamp_massey(a): sage: from sage.matrix.berlekamp_massey import berlekamp_massey sage: berlekamp_massey([1,2,1,2,1,2]) x^2 - 1 - sage: berlekamp_massey([GF(7)(1),19,1,19]) + sage: berlekamp_massey([GF(7)(1), 19, 1, 19]) x^2 + 6 sage: berlekamp_massey([2,2,1,2,1,191,393,132]) x^4 - 36727/11711*x^3 + 34213/5019*x^2 + 7024942/35133*x - 335813/1673 - sage: berlekamp_massey(prime_range(2,38)) + sage: berlekamp_massey(prime_range(2, 38)) # needs sage.libs.pari x^6 - 14/9*x^5 - 7/9*x^4 + 157/54*x^3 - 25/27*x^2 - 73/18*x + 37/9 TESTS:: @@ -84,15 +84,11 @@ def berlekamp_massey(a): K = a[0].parent().fraction_field() except AttributeError: K = sage.rings.rational_field.RationalField() - R = K['x'] - x = R.gen() - - f = {-1: R(a), 0: x**(2 * M)} - s = {-1: 1, 0: 0} - j = 0 - while f[j].degree() >= M: - j += 1 - qj, f[j] = f[j - 2].quo_rem(f[j - 1]) - s[j] = s[j - 2] - qj * s[j - 1] - t = s[j].reverse() - return ~(t[t.degree()]) * t # make monic (~ is inverse in python) + + R, x = K['x'].objgen() + f0, f1 = R(a), x**(2 * M) + s0, s1 = 1, 0 + while f1.degree() >= M: + f0, (q, f1) = f1, f0.quo_rem(f1) + s0, s1 = s1, s0 - q * s1 + return s1.reverse().monic() diff --git a/src/sage/matrix/compute_J_ideal.py b/src/sage/matrix/compute_J_ideal.py index 55dcb5e7072..3055f283a78 100644 --- a/src/sage/matrix/compute_J_ideal.py +++ b/src/sage/matrix/compute_J_ideal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.pari (for charpoly, minimal_polynomial in __init__) r""" `J`-ideals of matrices diff --git a/src/sage/matrix/constructor.pyx b/src/sage/matrix/constructor.pyx index ae4652c45f8..a31543e0795 100644 --- a/src/sage/matrix/constructor.pyx +++ b/src/sage/matrix/constructor.pyx @@ -172,9 +172,9 @@ def matrix(*args, **kwds): :: - sage: import numpy - sage: n = numpy.array([[1,2],[3,4]],float) - sage: m = matrix(n); m; m.parent() + sage: import numpy # needs numpy + sage: n = numpy.array([[1,2], [3,4]], float) # needs numpy + sage: m = matrix(n); m; m.parent() # needs numpy [1.0 2.0] [3.0 4.0] Full MatrixSpace of 2 by 2 dense matrices over Real Double Field @@ -196,15 +196,15 @@ def matrix(*args, **kwds): :: - sage: matrix(pari.mathilbert(3)) + sage: matrix(pari.mathilbert(3)) # needs sage.libs.pari [ 1 1/2 1/3] [1/2 1/3 1/4] [1/3 1/4 1/5] :: - sage: g = graphs.PetersenGraph() - sage: m = matrix(g); m; m.parent() + sage: g = graphs.PetersenGraph() # needs sage.graphs + sage: m = matrix(g); m; m.parent() # needs sage.graphs [0 1 0 0 1 1 0 0 0 0] [1 0 1 0 0 0 1 0 0 0] [0 1 0 1 0 0 0 1 0 0] @@ -238,7 +238,8 @@ def matrix(*args, **kwds): sage: M[0] = [9,9,9] Traceback (most recent call last): ... - ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + ValueError: matrix is immutable; please change a copy instead + (i.e., use copy(M) to change a copy of M). TESTS: @@ -456,42 +457,43 @@ def matrix(*args, **kwds): Check conversion from numpy:: + sage: # needs numpy sage: import numpy - sage: n = numpy.array([[complex(0,1),complex(0,2)],[3,4]],complex) + sage: n = numpy.array([[complex(0,1),complex(0,2)], [3,4]], complex) sage: m = matrix(n); m; m.parent() [1.0*I 2.0*I] [ 3.0 4.0] Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field - sage: n = numpy.array([[1,2],[3,4]],'int32') + sage: n = numpy.array([[1,2], [3,4]], 'int32') sage: m = matrix(n); m; m.parent() [1 2] [3 4] Full MatrixSpace of 2 by 2 dense matrices over Integer Ring - sage: n = numpy.array([[1,2,3],[4,5,6],[7,8,9]],'float32') + sage: n = numpy.array([[1,2,3], [4,5,6], [7,8,9]], 'float32') sage: m = matrix(n); m; m.parent() [1.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0] Full MatrixSpace of 3 by 3 dense matrices over Real Double Field - sage: n = numpy.matrix([[1,2,3],[4,5,6],[7,8,9]],'float64') + sage: n = numpy.matrix([[1,2,3], [4,5,6], [7,8,9]], 'float64') sage: m = matrix(n); m; m.parent() [1.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0] Full MatrixSpace of 3 by 3 dense matrices over Real Double Field - sage: n = numpy.array([[1,2,3],[4,5,6],[7,8,9]],'complex64') + sage: n = numpy.array([[1,2,3], [4,5,6], [7,8,9]], 'complex64') sage: m = matrix(n); m; m.parent() [1.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0] Full MatrixSpace of 3 by 3 dense matrices over Complex Double Field - sage: n = numpy.matrix([[1,2,3],[4,5,6],[7,8,9]],'complex128') + sage: n = numpy.matrix([[1,2,3], [4,5,6], [7,8,9]], 'complex128') sage: m = matrix(n); m; m.parent() [1.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0] Full MatrixSpace of 3 by 3 dense matrices over Complex Double Field - sage: a = matrix([[1,2],[3,4]]) + sage: a = matrix([[1,2], [3,4]]) sage: b = matrix(a.numpy()); b [1 2] [3 4] @@ -507,7 +509,8 @@ def matrix(*args, **kwds): A ring and a numpy array:: - sage: n = numpy.array([[1,2,3],[4,5,6],[7,8,9]],'float32') + sage: # needs numpy + sage: n = numpy.array([[1,2,3], [4,5,6], [7,8,9]], 'float32') sage: m = matrix(ZZ, n); m; m.parent() [1 2 3] [4 5 6] @@ -522,11 +525,11 @@ def matrix(*args, **kwds): The dimensions of a matrix may be given as numpy types:: - sage: matrix(numpy.int32(2), numpy.int32(3)) + sage: matrix(numpy.int32(2), numpy.int32(3)) # needs numpy [0 0 0] [0 0 0] - sage: matrix(nrows=numpy.int32(2), ncols=numpy.int32(3)) + sage: matrix(nrows=numpy.int32(2), ncols=numpy.int32(3)) # needs numpy [0 0 0] [0 0 0] @@ -542,7 +545,8 @@ def matrix(*args, **kwds): sage: v = vector(ZZ, [1, 10, 100]) sage: m = matrix(ZZ['x'], v); m; m.parent() [ 1 10 100] - Full MatrixSpace of 1 by 3 dense matrices over Univariate Polynomial Ring in x over Integer Ring + Full MatrixSpace of 1 by 3 dense matrices + over Univariate Polynomial Ring in x over Integer Ring sage: matrix(ZZ, 10, 10, range(100)).parent() Full MatrixSpace of 10 by 10 dense matrices over Integer Ring sage: m = matrix(GF(7), [[1/3,2/3,1/2], [3/4,4/5,7]]); m; m.parent() @@ -576,6 +580,7 @@ def matrix(*args, **kwds): Check :trac:`24459`:: + sage: # needs sage.libs.flint sage: Matrix(ZZ, sys.maxsize, sys.maxsize) Traceback (most recent call last): ... @@ -645,10 +650,13 @@ def matrix(*args, **kwds): M.set_immutable() return M + Matrix = matrix + from .special import * + @matrix_method class options(GlobalOptions): r""" diff --git a/src/sage/matrix/echelon_matrix.pyx b/src/sage/matrix/echelon_matrix.pyx index 3fc43b485ca..7f5457a7f7b 100644 --- a/src/sage/matrix/echelon_matrix.pyx +++ b/src/sage/matrix/echelon_matrix.pyx @@ -48,7 +48,7 @@ def reduced_echelon_matrix_iterator(K, k, n, bint sparse=False, bint copy=True, EXAMPLES:: sage: from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator - sage: it = reduced_echelon_matrix_iterator(GF(2),2,3) + sage: it = reduced_echelon_matrix_iterator(GF(2), 2, 3) sage: for m in it: ....: print(m) ....: print(m.pivots()) @@ -95,12 +95,12 @@ def reduced_echelon_matrix_iterator(K, k, n, bint sparse=False, bint copy=True, Testing options:: - sage: it = reduced_echelon_matrix_iterator(GF(4,'z'), 2, 4, copy=False) - sage: next(it) is next(it) + sage: it = reduced_echelon_matrix_iterator(GF(4, 'z'), 2, 4, copy=False) # needs sage.rings.finite_rings + sage: next(it) is next(it) # needs sage.rings.finite_rings True sage: for a in it: pass - sage: it = reduced_echelon_matrix_iterator(GF(4,'z'), 2, 4, set_immutable=True) + sage: it = reduced_echelon_matrix_iterator(GF(4, 'z'), 2, 4, set_immutable=True) # needs sage.rings.finite_rings sage: all(a.is_immutable() and a.echelon_form() == a for a in it) True """ diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 572936b9c42..cfdc96ec146 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -543,11 +543,11 @@ cdef class Matrix(sage.structure.element.Matrix): TESTS:: - sage: class MyAlgebraicNumber(sage.rings.qqbar.AlgebraicNumber): + sage: class MyAlgebraicNumber(sage.rings.qqbar.AlgebraicNumber): # needs sage.rings.number_fields ....: def __bool__(self): ....: raise ValueError - sage: mat = matrix(1,1,MyAlgebraicNumber(1)) - sage: bool(mat) + sage: mat = matrix(1, 1, MyAlgebraicNumber(1)) # needs sage.rings.number_fields + sage: bool(mat) # needs sage.rings.number_fields Traceback (most recent call last): ... ValueError @@ -581,26 +581,25 @@ cdef class Matrix(sage.structure.element.Matrix): self.set_unsafe(i, j, elt + self.get_unsafe(i, j)) + ## def _get_very_unsafe(self, i, j): + ## r""" + ## Entry access, but potentially fast since it might be without + ## bounds checking. (I know of no cases where this is actually + ## faster.) -## def _get_very_unsafe(self, i, j): -## r""" -## Entry access, but potentially fast since it might be without -## bounds checking. (I know of no cases where this is actually -## faster.) + ## This function it can very easily !! SEG FAULT !! if you call + ## it with invalid input. Use with *extreme* caution. -## This function it can very easily !! SEG FAULT !! if you call -## it with invalid input. Use with *extreme* caution. + ## EXAMPLES:: + ## + ## sage: a = matrix(ZZ,2,range(4)) + ## sage: a._get_very_unsafe(0,1) + ## 1 -## EXAMPLES:: -## -## sage: a = matrix(ZZ,2,range(4)) -## sage: a._get_very_unsafe(0,1) -## 1 - -## If you do \code{a.\_get\_very\_unsafe(0,10)} you'll very likely crash Sage -## completely. -## """ -## return self.get_unsafe(i, j) + ## If you do \code{a.\_get\_very\_unsafe(0,10)} you'll very likely crash Sage + ## completely. + ## """ + ## return self.get_unsafe(i, j) def __iter__(self): """ @@ -907,16 +906,19 @@ cdef class Matrix(sage.structure.element.Matrix): Check that submatrices with a specified implementation have the same implementation:: + sage: # needs sage.libs.pari sage: M = MatrixSpace(GF(2), 3, 3, implementation='generic') sage: m = M(range(9)) sage: type(m) sage: parent(m) - Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 2 (using Matrix_generic_dense) + Full MatrixSpace of 3 by 3 dense matrices + over Finite Field of size 2 (using Matrix_generic_dense) sage: type(m[:2,:2]) sage: parent(m[:2,:2]) - Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 (using Matrix_generic_dense) + Full MatrixSpace of 2 by 2 dense matrices + over Finite Field of size 2 (using Matrix_generic_dense) """ cdef list row_list cdef list col_list @@ -963,7 +965,7 @@ cdef class Matrix(sage.structure.element.Matrix): if ind < 0 or ind >= nrows: raise IndexError("matrix index out of range") elif isinstance(row_index, slice): - row_list = list(xrange(*row_index.indices(nrows))) + row_list = list(range(*row_index.indices(nrows))) else: if not PyIndex_Check(row_index): raise TypeError("index must be an integer") @@ -996,7 +998,7 @@ cdef class Matrix(sage.structure.element.Matrix): if ind < 0 or ind >= ncols: raise IndexError("matrix index out of range") elif isinstance(col_index, slice): - col_list = list(xrange(*col_index.indices(ncols))) + col_list = list(range(*col_index.indices(ncols))) else: if not PyIndex_Check(col_index): raise TypeError("index must be an integer") @@ -1047,7 +1049,7 @@ cdef class Matrix(sage.structure.element.Matrix): raise IndexError("matrix index out of range") r = self.matrix_from_rows(row_list) elif isinstance(row_index, slice): - row_list = list(xrange(*row_index.indices(nrows))) + row_list = list(range(*row_index.indices(nrows))) r = self.matrix_from_rows(row_list) else: if not PyIndex_Check(row_index): @@ -1636,13 +1638,14 @@ cdef class Matrix(sage.structure.element.Matrix): sage: A = Matrix(QQ, 2, 2, [1/2, 1/3, 1/3, 1/4]) sage: A.parent() - Full MatrixSpace of 2 by 2 dense matrices over Rational Field - sage: A.change_ring(GF(25,'a')) + Full MatrixSpace of 2 by 2 dense matrices over Rational Field + sage: A.change_ring(GF(25,'a')) # needs sage.rings.finite_rings [3 2] [2 4] - sage: A.change_ring(GF(25,'a')).parent() - Full MatrixSpace of 2 by 2 dense matrices over Finite Field in a of size 5^2 - sage: A.change_ring(ZZ) + sage: A.change_ring(GF(25,'a')).parent() # needs sage.rings.finite_rings + Full MatrixSpace of 2 by 2 dense matrices + over Finite Field in a of size 5^2 + sage: A.change_ring(ZZ) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: matrix has denominators so can...t change to ZZ @@ -1653,7 +1656,7 @@ cdef class Matrix(sage.structure.element.Matrix): [1/2 1/3] [-------] [1/3 1/4] - sage: A.change_ring(GF(25,'a')) + sage: A.change_ring(GF(25,'a')) # needs sage.rings.finite_rings [3 2] [---] [2 4] @@ -1922,9 +1925,10 @@ cdef class Matrix(sage.structure.element.Matrix): Prior to :trac:`11544` this could take a full minute to run (2011). :: + sage: # needs sage.rings.number_field sage: A = matrix(QQ, 4, 4, [1, 2, -2, 2, 1, 0, -1, -1, 0, -1, 1, 1, -1, 2, 1/2, 0]) sage: e = A.eigenvalues()[3] - sage: K = (A-e).kernel() + sage: K = (A - e).kernel() sage: P = K.basis_matrix() sage: P.str() '[ 1.000000000000000? + 0.?e-17*I -2.116651487479748? + 0.0255565807096352?*I -0.2585224251020429? + 0.2886023409047535?*I -0.4847545623533090? - 1.871890760086142?*I]' @@ -2239,11 +2243,10 @@ cdef class Matrix(sage.structure.element.Matrix): return "\\left" + matrix_delimiters[0] + "\\begin{array}{%s}\n"%format + s + "\n\\end{array}\\right" + matrix_delimiters[1] - - ################################################### ## Basic Properties ################################################### + def ncols(self): """ Return the number of columns of this matrix. @@ -2311,22 +2314,20 @@ cdef class Matrix(sage.structure.element.Matrix): """ return (self._nrows,self._ncols) - ################################################### # Functions ################################################### + def act_on_polynomial(self, f): r""" Return the polynomial f(self\*x). INPUT: - - ``self`` - an nxn matrix - ``f`` - a polynomial in n variables x=(x1,...,xn) - OUTPUT: The polynomial f(self\*x). EXAMPLES:: @@ -2361,17 +2362,18 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: - sage: f(x,y) = x^2+y - sage: m = matrix([[f,f*f],[f^3,f^4]]); m + sage: # needs sage.symbolic + sage: f(x,y) = x^2 + y + sage: m = matrix([[f, f*f], [f^3, f^4]]); m [ (x, y) |--> x^2 + y (x, y) |--> (x^2 + y)^2] [(x, y) |--> (x^2 + y)^3 (x, y) |--> (x^2 + y)^4] - sage: m(1,2) + sage: m(1, 2) [ 3 9] [27 81] - sage: m(y=2,x=1) + sage: m(y=2, x=1) [ 3 9] [27 81] - sage: m(2,1) + sage: m(2, 1) [ 5 25] [125 625] """ @@ -2559,6 +2561,7 @@ cdef class Matrix(sage.structure.element.Matrix): Next of all, create a permutation group element and act on ``M`` with it:: + sage: # needs sage.groups sage: G = PermutationGroup(['(1,2,3)(4,5)', '(1,2,3,4,5)']) sage: sigma, tau = G.gens() sage: sigma @@ -2610,6 +2613,7 @@ cdef class Matrix(sage.structure.element.Matrix): Next of all, create a permutation group element and act on ``M``:: + sage: # needs sage.groups sage: G = PermutationGroup(['(1,2,3)(4,5)', '(1,2,3,4,5)']) sage: sigma, tau = G.gens() sage: sigma @@ -2741,6 +2745,7 @@ cdef class Matrix(sage.structure.element.Matrix): Next of all, create a permutation group element and act on ``M``:: + sage: # needs sage.groups sage: G = PermutationGroup(['(1,2,3)(4,5)', '(1,2,3,4,5)']) sage: sigma, tau = G.gens() sage: sigma @@ -2790,6 +2795,7 @@ cdef class Matrix(sage.structure.element.Matrix): Next of all, create a permutation group element and act on ``M``:: + sage: # needs sage.groups sage: G = PermutationGroup(['(1,2,3)(4,5)', '(1,2,3,4,5)']) sage: sigma, tau = G.gens() sage: sigma @@ -2848,6 +2854,7 @@ cdef class Matrix(sage.structure.element.Matrix): Next of all, create a permutation group element and act on ``M``:: + sage: # needs sage.groups sage: G = PermutationGroup(['(1,2,3)(4,5)', '(1,2,3,4,5)']) sage: sigma, tau = G.gens() sage: sigma @@ -2893,6 +2900,7 @@ cdef class Matrix(sage.structure.element.Matrix): Next of all, create a permutation group element and act on ``M``:: + sage: # needs sage.groups sage: G = PermutationGroup(['(1,2,3)(4,5)', '(1,2,3,4,5)']) sage: sigma, tau = G.gens() sage: sigma @@ -2931,10 +2939,11 @@ cdef class Matrix(sage.structure.element.Matrix): If not, we get an error message:: - sage: a.add_multiple_of_row(1,0,SR.I()) + sage: a.add_multiple_of_row(1, 0, SR.I()) # needs sage.symbolic Traceback (most recent call last): ... - TypeError: Multiplying row by Symbolic Ring element cannot be done over Rational Field, use change_ring or with_added_multiple_of_row instead. + TypeError: Multiplying row by Symbolic Ring element cannot be done over + Rational Field, use change_ring or with_added_multiple_of_row instead. """ self.check_row_bounds_and_mutability(i,j) try: @@ -3015,10 +3024,11 @@ cdef class Matrix(sage.structure.element.Matrix): If not, we get an error message:: - sage: a.add_multiple_of_column(1,0,SR.I()) + sage: a.add_multiple_of_column(1, 0, SR.I()) # needs sage.symbolic Traceback (most recent call last): ... - TypeError: Multiplying column by Symbolic Ring element cannot be done over Rational Field, use change_ring or with_added_multiple_of_column instead. + TypeError: Multiplying column by Symbolic Ring element cannot be done over + Rational Field, use change_ring or with_added_multiple_of_column instead. """ self.check_column_bounds_and_mutability(i,j) try: @@ -3122,7 +3132,8 @@ cdef class Matrix(sage.structure.element.Matrix): sage: a.rescale_row(1,1/2) Traceback (most recent call last): ... - TypeError: Rescaling row by Rational Field element cannot be done over Integer Ring, use change_ring or with_rescaled_row instead. + TypeError: Rescaling row by Rational Field element cannot be done + over Integer Ring, use change_ring or with_rescaled_row instead. To rescale the matrix by 1/2, you must change the base ring to the rationals:: @@ -3236,7 +3247,8 @@ cdef class Matrix(sage.structure.element.Matrix): sage: a.rescale_col(2,1/2) Traceback (most recent call last): ... - TypeError: Rescaling column by Rational Field element cannot be done over Integer Ring, use change_ring or with_rescaled_col instead. + TypeError: Rescaling column by Rational Field element cannot be done + over Integer Ring, use change_ring or with_rescaled_col instead. To rescale the matrix by 1/2, you must change the base ring to the rationals:: @@ -3733,7 +3745,7 @@ cdef class Matrix(sage.structure.element.Matrix): - [FZ2001]_ """ cdef dict d = {} - cdef list queue = list(xrange(self._ncols)) + cdef list queue = list(range(self._ncols)) cdef int l, sign, i, j if skew: @@ -3927,21 +3939,21 @@ cdef class Matrix(sage.structure.element.Matrix): def is_symmetric(self): """ - Return True if this is a symmetric matrix. + Return ``True`` if this is a symmetric matrix. A symmetric matrix is necessarily square. EXAMPLES:: - sage: m=Matrix(QQ,2,range(0,4)) + sage: m = Matrix(QQ, 2, range(0,4)) sage: m.is_symmetric() False - sage: m=Matrix(QQ,2,(1,1,1,1,1,1)) + sage: m = Matrix(QQ, 2, (1,1,1,1,1,1)) sage: m.is_symmetric() False - sage: m=Matrix(QQ,1,(2,)) + sage: m = Matrix(QQ, 1, (2,)) sage: m.is_symmetric() True @@ -3987,6 +3999,7 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 1 + I, 1 - 6*I, -1 - I], ....: [-3 - I, -4*I, -2], ....: [-1 + I, -2 - 8*I, 2 + I]]) @@ -3999,6 +4012,7 @@ cdef class Matrix(sage.structure.element.Matrix): Sage has several fields besides the entire complex numbers where conjugation is non-trivial:: + sage: # needs sage.rings.number_field sage: F. = QuadraticField(-7) sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3], ....: [-2*b - 3, -3*b + 2, -2*b], @@ -4012,19 +4026,20 @@ cdef class Matrix(sage.structure.element.Matrix): A matrix that is nearly Hermitian, but for a non-real diagonal entry:: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 2, 2-I, 1+4*I], ....: [ 2+I, 3+I, 2-6*I], ....: [1-4*I, 2+6*I, 5]]) sage: A._is_hermitian(skew=False, tolerance=0) False - sage: A[1,1] = 132 + sage: A[1, 1] = 132 sage: A._is_hermitian(skew=False, tolerance=0) True Rectangular matrices are never Hermitian:: - sage: A = matrix(QQbar, 3, 4) - sage: A._is_hermitian(skew=False, tolerance=0) + sage: A = matrix(QQbar, 3, 4) # needs sage.rings.number_field + sage: A._is_hermitian(skew=False, tolerance=0) # needs sage.rings.number_field False A square, empty matrix is trivially Hermitian:: @@ -4034,8 +4049,9 @@ cdef class Matrix(sage.structure.element.Matrix): True A matrix that is skew-Hermitian:: - sage: A = matrix(QQbar, [[-I, 2+I], [-2+I, 0]]) - sage: A._is_hermitian(skew=False, tolerance=0) + + sage: A = matrix(QQbar, [[-I, 2+I], [-2+I, 0]]) # needs sage.rings.number_field + sage: A._is_hermitian(skew=False, tolerance=0) # needs sage.rings.number_field False sage: A._is_hermitian(skew=True, tolerance=0) True @@ -4129,18 +4145,20 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 1 + I, 1 - 6*I, -1 - I], ....: [-3 - I, -4*I, -2], ....: [-1 + I, -2 - 8*I, 2 + I]]) sage: A.is_hermitian() False - sage: B = A*A.conjugate_transpose() + sage: B = A * A.conjugate_transpose() sage: B.is_hermitian() True Sage has several fields besides the entire complex numbers where conjugation is non-trivial. :: + sage: # needs sage.rings.number_field sage: F. = QuadraticField(-7) sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3], ....: [-2*b - 3, -3*b + 2, -2*b], @@ -4154,19 +4172,20 @@ cdef class Matrix(sage.structure.element.Matrix): A matrix that is nearly Hermitian, but for a non-real diagonal entry. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 2, 2-I, 1+4*I], ....: [ 2+I, 3+I, 2-6*I], ....: [1-4*I, 2+6*I, 5]]) sage: A.is_hermitian() False - sage: A[1,1] = 132 + sage: A[1, 1] = 132 sage: A.is_hermitian() True Rectangular matrices are never Hermitian. :: - sage: A = matrix(QQbar, 3, 4) - sage: A.is_hermitian() + sage: A = matrix(QQbar, 3, 4) # needs sage.rings.number_field + sage: A.is_hermitian() # needs sage.rings.number_field False A square, empty matrix is trivially Hermitian. :: @@ -4204,27 +4223,28 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: - sage: A = matrix(QQbar, [[0, -1], + sage: A = matrix(QQbar, [[0, -1], # needs sage.rings.number_field ....: [1, 0]]) - sage: A.is_skew_hermitian() + sage: A.is_skew_hermitian() # needs sage.rings.number_field True A matrix that is nearly skew-Hermitian, but for a non-real diagonal entry. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ -I, -1, 1-I], ....: [ 1, 1, -1], ....: [-1-I, 1, -I]]) sage: A.is_skew_hermitian() False - sage: A[1,1] = -I + sage: A[1, 1] = -I sage: A.is_skew_hermitian() True Rectangular matrices are never skew-Hermitian. :: - sage: A = matrix(QQbar, 3, 4) - sage: A.is_skew_hermitian() + sage: A = matrix(QQbar, 3, 4) # needs sage.rings.number_field + sage: A.is_skew_hermitian() # needs sage.rings.number_field False A square, empty matrix is trivially Hermitian. :: @@ -4627,7 +4647,7 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: - sage: m = matrix(GF(7),5,range(25)) + sage: m = matrix(GF(7), 5, range(25)) sage: m.rank() 2 @@ -4645,8 +4665,8 @@ cdef class Matrix(sage.structure.element.Matrix): entries are polynomials over a finite field (:trac:`5014`):: sage: P. = PolynomialRing(GF(17)) - sage: m = matrix(P, [ [ 6*x^2 + 8*x + 12, 10*x^2 + 4*x + 11], - ....: [8*x^2 + 12*x + 15, 8*x^2 + 9*x + 16] ]) + sage: m = matrix(P, [[ 6*x^2 + 8*x + 12, 10*x^2 + 4*x + 11], + ....: [8*x^2 + 12*x + 15, 8*x^2 + 9*x + 16]]) sage: m.rank() 2 """ @@ -4879,17 +4899,18 @@ cdef class Matrix(sage.structure.element.Matrix): Over finite fields:: - sage: A = matrix(GF(59),3,[10,56,39,53,56,33,58,24,55]) - sage: A.multiplicative_order() + sage: A = matrix(GF(59), 3, [10,56,39,53,56,33,58,24,55]) + sage: A.multiplicative_order() # needs sage.groups 580 sage: (A^580).is_one() True - sage: B = matrix(GF(10007^3,'b'),0) - sage: B.multiplicative_order() + sage: B = matrix(GF(10007^3, 'b'), 0) # needs sage.rings.finite_rings + sage: B.multiplicative_order() # needs sage.rings.finite_rings 1 - sage: M = MatrixSpace(GF(11^2,'e'),5) + sage: # needs sage.rings.finite_rings + sage: M = MatrixSpace(GF(11^2, 'e'), 5) sage: E = M.random_element() sage: while E.det() == 0: ....: E = M.random_element() @@ -4898,23 +4919,23 @@ cdef class Matrix(sage.structure.element.Matrix): Over `\ZZ`:: - sage: m = matrix(ZZ,2,2,[-1,1,-1,0]) - sage: m.multiplicative_order() + sage: m = matrix(ZZ, 2, 2, [-1,1,-1,0]) + sage: m.multiplicative_order() # needs sage.groups 3 - sage: m = posets.ChainPoset(6).coxeter_transformation() - sage: m.multiplicative_order() + sage: m = posets.ChainPoset(6).coxeter_transformation() # needs sage.combinat sage.graphs + sage: m.multiplicative_order() # needs sage.combinat sage.graphs sage.groups 7 - sage: P = posets.TamariLattice(4).coxeter_transformation() - sage: P.multiplicative_order() + sage: P = posets.TamariLattice(4).coxeter_transformation() # needs sage.combinat sage.graphs + sage: P.multiplicative_order() # needs sage.combinat sage.graphs sage.groups 10 sage: M = matrix(ZZ, 2, 2, [1, 1, 0, 1]) - sage: M.multiplicative_order() + sage: M.multiplicative_order() # needs sage.groups +Infinity - sage: for k in range(600): + sage: for k in range(600): # needs sage.groups ....: m = SL2Z.random_element() ....: o = m.multiplicative_order() ....: if o != Infinity and m**o != SL2Z.one(): @@ -4929,18 +4950,18 @@ cdef class Matrix(sage.structure.element.Matrix): ....: else: ....: return ZZ.random_element(-100,100) sage: rnd = matrix(ZZ, 8, 8, val) - sage: (rnd * m24 * rnd.inverse_of_unit()).multiplicative_order() + sage: (rnd * m24 * rnd.inverse_of_unit()).multiplicative_order() # needs sage.groups 24 TESTS:: - sage: C = matrix(GF(2^10,'c'),2,3,[1]*6) - sage: C.multiplicative_order() + sage: C = matrix(GF(2^10, 'c'), 2, 3, [1]*6) # needs sage.rings.finite_rings + sage: C.multiplicative_order() # needs sage.rings.finite_rings Traceback (most recent call last): ... ArithmeticError: self must be invertible ... - sage: D = matrix(IntegerModRing(6),3,[5,5,3,0,2,5,5,4,0]) + sage: D = matrix(IntegerModRing(6), 3, [5,5,3,0,2,5,5,4,0]) sage: D.multiplicative_order() Traceback (most recent call last): ... @@ -5060,6 +5081,7 @@ cdef class Matrix(sage.structure.element.Matrix): Check that :trac:`8198` is fixed:: + sage: # needs sage.rings.padics sage: R = Qp(5, 5) sage: x = R(5).add_bigoh(1) sage: I = matrix(R, [[1, 0], [0, 1]]) @@ -5094,6 +5116,7 @@ cdef class Matrix(sage.structure.element.Matrix): Check that :trac:`8198` is fixed:: + sage: # needs sage.rings.padics sage: R = Qp(5, 5) sage: x = R(5).add_bigoh(1) sage: I = matrix(R, [[1, 0], [0, 1]]) @@ -5191,10 +5214,11 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: - sage: R. = FreeAlgebra(QQ,2) - sage: a = matrix(2,2, [1,2,x*y,y*x]) - sage: b = matrix(2,2, [1,2,y*x,y*x]) - sage: a+b # indirect doctest + sage: # needs sage.combinat + sage: R. = FreeAlgebra(QQ, 2) + sage: a = matrix(2, 2, [1,2,x*y,y*x]) + sage: b = matrix(2, 2, [1,2,y*x,y*x]) + sage: a + b # indirect doctest [ 2 4] [x*y + y*x 2*y*x] @@ -5214,10 +5238,11 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: + sage: # needs sage.combinat sage: R. = FreeAlgebra(QQ,2) - sage: a = matrix(2,2, [1,2,x*y,y*x]) - sage: b = matrix(2,2, [1,2,y*x,y*x]) - sage: a-b # indirect doctest + sage: a = matrix(2, 2, [1,2,x*y,y*x]) + sage: b = matrix(2, 2, [1,2,y*x,y*x]) + sage: a - b # indirect doctest [ 0 0] [x*y - y*x 0] @@ -5290,11 +5315,12 @@ cdef class Matrix(sage.structure.element.Matrix): [ x*y x^2*y x*y^2] [ -x^2*y^2 x^2*y + x*y^2 x^2*y - x*y^2] + sage: # needs sage.combinat sage: R. = FreeAlgebra(ZZ,2) - sage: a = matrix(R,2,3,[1,x,y,-x*y,x+y,x-y]); a + sage: a = matrix(R, 2, 3, [1,x,y, -x*y,x+y,x-y]); a [ 1 x y] [ -x*y x + y x - y] - sage: (x*y) * a # indirect doctest + sage: (x*y) * a # indirect doctest [ x*y x*y*x x*y^2] [ -x*y*x*y x*y*x + x*y^2 x*y*x - x*y^2] """ @@ -5323,8 +5349,9 @@ cdef class Matrix(sage.structure.element.Matrix): An example in which the base ring is not commutative:: + sage: # needs sage.combinat sage: F. = FreeAlgebra(QQ,2) - sage: a = matrix(2,[x,y,x^2,y^2]); a + sage: a = matrix(2, [x,y, x^2,y^2]); a [ x y] [x^2 y^2] sage: x * a # indirect doctest @@ -5334,8 +5361,9 @@ cdef class Matrix(sage.structure.element.Matrix): [ x*y y^2] [x^2*y y^3] + sage: # needs sage.combinat sage: R. = FreeAlgebra(ZZ,2) - sage: a = matrix(R,2,3,[1,x,y,-x*y,x+y,x-y]); a + sage: a = matrix(R, 2, 3, [1,x,y, -x*y,x+y,x-y]); a [ 1 x y] [ -x*y x + y x - y] sage: a * (x*y) @@ -5369,10 +5397,10 @@ cdef class Matrix(sage.structure.element.Matrix): [ 1 -x*y] [ x x + y] [ y x - y] - sage: a*b # indirect doctest + sage: a*b # indirect doctest [ x^2 + y^2 + 1 x^2 + x*y - y^2] [ x^2 + x*y - y^2 x^2*y^2 + 2*x^2 + 2*y^2] - sage: b*a # indirect doctest + sage: b*a # indirect doctest [ x^2*y^2 + 1 -x^2*y - x*y^2 + x -x^2*y + x*y^2 + y] [ -x^2*y - x*y^2 + x 2*x^2 + 2*x*y + y^2 x^2 + x*y - y^2] [ -x^2*y + x*y^2 + y x^2 + x*y - y^2 x^2 - 2*x*y + 2*y^2] @@ -5380,47 +5408,49 @@ cdef class Matrix(sage.structure.element.Matrix): We verify that the matrix multiplies are correct by comparing them with what PARI gets:: - sage: gp(a)*gp(b) - gp(a*b) + sage: gp(a)*gp(b) - gp(a*b) # needs sage.libs.pari [0, 0; 0, 0] - sage: gp(b)*gp(a) - gp(b*a) + sage: gp(b)*gp(a) - gp(b*a) # needs sage.libs.pari [0, 0, 0; 0, 0, 0; 0, 0, 0] EXAMPLE of matrix times matrix over different base rings:: - sage: a = matrix(ZZ,2,2,range(4)) - sage: b = matrix(GF(7),2,2,range(4)) - sage: c = matrix(QQ,2,2,range(4)) - sage: d = a*b; d + sage: a = matrix(ZZ, 2, 2, range(4)) + sage: b = matrix(GF(7), 2, 2, range(4)) + sage: c = matrix(QQ, 2, 2, range(4)) + sage: d = a * b; d [2 3] [6 4] sage: parent(d) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7 - sage: parent(b*a) + sage: parent(b * a) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7 - sage: d = a*c; d + sage: d = a * c; d [ 2 3] [ 6 11] sage: parent(d) Full MatrixSpace of 2 by 2 dense matrices over Rational Field - sage: d = b+c + sage: d = b + c Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for +: 'Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7' and 'Full MatrixSpace of 2 by 2 dense matrices over Rational Field' - sage: d = b+c.change_ring(GF(7)); d + TypeError: unsupported operand parent(s) for +: + 'Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7' and + 'Full MatrixSpace of 2 by 2 dense matrices over Rational Field' + sage: d = b + c.change_ring(GF(7)); d [0 2] [4 6] EXAMPLE of matrix times matrix where one matrix is sparse and the other is dense (in such mixed cases, the result is always dense):: - sage: a = matrix(ZZ,2,2,range(4),sparse=True) - sage: b = matrix(GF(7),2,2,range(4),sparse=False) - sage: c = a*b; c + sage: a = matrix(ZZ, 2, 2, range(4), sparse=True) + sage: b = matrix(GF(7), 2, 2, range(4), sparse=False) + sage: c = a * b; c [2 3] [6 4] sage: parent(c) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7 - sage: c = b*a; c + sage: c = b * a; c [2 3] [6 4] sage: parent(c) @@ -5428,11 +5458,12 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLE of matrix multiplication over a noncommutative base ring:: - sage: R. = FreeAlgebra(QQ,2) + sage: # needs sage.combinat + sage: R. = FreeAlgebra(QQ, 2) sage: x*y - y*x x*y - y*x - sage: a = matrix(2,2, [1,2,x,y]) - sage: b = matrix(2,2, [x,y,x^2,y^2]) + sage: a = matrix(2, 2, [1,2, x,y]) + sage: b = matrix(2, 2, [x,y, x^2,y^2]) sage: a*b [ x + 2*x^2 y + 2*y^2] [x^2 + y*x^2 x*y + y^3] @@ -5457,7 +5488,9 @@ cdef class Matrix(sage.structure.element.Matrix): sage: a*v Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 2 by 3 dense matrices over Integer Ring' and 'Ambient free module of rank 2 over the principal ideal domain Integer Ring' + TypeError: unsupported operand parent(s) for *: + 'Full MatrixSpace of 2 by 3 dense matrices over Integer Ring' and + 'Ambient free module of rank 2 over the principal ideal domain Integer Ring' This illustrates how coercion works:: @@ -5504,8 +5537,9 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLE of scalar multiplication in the noncommutative case:: - sage: R. = FreeAlgebra(ZZ,2) - sage: a = matrix(2,[x,y,x^2,y^2]) + sage: # needs sage.combinat + sage: R. = FreeAlgebra(ZZ, 2) + sage: a = matrix(2, [x,y, x^2,y^2]) sage: a * x [ x^2 y*x] [ x^3 y^2*x] @@ -5632,17 +5666,18 @@ cdef class Matrix(sage.structure.element.Matrix): sage: m = matrix(Zmod(2^100),2,[2,1,3,3]) sage: type(m) - sage: (~m)*m + sage: (~m)*m # needs sage.libs.pari [1 0] [0 1] - sage: ~m + sage: ~m # needs sage.libs.pari [ 1 422550200076076467165567735125] [1267650600228229401496703205375 422550200076076467165567735126] Matrices over p-adics. See :trac:`17272` :: - sage: R = ZpCA(5,5,print_mode='val-unit') - sage: A = matrix(R,3,3,[250,2369,1147,106,927,362,90,398,2483]) + sage: # needs sage.rings.padics + sage: R = ZpCA(5, 5, print_mode='val-unit') + sage: A = matrix(R, 3, 3, [250,2369,1147,106,927,362,90,398,2483]) sage: A [5^3 * 2 + O(5^5) 2369 + O(5^5) 1147 + O(5^5)] [ 106 + O(5^5) 927 + O(5^5) 362 + O(5^5)] @@ -5768,19 +5803,19 @@ cdef class Matrix(sage.structure.element.Matrix): EXAMPLES:: sage: R. = ZZ[] - sage: RR = R.quotient(a*d-b*c-1) - sage: a,b,c,d = RR.gens() - sage: m = matrix(2, [a,b,c,d]) - sage: n = m.inverse_of_unit() - sage: m * n + sage: RR = R.quotient(a*d - b*c - 1) + sage: a,b,c,d = RR.gens() # needs sage.libs.singular + sage: m = matrix(2, [a,b, c,d]) + sage: n = m.inverse_of_unit() # needs sage.libs.singular + sage: m * n # needs sage.libs.singular [1 0] [0 1] - sage: matrix(RR, 2, 1, [a,b]).inverse_of_unit() + sage: matrix(RR, 2, 1, [a,b]).inverse_of_unit() # needs sage.libs.singular Traceback (most recent call last): ... ArithmeticError: self must be a square matrix - sage: matrix(RR, 1, 1, [2]).inverse_of_unit() + sage: matrix(RR, 1, 1, [2]).inverse_of_unit() # needs sage.libs.singular Traceback (most recent call last): ... NotImplementedError: Lifting of multivariate polynomials over non-fields is not implemented. @@ -5793,9 +5828,9 @@ cdef class Matrix(sage.structure.element.Matrix): Tests for :trac:`28570`:: - sage: P = posets.TamariLattice(7) - sage: M = P._hasse_diagram._leq_matrix - sage: M.inverse_of_unit() # this was very slow, now 1s + sage: P = posets.TamariLattice(7) # needs sage.combinat sage.graphs + sage: M = P._hasse_diagram._leq_matrix # needs sage.combinat sage.graphs + sage: M.inverse_of_unit() # this was very slow, now 1s # needs sage.combinat sage.graphs 429 x 429 sparse matrix over Integer Ring... sage: m = matrix(Zmod(2**2), 1, 1, [1], sparse=True) @@ -5888,9 +5923,9 @@ cdef class Matrix(sage.structure.element.Matrix): Non-integer (symbolic) exponents are also supported:: - sage: k = var('k') + sage: k = var('k') # needs sage.symbolic sage: A = matrix([[2, -1], [1, 0]]) - sage: A^(2*k+1) + sage: A^(2*k+1) # needs sage.symbolic [ 2*k + 2 -2*k - 1] [ 2*k + 1 -2*k] """ diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index 8983192931b..2ee50b25b7b 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -5,7 +5,7 @@ For design documentation see :mod:`sage.matrix.docs`. TESTS:: - sage: A = Matrix(GF(5),3,3,srange(9)) + sage: A = Matrix(GF(5), 3, 3, srange(9)) sage: TestSuite(A).run() """ @@ -40,11 +40,11 @@ cdef class Matrix(Matrix0): sage: a = matrix(R,2,[x+1,2/3, x^2/2, 1+x^3]); a [ x + 1 2/3] [1/2*x^2 x^3 + 1] - sage: b = gp(a); b # indirect doctest + sage: b = gp(a); b # indirect doctest # needs sage.libs.pari [x + 1, 2/3; 1/2*x^2, x^3 + 1] sage: a.determinant() x^4 + x^3 - 1/3*x^2 + x + 1 - sage: b.matdet() + sage: b.matdet() # needs sage.libs.pari x^4 + x^3 - 1/3*x^2 + x + 1 """ w = self.list() @@ -69,11 +69,11 @@ cdef class Matrix(Matrix0): sage: a = matrix(R,2,[x+1,2/3, x^2/2, 1+x^3]); a [ x + 1 2/3] [1/2*x^2 x^3 + 1] - sage: b = pari(a); b # indirect doctest + sage: b = pari(a); b # indirect doctest # needs sage.libs.pari [x + 1, 2/3; 1/2*x^2, x^3 + 1] sage: a.determinant() x^4 + x^3 - 1/3*x^2 + x + 1 - sage: b.matdet() + sage: b.matdet() # needs sage.libs.pari x^4 + x^3 - 1/3*x^2 + x + 1 This function preserves precision for entries of inexact type (e.g. @@ -83,7 +83,7 @@ cdef class Matrix(Matrix0): sage: a = matrix(R, 2, [1, 2, 3, 1]); a [1.0 2.0] [3.0 1.0] - sage: b = pari(a); b + sage: b = pari(a); b # needs sage.libs.pari [1.000000000, 2.000000000; 3.000000000, 1.000000000] # 32-bit [1.00000000000000, 2.00000000000000; 3.00000000000000, 1.00000000000000] # 64-bit """ @@ -96,8 +96,9 @@ cdef class Matrix(Matrix0): EXAMPLES:: + sage: # needs sage.libs.gap sage: A = MatrixSpace(QQ,3,3)([0,1,2,3,4,5,6,7,8]) - sage: g = gap(A) # indirect doctest + sage: g = gap(A) # indirect doctest sage: g [ [ 0, 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8 ] ] sage: g.CharacteristicPolynomial() @@ -110,8 +111,9 @@ cdef class Matrix(Matrix0): Particularly difficult is the case of matrices over cyclotomic fields and general number fields. See :trac:`5618` and :trac:`8909`:: + sage: # needs sage.libs.gap sage.rings.number_field sage: K. = CyclotomicField(8) - sage: A = MatrixSpace(K,2,2)([0,1+zeta,2*zeta,3]) + sage: A = MatrixSpace(K, 2, 2)([0, 1+zeta, 2*zeta, 3]) sage: g = gap(A); g [ [ 0, 1+E(8) ], [ 2*E(8), 3 ] ] sage: matrix(K, g) == A @@ -119,10 +121,11 @@ cdef class Matrix(Matrix0): sage: g.IsMatrix() true + sage: # needs sage.libs.gap sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: L. = NumberField(x^3 - 2) # optional - sage.rings.number_field - sage: A = MatrixSpace(L, 2, 2)([0, 1+tau, 2*tau, 3]) # optional - sage.rings.number_field - sage: g = gap(A); g # optional - sage.rings.number_field + sage: L. = NumberField(x^3 - 2) + sage: A = MatrixSpace(L, 2, 2)([0, 1+tau, 2*tau, 3]) + sage: g = gap(A); g [ [ !0, tau+1 ], [ 2*tau, !3 ] ] sage: matrix(L, g) == A True @@ -153,9 +156,9 @@ cdef class Matrix(Matrix0): EXAMPLES:: - sage: libgap(identity_matrix(ZZ,2)) + sage: libgap(identity_matrix(ZZ, 2)) # needs sage.libs.gap [ [ 1, 0 ], [ 0, 1 ] ] - sage: libgap(matrix(GF(3),2,2,[4,5,6,7])) + sage: libgap(matrix(GF(3), 2, 2, [4,5,6,7])) # needs sage.libs.gap [ [ Z(3)^0, Z(3) ], [ 0*Z(3), Z(3)^0 ] ] """ from sage.libs.gap.libgap import libgap @@ -192,9 +195,9 @@ cdef class Matrix(Matrix0): :: - sage: y = var('y') - sage: M = matrix(SR, 2, [y+sin(y), y - 4, 1/y, dilog(y)]) - sage: M == fricas(M).sage() # optional - fricas + sage: y = var('y') # needs sage.symbolic + sage: M = matrix(SR, 2, [y+sin(y), y - 4, 1/y, dilog(y)]) # needs sage.symbolic + sage: M == fricas(M).sage() # optional - fricas # needs sage.symbolic True """ s = ','.join('[' + ','.join(cf._fricas_init_() for cf in row) + ']' @@ -212,22 +215,22 @@ cdef class Matrix(Matrix0): EXAMPLES:: - sage: M = matrix(ZZ,2,range(4)) - sage: giac(M) + sage: M = matrix(ZZ, 2, range(4)) + sage: giac(M) # needs sage.libs.giac [[0,1],[2,3]] - sage: M = matrix(QQ,3,[1,2,3,4/3,5/3,6/4,7,8,9]) - sage: giac(M) + sage: M = matrix(QQ, 3, [1,2,3, 4/3,5/3,6/4, 7,8,9]) + sage: giac(M) # needs sage.libs.giac [[1,2,3],[4/3,5/3,3/2],[7,8,9]] sage: P. = ZZ[] sage: M = matrix(P, 2, [-9*x^2-2*x+2, x-1, x^2+8*x, -3*x^2+5]) - sage: giac(M) + sage: giac(M) # needs sage.libs.giac [[-9*sageVARx^2-2*sageVARx+2,sageVARx-1],[sageVARx^2+8*sageVARx,-3*sageVARx^2+5]] - sage: y = var('y') - sage: M = matrix(SR, 2, [y+sin(y), y - 4, 1/y, dilog(y)]) - sage: giac(M).det().sage() + sage: y = var('y') # needs sage.symbolic + sage: M = matrix(SR, 2, [y+sin(y), y - 4, 1/y, dilog(y)]) # needs sage.symbolic + sage: giac(M).det().sage() # needs sage.libs.giac sage.symbolic (y^2*dilog(y) + y*dilog(y)*sin(y) - y + 4)/y """ s = ','.join('[' + ','.join(cf._giac_init_() for cf in row) + ']' @@ -244,11 +247,11 @@ cdef class Matrix(Matrix0): [0 1 2] [3 4 5] [6 7 8] - sage: m._maxima_init_() + sage: m._maxima_init_() # needs sage.symbolic 'matrix([0,1,2],[3,4,5],[6,7,8])' - sage: a = maxima(m); a + sage: a = maxima(m); a # needs sage.symbolic matrix([0,1,2],[3,4,5],[6,7,8]) - sage: a.charpoly('x').expand() + sage: a.charpoly('x').expand() # needs sage.symbolic ...-x^3...+12*x^2+18*x sage: m.charpoly() x^3 - 12*x^2 - 18*x @@ -271,7 +274,7 @@ cdef class Matrix(Matrix0): sage: A = MatrixSpace(QQ,3)([1,2,3,4/3,5/3,6/4,7,8,9]) sage: g = mathematica(A); g # optional - mathematica {{1, 2, 3}, {4/3, 5/3, 3/2}, {7, 8, 9}} - sage: A._mathematica_init_() + sage: A._mathematica_init_() # needs sage.symbolic '{{1/1, 2/1, 3/1}, {4/3, 5/3, 3/2}, {7/1, 8/1, 9/1}}' :: @@ -282,10 +285,10 @@ cdef class Matrix(Matrix0): :: - sage: a = matrix([[pi, sin(x)], [cos(x), 1/e]]); a + sage: a = matrix([[pi, sin(x)], [cos(x), 1/e]]); a # needs sage.symbolic [ pi sin(x)] [cos(x) e^(-1)] - sage: a._mathematica_init_() + sage: a._mathematica_init_() # needs sage.symbolic '{{Pi, Sin[x]}, {Cos[x], Exp[-1]}}' """ return '{' + ', '.join([v._mathematica_init_() for v in self.rows()]) + '}' @@ -299,26 +302,28 @@ cdef class Matrix(Matrix0): We first coerce a square matrix. :: + sage: # optional - magma sage: A = MatrixSpace(QQ,3)([1,2,3,4/3,5/3,6/4,7,8,9]) - sage: B = magma(A); B # (indirect doctest) optional - magma + sage: B = magma(A); B # indirect doctest [ 1 2 3] [4/3 5/3 3/2] [ 7 8 9] - sage: B.Type() # optional - magma + sage: B.Type() AlgMatElt - sage: B.Parent() # optional - magma + sage: B.Parent() Full Matrix Algebra of degree 3 over Rational Field We coerce a non-square matrix over `\ZZ/8\ZZ`. :: + sage: # optional - magma sage: A = MatrixSpace(Integers(8),2,3)([-1,2,3,4,4,-2]) - sage: B = magma(A); B # optional - magma + sage: B = magma(A); B [7 2 3] [4 4 6] - sage: B.Type() # optional - magma + sage: B.Type() ModMatRngElt - sage: B.Parent() # optional - magma + sage: B.Parent() Full RMatrixSpace of 2 by 3 matrices over IntegerRing(8) sage: R. = QQ[] @@ -336,17 +341,17 @@ cdef class Matrix(Matrix0): We coerce a matrix over a cyclotomic field, where the generator must be named during the coercion. :: - sage: K = CyclotomicField(9) ; z = K.0 - sage: M = matrix(K,3,3,[0,1,3,z,z**4,z-1,z**17,1,0]) - sage: M + sage: # optional - magma, needs sage.rings.number_field + sage: K = CyclotomicField(9); z = K.0 + sage: M = matrix(K, 3, 3, [0,1,3,z,z**4,z-1,z**17,1,0]); M [ 0 1 3] [ zeta9 zeta9^4 zeta9 - 1] [-zeta9^5 - zeta9^2 1 0] - sage: magma(M) # optional - magma + sage: magma(M) [ 0 1 3] [ zeta9 zeta9^4 zeta9 - 1] [-zeta9^5 - zeta9^2 1 0] - sage: magma(M**2) == magma(M)**2 # optional - magma + sage: magma(M**2) == magma(M)**2 True One sparse matrix:: @@ -389,9 +394,9 @@ cdef class Matrix(Matrix0): sage: maple(M) # optional - maple Matrix(2, 2, [[-9*x^2-2*x+2,x-1],[x^2+8*x,-3*x^2+5]]) - sage: y = var('y') - sage: M = matrix(SR, 2, [y+sin(y), y - 4, 1/y, dilog(y)]) - sage: M == maple(M).sage() # optional - maple + sage: y = var('y') # needs sage.symbolic + sage: M = matrix(SR, 2, [y+sin(y), y - 4, 1/y, dilog(y)]) # needs sage.symbolic + sage: M == maple(M).sage() # optional - maple # needs sage.symbolic True """ s = ','.join('[' + ','.join(cf._maple_init_() for cf in row) + ']' @@ -405,12 +410,12 @@ cdef class Matrix(Matrix0): EXAMPLES:: sage: M = matrix(ZZ,2,range(4)) - sage: polymake(M) # optional - jupymake + sage: polymake(M) # optional - jupymake 0 1 2 3 - sage: K. = QuadraticField(5) - sage: M = matrix(K, [[1, 2], [sqrt5, 3]]) - sage: polymake(M) # optional - jupymake + sage: K. = QuadraticField(5) # needs sage.rings.number_field + sage: M = matrix(K, [[1, 2], [sqrt5, 3]]) # needs sage.rings.number_field + sage: polymake(M) # optional - jupymake # needs sage.rings.number_field 1 2 0+1r5 3 """ @@ -436,7 +441,7 @@ cdef class Matrix(Matrix0): EXAMPLES:: sage: m = matrix(ZZ, [[1,2],[3,4]]) - sage: macaulay2(m) #optional - macaulay2 (indirect doctest) + sage: macaulay2(m) # indirect doctest # optional - macaulay2 | 1 2 | | 3 4 | @@ -444,7 +449,7 @@ cdef class Matrix(Matrix0): sage: R. = QQ[] sage: m = matrix([[x,y],[1+x,1+y]]) - sage: macaulay2(m) #optional - macaulay2 + sage: macaulay2(m) # optional - macaulay2 | x y | | x+1 y+1 | @@ -460,9 +465,9 @@ cdef class Matrix(Matrix0): Check that degenerate matrix dimensions are handled correctly (:trac:`28591`):: - sage: macaulay2(matrix(QQ, 2, 0)).numrows() # optional - macaulay2 + sage: macaulay2(matrix(QQ, 2, 0)).numrows() # optional - macaulay2 2 - sage: macaulay2(matrix(QQ, 0, 2)).numcols() # optional - macaulay2 + sage: macaulay2(matrix(QQ, 0, 2)).numcols() # optional - macaulay2 2 """ if macaulay2 is None: @@ -485,7 +490,7 @@ cdef class Matrix(Matrix0): [1 2 3] [4 5 6] [7 8 9] - sage: a._scilab_init_() + sage: a._scilab_init_() # needs sage.libs.pari '[1,2,3;4,5,6;7,8,9]' AUTHORS: @@ -514,7 +519,7 @@ cdef class Matrix(Matrix0): [1 2 3] [4 5 6] [7 8 9] - sage: b = scilab(a); b # optional - scilab (indirect doctest) + sage: b = scilab(a); b # indirect doctest # optional - scilab 1. 2. 3. 4. 5. 6. 7. 8. 9. @@ -540,41 +545,42 @@ cdef class Matrix(Matrix0): [1 2 3] [4 5 6] [7 8 9] - sage: sA = A._sympy_(); sA + sage: sA = A._sympy_(); sA # needs sympy Matrix([ [1, 2, 3], [4, 5, 6], [7, 8, 9]]) - sage: type(sA) + sage: type(sA) # needs sympy sage: I = MatrixSpace(QQ, 5, 5, sparse=True).identity_matrix() - sage: sI = I._sympy_(); sI + sage: sI = I._sympy_(); sI # needs sympy Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]]) - sage: type(sI) + sage: type(sI) # needs sympy If ``self`` was immutable, then converting the result to Sage gives back ``self``:: sage: immA = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], immutable=True) - sage: immA._sympy_()._sage_() is immA + sage: immA._sympy_()._sage_() is immA # needs sympy True If ``self`` was mutable, then converting back to Sage creates a new matrix:: - sage: sA._sage_() is A + sage: sA._sage_() is A # needs sympy sage.symbolic False - sage: sA._sage_() == A + sage: sA._sage_() == A # needs sympy sage.symbolic True Symbolic matrices are supported:: + sage: # needs sympy sage.symbolic sage: M = matrix([[sin(x), cos(x)], [-cos(x), sin(x)]]); M [ sin(x) cos(x)] [-cos(x) sin(x)] @@ -593,12 +599,12 @@ cdef class Matrix(Matrix0): sage: ZeroCol = matrix(QQ, 3, 0, sparse=False); ZeroCol [] - sage: sZeroCol = ZeroCol._sympy_(); sZeroCol + sage: sZeroCol = ZeroCol._sympy_(); sZeroCol # needs sympy Matrix(3, 0, []) sage: ZeroRow = matrix(QQ, 0, 2, sparse=False); ZeroRow [] - sage: sZeroRow = ZeroRow._sympy_(); sZeroRow + sage: sZeroRow = ZeroRow._sympy_(); sZeroRow # needs sympy Matrix(0, 2, []) """ @@ -678,7 +684,8 @@ cdef class Matrix(Matrix0): EXAMPLES:: - sage: a = matrix(3,range(12)) + sage: # needs numpy + sage: a = matrix(3, range(12)) sage: a.numpy() array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], @@ -699,16 +706,20 @@ cdef class Matrix(Matrix0): Type ``numpy.typecodes`` for a list of the possible typecodes:: - sage: import numpy - sage: sorted(numpy.typecodes.items()) - [('All', '?bhilqpBHILQPefdgFDGSUVOMm'), ('AllFloat', 'efdgFDG'), ('AllInteger', 'bBhHiIlLqQpP'), ('Character', 'c'), ('Complex', 'FDG'), ('Datetime', 'Mm'), ('Float', 'efdg'), ('Integer', 'bhilqp'), ('UnsignedInteger', 'BHILQP')] + sage: import numpy # needs numpy + sage: sorted(numpy.typecodes.items()) # needs numpy + [('All', '?bhilqpBHILQPefdgFDGSUVOMm'), ('AllFloat', 'efdgFDG'), + ('AllInteger', 'bBhHiIlLqQpP'), ('Character', 'c'), ('Complex', 'FDG'), + ('Datetime', 'Mm'), ('Float', 'efdg'), ('Integer', 'bhilqp'), + ('UnsignedInteger', 'BHILQP')] Alternatively, numpy automatically calls this function (via the magic :meth:`__array__` method) to convert Sage matrices to numpy arrays:: + sage: # needs numpy sage: import numpy - sage: b=numpy.array(a); b + sage: b = numpy.array(a); b array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) @@ -757,7 +768,7 @@ cdef class Matrix(Matrix0): EXAMPLES:: - sage: M = Matrix(Integers(7), 2, 2, [5, 9, 13, 15]) ; M + sage: M = Matrix(Integers(7), 2, 2, [5, 9, 13, 15]); M [5 2] [6 1] sage: M.lift() @@ -801,7 +812,7 @@ cdef class Matrix(Matrix0): EXAMPLES:: - sage: M = Matrix(Integers(8), 2, 4, range(8)) ; M + sage: M = Matrix(Integers(8), 2, 4, range(8)); M [0 1 2 3] [4 5 6 7] sage: L = M.lift_centered(); L @@ -973,14 +984,14 @@ cdef class Matrix(Matrix0): sage: matrix(3, [1..9]).columns() [(1, 4, 7), (2, 5, 8), (3, 6, 9)] - sage: matrix(RR, 2, [sqrt(2), pi, exp(1), 0]).columns() + sage: matrix(RR, 2, [sqrt(2), pi, exp(1), 0]).columns() # needs sage.symbolic [(1.41421356237310, 2.71828182845905), (3.14159265358979, 0.000000000000000)] sage: matrix(RR, 0, 2, []).columns() [(), ()] sage: matrix(RR, 2, 0, []).columns() [] - sage: m = matrix(RR, 3, 3, {(1,2): pi, (2, 2): -1, (0,1): sqrt(2)}) - sage: parent(m.columns()[0]) + sage: m = matrix(RR, 3, 3, {(1,2): pi, (2, 2): -1, (0,1): sqrt(2)}) # needs sage.symbolic + sage: parent(m.columns()[0]) # needs sage.symbolic Sparse vector space of dimension 3 over Real Field with 53 bits of precision Sparse matrices produce sparse columns. :: @@ -1029,14 +1040,14 @@ cdef class Matrix(Matrix0): sage: matrix(3, [1..9]).rows() [(1, 2, 3), (4, 5, 6), (7, 8, 9)] - sage: matrix(RR, 2, [sqrt(2), pi, exp(1), 0]).rows() + sage: matrix(RR, 2, [sqrt(2), pi, exp(1), 0]).rows() # needs sage.symbolic [(1.41421356237310, 3.14159265358979), (2.71828182845905, 0.000000000000000)] sage: matrix(RR, 0, 2, []).rows() [] sage: matrix(RR, 2, 0, []).rows() [(), ()] - sage: m = matrix(RR, 3, 3, {(1,2): pi, (2, 2): -1, (0,1): sqrt(2)}) - sage: parent(m.rows()[0]) + sage: m = matrix(RR, 3, 3, {(1,2): pi, (2, 2): -1, (0,1): sqrt(2)}) # needs sage.symbolic + sage: parent(m.rows()[0]) # needs sage.symbolic Sparse vector space of dimension 3 over Real Field with 53 bits of precision Sparse matrices produce sparse rows. :: @@ -1101,7 +1112,8 @@ cdef class Matrix(Matrix0): sage: c = a.dense_columns(); c [(x, 2/3*x), (x^2, x^5 + 1)] sage: parent(c[1]) - Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 2 over the principal ideal domain + Univariate Polynomial Ring in x over Rational Field TESTS: @@ -1461,10 +1473,10 @@ cdef class Matrix(Matrix0): tmp = [self.get_unsafe(i,j) for j in range(self._ncols)] return V(tmp, coerce=False, copy=False, check=False) - ########################################################################### # Building matrices out of other matrices, rows, or columns ########################################################################### + def stack(self, bottom, subdivide=False): r""" Return a new matrix formed by appending the matrix (or vector) @@ -1615,13 +1627,15 @@ cdef class Matrix(Matrix0): [ 1.00000000000000 2.00000000000000] [0.891207360061435 0.808496403819590] sage: C.parent() - Full MatrixSpace of 2 by 2 dense matrices over Real Field with 53 bits of precision + Full MatrixSpace of 2 by 2 dense matrices + over Real Field with 53 bits of precision sage: D = B.stack(A); D [0.891207360061435 0.808496403819590] [ 1.00000000000000 2.00000000000000] sage: D.parent() - Full MatrixSpace of 2 by 2 dense matrices over Real Field with 53 bits of precision + Full MatrixSpace of 2 by 2 dense matrices + over Real Field with 53 bits of precision :: @@ -1633,7 +1647,8 @@ cdef class Matrix(Matrix0): [ 1 2/3] [ y y^2] sage: C.parent() - Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in y over Rational Field + Full MatrixSpace of 2 by 2 dense matrices over + Univariate Polynomial Ring in y over Rational Field Stacking a dense matrix atop a sparse one returns a sparse matrix:: @@ -1879,17 +1894,18 @@ cdef class Matrix(Matrix0): sage: A = matrix(QQ, 2, [1,2]) sage: B = matrix(RR, 2, [sin(1.1), sin(2.2)]) - sage: C = A.augment(B); C + sage: C = A.augment(B); C # needs sage.symbolic [ 1 183017397/205358938] [ 2 106580492/131825561] - sage: C.parent() + sage: C.parent() # needs sage.symbolic Full MatrixSpace of 2 by 2 dense matrices over Rational Field sage: D = B.augment(A); D [0.89120736006... 1.00000000000000] [0.80849640381... 2.00000000000000] sage: D.parent() - Full MatrixSpace of 2 by 2 dense matrices over Real Field with 53 bits of precision + Full MatrixSpace of 2 by 2 dense matrices + over Real Field with 53 bits of precision Sometimes it is not possible to coerce into the base ring of ``self``. A solution is to change the base ring of ``self`` to @@ -1903,7 +1919,8 @@ cdef class Matrix(Matrix0): sage: C = B.augment(A); C [ y y^2 1 2] sage: C.parent() - Full MatrixSpace of 1 by 4 dense matrices over Univariate Polynomial Ring in y over Rational Field + Full MatrixSpace of 1 by 4 dense matrices over + Univariate Polynomial Ring in y over Rational Field sage: D = A.augment(B) Traceback (most recent call last): @@ -1914,7 +1931,8 @@ cdef class Matrix(Matrix0): sage: F = E.augment(B); F [ 1 2 y y^2] sage: F.parent() - Full MatrixSpace of 1 by 4 dense matrices over Univariate Polynomial Ring in y over Rational Field + Full MatrixSpace of 1 by 4 dense matrices over + Univariate Polynomial Ring in y over Rational Field AUTHORS: @@ -2090,8 +2108,8 @@ cdef class Matrix(Matrix0): INPUT: - * ``drows`` - list of indices of rows to be deleted from self. - * ``check`` - checks whether any index in ``drows`` is out of range. Defaults to ``True``. + * ``drows`` -- list of indices of rows to be deleted from ``self``. + * ``check`` -- (boolean, default: ``True``); whether to check if any index in ``drows`` is out of range. .. SEEALSO:: @@ -2153,7 +2171,7 @@ cdef class Matrix(Matrix0): def matrix_from_rows_and_columns(self, rows, columns): """ - Return the matrix constructed from self from the given rows and + Return the matrix constructed from ``self`` from the given rows and columns. EXAMPLES:: @@ -2176,9 +2194,7 @@ cdef class Matrix(Matrix0): [5 4] For example here we take from row 1 columns 2 then 0 twice, and do - this 3 times. - - :: + this 3 times:: sage: A.matrix_from_rows_and_columns([1,1,1],[2,0,0]) [5 3 3] @@ -2466,16 +2482,17 @@ cdef class Matrix(Matrix0): :: - sage: W. = CyclotomicField(100) - sage: M = Matrix(2, 3, [a, a/2, 0, a^2, a^100-1, a^2 - a]); M + sage: W. = CyclotomicField(100) # needs sage.rings.number_field + sage: M = Matrix(2, 3, [a, a/2, 0, a^2, a^100-1, a^2 - a]); M # needs sage.rings.number_field [ a 1/2*a 0] [ a^2 0 a^2 - a] - sage: M.zero_pattern_matrix() + sage: M.zero_pattern_matrix() # needs sage.rings.number_field [0 0 1] [0 1 0] :: + sage: # needs sage.rings.finite_rings sage: K. = GF(2^4) sage: l = [a^2 + 1, a^3 + 1, 0, 0, a, a^3 + a + 1, a + 1, ....: a + 1, a^2, a^3 + a + 1, a^3 + a, a^3 + a] @@ -2490,6 +2507,7 @@ cdef class Matrix(Matrix0): :: + sage: # needs sage.rings.finite_rings sage: K. = GF(25) sage: M = Matrix(K, 2, 3, [0, 2, 3, 5, a, a^2]) sage: M @@ -2521,10 +2539,9 @@ cdef class Matrix(Matrix0): M.set_unsafe(i, j, one) return M - - #################################################################################### + ###################################################################### # Change of representation between dense and sparse. - #################################################################################### + ###################################################################### def dense_matrix(self): """ @@ -2582,7 +2599,7 @@ cdef class Matrix(Matrix0): dict items are ETuples (see :trac:`17658`):: sage: from sage.rings.polynomial.polydict import ETuple - sage: matrix(GF(5^2,"z"),{ETuple((1, 1)): 2}).dense_matrix() + sage: matrix(GF(5^2, "z"), {ETuple((1, 1)): 2}).dense_matrix() # needs sage.rings.finite_rings [0 0] [0 2] """ diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 2053bca80c3..1e871d9e553 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -105,15 +105,17 @@ from sage.matrix.matrix_misc import permanental_minor_polynomial # used to deprecate only adjoint method from sage.misc.superseded import deprecated_function_alias + # temporary hack to silence the warnings from #34806 -from sage.rings.number_field.order import Order as NumberFieldOrder def ideal_or_fractional(R, *args): - if isinstance(R, NumberFieldOrder): + if isinstance(R, sage.rings.abc.Order): R = R.number_field() return R.ideal(*args) + _Fields = Fields() + cdef class Matrix(Matrix1): """ Base class for matrices, part 2 @@ -167,6 +169,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.symbolic sage: var('a,b,d,e') (a, b, d, e) sage: m = matrix([[a,b], [d,e]]) @@ -176,7 +179,7 @@ cdef class Matrix(Matrix1): sage: m.subs(a=b, b=d) [b d] [d e] - sage: m.subs({a: 3, b:2, d:1, e:-1}) + sage: m.subs({a: 3, b: 2, d: 1, e: -1}) [ 3 2] [ 1 -1] @@ -347,6 +350,8 @@ cdef class Matrix(Matrix1): True sage: X (-1, 2, 0, 0) + + sage: # needs sage.libs.pari sage: A = Matrix(Zmod(128), 2, 3, [5, 29, 33, 64, 0, 7]) sage: B = vector(Zmod(128), [31,39,56]) sage: X = A.solve_left(B); X @@ -391,6 +396,7 @@ cdef class Matrix(Matrix1): The vector of constants needs to be compatible with the base ring of the coefficient matrix:: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(27) sage: b = vector(F, [a,a,a,a,a]) sage: A.solve_left(b) @@ -412,9 +418,9 @@ cdef class Matrix(Matrix1): any are inexact, however, the ``check`` is still skipped (:trac:`29729` and :trac:`33159`):: - sage: A = matrix(SR, [[1, 1]]) # optional - sage.symbolic - sage: b = vector(SR, [2, 3]) # optional - sage.symbolic - sage: A.solve_left(b) # optional - sage.symbolic + sage: A = matrix(SR, [[1, 1]]) # needs sage.symbolic + sage: b = vector(SR, [2, 3]) # needs sage.symbolic + sage: A.solve_left(b) # needs sage.symbolic Traceback (most recent call last): ... ValueError: matrix equation has no solutions @@ -422,7 +428,7 @@ cdef class Matrix(Matrix1): In this case, turning off the ``check`` leads to a wrong result:: - sage: A.solve_left(b, check=False) # optional - sage.symbolic + sage: A.solve_left(b, check=False) # needs sage.symbolic (2) """ @@ -592,6 +598,7 @@ cdef class Matrix(Matrix1): Solving some systems over `\ZZ/n\ZZ`:: + sage: # needs sage.libs.pari sage: A = Matrix(Zmod(6), 3, 2, [1,2,3,4,5,6]) sage: B = vector(Zmod(6), [1,1,1]) sage: A.solve_right(B) @@ -618,8 +625,9 @@ cdef class Matrix(Matrix1): Solving a system over the p-adics:: - sage: k = Qp(5,4) - sage: a = matrix(k, 3, [1,7,3,2,5,4,1,1,2]); a + sage: # needs sage.rings.padics + sage: k = Qp(5, 4) + sage: a = matrix(k, 3, [1,7,3, 2,5,4, 1,1,2]); a [ 1 + O(5^4) 2 + 5 + O(5^4) 3 + O(5^4)] [ 2 + O(5^4) 5 + O(5^5) 4 + O(5^4)] [ 1 + O(5^4) 1 + O(5^4) 2 + O(5^4)] @@ -632,20 +640,21 @@ cdef class Matrix(Matrix1): Solving a system of linear equations symbolically using symbolic matrices:: - sage: var('a,b,c,d,x,y') # optional - sage.symbolic + sage: # needs sage.symbolic + sage: var('a,b,c,d,x,y') (a, b, c, d, x, y) - sage: A = matrix(SR, 2, [a,b,c,d]); A # optional - sage.symbolic + sage: A = matrix(SR, 2, [a,b,c,d]); A [a b] [c d] - sage: result = vector(SR, [3,5]); result # optional - sage.symbolic + sage: result = vector(SR, [3,5]); result (3, 5) - sage: soln = A.solve_right(result); soln # optional - sage.symbolic + sage: soln = A.solve_right(result); soln (-b*(3*c/a - 5)/(a*(b*c/a - d)) + 3/a, (3*c/a - 5)/(b*c/a - d)) - sage: (a*x+b*y).subs(x=soln[0], y=soln[1]).simplify_full() # optional - sage.symbolic + sage: (a*x + b*y).subs(x=soln[0], y=soln[1]).simplify_full() 3 - sage: (c*x+d*y).subs(x=soln[0], y=soln[1]).simplify_full() # optional - sage.symbolic + sage: (c*x + d*y).subs(x=soln[0], y=soln[1]).simplify_full() 5 - sage: (A*soln).apply_map(lambda x: x.simplify_full()) # optional - sage.symbolic + sage: (A*soln).apply_map(lambda x: x.simplify_full()) (3, 5) Over inexact rings, the output of this function may not be an exact @@ -720,8 +729,8 @@ cdef class Matrix(Matrix1): (:trac:`12406`):: sage: A = matrix(QQ, 2, [1, 2, 3, 4]) - sage: b = vector(RDF, [pi, e]) - sage: A.solve_right(b) # tol 1e-15 + sage: b = vector(RDF, [pi, e]) # needs sage.symbolic + sage: A.solve_right(b) # tol 1e-15 # needs sage.symbolic (-3.564903478720541, 3.353248066155167) sage: R. = ZZ[] sage: b = vector(R, [1, t]) @@ -736,7 +745,7 @@ cdef class Matrix(Matrix1): sage: A = Matrix(Zmod(6), 3, 2, [1,2,3,4,5,6]) sage: b = vector(ZZ, [1,1,1]) - sage: A.solve_right(b).base_ring() is Zmod(6) + sage: A.solve_right(b).base_ring() is Zmod(6) # needs sage.libs.pari True Check that the coercion mechanism gives consistent results @@ -777,9 +786,9 @@ cdef class Matrix(Matrix1): The vector of constants needs to be compatible with the base ring of the coefficient matrix. :: - sage: F. = FiniteField(27) - sage: b = vector(F, [a,a,a,a,a]) - sage: A.solve_right(b) + sage: F. = FiniteField(27) # needs sage.rings.finite_rings + sage: b = vector(F, [a,a,a,a,a]) # needs sage.rings.finite_rings + sage: A.solve_right(b) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: no common canonical parent for objects with parents: ... @@ -815,31 +824,32 @@ cdef class Matrix(Matrix1): any are inexact, however, the ``check`` is still skipped (:trac:`29729` and :trac:`33159`):: - sage: m = matrix(SR, [0]) # optional - sage.symbolic - sage: b = vector(SR, [1]) # optional - sage.symbolic - sage: m.solve_right(b, check=True) # optional - sage.symbolic + sage: m = matrix(SR, [0]) # needs sage.symbolic + sage: b = vector(SR, [1]) # needs sage.symbolic + sage: m.solve_right(b, check=True) # needs sage.symbolic Traceback (most recent call last): ... ValueError: matrix equation has no solutions In this case, turning off the ``check`` leads to a wrong result:: - sage: m.solve_right(b, check=False) # optional - sage.symbolic + sage: m.solve_right(b, check=False) # needs sage.symbolic (0) In the following, we have an inexact entry in the matrix, so the ``check`` is still skipped leading to a wrong result:: - sage: m = matrix(SR, [0.0]) # optional - sage.symbolic - sage: m.solve_right(b, check=True) # optional - sage.symbolic + sage: m = matrix(SR, [0.0]) # needs sage.symbolic + sage: m.solve_right(b, check=True) # needs sage.symbolic (0) :: - sage: SC = SR.subring(no_variables=True) # optional - sage.symbolic - sage: m = matrix(SC, [0]) # optional - sage.symbolic - sage: b = vector(SC, [1]) # optional - sage.symbolic - sage: m.solve_right(b) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: SC = SR.subring(no_variables=True) + sage: m = matrix(SC, [0]) + sage: b = vector(SC, [1]) + sage: m.solve_right(b) Traceback (most recent call last): ... ValueError: matrix equation has no solutions @@ -1131,17 +1141,19 @@ cdef class Matrix(Matrix1): :: - sage: G = matrix(GF(3),2,[0,1,2,2]) - sage: H = matrix(ZZ,2,[1,2,3,4]) + sage: G = matrix(GF(3), 2, [0, 1, 2, 2]) + sage: H = matrix(ZZ, 2, [1, 2, 3, 4]) sage: J = G.elementwise_product(H) sage: J [0 2] [0 2] sage: J.parent() - Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3 + Full MatrixSpace of 2 by 2 dense matrices + over Finite Field of size 3 Non-commutative rings behave as expected. These are the usual quaternions. :: + sage: # needs sage.combinat sage: R. = QuaternionAlgebra(-1, -1) sage: A = matrix(R, 2, [1,i,j,k]) sage: B = matrix(R, 2, [i,i,i,i]) @@ -1183,7 +1195,9 @@ cdef class Matrix(Matrix1): sage: A.elementwise_product(B) Traceback (most recent call last): ... - TypeError: no common canonical parent for objects with parents: 'Full MatrixSpace of 3 by 2 dense matrices over Rational Field' and 'Full MatrixSpace of 3 by 2 dense matrices over Finite Field of size 3' + TypeError: no common canonical parent for objects with parents: + 'Full MatrixSpace of 3 by 2 dense matrices over Rational Field' and + 'Full MatrixSpace of 3 by 2 dense matrices over Finite Field of size 3' We illustrate various combinations of sparse and dense matrices. The usual coercion rules apply:: @@ -1551,14 +1565,15 @@ cdef class Matrix(Matrix1): sage: Mx = M.pseudoinverse(algorithm="exact") sage: (Mx*M).norm() # huge error 11.5... - sage: Mx = M.pseudoinverse(algorithm="numpy") - sage: (Mx*M).norm() # still OK + sage: Mx = M.pseudoinverse(algorithm="numpy") # needs numpy + sage: (Mx * M).norm() # still OK 1.00... When multiplying the given matrix with the pseudoinverse, the result is symmetric for the ``exact`` algorithm or hermitian for the ``exactconj`` algorithm:: + sage: # needs sage.rings.number_field sage.symbolic sage: M = matrix(QQbar, 2, 2, [1, sqrt(-3), -sqrt(-3), 3]) sage: M * M.pseudoinverse() [ 0.2500000000000000? 0.4330127018922193?*I] @@ -1583,13 +1598,13 @@ cdef class Matrix(Matrix1): Numpy gives a strange answer due to rounding errors:: - sage: M.pseudoinverse(algorithm="numpy") # random + sage: M.pseudoinverse(algorithm="numpy") # random # needs numpy [-1286742750677287/643371375338643 1000799917193445/1000799917193444] [ 519646110850445/346430740566963 -300239975158034/600479950316067] Although it is not too far off:: - sage: (~M-M.pseudoinverse(algorithm="numpy")).norm() < 1e-14 + sage: (~M - M.pseudoinverse(algorithm="numpy")).norm() < 1e-14 # needs numpy True TESTS:: @@ -1705,7 +1720,7 @@ cdef class Matrix(Matrix1): These numbers are the coefficients of a modified Laguerre polynomial:: sage: x = polygen(QQ) - sage: factorial(8) * laguerre(8,-x) + sage: factorial(8) * laguerre(8,-x) # needs sage.symbolic x^8 + 64*x^7 + 1568*x^6 + 18816*x^5 + 117600*x^4 + 376320*x^3 + 564480*x^2 + 322560*x + 40320 @@ -1716,7 +1731,7 @@ cdef class Matrix(Matrix1): sage: A = identity_matrix(21) sage: A.rook_vector(complement=True)[-1] 18795307255050944540 - sage: Derangements(21).cardinality() + sage: Derangements(21).cardinality() # needs sage.combinat 18795307255050944540 An other example that we convert into a rook polynomial:: @@ -1740,7 +1755,7 @@ cdef class Matrix(Matrix1): [1, 8, 20, 16, 4] sage: A.rook_vector(algorithm="Ryser") [1, 8, 20, 16, 4] - sage: A.rook_vector(algorithm="Godsil") + sage: A.rook_vector(algorithm="Godsil") # needs sage.graphs [1, 8, 20, 16, 4] When the matrix `A` has more ones then zeroes it is usually faster @@ -1759,7 +1774,7 @@ cdef class Matrix(Matrix1): Ryser algorithms are available):: sage: R. = PolynomialRing(GF(5)) - sage: A = matrix(R,[[1,x,y],[x*y,x**2+y,0]]) + sage: A = matrix(R, [[1, x, y], [x*y, x**2+y, 0]]) sage: A.rook_vector(algorithm="ButeraPernici") [1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y] sage: A.rook_vector(algorithm="Ryser") @@ -1780,15 +1795,17 @@ cdef class Matrix(Matrix1): [1, 0, 0] sage: matrix([[0,0],[0,0]]).rook_vector(algorithm="Ryser") [1, 0, 0] - sage: matrix([[0,0],[0,0]]).rook_vector(algorithm="Godsil") + sage: matrix([[0,0],[0,0]]).rook_vector(algorithm="Godsil") # needs sage.graphs [1, 0, 0] sage: matrix.ones(4, 2).rook_vector("Ryser") [1, 8, 12] - sage: matrix.ones(4, 2).rook_vector("Godsil") + sage: matrix.ones(4, 2).rook_vector("Godsil") # needs sage.graphs [1, 8, 12] sage: m = matrix(ZZ,4,5) sage: m[:4,:4] = identity_matrix(4) - sage: for algorithm in ("Godsil","Ryser","ButeraPernici"): + sage: algos = ["Ryser", "ButeraPernici"] + sage: algos += ["Godsil"] + sage: for algorithm in algos: # needs sage.graphs ....: v = m.rook_vector(complement=True, use_complement=True, algorithm=algorithm) ....: if v != [1, 16, 78, 128, 53]: ....: print("ERROR with algorithm={} use_complement=True".format(algorithm)) @@ -1916,9 +1933,11 @@ cdef class Matrix(Matrix1): sage: k = GF(37) sage: P. = PolynomialRing(k) - sage: A = Matrix(P,2,3,[x0*x1, x0, x1, x2, x2 + 16, x2 + 5*x1 ]) - sage: A.minors(2) - [x0*x1*x2 + 16*x0*x1 - x0*x2, 5*x0*x1^2 + x0*x1*x2 - x1*x2, 5*x0*x1 + x0*x2 - x1*x2 - 16*x1] + sage: A = Matrix(P, 2, 3, [x0*x1, x0, x1, x2, x2 + 16, x2 + 5*x1]) + sage: A.minors(2) # needs sage.rings.finite_rings + [x0*x1*x2 + 16*x0*x1 - x0*x2, + 5*x0*x1^2 + x0*x1*x2 - x1*x2, + 5*x0*x1 + x0*x2 - x1*x2 - 16*x1] This test addresses an issue raised at :trac:`20512`:: @@ -2013,16 +2032,16 @@ cdef class Matrix(Matrix1): TESTS:: - sage: A = matrix(5, 5, [next_prime(i^2) for i in range(25)]) - sage: B = MatrixSpace(ZZ['x'], 5, 5)(A) - sage: A.det() - B.det() + sage: A = matrix(5, 5, [next_prime(i^2) for i in range(25)]) # needs sage.libs.pari + sage: B = MatrixSpace(ZZ['x'], 5, 5)(A) # needs sage.libs.pari + sage: A.det() - B.det() # needs sage.libs.pari 0 We verify that :trac:`5569` is resolved (otherwise the following would hang for hours):: - sage: d = random_matrix(GF(next_prime(10^20)),50).det() - sage: d = random_matrix(Integers(10^50),50).det() + sage: d = random_matrix(GF(next_prime(10^20)), 50).det() # needs sage.rings.finite_rings + sage: d = random_matrix(Integers(10^50), 50).det() # needs sage.rings.finite_rings We verify that :trac:`7704` is resolved:: @@ -2036,12 +2055,17 @@ cdef class Matrix(Matrix1): sage: A = GF(2)['x,y,z'] sage: A.inject_variables() Defining x, y, z - sage: R = A.quotient(x^2 + 1).quotient(y^2 + 1).quotient(z^2 + 1) - sage: R.inject_variables() + sage: R = A.quotient(x^2 + 1).quotient(y^2 + 1).quotient(z^2 + 1) # needs sage.rings.finite_rings + sage: R.inject_variables() # needs sage.rings.finite_rings Defining xbarbarbar, ybarbarbar, zbarbarbar - sage: M = matrix([[1,1,1,1],[xbarbarbar,ybarbarbar,1,1],[0,1,zbarbarbar,1],[xbarbarbar,zbarbarbar,1,1]]) - sage: M.determinant() - xbarbarbar*ybarbarbar*zbarbarbar + xbarbarbar*ybarbarbar + xbarbarbar*zbarbarbar + ybarbarbar*zbarbarbar + xbarbarbar + ybarbarbar + zbarbarbar + 1 + sage: M = matrix([[1, 1, 1, 1], # needs sage.rings.finite_rings + ....: [xbarbarbar, ybarbarbar, 1, 1], + ....: [0, 1, zbarbarbar, 1], + ....: [xbarbarbar, zbarbarbar, 1, 1]]) + sage: M.determinant() # needs sage.rings.finite_rings + xbarbarbar*ybarbarbar*zbarbarbar + xbarbarbar*ybarbarbar + + xbarbarbar*zbarbarbar + ybarbarbar*zbarbarbar + xbarbarbar + + ybarbarbar + zbarbarbar + 1 Check that the determinant is computed from a cached charpoly properly:: @@ -2203,14 +2227,14 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(SR, 2, lambda i, j: f'a{i}{j}'); A # optional - sage.symbolic + sage: A = matrix(SR, 2, lambda i, j: f'a{i}{j}'); A # needs sage.symbolic [a00 a01] [a10 a11] - sage: A.quantum_determinant() # optional - sage.symbolic + sage: A.quantum_determinant() # needs sage.symbolic -a01*a10*q + a00*a11 - sage: A = matrix(SR, 3, lambda i, j: f'a{i}{j}') # optional - sage.symbolic - sage: A.quantum_determinant() # optional - sage.symbolic + sage: A = matrix(SR, 3, lambda i, j: f'a{i}{j}') # needs sage.symbolic + sage: A.quantum_determinant() # needs sage.symbolic -a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2 + (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22 @@ -2414,7 +2438,7 @@ cdef class Matrix(Matrix1): In that case, the definition by perfect matchings is used instead:: - sage: A.pfaffian() + sage: A.pfaffian() # needs sage.combinat sage.rings.finite_rings 2 """ @@ -2499,7 +2523,7 @@ cdef class Matrix(Matrix1): ....: (2, -1, 0, 0, 1, 5/2), ....: (-2, 1, -3/2, -1, 0, 1/2), ....: (1/2, -3/2, -1, -5/2, -1/2, 0)]) - sage: A._pf_perfect_matchings() + sage: A._pf_perfect_matchings() # needs sage.combinat -1/2 """ @@ -2555,9 +2579,9 @@ cdef class Matrix(Matrix1): TESTS:: - sage: A = random_matrix(ZZ[x], 6) + sage: A = random_matrix(ZZ['x'], 6) sage: A = A - A.transpose() - sage: A.pfaffian(algorithm='bfl') == A._pf_perfect_matchings() + sage: A.pfaffian(algorithm='bfl') == A._pf_perfect_matchings() # needs sage.combinat True """ @@ -2608,7 +2632,8 @@ cdef class Matrix(Matrix1): [3 4 0] [1 2 3] sage: parent(m.apply_morphism(phi)) - Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5 + Full MatrixSpace of 3 by 3 dense matrices + over Finite Field of size 5 We apply a morphism to a matrix over a polynomial ring:: @@ -2650,14 +2675,15 @@ cdef class Matrix(Matrix1): EXAMPLES:: sage: m = matrix(ZZ, 3, 3, range(9)) - sage: k. = GF(9) + sage: k. = GF(9) # needs sage.rings.finite_rings sage: f = lambda x: k(x) - sage: n = m.apply_map(f); n + sage: n = m.apply_map(f); n # needs sage.rings.finite_rings [0 1 2] [0 1 2] [0 1 2] - sage: n.parent() - Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 + sage: n.parent() # needs sage.rings.finite_rings + Full MatrixSpace of 3 by 3 dense matrices + over Finite Field in a of size 3^2 In this example, we explicitly specify the codomain. @@ -2665,12 +2691,13 @@ cdef class Matrix(Matrix1): sage: s = GF(3) sage: f = lambda x: s(x) - sage: n = m.apply_map(f, k); n + sage: n = m.apply_map(f, k); n # needs sage.rings.finite_rings [0 1 2] [0 1 2] [0 1 2] - sage: n.parent() - Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 + sage: n.parent() # needs sage.rings.finite_rings + Full MatrixSpace of 3 by 3 dense matrices + over Finite Field in a of size 3^2 If self is subdivided, the result will be as well:: @@ -2763,7 +2790,7 @@ cdef class Matrix(Matrix1): sage: a = matrix(QQ, 2,2, [1,2,3,4]); a [1 2] [3 4] - sage: a.characteristic_polynomial('T') + sage: a.characteristic_polynomial('T') # needs sage.libs.pari T^2 - 5*T - 2 """ return self.charpoly(*args, **kwds) @@ -2775,9 +2802,9 @@ cdef class Matrix(Matrix1): EXAMPLES:: sage: a = matrix(QQ, 4, 4, range(16)) - sage: a.minimal_polynomial('z') + sage: a.minimal_polynomial('z') # needs sage.libs.pari z^3 - 30*z^2 - 80*z - sage: a.minpoly() + sage: a.minpoly() # needs sage.libs.pari x^3 - 30*x^2 - 80*x """ return self.minpoly(var, **kwds) @@ -2792,7 +2819,8 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(GF(9,'c'), 4, [1, 1, 0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) + sage: # needs sage.rings.finite_rings + sage: A = matrix(GF(9, 'c'), 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) sage: factor(A.minpoly()) (x + 1) * (x + 2)^2 sage: A.minpoly()(A) == 0 @@ -2803,7 +2831,7 @@ cdef class Matrix(Matrix1): The default variable name is `x`, but you can specify another name:: - sage: factor(A.minpoly('y')) + sage: factor(A.minpoly('y')) # needs sage.rings.finite_rings (y + 1) * (y + 2)^2 """ f = self.fetch('minpoly') @@ -2850,8 +2878,8 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: a = matrix([[1,2],[3,4]]) - sage: a._test_minpoly() + sage: a = matrix([[1,2], [3,4]]) + sage: a._test_minpoly() # needs sage.libs.pari """ if self.nrows() == self.ncols() and self.base_ring().is_exact(): tester = self._tester(**options) @@ -2911,8 +2939,8 @@ cdef class Matrix(Matrix1): An example over `\QQ`:: - sage: A = MatrixSpace(QQ,3)(range(9)) - sage: A.charpoly('x') + sage: A = MatrixSpace(QQ, 3)(range(9)) + sage: A.charpoly('x') # needs sage.libs.pari x^3 - 12*x^2 - 18*x sage: A.trace() 12 @@ -2923,7 +2951,7 @@ cdef class Matrix(Matrix1): polynomial ring `\ZZ[a]`:: sage: R. = PolynomialRing(ZZ) - sage: M = MatrixSpace(R,2)([a,1, a,a+1]); M + sage: M = MatrixSpace(R, 2)([a,1, a,a+1]); M [ a 1] [ a a + 1] sage: f = M.charpoly('x'); f @@ -2956,6 +2984,7 @@ cdef class Matrix(Matrix1): Here is an example over a number field:: + sage: # needs sage.rings.number_field sage: x = QQ['x'].gen() sage: K. = NumberField(x^2 - 2) sage: m = matrix(K, [[a-1, 2], [a, a+1]]) @@ -2977,7 +3006,7 @@ cdef class Matrix(Matrix1): sage: R. = QQ[] sage: S. = R.quo((b^3)) - sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]]) + sage: A = matrix(S, [[x*y^2, 2*x], [2, x^10*y]]) sage: A [ x*y^2 2*x] [ 2 x^10*y] @@ -2997,6 +3026,7 @@ cdef class Matrix(Matrix1): and crash if an empty dictionary was cached. We don't cache dictionaries anymore, but this test should still pass:: + sage: # needs sage.rings.padics sage: z = Zp(p=5) sage: A = matrix(z, [ [3 + O(5^1), 4 + O(5^1), 4 + O(5^1)], ....: [2*5^2 + O(5^3), 2 + O(5^1), 1 + O(5^1)], @@ -3114,8 +3144,8 @@ cdef class Matrix(Matrix1): Test that :trac:`27937` is fixed:: - sage: R = FreeAbelianMonoid('u,v').algebra(QQ) - sage: matrix(4, 4, lambda i, j: R.an_element())._charpoly_df() + sage: R = FreeAbelianMonoid('u,v').algebra(QQ) # needs sage.combinat + sage: matrix(4, 4, lambda i, j: R.an_element())._charpoly_df() # needs sage.combinat B[1]*x^4 - 4*B[u]*x^3 .. NOTE:: @@ -3224,12 +3254,12 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,3) - sage: A = M([1,9,-7,4/5,4,3,6,4,3]) - sage: A.fcp() + sage: M = MatrixSpace(QQ, 3, 3) + sage: A = M([1,9,-7, 4/5,4,3, 6,4,3]) + sage: A.fcp() # needs sage.libs.pari x^3 - 8*x^2 + 209/5*x - 286 sage: A = M([3, 0, -2, 0, -2, 0, 0, 0, 0]) - sage: A.fcp('T') + sage: A.fcp('T') # needs sage.libs.pari (T - 3) * T * (T + 2) """ return self.charpoly(var).factor() @@ -3274,9 +3304,10 @@ cdef class Matrix(Matrix1): Here's an example involving a cyclotomic field:: + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(3) - sage: M = MatrixSpace(K,3,sparse=True) - sage: A = M([(1+z)/3,(2+z)/3,z/3,1,1+z,-2,1,5,-1+z]) + sage: M = MatrixSpace(K, 3, sparse=True) + sage: A = M([(1+z)/3, (2+z)/3, z/3, 1, 1+z, -2, 1, 5, -1+z]) sage: print(A) [1/3*z + 1/3 1/3*z + 2/3 1/3*z] [ 1 z + 1 -2] @@ -3557,7 +3588,7 @@ cdef class Matrix(Matrix1): Z^3 - 12*Z^2 - 18*Z sage: matrix(ZZ,3,3,range(9))._charpoly_hessenberg('Z') Z^3 - 12*Z^2 - 18*Z - sage: matrix(GF(7),3,3,range(9))._charpoly_hessenberg('Z') + sage: matrix(GF(7), 3, 3, range(9))._charpoly_hessenberg('Z') Z^3 + 2*Z^2 + 3*Z sage: matrix(QQ['x'],3,3,range(9))._charpoly_hessenberg('Z') Z^3 - 12*Z^2 - 18*Z @@ -3684,7 +3715,7 @@ cdef class Matrix(Matrix1): OUTPUT: - Returns a pair. First item is the string 'pivot-pari-numberfield' + Returns a pair. First item is the string ``'pivot-pari-numberfield'`` that identifies the nature of the basis vectors. Second item is a matrix whose rows are a basis for the right kernel, @@ -3692,22 +3723,24 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.libs.pari sage.rings.number_field sage: Q = QuadraticField(-7) sage: a = Q.gen(0) - sage: A = matrix(Q, [[ 2, 5-a, 15-a], - ....: [2+a, a, -7 + 5*a]]) + sage: A = matrix(Q, [[ 2, 5 - a, 15 - a], + ....: [2 + a, a, -7 + 5*a]]) sage: result = A._right_kernel_matrix_over_number_field() sage: result[0] 'pivot-pari-numberfield' sage: P = result[1]; P [-a -3 1] - sage: A*P.transpose() == zero_matrix(Q, 2, 1) + sage: A * P.transpose() == zero_matrix(Q, 2, 1) True TESTS: We test some trivial cases. :: + sage: # needs sage.libs.pari sage.rings.number_field sage: Q = QuadraticField(-7) sage: A = matrix(Q, 0, 2) sage: A._right_kernel_matrix_over_number_field()[1] @@ -3715,7 +3748,9 @@ cdef class Matrix(Matrix1): [0 1] sage: A = matrix(Q, 2, 0) sage: A._right_kernel_matrix_over_number_field()[1].parent() - Full MatrixSpace of 0 by 0 dense matrices over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I + Full MatrixSpace of 0 by 0 dense matrices + over Number Field in a with defining polynomial x^2 + 7 + with a = 2.645751311064591?*I sage: A = zero_matrix(Q, 4, 3) sage: A._right_kernel_matrix_over_number_field()[1] [1 0 0] @@ -3746,6 +3781,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.rings.number_field sage: C = CyclotomicField(14) sage: a = C.gen(0) sage: A = matrix(C, 3, 4, [[ 1, a, 1+a, a^3+a^5], @@ -3757,13 +3793,14 @@ cdef class Matrix(Matrix1): sage: P = result[1]; P [ -1 -1 1 0] [-zeta14^3 -zeta14^4 0 1] - sage: A*P.transpose() == zero_matrix(C, 3, 2) + sage: A * P.transpose() == zero_matrix(C, 3, 2) True TESTS: We test some trivial cases. :: + sage: # needs sage.rings.number_field sage: C = CyclotomicField(14) sage: A = matrix(C, 0, 2) sage: A._right_kernel_matrix_over_field()[1] @@ -3771,7 +3808,8 @@ cdef class Matrix(Matrix1): [0 1] sage: A = matrix(C, 2, 0) sage: A._right_kernel_matrix_over_field()[1].parent() - Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 14 and degree 6 + Full MatrixSpace of 0 by 0 dense matrices + over Cyclotomic Field of order 14 and degree 6 sage: A = zero_matrix(C, 4, 3) sage: A._right_kernel_matrix_over_field()[1] [1 0 0] @@ -3892,7 +3930,8 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(Zmod(24480), [[1,2,3,4,5],[7,7,7,7,7]]) + sage: # needs sage.libs.pari + sage: A = matrix(Zmod(24480), [[1,2,3,4,5], [7,7,7,7,7]]) sage: result = A._right_kernel_matrix_over_integer_mod_ring() sage: result[0] 'computed-pari-matkermod' @@ -3900,7 +3939,7 @@ cdef class Matrix(Matrix1): [ 1 24478 1 0 0] [ 2 24477 0 1 0] [ 3 24476 0 0 1] - sage: A*P.transpose() == 0 + sage: A * P.transpose() == 0 True """ R = self.base_ring() @@ -4053,6 +4092,7 @@ cdef class Matrix(Matrix1): basis, so the `basis` keywords 'computed' and 'pivot' will return the same results. :: + sage: # needs sage.rings.number_field sage: Q = QuadraticField(-7) sage: a = Q.gen(0) sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a], @@ -4062,10 +4102,10 @@ cdef class Matrix(Matrix1): [ -2 -a - 1 0 1] sage: A*C.transpose() == zero_matrix(Q, 2, 2) True - sage: P = A.right_kernel_matrix(algorithm='pari', basis='pivot'); P + sage: P = A.right_kernel_matrix(algorithm='pari', basis='pivot'); P # needs sage.libs.pari [ -a -3 1 0] [ -2 -a - 1 0 1] - sage: A*P.transpose() == zero_matrix(Q, 2, 2) + sage: A*P.transpose() == zero_matrix(Q, 2, 2) # needs sage.libs.pari True sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E [ 1 0 7/88*a + 3/88 -3/176*a - 39/176] @@ -4077,9 +4117,10 @@ cdef class Matrix(Matrix1): code for matrices over any field. The basis vectors as computed are in pivot format. :: + sage: # needs sage.rings.number_field sage: Q = QuadraticField(-7) sage: a = Q.gen(0) - sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]]) + sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a], [2+a, a, -7 + 5*a, -3+3*a]]) sage: G = A.right_kernel_matrix(algorithm='generic', basis='computed'); G [ -a -3 1 0] [ -2 -a - 1 0 1] @@ -4089,16 +4130,18 @@ cdef class Matrix(Matrix1): We check that number fields are handled by the right routine as part of typical right kernel computation. :: + sage: # needs sage.rings.number_field sage: Q = QuadraticField(-7) sage: a = Q.gen(0) - sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]]) + sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a], [2+a, a, -7 + 5*a, -3+3*a]]) sage: set_verbose(1) sage: A.right_kernel(algorithm='default') verbose ... verbose 1 () computing right kernel matrix over a number field for 2x4 matrix verbose 1 () done computing right kernel matrix over a number field for 2x4 matrix ... - Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I + Vector space of degree 4 and dimension 2 over + Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I Basis matrix: [ 1 0 7/88*a + 3/88 -3/176*a - 39/176] [ 0 1 -1/88*a - 13/88 13/176*a - 7/176] @@ -4127,9 +4170,9 @@ cdef class Matrix(Matrix1): keywords, 'pluq', 'default' and unspecified, all have the same effect as there is no optional behavior. :: - sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0], - ....: [1, 0, 0, 0, 1, 1,], - ....: [1, 0, 0, 0, 1, 1]]) + sage: A = matrix(GF(2), [[0, 1, 1, 0, 0, 0], + ....: [1, 0, 0, 0, 1, 1,], + ....: [1, 0, 0, 0, 1, 1]]) sage: P = A.right_kernel_matrix(algorithm='generic', basis='pivot'); P [0 1 1 0 0 0] [0 0 0 1 0 0] @@ -4152,9 +4195,9 @@ cdef class Matrix(Matrix1): We test that the mod 2 code is called for matrices over GF(2). :: - sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0], - ....: [1, 0, 0, 0, 1, 1,], - ....: [1, 0, 0, 0, 1, 1]]) + sage: A = matrix(GF(2), [[0, 1, 1, 0, 0, 0], + ....: [1, 0, 0, 0, 1, 1,], + ....: [1, 0, 0, 0, 1, 1]]) sage: set_verbose(1) sage: A.right_kernel(algorithm='default') verbose ... @@ -4175,6 +4218,7 @@ cdef class Matrix(Matrix1): will compute a set of basis vectors in the pivot format. These could be returned as a basis in echelon form. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^2) sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5], ....: [ a, a^4, a+a^4, a^4+a^8], @@ -4214,6 +4258,7 @@ cdef class Matrix(Matrix1): We test that the generic code is called for matrices over fields, lacking any more specific routine. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^2) sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5], ....: [ a, a^4, a+a^4, a^4+a^8], @@ -4259,6 +4304,7 @@ cdef class Matrix(Matrix1): sage: A*X.transpose() == zero_matrix(ZZ, 4, 3) True + sage: # needs sage.libs.pari sage: X = A.right_kernel_matrix(algorithm='pari', basis='computed'); X [ 3 1 -5 -7 -2 3 2] [ 3 1 2 5 -5 2 -6] @@ -4333,7 +4379,8 @@ cdef class Matrix(Matrix1): sage: A.right_kernel_matrix() Traceback (most recent call last): ... - ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal + ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of + Univariate Polynomial Ring in x over Integer Ring not principal We test that the domain code is called for domains that lack any extra structure. :: @@ -4347,7 +4394,8 @@ cdef class Matrix(Matrix1): verbose 1 () computing right kernel matrix over a domain for 2x3 matrix verbose 1 () done computing right kernel matrix over a domain for 2x3 matrix ... - Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field + Free module of degree 3 and rank 1 over + Univariate Polynomial Ring in y over Rational Field Echelon basis matrix: [-1 -y 1] sage: set_verbose(0) @@ -4698,16 +4746,18 @@ cdef class Matrix(Matrix1): Over an arbitrary field, with two basis formats. Same vector space, different bases. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^2) sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5], ....: [ a, a^4, a+a^4, a^4+a^8], ....: [a^2, a^6, a^2+a^6, a^5+a^10]]) sage: K = A.right_kernel(); K - Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2 + Vector space of degree 4 and dimension 2 + over Finite Field in a of size 5^2 Basis matrix: [ 1 0 3*a + 4 2*a + 2] [ 0 1 2*a 3*a + 3] - sage: A*K.basis_matrix().transpose() == zero_matrix(F, 3, 2) + sage: A * K.basis_matrix().transpose() == zero_matrix(F, 3, 2) True In the following test, we have to force usage of @@ -4718,8 +4768,9 @@ cdef class Matrix(Matrix1): sage: from sage.matrix.matrix_generic_dense import Matrix_generic_dense sage: B = Matrix_generic_dense(A.parent(), A.list(), False, False) - sage: P = B.right_kernel(basis = 'pivot'); P - Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2 + sage: P = B.right_kernel(basis='pivot'); P # needs sage.rings.finite_rings + Vector space of degree 4 and dimension 2 + over Finite Field in a of size 5^2 User basis matrix: [ 4 4 1 0] [ a + 2 3*a + 3 0 1] @@ -4727,32 +4778,36 @@ cdef class Matrix(Matrix1): If the optional meataxe package is installed, we again have to make sure to work with a copy of B that has the same type as ``P.basis_matrix()``:: - sage: B.parent()(B.list())*P.basis_matrix().transpose() == zero_matrix(F, 3, 2) + sage: (B.parent()(B.list()) * P.basis_matrix().transpose() # needs sage.rings.finite_rings + ....: == zero_matrix(F, 3, 2)) True - sage: K == P + sage: K == P # needs sage.rings.finite_rings True Over number fields, PARI is used by default, but general-purpose code can be requested. Same vector space, same bases, different code.:: + sage: # needs sage.rings.number_field sage: Q = QuadraticField(-7) sage: a = Q.gen(0) - sage: A = matrix(Q, [[ 2, 5-a, 15-a, 16+4*a], - ....: [2+a, a, -7 + 5*a, -3+3*a]]) + sage: A = matrix(Q, [[ 2, 5 - a, 15 - a, 16 + 4*a], + ....: [2 + a, a, -7 + 5*a, -3 + 3*a]]) sage: K = A.right_kernel(algorithm='default'); K - Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I + Vector space of degree 4 and dimension 2 + over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I Basis matrix: [ 1 0 7/88*a + 3/88 -3/176*a - 39/176] [ 0 1 -1/88*a - 13/88 13/176*a - 7/176] - sage: A*K.basis_matrix().transpose() == zero_matrix(Q, 2, 2) + sage: A * K.basis_matrix().transpose() == zero_matrix(Q, 2, 2) True sage: B = copy(A) sage: G = A.right_kernel(algorithm='generic'); G - Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I + Vector space of degree 4 and dimension 2 + over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I Basis matrix: [ 1 0 7/88*a + 3/88 -3/176*a - 39/176] [ 0 1 -1/88*a - 13/88 13/176*a - 7/176] - sage: B*G.basis_matrix().transpose() == zero_matrix(Q, 2, 2) + sage: B * G.basis_matrix().transpose() == zero_matrix(Q, 2, 2) True sage: K == G True @@ -5131,7 +5186,7 @@ cdef class Matrix(Matrix1): [ 0 2 0 -1] [ 0 1 -2 0] [ 0 2 0 -2] - sage: t.fcp() + sage: t.fcp() # needs sage.libs.pari (x - 39) * (x + 2) * (x^2 - 2) sage: s = (t-39)*(t^2-2) sage: V = s.kernel(); V @@ -5227,11 +5282,12 @@ cdef class Matrix(Matrix1): An example over a bigger ring:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: L. = NumberField(x^2 - x + 2) # optional - sage.rings.number_field - sage: OL = L.ring_of_integers() # optional - sage.rings.number_field - sage: A = matrix(L, 2, [1, w/2]) # optional - sage.rings.number_field - sage: A.integer_kernel(OL) # optional - sage.rings.number_field + sage: L. = NumberField(x^2 - x + 2) + sage: OL = L.ring_of_integers() + sage: A = matrix(L, 2, [1, w/2]) + sage: A.integer_kernel(OL) Free module of degree 2 and rank 1 over Maximal Order in Number Field in w with defining polynomial x^2 - x + 2 Echelon basis matrix: @@ -5445,23 +5501,23 @@ cdef class Matrix(Matrix1): [198 209 220 231 242 253] [264 275 286 297 308 319] [330 341 352 363 374 385] - sage: A.decomposition() - [ - (Ambient free module of rank 4 over the principal ideal domain Integer Ring, True) - ] - sage: B.decomposition() - [ - (Vector space of degree 6 and dimension 2 over Rational Field - Basis matrix: - [ 1 0 -1 -2 -3 -4] - [ 0 1 2 3 4 5], True), - (Vector space of degree 6 and dimension 4 over Rational Field - Basis matrix: - [ 1 0 0 0 -5 4] - [ 0 1 0 0 -4 3] - [ 0 0 1 0 -3 2] - [ 0 0 0 1 -2 1], False) - ] + sage: A.decomposition() # needs sage.libs.pari + [ (Ambient free module of rank 4 + over the principal ideal domain Integer Ring, + True) ] + sage: B.decomposition() # needs sage.libs.pari + [ (Vector space of degree 6 and dimension 2 over Rational Field + Basis matrix: + [ 1 0 -1 -2 -3 -4] + [ 0 1 2 3 4 5], + True), + (Vector space of degree 6 and dimension 4 over Rational Field + Basis matrix: + [ 1 0 0 0 -5 4] + [ 0 1 0 0 -4 3] + [ 0 0 1 0 -3 2] + [ 0 0 0 1 -2 1], + False) ] """ if algorithm == 'kernel' or self.base_ring() not in _Fields: return self._decomposition_using_kernels(is_diagonalizable = is_diagonalizable, dual=dual) @@ -5634,26 +5690,25 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.libs.pari sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]); t [ 3 0 -2] [ 0 -2 0] [ 0 0 0] - sage: t.fcp('X') # factored charpoly + sage: t.fcp('X') # factored charpoly (X - 3) * X * (X + 2) - sage: v = kernel(t*(t+2)); v # an invariant subspace + sage: v = kernel(t*(t+2)); v # an invariant subspace Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [0 1 0] [0 0 1] sage: D = t.decomposition_of_subspace(v); D - [ - (Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [0 0 1], True), - (Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [0 1 0], True) - ] + [ (Vector space of degree 3 and dimension 1 over Rational Field + Basis matrix: [0 0 1], + True), + (Vector space of degree 3 and dimension 1 over Rational Field + Basis matrix: [0 1 0], + True) ] sage: t.restrict(D[0][0]) [0] sage: t.restrict(D[1][0]) @@ -5661,25 +5716,30 @@ cdef class Matrix(Matrix1): We do a decomposition over ZZ:: - sage: a = matrix(ZZ,6,[0, 0, -2, 0, 2, 0, 2, -4, -2, 0, 2, 0, 0, 0, -2, -2, 0, 0, 2, 0, -2, -4, 2, -2, 0, 2, 0, -2, -2, 0, 0, 2, 0, -2, 0, 0]) - sage: a.decomposition_of_subspace(ZZ^6) - [ - (Free module of degree 6 and rank 2 over Integer Ring - Echelon basis matrix: - [ 1 0 1 -1 1 -1] - [ 0 1 0 -1 2 -1], False), - (Free module of degree 6 and rank 4 over Integer Ring - Echelon basis matrix: - [ 1 0 -1 0 1 0] - [ 0 1 0 0 0 0] - [ 0 0 0 1 0 0] - [ 0 0 0 0 0 1], False) - ] + sage: a = matrix(ZZ, 6, [0, 0, -2, 0, 2, 0, + ....: 2, -4, -2, 0, 2, 0, + ....: 0, 0, -2, -2, 0, 0, + ....: 2, 0, -2, -4, 2, -2, + ....: 0, 2, 0, -2, -2, 0, + ....: 0, 2, 0, -2, 0, 0]) + sage: a.decomposition_of_subspace(ZZ^6) # needs sage.libs.pari + [ (Free module of degree 6 and rank 2 over Integer Ring + Echelon basis matrix: + [ 1 0 1 -1 1 -1] + [ 0 1 0 -1 2 -1], + False), + (Free module of degree 6 and rank 4 over Integer Ring + Echelon basis matrix: + [ 1 0 -1 0 1 0] + [ 0 1 0 0 0 0] + [ 0 0 0 1 0 0] + [ 0 0 0 0 0 1], + False) ] TESTS:: sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]) - sage: t.decomposition_of_subspace(v, check_restrict = False) == t.decomposition_of_subspace(v) + sage: t.decomposition_of_subspace(v, check_restrict=False) == t.decomposition_of_subspace(v) # needs sage.libs.pari True """ if not sage.modules.free_module.is_FreeModule(M): @@ -5953,7 +6013,7 @@ cdef class Matrix(Matrix1): [6 7 8] sage: t.wiedemann(0) x^2 - 12*x - 18 - sage: t.charpoly() + sage: t.charpoly() # needs sage.libs.pari x^3 - 12*x^2 - 18*x """ i = int(i); t=int(t) @@ -5969,7 +6029,7 @@ cdef class Matrix(Matrix1): # sequence corresponding to the 0-th entries of the iterates, # then the 1-th entries, etc. if t == 0: - R = list(xrange(n)) + R = list(range(n)) else: R = [t] for i in R: @@ -5990,14 +6050,14 @@ cdef class Matrix(Matrix1): INPUT: - - ``format`` - ``None``, ``'all'`` or ``'galois'`` + - ``format`` -- ``None``, ``'all'`` or ``'galois'`` OUTPUT: Any format except ``None`` is just passed through. When the - format is ``None`` a choice is made about the style of the output. + format is ``None``, a choice is made about the style of the output. If there is an algebraically closed field that will contain the - possible eigenvalues, then 'all" of the eigenspaces are given. + possible eigenvalues, then ``'all'`` of the eigenspaces are given. However if this is not the case, then only one eigenspace is output for each irreducible factor of the characteristic polynomial. @@ -6017,17 +6077,17 @@ cdef class Matrix(Matrix1): of finite fields:: sage: A = matrix(QQ, 2, range(4)) - sage: A._eigenspace_format(None) == 'all' + sage: A._eigenspace_format(None) == 'all' # needs sage.rings.number_field True sage: B = matrix(GF(13), 2, range(4)) - sage: B._eigenspace_format(None) + sage: B._eigenspace_format(None) # needs sage.rings.finite_rings 'all' Subrings are promoted to fraction fields and then checked for the existence of algebraic closures. :: sage: A = matrix(ZZ, 2, range(4)) - sage: A._eigenspace_format(None) == 'all' + sage: A._eigenspace_format(None) == 'all' # needs sage.rings.number_field True """ if format not in [None, 'all', 'galois']: @@ -6049,48 +6109,48 @@ cdef class Matrix(Matrix1): r""" Compute the left eigenspaces of a matrix. - Note that ``eigenspaces_left()`` and ``left_eigenspaces()`` + Note that :meth:`eigenspaces_left` and :meth:`left_eigenspaces` are identical methods. Here "left" refers to the eigenvectors being placed to the left of the matrix. INPUT: - - ``self`` - a square matrix over an exact field. For inexact + - ``self`` -- a square matrix over an exact field. For inexact matrices consult the numerical or symbolic matrix classes. - - ``format`` - default: ``None`` + - ``format`` -- one of: - - ``'all'`` - attempts to create every eigenspace. This will + - ``'all'`` -- Attempts to create every eigenspace. This will always be possible for matrices with rational entries. - - ``'galois'`` - for each irreducible factor of the characteristic + - ``'galois'`` -- For each irreducible factor of the characteristic polynomial, a single eigenspace will be output for a single root/eigenvalue for the irreducible factor. - - ``None`` - Uses the 'all' format if the base ring is contained + - ``None`` (default) -- Uses the ``'all'`` format if the base ring is contained in an algebraically closed field which is implemented. - Otherwise, uses the 'galois' format. + Otherwise, uses the ``'galois'`` format. - - ``var`` - default: 'a' - variable name used to + - ``var`` -- string (default: ``'a'``); variable name used to represent elements of the root field of each irreducible factor of the characteristic polynomial. - If var='a', then the root fields will be in terms of - a0, a1, a2, ...., where the numbering runs across all + If ``var='a'``, then the root fields will be in terms of + ``a0, a1, a2, ...``, where the numbering runs across all the irreducible factors of the characteristic polynomial, even for linear factors. - - ``algebraic_multiplicity`` - default: False - whether or - not to include the algebraic multiplicity of each eigenvalue + - ``algebraic_multiplicity`` -- (boolean, default: ``False``); + whether to include the algebraic multiplicity of each eigenvalue in the output. See the discussion below. OUTPUT: - If algebraic_multiplicity=False, return a list of pairs (e, V) - where e is an eigenvalue of the matrix, and V is the corresponding + If ``algebraic_multiplicity=False``, return a list of pairs `(e, V)` + where `e` is an eigenvalue of the matrix, and `V` is the corresponding left eigenspace. For Galois conjugates of eigenvalues, there may be just one representative eigenspace, depending on the ``format`` keyword. - If algebraic_multiplicity=True, return a list of triples (e, V, n) - where e and V are as above and n is the algebraic multiplicity of + If ``algebraic_multiplicity=True``, return a list of triples `(e, V, n)` + where `e` and `V` are as above and `n` is the algebraic multiplicity of the eigenvalue. .. warning:: @@ -6102,46 +6162,53 @@ cdef class Matrix(Matrix1): EXAMPLES: We compute the left eigenspaces of a `3\times 3` - rational matrix. First, we request `all` of the eigenvalues, - so the results are in the field of algebraic numbers, `QQbar`. + rational matrix. First, we request ``'all'`` of the eigenvalues, + so the results are in the field of algebraic numbers, ``QQbar``. Then we request just one eigenspace per irreducible factor of - the characteristic polynomial with the `galois` keyword. :: + the characteristic polynomial with ``format='galois'``. :: - sage: A = matrix(QQ,3,3,range(9)); A + sage: A = matrix(QQ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] - sage: es = A.eigenspaces_left(format='all'); es - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1]), - (-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field - User basis matrix: - [ 1 0.3101020514433644? -0.3797958971132713?]), - (13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field - User basis matrix: - [ 1 1.289897948556636? 1.579795897113272?]) - ] - + sage: es = A.eigenspaces_left(format='all'); es # needs sage.rings.number_field + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1]), + (-1.348469228349535?, + Vector space of degree 3 and dimension 1 over Algebraic Field + User basis matrix: + [ 1 0.3101020514433644? -0.3797958971132713?]), + (13.34846922834954?, + Vector space of degree 3 and dimension 1 over Algebraic Field + User basis matrix: + [ 1 1.289897948556636? 1.579795897113272?]) ] + + sage: # needs sage.rings.number_field sage: es = A.eigenspaces_left(format='galois'); es - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1]), - (a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 - User basis matrix: - [ 1 1/15*a1 + 2/5 2/15*a1 - 1/5]) - ] - sage: es = A.eigenspaces_left(format='galois', algebraic_multiplicity=True); es - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1], 1), - (a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 - User basis matrix: - [ 1 1/15*a1 + 2/5 2/15*a1 - 1/5], 1) - ] + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1]), + (a1, + Vector space of degree 3 and dimension 1 over + Number Field in a1 with defining polynomial x^2 - 12*x - 18 + User basis matrix: + [ 1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ] + sage: es = A.eigenspaces_left(format='galois', + ....: algebraic_multiplicity=True); es + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1], + 1), + (a1, + Vector space of degree 3 and dimension 1 over + Number Field in a1 with defining polynomial x^2 - 12*x - 18 + User basis matrix: + [ 1 1/15*a1 + 2/5 2/15*a1 - 1/5], + 1) ] sage: e, v, n = es[0]; v = v.basis()[0] sage: delta = e*v - v*A sage: abs(abs(delta)) < 1e-10 @@ -6149,24 +6216,26 @@ cdef class Matrix(Matrix1): The same computation, but with implicit base change to a field. :: - sage: A = matrix(ZZ,3,3,range(9)); A + sage: A = matrix(ZZ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] - sage: A.eigenspaces_left(format='galois') - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1]), - (a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 - User basis matrix: - [ 1 1/15*a1 + 2/5 2/15*a1 - 1/5]) - ] + sage: A.eigenspaces_left(format='galois') # needs sage.rings.number_field + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1]), + (a1, + Vector space of degree 3 and dimension 1 over + Number Field in a1 with defining polynomial x^2 - 12*x - 18 + User basis matrix: + [ 1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ] We compute the left eigenspaces of the matrix of the Hecke operator `T_2` on level 43 modular symbols, both with all eigenvalues (the default) and with one subspace per factor. :: + sage: # needs sage.modular sage: A = ModularSymbols(43).T(2).matrix(); A [ 3 0 0 0 0 0 -1] [ 0 -2 1 0 0 0 0] @@ -6182,40 +6251,52 @@ cdef class Matrix(Matrix1): sage: factor(f) (x - 3) * (x + 2)^2 * (x^2 - 2)^2 sage: A.eigenspaces_left(algebraic_multiplicity=True) - [ - (3, Vector space of degree 7 and dimension 1 over Rational Field - User basis matrix: - [ 1 0 1/7 0 -1/7 0 -2/7], 1), - (-2, Vector space of degree 7 and dimension 2 over Rational Field - User basis matrix: - [ 0 1 0 1 -1 1 -1] - [ 0 0 1 0 -1 2 -1], 2), - (-1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field - User basis matrix: - [ 0 1 0 -1 0.4142135623730951? 1 -1] - [ 0 0 1 0 -1 0 2.414213562373095?], 2), - (1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field - User basis matrix: - [ 0 1 0 -1 -2.414213562373095? 1 -1] - [ 0 0 1 0 -1 0 -0.4142135623730951?], 2) - ] + [ (3, + Vector space of degree 7 and dimension 1 over Rational Field + User basis matrix: + [ 1 0 1/7 0 -1/7 0 -2/7], + 1), + (-2, + Vector space of degree 7 and dimension 2 over Rational Field + User basis matrix: + [ 0 1 0 1 -1 1 -1] + [ 0 0 1 0 -1 2 -1], + 2), + (-1.414213562373095?, + Vector space of degree 7 and dimension 2 over Algebraic Field + User basis matrix: + [ 0 1 0 -1 0.4142135623730951? 1 -1] + [ 0 0 1 0 -1 0 2.414213562373095?], + 2), + (1.414213562373095?, + Vector space of degree 7 and dimension 2 over Algebraic Field + User basis matrix: + [ 0 1 0 -1 -2.414213562373095? 1 -1] + [ 0 0 1 0 -1 0 -0.4142135623730951?], + 2) ] sage: A.eigenspaces_left(format='galois', algebraic_multiplicity=True) - [ - (3, Vector space of degree 7 and dimension 1 over Rational Field - User basis matrix: - [ 1 0 1/7 0 -1/7 0 -2/7], 1), - (-2, Vector space of degree 7 and dimension 2 over Rational Field - User basis matrix: - [ 0 1 0 1 -1 1 -1] - [ 0 0 1 0 -1 2 -1], 2), - (a2, Vector space of degree 7 and dimension 2 over Number Field in a2 with defining polynomial x^2 - 2 - User basis matrix: - [ 0 1 0 -1 -a2 - 1 1 -1] - [ 0 0 1 0 -1 0 -a2 + 1], 2) - ] + [ (3, + Vector space of degree 7 and dimension 1 over Rational Field + User basis matrix: + [ 1 0 1/7 0 -1/7 0 -2/7], + 1), + (-2, + Vector space of degree 7 and dimension 2 over Rational Field + User basis matrix: + [ 0 1 0 1 -1 1 -1] + [ 0 0 1 0 -1 2 -1], + 2), + (a2, + Vector space of degree 7 and dimension 2 + over Number Field in a2 with defining polynomial x^2 - 2 + User basis matrix: + [ 0 1 0 -1 -a2 - 1 1 -1] + [ 0 0 1 0 -1 0 -a2 + 1], + 2) ] Next we compute the left eigenspaces over the finite field of order 11. :: + sage: # needs sage.modular sage.rings.finite_rings sage: A = ModularSymbols(43, base_ring=GF(11), sign=1).T(2).matrix(); A [ 3 0 9 0] [ 0 9 0 10] @@ -6225,17 +6306,16 @@ cdef class Matrix(Matrix1): Finite Field of size 11 sage: A.charpoly() x^4 + 10*x^3 + 3*x^2 + 2*x + 1 - sage: A.eigenspaces_left(format='galois', var = 'beta') - [ - (9, Vector space of degree 4 and dimension 1 over Finite Field of size 11 - User basis matrix: - [0 1 5 6]), - (3, Vector space of degree 4 and dimension 1 over Finite Field of size 11 - User basis matrix: - [1 0 1 6]), - (beta2, Vector space of degree 4 and dimension 1 over Univariate Quotient Polynomial Ring in beta2 over Finite Field of size 11 with modulus x^2 + 9 - User basis matrix: - [ 0 0 1 beta2 + 1]) + sage: A.eigenspaces_left(format='galois', var='beta') + [ (9, + Vector space of degree 4 and dimension 1 over Finite Field of size 11 + User basis matrix: [0 1 5 6]), + (3, Vector space of degree 4 and dimension 1 over Finite Field of size 11 + User basis matrix: [1 0 1 6]), + (beta2, Vector space of degree 4 and dimension 1 + over Univariate Quotient Polynomial Ring in beta2 + over Finite Field of size 11 with modulus x^2 + 9 + User basis matrix: [ 0 0 1 beta2 + 1]) ] This method is only applicable to exact matrices. @@ -6263,6 +6343,7 @@ cdef class Matrix(Matrix1): [ 0.897878732... 0.278434036... -0.341010658...] [ 0.408248290... -0.816496580... 0.408248290...] + sage: # needs sage.symbolic sage: x, y = var('x y') sage: S = matrix([[x, y], [y, 3*x^2]]) sage: em = S.eigenmatrix_left() @@ -6277,6 +6358,7 @@ cdef class Matrix(Matrix1): possible, will raise an error. Using the ``'galois'`` format option is more likely to be successful. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(11^2) sage: A = matrix(F, [[b + 1, b + 1], [10*b + 4, 5*b + 4]]) sage: A.eigenspaces_left(format='all') @@ -6284,21 +6366,23 @@ cdef class Matrix(Matrix1): ... NotImplementedError: unable to construct eigenspaces for eigenvalues outside the base field, try the keyword option: format='galois' - sage: A.eigenspaces_left(format='galois') - [ - (a0, Vector space of degree 2 and dimension 1 over Univariate Quotient Polynomial Ring in a0 over Finite Field in b of size 11^2 with modulus x^2 + (5*b + 6)*x + 8*b + 10 - User basis matrix: - [ 1 6*b*a0 + 3*b + 1]) - ] + [ (a0, + Vector space of degree 2 and dimension 1 over + Univariate Quotient Polynomial Ring in a0 over + Finite Field in b of size 11^2 + with modulus x^2 + (5*b + 6)*x + 8*b + 10 + User basis matrix: + [ 1 6*b*a0 + 3*b + 1]) ] TESTS: We make sure that :trac:`13308` is fixed. :: - sage: M = ModularSymbols(Gamma1(23), sign=1) - sage: m = M.cuspidal_subspace().hecke_matrix(2) - sage: [j*m==i[0]*j for i in m.eigenspaces_left(format='all') for j in i[1].basis()] # long time (4s) + sage: M = ModularSymbols(Gamma1(23), sign=1) # needs sage.modular + sage: m = M.cuspidal_subspace().hecke_matrix(2) # needs sage.modular + sage: [j*m == i[0]*j # long time (4s) # needs sage.modular + ....: for i in m.eigenspaces_left(format='all') for j in i[1].basis()] [True, True, True, True, True, True, True, True, True, True, True, True] sage: B = matrix(QQ, 2, 3, range(6)) @@ -6451,40 +6535,47 @@ cdef class Matrix(Matrix1): We compute the right eigenspaces of a `3\times 3` rational matrix. :: - sage: A = matrix(QQ, 3 ,3, range(9)); A + sage: # needs sage.rings.number_field + sage: A = matrix(QQ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] sage: A.eigenspaces_right() - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1]), - (-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field - User basis matrix: - [ 1 0.1303061543300932? -0.7393876913398137?]), - (13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field - User basis matrix: - [ 1 3.069693845669907? 5.139387691339814?]) - ] + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1]), + (-1.348469228349535?, + Vector space of degree 3 and dimension 1 over Algebraic Field + User basis matrix: + [ 1 0.1303061543300932? -0.7393876913398137?]), + (13.34846922834954?, + Vector space of degree 3 and dimension 1 over Algebraic Field + User basis matrix: + [ 1 3.069693845669907? 5.139387691339814?]) ] sage: es = A.eigenspaces_right(format='galois'); es - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1]), - (a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 - User basis matrix: - [ 1 1/5*a1 + 2/5 2/5*a1 - 1/5]) - ] - sage: es = A.eigenspaces_right(format='galois', algebraic_multiplicity=True); es - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1], 1), - (a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 - User basis matrix: - [ 1 1/5*a1 + 2/5 2/5*a1 - 1/5], 1) - ] + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1]), + (a1, + Vector space of degree 3 and dimension 1 over + Number Field in a1 with defining polynomial x^2 - 12*x - 18 + User basis matrix: + [ 1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ] + sage: es = A.eigenspaces_right(format='galois', + ....: algebraic_multiplicity=True); es + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1], + 1), + (a1, + Vector space of degree 3 and dimension 1 over + Number Field in a1 with defining polynomial x^2 - 12*x - 18 + User basis matrix: + [ 1 1/5*a1 + 2/5 2/5*a1 - 1/5], + 1) ] sage: e, v, n = es[0]; v = v.basis()[0] sage: delta = v*e - A*v sage: abs(abs(delta)) < 1e-10 @@ -6496,15 +6587,16 @@ cdef class Matrix(Matrix1): [0 1 2] [3 4 5] [6 7 8] - sage: A.eigenspaces_right(format='galois') - [ - (0, Vector space of degree 3 and dimension 1 over Rational Field - User basis matrix: - [ 1 -2 1]), - (a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 - User basis matrix: - [ 1 1/5*a1 + 2/5 2/5*a1 - 1/5]) - ] + sage: A.eigenspaces_right(format='galois') # needs sage.rings.number_field + [ (0, + Vector space of degree 3 and dimension 1 over Rational Field + User basis matrix: + [ 1 -2 1]), + (a1, + Vector space of degree 3 and dimension 1 over + Number Field in a1 with defining polynomial x^2 - 12*x - 18 + User basis matrix: + [ 1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ] This method is only applicable to exact matrices. The "eigenmatrix" routines for matrices with double-precision @@ -6518,11 +6610,12 @@ cdef class Matrix(Matrix1): sage: B.eigenspaces_right() Traceback (most recent call last): ... - NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision, + NotImplementedError: eigenspaces cannot be computed reliably + for inexact rings such as Real Field with 53 bits of precision, consult numerical or symbolic matrix classes for other options sage: em = B.change_ring(RDF).eigenmatrix_right() - sage: eigenvalues = em[0]; eigenvalues.dense_matrix() # abs tol 1e-13 + sage: eigenvalues = em[0]; eigenvalues.dense_matrix() # abs tol 1e-13 [13.348469228349522 0.0 0.0] [ 0.0 -1.348469228349534 0.0] [ 0.0 0.0 0.0] @@ -6531,6 +6624,7 @@ cdef class Matrix(Matrix1): [ 0.505774475... 0.104205787... -0.816496580...] [ 0.846785134... -0.591288087... 0.408248290...] + sage: # needs sage.symbolic sage: x, y = var('x y') sage: S = matrix([[x, y], [y, 3*x^2]]) sage: em = S.eigenmatrix_right() @@ -6591,14 +6685,14 @@ cdef class Matrix(Matrix1): right_eigenspaces = eigenspaces_right - def eigenvalues(self,extend=True): + def eigenvalues(self, extend=True): r""" Return a sequence of the eigenvalues of a matrix, with - multiplicity. If the eigenvalues are roots of polynomials in QQ, - then QQbar elements are returned that represent each separate + multiplicity. If the eigenvalues are roots of polynomials in ``QQ``, + then ``QQbar`` elements are returned that represent each separate root. - If the option extend is set to False, only eigenvalues in the base + If the option ``extend`` is set to ``False``, only eigenvalues in the base ring are considered. EXAMPLES:: @@ -6608,33 +6702,40 @@ cdef class Matrix(Matrix1): [ 4 5 6 7] [ 8 9 10 11] [12 13 14 15] - sage: sorted(a.eigenvalues(), reverse=True) + sage: sorted(a.eigenvalues(), reverse=True) # needs sage.rings.number_field [32.46424919657298?, 0, 0, -2.464249196572981?] :: - sage: a=matrix([(1, 9, -1, -1), (-2, 0, -10, 2), (-1, 0, 15, -2), (0, 1, 0, -1)]) - sage: a.eigenvalues() - [-0.9386318578049146?, 15.50655435353258?, 0.2160387521361705? - 4.713151979747493?*I, 0.2160387521361705? + 4.713151979747493?*I] + sage: a = matrix([(1, 9, -1, -1), + ....: (-2, 0, -10, 2), + ....: (-1, 0, 15, -2), + ....: (0, 1, 0, -1)]) + sage: a.eigenvalues() # needs sage.rings.number_field + [-0.9386318578049146?, + 15.50655435353258?, + 0.2160387521361705? - 4.713151979747493?*I, + 0.2160387521361705? + 4.713151979747493?*I] - A symmetric matrix a+a.transpose() should have real eigenvalues + A symmetric matrix ``a + a.transpose()`` should have real eigenvalues :: - sage: b=a+a.transpose() - sage: ev = b.eigenvalues(); ev - [-8.35066086057957?, -1.107247901349379?, 5.718651326708515?, 33.73925743522043?] + sage: b = a + a.transpose() + sage: ev = b.eigenvalues(); ev # needs sage.rings.number_field + [-8.35066086057957?, -1.107247901349379?, + 5.718651326708515?, 33.73925743522043?] - The eigenvalues are elements of QQbar, so they really represent + The eigenvalues are elements of ``QQbar``, so they really represent exact roots of polynomials, not just approximations. :: - sage: e = ev[0]; e + sage: e = ev[0]; e # needs sage.rings.number_field -8.35066086057957? - sage: p = e.minpoly(); p + sage: p = e.minpoly(); p # needs sage.rings.number_field x^4 - 30*x^3 - 171*x^2 + 1460*x + 1784 - sage: p(e) == 0 + sage: p(e) == 0 # needs sage.rings.number_field True To perform computations on the eigenvalue as an element of a number @@ -6642,42 +6743,45 @@ cdef class Matrix(Matrix1): :: - sage: e.as_number_field_element() - (Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264, - a + 7, - Ring morphism: - From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264 - To: Algebraic Real Field - Defn: a |--> -15.35066086057957?) + sage: e.as_number_field_element() # needs sage.rings.number_field + (Number Field in a + with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264, + a + 7, + Ring morphism: + From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264 + To: Algebraic Real Field + Defn: a |--> -15.35066086057957?) - Notice the effect of the extend option. + Notice the effect of the ``extend`` option. :: - sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]]) - sage: M.eigenvalues() + sage: M = matrix(QQ, [[0,-1,0], [1,0,0], [0,0,2]]) + sage: M.eigenvalues() # needs sage.rings.number_field [2, -1*I, 1*I] - sage: M.eigenvalues(extend=False) + sage: M.eigenvalues(extend=False) # needs sage.rings.number_field [2] The method also works for matrices over finite fields:: - sage: M = matrix(GF(3), [[0,1,1],[1,2,0],[2,0,1]]) - sage: ev = sorted(M.eigenvalues()); ev + sage: M = matrix(GF(3), [[0,1,1], [1,2,0], [2,0,1]]) + sage: ev = sorted(M.eigenvalues()); ev # needs sage.rings.finite_rings [2*z3, 2*z3 + 1, 2*z3 + 2] - Similarly as in the case of QQbar, the eigenvalues belong to some + Similarly as in the case of ``QQbar``, the eigenvalues belong to some algebraic closure but they can be converted to elements of a finite field:: - sage: e = ev[0] - sage: e.parent() + sage: e = ev[0] # needs sage.rings.finite_rings + sage: e.parent() # needs sage.rings.finite_rings Algebraic closure of Finite Field of size 3 - sage: e.as_finite_field_element() - (Finite Field in z3 of size 3^3, 2*z3, Ring morphism: - From: Finite Field in z3 of size 3^3 - To: Algebraic closure of Finite Field of size 3 - Defn: z3 |--> z3) + sage: e.as_finite_field_element() # needs sage.rings.finite_rings + (Finite Field in z3 of size 3^3, + 2*z3, + Ring morphism: + From: Finite Field in z3 of size 3^3 + To: Algebraic closure of Finite Field of size 3 + Defn: z3 |--> z3) """ x = self.fetch('eigenvalues') if x is not None: @@ -6746,16 +6850,15 @@ cdef class Matrix(Matrix1): :: - sage: A = matrix(QQ,3,3,range(9)); A + sage: # needs sage.rings.number_field + sage: A = matrix(QQ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] sage: es = A.eigenvectors_left(); es - [(0, [ - (1, -2, 1) - ], 1), - (-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1), - (13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)] + [(0, [ (1, -2, 1) ], 1), + (-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1), + (13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)] sage: eval, [evec], mult = es[0] sage: delta = eval*evec - evec*A sage: abs(abs(delta)) < 1e-10 @@ -6765,15 +6868,13 @@ cdef class Matrix(Matrix1): :: - sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]]) - sage: M.eigenvectors_left() - [(2, [ - (0, 0, 1) - ], 1), (-1*I, [(1, -1*I, 0)], 1), (1*I, [(1, 1*I, 0)], 1)] - sage: M.eigenvectors_left(extend=False) - [(2, [ - (0, 0, 1) - ], 1)] + sage: M = matrix(QQ, [[0,-1,0], [1,0,0], [0,0,2]]) + sage: M.eigenvectors_left() # needs sage.rings.number_field + [(2, [ (0, 0, 1) ], 1), + (-1*I, [(1, -1*I, 0)], 1), + (1*I, [(1, 1*I, 0)], 1)] + sage: M.eigenvectors_left(extend=False) # needs sage.rings.number_field + [(2, [ (0, 0, 1) ], 1)] TESTS:: @@ -6787,13 +6888,14 @@ cdef class Matrix(Matrix1): Check the deprecation:: - sage: matrix(QQ, [[1, 2], [3, 4]]).eigenvectors_left(False) + sage: matrix(QQ, [[1, 2], [3, 4]]).eigenvectors_left(False) # needs sage.rings.number_field doctest:...: DeprecationWarning: "extend" should be used as keyword argument See https://github.com/sagemath/sage/issues/29243 for details. [] Check :trac:`30518`:: + sage: # needs sage.rings.number_field sage: K. = QuadraticField(-1) sage: m = matrix(K, 4, [2,4*i,-i,0, -4*i,2,-1,0, 2*i,-2,0,0, 4*i+4, 4*i-4,1-i,-2]) sage: assert all(m*v == e*v for e, vs, _ in m.eigenvectors_right() for v in vs) @@ -6821,7 +6923,6 @@ cdef class Matrix(Matrix1): warn("Using generic algorithm for an inexact ring, which may result in garbage from numerical precision issues.") V = [] - from sage.rings.qqbar import QQbar from sage.categories.homset import hom eigenspaces = self.eigenspaces_left(format='galois', algebraic_multiplicity=True) evec_list=[] @@ -6837,6 +6938,7 @@ cdef class Matrix(Matrix1): evec_eval_list.append((eigval, eigbasis, eigmult)) else: try: + from sage.rings.qqbar import QQbar eigval_conj = eigval.galois_conjugates(QQbar) except AttributeError: raise NotImplementedError("eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar") @@ -6880,20 +6982,17 @@ cdef class Matrix(Matrix1): :: - sage: A = matrix(QQ,3,3,range(9)); A + sage: # needs sage.rings.number_field + sage: A = matrix(QQ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] sage: es = A.eigenvectors_right(); es - [(0, [ - (1, -2, 1) - ], 1), - (-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1), - (13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)] + [(0, [ (1, -2, 1) ], 1), + (-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1), + (13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)] sage: A.eigenvectors_right(extend=False) - [(0, [ - (1, -2, 1) - ], 1)] + [(0, [ (1, -2, 1) ], 1)] sage: eval, [evec], mult = es[0] sage: delta = eval*evec - A*evec sage: abs(abs(delta)) < 1e-10 @@ -6952,7 +7051,8 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(QQ,3,3,range(9)); A + sage: # needs sage.rings.number_field + sage: A = matrix(QQ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] @@ -6972,7 +7072,7 @@ cdef class Matrix(Matrix1): :: - sage: A == (~P)*D*P + sage: A == (~P)*D*P # needs sage.rings.number_field True The matrix `P` may contain zero rows corresponding to eigenvalues for @@ -6981,7 +7081,8 @@ cdef class Matrix(Matrix1): :: - sage: A = jordan_block(2,3); A + sage: # needs sage.rings.number_field + sage: A = jordan_block(2, 3); A [2 1 0] [0 2 1] [0 0 2] @@ -7010,15 +7111,15 @@ cdef class Matrix(Matrix1): sage: A = matrix.identity(CDF, 2) sage: B = matrix(CDF, [[2, 1+I], [4, 2+2*I]]) sage: D, P = A.eigenmatrix_left(B) - sage: D.diagonal() # tol 1e-14 + sage: D.diagonal() # tol 1e-14 # needs sage.symbolic [0.2 - 0.1*I, +infinity] In this case, we can still verify the eigenvector equation for the first eigenvalue and first eigenvector:: - sage: l = D[0, 0] + sage: l = D[0, 0] # needs sage.symbolic sage: v = P[0, :] - sage: (v * A - l * v * B).norm() < 1e-14 + sage: (v * A - l * v * B).norm() < 1e-14 # needs sage.symbolic True The second eigenvector is contained in the left kernel of `B`:: @@ -7043,7 +7144,7 @@ cdef class Matrix(Matrix1): sage: A = matrix(QQ, 3, 3, range(9)) sage: em = A.change_ring(RDF).eigenmatrix_left() - sage: evalues = em[0]; evalues.dense_matrix() # abs tol 1e-13 + sage: evalues = em[0]; evalues.dense_matrix() # abs tol 1e-13 [13.348469228349522 0.0 0.0] [ 0.0 -1.348469228349534 0.0] [ 0.0 0.0 0.0] @@ -7079,21 +7180,24 @@ cdef class Matrix(Matrix1): the algebraic multiplicity. The following examples show that these cases are detected (:trac:`27842`):: - sage: A = matrix(SR, [(225/548, 0, -175/274*sqrt(193/1446)), # optional - sage.symbolic + sage: # needs sage.symbolic + sage: A = matrix(SR, [(225/548, 0, -175/274*sqrt(193/1446)), ....: (0, 1/2, 0), ....: (-63/548*sqrt(723/386), 0, 49/548)]) - sage: A.eigenmatrix_left() # optional - sage.symbolic + sage: A.eigenmatrix_left() Traceback (most recent call last): ... - RuntimeError: failed to compute eigenvectors for eigenvalue ..., check eigenvectors_left() for partial results - sage: B = matrix(SR, [(1/2, -7/2*sqrt(1/386), 0, 49/2*sqrt(1/279078)), # optional - sage.symbolic + RuntimeError: failed to compute eigenvectors for eigenvalue ..., + check eigenvectors_left() for partial results + sage: B = matrix(SR, [(1/2, -7/2*sqrt(1/386), 0, 49/2*sqrt(1/279078)), ....: (-7/2*sqrt(1/386), 211/772, 0, -8425/772*sqrt(1/723)), ....: (0, 0, 1/2, 0), ....: (49/2*sqrt(1/279078), -8425/772*sqrt(1/723), 0, 561/772)]) - sage: B.eigenmatrix_left() # long time (1.2 seconds) # optional - sage.symbolic + sage: B.eigenmatrix_left() # long time (1.2 seconds) Traceback (most recent call last): ... - RuntimeError: failed to compute eigenvectors for eigenvalue ..., check eigenvectors_left() for partial results + RuntimeError: failed to compute eigenvectors for eigenvalue ..., + check eigenvectors_left() for partial results The following example shows that :trac:`12595` has been resolved:: @@ -7168,7 +7272,8 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(QQ,3,3,range(9)); A + sage: # needs sage.rings.number_field + sage: A = matrix(QQ, 3, 3, range(9)); A [0 1 2] [3 4 5] [6 7 8] @@ -7188,7 +7293,7 @@ cdef class Matrix(Matrix1): :: - sage: A == P*D*(~P) + sage: A == P*D*(~P) # needs sage.rings.number_field True The matrix `P` may contain zero columns corresponding to eigenvalues @@ -7197,7 +7302,8 @@ cdef class Matrix(Matrix1): :: - sage: A = jordan_block(2,3); A + sage: # needs sage.rings.number_field + sage: A = jordan_block(2, 3); A [2 1 0] [0 2 1] [0 0 2] @@ -7232,9 +7338,9 @@ cdef class Matrix(Matrix1): In this case, we can still verify the eigenvector equation for the first eigenvalue and first eigenvector:: - sage: l = D[0, 0] + sage: l = D[0, 0] # needs sage.symbolic sage: v = P[:, 0] - sage: (A * v - B * v * l).norm() < 1e-14 + sage: (A * v - B * v * l).norm() < 1e-14 # needs sage.symbolic True The second eigenvector is contained in the right kernel of `B`:: @@ -7310,8 +7416,8 @@ cdef class Matrix(Matrix1): sage: M.eigenvalue_multiplicity(1) 0 - sage: M = posets.DiamondPoset(5).coxeter_transformation() - sage: [M.eigenvalue_multiplicity(x) for x in [-1, 1]] + sage: M = posets.DiamondPoset(5).coxeter_transformation() # needs sage.graphs + sage: [M.eigenvalue_multiplicity(x) for x in [-1, 1]] # needs sage.graphs [3, 2] TESTS:: @@ -7364,7 +7470,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A=matrix(3,range(9)); A + sage: A = matrix(3,range(9)); A [0 1 2] [3 4 5] [6 7 8] @@ -7418,7 +7524,8 @@ cdef class Matrix(Matrix1): sage: C.echelon_form() Traceback (most recent call last): ... - NotImplementedError: Ideal Ideal (2, x + 1) of Univariate Polynomial Ring in x over Integer Ring not principal + NotImplementedError: Ideal Ideal (2, x + 1) of Univariate + Polynomial Ring in x over Integer Ring not principal Echelon form not implemented over 'Univariate Polynomial Ring in x over Integer Ring'. sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1/2]) sage: C.echelon_form() @@ -7464,14 +7571,15 @@ cdef class Matrix(Matrix1): [ 0 4 8 12] [ 0 0 0 0] + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: L. = NumberField(x^2 - x + 2) # optional - sage.rings.number_field - sage: OL = L.ring_of_integers() # optional - sage.rings.number_field - sage: m = matrix(OL, 2, 2, [1,2,3,4+w]) # optional - sage.rings.number_field - sage: m.echelon_form() # optional - sage.rings.number_field + sage: L. = NumberField(x^2 - x + 2) + sage: OL = L.ring_of_integers() + sage: m = matrix(OL, 2, 2, [1,2,3,4+w]) + sage: m.echelon_form() [ 1 2] [ 0 w - 2] - sage: E, T = m.echelon_form(transformation=True); E,T + sage: E, T = m.echelon_form(transformation=True); E, T ( [ 1 2] [ 1 0] [ 0 w - 2], [-3 1] @@ -7614,8 +7722,8 @@ cdef class Matrix(Matrix1): We compute an echelon form both over a domain and fraction field:: sage: R. = QQ[] - sage: a = matrix(R, 2, [x,y,x,y]) - sage: a.echelon_form() # not very useful? -- why two copies of the same row? + sage: a = matrix(R, 2, [x,y, x,y]) + sage: a.echelon_form() # not very useful? -- why two copies of the same row? # needs sage.rings.function_field [x y] [x y] @@ -7629,8 +7737,9 @@ cdef class Matrix(Matrix1): We check that the echelon form works for matrices over p-adics. See :trac:`17272`:: + sage: # needs sage.rings.padics sage: R = ZpCA(5,5,print_mode='val-unit') - sage: A = matrix(R,3,3,[250,2369,1147,106,927,362,90,398,2483]) + sage: A = matrix(R, 3,3, [250,2369,1147, 106,927,362, 90,398,2483]) sage: A [5^3 * 2 + O(5^5) 2369 + O(5^5) 1147 + O(5^5)] [ 106 + O(5^5) 927 + O(5^5) 362 + O(5^5)] @@ -7675,8 +7784,8 @@ cdef class Matrix(Matrix1): Check that :trac:`34724` is fixed (indirect doctest):: - sage: a=6.12323399573677e-17 - sage: m=matrix(RR,[[-a, -1.72508242466029], [ 0.579682446302195, a]]) + sage: a = 6.12323399573677e-17 + sage: m = matrix(RR,[[-a, -1.72508242466029], [ 0.579682446302195, a]]) sage: (~m*m).norm() 1.0 """ @@ -7772,7 +7881,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: MS = MatrixSpace(GF(19),2,3) + sage: MS = MatrixSpace(GF(19), 2, 3) sage: C = MS.matrix([1,2,3,4,5,6]) sage: C.rank() 2 @@ -7842,9 +7951,10 @@ cdef class Matrix(Matrix1): sage: a._echelon('classical') [ 1 0 -1] [ 0 1 2] - sage: R = ZpCA(5,5,print_mode='val-unit') - sage: A = matrix(R,3,3,[250,2369,1147,106,927,362,90,398,2483]) - sage: A + + sage: # needs sage.rings.padics + sage: R = ZpCA(5, 5, print_mode='val-unit') + sage: A = matrix(R, 3, 3, [250,2369,1147, 106,927,362, 90,398,2483]); A [5^3 * 2 + O(5^5) 2369 + O(5^5) 1147 + O(5^5)] [ 106 + O(5^5) 927 + O(5^5) 362 + O(5^5)] [ 5 * 18 + O(5^5) 398 + O(5^5) 2483 + O(5^5)] @@ -7921,9 +8031,10 @@ cdef class Matrix(Matrix1): sage: P = a._echelon_in_place('classical'); a [ 1 0 -1] [ 0 1 2] - sage: R = ZpCA(5,5,print_mode='val-unit') - sage: A = matrix(R,3,3,[250,2369,1147,106,927,362,90,398,2483]) - sage: A + + sage: # needs sage.rings.padics + sage: R = ZpCA(5, 5, print_mode='val-unit') + sage: A = matrix(R,3,3,[250,2369,1147,106,927,362,90,398,2483]); A [5^3 * 2 + O(5^5) 2369 + O(5^5) 1147 + O(5^5)] [ 106 + O(5^5) 927 + O(5^5) 362 + O(5^5)] [ 5 * 18 + O(5^5) 398 + O(5^5) 2483 + O(5^5)] @@ -8079,12 +8190,12 @@ cdef class Matrix(Matrix1): def extended_echelon_form(self, subdivide=False, **kwds): r""" - Returns the echelon form of ``self`` augmented with an identity matrix. + Return the echelon form of ``self`` augmented with an identity matrix. INPUT: - - ``subdivide`` - default: ``False`` - determines if the - returned matrix is subdivided. See the description of the + - ``subdivide`` -- (boolean, default: ``False``) whether to + subdivide the returned matrix. See the description of the (output) below for details. - ``kwds`` - additional keywords that can be passed to the method that computes the echelon form. @@ -8225,7 +8336,7 @@ cdef class Matrix(Matrix1): sage: F.is_mutable() False sage: G = copy(F) - sage: G.subdivide([],[]); G + sage: G.subdivide([], []); G [1 0 0 0 4 6] [0 1 0 4 2 2] [0 0 1 5 2 3] @@ -8299,8 +8410,8 @@ cdef class Matrix(Matrix1): [ 6 1/4] [ 8 -5] - sage: B = M.as_bipartite_graph() - sage: B + sage: # needs sage.graphs + sage: B = M.as_bipartite_graph(); B Bipartite graph on 5 vertices sage: B.edges(sort=True) [(1, 4, 1/3), (1, 5, 7), (2, 4, 6), (2, 5, 1/4), (3, 4, 8), (3, 5, -5)] @@ -8328,15 +8439,14 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: M = matrix(ZZ,[[1,0],[1,0],[0,1]]) - sage: M + sage: # needs sage.groups + sage: M = matrix(ZZ,[[1,0],[1,0],[0,1]]); M [1 0] [1 0] [0 1] - sage: A = M.automorphisms_of_rows_and_columns() - sage: A + sage: A = M.automorphisms_of_rows_and_columns(); A [((), ()), ((1,2), ())] - sage: M = matrix(ZZ,[[1,1,1,1],[1,1,1,1]]) + sage: M = matrix(ZZ, [[1,1,1,1],[1,1,1,1]]) sage: A = M.automorphisms_of_rows_and_columns() sage: len(A) 48 @@ -8344,7 +8454,7 @@ cdef class Matrix(Matrix1): One can now apply these automorphisms to ``M`` to show that it leaves it invariant:: - sage: all(M.with_permuted_rows_and_columns(*i) == M for i in A) + sage: all(M.with_permuted_rows_and_columns(*i) == M for i in A) # needs sage.groups True Check that :trac:`25426` is fixed:: @@ -8354,7 +8464,7 @@ cdef class Matrix(Matrix1): ....: (1, 0, 3, 0, 2), ....: (0, 1, 0, 2, 1), ....: (0, 0, 2, 1, 2)]) - sage: j.automorphisms_of_rows_and_columns() + sage: j.automorphisms_of_rows_and_columns() # needs sage.groups [((), ()), ((1,3)(2,5), (1,3)(2,5))] """ from sage.groups.perm_gps.constructor import \ @@ -8385,9 +8495,9 @@ cdef class Matrix(Matrix1): INPUT: - ``check`` -- (default: ``False``) If ``True`` return a tuple of - the maximal matrix and the permutations taking ``self`` - to the maximal matrix. - If ``False``, return only the maximal matrix. + the maximal matrix and the permutations taking ``self`` + to the maximal matrix. + If ``False``, return only the maximal matrix. OUTPUT: @@ -8412,7 +8522,7 @@ cdef class Matrix(Matrix1): [-1 5] [ 2 4] - sage: M.permutation_normal_form(check=True) + sage: M.permutation_normal_form(check=True) # needs sage.graphs sage.groups ( [ 5 -1] [ 4 2] @@ -8423,7 +8533,7 @@ cdef class Matrix(Matrix1): TESTS:: sage: M = matrix(ZZ, [[3, 4, 5], [3, 4, 5], [3, 5, 4], [2, 0,1]]) - sage: M.permutation_normal_form() + sage: M.permutation_normal_form() # needs sage.graphs [5 4 3] [5 4 3] [4 5 3] @@ -8474,7 +8584,7 @@ cdef class Matrix(Matrix1): aM.append(aN) # We construct line l: for l in range(1, nrows - 1): - if not S == list(xrange(first_row[0] + ncols, first_row[0], -1)): + if not S == list(range(first_row[0] + ncols, first_row[0], -1)): # Sort each row with respect to S for the first matrix in X = MS X = copy(MS) SM = [sorted([(S[j], X[0][k][j]) for j in range(ncols)], reverse=True) @@ -8564,29 +8674,29 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: M = matrix(ZZ,[[1,2,3],[3,5,3],[2,6,4]]) + sage: M = matrix(ZZ, [[1,2,3], [3,5,3], [2,6,4]]) sage: M [1 2 3] [3 5 3] [2 6 4] - sage: N = matrix(ZZ,[[1,2,3],[2,6,4],[3,5,3]]) + sage: N = matrix(ZZ, [[1,2,3], [2,6,4], [3,5,3]]) sage: N [1 2 3] [2 6 4] [3 5 3] - sage: M.is_permutation_of(N) + sage: M.is_permutation_of(N) # needs sage.graphs True Some examples that are not permutations of each other:: - sage: N = matrix(ZZ,[[1,2,3],[4,5,6],[7,8,9]]) + sage: N = matrix(ZZ, [[1,2,3], [4,5,6], [7,8,9]]) sage: N [1 2 3] [4 5 6] [7 8 9] - sage: M.is_permutation_of(N) + sage: M.is_permutation_of(N) # needs sage.graphs False - sage: N = matrix(ZZ,[[1,2],[3,4]]) + sage: N = matrix(ZZ, [[1,2], [3,4]]) sage: N [1 2] [3 4] @@ -8595,7 +8705,8 @@ cdef class Matrix(Matrix1): And for when ``check`` is True:: - sage: N = matrix(ZZ,[[3,5,3],[2,6,4],[1,2,3]]) + sage: # needs sage.graphs + sage: N = matrix(ZZ, [[3,5,3], [2,6,4], [1,2,3]]) sage: N [3 5 3] [2 6 4] @@ -8822,6 +8933,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.libs.pari sage: M = matrix(5, 5, prime_range(100)) sage: M.subdivide(2,3); M [ 2 3 5| 7 11] @@ -8850,6 +8962,7 @@ cdef class Matrix(Matrix1): Degenerate cases work too:: + sage: # needs sage.libs.pari sage: M.subdivide([2,5], [0,1,3]); M [| 2| 3 5| 7 11] [|13|17 19|23 29] @@ -8879,7 +8992,7 @@ cdef class Matrix(Matrix1): Indices do not need to be in the right order (:trac:`14064`):: - sage: M.subdivide([4, 2], [3, 1]); M + sage: M.subdivide([4, 2], [3, 1]); M # needs sage.libs.pari [ 2| 3 5| 7 11] [13|17 19|23 29] [--+-----+-----] @@ -9208,10 +9321,12 @@ cdef class Matrix(Matrix1): sage: D = A.tensor_product(B) sage: D.parent() Full MatrixSpace of 6 by 12 dense matrices over Finite Field of size 23 - sage: E = C.tensor_product(B) + sage: E = C.tensor_product(B) # needs sage.rings.finite_rings Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Finite Field of size 29' and 'Full MatrixSpace of 3 by 4 dense matrices over Finite Field of size 23' + TypeError: unsupported operand parent(s) for *: + 'Finite Field of size 29' and + 'Full MatrixSpace of 3 by 4 dense matrices over Finite Field of size 23' The input is checked to be sure it is a matrix. :: @@ -9523,14 +9638,16 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(QQbar, [[(1/sqrt(5))*(1+i), (1/sqrt(55))*(3+2*I), (1/sqrt(22))*(2+2*I)], - ....: [(1/sqrt(5))*(1-i), (1/sqrt(55))*(2+2*I), (1/sqrt(22))*(-3+I)], - ....: [ (1/sqrt(5))*I, (1/sqrt(55))*(3-5*I), (1/sqrt(22))*(-2)]]) - sage: A.is_unitary() + sage: A = matrix(QQbar, # needs sage.rings.number_field sage.symbolic + ....: [[(1/sqrt(5))*(1+i), (1/sqrt(55))*(3+2*I), (1/sqrt(22))*(2+2*I)], + ....: [(1/sqrt(5))*(1-i), (1/sqrt(55))*(2+2*I), (1/sqrt(22))*(-3+I)], + ....: [ (1/sqrt(5))*I, (1/sqrt(55))*(3-5*I), (1/sqrt(22))*(-2)]]) + sage: A.is_unitary() # needs sage.rings.number_field sage.symbolic True A permutation matrix is always orthogonal. :: + sage: # needs sage.combinat sage: sigma = Permutation([1,3,4,5,2]) sage: P = sigma.to_matrix(); P [1 0 0 0 0] @@ -9540,9 +9657,9 @@ cdef class Matrix(Matrix1): [0 0 0 1 0] sage: P.is_unitary() True - sage: P.change_ring(GF(3)).is_unitary() + sage: P.change_ring(GF(3)).is_unitary() # needs sage.rings.finite_rings True - sage: P.change_ring(GF(3)).is_unitary() + sage: P.change_ring(GF(3)).is_unitary() # needs sage.rings.finite_rings True A square matrix far from unitary. :: @@ -9553,7 +9670,7 @@ cdef class Matrix(Matrix1): Rectangular matrices are never unitary. :: - sage: A = matrix(QQbar, 3, 4) + sage: A = matrix(QQbar, 3, 4) # needs sage.rings.number_field sage: A.is_unitary() False """ @@ -9592,7 +9709,7 @@ cdef class Matrix(Matrix1): sage: (2 * Matrix(5,5,1)).is_bistochastic() False - sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized = False) + sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized=False) True Here is a matrix whose row and column sums is 1, but not all entries are @@ -9640,6 +9757,7 @@ cdef class Matrix(Matrix1): Hermitian matrices are normal. :: + sage: # needs sage.symbolic sage: A = matrix(QQ, 5, 5, range(25)) + I*matrix(QQ, 5, 5, range(0, 50, 2)) sage: B = A*A.conjugate_transpose() sage: B.is_hermitian() @@ -9649,6 +9767,7 @@ cdef class Matrix(Matrix1): Circulant matrices are normal. :: + sage: # needs sage.graphs sage: G = graphs.CirculantGraph(20, [3, 7]) sage: D = digraphs.Circuit(20) sage: A = 3*D.adjacency_matrix() - 5*G.adjacency_matrix() @@ -9677,6 +9796,7 @@ cdef class Matrix(Matrix1): Sage has several fields besides the entire complex numbers where conjugation is non-trivial. :: + sage: # needs sage.rings.number_field sage: F. = QuadraticField(-7) sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3], ....: [-2*b - 3, -3*b + 2, -2*b], @@ -9688,6 +9808,7 @@ cdef class Matrix(Matrix1): A matrix that is nearly normal, but for a non-real diagonal entry. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 2, 2-I, 1+4*I], ....: [ 2+I, 3+I, 2-6*I], ....: [1-4*I, 2+6*I, 5]]) @@ -9699,8 +9820,8 @@ cdef class Matrix(Matrix1): Rectangular matrices are never normal. :: - sage: A = matrix(QQbar, 3, 4) - sage: A.is_normal() + sage: A = matrix(QQbar, 3, 4) # needs sage.rings.number_field + sage: A.is_normal() # needs sage.rings.number_field False A square, empty matrix is trivially normal. :: @@ -9765,19 +9886,20 @@ cdef class Matrix(Matrix1): try to deduce the decomposition from the matrix :: sage: L = [] - sage: L.append((9,Permutation([4, 1, 3, 5, 2]))) - sage: L.append((6,Permutation([5, 3, 4, 1, 2]))) - sage: L.append((3,Permutation([3, 1, 4, 2, 5]))) - sage: L.append((2,Permutation([1, 4, 2, 3, 5]))) - sage: M = sum([c * p.to_matrix() for (c,p) in L]) - sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M) - sage: print(decomp) + sage: L.append((9, Permutation([4, 1, 3, 5, 2]))) + sage: L.append((6, Permutation([5, 3, 4, 1, 2]))) + sage: L.append((3, Permutation([3, 1, 4, 2, 5]))) + sage: L.append((2, Permutation([1, 4, 2, 3, 5]))) + sage: M = sum([c * p.to_matrix() for c, p in L]) + sage: from sage.combinat.permutation import bistochastic_as_sum_of_permutations + sage: decomp = bistochastic_as_sum_of_permutations(M) # needs sage.combinat + sage: print(decomp) # needs sage.combinat 2*B[[1, 4, 2, 3, 5]] + 3*B[[3, 1, 4, 2, 5]] + 9*B[[4, 1, 3, 5, 2]] + 6*B[[5, 3, 4, 1, 2]] An exception is raised when the matrix is not bistochastic:: sage: M = Matrix([[2,3],[2,2]]) - sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M) + sage: decomp = bistochastic_as_sum_of_permutations(M) # needs sage.combinat Traceback (most recent call last): ... ValueError: The matrix is not bistochastic @@ -9813,15 +9935,17 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.rings.real_mpfr sage: M = random_matrix(CC, 5, 7) sage: for i in range(5): M[i,i] = 0 sage: M[4, 0] = M[0, 6] = M[4, 6] = 0 - sage: img = M.visualize_structure(); img + sage: img = M.visualize_structure(); img # needs pillow 7x5px 24-bit RGB image You can use :meth:`~sage.repl.image.Image.save` to save the resulting image:: + sage: # needs pillow sage.rings.real_mpfr sage: filename = tmp_filename(ext='.png') sage: img.save(filename) sage: with open(filename, 'rb') as fobj: @@ -9832,7 +9956,7 @@ cdef class Matrix(Matrix1): Test :trac:`17341`:: - sage: random_matrix(GF(2), 8, 586, sparse=True).visualize_structure() + sage: random_matrix(GF(2), 8, 586, sparse=True).visualize_structure() # needs pillow 512x6px 24-bit RGB image """ cdef Py_ssize_t x, y, _x, _y, v, bi, bisq @@ -9884,7 +10008,7 @@ cdef class Matrix(Matrix1): :: - sage: A = random_matrix(GF(127),200,200,density=0.3) + sage: A = random_matrix(GF(127), 200, 200, density=0.3) sage: A.density() <= 0.3 True @@ -9957,7 +10081,7 @@ cdef class Matrix(Matrix1): Test :trac:`27473`:: sage: F. = LaurentSeriesRing(GF(2)) - sage: M = Matrix([[t,1],[0,t]]) + sage: M = Matrix([[t,1], [0,t]]) sage: ~M [t^-1 t^-2] [ 0 t^-1] @@ -9977,10 +10101,10 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: M = Matrix(ZZ,2,2,[5,2,3,4]) ; M + sage: M = Matrix(ZZ,2,2,[5,2,3,4]); M [5 2] [3 4] - sage: N = M.adjugate() ; N + sage: N = M.adjugate(); N [ 4 -2] [-3 5] sage: M * N @@ -9989,25 +10113,25 @@ cdef class Matrix(Matrix1): sage: N * M [14 0] [ 0 14] - sage: M = Matrix(QQ,2,2,[5/3,2/56,33/13,41/10]) ; M + sage: M = Matrix(QQ, 2, 2, [5/3,2/56, 33/13,41/10]); M [ 5/3 1/28] [33/13 41/10] - sage: N = M.adjugate() ; N + sage: N = M.adjugate(); N # needs sage.libs.pari [ 41/10 -1/28] [-33/13 5/3] - sage: M * N + sage: M * N # needs sage.libs.pari [7363/1092 0] [ 0 7363/1092] An alias is :meth:`adjoint_classical`, which replaces the deprecated :meth:`adjoint` method:: - sage: M.adjoint() + sage: M.adjoint() # needs sage.libs.pari ...: DeprecationWarning: adjoint is deprecated. Please use adjugate instead. See https://github.com/sagemath/sage/issues/10501 for details. [ 41/10 -1/28] [-33/13 5/3] - sage: M.adjoint_classical() + sage: M.adjoint_classical() # needs sage.libs.pari [ 41/10 -1/28] [-33/13 5/3] @@ -10075,9 +10199,10 @@ cdef class Matrix(Matrix1): Finally, an example over a general ring ``S`` that is not an integral domain:: + sage: # needs sage.libs.singular sage: R. = QQ[] sage: S. = R.quo((b^3)) - sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]]) + sage: A = matrix(S, [[x*y^2, 2*x], [2, x^10*y]]) sage: A [ x*y^2 2*x] [ 2 x^10*y] @@ -10111,8 +10236,8 @@ cdef class Matrix(Matrix1): presence of non-integral powers of the variable `x` (:trac:`14403`):: - sage: x = var('x') - sage: Matrix([[sqrt(x),x],[1,0]]).adjugate() + sage: x = var('x') # needs sage.symbolic + sage: Matrix([[sqrt(x),x], [1,0]]).adjugate() # needs sage.symbolic [ 0 -x] [ -1 sqrt(x)] @@ -10187,6 +10312,7 @@ cdef class Matrix(Matrix1): For a nonsingular matrix, the QR decomposition is unique. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[-2, 0, -4, -1, -1], ....: [-2, 1, -6, -3, -1], ....: [1, 1, 7, 4, 5], @@ -10211,13 +10337,14 @@ cdef class Matrix(Matrix1): [ 0.?e-17 0.?e-17 1.000000000000000? 0.?e-16 0.?e-13] [ 0.?e-16 0.?e-16 0.?e-16 1.000000000000000? 0.?e-13] [ 0.?e-13 0.?e-13 0.?e-13 0.?e-13 1.0000000000000?] - sage: Q*R == A + sage: Q * R == A True An example with complex numbers in ``QQbar``, the field of algebraic numbers. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[-8, 4*I + 1, -I + 2, 2*I + 1], ....: [1, -2*I - 1, -I + 3, -I + 1], ....: [I + 7, 2*I + 1, -2*I + 7, -I + 1], @@ -10246,6 +10373,7 @@ cdef class Matrix(Matrix1): A rank-deficient rectangular matrix, with both values of the ``full`` keyword. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[2, -3, 3], ....: [-1, 1, -1], ....: [-1, 3, -3], @@ -10261,12 +10389,13 @@ cdef class Matrix(Matrix1): [ 0 3.569584777515583? -3.569584777515583?] [ 0 0 0] [ 0 0 0] - sage: Q.conjugate_transpose()*Q + sage: Q.conjugate_transpose() * Q [ 1 0.?e-18 0.?e-18 0.?e-18] [ 0.?e-18 1 0.?e-18 0.?e-18] [ 0.?e-18 0.?e-18 1.000000000000000? 0.?e-18] [ 0.?e-18 0.?e-18 0.?e-18 1.000000000000000?] + sage: # needs sage.rings.number_field sage: Q, R = A.QR(full=False) sage: Q [ 0.3592106040535498? -0.5693261797050169?] @@ -10283,6 +10412,7 @@ cdef class Matrix(Matrix1): Another rank-deficient rectangular matrix, with complex entries, as a reduced decomposition. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[-3*I - 3, I - 3, -12*I + 1, -2], ....: [-I - 1, -2, 5*I - 1, -I - 2], ....: [-4*I - 4, I - 5, -7*I, -I - 4]]) @@ -10297,7 +10427,7 @@ cdef class Matrix(Matrix1): sage: Q.conjugate_transpose()*Q [1 0] [0 1] - sage: Q*R-A + sage: Q*R - A [0 0 0 0] [0 0 0 0] [0 0 0 0] @@ -10305,6 +10435,7 @@ cdef class Matrix(Matrix1): Results of full decompositions are cached and thus returned immutable. :: + sage: # needs sage.rings.number_field sage: A = random_matrix(QQbar, 2, 2) sage: Q, R = A.QR() sage: Q.is_mutable() @@ -10315,6 +10446,7 @@ cdef class Matrix(Matrix1): Trivial cases return trivial results of the correct size, and we check `Q` itself in one case. :: + sage: # needs sage.rings.number_field sage: A = zero_matrix(QQbar, 0, 10) sage: Q, R = A.QR() sage: Q.nrows(), Q.ncols() @@ -10354,7 +10486,7 @@ cdef class Matrix(Matrix1): roots, though some small cases pass through. :: sage: A = matrix(ZZ, 3, 3, range(9)) - sage: A.QR() + sage: A.QR() # needs sage.symbolic Traceback (most recent call last): ... TypeError: QR decomposition unable to compute square roots in Rational Field @@ -10484,6 +10616,7 @@ cdef class Matrix(Matrix1): so we need to check with the conjugate-transpose. This example verifies that the bug on :trac:`10791` is fixed. :: + sage: # needs sage.rings.number_field sage: F. = QuadraticField(-5) sage: A = matrix(F, [[ 1, a - 3, a - 2, a + 1], ....: [ a, 2*a + 1, 3*a + 1, 1], @@ -10540,7 +10673,8 @@ cdef class Matrix(Matrix1): sage: A._gram_schmidt_noscale() Traceback (most recent call last): ... - TypeError: Gram-Schmidt orthogonalization requires a base ring with a fraction field, not Ring of integers modulo 6 + TypeError: Gram-Schmidt orthogonalization requires a base ring + with a fraction field, not Ring of integers modulo 6 """ from sage.matrix.constructor import matrix, zero_matrix R = self.base_ring() @@ -10701,6 +10835,7 @@ cdef class Matrix(Matrix1): for small cases or instruction. Now we need to use the ``orthonormal`` keyword. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[6, -8, 1], ....: [4, 1, 3], ....: [6, 3, 3], @@ -10717,13 +10852,13 @@ cdef class Matrix(Matrix1): [ 1.492555785314984? 7.006153332071100? 1.638930357041381?] [ 2.885607851608969? 1.804330147889395? 7.963520581008761?] [ 7.064764050490923? 5.626248468100069? -1.197679876299471?] - sage: M*G-A + sage: M*G - A [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] - sage: (G*G.transpose()-identity_matrix(3)).norm() < 10^-10 + sage: (G*G.transpose() - identity_matrix(3)).norm() < 10^-10 True sage: G.row_space() == A.row_space() True @@ -10731,6 +10866,7 @@ cdef class Matrix(Matrix1): After :trac:`14047`, the matrix can also be over the algebraic reals ``AA``:: + sage: # needs sage.rings.number_field sage: A = matrix(AA, [[6, -8, 1], ....: [4, 1, 3], ....: [6, 3, 3], @@ -10752,22 +10888,24 @@ cdef class Matrix(Matrix1): Note the use of the conjugate-transpose when checking the orthonormality. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ -2, -I - 1, 4*I + 2, -1], ....: [-4*I, -2*I + 17, 0, 9*I + 1], ....: [ 1, -2*I - 6, -I + 11, -5*I + 1]]) sage: G, M = A.gram_schmidt(orthonormal=True) - sage: (M*G-A).norm() < 10^-10 + sage: (M*G - A).norm() < 10^-10 True sage: id3 = G*G.conjugate().transpose() sage: (id3 - identity_matrix(3)).norm() < 10^-10 True - sage: G.row_space() == A.row_space() # long time + sage: G.row_space() == A.row_space() # long time True A square matrix with small rank. The zero vectors produced as a result of linear dependence get eliminated, so the rows of ``G`` are a basis for the row space of ``A``. :: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[2, -6, 3, 8], ....: [1, -3, 2, 5], ....: [0, 0, 2, 4], @@ -10783,12 +10921,12 @@ cdef class Matrix(Matrix1): [ 6.208757731331742? 0.6718090752798139?] [ 3.574739299857670? 2.687236301119256?] [10.630145812734649? 0] - sage: M*G-A + sage: M*G - A [0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0] - sage: (G*G.transpose()-identity_matrix(2)).norm() < 10^-10 + sage: (G*G.transpose() - identity_matrix(2)).norm() < 10^-10 True sage: G.row_space() == A.row_space() True @@ -10834,10 +10972,12 @@ cdef class Matrix(Matrix1): A complex subfield of the complex numbers. :: + sage: # needs sage.rings.number_field sage: C. = CyclotomicField(5) - sage: A = matrix(C, [[ -z^3 - 2*z, -z^3 - 1, 2*z^3 - 2*z^2 + 2*z, 1], - ....: [ z^3 - 2*z^2 + 1, -z^3 + 2*z^2 - z - 1, -1, z^2 + z], - ....: [-1/2*z^3 - 2*z^2 + z + 1, -z^3 + z - 2, -2*z^3 + 1/2*z^2, 2*z^2 - z + 2]]) + sage: A = matrix(C, + ....: [[ -z^3 - 2*z, -z^3 - 1, 2*z^3 - 2*z^2 + 2*z, 1], + ....: [ z^3 - 2*z^2 + 1, -z^3 + 2*z^2 - z - 1, -1, z^2 + z], + ....: [-1/2*z^3 - 2*z^2 + z + 1, -z^3 + z - 2, -2*z^3 + 1/2*z^2, 2*z^2 - z + 2]]) sage: G, M = A.gram_schmidt(orthonormal=False) sage: G [ -z^3 - 2*z -z^3 - 1 2*z^3 - 2*z^2 + 2*z 1] @@ -10959,6 +11099,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.combinat sage: a = matrix(ZZ,4,[1, 0, 0, 0, 0, 1, 0, 0, ....: 1, -1, 1, 0, 1, -1, 1, 2]); a [ 1 0 0 0] @@ -10993,8 +11134,8 @@ cdef class Matrix(Matrix1): Here we need to specify a field, since the eigenvalues are not defined in the smallest ring containing the matrix entries (:trac:`14508`):: - sage: c = matrix([[0,1,0],[0,0,1],[1,0,0]]) - sage: c.jordan_form(CyclotomicField(3)) + sage: c = matrix([[0,1,0], [0,0,1], [1,0,0]]) + sage: c.jordan_form(CyclotomicField(3)) # needs sage.combinat sage.rings.number_field [ 1| 0| 0] [----------+----------+----------] [ 0| zeta3| 0] @@ -11004,20 +11145,20 @@ cdef class Matrix(Matrix1): If you need the transformation matrix as well as the Jordan form of ``self``, then pass the option ``transformation=True``. For example:: - sage: m = matrix([[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]]); m + sage: m = matrix([[5,4,2,1], [0,1,-1,-1], [-1,-1,3,0], [1,1,-1,2]]); m [ 5 4 2 1] [ 0 1 -1 -1] [-1 -1 3 0] [ 1 1 -1 2] - sage: jf, p = m.jordan_form(transformation=True) - sage: jf + sage: jf, p = m.jordan_form(transformation=True) # needs sage.combinat + sage: jf # needs sage.combinat [2|0|0 0] [-+-+---] [0|1|0 0] [-+-+---] [0|0|4 1] [0|0|0 4] - sage: ~p * m * p + sage: ~p * m * p # needs sage.combinat [2 0 0 0] [0 1 0 0] [0 0 4 1] @@ -11027,8 +11168,8 @@ cdef class Matrix(Matrix1): compute the Jordan normal form, since it is not numerically stable:: - sage: b = matrix(ZZ,3,3,range(9)) - sage: jf, p = b.jordan_form(RealField(15), transformation=True) + sage: b = matrix(ZZ, 3, 3, range(9)) + sage: jf, p = b.jordan_form(RealField(15), transformation=True) # needs sage.combinat Traceback (most recent call last): ... ValueError: Jordan normal form not implemented over inexact rings. @@ -11039,13 +11180,14 @@ cdef class Matrix(Matrix1): [1 1 1] [1 1 1] [1 1 1] - sage: c.jordan_form(subdivide=False) + sage: c.jordan_form(subdivide=False) # needs sage.combinat [3 0 0] [0 0 0] [0 0 0] :: + sage: # needs sage.combinat sage: evals = [(i,i) for i in range(1,6)] sage: n = sum(range(1,6)) sage: jf = block_diagonal_matrix([jordan_block(ev,size) for ev,size in evals]) @@ -11056,13 +11198,16 @@ cdef class Matrix(Matrix1): sage: mjf == jf True sage: m = diagonal_matrix([1,1,0,0]) - sage: jf,P = m.jordan_form(transformation=True) + sage: jf, P = m.jordan_form(transformation=True) sage: jf == ~P*m*P True We verify that the bug from :trac:`6942` is fixed:: - sage: M = Matrix(GF(2),[[1,0,1,0,0,0,1],[1,0,0,1,1,1,0],[1,1,0,1,1,1,1],[1,1,1,0,1,1,1],[1,1,1,0,0,1,0],[1,1,1,0,1,0,0],[1,1,1,1,1,1,0]]) + sage: # needs sage.combinat + sage: M = Matrix(GF(2),[[1,0,1,0,0,0,1], [1,0,0,1,1,1,0], [1,1,0,1,1,1,1], + ....: [1,1,1,0,1,1,1], [1,1,1,0,0,1,0], [1,1,1,0,1,0,0], + ....: [1,1,1,1,1,1,0]]) sage: J, T = M.jordan_form(transformation=True) sage: J [1 1|0 0|0 0|0] @@ -11084,8 +11229,8 @@ cdef class Matrix(Matrix1): We verify that the bug from :trac:`6932` is fixed:: - sage: M=Matrix(1,1,[1]) - sage: M.jordan_form(transformation=True) + sage: M = Matrix(1, 1, [1]) + sage: M.jordan_form(transformation=True) # needs sage.combinat ([1], [1]) We now go through three `10 \times 10` matrices to exhibit cases where @@ -11102,7 +11247,7 @@ cdef class Matrix(Matrix1): [ 20 26/3 -66 -199/3 -42 -41/3 0 13/3 -55/3 -2/3] [ 18 57 -9 -54 -57 0 0 0 -15 0] [ 0 0 0 0 0 0 0 0 0 3] - sage: J, T = A.jordan_form(transformation=True); J + sage: J, T = A.jordan_form(transformation=True); J # needs sage.combinat [3 1 0|0 0 0|0 0 0|0] [0 3 1|0 0 0|0 0 0|0] [0 0 3|0 0 0|0 0 0|0] @@ -11116,9 +11261,9 @@ cdef class Matrix(Matrix1): [0 0 0|0 0 0|0 0 3|0] [-----+-----+-----+-] [0 0 0|0 0 0|0 0 0|3] - sage: T * J * T**(-1) == A + sage: T * J * T**(-1) == A # needs sage.combinat True - sage: T.rank() + sage: T.rank() # needs sage.combinat 10 :: @@ -11134,7 +11279,7 @@ cdef class Matrix(Matrix1): [ 20 26/3 -66 -28/3 -42 -41/3 0 13/3 2/3 82/3] [ 18 57 -9 0 -57 0 0 0 3 28] [ 0 0 0 0 0 0 0 0 0 3] - sage: J, T = A.jordan_form(transformation=True); J + sage: J, T = A.jordan_form(transformation=True); J # needs sage.combinat [3 1 0|0 0 0|0 0|0 0] [0 3 1|0 0 0|0 0|0 0] [0 0 3|0 0 0|0 0|0 0] @@ -11148,9 +11293,9 @@ cdef class Matrix(Matrix1): [-----+-----+---+---] [0 0 0|0 0 0|0 0|3 1] [0 0 0|0 0 0|0 0|0 3] - sage: T * J * T**(-1) == A + sage: T * J * T**(-1) == A # needs sage.combinat True - sage: T.rank() + sage: T.rank() # needs sage.combinat 10 :: @@ -11166,7 +11311,7 @@ cdef class Matrix(Matrix1): [ 20 26/3 -30 -199/3 -42 -14/3 70 13/3 -55/3 -2/3] [ 18 57 -9 -54 -57 0 63 0 -15 0] [ 0 0 0 0 0 0 0 0 0 3] - sage: J, T = A.jordan_form(transformation=True); J + sage: J, T = A.jordan_form(transformation=True); J # needs sage.combinat [3 1 0|0 0|0 0|0 0|0] [0 3 1|0 0|0 0|0 0|0] [0 0 3|0 0|0 0|0 0|0] @@ -11181,15 +11326,16 @@ cdef class Matrix(Matrix1): [0 0 0|0 0|0 0|0 3|0] [-----+---+---+---+-] [0 0 0|0 0|0 0|0 0|3] - sage: T * J * T**(-1) == A + sage: T * J * T**(-1) == A # needs sage.combinat True - sage: T.rank() + sage: T.rank() # needs sage.combinat 10 Verify that we smoothly move to QQ from ZZ (:trac:`12693`), i.e. we work in the vector space over the field:: - sage: M = matrix(((2,2,2),(0,0,0),(-2,-2,-2))) + sage: # needs sage.combinat + sage: M = matrix(((2,2,2), (0,0,0), (-2,-2,-2))) sage: J, P = M.jordan_form(transformation=True) sage: J; P [0 1|0] @@ -11216,16 +11362,16 @@ cdef class Matrix(Matrix1): sage: Qx = PolynomialRing(QQ, 'x11, x12, x13, x21, x22, x23, x31, x32, x33') sage: x11, x12, x13, x21, x22, x23, x31, x32, x33 = Qx.gens() sage: M = matrix(Qx, [[0, 0, x31], [0, 0, x21], [0, 0, 0]]) # This is a nilpotent matrix. - sage: M.jordan_form(eigenvalues=[(0, 3)]) + sage: M.jordan_form(eigenvalues=[(0, 3)]) # needs sage.combinat [0 1|0] [0 0|0] [---+-] [0 0|0] - sage: M.jordan_form(eigenvalues=[(0, 2)]) + sage: M.jordan_form(eigenvalues=[(0, 2)]) # needs sage.combinat Traceback (most recent call last): ... ValueError: The provided list of eigenvalues is not correct. - sage: M.jordan_form(transformation=True, eigenvalues=[(0, 3)]) + sage: M.jordan_form(transformation=True, eigenvalues=[(0, 3)]) # needs sage.combinat ( [0 1|0] [0 0|0] [x31 0 1] @@ -11237,17 +11383,17 @@ cdef class Matrix(Matrix1): and it needs to be implemented. :: sage: A = matrix(Integers(6), 2, 2, range(4)) - sage: A.jordan_form() + sage: A.jordan_form() # needs sage.combinat Traceback (most recent call last): ... ValueError: Matrix entries must be from a field, not Ring of integers modulo 6 Test for :trac:`10563`:: - sage: R = FractionField(PolynomialRing(RationalField(),'a')) + sage: R = FractionField(PolynomialRing(RationalField(), 'a')) sage: a = R.gen() - sage: A = matrix(R,[[1,a],[a,1]]) - sage: A.jordan_form() + sage: A = matrix(R, [[1,a], [a,1]]) + sage: A.jordan_form() # needs sage.combinat [ a + 1| 0] [------+------] [ 0|-a + 1] @@ -11414,6 +11560,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.libs.pari sage: A = matrix(QQ, 4, [-4, 6, 3, 3, -3, 5, 3, 3, 3, -6, -4, -3, -3, 6, 3, 2]) sage: A [-4 6 3 3] @@ -11433,18 +11580,19 @@ cdef class Matrix(Matrix1): sage: P^-1*A*P == D True + sage: # needs sage.libs.pari sage: A = matrix(QQ, 2, [0, 2, 1, 0]) sage: A.is_diagonalizable() False - sage: A.is_diagonalizable(QQbar) + sage: A.is_diagonalizable(QQbar) # needs sage.rings.number_field True - sage: D, P = A.diagonalization(QQbar) - sage: P^-1*A*P == D + sage: D, P = A.diagonalization(QQbar) # needs sage.rings.number_field + sage: P^-1*A*P == D # needs sage.rings.number_field True Matrices may fail to be diagonalizable for various reasons:: - sage: A = matrix(QQ, 2, [1,2,3,4,5,6]) + sage: A = matrix(QQ, 2, [1,2,3, 4,5,6]) sage: A [1 2 3] [4 5 6] @@ -11475,7 +11623,7 @@ cdef class Matrix(Matrix1): sage: D [0 2] [1 0] - sage: D.diagonalization() + sage: D.diagonalization() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: not diagonalizable over Rational Field @@ -11484,11 +11632,11 @@ cdef class Matrix(Matrix1): sage: E [3 1] [0 3] - sage: E.diagonalization() + sage: E.diagonalization() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: not diagonalizable - sage: E.jordan_form() + sage: E.jordan_form() # needs sage.combinat [3 1] [0 3] """ @@ -11571,9 +11719,9 @@ cdef class Matrix(Matrix1): ....: [ 9, -8, 11, -12, 51], ....: [ 3, -4, 0, -1, 9], ....: [-1, 0, -4, 4, -12]]) - sage: A.is_diagonalizable() + sage: A.is_diagonalizable() # needs sage.libs.pari True - sage: A.diagonalization() + sage: A.diagonalization() # needs sage.libs.pari ( [ 2 0 0 0 0] [ 1 1 0 1 0] [ 0 3 0 0 0] [ 1/2 0 1 0 1] @@ -11590,9 +11738,9 @@ cdef class Matrix(Matrix1): ....: [-2, -14, 0, 0, 10], ....: [3, 13, -2, 0, -11], ....: [-1, 6, 1, -3, 1]]) - sage: A.is_diagonalizable() + sage: A.is_diagonalizable() # needs sage.libs.pari False - sage: A.jordan_form(subdivide=False) + sage: A.jordan_form(subdivide=False) # needs sage.libs.pari [-1 1 0 0 0] [ 0 -1 0 0 0] [ 0 0 2 1 0] @@ -11609,24 +11757,25 @@ cdef class Matrix(Matrix1): ....: [2, -1, 1, 0, -2], ....: [0, -1, -1, -5, -8]]) - sage: [e in QQ for e in A.eigenvalues()] + sage: [e in QQ for e in A.eigenvalues()] # needs sage.rings.number_field [False, False, False, False, False] - sage: A.is_diagonalizable() + sage: A.is_diagonalizable() # needs sage.libs.pari False - sage: A.diagonalization() + sage: A.diagonalization() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: not diagonalizable over Rational Field - sage: [e in QQbar for e in A.eigenvalues()] + sage: [e in QQbar for e in A.eigenvalues()] # needs sage.rings.number_field [True, True, True, True, True] - sage: A.is_diagonalizable(base_field=QQbar) + sage: A.is_diagonalizable(base_field=QQbar) # needs sage.rings.number_field True Other exact fields may be employed, though it will not always be possible to extend their base fields to contain all the eigenvalues. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^2) sage: A = matrix(F, [[ 4, 3*b + 2, 3*b + 1, 3*b + 4], ....: [2*b + 1, 4*b, 0, 2], @@ -11641,6 +11790,7 @@ cdef class Matrix(Matrix1): [ 0 0|2*b + 1 1] [ 0 0| 0 2*b + 1] + sage: # needs sage.rings.number_field sage: F. = QuadraticField(-7) sage: A = matrix(F, [[ c + 3, 2*c - 2, -2*c + 2, c - 1], ....: [2*c + 10, 13*c + 15, -13*c - 17, 11*c + 31], @@ -11659,7 +11809,7 @@ cdef class Matrix(Matrix1): A trivial matrix is diagonalizable, trivially. :: sage: A = matrix(QQ, 0, 0) - sage: A.is_diagonalizable() + sage: A.is_diagonalizable() # needs sage.libs.pari True A matrix must be square to be diagonalizable. :: @@ -11812,6 +11962,8 @@ cdef class Matrix(Matrix1): ....: [ 0, 6, 1]]) sage: A.is_similar(B) True + + sage: # needs sage.libs.pari sage: _, T = A.is_similar(B, transformation=True) sage: T [ 1.00000000000000? + 0.?e-14*I 0.?e-14 + 0.?e-14*I 0.?e-14 + 0.?e-14*I] @@ -11826,13 +11978,14 @@ cdef class Matrix(Matrix1): Other exact fields are supported. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(7^2) - sage: A = matrix(F,[[2*a + 5, 6*a + 6, a + 3], - ....: [ a + 3, 2*a + 2, 4*a + 2], - ....: [2*a + 6, 5*a + 5, 3*a]]) - sage: B = matrix(F,[[5*a + 5, 6*a + 4, a + 1], - ....: [ a + 5, 4*a + 3, 3*a + 3], - ....: [3*a + 5, a + 4, 5*a + 6]]) + sage: A = matrix(F, [[2*a + 5, 6*a + 6, a + 3], + ....: [ a + 3, 2*a + 2, 4*a + 2], + ....: [2*a + 6, 5*a + 5, 3*a]]) + sage: B = matrix(F, [[5*a + 5, 6*a + 4, a + 1], + ....: [ a + 5, 4*a + 3, 3*a + 3], + ....: [3*a + 5, a + 4, 5*a + 6]]) sage: A.is_similar(B) True sage: B.is_similar(A) @@ -11842,7 +11995,7 @@ cdef class Matrix(Matrix1): [ 1 0 0] [6*a + 1 4*a + 3 4*a + 2] [6*a + 3 3*a + 5 3*a + 6] - sage: A == T.inverse()*B*T + sage: A == T.inverse() * B * T True Two matrices with different sets of eigenvalues, so they @@ -11856,7 +12009,7 @@ cdef class Matrix(Matrix1): ....: [-1, 2, -3, -7], ....: [-2, 3, -4, -7], ....: [ 0, -1, 0, 0]]) - sage: A.eigenvalues() == B.eigenvalues() + sage: A.eigenvalues() == B.eigenvalues() # needs sage.rings.number_field False sage: A.is_similar(B, transformation=True) (False, None) @@ -11874,7 +12027,7 @@ cdef class Matrix(Matrix1): sage: B = matrix(QQ, [[-38, -63, 42], ....: [ 14, 25, -14], ....: [-14, -21, 18]]) - sage: A.charpoly() == B.charpoly() + sage: A.charpoly() == B.charpoly() # needs sage.libs.pari True sage: A.rational_form() [ 0 0 -48] @@ -11901,9 +12054,10 @@ cdef class Matrix(Matrix1): design, but we are not able to resurrect a similarity transformation. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(7^2) - sage: C = matrix(F,[[ a + 2, 5*a + 4], - ....: [6*a + 6, 6*a + 4]]) + sage: C = matrix(F, [[ a + 2, 5*a + 4], + ....: [6*a + 6, 6*a + 4]]) sage: S = matrix(F, [[0, 1], ....: [1, 0]]) sage: D = S.inverse()*C*S @@ -11923,9 +12077,10 @@ cdef class Matrix(Matrix1): algebraic closure of this field to find the change-of-basis matrix:: + sage: # needs sage.combinat sage.graphs sage.rings.finite_rings sage: cox = posets.TamariLattice(3).coxeter_transformation() sage: M = cox.change_ring(GF(3)) - sage: M.is_similar(M**3, True) # long time + sage: M.is_similar(M**3, True) # long time ( [1 0 0 0 0] [0 1 1 0 2] @@ -11960,7 +12115,7 @@ cdef class Matrix(Matrix1): sage: A = matrix(GF(3), 2, 2, range(4)) sage: B = matrix(GF(2), 2, 2, range(4)) - sage: A.is_similar(B, transformation=True) + sage: A.is_similar(B, transformation=True) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: no common canonical parent for objects with parents: @@ -11974,8 +12129,8 @@ cdef class Matrix(Matrix1): of ``QQ`` in ``QQbar``). :: sage: A = matrix(ZZ, 2, 2, range(4)) - sage: B = matrix(QQbar, 2, 2, range(4)) - sage: A.is_similar(B) + sage: B = matrix(QQbar, 2, 2, range(4)) # needs sage.rings.number_field + sage: A.is_similar(B) # needs sage.rings.number_field True TESTS: @@ -12384,13 +12539,13 @@ cdef class Matrix(Matrix1): ... TypeError: first input should be a vector, not junk - sage: A.cyclic_subspace(v, var=sin(x)) + sage: A.cyclic_subspace(v, var=sin(x)) # needs sage.symbolic Traceback (most recent call last): ... TypeError: polynomial variable must be a string or polynomial ring generator, not sin(x) - sage: t = polygen(GF(7), 't') # optional - sage.rings.finite_rings - sage: A.cyclic_subspace(v, var=t) # optional - sage.rings.finite_rings + sage: t = polygen(GF(7), 't') + sage: A.cyclic_subspace(v, var=t) Traceback (most recent call last): ... TypeError: polynomial generator must be over the same ring as the matrix entries @@ -12424,10 +12579,10 @@ cdef class Matrix(Matrix1): ... TypeError: matrix entries must be from an exact field, not Ring of integers modulo 6 - sage: F. = GF(2^4) + sage: F. = GF(2^4) # needs sage.rings.finite_rings sage: G = matrix(QQ, 4, range(16)) - sage: w = vector(F, 4, [1, a, a^2, a^3]) - sage: G.cyclic_subspace(w) + sage: w = vector(F, 4, [1, a, a^2, a^3]) # needs sage.rings.finite_rings + sage: G.cyclic_subspace(w) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: unable to make vector entries compatible with matrix entries @@ -12549,8 +12704,7 @@ cdef class Matrix(Matrix1): ....: [ 2, -7, 4, 7]]) sage: A.is_symmetric() True - sage: L = A.cholesky() - sage: L + sage: L = A.cholesky(); L [ 2 0 0 0] [-1 3 0 0] [ 2 0 2 0] @@ -12571,21 +12725,21 @@ cdef class Matrix(Matrix1): ....: [ -2, -18, -38, 15]]) sage: A.is_symmetric() True - sage: L = A.cholesky() - sage: L + sage: L = A.cholesky(); L # needs sage.rings.number_field [ 8.83176086632785? 0 0 0] [ -3.396831102433787? 9.51112708681461? 0 0] [ -4.189425026335004? 17.32383862241232? 2.886751345948129? 0] [-0.2264554068289192? -1.973397116652010? -1.649572197684645? 2.886751345948129?] - sage: L.parent() + sage: L.parent() # needs sage.rings.number_field Full MatrixSpace of 4 by 4 dense matrices over Algebraic Real Field - sage: L*L.transpose() == A + sage: L*L.transpose() == A # needs sage.rings.number_field True Some subfields of the complex numbers, such as this number field of complex numbers with rational real and imaginary parts, allow for this computation:: + sage: # needs sage.rings.number_field sage: C. = QuadraticField(-1) sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], ....: [ -17*I + 3, 38, -69*I + 89, 7*I + 15], @@ -12593,8 +12747,7 @@ cdef class Matrix(Matrix1): ....: [ -21*I, -7*I + 15, -24*I + 6, 28]]) sage: A.is_hermitian() True - sage: L = A.cholesky() - sage: L + sage: L = A.cholesky(); L [ 4.79...? 0 0 0] [ 0.62...? - 3.54...?*I 5.00...? 0 0] [ 5.21...? - 5.00...?*I 13.58...? + 10.72...?*I 24.98...? 0] @@ -12607,6 +12760,7 @@ cdef class Matrix(Matrix1): The field of algebraic numbers is an ideal setting for this computation:: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I], ....: [ -2*I + 4, 11, 10 - 12*I], ....: [ 4*I + 6, 10 + 12*I, 37]]) @@ -12655,8 +12809,8 @@ cdef class Matrix(Matrix1): Even symbolic matrices can sometimes be factored:: - sage: A = matrix(SR, [[pi,0], [0,pi]]) # optional - sage.symbolic - sage: A.cholesky() # optional - sage.symbolic + sage: A = matrix(SR, [[pi,0], [0,pi]]) # needs sage.symbolic + sage: A.cholesky() # needs sage.symbolic [sqrt(pi) 0] [ 0 sqrt(pi)] @@ -12675,15 +12829,16 @@ cdef class Matrix(Matrix1): The matrix may not be Hermitian:: - sage: F. = FiniteField(5^4) - sage: A = matrix(F, [[2+a^3, 3], [3, 3]]) - sage: A.cholesky() + sage: F. = FiniteField(5^4) # needs sage.rings.finite_rings + sage: A = matrix(F, [[2+a^3, 3], [3, 3]]) # needs sage.rings.finite_rings + sage: A.cholesky() # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: matrix is not Hermitian The matrix may not be positive-definite:: + sage: # needs sage.rings.number_field sage: C. = QuadraticField(-1) sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I], ....: [4 + 2*I, 8, 10*I], @@ -12715,11 +12870,11 @@ cdef class Matrix(Matrix1): sage: E = matrix(QQ, [[2, 1], [1, 1]]) sage: E.is_symmetric() True - sage: E.eigenvalues() + sage: E.eigenvalues() # needs sage.rings.number_field [0.38...?, 2.61...?] sage: E.det() 1 - sage: E.cholesky() + sage: E.cholesky() # needs sage.rings.number_field [ 1.414213562373095? 0] [0.7071067811865475? 0.7071067811865475?] @@ -12731,7 +12886,7 @@ cdef class Matrix(Matrix1): Rational Field sage: E = matrix(QQ, [[2, 1], [1, 1]]) - sage: E.cholesky().base_ring() + sage: E.cholesky().base_ring() # needs sage.rings.number_field Algebraic Real Field Check that sparse floating-point matrices can be factored @@ -12741,17 +12896,17 @@ cdef class Matrix(Matrix1): sage: A.cholesky() [1.0 0.0] [1.0 1.0] - sage: A = matrix(CDF, [[1, I], [-I, 2]], sparse=True) + sage: A = matrix(CDF, [[1, I], [-I, 2]], sparse=True) # needs sage.rings.number_field sage: A.cholesky() [ 1.0 0.0] [-1.0*I 1.0] Try the trivial case (:trac:`33107`):: - sage: all( matrix(R,[]).cholesky() == matrix(R,[]) + sage: all( matrix(R,[]).cholesky() == matrix(R,[]) # needs sage.rings.number_field ....: for R in (RR,CC,RDF,CDF,ZZ,QQ,AA,QQbar) ) True - sage: all( matrix(R,[]).cholesky().is_immutable() + sage: all( matrix(R,[]).cholesky().is_immutable() # needs sage.rings.number_field ....: for R in (RR,CC,RDF,CDF,ZZ,QQ,AA,QQbar) ) True @@ -12881,6 +13036,7 @@ cdef class Matrix(Matrix1): A matrix containing real roots:: + sage: # needs sage.rings.number_field sage.symbolic sage: A = matrix(AA, [ [1, 0, sqrt(2)], ....: [0, sqrt(3), 0 ], ....: [sqrt(2), 0, sqrt(5)] ]) @@ -12896,6 +13052,7 @@ cdef class Matrix(Matrix1): A Hermitian (but not symmetric) matrix with complex entries:: + sage: # needs sage.rings.number_field sage.symbolic sage: A = matrix(QQbar, [ [ 1, 0, I ], ....: [ 0, sqrt(5), 0 ], ....: [-I, 0, 3 ] ]) @@ -12934,6 +13091,7 @@ cdef class Matrix(Matrix1): and rational one because inverting a matrix with algebraic entries is harder and requires smaller test cases:: + sage: # needs sage.rings.number_field sage: from sage.misc.prandom import choice sage: n = ZZ.random_element(2) sage: ring = choice([AA, QQbar]) @@ -13196,13 +13354,15 @@ cdef class Matrix(Matrix1): sage: P, L, U = A.LU() Traceback (most recent call last): ... - TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision + TypeError: base ring of the matrix must be exact, + not Real Field with 100 bits of precision sage: A = matrix(Integers(6), 3, 2, range(6)) sage: A.LU() Traceback (most recent call last): ... - TypeError: base ring of the matrix needs a field of fractions, not Ring of integers modulo 6 + TypeError: base ring of the matrix needs a field of fractions, + not Ring of integers modulo 6 sage: R. = PolynomialRing(QQ, 'y') sage: B = matrix(R, [[y+1, y^2+y], [y^2, y^3]]) @@ -13225,6 +13385,7 @@ cdef class Matrix(Matrix1): sage: B == P*L*U True + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^2) sage: C = matrix(F, [[a + 3, 4*a + 4, 2, 4*a + 2], ....: [3, 2*a + 4, 2*a + 4, 2*a + 1], @@ -13236,17 +13397,17 @@ cdef class Matrix(Matrix1): [0 1 0 0] [0 0 1 0] [0 0 0 1] - sage: L + sage: L # needs sage.combinat [ 1 0 0 0] [3*a + 3 1 0 0] [ 2*a 4*a + 2 1 0] [2*a + 3 2 2*a + 4 1] - sage: U + sage: U # needs sage.combinat [ a + 3 4*a + 4 2 4*a + 2] [ 0 a + 1 a + 3 2*a + 4] [ 0 0 1 4*a + 2] [ 0 0 0 0] - sage: L.base_ring() + sage: L.base_ring() # needs sage.combinat Finite Field in a of size 5^2 sage: C == P*L*U True @@ -13325,6 +13486,7 @@ cdef class Matrix(Matrix1): absolute value must be handled carefully. This tests that situation in the case of cyclotomic fields. :: + sage: # needs sage.groups sage.rings.number_field sage: C = SymmetricGroup(5).character_table() sage: C.base_ring() Cyclotomic Field of order 1 and degree 1 @@ -13388,7 +13550,7 @@ cdef class Matrix(Matrix1): M = self.change_ring(F) m, n = M._nrows, M._ncols d = min(m, n) - perm = list(xrange(m)) + perm = list(range(m)) zero = F(0) for k in range(d): max_location = -1 @@ -13505,9 +13667,10 @@ cdef class Matrix(Matrix1): A Hermitian matrix. :: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ) - sage: C. = NumberField(x^2 + 1) # optional - sage.rings.number_field - sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], # optional - sage.rings.number_field + sage: C. = NumberField(x^2 + 1) + sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], ....: [ -17*I + 3, 38, -69*I + 89, 7*I + 15], ....: [-24*I + 25, 69*I + 89, 976, 24*I + 6], ....: [ -21*I, -7*I + 15, -24*I + 6, 28]]) @@ -13586,7 +13749,7 @@ cdef class Matrix(Matrix1): ... ValueError: matrix is not symmetric (maybe try the 'hermitian' keyword) - sage: A = matrix([[3, 2+3*I], [5+6*I, 12]]) + sage: A = matrix([[3, 2+3*I], [5+6*I, 12]]) # needs sage.rings.number_field sage: A._indefinite_factorization('hermitian', check=True) Traceback (most recent call last): ... @@ -13788,6 +13951,7 @@ cdef class Matrix(Matrix1): with rational real and imaginary parts. As theory predicts, the diagonal entries will be real numbers. :: + sage: # needs sage.rings.number_field sage: C. = QuadraticField(-1) sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I], ....: [4 + 2*I, 8, 10*I], @@ -13830,6 +13994,7 @@ cdef class Matrix(Matrix1): may be factored. This provides a reasonable alternative to the Cholesky decomposition. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^3) sage: A = matrix(F, ....: [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1], @@ -14256,6 +14421,7 @@ cdef class Matrix(Matrix1): The same is true of the following complex Hermitian matrix:: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [ [ 0,I], ....: [-I,0] ]) sage: A.block_ldlt(classical=True) @@ -14350,11 +14516,11 @@ cdef class Matrix(Matrix1): An indefinite Hermitian matrix that happens to have a classical factorization:: - sage: F. = QuadraticField(-1) - sage: A = matrix(F, [[ 2, 4 - 2*I, 2 + 2*I], + sage: F. = QuadraticField(-1) # needs sage.rings.number_field + sage: A = matrix(F, [[ 2, 4 - 2*I, 2 + 2*I], # needs sage.rings.number_field ....: [4 + 2*I, 8, 10*I], ....: [2 - 2*I, -10*I, -3]]) - sage: A.block_ldlt(classical=True)[1:] + sage: A.block_ldlt(classical=True)[1:] # needs sage.rings.number_field ( [ 2| 0| 0] [--+--+--] @@ -14385,6 +14551,7 @@ cdef class Matrix(Matrix1): Ensure that a "random" complex Hermitian matrix is factored correctly:: + sage: # needs sage.rings.number_field sage: n = ZZ.random_element(6) sage: F = QuadraticField(-1, 'I') sage: A = matrix.random(F, n) @@ -14397,12 +14564,13 @@ cdef class Matrix(Matrix1): factored correctly and that the resulting block-diagonal matrix is in fact diagonal:: + sage: # needs sage.rings.number_field sage: n = ZZ.random_element(6) sage: F = QuadraticField(-1, 'I') sage: A = matrix.random(F, n) - sage: A = A*A.conjugate_transpose() + sage: A = A * A.conjugate_transpose() sage: P,L,D = A.block_ldlt() - sage: A == P*L*D*L.conjugate_transpose()*P.conjugate_transpose() + sage: A == P * L * D * L.conjugate_transpose() * P.conjugate_transpose() True sage: diagonal_matrix(D.diagonal()) == D True @@ -14538,7 +14706,7 @@ cdef class Matrix(Matrix1): sage: A = matrix(QQ, [ [2,1], ....: [1,2] ] ) - sage: A.eigenvalues() + sage: A.eigenvalues() # needs sage.rings.number_field [3, 1] sage: A.is_positive_semidefinite() True @@ -14547,7 +14715,7 @@ cdef class Matrix(Matrix1): sage: A = matrix(QQ, [ [1,1], ....: [1,1] ] ) - sage: A.eigenvalues() + sage: A.eigenvalues() # needs sage.rings.number_field [2, 0] sage: A.is_positive_semidefinite() True @@ -14556,7 +14724,7 @@ cdef class Matrix(Matrix1): sage: A = matrix(QQ, [ [0,1], ....: [1,0] ] ) - sage: A.eigenvalues() + sage: A.eigenvalues() # needs sage.rings.number_field [1, -1] sage: A.is_positive_semidefinite() False @@ -14566,7 +14734,7 @@ cdef class Matrix(Matrix1): sage: A = matrix(QQ, [ [2,1], ....: [0,0] ]) - sage: A.eigenvalues() + sage: A.eigenvalues() # needs sage.rings.number_field [2, 0] sage: A.is_positive_semidefinite() False @@ -14607,27 +14775,28 @@ cdef class Matrix(Matrix1): a Hermitian matrix (for a non-Hermitian matrix, both "obviously" return ``False``):: - sage: F = QuadraticField(-1, 'I') + sage: rings = [ZZ, QQ, RDF, CDF] + sage: rings.append(QuadraticField(-1, 'I')) # needs sage.rings.number_field sage: from sage.misc.prandom import choice - sage: ring = choice([ZZ, QQ, F, RDF, CDF]) + sage: ring = choice(rings) sage: A = matrix.random(ring, 10); A = A + A.conjugate_transpose() sage: def is_positive_semidefinite_naive(A): ....: if A.nrows() == 0: ....: return True ....: return ( A.is_hermitian() and ....: all(v >= 0 for v in A.eigenvalues()) ) - sage: expected = is_positive_semidefinite_naive(A) + sage: expected = is_positive_semidefinite_naive(A) # needs numpy sage: actual = A.is_positive_semidefinite() - sage: actual == expected + sage: actual == expected # needs numpy True We reject matrices whose base fields cannot be coerced to either real numbers, complex numbers, or symbolics; otherwise we risk returning nonsensical results:: - sage: F = FiniteField(5^2) - sage: A = matrix.identity(F, 1) - sage: A.is_positive_semidefinite() + sage: F = FiniteField(5^2) # needs sage.rings.finite_rings + sage: A = matrix.identity(F, 1) # needs sage.rings.finite_rings + sage: A.is_positive_semidefinite() # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: Could not see Finite Field in z2 of size 5^2 @@ -14735,9 +14904,10 @@ cdef class Matrix(Matrix1): confirmed by the positive determinants of its leading principal submatrices:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: C. = NumberField(x^2 + 1, embedding=CC(0,1)) # optional - sage.rings.number_field - sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], # optional - sage.rings.number_field + sage: C. = NumberField(x^2 + 1, embedding=CC(0,1)) + sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], ....: [ -17*I + 3, 38, -69*I + 89, 7*I + 15], ....: [-24*I + 25, 69*I + 89, 976, 24*I + 6], ....: [ -21*I, -7*I + 15, -24*I + 6, 28]]) @@ -14749,6 +14919,7 @@ cdef class Matrix(Matrix1): An Hermitian matrix that is not positive-definite and a vector ``u`` that makes the corresponding quadratic form negative:: + sage: # needs sage.rings.number_field sage: C. = QuadraticField(-1) sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I], ....: [4 + 2*I, 8, 10*I], @@ -14763,12 +14934,13 @@ cdef class Matrix(Matrix1): confirmed by the positive determinants of its leading principal submatrices:: + sage: # needs sage.rings.number_field sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I], ....: [ -2*I + 4, 11, 10 - 12*I], ....: [ 4*I + 6, 10 + 12*I, 37]]) sage: A.is_positive_definite() True - sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] + sage: [A[:i,:i].determinant() for i in range(1, A.nrows() + 1)] [2, 2, 6] TESTS: @@ -14777,6 +14949,7 @@ cdef class Matrix(Matrix1): numbers, complex numbers, or symbolic ring, then this routine will fail since comparison to zero is meaningless:: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(5^3) sage: a.conjugate() Traceback (most recent call last): @@ -14801,11 +14974,13 @@ cdef class Matrix(Matrix1): We can check positive-definiteness of matrices over approximate real/complex and symbolic rings:: + sage: # needs sage.rings.real_mpfr sage: matrix.identity(RR,4).is_positive_definite() True sage: matrix.identity(CC,4).is_positive_definite() True - sage: matrix.identity(SR,4).is_positive_definite() # optional - sage.symbolic + + sage: matrix.identity(SR,4).is_positive_definite() # needs sage.symbolic True """ result = self._is_positive_definite_or_semidefinite(False) @@ -14876,7 +15051,7 @@ cdef class Matrix(Matrix1): (automatically) using MPFR instead of doubles, since doubles overflow:: - sage: a = matrix(ZZ, 2, [2^10000,3^10000,2^50,3^19292]) + sage: a = matrix(ZZ, 2, [2^10000, 3^10000, 2^50, 3^19292]) sage: a.hadamard_bound() 12215 sage: len(str(a.det())) @@ -14924,7 +15099,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1]) - sage: M.find(lambda entry:entry==0) + sage: M.find(lambda entry: entry == 0) [0 0 0] [0 0 0] [0 1 1] @@ -14932,7 +15107,7 @@ cdef class Matrix(Matrix1): :: - sage: M.find(lambda u:u<0) + sage: M.find(lambda u: u < 0) [0 1 1] [0 1 1] [1 0 0] @@ -14946,7 +15121,7 @@ cdef class Matrix(Matrix1): :: - sage: M.find(lambda u:u!=1/2) + sage: M.find(lambda u: u != 1/2) [1 1 1] [1 1 1] [1 1 1] @@ -14954,7 +15129,7 @@ cdef class Matrix(Matrix1): :: - sage: M.find(lambda u:u>1.2) + sage: M.find(lambda u: u > 1.2) [0 0 0] [0 0 0] [0 0 0] @@ -14962,7 +15137,7 @@ cdef class Matrix(Matrix1): :: - sage: sorted(M.find(lambda u:u!=0,indices=True).keys()) == M.nonzero_positions() + sage: sorted(M.find(lambda u: u != 0, indices=True).keys()) == M.nonzero_positions() True """ from sage.matrix.matrix_space import MatrixSpace @@ -15007,21 +15182,21 @@ cdef class Matrix(Matrix1): A matrix over a not-totally-real number field:: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 + 5) # optional - sage.rings.number_field - sage: M = matrix(K, [[1+j,1], [0,2*j]]) # optional - sage.rings.number_field - sage: M.conjugate() # optional - sage.rings.number_field + sage: K. = NumberField(x^2 + 5) # needs sage.rings.number_field + sage: M = matrix(K, [[1+j,1], [0,2*j]]) # needs sage.rings.number_field + sage: M.conjugate() # needs sage.rings.number_field [-j + 1 1] [ 0 -2*j] There is a shortcut for the conjugate:: - sage: M.C + sage: M.C # needs sage.rings.number_field [-j + 1 1] [ 0 -2*j] There is also a shortcut for the conjugate transpose, or "Hermitian transpose":: - sage: M.H + sage: M.H # needs sage.rings.number_field [-j + 1 0] [ 1 -2*j] @@ -15062,14 +15237,17 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: M = matrix(SR, 2, 2, [[2-I, 3+4*I], [9-6*I, 5*I]]) # optional - sage.symbolic - sage: M.base_ring() # optional - sage.symbolic + sage: M = matrix(SR, 2, 2, [[2-I, 3+4*I], [9-6*I, 5*I]]) # needs sage.symbolic + sage: M.base_ring() # needs sage.symbolic Symbolic Ring - sage: M.conjugate_transpose() # optional - sage.symbolic + sage: M.conjugate_transpose() # needs sage.symbolic [ I + 2 6*I + 9] [-4*I + 3 -5*I] - sage: P = matrix(CC, 3, 2, [0.95-0.63*I, 0.84+0.13*I, 0.94+0.23*I, 0.23+0.59*I, 0.52-0.41*I, -0.50+0.90*I]) + sage: # needs sage.rings.real_mpfr sage.symbolic + sage: P = matrix(CC, 3, 2, [0.95-0.63*I, 0.84+0.13*I, + ....: 0.94+0.23*I, 0.23+0.59*I, + ....: 0.52-0.41*I, -0.50+0.90*I]) sage: P.base_ring() Complex Field with 53 bits of precision sage: P.conjugate_transpose() @@ -15078,7 +15256,7 @@ cdef class Matrix(Matrix1): There is also a shortcut for the conjugate transpose, or "Hermitian transpose":: - sage: M.H + sage: M.H # needs sage.symbolic [ I + 2 6*I + 9] [-4*I + 3 -5*I] @@ -15095,6 +15273,7 @@ cdef class Matrix(Matrix1): (Matrices over quadratic number fields are another class of examples.) :: + sage: # needs sage.rings.number_field sage: C = CyclotomicField(5) sage: a = C.gen(); a zeta5 @@ -15108,11 +15287,11 @@ cdef class Matrix(Matrix1): Furthermore, this method can be applied to matrices over quadratic extensions of finite fields:: - sage: F. = GF(9,'a') - sage: N = matrix(F, 2, [0,a,-a,1]); N + sage: F. = GF(9,'a') # needs sage.rings.finite_rings + sage: N = matrix(F, 2, [0,a,-a,1]); N # needs sage.rings.finite_rings [ 0 a] [2*a 1] - sage: N.conjugate_transpose() + sage: N.conjugate_transpose() # needs sage.rings.finite_rings [ 0 a + 2] [2*a + 1 1] @@ -15123,7 +15302,8 @@ cdef class Matrix(Matrix1): sage: N.conjugate_transpose() Traceback (most recent call last): ... - AttributeError: 'sage.rings.finite_rings.integer_mod.IntegerMod_int' object has no attribute 'conjugate' + AttributeError: 'sage.rings.finite_rings.integer_mod.IntegerMod_int' object + has no attribute 'conjugate' """ # limited testing on a 1000 x 1000 matrix over CC: # transpose is fast, conjugate is slow @@ -15138,8 +15318,7 @@ cdef class Matrix(Matrix1): INPUT: - - ``self`` - a matrix whose entries are coercible into - CDF + - ``self`` - a matrix whose entries are coercible into ``CDF`` - ``p`` - one of the following options: @@ -15174,6 +15353,8 @@ cdef class Matrix(Matrix1): sage: Id = identity_matrix(12) sage: Id.norm(2) 1.0 + + sage: # needs sage.rings.real_mpfr sage: A = matrix(RR, 2, 2, [13,-4,-4,7]) sage: A.norm() # rel tol 2e-16 14.999999999999998 @@ -15182,6 +15363,7 @@ cdef class Matrix(Matrix1): Faster routines for double precision entries from `RDF` or `CDF` are provided by the :class:`~sage.matrix.matrix_double_dense.Matrix_double_dense` class. :: + sage: # needs sage.rings.real_mpfr sage: A = matrix(CC, 2, 3, [3*I,4,1-I,1,2,0]) sage: A.norm('frob') 5.656854249492381 @@ -15250,32 +15432,24 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: d = matrix([[3, 0],[0,sqrt(2)]]) - sage: b = matrix([[1, -1], [2, 2]]) ; e = b * d * b.inverse();e + sage: # needs sage.symbolic + sage: d = matrix([[3, 0], [0, sqrt(2)]]) + sage: b = matrix([[1, -1], [2, 2]]); e = b * d * b.inverse(); e [ 1/2*sqrt(2) + 3/2 -1/4*sqrt(2) + 3/4] [ -sqrt(2) + 3 1/2*sqrt(2) + 3/2] - - :: - sage: e.numerical_approx(53) [ 2.20710678118655 0.396446609406726] [ 1.58578643762690 2.20710678118655] - - :: - sage: e.numerical_approx(20) [ 2.2071 0.39645] [ 1.5858 2.2071] - - :: - - sage: (e-I).numerical_approx(20) + sage: (e - I).numerical_approx(20) [2.2071 - 1.0000*I 0.39645] [ 1.5858 2.2071 - 1.0000*I] :: - sage: M=matrix(QQ,4,[i/(i+1) for i in range(12)]);M + sage: M = matrix(QQ, 4, [i/(i+1) for i in range(12)]); M [ 0 1/2 2/3] [ 3/4 4/5 5/6] [ 6/7 7/8 8/9] @@ -15291,7 +15465,7 @@ cdef class Matrix(Matrix1): :: - sage: matrix(SR, 2, 2, range(4)).n() # optional - sage.symbolic + sage: matrix(SR, 2, 2, range(4)).n() # needs sage.symbolic [0.000000000000000 1.00000000000000] [ 2.00000000000000 3.00000000000000] @@ -15305,9 +15479,9 @@ cdef class Matrix(Matrix1): We check that :trac:`29700` is fixed:: - sage: M = matrix(3,[1,1,1,1,0,0,0,1,0]) - sage: A,B = M.diagonalization(QQbar) - sage: _ = A.n() + sage: M = matrix(3, [1,1,1,1,0,0,0,1,0]) + sage: A, B = M.diagonalization(QQbar) # needs sage.rings.number_field + sage: _ = A.n() # needs sage.rings.number_field """ from sage.rings.real_mpfr import RealField @@ -15342,21 +15516,21 @@ cdef class Matrix(Matrix1): A matrix over ZZ colored with different grey levels:: sage: A = matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]) - sage: A.plot() + sage: A.plot() # needs sage.plot Graphics object consisting of 1 graphics primitive - Here we make a random matrix over RR and use cmap='hsv' to color + Here we make a random matrix over ``RR`` and use ``cmap='hsv'`` to color the matrix elements different RGB colors (see documentation for ``matrix_plot`` for more information on cmaps):: sage: A = random_matrix(RDF, 50) - sage: plot(A, cmap='hsv') + sage: plot(A, cmap='hsv') # needs sage.plot Graphics object consisting of 1 graphics primitive Another random plot, but over GF(389):: sage: A = random_matrix(GF(389), 10) - sage: A.plot(cmap='Oranges') + sage: A.plot(cmap='Oranges') # needs sage.plot Graphics object consisting of 1 graphics primitive """ from sage.plot.matrix_plot import matrix_plot @@ -15372,6 +15546,7 @@ cdef class Matrix(Matrix1): EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector([1,x,x^2]) sage: v.derivative(x) (0, 1, 2*x) @@ -15407,24 +15582,25 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: a=matrix([[1,2],[3,4]]) + sage: # needs sage.symbolic + sage: a = matrix([[1,2], [3,4]]) sage: a.exp() [-1/22*((sqrt(33) - 11)*e^sqrt(33) - sqrt(33) - 11)*e^(-1/2*sqrt(33) + 5/2) 2/33*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2)] [ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)] - sage: type(a.exp()) + sage: type(a.exp()) # needs sage.symbolic - sage: a=matrix([[1/2,2/3],[3/4,4/5]]) - sage: a.exp() + sage: a = matrix([[1/2,2/3], [3/4,4/5]]) + sage: a.exp() # needs sage.symbolic [-1/418*((3*sqrt(209) - 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) - 209)*e^(-1/20*sqrt(209) + 13/20) 20/627*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20)] [ 15/418*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20) 1/418*((3*sqrt(209) + 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) + 209)*e^(-1/20*sqrt(209) + 13/20)] - sage: a=matrix(RR,[[1,pi.n()],[1e2,1e-2]]) - sage: a.exp() + sage: a = matrix(RR, [[1,pi.n()], [1e2,1e-2]]) # needs sage.symbolic + sage: a.exp() # needs sage.symbolic [ 1/11882424341266*((11*sqrt(227345670387496707609) + 5941212170633)*e^(3/1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) + 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) 445243650/75781890129165569203*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)] [ 10000/53470909535697*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) -1/11882424341266*((11*sqrt(227345670387496707609) - 5941212170633)*e^(3/1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) - 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)] - sage: a.change_ring(RDF).exp() # rel tol 1e-14 + sage: a.change_ring(RDF).exp() # rel tol 1e-14 # needs sage.symbolic [42748127.31532951 7368259.244159399] [234538976.1381042 40426191.45156228] @@ -15433,9 +15609,9 @@ cdef class Matrix(Matrix1): Sparse matrices are handled correctly (:trac:`28935`), but may require a patched version of maxima (:trac:`32898`) for now:: - sage: matrix.diagonal([0], sparse=True).exp() # not tested, requires patched maxima + sage: matrix.diagonal([0], sparse=True).exp() # not tested # needs sage.symbolic [1] - sage: matrix.zero(CBF, 2, sparse=True).exp() + sage: matrix.zero(CBF, 2, sparse=True).exp() # needs sage.libs.flint sage.symbolic [1.000000000000000 0] [ 0 1.000000000000000] """ @@ -15445,27 +15621,31 @@ cdef class Matrix(Matrix1): from sage.symbolic.ring import SR return self.change_ring(SR).exp() - def elementary_divisors(self): + def elementary_divisors(self, algorithm=None): r""" - If self is a matrix over a principal ideal domain R, return + If ``self`` is a matrix over a principal ideal domain `R`, return elements `d_i` for `1 \le i \le k = \min(r,s)` where `r` and `s` are the number of rows and - columns of self, such that the cokernel of self is isomorphic to + columns of self, such that the cokernel of ``self`` is isomorphic to .. MATH:: R/(d_1) \oplus R/(d_2) \oplus R/(d_k) with `d_i \mid d_{i+1}` for all `i`. These are - the diagonal entries of the Smith form of self (see - :meth:`smith_form()`). + the diagonal entries of the Smith form of ``self`` (see + :meth:`smith_form`). + + INPUT: + + - ``algorithm`` -- ignored EXAMPLES:: sage: x = polygen(ZZ, 'x') - sage: OE. = EquationOrder(x^2 - x + 2) # optional - sage.rings.number_field - sage: m = Matrix([[1, w], [w, 7]]) # optional - sage.rings.number_field - sage: m.elementary_divisors() # optional - sage.rings.number_field + sage: OE. = EquationOrder(x^2 - x + 2) # needs sage.rings.number_field + sage: m = Matrix([[1, w], [w, 7]]) # needs sage.rings.number_field + sage: m.elementary_divisors() # needs sage.rings.number_field [1, -w + 9] .. SEEALSO:: @@ -15554,11 +15734,12 @@ cdef class Matrix(Matrix1): An example over the ring of integers of a number field (of class number 1):: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: OE. = EquationOrder(x^2 - x + 2) # optional - sage.rings.number_field - sage: m = Matrix([[1, w], [w, 7]]) # optional - sage.rings.number_field - sage: d, u, v = m.smith_form() # optional - sage.rings.number_field - sage: (d, u, v) # optional - sage.rings.number_field + sage: OE. = EquationOrder(x^2 - x + 2) + sage: m = Matrix([[1, w], [w, 7]]) + sage: d, u, v = m.smith_form() + sage: (d, u, v) ( [ 1 0] [ 1 0] [ 1 -w] [ 0 -w + 9], [-w 1], [ 0 1] @@ -15572,7 +15753,8 @@ cdef class Matrix(Matrix1): An example over the polynomial ring QQ[x]:: - sage: R. = QQ[]; m=x*matrix(R,2,2,1) - matrix(R, 2,2,[3,-4,1,-1]); m.smith_form() + sage: R. = QQ[]; m = x*matrix(R, 2, 2, 1) - matrix(R, 2, 2, [3,-4,1,-1]) + sage: m.smith_form() ( [ 1 0] [ 0 -1] [ 1 x + 1] [ 0 x^2 - 2*x + 1], [ 1 x - 3], [ 0 1] @@ -15580,12 +15762,13 @@ cdef class Matrix(Matrix1): An example over a field:: - sage: m = matrix( GF(17), 3, 3, [11,5,1,3,6,8,1,16,0]); d,u,v = m.smith_form() + sage: m = matrix(GF(17), 3, 3, [11,5,1, 3,6,8, 1,16,0]) + sage: d, u, v = m.smith_form() sage: d [1 0 0] [0 1 0] [0 0 0] - sage: u*m*v == d + sage: u * m * v == d True When the base ring has a ``ring_of_integers`` method and supports denominators, @@ -15605,45 +15788,57 @@ cdef class Matrix(Matrix1): Some examples over non-PID's work anyway:: - sage: R. = EquationOrder(x^2 + 5) # class number 2 - sage: A = matrix(R, 2, 2, [s-1,-s,-s,2*s+1]) + sage: # needs sage.rings.number_field + sage: R. = EquationOrder(x^2 + 5) # class number 2 + sage: A = matrix(R, 2, 2, [s - 1, -s, -s, 2*s + 1]) sage: D, U, V = A.smith_form() sage: D, U, V ( [ 1 0] [ 4 s + 4] [ 1 -5*s + 6] [ 0 -s - 6], [ s s - 1], [ 0 1] ) - sage: D == U*A*V + sage: D == U * A * V True Others don't, but they fail quite constructively:: - sage: matrix(R,2,2,[s-1,-s-2,-2*s,-s-2]).smith_form() + sage: matrix(R, 2, 2, [s - 1, -s - 2, -2*s, -s - 2]).smith_form() # needs sage.rings.number_field Traceback (most recent call last): ... ArithmeticError: Ideal Fractional ideal (2, s + 1) not principal Empty matrices are handled safely:: - sage: m = MatrixSpace(OE, 2,0)(0); d,u,v=m.smith_form(); u*m*v == d + sage: # needs sage.rings.number_field + sage: m = MatrixSpace(OE, 2,0)(0) + sage: d, u, v = m.smith_form(); u * m * v == d True - sage: m = MatrixSpace(OE, 0,2)(0); d,u,v=m.smith_form(); u*m*v == d + sage: m = MatrixSpace(OE, 0,2)(0) + sage: d, u, v = m.smith_form(); u * m * v == d True - sage: m = MatrixSpace(OE, 0,0)(0); d,u,v=m.smith_form(); u*m*v == d + sage: m = MatrixSpace(OE, 0,0)(0) + sage: d, u, v = m.smith_form(); u * m * v == d True Some pathological cases that crashed earlier versions:: - sage: m = Matrix(OE, [[2*w,2*w-1,-w+1],[2*w+2,-2*w-1,w-1],[-2*w-1,-2*w-2,2*w-1]]); d, u, v = m.smith_form(); u * m * v == d + sage: # needs sage.rings.number_field + sage: m = Matrix(OE, [[ 2*w, 2*w - 1, -w + 1], + ....: [ 2*w + 2, -2*w - 1, w - 1], + ....: [-2*w - 1, -2*w - 2, 2*w - 1]]) + sage: d, u, v = m.smith_form(); u * m * v == d True - sage: m = matrix(OE, 3, 3, [-5*w-1,-2*w-2,4*w-10,8*w,-w,w-1,-1,1,-8]); d,u,v = m.smith_form(); u*m*v == d + sage: m = matrix(OE, [[-5*w - 1, -2*w - 2, 4*w - 10], + ....: [ 8*w, -w, w - 1], + ....: [ -1, 1, -8]]) + sage: d, u, v = m.smith_form(); u * m * v == d True Over local fields, we can request the transformation matrices to be integral:; - sage: K = Qp(2, 5, print_mode='terse') - sage: M = matrix(K, 2, 3, [1/2, 1, 2, 1/3, 1, 3]) - sage: M.smith_form(integral=True) + sage: K = Qp(2, 5, print_mode='terse') # needs sage.rings.padics + sage: M = matrix(K, 2, 3, [1/2, 1, 2, 1/3, 1, 3]) # needs sage.rings.padics + sage: M.smith_form(integral=True) # needs sage.rings.padics ( [1/2 + O(2^4) 0 0] [ 1 + O(2^5) 0] [ 0 1 + O(2^5) 0], [42 + O(2^6) 1 + O(2^5)], @@ -15750,7 +15945,8 @@ cdef class Matrix(Matrix1): [ -x + 1 -1 -x^2 + 2*x - 1] [-x^2 + 2*x - 1 -x + 1 -1] sage: H = A.__copy__() - sage: U = H._hermite_form_euclidean(transformation=True, normalization=lambda p: ~p.lc()) + sage: U = H._hermite_form_euclidean(transformation=True, + ....: normalization=lambda p: ~p.lc()) sage: H [ 1 x^2 - 2*x + 1 x - 1] [ 0 x^3 - 3*x^2 + 3*x - 2 0] @@ -15857,9 +16053,9 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: M = FunctionField(GF(7),'x').maximal_order() + sage: M = FunctionField(GF(7), 'x').maximal_order() sage: K. = FunctionField(GF(7)); M = K.maximal_order() - sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2]) + sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1 + x, 2]) sage: A.hermite_form() [ x 1 2*x] [ 0 x 5*x + 2] @@ -15871,17 +16067,18 @@ cdef class Matrix(Matrix1): sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x]) sage: A.hermite_form(transformation=True, include_zero_rows=False) ([ x 1 2*x], [1 0]) - sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U + sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True) + sage: H, U ( [ x 1 2*x] [1 0] [ 0 0 0], [5 1] ) - sage: U*A == H + sage: U * A == H True sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False) - sage: U*A + sage: U * A [ x 1 2*x] - sage: U*A == H + sage: U * A == H True """ left, H, pivots = self._echelon_form_PID() @@ -15909,11 +16106,12 @@ cdef class Matrix(Matrix1): EXAMPLES:: sage: x = polygen(ZZ, 'x') - sage: L. = NumberField(x^3 - 2) # optional - sage.rings.number_field - sage: OL = L.ring_of_integers() # optional - sage.rings.number_field + sage: L. = NumberField(x^3 - 2) # needs sage.rings.number_field + sage: OL = L.ring_of_integers() # needs sage.rings.number_field We check some degenerate cases:: + sage: # needs sage.rings.number_field sage: m = matrix(OL, 0, 0, []); r,s,p = m._echelon_form_PID() sage: (r,s,p) ([], [], []) @@ -15932,17 +16130,18 @@ cdef class Matrix(Matrix1): A 2x2 matrix:: - sage: m = matrix(OL, 2, 2, [1,0, a, 2]) - sage: r,s,p = m._echelon_form_PID(); (r,s,p) + sage: m = matrix(OL, 2, 2, [1, 0, a, 2]) # needs sage.rings.number_field + sage: r,s,p = m._echelon_form_PID(); (r,s,p) # needs sage.rings.number_field ( [ 1 0] [1 0] [-a 1], [0 2], [0, 1] ) - sage: r * m == s and r.det() == 1 + sage: r * m == s and r.det() == 1 # needs sage.rings.number_field True A larger example:: + sage: # needs sage.rings.number_field sage: m = matrix(OL, 3, 5, [a^2 - 3*a - 1, a^2 - 3*a + 1, a^2 + 1, ....: -a^2 + 2, -3*a^2 - a - 1, -6*a - 1, a^2 - 3*a - 1, ....: 2*a^2 + a + 5, -2*a^2 + 5*a + 1, -a^2 + 13*a - 3, @@ -16382,7 +16581,7 @@ cdef class Matrix(Matrix1): sage: U.inverse()*B*U == Z True - sage: A.jordan_form() == B.jordan_form() + sage: A.jordan_form() == B.jordan_form() # needs sage.combinat True Two more examples, illustrating the two extremes of the zig-zag @@ -16443,13 +16642,14 @@ cdef class Matrix(Matrix1): sage: U.inverse()*D*U == Z True - sage: C.jordan_form() == D.jordan_form() + sage: C.jordan_form() == D.jordan_form() # needs sage.combinat True ZigZag form is achieved entirely with the operations of the field, so while the eigenvalues may lie outside the field, this does not impede the computation of the form. :: + sage: # needs sage.rings.finite_rings sage: F. = GF(5^4) sage: A = matrix(F, [[ a, 0, 0, a + 3], ....: [ 0,a^2 + 1, 0, 0], @@ -16469,12 +16669,12 @@ cdef class Matrix(Matrix1): Subdivisions are optional. :: - sage: F. = GF(5^4) - sage: A = matrix(F, [[ a, 0, 0, a + 3], + sage: F. = GF(5^4) # needs sage.rings.finite_rings + sage: A = matrix(F, [[ a, 0, 0, a + 3], # needs sage.rings.finite_rings ....: [ 0,a^2 + 1, 0, 0], ....: [ 0, 0,a^3, 0], ....: [a^2 +4 , 0, 0,a + 2]]) - sage: A.zigzag_form(subdivide=False) + sage: A.zigzag_form(subdivide=False) # needs sage.rings.finite_rings [ 0 a^3 + 2*a^2 + 2*a + 2 0 0] [ 1 2*a + 2 0 0] [ 0 0 a^3 0] @@ -16645,13 +16845,13 @@ cdef class Matrix(Matrix1): sage: invariants [[4, -4, 1], [-12, 4, 9, -6, 1], [216, -108, -306, 271, 41, -134, 64, -13, 1]] sage: polys = [R(p) for p in invariants] - sage: [p.factor() for p in polys] + sage: [p.factor() for p in polys] # needs sage.rings.finite_rings [(x - 2)^2, (x - 3) * (x + 1) * (x - 2)^2, (x + 1)^2 * (x - 3)^3 * (x - 2)^3] sage: all(polys[i].divides(polys[i+1]) for i in range(len(polys)-1)) True - sage: polys[-1] == A.minimal_polynomial(var='x') + sage: polys[-1] == A.minimal_polynomial(var='x') # needs sage.libs.pari True - sage: prod(polys) == A.characteristic_polynomial(var='x') + sage: prod(polys) == A.characteristic_polynomial(var='x') # needs sage.libs.pari True Rational form is a canonical form. Any two matrices are similar @@ -16669,9 +16869,9 @@ cdef class Matrix(Matrix1): ....: [0, -42, 14, 8, 167, -17, -84, 13], ....: [0, -50, 17, 10, 199, -23, -98, 14], ....: [0, 15, -5, -2, -59, 7, 30, -2]]) - sage: C.minimal_polynomial().factor() + sage: C.minimal_polynomial().factor() # needs sage.libs.pari (x - 2)^2 - sage: C.characteristic_polynomial().factor() + sage: C.characteristic_polynomial().factor() # needs sage.libs.pari (x - 2)^8 sage: C.rational_form() [ 0 -4| 0 0| 0 0| 0 0] @@ -16694,9 +16894,9 @@ cdef class Matrix(Matrix1): ....: [ 31, -18, 135, 38, 12, 47, 155, -147], ....: [-33, 19, -138, -39, -13, -45, -156, 151], ....: [ -7, 4, -29, -8, -3, -10, -34, 34]]) - sage: D.minimal_polynomial().factor() + sage: D.minimal_polynomial().factor() # needs sage.libs.pari (x - 2)^2 - sage: D.characteristic_polynomial().factor() + sage: D.characteristic_polynomial().factor() # needs sage.libs.pari (x - 2)^8 sage: D.rational_form() [ 0 -4| 0 0| 0 0| 0 0] @@ -16719,9 +16919,9 @@ cdef class Matrix(Matrix1): ....: [-3, -7, 5, -6, -1, 5, -4, 14], ....: [ 6, 18, -10, 14, 4, -10, 10, -28], ....: [-2, -6, 4, -5, -1, 3, -3, 13]]) - sage: E.minimal_polynomial().factor() + sage: E.minimal_polynomial().factor() # needs sage.libs.pari (x - 2)^3 - sage: E.characteristic_polynomial().factor() + sage: E.characteristic_polynomial().factor() # needs sage.libs.pari (x - 2)^8 sage: E.rational_form() [ 2| 0 0| 0 0| 0 0 0] @@ -16758,9 +16958,9 @@ cdef class Matrix(Matrix1): ....: [ 139, -35, 99, -49, -18, 236, -41, -70, 370, -118, -377, -619], ....: [ 243, 9, 81, -72, -81, 386, 43, -105, 508, -124, -564, -911], ....: [-155, -3, -55, 45, 50, -245, -27, 65, -328, 77, 365, 583]]) - sage: A.characteristic_polynomial().factor() + sage: A.characteristic_polynomial().factor() # needs sage.libs.pari (x^2 - 2)^2 * (x^2 + 2*x + 5)^4 - sage: A.eigenvalues(extend=False) + sage: A.eigenvalues(extend=False) # needs sage.rings.number_field [] sage: A.rational_form() [ 0 -5| 0 0 0 0| 0 0 0 0 0 0] @@ -16779,12 +16979,13 @@ cdef class Matrix(Matrix1): [ 0 0| 0 0 0 0| 0 0 0 0 1 -4] sage: F. = QQ[] sage: polys = A.rational_form(format='invariants') - sage: [F(p).factor() for p in polys] + sage: [F(p).factor() for p in polys] # needs sage.libs.pari [x^2 + 2*x + 5, (x^2 - 2) * (x^2 + 2*x + 5), (x^2 - 2) * (x^2 + 2*x + 5)^2] Rational form may be computed over any field. The matrix below is an example where the eigenvalues lie outside the field. :: + sage: # needs sage.rings.finite_rings sage: F. = FiniteField(7^2) sage: A = matrix(F, ....: [[5*a + 3, 4*a + 1, 6*a + 2, 2*a + 5, 6, 4*a + 5, 4*a + 5, 5, a + 6, 5, 4*a + 4], @@ -17020,24 +17221,25 @@ cdef class Matrix(Matrix1): Nonnegative matrices are positive operators on the nonnegative orthant:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = random_matrix(QQ,3).apply_map(abs) - sage: L.is_positive_operator_on(K) + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = random_matrix(QQ, 3).apply_map(abs) + sage: L.is_positive_operator_on(K) # needs sage.geometry.polyhedron True Symbolic entries also work in some easy cases:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = matrix(SR, [ [0, e, 0 ], + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = matrix(SR, [ [0, e, 0 ], # needs sage.symbolic ....: [0, 2, pi], ....: [sqrt(2), 0, 0 ] ]) - sage: L.is_positive_operator_on(K) + sage: L.is_positive_operator_on(K) # needs sage.geometry.polyhedron sage.symbolic True Your matrix can be over any exact ring, for example the ring of univariate polynomials with rational coefficients:: - sage: K = Cone([(1,0),(-1,0),(0,1),(0,-1)]) + sage: # needs sage.geometry.polyhedron + sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)]) sage: K.is_full_space() True sage: x = polygen(ZZ, 'x') @@ -17049,6 +17251,7 @@ cdef class Matrix(Matrix1): The identity matrix is always a positive operator:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = identity_matrix(R, K.lattice_dim()) @@ -17057,6 +17260,7 @@ cdef class Matrix(Matrix1): The zero matrix is always a positive operator:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = zero_matrix(R, K.lattice_dim()) @@ -17068,11 +17272,12 @@ cdef class Matrix(Matrix1): the underlying ring symbolic (the usual case is tested by the ``positive_operators_gens`` method):: + sage: # needs sage.geometry.polyhedron sage.symbolic sage: K1 = random_cone(max_ambient_dim=5) sage: K2 = random_cone(max_ambient_dim=5) sage: results = ( L.change_ring(SR).is_positive_operator_on(K1, K2) ....: for L in K1.positive_operators_gens(K2) ) - sage: all(results) # long time + sage: all(results) # long time True Technically we could test this, but for now only closed convex cones @@ -17087,9 +17292,9 @@ cdef class Matrix(Matrix1): We can't give reliable answers over inexact rings:: - sage: K = Cone([(1,2,3), (4,5,6)]) - sage: L = identity_matrix(RR,3) - sage: L.is_positive_operator_on(K) + sage: K = Cone([(1,2,3), (4,5,6)]) # needs sage.geometry.polyhedron + sage: L = identity_matrix(RR, 3) + sage: L.is_positive_operator_on(K) # needs sage.geometry.polyhedron Traceback (most recent call last): ... ValueError: The base ring of the matrix is neither symbolic nor @@ -17097,6 +17302,7 @@ cdef class Matrix(Matrix1): Symbolic subrings are fine:: + sage: # needs sage.geometry.polyhedron sage.symbolic sage: SCR = SR.subring(no_variables=True); SCR Symbolic Constants Subring sage: K = Cone([(1,2,3), (4,5,6)]) @@ -17179,26 +17385,27 @@ cdef class Matrix(Matrix1): Negative Z-matrices are cross-positive operators on the nonnegative orthant:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = matrix(SR, [ [-1, 2, 0], + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = matrix(SR, [ [-1, 2, 0], # needs sage.symbolic ....: [ 0, 2, 7], ....: [ 3, 0, 3] ]) - sage: L.is_cross_positive_on(K) + sage: L.is_cross_positive_on(K) # needs sage.geometry.polyhedron sage.symbolic True Symbolic entries also work in some easy cases:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = matrix(SR, [ [-1, e, 0 ], + sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) # needs sage.geometry.polyhedron + sage: L = matrix(SR, [ [-1, e, 0 ], # needs sage.symbolic ....: [ 0, 2, pi], ....: [ sqrt(2), 0, 3 ] ]) - sage: L.is_cross_positive_on(K) + sage: L.is_cross_positive_on(K) # needs sage.geometry.polyhedron sage.symbolic True TESTS: The identity matrix is always cross-positive:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = identity_matrix(R, K.lattice_dim()) @@ -17207,6 +17414,7 @@ cdef class Matrix(Matrix1): The zero matrix is always cross-positive:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = zero_matrix(R, K.lattice_dim()) @@ -17218,10 +17426,11 @@ cdef class Matrix(Matrix1): symbolic (the usual case is tested by the ``cross_positive_operators_gens`` method):: + sage: # needs sage.geometry.polyhedron sage.symbolic sage: K = random_cone(max_ambient_dim=5) sage: results = ( L.change_ring(SR).is_cross_positive_on(K) ....: for L in K.cross_positive_operators_gens() ) - sage: all(results) # long time + sage: all(results) # long time True Technically we could test this, but for now only closed convex cones @@ -17236,9 +17445,9 @@ cdef class Matrix(Matrix1): We can't give reliable answers over inexact rings:: - sage: K = Cone([(1,2,3), (4,5,6)]) - sage: L = identity_matrix(RR,3) - sage: L.is_cross_positive_on(K) + sage: K = Cone([(1,2,3), (4,5,6)]) # needs sage.geometry.polyhedron + sage: L = identity_matrix(RR, 3) + sage: L.is_cross_positive_on(K) # needs sage.geometry.polyhedron Traceback (most recent call last): ... ValueError: The base ring of the matrix is neither symbolic nor @@ -17246,6 +17455,7 @@ cdef class Matrix(Matrix1): Symbolic subrings are fine:: + sage: # needs sage.geometry.polyhedron sage.symbolic sage: SCR = SR.subring(no_variables=True); SCR Symbolic Constants Subring sage: K = Cone([(1,2,3), (4,5,6)]) @@ -17317,26 +17527,27 @@ cdef class Matrix(Matrix1): Z-matrices are Z-operators on the nonnegative orthant:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = matrix(SR, [ [-1, -2, 0], + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = matrix(SR, [ [-1, -2, 0], # needs sage.symbolic ....: [ 0, 2, -7], ....: [-3, 0, 3] ]) - sage: L.is_Z_operator_on(K) + sage: L.is_Z_operator_on(K) # needs sage.geometry.polyhedron sage.symbolic True Symbolic entries also work in some easy cases:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = matrix(SR, [ [-1, -e, 0 ], + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = matrix(SR, [ [-1, -e, 0 ], # needs sage.symbolic ....: [ 0, 2, -pi], ....: [-sqrt(2), 0, 3 ] ]) - sage: L.is_Z_operator_on(K) + sage: L.is_Z_operator_on(K) # needs sage.geometry.polyhedron sage.symbolic True TESTS: The identity matrix is always a Z-operator:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = identity_matrix(R, K.lattice_dim()) @@ -17345,6 +17556,7 @@ cdef class Matrix(Matrix1): The zero matrix is always a Z-operator:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = zero_matrix(R, K.lattice_dim()) @@ -17355,8 +17567,8 @@ cdef class Matrix(Matrix1): ``K``, , even if we make the underlying ring symbolic (the usual case is tested by the ``Z_operators_gens`` method):: - sage: K = random_cone(max_ambient_dim=5) - sage: all(L.change_ring(SR).is_Z_operator_on(K) # long time + sage: K = random_cone(max_ambient_dim=5) # needs sage.geometry.polyhedron + sage: all(L.change_ring(SR).is_Z_operator_on(K) # long time # needs sage.geometry.polyhedron sage.symbolic ....: for L in K.Z_operators_gens()) True @@ -17372,9 +17584,9 @@ cdef class Matrix(Matrix1): We can't give reliable answers over inexact rings:: - sage: K = Cone([(1,2,3), (4,5,6)]) - sage: L = identity_matrix(RR,3) - sage: L.is_Z_operator_on(K) + sage: K = Cone([(1,2,3), (4,5,6)]) # needs sage.geometry.polyhedron + sage: L = identity_matrix(RR, 3) + sage: L.is_Z_operator_on(K) # needs sage.geometry.polyhedron Traceback (most recent call last): ... ValueError: The base ring of the matrix is neither symbolic nor @@ -17436,24 +17648,25 @@ cdef class Matrix(Matrix1): Diagonal matrices are Lyapunov-like operators on the nonnegative orthant:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = diagonal_matrix(random_vector(QQ,3)) - sage: L.is_lyapunov_like_on(K) + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = diagonal_matrix(random_vector(QQ, 3)) + sage: L.is_lyapunov_like_on(K) # needs sage.geometry.polyhedron True Symbolic entries also work in some easy cases:: - sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) - sage: L = matrix(SR, [ [e, 0, 0 ], + sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)]) # needs sage.geometry.polyhedron + sage: L = matrix(SR, [ [e, 0, 0 ], # needs sage.symbolic ....: [0, pi, 0 ], ....: [0, 0, sqrt(2)] ]) - sage: L.is_lyapunov_like_on(K) + sage: L.is_lyapunov_like_on(K) # needs sage.geometry.polyhedron sage.symbolic True TESTS: The identity matrix is always Lyapunov-like:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = identity_matrix(R, K.lattice_dim()) @@ -17462,6 +17675,7 @@ cdef class Matrix(Matrix1): The zero matrix is always Lyapunov-like:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=8) sage: R = K.lattice().vector_space().base_ring() sage: L = zero_matrix(R, K.lattice_dim()) @@ -17473,8 +17687,8 @@ cdef class Matrix(Matrix1): symbolic (the usual case is tested by the ``lyapunov_like_basis`` method):: - sage: K = random_cone(max_ambient_dim=5) - sage: all(L.change_ring(SR).is_lyapunov_like_on(K) # long time + sage: K = random_cone(max_ambient_dim=5) # needs sage.geometry.polyhedron + sage: all(L.change_ring(SR).is_lyapunov_like_on(K) # long time # needs sage.geometry.polyhedron sage.symbolic ....: for L in K.lyapunov_like_basis()) True @@ -17490,9 +17704,9 @@ cdef class Matrix(Matrix1): We can't give reliable answers over inexact rings:: - sage: K = Cone([(1,2,3), (4,5,6)]) - sage: L = identity_matrix(RR,3) - sage: L.is_lyapunov_like_on(K) + sage: K = Cone([(1,2,3), (4,5,6)]) # needs sage.geometry.polyhedron + sage: L = identity_matrix(RR, 3) + sage: L.is_lyapunov_like_on(K) # needs sage.geometry.polyhedron Traceback (most recent call last): ... ValueError: The base ring of the matrix is neither symbolic nor @@ -17500,6 +17714,7 @@ cdef class Matrix(Matrix1): Symbolic subrings are fine:: + sage: # needs sage.geometry.polyhedron sage.symbolic sage: SCR = SR.subring(no_variables=True); SCR Symbolic Constants Subring sage: K = Cone([(1,2,3), (4,5,6)]) @@ -17510,13 +17725,14 @@ cdef class Matrix(Matrix1): A matrix is Lyapunov-like on a cone if and only if both the matrix and its negation are cross-positive on the cone:: + sage: # needs sage.geometry.polyhedron sage: K = random_cone(max_ambient_dim=5) sage: R = K.lattice().vector_space().base_ring() sage: L = random_matrix(R, K.lattice_dim()) - sage: actual = L.is_lyapunov_like_on(K) # long time - sage: expected = (L.is_cross_positive_on(K) and # long time + sage: actual = L.is_lyapunov_like_on(K) # long time + sage: expected = (L.is_cross_positive_on(K) and # long time ....: (-L).is_cross_positive_on(K)) - sage: actual == expected # long time + sage: actual == expected # long time True """ import sage.geometry.abc @@ -17577,9 +17793,9 @@ cdef class Matrix(Matrix1): Create a Gram matrix and LLL-reduce it:: sage: M = Matrix(ZZ, 2, 2, [5, 3, 3, 2]) - sage: U = M.LLL_gram() - sage: MM = U.transpose() * M * U - sage: M, U, MM + sage: U = M.LLL_gram() # needs sage.libs.pari + sage: MM = U.transpose() * M * U # needs sage.libs.pari + sage: M, U, MM # needs sage.libs.pari ( [5 3] [-1 1] [1 0] [3 2], [ 1 -2], [0 1] @@ -17591,28 +17807,28 @@ cdef class Matrix(Matrix1): preserve orientation). :: sage: M = Matrix(RDF, 2, 2, [1, 0, 0, 1e-5]) - sage: M.LLL_gram() + sage: M.LLL_gram() # needs sage.libs.pari [ 0 -1] [ 1 0] The algorithm might work for some semidefinite and indefinite forms:: - sage: Matrix(ZZ, 2, 2, [2, 6, 6, 3]).LLL_gram() + sage: Matrix(ZZ, 2, 2, [2, 6, 6, 3]).LLL_gram() # needs sage.libs.pari [-3 -1] [ 1 0] - sage: Matrix(ZZ, 2, 2, [1, 0, 0, -1]).LLL_gram() + sage: Matrix(ZZ, 2, 2, [1, 0, 0, -1]).LLL_gram() # needs sage.libs.pari [ 0 -1] [ 1 0] However, it might fail for others, either raising a ``ValueError``:: - sage: Matrix(ZZ, 1, 1, [0]).LLL_gram() + sage: Matrix(ZZ, 1, 1, [0]).LLL_gram() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: qflllgram did not return a square matrix, perhaps the matrix is not positive definite - sage: Matrix(ZZ, 2, 2, [0, 1, 1, 0]).LLL_gram() + sage: Matrix(ZZ, 2, 2, [0, 1, 1, 0]).LLL_gram() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: qflllgram did not return a square matrix, @@ -17620,14 +17836,14 @@ cdef class Matrix(Matrix1): or running forever:: - sage: Matrix(ZZ, 2, 2, [-5, -1, -1, -5]).LLL_gram() # not tested + sage: Matrix(ZZ, 2, 2, [-5, -1, -1, -5]).LLL_gram() # not tested, needs sage.libs.pari Traceback (most recent call last): ... RuntimeError: infinite loop while calling qflllgram Nonreal input leads to a value error:: - sage: Matrix(2, 2, [CDF(1, 1), 0, 0, 1]).LLL_gram() + sage: Matrix(2, 2, [CDF(1, 1), 0, 0, 1]).LLL_gram() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: qflllgram failed, perhaps the matrix is not positive definite @@ -17681,10 +17897,10 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], + sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], # needs sage.rings.number_field ....: [7 + 3*I, -1 + 6*I, 3 + 5*I], ....: [3 + 3*I, -3 + 6*I, 5 + I]]) - sage: A.C + sage: A.C # needs sage.rings.number_field [ -3 5 + 3*I 7 + 4*I] [ 7 - 3*I -1 - 6*I 3 - 5*I] [ 3 - 3*I -3 - 6*I 5 - 1*I] @@ -17699,10 +17915,10 @@ cdef class Matrix(Matrix1): EXAMPLES:: - sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], + sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], # needs sage.rings.number_field ....: [7 + 3*I, -1 + 6*I, 3 + 5*I], ....: [3 + 3*I, -3 + 6*I, 5 + I]]) - sage: A.H + sage: A.H # needs sage.rings.number_field [ -3 7 - 3*I 3 - 3*I] [ 5 + 3*I -1 - 6*I -3 - 6*I] [ 7 + 4*I 3 - 5*I 5 - 1*I] @@ -17721,18 +17937,19 @@ def _smith_diag(d, transformation=True): EXAMPLES:: + sage: # needs sage.rings.number_field sage: from sage.matrix.matrix2 import _smith_diag sage: x = polygen(ZZ, 'x') - sage: OE = EquationOrder(x^2 - x + 2, 'w') # optional - sage.rings.number_field - sage: A = matrix(OE, 2, [2, 0, 0, 3]) # optional - sage.rings.number_field - sage: D,U,V = _smith_diag(A); D,U,V # optional - sage.rings.number_field + sage: OE = EquationOrder(x^2 - x + 2, 'w') + sage: A = matrix(OE, 2, [2, 0, 0, 3]) + sage: D,U,V = _smith_diag(A); D,U,V ( [1 0] [2 1] [ 1 -3] [0 6], [3 2], [-1 4] ) sage: D == U*A*V True - sage: m = matrix(GF(7),2, [3,0,0,6]); d,u,v = _smith_diag(m); d + sage: m = matrix(GF(7), 2, [3,0,0,6]); d,u,v = _smith_diag(m); d [1 0] [0 1] sage: u*m*v == d @@ -17799,12 +18016,13 @@ def _generic_clear_column(m): EXAMPLES:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: L. = NumberField(x^2 - x + 2) # optional - sage.rings.number_field - sage: OL = L.ring_of_integers(); w = OL(w) # optional - sage.rings.number_field - sage: m = matrix(OL, 8, 4, [2*w - 2, 2*w + 1, -2, w, 2, -2, -2*w - 2, -2*w + 2, -w + 2, 2*w + 1, -w + 2, -w - 2, -2*w, # optional - sage.rings.number_field + sage: L. = NumberField(x^2 - x + 2) + sage: OL = L.ring_of_integers(); w = OL(w) + sage: m = matrix(OL, 8, 4, [2*w - 2, 2*w + 1, -2, w, 2, -2, -2*w - 2, -2*w + 2, -w + 2, 2*w + 1, -w + 2, -w - 2, -2*w, ....: 2*w, -w+ 2, w - 1, -2*w + 2, 2*w + 2, 2*w - 1, -w, 2*w + 2, -w + 2, 2, 2*w -1, w - 4, -2*w - 2, 2*w - 1, 0, 6, 7, 2*w + 1, 14]) - sage: s,t = m.echelon_form(transformation=True); t*m == s # indirect doctest # optional - sage.rings.number_field + sage: s,t = m.echelon_form(transformation=True); t*m == s # indirect doctest True sage: s[0] (w, 0, 0, 0) @@ -17907,11 +18125,12 @@ def _smith_onestep(m): EXAMPLES:: + sage: # needs sage.rings.number_field sage: from sage.matrix.matrix2 import _smith_onestep sage: x = polygen(ZZ, 'x') - sage: OE. = EquationOrder(x^2 - x + 2) # optional - sage.rings.number_field - sage: m = matrix(OE, 3, 3, [1, 0, 7, 2, w, w+17, 13+8*w, 0, 6]) # optional - sage.rings.number_field - sage: a,b,c = _smith_onestep(m); b # optional - sage.rings.number_field + sage: OE. = EquationOrder(x^2 - x + 2) + sage: m = matrix(OE, 3, 3, [1, 0, 7, 2, w, w+17, 13+8*w, 0, 6]) + sage: a,b,c = _smith_onestep(m); b [ 1 0 0] [ 0 w w + 3] [ 0 0 -56*w - 85] @@ -17995,7 +18214,7 @@ def _choose(Py_ssize_t n, Py_ssize_t t): cdef Py_ssize_t j, temp x = [] # initialize T1 - c = list(xrange(t)) + c = list(range(t)) if t == n: x.append(c) return x @@ -18081,11 +18300,13 @@ def _jordan_form_vector_in_difference(V, W): sage: sage.matrix.matrix2._jordan_form_vector_in_difference([v,w], [u]) (1, 0, 0, 0) """ + from sage.modules.free_module import span + if not V: return None if not W: return V[0] - W_space = sage.all.span(W) + W_space = span(W) for v in V: if v not in W_space: return v @@ -18113,6 +18334,7 @@ def _matrix_power_symbolic(A, n): General power of a two by two matrix:: + sage: # needs sage.symbolic sage: n = SR.var('n') sage: A = matrix(QQ, [[2, -1], [1, 0]]) sage: B = A^n; B @@ -18123,9 +18345,9 @@ def _matrix_power_symbolic(A, n): General power of a three by three matrix in Jordan form:: + sage: # needs sage.symbolic sage: n = SR.var('n') - sage: A = matrix(QQ, 3, [[2, 1, 0], [0, 2, 0], [0, 0, 3]]) - sage: A + sage: A = matrix(QQ, 3, [[2, 1, 0], [0, 2, 0], [0, 0, 3]]); A [2 1 0] [0 2 0] [0 0 3] @@ -18138,8 +18360,8 @@ def _matrix_power_symbolic(A, n): General power of a three by three matrix not in Jordan form:: - sage: A = matrix([[4, 1, 2], [0, 2, -4], [0, 1, 6]]) - sage: A + sage: # needs sage.symbolic + sage: A = matrix([[4, 1, 2], [0, 2, -4], [0, 1, 6]]); A [ 4 1 2] [ 0 2 -4] [ 0 1 6] @@ -18160,9 +18382,9 @@ def _matrix_power_symbolic(A, n): Testing exponentiation in the symbolic ring:: - sage: n = var('n') - sage: A = matrix([[pi, e],[0, -2*I]]) - sage: (A^n).list() + sage: n = var('n') # needs sage.symbolic + sage: A = matrix([[pi, e],[0, -2*I]]) # needs sage.symbolic + sage: (A^n).list() # needs sage.symbolic [pi^n, -(-2*I)^n/(pi*e^(-1) + 2*I*e^(-1)) + pi^n/(pi*e^(-1) + 2*I*e^(-1)), 0, @@ -18171,22 +18393,22 @@ def _matrix_power_symbolic(A, n): If the base ring is inexact, the Jordan normal form is not available:: sage: A = matrix(RDF, [[2, -1], [1, 0]]) - sage: A^n + sage: A^n # needs sage.symbolic Traceback (most recent call last): ... ValueError: Jordan normal form not implemented over inexact rings. Testing exponentiation in the integer ring:: - sage: A = matrix(ZZ, [[1,-1],[-1,1]]) - sage: A^(2*n+1) + sage: A = matrix(ZZ, [[1,-1], [-1,1]]) + sage: A^(2*n+1) # needs sage.symbolic [ 1/2*2^(2*n + 1) -1/2*2^(2*n + 1)] [-1/2*2^(2*n + 1) 1/2*2^(2*n + 1)] Check if :trac:`23215` is fixed:: - sage: a, b, k = var('a, b, k') - sage: (matrix(2, [a, b, -b, a])^k).list() + sage: a, b, k = var('a, b, k') # needs sage.symbolic + sage: (matrix(2, [a, b, -b, a])^k).list() # needs sage.symbolic [1/2*(a + I*b)^k + 1/2*(a - I*b)^k, -1/2*I*(a + I*b)^k + 1/2*I*(a - I*b)^k, 1/2*I*(a + I*b)^k - 1/2*I*(a - I*b)^k, diff --git a/src/sage/matrix/matrix_cdv.pyx b/src/sage/matrix/matrix_cdv.pyx index 43421c74cb9..dfbdb053328 100644 --- a/src/sage/matrix/matrix_cdv.pyx +++ b/src/sage/matrix/matrix_cdv.pyx @@ -35,6 +35,7 @@ cpdef hessenbergize_cdvf(Matrix_generic_dense H): TESTS:: + sage: # needs sage.rings.padics sage: K = Qp(5, print_mode="digits", prec=5) sage: H = matrix(K, 3, 3, range(9)) sage: H @@ -49,14 +50,16 @@ cpdef hessenbergize_cdvf(Matrix_generic_dense H): :: - sage: M = random_matrix(K, 6, 6) - sage: M.charpoly()[0] == M.determinant() + sage: M = random_matrix(K, 6, 6) # needs sage.rings.padics + sage: M.charpoly()[0] == M.determinant() # needs sage.rings.padics True We check that :trac:`31753` is resolved:: sage: R. = GF(5)[[]] - sage: M = matrix(3, 3, [ 1, t + O(t^3), t^2, 1 + t + O(t^3), 2 + t^2, 3 + 2*t + O(t^3), t - t^2, 2*t, 1 + t ]) + sage: M = matrix(3, 3, [ 1, t + O(t^3), t^2, + ....: 1 + t + O(t^3), 2 + t^2, 3 + 2*t + O(t^3), + ....: t - t^2, 2*t, 1 + t ]) sage: M.charpoly() x^3 + (1 + 4*t + 4*t^2 + O(t^3))*x^2 + (t + 2*t^2 + O(t^3))*x + 3 + 2*t^2 + O(t^3) """ diff --git a/src/sage/matrix/matrix_complex_ball_dense.pyx b/src/sage/matrix/matrix_complex_ball_dense.pyx index ad57de71deb..47ca41070fa 100644 --- a/src/sage/matrix/matrix_complex_ball_dense.pyx +++ b/src/sage/matrix/matrix_complex_ball_dense.pyx @@ -664,7 +664,7 @@ cdef class Matrix_complex_ball_dense(Matrix_dense): Pol = polynomial_ring_constructor._single_variate(self.base_ring(), var) cdef Polynomial_complex_arb res = Polynomial_complex_arb(Pol) sig_on() - acb_mat_charpoly(res.__poly, self.value, prec(self)) + acb_mat_charpoly(res._poly, self.value, prec(self)) sig_off() return res @@ -945,7 +945,7 @@ cdef class Matrix_complex_ball_dense(Matrix_dense): EXAMPLES:: - sage: matrix(CBF, [[i*pi, 1], [0, i*pi]]).exp() + sage: matrix(CBF, [[i*pi, 1], [0, i*pi]]).exp() # needs sage.symbolic [[-1.00000000000000 +/- ...e-16] + [+/- ...e-16]*I [-1.00000000000000 +/- ...e-16] + [+/- ...e-16]*I] [ 0 [-1.00000000000000 +/- ...e-16] + [+/- ...e-16]*I] sage: matrix(CBF, [[1/2, 1/3]]).exp() diff --git a/src/sage/matrix/matrix_complex_double_dense.pyx b/src/sage/matrix/matrix_complex_double_dense.pyx index 9f8b8ec9fc8..162332eb44e 100644 --- a/src/sage/matrix/matrix_complex_double_dense.pyx +++ b/src/sage/matrix/matrix_complex_double_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy """ Dense matrices over the Complex Double Field using NumPy diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index 0b78bb7fd78..f1ed9af8403 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -396,11 +396,11 @@ cdef class Matrix_cyclo_dense(Matrix_dense): # Now set k-th entry of x's numerator to tmp fmpz_get_mpz(tmp, ftmp) mpz_to_ZZ(&coeff, tmp) - ZZX_SetCoeff(x.__numerator, k, coeff) + ZZX_SetCoeff(x._numerator, k, coeff) # Set the denominator of x to denom. fmpz_get_mpz(tmp, denom) - mpz_to_ZZ(&x.__denominator, tmp) + mpz_to_ZZ(&x._denominator, tmp) fmpz_clear(denom) mpz_clear(tmp) fmpz_clear(ftmp) @@ -814,7 +814,6 @@ cdef class Matrix_cyclo_dense(Matrix_dense): A._matrix = -self._matrix return A - ######################################################################## # LEVEL 3 functionality (Optional) # * __deepcopy__ @@ -824,6 +823,7 @@ cdef class Matrix_cyclo_dense(Matrix_dense): # * Specialized echelon form # * tensor product ######################################################################## + def set_immutable(self): """ Change this matrix so that it is immutable. diff --git a/src/sage/matrix/matrix_dense.pyx b/src/sage/matrix/matrix_dense.pyx index 164846caba1..0f5089b5122 100644 --- a/src/sage/matrix/matrix_dense.pyx +++ b/src/sage/matrix/matrix_dense.pyx @@ -74,6 +74,7 @@ cdef class Matrix_dense(matrix.Matrix): Check :trac:`27629`:: + sage: # needs sage.symbolic sage: var('x') x sage: assume(x, 'real') @@ -270,8 +271,8 @@ cdef class Matrix_dense(matrix.Matrix): EXAMPLES:: - sage: m = matrix(2, [x^i for i in range(4)]) - sage: m._derivative(x) + sage: m = matrix(2, [x^i for i in range(4)]) # needs sage.symbolic + sage: m._derivative(x) # needs sage.symbolic [ 0 1] [ 2*x 3*x^2] """ diff --git a/src/sage/matrix/matrix_double_dense.pyx b/src/sage/matrix/matrix_double_dense.pyx index 4515e01978e..bf8ade78c14 100644 --- a/src/sage/matrix/matrix_double_dense.pyx +++ b/src/sage/matrix/matrix_double_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy """ Dense matrices using a NumPy backend @@ -1374,7 +1375,7 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): location = None best_fit = tol for i in range(len(ev_group)): - s, m, avg = ev_group[i] + _, m, avg = ev_group[i] d = numpy.abs(avg - e) if d < best_fit: best_fit = d @@ -1738,14 +1739,13 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): import scipy import scipy.linalg X = self._new(self._ncols, B.ncols()) - arr, resid, rank, s = scipy.linalg.lstsq(self._matrix_numpy, B.numpy()) + arr = scipy.linalg.lstsq(self._matrix_numpy, B.numpy())[0] X._matrix_numpy = arr return X - def determinant(self): """ - Return the determinant of self. + Return the determinant of ``self``. ALGORITHM: @@ -1807,7 +1807,6 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): [] sage: m.log_determinant() 0.0 - """ global numpy cdef Matrix_double_dense U @@ -1818,7 +1817,7 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): if not self.is_square(): raise ArithmeticError("self must be a square matrix") - P, L, U = self.LU() + _, _, U = self.LU() if numpy is None: import numpy @@ -2489,7 +2488,7 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): return True if numpy is None: import numpy - cdef Py_ssize_t i, j + cdef Py_ssize_t i cdef Matrix_double_dense T # A matrix M is skew-hermitian iff I*M is hermitian T = self.__mul__(1j) if skew else self.__copy__() @@ -2499,13 +2498,13 @@ cdef class Matrix_double_dense(Matrix_numpy_dense): hermitian = T._is_lower_triangular(tol) if hermitian: for i in range(T._nrows): - if abs(T.get_unsafe(i,i).imag()) > tol: + if abs(T.get_unsafe(i, i).imag()) > tol: hermitian = False break self.cache(key, hermitian) return hermitian - def is_hermitian(self, tol = 1e-12, algorithm = "naive"): + def is_hermitian(self, tol=1e-12, algorithm = "naive"): r""" Return ``True`` if the matrix is equal to its conjugate-transpose. diff --git a/src/sage/matrix/matrix_generic_dense.pyx b/src/sage/matrix/matrix_generic_dense.pyx index da22ca12175..9c16ac3c486 100644 --- a/src/sage/matrix/matrix_generic_dense.pyx +++ b/src/sage/matrix/matrix_generic_dense.pyx @@ -69,9 +69,10 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): We check that the problem related to :trac:`9049` is not an issue any more:: - sage: S.=PolynomialRing(QQ) - sage: F.=QQ.extension(t^4+1) - sage: R.=PolynomialRing(F) + sage: # needs sage.rings.number_field + sage: S. = PolynomialRing(QQ) + sage: F. = QQ.extension(t^4 + 1) + sage: R. = PolynomialRing(F) sage: M = MatrixSpace(R, 1, 2) sage: from sage.matrix.matrix_generic_dense import Matrix_generic_dense sage: Matrix_generic_dense(M, (x, y), True, True) @@ -214,7 +215,8 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): EXAMPLES:: - sage: R. = FreeAlgebra(QQ,2) + sage: # needs sage.combinat + sage: R. = FreeAlgebra(QQ, 2) sage: a = matrix(R, 2, 2, [1,2,x*y,y*x]) sage: b = matrix(R, 2, 2, [1,2,y*x,y*x]) sage: a._add_(b) @@ -237,7 +239,8 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): EXAMPLES:: - sage: R. = FreeAlgebra(QQ,2) + sage: # needs sage.combinat + sage: R. = FreeAlgebra(QQ, 2) sage: a = matrix(R, 2, 2, [1,2,x*y,y*x]) sage: b = matrix(R, 2, 2, [1,2,y*x,y*x]) sage: a._sub_(b) diff --git a/src/sage/matrix/matrix_generic_sparse.pyx b/src/sage/matrix/matrix_generic_sparse.pyx index df138cfab3f..4cd7cecc7e8 100644 --- a/src/sage/matrix/matrix_generic_sparse.pyx +++ b/src/sage/matrix/matrix_generic_sparse.pyx @@ -4,8 +4,9 @@ Sparse Matrices over a general ring EXAMPLES:: sage: R. = PolynomialRing(QQ) - sage: M = MatrixSpace(QQ['x'],2,3,sparse=True); M - Full MatrixSpace of 2 by 3 sparse matrices over Univariate Polynomial Ring in x over Rational Field + sage: M = MatrixSpace(QQ['x'], 2, 3, sparse=True); M + Full MatrixSpace of 2 by 3 sparse matrices over + Univariate Polynomial Ring in x over Rational Field sage: a = M(range(6)); a [0 1 2] [3 4 5] @@ -15,7 +16,7 @@ EXAMPLES:: sage: a * b.transpose() [ 2*x^2 + x 2*x^5 + x^4] [ 5*x^2 + 4*x + 3 5*x^5 + 4*x^4 + 3*x^3] - sage: pari(a)*pari(b.transpose()) + sage: pari(a)*pari(b.transpose()) # needs sage.libs.pari [2*x^2 + x, 2*x^5 + x^4; 5*x^2 + 4*x + 3, 5*x^5 + 4*x^4 + 3*x^3] sage: c = copy(b); c [ 1 x x^2] diff --git a/src/sage/matrix/matrix_gf2e_dense.pyx b/src/sage/matrix/matrix_gf2e_dense.pyx index fe8cfb0d38b..977dbd0d6b5 100644 --- a/src/sage/matrix/matrix_gf2e_dense.pyx +++ b/src/sage/matrix/matrix_gf2e_dense.pyx @@ -804,7 +804,6 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): cdef m4ri_word mask = (1<<(self._parent.base_ring().degree())) - 1 cdef randstate rstate = current_randstate() - K = self._parent.base_ring() if self._ncols == 0 or self._nrows == 0: return @@ -898,7 +897,7 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): self.cache('pivots', []) return self - cdef int k, n, full + cdef int full full = int(reduced) diff --git a/src/sage/matrix/matrix_gfpn_dense.pyx b/src/sage/matrix/matrix_gfpn_dense.pyx index abd0754db48..49a556ba7d4 100644 --- a/src/sage/matrix/matrix_gfpn_dense.pyx +++ b/src/sage/matrix/matrix_gfpn_dense.pyx @@ -730,7 +730,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): x = self.Data.Data cdef int nr = self.Data.Nor cdef int nc = self.Data.Noc - cdef int i, j, k + cdef int i, j FfSetField(fl) FfSetNoc(nc) @@ -1392,15 +1392,13 @@ cdef class Matrix_gfpn_dense(Matrix_dense): True sage: M*int(-1)+M == 0 True - """ if self.Data == NULL: raise ValueError("The matrix must not be empty") - cdef Matrix_gfpn_dense left FfSetField(self.Data.Field) cdef FEL r with cython.cdivision(False): - r = FfFromInt(n%FfChar) + r = FfFromInt(n % FfChar) sig_on() try: mat = MatDup(self.Data) diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 7fe211835cc..bf8819bd30a 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -1094,7 +1094,6 @@ cdef class Matrix_integer_dense(Matrix_dense): sig_off() return ans - ######################################################################## # LEVEL 3 functionality (Optional) # * __deepcopy__ @@ -1372,12 +1371,12 @@ cdef class Matrix_integer_dense(Matrix_dense): if algorithm == 'flint': g = ( PolynomialRing(ZZ, names=var).gen())._new() sig_on() - fmpz_mat_charpoly(g.__poly, self._matrix) + fmpz_mat_charpoly(g._poly, self._matrix) sig_off() elif algorithm == 'linbox': g = ( PolynomialRing(ZZ, names=var).gen())._new() sig_on() - linbox_fmpz_mat_charpoly(g.__poly, self._matrix) + linbox_fmpz_mat_charpoly(g._poly, self._matrix) sig_off() elif algorithm == 'generic': g = Matrix_dense.charpoly(self, var) @@ -1461,7 +1460,7 @@ cdef class Matrix_integer_dense(Matrix_dense): if algorithm == 'linbox': g = ( PolynomialRing(ZZ, names=var).gen())._new() sig_on() - linbox_fmpz_mat_minpoly(g.__poly, self._matrix) + linbox_fmpz_mat_minpoly(g._poly, self._matrix) sig_off() elif algorithm == 'generic': g = Matrix_dense.minpoly(self, var) @@ -1614,7 +1613,7 @@ cdef class Matrix_integer_dense(Matrix_dense): return self._mod_two() elif p < MAX_MODULUS_FLOAT: res_f = Matrix_modn_dense_float.__new__(Matrix_modn_dense_float, - matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None) + matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None, zeroed_alloc=False) for i from 0 <= i < self._nrows: res_row_f = res_f._matrix[i] for j from 0 <= j < self._ncols: @@ -1623,7 +1622,7 @@ cdef class Matrix_integer_dense(Matrix_dense): elif p < MAX_MODULUS_DOUBLE: res_d = Matrix_modn_dense_double.__new__(Matrix_modn_dense_double, - matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None) + matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None, zeroed_alloc=False) for i from 0 <= i < self._nrows: res_row_d = res_d._matrix[i] for j from 0 <= j < self._ncols: @@ -1649,11 +1648,11 @@ cdef class Matrix_integer_dense(Matrix_dense): if p < MAX_MODULUS_FLOAT: res.append( Matrix_modn_dense_float.__new__(Matrix_modn_dense_float, matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), - None, None, None) ) + None, None, None, zeroed_alloc=False) ) elif p < MAX_MODULUS_DOUBLE: res.append( Matrix_modn_dense_double.__new__(Matrix_modn_dense_double, matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), - None, None, None) ) + None, None, None, zeroed_alloc=False) ) else: raise ValueError("p=%d too big."%p) @@ -2743,10 +2742,9 @@ cdef class Matrix_integer_dense(Matrix_dense): import sage.libs.ntl.ntl_mat_ZZ return sage.libs.ntl.ntl_mat_ZZ.ntl_mat_ZZ(self._nrows,self._ncols, self.list()) - - #################################################################################### + ####################################################################### # LLL - #################################################################################### + ####################################################################### def BKZ(self, delta=None, algorithm="fpLLL", fp=None, block_size=10, prune=0, use_givens=False, precision=0, proof=None, **kwds): @@ -4678,7 +4676,7 @@ cdef class Matrix_integer_dense(Matrix_dense): """ if self._nrows == 0: pivots = [] - nonpivots = list(xrange(self._ncols)) + nonpivots = list(range(self._ncols)) X = self.__copy__() d = Integer(1) return pivots, nonpivots, X, d @@ -4947,7 +4945,6 @@ cdef class Matrix_integer_dense(Matrix_dense): new_top = s*row_i + t*row_n new_bot = bg*row_i - ag*row_n - # OK -- now we have to make sure the top part of the matrix # but with row i replaced by # r = s*row_i[j] + t*row_n[j] @@ -4955,7 +4952,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # function with the top part of A (all but last row) and the # row r. - zz = list(xrange(A.nrows() - 1)) + zz = list(range(A.nrows() - 1)) del zz[i] top_mat = A.matrix_from_rows(zz) new_pivots = list(pivots) @@ -5165,7 +5162,6 @@ cdef class Matrix_integer_dense(Matrix_dense): sig_free(T_rows) return res - ################################################################# # operations with matrices ################################################################# diff --git a/src/sage/matrix/matrix_integer_sparse.pyx b/src/sage/matrix/matrix_integer_sparse.pyx index a41677c7b6a..f6d79abf56a 100644 --- a/src/sage/matrix/matrix_integer_sparse.pyx +++ b/src/sage/matrix/matrix_integer_sparse.pyx @@ -29,7 +29,7 @@ TESTS:: from cysignals.memory cimport check_calloc, sig_free from cysignals.signals cimport sig_on, sig_off -from cpython.int cimport PyInt_FromSize_t +from cpython.long cimport PyLong_FromSize_t from sage.ext.stdsage cimport PY_NEW from sage.ext.mod_int cimport * @@ -182,24 +182,21 @@ cdef class Matrix_integer_sparse(Matrix_sparse): return M cpdef _add_(self, right): - cdef Py_ssize_t i, j - cdef mpz_vector *self_row - cdef mpz_vector *M_row + cdef Py_ssize_t i cdef Matrix_integer_sparse M M = Matrix_integer_sparse.__new__(Matrix_integer_sparse, self._parent, None, None, None) cdef mpz_t mul mpz_init_set_si(mul,1) - for i from 0 <= i < self._nrows: + for i in range(self._nrows): mpz_vector_clear(&M._matrix[i]) - add_mpz_vector_init(&M._matrix[i], &self._matrix[i], &(right)._matrix[i], mul) + add_mpz_vector_init(&M._matrix[i], &self._matrix[i], + &(right)._matrix[i], mul) mpz_clear(mul) return M cpdef _sub_(self, right): - cdef Py_ssize_t i, j - cdef mpz_vector *self_row - cdef mpz_vector *M_row + cdef Py_ssize_t i cdef Matrix_integer_sparse M M = Matrix_integer_sparse.__new__(Matrix_integer_sparse, self._parent, None, None, None) @@ -214,6 +211,7 @@ cdef class Matrix_integer_sparse(Matrix_sparse): def _dict(self): """ Unsafe version of the dict method, mainly for internal use. + This may return the dict of elements, but as an *unsafe* reference to the underlying dict of the object. It might be dangerous if you change entries of the returned dict. @@ -222,13 +220,13 @@ cdef class Matrix_integer_sparse(Matrix_sparse): if d is not None: return d - cdef Py_ssize_t i, j, k + cdef Py_ssize_t i, j d = {} - for i from 0 <= i < self._nrows: - for j from 0 <= j < self._matrix[i].num_nonzero: + for i in range(self._nrows): + for j in range(self._matrix[i].num_nonzero): x = Integer() mpz_set((x).value, self._matrix[i].entries[j]) - d[(int(i),int(self._matrix[i].positions[j]))] = x + d[(int(i), int(self._matrix[i].positions[j]))] = x self.cache('dict', d) return d @@ -723,7 +721,7 @@ cdef class Matrix_integer_sparse(Matrix_sparse): del M - return PyInt_FromSize_t(r) + return PyLong_FromSize_t(r) def _det_linbox(self): r""" @@ -869,10 +867,10 @@ cdef class Matrix_integer_sparse(Matrix_sparse): sig_off() cdef size_t i - fmpz_poly_fit_length(g.__poly, p.size()) + fmpz_poly_fit_length(g._poly, p.size()) for i in range(p.size()): - fmpz_poly_set_coeff_mpz(g.__poly, i, p[0][i].get_mpz_const()) - _fmpz_poly_set_length(g.__poly, p.size()) + fmpz_poly_set_coeff_mpz(g._poly, i, p[0][i].get_mpz_const()) + _fmpz_poly_set_length(g._poly, p.size()) del M del p @@ -968,10 +966,10 @@ cdef class Matrix_integer_sparse(Matrix_sparse): sig_off() cdef size_t i - fmpz_poly_fit_length(g.__poly, p.size()) + fmpz_poly_fit_length(g._poly, p.size()) for i in range(p.size()): - fmpz_poly_set_coeff_mpz(g.__poly, i, p[0][i].get_mpz_const()) - _fmpz_poly_set_length(g.__poly, p.size()) + fmpz_poly_set_coeff_mpz(g._poly, i, p[0][i].get_mpz_const()) + _fmpz_poly_set_length(g._poly, p.size()) del M del p diff --git a/src/sage/matrix/matrix_mod2_dense.pyx b/src/sage/matrix/matrix_mod2_dense.pyx index d5a368d9b70..777ce0b409f 100644 --- a/src/sage/matrix/matrix_mod2_dense.pyx +++ b/src/sage/matrix/matrix_mod2_dense.pyx @@ -2057,11 +2057,13 @@ def unpickle_matrix_mod2_dense_v2(r, c, data, size, immutable=False): return A + from sage.misc.persist import register_unpickle_override register_unpickle_override('sage.matrix.matrix_mod2_dense', 'unpickle_matrix_mod2_dense_v1', unpickle_matrix_mod2_dense_v2) + def from_png(filename): """ Returns a dense matrix over GF(2) from a 1-bit PNG image read from diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index ca3382859f5..69569297923 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -90,7 +90,7 @@ We test corner cases for multiplication:: from libc.stdint cimport uint64_t from cpython.bytes cimport * -from cysignals.memory cimport check_malloc, check_allocarray, sig_malloc, sig_free +from cysignals.memory cimport check_malloc, check_allocarray, check_calloc, sig_malloc, sig_free from cysignals.signals cimport sig_check, sig_on, sig_off from sage.libs.gmp.mpz cimport * @@ -123,7 +123,7 @@ from sage.structure.proof.proof import get_flag as get_proof_flag from sage.structure.richcmp cimport rich_to_bool from sage.misc.randstate cimport randstate, current_randstate import sage.matrix.matrix_space as matrix_space -from .args cimport MatrixArgs_init +from .args cimport SparseEntry, MatrixArgs_init from sage.cpython.string cimport char_to_str @@ -441,15 +441,18 @@ cpdef __matrix_from_rows_of_matrices(X): cdef class Matrix_modn_dense_template(Matrix_dense): - def __cinit__(self): + def __cinit__(self, *args, bint zeroed_alloc=True, **kwds): cdef long p = self._base_ring.characteristic() self.p = p if p >= MAX_MODULUS: raise OverflowError("p (=%s) must be < %s."%(p, MAX_MODULUS)) - self._entries = check_allocarray(self._nrows * self._ncols, sizeof(celement)) + if zeroed_alloc: + self._entries = check_calloc(self._nrows * self._ncols, sizeof(celement)) + else: + self._entries = check_allocarray(self._nrows * self._ncols, sizeof(celement)) + self._matrix = check_allocarray(self._nrows, sizeof(celement*)) - cdef unsigned int k cdef Py_ssize_t i k = 0 @@ -462,7 +465,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): TESTS:: sage: import gc - sage: for i in range(10): + sage: for i in range(10): # needs sage.rings.finite_rings ....: A = random_matrix(GF(7),1000,1000) ....: B = random_matrix(Integers(10),1000,1000) ....: C = random_matrix(GF(16007),1000,1000) @@ -508,37 +511,38 @@ cdef class Matrix_modn_dense_template(Matrix_dense): [6 5] [4 2] - sage: Matrix(GF(6434383), 2, 2, [-1, int(-2), GF(7)(-3), 1/4]) + sage: Matrix(GF(6434383), 2, 2, [-1, int(-2), GF(7)(-3), 1/4]) # needs sage.rings.finite_rings [6434382 6434381] [ 4 1608596] - sage: Matrix(Integers(4618990), 2, 2, [-1, int(-2), GF(7)(-3), 1/7]) + sage: Matrix(Integers(4618990), 2, 2, [-1, int(-2), GF(7)(-3), 1/7]) # needs sage.rings.finite_rings [4618989 4618988] [ 4 2639423] """ ma = MatrixArgs_init(parent, entries) cdef long i, j - it = ma.iter(False) + it = ma.iter(convert=False, sparse=True) R = ma.base p = R.characteristic() - for i in range(ma.nrows): - v = self._matrix[i] - for j in range(ma.ncols): - x = next(it) - if type(x) is int: - tmp = (x) % p - v[j] = tmp + (tmp<0)*p - elif type(x) is IntegerMod_int and (x)._parent is R: - v[j] = (x).ivalue - elif type(x) is Integer: - if coerce: - v[j] = mpz_fdiv_ui((x).value, p) - else: - v[j] = mpz_get_ui((x).value) - elif coerce: - v[j] = R(x) + + for t in it: + se = t + x = se.entry + v = self._matrix[se.i] + if type(x) is int: + tmp = (x) % p + v[se.j] = tmp + (tmp<0)*p + elif type(x) is IntegerMod_int and (x)._parent is R: + v[se.j] = (x).ivalue + elif type(x) is Integer: + if coerce: + v[se.j] = mpz_fdiv_ui((x).value, p) else: - v[j] = x + v[se.j] = mpz_get_ui((x).value) + elif coerce: + v[se.j] = R(x) + else: + v[se.j] = x cdef long _hash_(self) except -1: """ @@ -668,6 +672,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): And for larger modulus:: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(1009), 51, 5) sage: data, version = A._pickle() sage: B = A.parent()(0) @@ -786,7 +791,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cdef Matrix_modn_dense_template M cdef celement p = self.p - M = self.__class__.__new__(self.__class__, self._parent,None,None,None) + M = self.__class__.__new__(self.__class__, self._parent,None,None,None, zeroed_alloc=False) sig_on() for i in range(self._nrows*self._ncols): @@ -825,7 +830,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cdef celement p = self.p cdef celement a = left - M = self.__class__.__new__(self.__class__, self._parent,None,None,None) + M = self.__class__.__new__(self.__class__, self._parent,None,None,None,zeroed_alloc=False) sig_on() for i in range(self._nrows*self._ncols): @@ -844,7 +849,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): False """ cdef Matrix_modn_dense_template A - A = self.__class__.__new__(self.__class__, self._parent, 0, 0, 0) + A = self.__class__.__new__(self.__class__,self._parent,None,None,None,zeroed_alloc=False) memcpy(A._entries, self._entries, sizeof(celement)*self._nrows*self._ncols) if self._subdivisions is not None: A.subdivide(*self.subdivisions()) @@ -883,7 +888,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cdef celement k, p cdef Matrix_modn_dense_template M - M = self.__class__.__new__(self.__class__, self._parent,None,None,None) + M = self.__class__.__new__(self.__class__, self._parent,None,None,None,zeroed_alloc=False) p = self.p cdef celement* other_ent = (right)._entries @@ -920,7 +925,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cdef celement k, p cdef Matrix_modn_dense_template M - M = self.__class__.__new__(self.__class__, self._parent, None, None, None) + M = self.__class__.__new__(self.__class__, self._parent, None, None, None, zeroed_alloc=False) p = self.p cdef celement* other_ent = (right)._entries @@ -963,11 +968,11 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: A = matrix(ZZ, 10, 10, range(1000, 1100)) sage: A.change_ring(GF(17)) == A.change_ring(GF(17)) True - sage: A.change_ring(GF(17)) == A.change_ring(GF(19)) + sage: A.change_ring(GF(17)) == A.change_ring(GF(19)) # needs sage.rings.finite_rings False - sage: A.change_ring(GF(17)) == A.change_ring(Integers(2000)) + sage: A.change_ring(GF(17)) == A.change_ring(Integers(2000)) # needs sage.rings.finite_rings False - sage: A.change_ring(GF(17)) == A.change_ring(Integers(2000)) + sage: A.change_ring(GF(17)) == A.change_ring(Integers(2000)) # needs sage.rings.finite_rings False """ cdef Py_ssize_t i @@ -1061,8 +1066,8 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: - sage: A = random_matrix(GF(16007),2,2) - sage: B = random_matrix(GF(16007),2,2) + sage: A = random_matrix(GF(16007),2,2) # needs sage.rings.finite_rings + sage: B = random_matrix(GF(16007),2,2) # needs sage.rings.finite_rings sage: C = A*B sage: all(C[i, j] == sum(A[i, k]*B[k, j] for k in range(2)) for i in range(2) for j in range(2)) True @@ -1073,6 +1078,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(15991), 201, 117) sage: B = random_matrix(GF(15991), 117, 195) sage: C = random_matrix(GF(15991), 201, 117) @@ -1087,7 +1093,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: - sage: A = random_matrix(GF(16007), 200, 200) + sage: A = random_matrix(GF(16007), 200, 200) # needs sage.rings.finite_rings sage: MS = parent(A) sage: (MS(0) * A) == 0 True @@ -1160,13 +1166,13 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: matrix(v*A) == matrix(v)*A True - sage: A = random_matrix(GF(4796509), 10, 20) - sage: v = random_vector(GF(4796509), 10) + sage: A = random_matrix(GF(4796509), 10, 20) # needs sage.rings.finite_rings + sage: v = random_vector(GF(4796509), 10) # needs sage.rings.finite_rings sage: matrix(v*A) == matrix(v)*A True sage: A = random_matrix(Integers(16337), 10, 20) - sage: v = random_vector(Integers(16337), 10) + sage: v = random_vector(Integers(16337), 10) # needs sage.rings.finite_rings sage: matrix(v*A) == matrix(v)*A True @@ -1213,13 +1219,13 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: matrix(A*v).transpose() == A*matrix(v).transpose() True - sage: A = random_matrix(GF(4796509), 10, 20) - sage: v = random_vector(GF(4796509), 20) + sage: A = random_matrix(GF(4796509), 10, 20) # needs sage.rings.finite_rings + sage: v = random_vector(GF(4796509), 20) # needs sage.rings.finite_rings sage: matrix(A*v).transpose() == A*matrix(v).transpose() True sage: A = random_matrix(Integers(16337), 10, 20) - sage: v = random_vector(Integers(16337), 20) + sage: v = random_vector(Integers(16337), 20) # needs sage.rings.finite_rings sage: matrix(A*v).transpose() == A*matrix(v).transpose() True """ @@ -1289,7 +1295,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: - sage: A = random_matrix(GF(2916337), 7, 7) + sage: A = random_matrix(GF(2916337), 7, 7) # needs sage.rings.finite_rings sage: B = copy(A) sage: char_p = A.characteristic_polynomial() sage: char_p(A) == 0 @@ -1328,27 +1334,27 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ValueError: matrix must be square sage: A = matrix(GF(19), 10, 10) - sage: A.minimal_polynomial() + sage: A.minimal_polynomial() # needs sage.libs.pari x - sage: A = random_matrix(GF(4198973), 0, 0) - sage: A.minimal_polynomial() + sage: A = random_matrix(GF(4198973), 0, 0) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings 1 - sage: A = random_matrix(GF(4198973), 0, 1) - sage: A.minimal_polynomial() + sage: A = random_matrix(GF(4198973), 0, 1) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: matrix must be square - sage: A = random_matrix(GF(4198973), 1, 0) - sage: A.minimal_polynomial() + sage: A = random_matrix(GF(4198973), 1, 0) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: matrix must be square - sage: A = matrix(GF(4198973), 10, 10) - sage: A.minimal_polynomial() + sage: A = matrix(GF(4198973), 10, 10) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings x sage: A = Mat(GF(7),3,3)([0, 1, 2] * 3) @@ -1443,7 +1449,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: - sage: A = random_matrix(GF(1214471), 10, 10) + sage: A = random_matrix(GF(1214471), 10, 10) # needs sage.rings.finite_rings sage: B = copy(A) sage: min_p = A.minimal_polynomial(proof=True) sage: min_p(A) == 0 @@ -1474,29 +1480,29 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ValueError: matrix must be square sage: A = matrix(GF(17), 10, 10) - sage: A.minimal_polynomial() + sage: A.minimal_polynomial() # needs sage.libs.pari x :: - sage: A = random_matrix(GF(2535919), 0, 0) - sage: A.minimal_polynomial() + sage: A = random_matrix(GF(2535919), 0, 0) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings 1 - sage: A = random_matrix(GF(2535919), 0, 1) - sage: A.minimal_polynomial() + sage: A = random_matrix(GF(2535919), 0, 1) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: matrix must be square - sage: A = random_matrix(GF(2535919), 1, 0) - sage: A.minimal_polynomial() + sage: A = random_matrix(GF(2535919), 1, 0) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: matrix must be square - sage: A = matrix(GF(2535919), 10, 10) - sage: A.minimal_polynomial() + sage: A = matrix(GF(2535919), 10, 10) # needs sage.rings.finite_rings + sage: A.minimal_polynomial() # needs sage.rings.finite_rings x EXAMPLES:: @@ -1639,6 +1645,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 10, 20) sage: E = A.echelon_form() sage: A.row_space() == E.row_space() @@ -1656,6 +1663,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): Parallel computation:: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(65521),100,200) sage: Parallelism().set('linbox', nproc=2) sage: E = A.echelon_form() @@ -1687,6 +1695,8 @@ cdef class Matrix_modn_dense_template(Matrix_dense): [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] + + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 0, 10) sage: A.echelon_form() [] @@ -2126,6 +2136,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 100, 100) sage: B = copy(A) sage: A.rank() @@ -2147,6 +2158,8 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: A = random_matrix(GF(7), 0, 1) sage: A.rank() 0 + + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 0, 0) sage: A.rank() 0 @@ -2193,26 +2206,26 @@ cdef class Matrix_modn_dense_template(Matrix_dense): :: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 10, 10) sage: A.determinant().parent() is GF(16007) True :: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 100, 100) sage: A.determinant().parent() is GF(16007) True - - sage: A.determinant() == A.transpose().determinant() True - sage: B = random_matrix(GF(16007), 100, 100) sage: (A*B).determinant() == A.determinant() * B.determinant() True Parallel computation:: + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(65521),200) sage: B = copy(A) sage: Parallelism().set('linbox', nproc=2) @@ -2237,22 +2250,20 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ... ValueError: self must be a square matrix - sage: A = matrix(GF(7), 5, 5); A.det() + sage: A = matrix(GF(7), 5, 5); A.det() # needs sage.libs.pari 0 + sage: # needs sage.rings.finite_rings sage: A = random_matrix(GF(16007), 0, 0); A.det() 1 - sage: A = random_matrix(GF(16007), 0, 1); A.det() Traceback (most recent call last): ... ValueError: self must be a square matrix - sage: A = random_matrix(GF(16007), 1, 0); A.det() Traceback (most recent call last): ... ValueError: self must be a square matrix - sage: A = matrix(GF(16007), 5, 5); A.det() 0 """ @@ -2738,6 +2749,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: A.lift().parent() Full MatrixSpace of 2 by 3 dense matrices over Integer Ring + sage: # needs sage.rings.finite_rings sage: A = matrix(GF(16007),2,3,[1..6]) sage: A.lift() [1 2 3] @@ -3012,14 +3024,21 @@ cdef class Matrix_modn_dense_template(Matrix_dense): if nrows == -1: nrows = self._nrows - row - if col != 0 or ncols != self._ncols: - return self.matrix_from_rows_and_columns(range(row, row+nrows), range(col, col+ncols)) - if nrows < 0 or row < 0 or row + nrows > self._nrows: raise IndexError("rows out of range") + if ncols < 0 or col < 0 or col + ncols > self._ncols: + raise IndexError("columns out of range") + + cdef Matrix_modn_dense_template M = self.new_matrix(nrows=nrows, ncols=ncols) + + if col == 0 and ncols == self._ncols: + memcpy(M._entries, self._matrix[row], sizeof(celement)*ncols*nrows) + return M + + cdef Py_ssize_t i,r + for i,r in enumerate(range(row, row+nrows)) : + memcpy(M._matrix[i], self._matrix[r]+col, sizeof(celement)*ncols) - cdef Matrix_modn_dense_template M = self.new_matrix(nrows=nrows, ncols=self._ncols) - memcpy(M._entries, self._entries+row*ncols, sizeof(celement)*ncols*nrows) return M def _matrices_from_rows(self, Py_ssize_t nrows, Py_ssize_t ncols): @@ -3065,6 +3084,122 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ans.append(M) return ans + def matrix_from_columns(self, columns): + """ + Return the matrix constructed from self using columns with indices + in the columns list. + + EXAMPLES:: + + sage: M = MatrixSpace(Integers(8),3,3) + sage: A = M(range(9)); A + [0 1 2] + [3 4 5] + [6 7 0] + sage: A.matrix_from_columns([2,1]) + [2 1] + [5 4] + [0 7] + """ + cdef Py_ssize_t ncols = len(columns) + + # Construct new matrix + cdef Matrix_modn_dense_template A = self.new_matrix(ncols=ncols) + cdef Py_ssize_t i, j, col + for j, col in enumerate(columns): + if col < 0 or col >= self._ncols: + raise IndexError("column index out of range") + for i in range(self._nrows): + A._matrix[i][j] = self._matrix[i][col] + + return A + + def matrix_from_rows(self, rows): + """ + Return the matrix constructed from self using rows with indices in + the rows list. + + EXAMPLES:: + + sage: M = MatrixSpace(Integers(8),3,3) + sage: A = M(range(9)); A + [0 1 2] + [3 4 5] + [6 7 0] + sage: A.matrix_from_rows([2,1]) + [6 7 0] + [3 4 5] + """ + cdef Py_ssize_t nrows = len(rows) + + # Construct new matrix + cdef Matrix_modn_dense_template A = self.new_matrix(nrows=nrows) + + cdef Py_ssize_t i, row + for i, row in enumerate(rows): + if row < 0 or row >= self._nrows: + raise IndexError("row index out of range") + memcpy(A._matrix[i], self._matrix[row], sizeof(celement)*self._ncols) + + return A + + def matrix_from_rows_and_columns(self, rows, columns): + """ + Return the matrix constructed from self from the given rows and + columns. + + EXAMPLES:: + + sage: M = MatrixSpace(Integers(8),3,3) + sage: A = M(range(9)); A + [0 1 2] + [3 4 5] + [6 7 0] + sage: A.matrix_from_rows_and_columns([1], [0,2]) + [3 5] + sage: A.matrix_from_rows_and_columns([1,2], [1,2]) + [4 5] + [7 0] + + Note that row and column indices can be reordered or repeated:: + + sage: A.matrix_from_rows_and_columns([2,1], [2,1]) + [0 7] + [5 4] + + For example here we take from row 1 columns 2 then 0 twice, and do + this 3 times:: + + sage: A.matrix_from_rows_and_columns([1,1,1],[2,0,0]) + [5 3 3] + [5 3 3] + [5 3 3] + + AUTHORS: + + - Jaap Spies (2006-02-18) + + - Didier Deshommes: some Pyrex speedups implemented + """ + cdef Py_ssize_t ncols = len(columns) + cdef Py_ssize_t nrows = len(rows) + + # Check whether column indices are valid + cdef Py_ssize_t i, j, row, col + for col in columns: + if col < 0 or col >= self._ncols: + raise IndexError("column index out of range") + + # Construct new matrix + cdef Matrix_modn_dense_template A = self.new_matrix(nrows=nrows, ncols=ncols) + for i, row in enumerate(rows): + if row < 0 or row >= self._nrows: + raise IndexError("row index out of range") + for j, col in enumerate(columns): + A._matrix[i][j] = self._matrix[row][col] + + return A + def __bool__(self): """ Test whether this matrix is zero. @@ -3081,14 +3216,13 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: bool(A) False + sage: # needs sage.rings.finite_rings sage: A = matrix(GF(16007), 0, 0) sage: A.is_zero() True - sage: A = matrix(GF(16007), 1, 0) sage: A.is_zero() True - sage: A = matrix(GF(16007), 0, 1) sage: A.is_zero() True @@ -3109,8 +3243,8 @@ cdef class Matrix_modn_dense_template(Matrix_dense): EXAMPLES:: - sage: M = Matrix(GF(49), 2, [1,2,-2,0]) - sage: M.zero_pattern_matrix() # indirect doctest + sage: M = Matrix(GF(49), 2, [1,2,-2,0]) # needs sage.rings.finite_rings + sage: M.zero_pattern_matrix() # indirect doctest # needs sage.rings.finite_rings [0 0] [0 1] diff --git a/src/sage/matrix/matrix_modn_sparse.pxd b/src/sage/matrix/matrix_modn_sparse.pxd index 5c471a7082f..dded069b3d8 100644 --- a/src/sage/matrix/matrix_modn_sparse.pxd +++ b/src/sage/matrix/matrix_modn_sparse.pxd @@ -1,4 +1,4 @@ -from .matrix_sparse cimport Matrix_sparse +from sage.matrix.matrix_sparse cimport Matrix_sparse from sage.modules.vector_modn_sparse cimport * cdef class Matrix_modn_sparse(Matrix_sparse): diff --git a/src/sage/matrix/matrix_modn_sparse.pyx b/src/sage/matrix/matrix_modn_sparse.pyx index dd908a4c91b..84cfbedb226 100644 --- a/src/sage/matrix/matrix_modn_sparse.pyx +++ b/src/sage/matrix/matrix_modn_sparse.pyx @@ -86,44 +86,42 @@ from libc.limits cimport UINT_MAX from cysignals.memory cimport check_calloc, sig_free from cysignals.signals cimport sig_on, sig_off -from sage.ext.stdsage cimport PY_NEW +cimport sage.libs.linbox.givaro as givaro +cimport sage.libs.linbox.linbox as linbox +from sage.arith.misc import is_prime +from sage.data_structures.binary_search cimport * +from sage.ext.stdsage cimport PY_NEW from sage.libs.flint.fmpz cimport fmpz_get_mpz, fmpz_set_mpz from sage.libs.flint.fmpz_mat cimport fmpz_mat_entry - +from sage.libs.gmp.mpz cimport mpz_set +from sage.libs.linbox.conversion cimport (get_method, + METHOD_DEFAULT, + METHOD_DENSE_ELIMINATION, + METHOD_SPARSE_ELIMINATION, + METHOD_BLACKBOX, + METHOD_WIEDEMANN, + new_linbox_matrix_modn_sparse, + new_linbox_matrix_integer_sparse, + new_linbox_vector_integer_dense, + new_sage_vector_integer_dense) +from sage.matrix.args cimport SparseEntry, MatrixArgs_init +from sage.matrix.matrix2 import Matrix as Matrix2 +from sage.matrix.matrix_dense cimport Matrix_dense +from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense +from sage.misc.verbose import verbose, get_verbose +from sage.modules.vector_integer_dense cimport Vector_integer_dense +from sage.modules.vector_integer_sparse cimport * from sage.modules.vector_modn_sparse cimport * - -cimport sage.libs.linbox.givaro as givaro -cimport sage.libs.linbox.linbox as linbox - -from sage.libs.linbox.conversion cimport * - -from .matrix2 cimport Matrix -cimport sage.matrix.matrix as matrix -cimport sage.matrix.matrix_sparse as matrix_sparse -cimport sage.matrix.matrix_dense as matrix_dense +from sage.rings.fast_arith cimport arith_int from sage.rings.finite_rings.integer_mod cimport IntegerMod_int, IntegerMod_abstract from sage.rings.integer cimport Integer -from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ - -from sage.misc.verbose import verbose, get_verbose - -from sage.matrix.matrix2 import Matrix as Matrix2 -from .args cimport SparseEntry, MatrixArgs_init -from sage.arith.misc import is_prime - -cimport sage.structure.element - -from sage.data_structures.binary_search cimport * -from sage.modules.vector_integer_sparse cimport * - -from .matrix_integer_dense cimport Matrix_integer_dense -from sage.modules.vector_integer_dense cimport Vector_integer_dense +from sage.rings.rational_field import QQ +from sage.structure.element cimport Matrix ################ # TODO: change this to use extern cdef's methods. -from sage.rings.fast_arith cimport arith_int cdef arith_int ai ai = arith_int() ################ @@ -133,7 +131,7 @@ ai = arith_int() # Github Issue #12679. MAX_MODULUS = 46341 -cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): +cdef class Matrix_modn_sparse(Matrix_sparse): def __cinit__(self): nr = self._nrows nc = self._ncols @@ -257,7 +255,7 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): else: raise ValueError("unknown matrix format") - cdef sage.structure.element.Matrix _matrix_times_matrix_(self, sage.structure.element.Matrix _right): + cdef Matrix _matrix_times_matrix_(self, Matrix _right): """ This code is implicitly called for multiplying self by another sparse matrix. @@ -336,7 +334,7 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): set_entry(&ans.rows[i], j, s) return ans - def _matrix_times_matrix_dense(self, sage.structure.element.Matrix _right): + def _matrix_times_matrix_dense(self, Matrix _right): """ Multiply self by the sparse matrix _right, and return the result as a dense matrix. @@ -361,7 +359,7 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): """ cdef Matrix_modn_sparse right - cdef matrix_dense.Matrix_dense ans + cdef Matrix_dense ans right = _right cdef c_vector_modint* v @@ -871,7 +869,7 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): self.cache('det', d) return d elif algorithm == 'generic': - d = matrix_sparse.Matrix_sparse.determinant(self) + d = Matrix_sparse.determinant(self) self.cache('det', d) return d else: @@ -949,7 +947,7 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): if algorithm == "generic": return Matrix_sparse.solve_right(self, B) else: - if isinstance(B, sage.structure.element.Matrix): + if isinstance(B, Matrix): from sage.matrix.special import diagonal_matrix m, d = self._solve_matrix_linbox(B, algorithm) return m * diagonal_matrix([QQ((1,x)) for x in d]) @@ -1121,7 +1119,7 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): from sage.modules.free_module_element import vector cdef Matrix_integer_dense B - if not isinstance(mat, Matrix): + if not isinstance(mat, Matrix2): B = matrix(ZZ, mat, sparse=False) else: B = mat.change_ring(ZZ).dense_matrix() diff --git a/src/sage/matrix/matrix_numpy_dense.pyx b/src/sage/matrix/matrix_numpy_dense.pyx index 17867f9a65c..31ffaa0a51c 100644 --- a/src/sage/matrix/matrix_numpy_dense.pyx +++ b/src/sage/matrix/matrix_numpy_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy """ Dense matrices using a NumPy backend diff --git a/src/sage/matrix/matrix_numpy_integer_dense.pyx b/src/sage/matrix/matrix_numpy_integer_dense.pyx index bc605df9b92..8c449a86abf 100644 --- a/src/sage/matrix/matrix_numpy_integer_dense.pyx +++ b/src/sage/matrix/matrix_numpy_integer_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy r""" Dense integer matrices using a NumPy backend diff --git a/src/sage/matrix/matrix_polynomial_dense.pyx b/src/sage/matrix/matrix_polynomial_dense.pyx index 532350bdc66..10d9a9248b6 100644 --- a/src/sage/matrix/matrix_polynomial_dense.pyx +++ b/src/sage/matrix/matrix_polynomial_dense.pyx @@ -114,7 +114,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix( pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M._check_shift_dimension(shifts=[1,3,2]) sage: M._check_shift_dimension(shifts=[1,3,2], row_wise=False) @@ -140,19 +140,19 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix( pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.degree() 3 The zero matrix has degree ``-1``:: - sage: M = Matrix( pR, 2, 3 ) + sage: M = Matrix(pR, 2, 3) sage: M.degree() -1 For an empty matrix, the degree is not defined:: - sage: M = Matrix( pR, 3, 0 ) + sage: M = Matrix(pR, 3, 0) sage: M.degree() Traceback (most recent call last): ... @@ -194,7 +194,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix( pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.degree_matrix() [ 1 -1 0] [ 3 -1 -1] @@ -267,7 +267,6 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix([ ....: [ x^3+5*x^2+5*x+1, 5, 6*x+4, 0], ....: [ 6*x^2+3*x+1, 1, 2, 0], @@ -275,9 +274,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ....: ]) sage: M.is_constant() False - sage: M = Matrix(pR,[[1,5,2],[3,1,5]]); M.is_constant() + sage: M = Matrix(pR, [[1,5,2], [3,1,5]]); M.is_constant() True - sage: M = Matrix.zero(pR,3,5); M.is_constant() + sage: M = Matrix.zero(pR, 3, 5); M.is_constant() True .. SEEALSO:: @@ -651,7 +650,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [ 4*x + 6 x + 5 5*x + 5 6*x + 5] - sage: M.reverse(M.column_degrees(),row_wise=False) + sage: M.reverse(M.column_degrees(), row_wise=False) [ x^3 + 5*x^2 + 5*x + 1 5*x 4*x^2 + 6*x 0] [ x^3 + 3*x^2 + 6*x x @@ -743,10 +742,10 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: A = Matrix(pR, 3, 3, \ - [[4*x+5, 5*x^2 + x + 1, 4*x^2 + 4], \ - [6*x^2 + 6*x + 6, 4*x^2 + 5*x, 4*x^2 + x + 3], \ - [3*x^2 + 2, 4*x + 1, x^2 + 3*x]]) + sage: A = Matrix(pR, 3, 3, + ....: [[4*x+5, 5*x^2 + x + 1, 4*x^2 + 4], + ....: [6*x^2 + 6*x + 6, 4*x^2 + 5*x, 4*x^2 + x + 3], + ....: [3*x^2 + 2, 4*x + 1, x^2 + 3*x]]) sage: B = A.inverse_series_trunc(4); B [ x^3 + 5*x^2 + x + 4 x^3 + 5*x^2 + 6*x + 4 6*x^2 + 5*x + 3] [ 4*x^2 + 5*x + 6 6*x^3 + x^2 + x + 6 3*x^3 + 2*x^2 + 2] @@ -839,51 +838,52 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: + sage: pR. = GF(7)[] - sage: A = Matrix(pR, 3, 3, \ - [[4*x+5, 5*x^2 + x + 1, 4*x^2 + 4], \ - [6*x^2 + 6*x + 6, 4*x^2 + 5*x, 4*x^2 + x + 3], \ - [3*x^2 + 2, 4*x + 1, x^2 + 3*x]]) + sage: A = Matrix(pR, 3, 3, + ....: [[4*x+5, 5*x^2 + x + 1, 4*x^2 + 4], + ....: [6*x^2 + 6*x + 6, 4*x^2 + 5*x, 4*x^2 + x + 3], + ....: [3*x^2 + 2, 4*x + 1, x^2 + 3*x]]) sage: A.is_square() and A.constant_matrix().is_invertible() True sage: B = vector([2*x^2 + 6*x + 6, 0, x + 6]) - sage: X = A.solve_left_series_trunc(B,4); X + sage: X = A.solve_left_series_trunc(B, 4); X (3*x^3 + 3*x^2 + 2*x + 4, 4*x^3 + x^2 + 2*x + 6, 6*x^3 + x + 3) sage: B == X*A % x**4 True - sage: B = Matrix(pR, 2, 3, \ - [[3*x, x^2 + x + 2, x^2 + 2*x + 3], \ - [ 0, 6*x^2 + 1, 1]]) - sage: A.solve_left_series_trunc(B,3) + sage: B = Matrix(pR, 2, 3, + ....: [[3*x, x^2 + x + 2, x^2 + 2*x + 3], + ....: [ 0, 6*x^2 + 1, 1]]) + sage: A.solve_left_series_trunc(B, 3) [6*x^2 + 2*x + 2 4*x + 3 2*x^2 + 3*x] [3*x^2 + 4*x + 5 4*x^2 + 3 x^2 + 6*x + 3] - sage: X = A.solve_left_series_trunc(B,37); B == X*A % x**37 + sage: X = A.solve_left_series_trunc(B, 37); B == X*A % x**37 True Dimensions of input are checked:: - sage: A.solve_left_series_trunc(B[:,:2],3) + sage: A.solve_left_series_trunc(B[:,:2], 3) Traceback (most recent call last): ... ValueError: number of columns of self must equal number of columns of right-hand side Raises an exception when no solution:: - sage: A[2:,:].solve_left_series_trunc(B,4) + sage: A[2:,:].solve_left_series_trunc(B, 4) Traceback (most recent call last): ... ValueError: matrix equation has no solutions sage: Ax = x*A; C = vector(pR, [1,1,1]) - sage: Ax.solve_left_series_trunc(C,5) + sage: Ax.solve_left_series_trunc(C, 5) Traceback (most recent call last): ... ValueError: matrix equation has no solutions Supports rectangular and rank-deficient cases:: - sage: A[:,:2].solve_left_series_trunc(B[:,:2],4) + sage: A[:,:2].solve_left_series_trunc(B[:,:2], 4) [5*x^2 + 2*x + 5 5*x + 5 2*x + 4] [5*x^3 + 2*x + 1 2*x^2 + 2*x + 5 4*x^2] @@ -987,45 +987,45 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: A = Matrix(pR, 3, 3, \ - [[4*x+5, 5*x^2 + x + 1, 4*x^2 + 4], \ - [6*x^2 + 6*x + 6, 4*x^2 + 5*x, 4*x^2 + x + 3], \ - [3*x^2 + 2, 4*x + 1, x^2 + 3*x]]) + sage: A = Matrix(pR, 3, 3, + ....: [[4*x+5, 5*x^2 + x + 1, 4*x^2 + 4], + ....: [6*x^2 + 6*x + 6, 4*x^2 + 5*x, 4*x^2 + x + 3], + ....: [3*x^2 + 2, 4*x + 1, x^2 + 3*x]]) sage: A.is_square() and A.constant_matrix().is_invertible() True sage: B = vector([2*x^2 + 6*x + 6, 0, x + 6]) - sage: X = A.solve_right_series_trunc(B,4); X + sage: X = A.solve_right_series_trunc(B, 4); X (2*x^3 + x^2, 5*x^3 + x^2 + 5*x + 6, 4*x^3 + 6*x^2 + 4*x) sage: B == A*X % x**4 True - sage: B = Matrix(pR, 3, 2, \ - [[5*x^2 + 6*x + 3, 4*x^2 + 6*x + 4], \ - [ x^2 + 4*x + 2, 5*x + 2], \ - [ 5*x + 3, 0]]) - sage: A.solve_right_series_trunc(B,3) + sage: B = Matrix(pR, 3, 2, + ....: [[5*x^2 + 6*x + 3, 4*x^2 + 6*x + 4], + ....: [ x^2 + 4*x + 2, 5*x + 2], + ....: [ 5*x + 3, 0]]) + sage: A.solve_right_series_trunc(B, 3) [ 3*x^2 + x + 1 5*x^2 + 4*x + 3] [6*x^2 + 3*x + 1 4*x + 1] [ 6*x^2 + 1 2*x^2 + x + 4] - sage: X = A.solve_right_series_trunc(B,37); B == A*X % x**37 + sage: X = A.solve_right_series_trunc(B, 37); B == A*X % x**37 True Dimensions of input are checked:: - sage: A.solve_right_series_trunc(B[:2,:],3) + sage: A.solve_right_series_trunc(B[:2,:], 3) Traceback (most recent call last): ... ValueError: number of rows of self must equal number of rows of right-hand side Raises an exception when no solution:: - sage: A[:,2:].solve_right_series_trunc(B,4) + sage: A[:,2:].solve_right_series_trunc(B, 4) Traceback (most recent call last): ... ValueError: matrix equation has no solutions sage: Ax = x*A; C = vector(pR, [1,1,1]) - sage: Ax.solve_right_series_trunc(C,5) + sage: Ax.solve_right_series_trunc(C, 5) Traceback (most recent call last): ... ValueError: matrix equation has no solutions @@ -1096,7 +1096,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [3*x+1, 0, 1], [x^3+3, 0, 0] ]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.row_degrees() [1, 3] @@ -1116,13 +1116,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): The row degrees of an empty matrix (`0\times n` or `m\times 0`) is not defined:: - sage: M = Matrix( pR, 0, 3 ) + sage: M = Matrix(pR, 0, 3) sage: M.row_degrees() Traceback (most recent call last): ... ValueError: empty matrix does not have row degrees - sage: M = Matrix( pR, 3, 0 ) + sage: M = Matrix(pR, 3, 0) sage: M.row_degrees() Traceback (most recent call last): ... @@ -1163,7 +1163,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [3*x+1, 0, 1], [x^3+3, 0, 0] ]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.column_degrees() [3, -1, 0] @@ -1179,13 +1179,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): The column degrees of an empty matrix (`0\times n` or `m\times 0`) is not defined:: - sage: M = Matrix( pR, 0, 3 ) + sage: M = Matrix(pR, 0, 3) sage: M.column_degrees() Traceback (most recent call last): ... ValueError: empty matrix does not have column degrees - sage: M = Matrix( pR, 3, 0 ) + sage: M = Matrix(pR, 3, 0) sage: M.column_degrees() Traceback (most recent call last): ... @@ -1244,7 +1244,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [3*x+1, 0, 1], [x^3+3, 0, 0] ]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.leading_matrix() [3 0 0] [1 0 0] @@ -1390,7 +1390,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [3*x+1, 0, 1], [x^3+3, 0, 0] ]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.is_reduced() False @@ -1401,10 +1401,10 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): True sage: M.is_reduced(shifts=[2,0], row_wise=False, - ....: include_zero_vectors=False) + ....: include_zero_vectors=False) False - sage: M = Matrix(pR, [ [3*x+1, 0, 1], [x^3+3, 0, 0], [0, 1, 0] ]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0], [0, 1, 0]]) sage: M.is_reduced(shifts=[2,0,0], row_wise=False) True @@ -1470,7 +1470,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [3*x+1, 0, 1], [x^3+3, 0, 0] ]) + sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]]) sage: M.leading_positions() [0, 0] @@ -1484,23 +1484,24 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ([1, -1, 0], [3, -1, 0]) sage: M.leading_positions(shifts=[1,2], row_wise=False, - ....: return_degree=True) + ....: return_degree=True) ([1, -1, 0], [3, -1, 0]) In case several entries in the row (resp. column) reach the shifted row (resp. column) degree, the leading position is chosen as the rightmost (resp. bottommost) such entry:: - sage: M.leading_positions(shifts=[0,5,1],return_degree=True) + sage: M.leading_positions(shifts=[0,5,1], return_degree=True) ([2, 0], [0, 3]) - sage: M.leading_positions(shifts=[2,0], row_wise=False,return_degree=True) + sage: M.leading_positions(shifts=[2,0], row_wise=False, + ....: return_degree=True) ([1, -1, 0], [3, -1, 0]) The leading positions and pivot degrees of an empty matrix (`0\times n` or `m\times 0`) is not defined:: - sage: M = Matrix( pR, 0, 3 ) + sage: M = Matrix(pR, 0, 3) sage: M.leading_positions() Traceback (most recent call last): ... @@ -1511,7 +1512,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ... ValueError: empty matrix does not have leading positions - sage: M = Matrix( pR, 3, 0 ) + sage: M = Matrix(pR, 3, 0) sage: M.leading_positions(row_wise=False) Traceback (most recent call last): ... @@ -1613,7 +1614,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.is_weak_popov(ordered=True) True - sage: N = M.with_swapped_rows(1,2) + sage: N = M.with_swapped_rows(1, 2) sage: N.is_weak_popov() True sage: N.is_weak_popov(ordered=True) @@ -1624,7 +1625,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.is_weak_popov(shifts=[2,3,1]) False - sage: M.is_weak_popov(shifts=[0,2,0],row_wise=False,ordered=True) + sage: M.is_weak_popov(shifts=[0,2,0], row_wise=False, + ....: ordered=True) True Rectangular matrices are supported:: @@ -1637,7 +1639,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.is_weak_popov(shifts=[0,2,1,3]) True - sage: M.is_weak_popov(shifts=[0,2,1,3],ordered=True) + sage: M.is_weak_popov(shifts=[0,2,1,3], ordered=True) True Zero rows (resp. columns) can be forbidden:: @@ -1647,11 +1649,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ....: [ 2, 5*x + 1, 6*x^2+3*x+1, 0], ....: [2*x^2+5*x+5, 1, 2*x^3+4*x^2+6*x+4, 0] ....: ]) - sage: M.is_weak_popov(shifts=[2,1,0], row_wise=False, ordered=True) + sage: M.is_weak_popov(shifts=[2,1,0], row_wise=False, + ....: ordered=True) True sage: M.is_weak_popov(shifts=[2,1,0], row_wise=False, - ....: include_zero_vectors=False) + ....: include_zero_vectors=False) False .. SEEALSO:: @@ -1667,8 +1670,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): # the row-wise case (resp. column-wise case), it will be convenient to # have leading position ncols (resp. nrows) for these zero vectors pos_zero_vec = self.ncols() if row_wise else self.nrows() - leading_positions = [pos if pos>=0 else pos_zero_vec + 1 \ - for pos in leading_positions] + leading_positions = [pos if pos >= 0 else pos_zero_vec + 1 + for pos in leading_positions] # leading positions should not have duplicates, which is equivalent to: # once sorted, it doesn't contain a pair of equal successive entries if not ordered: @@ -1739,9 +1742,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [x^4+6*x^3+4*x+4, 3*x+6, 3 ], - ....: [x^2+6*x+6, x^2+5*x+5, 2 ], - ....: [3*x, 6*x+5, x+5] ]) + sage: M = Matrix(pR, [[x^4+6*x^3+4*x+4, 3*x+6, 3 ], + ....: [x^2+6*x+6, x^2+5*x+5, 2 ], + ....: [3*x, 6*x+5, x+5]]) sage: M.is_popov() True @@ -1754,9 +1757,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M[:2,:].is_popov(shifts=[0,1,2]) True - sage: M = Matrix(pR, [ [x^4+3*x^3+x^2+2*x+6, x^3+5*x^2+5*x+1], - ....: [6*x+1, x^2+4*x+1 ], - ....: [6, 6 ] ]) + sage: M = Matrix(pR, [[x^4+3*x^3+x^2+2*x+6, x^3+5*x^2+5*x+1], + ....: [6*x+1, x^2+4*x+1 ], + ....: [6, 6 ]]) sage: M.is_popov(row_wise=False) False @@ -1765,9 +1768,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): One can forbid zero rows (or columns if not working row-wise):: - sage: N = Matrix(pR, [ [x^4+3*x^3+x^2+2*x+6, 6*x+1 ], - ....: [5*x^2+5*x+1, x^2+4*x+1 ], - ....: [0, 0 ] ]) + sage: N = Matrix(pR, [[x^4+3*x^3+x^2+2*x+6, 6*x+1 ], + ....: [5*x^2+5*x+1, x^2+4*x+1 ], + ....: [0, 0 ]]) sage: N.is_popov() True @@ -1778,15 +1781,15 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): One can verify Popov form up to row permutation (or column permutation if not working row-wise):: - sage: M.swap_columns(0,1) + sage: M.swap_columns(0, 1) sage: M.is_popov(shifts=[0,2,3], row_wise=False) False sage: M.is_popov(shifts=[0,2,3], row_wise=False, - ....: up_to_permutation=True) + ....: up_to_permutation=True) True - sage: N.swap_rows(0,2) + sage: N.swap_rows(0, 2) sage: N.is_popov() False @@ -1877,9 +1880,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ [x^4+6*x^3+4*x+4, 3*x+6, 3 ], - ....: [0, x^2+5*x+5, 2 ], - ....: [0, 0, x+5] ]) + sage: M = Matrix(pR, [[x^4+6*x^3+4*x+4, 3*x+6, 3 ], + ....: [0, x^2+5*x+5, 2 ], + ....: [0, 0, x+5]]) sage: M.is_hermite() True @@ -1888,9 +1891,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M.is_hermite(row_wise=False, lower_echelon=True) False - sage: N = Matrix(pR, [ [x+5, 0, 0 ], - ....: [2, x^4+6*x^3+4*x+4, 0 ], - ....: [3, 3*x^3+6, x^2+5*x+5] ]) + sage: N = Matrix(pR, [[x+5, 0, 0 ], + ....: [2, x^4+6*x^3+4*x+4, 0 ], + ....: [3, 3*x^3+6, x^2+5*x+5]]) sage: N.is_hermite() False sage: N.is_hermite(lower_echelon=True) @@ -1992,23 +1995,22 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ \ - [ 6*x+4, 5*x^3+5*x, 6*x^2+2*x+2], \ - [4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]]) - - sage: P,U = M.weak_popov_form(transformation=True) + sage: M = Matrix(pR, [ + ....: [ 6*x+4, 5*x^3+5*x, 6*x^2+2*x+2], + ....: [4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]]) + sage: P, U = M.weak_popov_form(transformation=True) sage: P [ 4 x^2 6*x^2 + x + 2] [ 2 4*x^2 + 2*x + 4 5] sage: U [2*x^2 + 1 4*x] [ 4*x 1] - sage: P.is_weak_popov() and U.is_invertible() and U*M==P + sage: P.is_weak_popov() and U.is_invertible() and U*M == P True Demonstrating the ``ordered`` option:: - sage: P.leading_positions() + sage: P.leading_positions() # needs sage.combinat [2, 1] sage: PP = M.weak_popov_form(ordered=True); PP [ 2 4*x^2 + 2*x + 4 5] @@ -2021,7 +2023,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: P = M.weak_popov_form(shifts=[0,2,4]); P [ 6*x^2 + 6*x + 4 5*x^4 + 4*x^3 + 5*x^2 + 5*x 2*x + 2] [ 2 4*x^2 + 2*x + 4 5] - sage: P==M.weak_popov_form(shifts=[-10,-8,-6]) + sage: P == M.weak_popov_form(shifts=[-10,-8,-6]) True Column-wise form is the row-wise form of the transpose:: @@ -2035,9 +2037,10 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [x + 4 6 0] [ 5 1 0] - sage: P,U = M.weak_popov_form(transformation=True, \ - row_wise=False, \ - include_zero_vectors=False) + sage: # needs sage.combinat + sage: P, U = M.weak_popov_form(transformation=True, + ....: row_wise=False, + ....: include_zero_vectors=False) sage: P [x + 4 6] [ 5 1] @@ -2120,17 +2123,18 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: - sage: F. = GF(2^4,'a') + sage: # needs sage.rings.finite_rings + sage: F. = GF(2^4, 'a') sage: PF. = F[] sage: A = matrix(PF,[[1, a*x^17 + 1 ], ....: [0, a*x^11 + a^2*x^7 + 1 ]]) sage: M = A.__copy__() - sage: U = M._weak_popov_form(transformation=True) - sage: U * A == M + sage: U = M._weak_popov_form(transformation=True) # needs sage.combinat + sage: U * A == M # needs sage.combinat True - sage: M.is_weak_popov() + sage: M.is_weak_popov() # needs sage.combinat True - sage: U.is_invertible() + sage: U.is_invertible() # needs sage.combinat True sage: PF. = QQ[] @@ -2276,30 +2280,32 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: M = Matrix(pR, [ \ - [ 6*x+4, 5*x^3+5*x, 6*x^2+2*x+2], \ - [4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]]) + sage: M = Matrix(pR, [ + ....: [ 6*x+4, 5*x^3+5*x, 6*x^2+2*x+2], + ....: [4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]]) - sage: P,U = M.popov_form(transformation=True) + sage: # needs sage.combinat + sage: P, U = M.popov_form(transformation=True) sage: P [ 4 x^2 + 4*x + 1 3] [ 0 4*x + 1 x^2 + 6*x + 1] sage: U [ x 2] [5*x^2 + x + 6 3*x + 2] - sage: P.is_popov() and U.is_invertible() and U*M==P + sage: P.is_popov() and U.is_invertible() and U*M == P True Demonstrating shifts and specific case of Hermite form:: + sage: # needs sage.combinat sage: P = M.popov_form(shifts=[0,2,4]); P [ 4*x^2 + 3*x + 4 x^4 + 3*x^3 + 5*x^2 + 5*x + 5 0] [ 6 5*x^2 + 6*x + 5 1] sage: P.is_popov(shifts=[0,2,4]) True - sage: P==M.popov_form(shifts=[-6,-4,-2]) + sage: P == M.popov_form(shifts=[-6,-4,-2]) True - sage: dd=sum(M.row_degrees())+1 + sage: dd = sum(M.row_degrees()) + 1 sage: M.popov_form(shifts=[2*dd,dd,0]) == M.hermite_form() True @@ -2314,9 +2320,10 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [x + 2 6 0] [ 0 1 0] - sage: P,U = M.popov_form(transformation=True, \ - row_wise=False, \ - include_zero_vectors=False) + sage: # needs sage.combinat + sage: P, U = M.popov_form(transformation=True, + ....: row_wise=False, + ....: include_zero_vectors=False) sage: P [x + 2 6] [ 0 1] @@ -2467,9 +2474,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(3)[] - sage: A = matrix(pR,3,[x, x^2, x^3, - ....: x^2, x^1, 0, - ....: x^3, x^3, x^3]) + sage: A = matrix(pR, 3, [x, x^2, x^3, + ....: x^2, x^1, 0, + ....: x^3, x^3, x^3]) sage: R = A.reduced_form(); R [ x x^2 x^3] [ x^2 x 0] @@ -2489,7 +2496,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): `R` has a single non-zero entry and that entry is a scalar multiple of the greatest-common-divisor of the entries of the matrix:: - sage: A = matrix([[x*(x-1)*(x+1)],[x*(x-2)*(x+2)],[x]]) + sage: A = matrix([[x*(x-1)*(x+1)], [x*(x-2)*(x+2)], [x]]) sage: R = A.reduced_form() sage: R [x] @@ -2521,12 +2528,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): The last example shows the usage of the transformation parameter:: + sage: # needs sage.rings.finite_rings sage: Fq. = GF(2^3) sage: pR. = Fq[] sage: A = matrix(pR, [[x^2+a, x^4+a], - ....: [ x^3, a*x^4]]) - sage: W,U = A.reduced_form(transformation=True) - sage: W,U + ....: [ x^3, a*x^4]]) + sage: W, U = A.reduced_form(transformation=True) + sage: W, U ( [ x^2 + a x^4 + a] [1 0] [x^3 + a*x^2 + a^2 a^2], [a 1] @@ -2588,14 +2596,16 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x]) sage: A.hermite_form(transformation=True, include_zero_rows=False) ([ x 1 2*x], [0 4]) - sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U + sage: H, U = A.hermite_form(transformation=True, + ....: include_zero_rows=True); H, U ( [ x 1 2*x] [0 4] [ 0 0 0], [5 1] ) sage: U * A == H True - sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False) + sage: H, U = A.hermite_form(transformation=True, + ....: include_zero_rows=False) sage: U * A [ x 1 2*x] sage: U * A == H @@ -2636,22 +2646,22 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: A = Matrix(pR, 3, 2, \ - [[ 3*x^3 + 3*x, 2*x^3 + 4], \ - [ 3*x^3 + 6*x + 5, 6*x^3 + 5*x^2 + 1], \ - [ 2*x^3 + 2*x + 6, 3*x^2 + 2*x + 2]]) - sage: B = Matrix(pR, 3, 3, \ - [[ 3, x + 3, 6], \ - [3*x^3 + 3*x + 1, 4*x^2 + 3*x, 6*x^3 + x + 4], \ - [ 4*x^2 + x + 4, 3*x^2 + 4*x, 3*x^2 + 3*x + 2]]) - sage: Q,R = A.left_quo_rem(B); (Q,R) + sage: A = Matrix(pR, 3, 2, + ....: [[ 3*x^3 + 3*x, 2*x^3 + 4], + ....: [ 3*x^3 + 6*x + 5, 6*x^3 + 5*x^2 + 1], + ....: [ 2*x^3 + 2*x + 6, 3*x^2 + 2*x + 2]]) + sage: B = Matrix(pR, 3, 3, + ....: [[ 3, x + 3, 6], + ....: [3*x^3 + 3*x + 1, 4*x^2 + 3*x, 6*x^3 + x + 4], + ....: [ 4*x^2 + x + 4, 3*x^2 + 4*x, 3*x^2 + 3*x + 2]]) + sage: Q, R = A.left_quo_rem(B); Q, R ( [2*x^2 + 4*x + 6 6*x^2 + 4*x + 1] [ 3 1] [ 3*x^2 + 5*x 2*x^2 + x + 5] [ 6 5*x^2 + 2*x + 3] [ 6*x^2 + 3*x 4*x^2 + 6*x + 1], [ 2*x + 3 6*x + 3] ) sage: rdegR = R.row_degrees(); rdegB = B.row_degrees() - sage: A == B*Q+R and all([rdegR[i] < rdegB[i] for i in range(3)]) + sage: A == B*Q+R and all(rdegR[i] < rdegB[i] for i in range(3)) True sage: A[:2,:].left_quo_rem(B) @@ -2664,7 +2674,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): no quotient and remainder (unless the matrix has full row rank, see :meth:`right_quo_rem`):: - sage: Q,R = A[:2,:].left_quo_rem(B[:2,:]); (Q,R) + sage: Q, R = A[:2,:].left_quo_rem(B[:2,:]); Q, R ( [ 3*x + 3 2*x + 1] [ 3*x^2 + 5*x 2*x^2 + x + 5] [ 5 0] @@ -2731,17 +2741,16 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Case where `B` is a square, column reduced matrix:: sage: pR. = GF(7)[] - sage: A = Matrix(pR, 2, 3, \ - [[3*x^3 + 3*x, 3*x^3 + 6*x + 5, 2*x^3 + 2*x + 6], \ - [2*x^3 + 4, 6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]]) - - sage: B = Matrix(pR, 3, 3, \ - [[4*x^2 + 3*x + 3, 3*x^2 + 3*x + 1, 4*x^2 + x + 4], \ - [6*x^2 + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], \ - [5*x^2 + 3*x + 6, 6*x^2 + x + 4, 3*x^2 + 3*x + 2]]) + sage: A = Matrix(pR, 2, 3, + ....: [[3*x^3 + 3*x, 3*x^3 + 6*x + 5, 2*x^3 + 2*x + 6], + ....: [2*x^3 + 4, 6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]]) + sage: B = Matrix(pR, 3, 3, + ....: [[4*x^2 + 3*x + 3, 3*x^2 + 3*x + 1, 4*x^2 + x + 4], + ....: [6*x^2 + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], + ....: [5*x^2 + 3*x + 6, 6*x^2 + x + 4, 3*x^2 + 3*x + 2]]) sage: B.is_reduced(row_wise=False) True - sage: Q,R = A.right_quo_rem(B); (Q,R) + sage: Q, R = A.right_quo_rem(B); Q, R ( [ 4*x x + 2 6*x + 1] [ x + 2 6*x + 1 5*x + 4] [4*x + 3 x + 6 3*x + 4], [4*x + 2 2*x + 3 4*x + 3] @@ -2754,13 +2763,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ValueError: column dimension of self should be the column dimension of the input matrix - sage: B = Matrix(pR, 3, 3, \ - [[3, 3*x^3 + 3*x + 1, 4*x^2 + x + 4], \ - [x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], \ - [6, 6*x^3 + x + 4, 3*x^2 + 3*x + 2]]) + sage: B = Matrix(pR, 3, 3, + ....: [[3, 3*x^3 + 3*x + 1, 4*x^2 + x + 4], + ....: [x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], + ....: [6, 6*x^3 + x + 4, 3*x^2 + 3*x + 2]]) sage: B.is_reduced(row_wise=False) True - sage: Q,R = A.right_quo_rem(B); (Q,R) + sage: Q, R = A.right_quo_rem(B); Q, R ( [2*x^2 + 4*x + 6 3*x^2 + 5*x 6*x^2 + 3*x] [6*x^2 + 4*x + 1 2*x^2 + x + 5 4*x^2 + 6*x + 1], @@ -2775,13 +2784,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): With a nonsingular but also non-reduced matrix, there exists a solution, but it might not be unique:: - sage: B = Matrix(pR, 3, 3, \ - [[ 5, 0, 2*x + 6], \ - [ 4*x, 3*x^2 + 4*x + 5, x + 1], \ - [3*x^2 + 5*x + 2, 6*x^3 + 4*x + 6, 3]]) + sage: B = Matrix(pR, 3, 3, + ....: [[ 5, 0, 2*x + 6], + ....: [ 4*x, 3*x^2 + 4*x + 5, x + 1], + ....: [3*x^2 + 5*x + 2, 6*x^3 + 4*x + 6, 3]]) sage: B.det() != 0 and (not B.is_reduced(row_wise=False)) True - sage: Q,R = A.right_quo_rem(B); (Q,R) + sage: Q, R = A.right_quo_rem(B); Q, R ( [ 6*x^2 + 3*x 4*x^2 + 3*x + 1 5*x + 1] [ x^2 + 5*x + 5 5*x^2 + 3*x + 5 x + 2], @@ -2790,15 +2799,15 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [ 6*x + 3 5*x^2 + 6 3] ) sage: cdegR = R.column_degrees(); cdegB = B.column_degrees() - sage: A == Q*B+R and all([cdegR[i] < cdegB[i] for i in range(3)]) + sage: A == Q*B+R and all(cdegR[i] < cdegB[i] for i in range(3)) True - sage: Q2 = Matrix(pR, 2, 3, \ - [[6*x^2 + 3*x + 1, 4*x^2 + 3*x + 6, 5*x + 1], \ - [ x^2 + 5*x + 3, 5*x^2 + 3*x + 2, x + 2]]) - sage: R2 = Matrix(pR, 2, 3, \ - [[ 5*x, 3*x + 4, 5], \ - [4*x + 6, 5*x, 4]]) + sage: Q2 = Matrix(pR, 2, 3, + ....: [[6*x^2 + 3*x + 1, 4*x^2 + 3*x + 6, 5*x + 1], + ....: [ x^2 + 5*x + 3, 5*x^2 + 3*x + 2, x + 2]]) + sage: R2 = Matrix(pR, 2, 3, + ....: [[ 5*x, 3*x + 4, 5], + ....: [4*x + 6, 5*x, 4]]) sage: A == Q2*B + R2 True @@ -2807,8 +2816,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): other cases (rank-deficient matrix `B` or matrix `B` having strictly fewer rows than columns) there may be no solution:: - sage: C = B.stack(B[1,:] + B[2,:]) # matrix 4 x 3, full column rank - sage: Q,R = A.right_quo_rem(C); (Q,R) + sage: C = B.stack(B[1,:] + B[2,:]) # 4 x 3, full column rank + sage: Q, R = A.right_quo_rem(C); Q, R ( [ 6*x^2 + 3*x 4*x^2 + 3*x + 1 5*x + 1 0] [ x^2 + 5*x + 5 5*x^2 + 3*x + 5 x + 2 0], @@ -2822,7 +2831,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ... ValueError: division of these matrices does not admit a remainder with the required degree property - sage: D = copy(B); D[2,:] = B[0,:]+B[1,:] # square, singular + sage: D = copy(B); D[2,:] = B[0,:]+B[1,:] # square, singular sage: A.right_quo_rem(D) Traceback (most recent call last): ... @@ -2887,17 +2896,16 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: A = Matrix(pR, 2, 3, \ - [[3*x^3 + 3*x, 3*x^3 + 6*x + 5, 2*x^3 + 2*x + 6], \ - [2*x^3 + 4, 6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]]) - - sage: B = Matrix(pR, 3, 3, \ - [[4*x^2 + 3*x + 3, 3*x^2 + 3*x + 1, 4*x^2 + x + 4], \ - [6*x^2 + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], \ - [5*x^2 + 3*x + 6, 6*x^2 + x + 4, 3*x^2 + 3*x + 2]]) + sage: A = Matrix(pR, 2, 3, + ....: [[3*x^3 + 3*x, 3*x^3 + 6*x + 5, 2*x^3 + 2*x + 6], + ....: [2*x^3 + 4, 6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]]) + sage: B = Matrix(pR, 3, 3, + ....: [[4*x^2 + 3*x + 3, 3*x^2 + 3*x + 1, 4*x^2 + x + 4], + ....: [6*x^2 + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], + ....: [5*x^2 + 3*x + 6, 6*x^2 + x + 4, 3*x^2 + 3*x + 2]]) sage: B.is_reduced(row_wise=False) True - sage: Q,R = A._right_quo_rem_reduced(B); (Q,R) + sage: Q, R = A._right_quo_rem_reduced(B); Q, R ( [ 4*x x + 2 6*x + 1] [ x + 2 6*x + 1 5*x + 4] [4*x + 3 x + 6 3*x + 4], [4*x + 2 2*x + 3 4*x + 3] @@ -2905,13 +2913,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: A == Q*B+R and R.degree() < 2 True - sage: B = Matrix(pR, 3, 3, \ - [[4*x + 3*x + 3, 3*x^3 + 3*x + 1, 4*x^2 + x + 4], \ - [6*x + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], \ - [6, 6*x^3 + x + 4, 3*x^2 + 3*x + 2]]) + sage: B = Matrix(pR, 3, 3, + ....: [[4*x + 3*x + 3, 3*x^3 + 3*x + 1, 4*x^2 + x + 4], + ....: [6*x + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], + ....: [6, 6*x^3 + x + 4, 3*x^2 + 3*x + 2]]) sage: B.is_reduced(row_wise=False) True - sage: Q,R = A._right_quo_rem_reduced(B); (Q,R) + sage: Q, R = A._right_quo_rem_reduced(B); Q, R ( [2*x^2 + 4*x + 6 3*x^2 + 5*x 6*x^2 + 3*x] [6*x^2 + 4*x + 1 2*x^2 + x + 5 4*x^2 + 6*x + 1], @@ -2920,7 +2928,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [ 1 5*x^2 + 2*x + 3 6*x + 3] ) sage: cdegR = R.column_degrees(); cdegB = B.column_degrees() - sage: A == Q*B+R and all([cdegR[i] < cdegB[i] for i in range(3)]) + sage: A == Q*B+R and all(cdegR[i] < cdegB[i] for i in range(3)) True """ # Step 0: find parameter d (delta in above reference) @@ -2966,15 +2974,14 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: A = Matrix(pR, 2, 3, \ - [[3*x^3 + 3*x, 3*x^3 + 6*x + 5, 2*x^3 + 2*x + 6], \ - [2*x^3 + 4, 6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]]) - - sage: B = Matrix(pR, 3, 3, \ - [[4*x + 3*x + 3, 3*x^3 + 3*x + 1, 4*x^2 + x + 4], \ - [6*x + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], \ - [6, 6*x^3 + x + 4, 3*x^2 + 3*x + 2]]) - sage: Q,R = A._right_quo_rem_solve(B); (Q,R) + sage: A = Matrix(pR, 2, 3, + ....: [[3*x^3 + 3*x, 3*x^3 + 6*x + 5, 2*x^3 + 2*x + 6], + ....: [2*x^3 + 4, 6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]]) + sage: B = Matrix(pR, 3, 3, + ....: [[4*x + 3*x + 3, 3*x^3 + 3*x + 1, 4*x^2 + x + 4], + ....: [6*x + 2*x + 3, 4*x^2 + 3*x, 3*x^2 + 4*x], + ....: [6, 6*x^3 + x + 4, 3*x^2 + 3*x + 2]]) + sage: Q, R = A._right_quo_rem_solve(B); Q, R ( [2*x^2 + 4*x + 6 3*x^2 + 5*x 6*x^2 + 3*x] [6*x^2 + 4*x + 1 2*x^2 + x + 5 4*x^2 + 6*x + 1], @@ -2991,13 +2998,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): With a nonsingular but also non-reduced matrix, there exists a solution and one is found by this method, but it might not be unique:: - sage: B = Matrix(pR, 3, 3, \ - [[ 5, 0, 2*x + 6], \ - [ 4*x, 3*x^2 + 4*x + 5, x + 1], \ - [3*x^2 + 5*x + 2, 6*x^3 + 4*x + 6, 3]]) - sage: B.det() != 0 and (not B.is_reduced(row_wise=False)) + sage: B = Matrix(pR, 3, 3, + ....: [[ 5, 0, 2*x + 6], + ....: [ 4*x, 3*x^2 + 4*x + 5, x + 1], + ....: [3*x^2 + 5*x + 2, 6*x^3 + 4*x + 6, 3]]) + sage: B.det() != 0 and not B.is_reduced(row_wise=False) True - sage: Q,R = A._right_quo_rem_solve(B); (Q,R) + sage: Q, R = A._right_quo_rem_solve(B); Q, R ( [ 6*x^2 + 3*x 4*x^2 + 3*x + 1 5*x + 1] [ x^2 + 5*x + 5 5*x^2 + 3*x + 5 x + 2], @@ -3006,15 +3013,15 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [ 6*x + 3 5*x^2 + 6 3] ) sage: cdegR = R.column_degrees(); cdegB = B.column_degrees() - sage: A == Q*B+R and all([cdegR[i] < cdegB[i] for i in range(3)]) + sage: A == Q*B+R and all(cdegR[i] < cdegB[i] for i in range(3)) True - sage: Q2 = Matrix(pR, 2, 3, \ - [[6*x^2 + 3*x + 1, 4*x^2 + 3*x + 6, 5*x + 1], \ - [ x^2 + 5*x + 3, 5*x^2 + 3*x + 2, x + 2]]) - sage: R2 = Matrix(pR, 2, 3, \ - [[ 5*x, 3*x + 4, 5], \ - [4*x + 6, 5*x, 4]]) + sage: Q2 = Matrix(pR, 2, 3, + ....: [[6*x^2 + 3*x + 1, 4*x^2 + 3*x + 6, 5*x + 1], + ....: [ x^2 + 5*x + 3, 5*x^2 + 3*x + 2, x + 2]]) + sage: R2 = Matrix(pR, 2, 3, + ....: [[ 5*x, 3*x + 4, 5], + ....: [4*x + 6, 5*x, 4]]) sage: A == Q2*B + R2 True @@ -3023,8 +3030,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): other cases (rank-deficient or strictly fewer rows than columns) there might be no solution:: - sage: C = B.stack(B[1,:] + B[2,:]) # matrix 4 x 3, full column rank - sage: Q,R = A._right_quo_rem_solve(C); (Q,R) + sage: C = B.stack(B[1,:] + B[2,:]) # 4 x 3, full column rank + sage: Q, R = A._right_quo_rem_solve(C); Q, R ( [ 6*x^2 + 3*x 4*x^2 + 3*x + 1 5*x + 1 0] [ x^2 + 5*x + 5 5*x^2 + 3*x + 5 x + 2 0], @@ -3033,11 +3040,11 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): [ 6*x + 3 5*x^2 + 6 3] ) - sage: A._right_quo_rem_solve(B[:2,:]) # matrix 2 x 3, full row rank + sage: A._right_quo_rem_solve(B[:2,:]) # 2 x 3, full row rank Traceback (most recent call last): ... ValueError: dividing via system solving yields no solution - sage: D = copy(B); D[2,:] = B[0,:]+B[1,:] # square, singular + sage: D = copy(B); D[2,:] = B[0,:]+B[1,:] # square, singular sage: A._right_quo_rem_solve(D) Traceback (most recent call last): ... @@ -3133,13 +3140,13 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: B = Matrix(pR, [ \ - [ 6*x+4, 5*x^3+5*x, 6*x^2+2*x+2], \ - [4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]]) - sage: A = Matrix(pR, 1, 3, [ \ - [3*x^4+3*x^3+4*x^2+5*x+1, x^4+x^3+5*x^2+4*x+4, 4*x^4+2*x^3+x]]) + sage: B = Matrix(pR, [ + ....: [ 6*x+4, 5*x^3+5*x, 6*x^2+2*x+2], + ....: [4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]]) + sage: A = Matrix(pR, 1, 3, [ + ....: [3*x^4+3*x^3+4*x^2+5*x+1, x^4+x^3+5*x^2+4*x+4, 4*x^4+2*x^3+x]]) - sage: (Q,R) = A.reduce(B,return_quotient=True); R + sage: Q, R = A.reduce(B,return_quotient=True); R [3*x^4 + 3*x^3 + 4*x + 3 2*x + 2 2*x + 6] sage: A == Q*B + R True @@ -3157,12 +3164,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Demonstrating shifts:: - sage: (Qs,Rs) = A.reduce(B,shifts=[0,2,4],return_quotient=True); Rs + sage: Qs, Rs = A.reduce(B, shifts=[0,2,4], return_quotient=True); Rs [3*x^4 + 3*x^3 + 6*x + 2 4*x^3 + 5*x 0] sage: A == Qs*B + Rs True sage: Ps = B.popov_form(shifts=[0,2,4]) - sage: Ps.leading_positions(shifts=[0,2,4],return_degree=True) + sage: Ps.leading_positions(shifts=[0,2,4], return_degree=True) ([1, 2], [4, 0]) sage: Rs.degree_matrix() [ 4 3 -1] @@ -3171,17 +3178,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): If ``return_quotient`` is ``False``, only the normal form is returned:: - sage: R == A.reduce(B) and Rs == A.reduce(B,shifts=[0,2,4]) + sage: R == A.reduce(B) and Rs == A.reduce(B, shifts=[0,2,4]) True Demonstrating column-wise normal forms, with a matrix `A` which has several columns, and a matrix `B` which does not have full column rank (its column-wise Popov form has a zero column):: - sage: A = Matrix(pR, 2, 2, \ - [[5*x^3 + 2*x^2 + 4*x + 1, x^3 + 4*x + 4], \ - [2*x^3 + 5*x^2 + 2*x + 4, 2*x^3 + 3*x + 2]]) - sage: (Q,R) = A.reduce(B,row_wise=False,return_quotient=True); R + sage: A = Matrix(pR, 2, 2, + ....: [[5*x^3 + 2*x^2 + 4*x + 1, x^3 + 4*x + 4], + ....: [2*x^3 + 5*x^2 + 2*x + 4, 2*x^3 + 3*x + 2]]) + sage: (Q,R) = A.reduce(B,row_wise=False, return_quotient=True); R [0 3] [0 0] sage: A == B*Q + R @@ -3297,20 +3304,20 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): computing minimal approximant bases, 2006]:: sage: order = 8; shifts = [1,1,0,0,0] - sage: pmat = Matrix(pR, 5, 1, [ \ - pR([35, 0, 41, 87, 3, 42, 22, 90]), \ - pR([80, 15, 62, 87, 14, 93, 24, 0]), \ - pR([42, 57, 90, 87, 22, 80, 71, 53]), \ - pR([37, 72, 74, 6, 5, 75, 23, 47]), \ - pR([36, 10, 74, 1, 29, 44, 87, 74]) ]) - sage: appbas = Matrix(pR, [ \ - [x+47, 57, 58*x+44, 9*x+23, 93*x+76], \ - [ 15, x+18, 52*x+23, 15*x+58, 93*x+88], \ - [ 17, 86, x^2+77*x+16, 76*x+29, 90*x+78], \ - [ 44, 36, 3*x+42, x^2+50*x+26, 85*x+44], \ - [ 2, 22, 54*x+94, 73*x+24, x^2+2*x+25] ]) - sage: appbas.is_minimal_approximant_basis(pmat,\ - order, shifts, row_wise=True, normal_form=True) + sage: pmat = Matrix(pR, 5, 1, [ + ....: pR([35, 0, 41, 87, 3, 42, 22, 90]), + ....: pR([80, 15, 62, 87, 14, 93, 24, 0]), + ....: pR([42, 57, 90, 87, 22, 80, 71, 53]), + ....: pR([37, 72, 74, 6, 5, 75, 23, 47]), + ....: pR([36, 10, 74, 1, 29, 44, 87, 74])]) + sage: appbas = Matrix(pR, [ + ....: [x+47, 57, 58*x+44, 9*x+23, 93*x+76], + ....: [ 15, x+18, 52*x+23, 15*x+58, 93*x+88], + ....: [ 17, 86, x^2+77*x+16, 76*x+29, 90*x+78], + ....: [ 44, 36, 3*x+42, x^2+50*x+26, 85*x+44], + ....: [ 2, 22, 54*x+94, 73*x+24, x^2+2*x+25]]) + sage: appbas.is_minimal_approximant_basis( + ....: pmat, order, shifts, row_wise=True, normal_form=True) True The matrix `x^8 \mathrm{Id}_5` is square, nonsingular, in Popov form, @@ -3318,16 +3325,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): not an approximant basis since its rows generate a module strictly contained in the set of approximants for ``pmat`` at order 8:: - sage: (x^8*Matrix.identity(pR, 5)).is_minimal_approximant_basis(\ - pmat, 8) + sage: M = x^8 * Matrix.identity(pR, 5) + sage: M.is_minimal_approximant_basis(pmat, 8) False Since ``pmat`` is a single column, with nonzero constant coefficient, its column-wise approximant bases at order 8 are all `1\times 1` matrices `[c x^8]` for some nonzero field element `c`:: - sage: Matrix(pR, [x^8]).is_minimal_approximant_basis(pmat, \ - 8, row_wise=False, normal_form=True) + sage: M = Matrix(pR, [x^8]) + sage: M.is_minimal_approximant_basis( + ....: pmat, 8, row_wise=False, normal_form=True) True Exceptions are raised if input dimensions are not sound:: @@ -3338,8 +3346,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): ValueError: order length should be the column dimension of the input matrix - sage: appbas.is_minimal_approximant_basis(pmat, \ - order, shifts, row_wise=False) + sage: appbas.is_minimal_approximant_basis( + ....: pmat, order, shifts, row_wise=False) Traceback (most recent call last): ... ValueError: shifts length should be the column dimension @@ -3504,9 +3512,9 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: pR. = GF(7)[] sage: order = [4, 3]; shifts = [-1, 2, 0] - sage: F = Matrix(pR, [[5*x^3 + 4*x^2 + 4*x + 6, 5*x^2 + 4*x + 1], \ - [ 2*x^2 + 2*x + 3, 6*x^2 + 6*x + 3], \ - [4*x^3 + x + 1, 4*x^2 + 2*x + 3] ]) + sage: F = Matrix(pR, [[5*x^3 + 4*x^2 + 4*x + 6, 5*x^2 + 4*x + 1], + ....: [ 2*x^2 + 2*x + 3, 6*x^2 + 6*x + 3], + ....: [4*x^3 + x + 1, 4*x^2 + 2*x + 3]]) sage: P = F.minimal_approximant_basis(order, shifts) sage: P.is_minimal_approximant_basis(F, order, shifts) True @@ -3514,30 +3522,33 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): By default, the computed basis is not required to be in normal form (and will not be except in rare special cases):: - sage: P.is_minimal_approximant_basis(F, order, shifts, \ - normal_form=True) + sage: P.is_minimal_approximant_basis(F, order, shifts, + ....: normal_form=True) False - sage: P = F.minimal_approximant_basis(order, shifts, normal_form=True) - sage: P.is_minimal_approximant_basis(F, order, shifts, \ - normal_form=True) + sage: P = F.minimal_approximant_basis(order, shifts, + ....: normal_form=True) + sage: P.is_minimal_approximant_basis(F, order, shifts, + ....: normal_form=True) True If shifts are not specified, they are chosen as uniform `[0,\ldots,0]` by default. Besides, if the orders are all the same, one can rather give a single integer:: - sage: F.minimal_approximant_basis(3) == \ - F.minimal_approximant_basis([3,3], shifts=None) + sage: (F.minimal_approximant_basis(3) == + ....: F.minimal_approximant_basis([3,3], shifts=None)) True One can work column-wise by specifying ``row_wise=False``:: - sage: P = F.minimal_approximant_basis([5,2,2], [0,1], row_wise=False) - sage: P.is_minimal_approximant_basis(F, [5,2,2], \ - shifts=[0,1], row_wise=False) + sage: P = F.minimal_approximant_basis([5,2,2], [0,1], + ....: row_wise=False) + sage: P.is_minimal_approximant_basis(F, [5,2,2], shifts=[0,1], + ....: row_wise=False) True - sage: F.minimal_approximant_basis(3, row_wise=True) == \ - F.transpose().minimal_approximant_basis(3, row_wise=False).transpose() + sage: (F.minimal_approximant_basis(3, row_wise=True) == + ....: F.transpose().minimal_approximant_basis( + ....: 3, row_wise=False).transpose()) True Errors are raised if the input dimensions are not sound:: @@ -3657,10 +3668,10 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): arbitrary shifts and orders:: sage: order = [4, 1, 2]; shifts = [-3, 4] - sage: pmat = Matrix(pR, [[5*x^3 + 4*x^2 + 4*x + 6, 5, 4], \ - [2*x^3 + 2*x^2 + 2*x + 3, 6, 6*x + 3]]) - sage: appbas,rdeg = pmat._approximant_basis_iterative(order, \ - shifts) + sage: pmat = Matrix(pR, [[5*x^3 + 4*x^2 + 4*x + 6, 5, 4], + ....: [2*x^3 + 2*x^2 + 2*x + 3, 6, 6*x + 3]]) + sage: appbas, rdeg = pmat._approximant_basis_iterative(order, + ....: shifts) sage: appbas.is_minimal_approximant_basis(pmat, order, shifts) True @@ -3673,8 +3684,8 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): matrices; in fact, this algorithm returns the identity:: sage: pmat = Matrix(pR, 3, 2) - sage: appbas,rdeg = pmat._approximant_basis_iterative([2,5], \ - [5,0,-4]) + sage: appbas,rdeg = pmat._approximant_basis_iterative([2,5], + ....: [5,0,-4]) sage: rdeg == [5,0,-4] and appbas == Matrix.identity(pR, 3) True """ @@ -3805,23 +3816,25 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(97)[] - sage: pmat = Matrix(pR, [[1],[x],[x**2]]) + sage: pmat = Matrix(pR, [[1], [x], [x**2]]) - sage: kerbas = Matrix(pR, [[x,-1,0],[0,x,-1]]) + sage: kerbas = Matrix(pR, [[x,-1,0], [0,x,-1]]) sage: kerbas.is_minimal_kernel_basis(pmat) True A matrix in Popov form which has the right rank, all rows in the kernel, but does not generate the kernel:: - sage: kerbas = Matrix(pR, [[x**2,0,-1],[0,x,-1]]) + sage: kerbas = Matrix(pR, [[x**2,0,-1], [0,x,-1]]) sage: kerbas.is_minimal_kernel_basis(pmat) False Shifts and right kernel bases are supported (with ``row_wise``), and one can test whether the kernel basis is normalized in shifted-Popov form (with ``normal_form``):: - sage: kerbas = Matrix(pR, [[-x,-x**2],[1,0],[0,1]]) - sage: kerbas.is_minimal_kernel_basis(pmat.transpose(),row_wise=False,normal_form=True,shifts=[0,1,2]) + sage: kerbas = Matrix(pR, [[-x,-x**2], [1,0], [0,1]]) + sage: kerbas.is_minimal_kernel_basis( + ....: pmat.transpose(), row_wise=False, + ....: normal_form=True, shifts=[0,1,2]) True """ m = pmat.nrows() @@ -3925,24 +3938,25 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): EXAMPLES:: sage: pR. = GF(7)[] - sage: pmat = Matrix([[(x+1)*(x+3)],[(x+1)*(x+3)+1]]) + sage: pmat = Matrix([[(x+1)*(x+3)], [(x+1)*(x+3)+1]]) sage: pmat.minimal_kernel_basis() [6*x^2 + 3*x + 3 x^2 + 4*x + 3] - sage: pmat = Matrix([[(x+1)*(x+3)],[(x+1)*(x+4)]]) + sage: pmat = Matrix([[(x+1)*(x+3)], [(x+1)*(x+4)]]) sage: pmat.minimal_kernel_basis() [6*x + 3 x + 3] sage: pmat.minimal_kernel_basis(row_wise=False) [] - sage: pmat = Matrix(pR, [[1,x,x**2]]) - sage: pmat.minimal_kernel_basis(row_wise=False,normal_form=True) + sage: pmat = Matrix(pR, [[1, x, x**2]]) + sage: pmat.minimal_kernel_basis(row_wise=False, normal_form=True) [x 0] [6 x] [0 6] - sage: pmat.minimal_kernel_basis(row_wise=False,normal_form=True,shifts=[0,1,2]) + sage: pmat.minimal_kernel_basis(row_wise=False, normal_form=True, + ....: shifts=[0,1,2]) [ 6*x 6*x^2] [ 1 0] [ 0 1] diff --git a/src/sage/matrix/matrix_rational_sparse.pyx b/src/sage/matrix/matrix_rational_sparse.pyx index 37576901d30..06b9689e849 100644 --- a/src/sage/matrix/matrix_rational_sparse.pyx +++ b/src/sage/matrix/matrix_rational_sparse.pyx @@ -268,7 +268,6 @@ cdef class Matrix_rational_sparse(Matrix_sparse): mpq_clear(s) return ans - ######################################################################## # def _pickle(self): # def _unpickle(self, data, int version): # use version >= 0 @@ -281,20 +280,21 @@ cdef class Matrix_rational_sparse(Matrix_sparse): # def _multiply_classical(left, matrix.Matrix _right): # def _list(self): -# TODO -## cpdef _lmul_(self, Element right): -## """ -## EXAMPLES:: -## -## sage: a = matrix(QQ,2,range(6)) -## sage: (3/4) * a -## [ 0 3/4 3/2] -## [ 9/4 3 15/4] -## """ + # TODO + ## cpdef _lmul_(self, Element right): + ## """ + ## EXAMPLES:: + ## + ## sage: a = matrix(QQ,2,range(6)) + ## sage: (3/4) * a + ## [ 0 3/4 3/2] + ## [ 9/4 3 15/4] + ## """ def _dict(self): """ Unsafe version of the dict method, mainly for internal use. + This may return the dict of elements, but as an *unsafe* reference to the underlying dict of the object. It might be dangerous if you change entries of the returned dict. @@ -303,17 +303,16 @@ cdef class Matrix_rational_sparse(Matrix_sparse): if d is not None: return d - cdef Py_ssize_t i, j, k + cdef Py_ssize_t i, j d = {} - for i from 0 <= i < self._nrows: - for j from 0 <= j < self._matrix[i].num_nonzero: + for i in range(self._nrows): + for j in range(self._matrix[i].num_nonzero): x = Rational() mpq_set((x).value, self._matrix[i].entries[j]) - d[(int(i),int(self._matrix[i].positions[j]))] = x + d[(int(i), int(self._matrix[i].positions[j]))] = x self.cache('dict', d) return d - ######################################################################## # LEVEL 3 functionality (Optional) # * cdef _sub_ @@ -325,7 +324,7 @@ cdef class Matrix_rational_sparse(Matrix_sparse): def _nonzero_positions_by_row(self, copy=True): """ - Returns the list of pairs (i,j) such that self[i,j] != 0. + Return the list of pairs (i,j) such that self[i,j] != 0. It is safe to change the resulting list (unless you give the option copy=False). @@ -397,25 +396,23 @@ cdef class Matrix_rational_sparse(Matrix_sparse): return 0 cdef int mpz_denom(self, mpz_t d) except -1: - mpz_set_si(d,1) + mpz_set_si(d, 1) cdef Py_ssize_t i, j - cdef mpq_vector *v sig_on() - for i from 0 <= i < self._nrows: - for j from 0 <= j < self._matrix[i].num_nonzero: + for i in range(self._nrows): + for j in range(self._matrix[i].num_nonzero): mpz_lcm(d, d, mpq_denref(self._matrix[i].entries[j])) sig_off() return 0 - def denominator(self): """ Return the denominator of this matrix. OUTPUT: - -- Sage Integer + - Sage Integer EXAMPLES:: diff --git a/src/sage/matrix/matrix_real_double_dense.pyx b/src/sage/matrix/matrix_real_double_dense.pyx index 39bb0fcdbab..eeff7658041 100644 --- a/src/sage/matrix/matrix_real_double_dense.pyx +++ b/src/sage/matrix/matrix_real_double_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy """ Dense matrices over the Real Double Field using NumPy diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index f3952cecda7..1ea8c0bca9f 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -19,7 +19,7 @@ sage: matrix(RR,2,2,sparse=True) [0.000000000000000 0.000000000000000] [0.000000000000000 0.000000000000000] - sage: matrix(GF(11),2,2,sparse=True) + sage: matrix(GF(11), 2, 2, sparse=True) [0 0] [0 0] """ @@ -114,16 +114,17 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): sage: get_matrix_class(ZZ, 3, 3, False, 'flint') - sage: get_matrix_class(ZZ, 3, 3, False, 'gap') + sage: get_matrix_class(ZZ, 3, 3, False, 'gap') # needs sage.modules sage: get_matrix_class(ZZ, 3, 3, False, 'generic') - sage: get_matrix_class(GF(2^15), 3, 3, False, None) + sage: get_matrix_class(GF(2^15), 3, 3, False, None) # needs sage.rings.finite_rings - sage: get_matrix_class(GF(2^17), 3, 3, False, None) + sage: get_matrix_class(GF(2^17), 3, 3, False, None) # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings sage: get_matrix_class(GF(2), 2, 2, False, 'm4ri') sage: get_matrix_class(GF(4), 2, 2, False, 'm4ri') @@ -133,12 +134,12 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): sage: get_matrix_class(GF(7), 2, 2, False, 'linbox-double') - sage: get_matrix_class(RDF, 2, 2, False, 'numpy') + sage: get_matrix_class(RDF, 2, 2, False, 'numpy') # needs numpy - sage: get_matrix_class(CDF, 2, 3, False, 'numpy') + sage: get_matrix_class(CDF, 2, 3, False, 'numpy') # needs numpy - sage: get_matrix_class(GF(25,'x'), 4, 4, False, 'meataxe') # optional - meataxe + sage: get_matrix_class(GF(25,'x'), 4, 4, False, 'meataxe') # optional - meataxe, needs sage.rings.finite_rings sage: get_matrix_class(IntegerModRing(3), 4, 4, False, 'meataxe') # optional - meataxe @@ -146,7 +147,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): Traceback (most recent call last): ... ValueError: 'meataxe' matrix can only deal with finite fields of order < 256 - sage: get_matrix_class(GF(next_prime(255)), 4, 4, False, 'meataxe') + sage: get_matrix_class(GF(next_prime(255)), 4, 4, False, 'meataxe') # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: 'meataxe' matrix can only deal with finite fields of order < 256 @@ -168,21 +169,21 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): ... ValueError: 'linbox-double' matrices can only deal with order < 94906266 - sage: type(matrix(SR, 2, 2, 0)) + sage: type(matrix(SR, 2, 2, 0)) # needs sage.symbolic - sage: type(matrix(SR, 2, 2, 0, sparse=True)) + sage: type(matrix(SR, 2, 2, 0, sparse=True)) # needs sage.symbolic - sage: type(matrix(GF(7), 2, range(4))) + sage: type(matrix(GF(7), 2, range(4))) # needs sage.rings.finite_rings - sage: type(matrix(GF(16007), 2, range(4))) + sage: type(matrix(GF(16007), 2, range(4))) # needs sage.rings.finite_rings - sage: type(matrix(CBF, 2, range(4))) + sage: type(matrix(CBF, 2, range(4))) # needs sage.libs.flint - sage: type(matrix(GF(2), 2, range(4))) + sage: type(matrix(GF(2), 2, range(4))) # needs sage.rings.finite_rings - sage: type(matrix(GF(64,'z'), 2, range(4))) + sage: type(matrix(GF(64, 'z'), 2, range(4))) # needs sage.rings.finite_rings - sage: type(matrix(GF(125,'z'), 2, range(4))) # optional - meataxe + sage: type(matrix(GF(125, 'z'), 2, range(4))) # optional - meataxe # needs sage.rings.finite_rings """ @@ -250,11 +251,15 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): pass if isinstance(R, sage.rings.abc.IntegerModRing): - from . import matrix_modn_dense_double, matrix_modn_dense_float - if R.order() < matrix_modn_dense_float.MAX_MODULUS: - return matrix_modn_dense_float.Matrix_modn_dense_float - if R.order() < matrix_modn_dense_double.MAX_MODULUS: - return matrix_modn_dense_double.Matrix_modn_dense_double + try: + from . import matrix_modn_dense_double, matrix_modn_dense_float + except ImportError: + pass + else: + if R.order() < matrix_modn_dense_float.MAX_MODULUS: + return matrix_modn_dense_float.Matrix_modn_dense_float + if R.order() < matrix_modn_dense_double.MAX_MODULUS: + return matrix_modn_dense_double.Matrix_modn_dense_double if isinstance(R, sage.rings.abc.NumberField_cyclotomic): from . import matrix_cyclo_dense @@ -491,28 +496,29 @@ class MatrixSpace(UniqueRepresentation, Parent): Check that different implementations play together as expected:: - sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') + sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') # needs sage.libs.flint sage: M2 = MatrixSpace(ZZ, 2, implementation='generic') - sage: type(M1(range(4))) + sage: type(M1(range(4))) # needs sage.libs.flint sage: type(M2(range(4))) - sage: M1(M2.an_element()) + sage: M1(M2.an_element()) # needs sage.libs.flint [ 0 1] [-1 2] - sage: M2(M1.an_element()) + sage: M2(M1.an_element()) # needs sage.libs.flint [ 0 1] [-1 2] - sage: all(((A.get_action(B) is not None) == (A is B)) for A in [M1,M2] for B in [M1,M2]) + sage: all((A.get_action(B) is not None) == (A is B) # needs sage.libs.flint + ....: for A in [M1, M2] for B in [M1, M2]) True Check that libgap matrices over finite fields are working properly:: - sage: M2 = MatrixSpace(GF(2), 5, implementation='gap') - sage: M2.one() + sage: M2 = MatrixSpace(GF(2), 5, implementation='gap') # needs sage.libs.gap sage.rings.finite_rings + sage: M2.one() # needs sage.libs.gap sage.rings.finite_rings [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] @@ -520,7 +526,7 @@ class MatrixSpace(UniqueRepresentation, Parent): [0 0 0 0 1] sage: m = M2.random_element() sage: M1 = MatrixSpace(GF(2), 5) - sage: M1(m * m) == M1(m) * M1(m) + sage: M1(m * m) == M1(m) * M1(m) # needs sage.libs.gap sage.rings.finite_rings True """ @@ -535,16 +541,18 @@ def __classcall__(cls, base_ring, nrows, ncols=None, sparse=False, implementatio sage: M1 = MatrixSpace(QQ, 2) sage: M2 = MatrixSpace(QQ, 2) - sage: M3 = MatrixSpace(QQ, 2, implementation='flint') - sage: M1 is M2 and M1 is M3 + sage: M1 is M2 + True + sage: M3 = MatrixSpace(QQ, 2, implementation='flint') # needs sage.libs.flint + sage: M1 is M3 # needs sage.libs.flint True :: - sage: M = MatrixSpace(ZZ, 10, implementation="flint") - sage: M + sage: M = MatrixSpace(ZZ, 10, implementation="flint") # needs sage.libs.flint + sage: M # needs sage.libs.flint Full MatrixSpace of 10 by 10 dense matrices over Integer Ring - sage: loads(M.dumps()) is M + sage: loads(M.dumps()) is M # needs sage.libs.flint True sage: MatrixSpace(ZZ, 10, implementation="foobar") @@ -675,6 +683,8 @@ def __init__(self, base_ring, nrows, ncols, sparse, implementation): 200 x 1 dense matrix over Rational Field (use the '.str()' method to see the entries) sage: A = MatrixSpace(RDF,1000,1000).random_element() sage: B = MatrixSpace(RDF,1000,1000).random_element() + + sage: # needs numpy (otherwise timeout) sage: C = A * B We check that :trac:`18186` is fixed:: @@ -748,7 +758,7 @@ def characteristic(self): sage: MatrixSpace(ZZ, 2).characteristic() 0 - sage: MatrixSpace(GF(9), 0).characteristic() + sage: MatrixSpace(GF(9), 0).characteristic() # needs sage.rings.finite_rings 3 """ return self.base_ring().characteristic() @@ -795,15 +805,15 @@ def _copy_zero(self): EXAMPLES:: - sage: MS = MatrixSpace(GF(2),20,20) - sage: MS._copy_zero + sage: MS = MatrixSpace(GF(2), 20, 20) + sage: MS._copy_zero # needs sage.rings.finite_rings False - sage: MS = MatrixSpace(GF(3),20,20) - sage: MS._copy_zero + sage: MS = MatrixSpace(GF(3), 20, 20) + sage: MS._copy_zero # needs sage.rings.finite_rings True - sage: MS = MatrixSpace(GF(3),200,200) - sage: MS._copy_zero + sage: MS = MatrixSpace(GF(3), 200, 200) + sage: MS._copy_zero # needs sage.rings.finite_rings False sage: MS = MatrixSpace(ZZ,200,200) @@ -838,9 +848,10 @@ def _element_constructor_(self, entries, **kwds): EXAMPLES:: - sage: k = GF(7); G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])]) + sage: k = GF(7) + sage: G = MatrixGroup([matrix(k, 2, [1,1,0,1]), matrix(k, 2, [1,0,0,2])]) sage: g = G.0 - sage: MatrixSpace(k,2)(g) + sage: MatrixSpace(k, 2)(g) [1 1] [0 1] @@ -870,7 +881,7 @@ def _element_constructor_(self, entries, **kwds): [3 4] sage: MS = MatrixSpace(ZZ, 2) - sage: g = Gamma0(5)([1,1,0,1]) + sage: g = Gamma0(5)([1,1,0,1]) # needs sage.modular sage: MS(g) [1 1] [0 1] @@ -890,14 +901,17 @@ def _element_constructor_(self, entries, **kwds): Ensure that :trac:`12020` is fixed:: + sage: rings = [ZZ, QQ, RealField(100), ComplexField(100), RDF, CDF] + sage: rings.append(PolynomialRing(QQ, 'x')) + sage: rings.append(PolynomialRing(CC, 2, 'x')) + sage: rings.append(SR) # needs sage.symbolic + sage: rings.extend([GF(2), GF(11), GF(2^8,'a'), GF(3^19,'a')]) # needs sage.rings.finite_rings sage: x = polygen(QQ) - sage: for R in [ZZ, QQ, RealField(100), ComplexField(100), RDF, CDF, - ....: SR, GF(2), GF(11), GF(2^8,'a'), GF(3^19,'a'), - ....: NumberField(x^3+2,'a'), CyclotomicField(4), - ....: PolynomialRing(QQ,'x'), PolynomialRing(CC,2,'x')]: - ....: A = MatrixSpace(R,60,30,sparse=False)(0) + sage: rings.extend([NumberField(x^3 + 2, 'a'), CyclotomicField(4)]) # needs sage.rings.number_field + sage: for R in rings: + ....: A = MatrixSpace(R, 60, 30, sparse=False)(0) ....: B = A.augment(A) - ....: A = MatrixSpace(R,60,30,sparse=True)(0) + ....: A = MatrixSpace(R, 60, 30, sparse=True)(0) ....: B = A.augment(A) Check that :trac:`13012` is fixed:: @@ -958,8 +972,9 @@ def change_ring(self, R): EXAMPLES:: - sage: Mat(QQ,3,5).change_ring(GF(7)) - Full MatrixSpace of 3 by 5 dense matrices over Finite Field of size 7 + sage: Mat(QQ, 3, 5).change_ring(GF(7)) + Full MatrixSpace of 3 by 5 dense matrices + over Finite Field of size 7 """ try: return self.__change_ring[R] @@ -983,9 +998,9 @@ def base_extend(self, R): EXAMPLES:: - sage: Mat(ZZ,3,5).base_extend(QQ) + sage: Mat(ZZ, 3, 5).base_extend(QQ) Full MatrixSpace of 3 by 5 dense matrices over Rational Field - sage: Mat(QQ,3,5).base_extend(GF(7)) + sage: Mat(QQ, 3, 5).base_extend(GF(7)) Traceback (most recent call last): ... TypeError: no base extension defined @@ -1144,8 +1159,8 @@ def _coerce_map_from_(self, S): Coercion map: From: General Linear Group of degree 2 over Finite Field of size 3 To: Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3 - sage: MS.coerce_map_from(GL(2, 2)) - sage: MS.coerce_map_from(Gamma1(5)) + sage: MS.coerce_map_from(GL(2, 2)) # needs sage.rings.finite_rings + sage: MS.coerce_map_from(Gamma1(5)) # needs sage.rings.finite_rings Coercion map: From: Congruence Subgroup Gamma1(5) To: Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3 @@ -1169,7 +1184,7 @@ def _coerce_map_from_(self, S): sage: m = R([[1, 0], [0, 1]]) sage: m in G True - sage: m in list(G) + sage: m in list(G) # needs sage.libs.gap True sage: m == G(m) True @@ -1186,11 +1201,11 @@ def _coerce_map_from_(self, S): Verify which coercion maps are allowed (this should form a poset):: - sage: M1 = MatrixSpace(ZZ, 3, implementation='flint') - sage: M2 = MatrixSpace(ZZ, 3, implementation='generic') - sage: M3 = MatrixSpace(ZZ, 3, implementation='gap') - sage: M4 = MatrixSpace(ZZ, 3, sparse=True) - sage: S = [M1, M2, M3, M4] + sage: S = [] + sage: S += [MatrixSpace(ZZ, 3, implementation='flint')] # needs sage.libs.flint + sage: S += [MatrixSpace(ZZ, 3, implementation='generic')] + sage: S += [MatrixSpace(ZZ, 3, implementation='gap')] # needs sage.libs.gap + sage: S += [MatrixSpace(ZZ, 3, sparse=True)] sage: mult = '' sage: for A in S: ....: for B in S: @@ -1199,7 +1214,7 @@ def _coerce_map_from_(self, S): ....: else: ....: mult += ' ' ....: mult += '\n' - sage: print(mult) + sage: print(mult) # needs sage.libs.flint sage.libs.gap XXXX X X XX @@ -1279,7 +1294,7 @@ def _repr_(self): sage: MS Full MatrixSpace of 2 by 4 sparse matrices over Integer Ring - sage: MatrixSpace(ZZ, 2, implementation='flint') + sage: MatrixSpace(ZZ, 2, implementation='flint') # needs sage.libs.flint Full MatrixSpace of 2 by 2 dense matrices over Integer Ring sage: MatrixSpace(ZZ, 2, implementation='generic') Full MatrixSpace of 2 by 2 dense matrices over Integer Ring (using Matrix_generic_dense) @@ -1334,14 +1349,14 @@ def __len__(self): EXAMPLES:: - sage: len(MatrixSpace(GF(3),3,2)) + sage: len(MatrixSpace(GF(3), 3, 2)) 729 - sage: len(MatrixSpace(GF(3),2,3)) + sage: len(MatrixSpace(GF(3), 2, 3)) 729 sage: 3^(2*3) 729 - sage: len(MatrixSpace(GF(2003),3,2)) + sage: len(MatrixSpace(GF(2003), 3, 2)) # needs sage.rings.finite_rings Traceback (most recent call last): ... OverflowError: cannot fit 'int' into an index-sized integer @@ -1367,7 +1382,7 @@ def __iter__(self): :: - sage: list( GF(5) ) + sage: list(GF(5)) [0, 1, 2, 3, 4] sage: MS = MatrixSpace(GF(5), 2, 2) sage: l = list(MS) @@ -1428,7 +1443,7 @@ def __iter__(self): Some more examples:: - sage: MS = MatrixSpace(GF(2),2) + sage: MS = MatrixSpace(GF(2), 2) sage: a = list(MS) sage: len(a) 16 @@ -1486,7 +1501,7 @@ def __iter__(self): :: - sage: MS = MatrixSpace(GF(2),2, 3) + sage: MS = MatrixSpace(GF(2), 2, 3) sage: a = list(MS) sage: len(a) 64 @@ -1512,11 +1527,11 @@ def __iter__(self): :: - sage: list( MatrixSpace(GF(2), 2, 0) ) + sage: list(MatrixSpace(GF(2), 2, 0)) [[]] - sage: list( MatrixSpace(GF(2), 0, 2) ) + sage: list(MatrixSpace(GF(2), 0, 2)) [[]] - sage: list( MatrixSpace(GF(2), 0, 0) ) + sage: list(MatrixSpace(GF(2), 0, 0)) [[]] If the base ring does not support iteration (for example, with the @@ -1588,7 +1603,9 @@ def __getitem__(self, x): sage: MS = MatrixSpace(GF(3), 2, 2) sage: MS['x'] - Univariate Polynomial Ring in x over Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3 + Univariate Polynomial Ring in x + over Full MatrixSpace of 2 by 2 dense matrices + over Finite Field of size 3 sage: MS[0] [0 0] [0 0] @@ -1793,10 +1810,10 @@ def identity_matrix(self): Check different implementations:: - sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') + sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') # needs sage.libs.flint sage: M2 = MatrixSpace(ZZ, 2, implementation='generic') - sage: type(M1.identity_matrix()) + sage: type(M1.identity_matrix()) # needs sage.libs.flint sage: type(M2.identity_matrix()) @@ -1851,10 +1868,10 @@ def diagonal_matrix(self, entries): Check different implementations:: - sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') + sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') # needs sage.libs.flint sage: M2 = MatrixSpace(ZZ, 2, implementation='generic') - sage: type(M1.diagonal_matrix([1, 2])) + sage: type(M1.diagonal_matrix([1, 2])) # needs sage.libs.flint sage: type(M2.diagonal_matrix([1, 2])) @@ -1887,9 +1904,9 @@ def is_sparse(self): EXAMPLES:: - sage: Mat(GF(2011),10000).is_sparse() + sage: Mat(GF(2011), 10000).is_sparse() # needs sage.rings.finite_rings False - sage: Mat(GF(2011),10000,sparse=True).is_sparse() + sage: Mat(GF(2011), 10000, sparse=True).is_sparse() # needs sage.rings.finite_rings True """ return self.__is_sparse @@ -1916,7 +1933,7 @@ def gen(self, n): EXAMPLES:: - sage: M = Mat(GF(7),10000,5); M.ngens() + sage: M = Mat(GF(7), 10000, 5); M.ngens() 50000 sage: a = M.10 sage: a[:4] @@ -1943,7 +1960,7 @@ def zero_matrix(self): EXAMPLES:: - sage: z = MatrixSpace(GF(7),2,4).zero_matrix(); z + sage: z = MatrixSpace(GF(7), 2, 4).zero_matrix(); z [0 0 0 0] [0 0 0 0] sage: z.is_mutable() @@ -1977,7 +1994,7 @@ def ngens(self): EXAMPLES:: - sage: M = Mat(GF(7),100,200); M.ngens() + sage: M = Mat(GF(7), 100, 200); M.ngens() 20000 """ return self.dimension() @@ -2048,8 +2065,8 @@ def matrix(self, x=None, **kwds): [2] sage: MS = MatrixSpace(CC, 2, 1) sage: x = polygen(ZZ, 'x') - sage: F = NumberField(x^2 + 1, name='x') # optional - sage.rings.number_field - sage: MS([F(1), F(0)]) # optional - sage.rings.number_field + sage: F = NumberField(x^2 + 1, name='x') # needs sage.rings.number_field + sage: MS([F(1), F(0)]) # needs sage.rings.number_field [ 1.00000000000000] [0.000000000000000] @@ -2072,19 +2089,20 @@ def matrix(self, x=None, **kwds): Check that :trac:`13302` is fixed:: - sage: MatrixSpace(Qp(3),1,1)([Qp(3).zero()]) + sage: MatrixSpace(Qp(3), 1,1)([Qp(3).zero()]) # needs sage.rings.padics [0] - sage: MatrixSpace(Qp(3),1,1)([Qp(3)(4/3)]) + sage: MatrixSpace(Qp(3), 1,1)([Qp(3)(4/3)]) # needs sage.rings.padics [3^-1 + 1 + O(3^19)] One-rowed matrices over combinatorial free modules used to break the constructor (:trac:`17124`). Check that this is fixed:: + sage: # needs sage.combinat sage: Sym = SymmetricFunctions(ZZ) sage: h = Sym.h() - sage: MatrixSpace(h,1,1)([h[1]]) + sage: MatrixSpace(h, 1,1)([h[1]]) [h[1]] - sage: MatrixSpace(h,2,1)([h[1], h[2]]) + sage: MatrixSpace(h, 2,1)([h[1], h[2]]) [h[1]] [h[2]] @@ -2093,7 +2111,7 @@ def matrix(self, x=None, **kwds): sage: m = identity_matrix(GF(2), 2000, sparse=True) sage: MS = MatrixSpace(GF(2), 2000, sparse=False) - sage: md = MS(m) # used to be slow + sage: md = MS(m) sage: md.parent() is MS True """ @@ -2107,7 +2125,7 @@ def matrix_space(self, nrows=None, ncols=None, sparse=False): EXAMPLES:: - sage: M = Mat(GF(7),100,200) + sage: M = Mat(GF(7), 100, 200) sage: M.matrix_space(5000) Full MatrixSpace of 5000 by 200 dense matrices over Finite Field of size 7 sage: M.matrix_space(ncols=5000) @@ -2172,7 +2190,7 @@ def column_space(self): EXAMPLES:: - sage: M = Mat(GF(9,'a'),20,5,sparse=True); M.column_space() + sage: M = Mat(GF(9,'a'), 20, 5, sparse=True); M.column_space() # needs sage.rings.finite_rings Sparse vector space of dimension 20 over Finite Field in a of size 3^2 """ try: @@ -2229,10 +2247,10 @@ def random_element(self, density=None, *args, **kwds): sage: TestSuite(M).run() sage: M = Mat(QQ, 3, sparse=True).random_element() - sage: TestSuite(M).run() + sage: TestSuite(M).run() # needs sage.libs.pari - sage: M = Mat(GF(9,'a'), 3, sparse=True).random_element() - sage: TestSuite(M).run() + sage: M = Mat(GF(9,'a'), 3, sparse=True).random_element() # needs sage.rings.finite_rings + sage: TestSuite(M).run() # needs sage.rings.finite_rings """ Z = self.zero_matrix().__copy__() if density is None: @@ -2329,8 +2347,8 @@ def some_elements(self): [ 1/2 -1/2 2] [1 0 0] [0 1 0] [0 0 1] [0 0 0] [0 0 0] [0 0 0] [ -2 0 1], [0 0 0], [0 0 0], [0 0 0], [1 0 0], [0 1 0], [0 0 1] ) - sage: M = MatrixSpace(SR, 2, 2) - sage: tuple(M.some_elements()) + sage: M = MatrixSpace(SR, 2, 2) # needs sage.symbolic + sage: tuple(M.some_elements()) # needs sage.symbolic ( [some_variable some_variable] [1 0] [0 1] [0 0] [0 0] [some_variable some_variable], [0 0], [0 0], [1 0], [0 1] @@ -2365,9 +2383,9 @@ def _polymake_init_(self): EXAMPLES:: - sage: polymake(MatrixSpace(QQ,3)) # optional - jupymake + sage: polymake(MatrixSpace(QQ, 3)) # optional - jupymake Matrix - sage: polymake(MatrixSpace(QuadraticField(5),3)) # optional - jupymake + sage: polymake(MatrixSpace(QuadraticField(5), 3)) # optional - jupymake, needs sage.rings.number_field Matrix """ from sage.interfaces.polymake import polymake @@ -2481,14 +2499,14 @@ def _test_trivial_matrices_inverse(ring, sparse=True, implementation=None, check sage: tinv(GF(11), sparse=False) sage: tinv(GF(2), sparse=True) sage: tinv(GF(2), sparse=False) - sage: tinv(SR, sparse=True) - sage: tinv(SR, sparse=False) + sage: tinv(SR, sparse=True) # needs sage.symbolic + sage: tinv(SR, sparse=False) # needs sage.symbolic sage: tinv(RDF, sparse=True) sage: tinv(RDF, sparse=False) sage: tinv(CDF, sparse=True) sage: tinv(CDF, sparse=False) - sage: tinv(CyclotomicField(7), sparse=True) - sage: tinv(CyclotomicField(7), sparse=False) + sage: tinv(CyclotomicField(7), sparse=True) # needs sage.rings.number_field + sage: tinv(CyclotomicField(7), sparse=False) # needs sage.rings.number_field sage: tinv(QQ['x,y'], sparse=True) sage: tinv(QQ['x,y'], sparse=False) diff --git a/src/sage/matrix/matrix_sparse.pyx b/src/sage/matrix/matrix_sparse.pyx index 1addeac9b83..6c4199340c9 100644 --- a/src/sage/matrix/matrix_sparse.pyx +++ b/src/sage/matrix/matrix_sparse.pyx @@ -363,10 +363,10 @@ cdef class Matrix_sparse(matrix.Matrix): return data, version def _unpickle_generic(self, data, int version): - cdef Py_ssize_t i, j, k + cdef Py_ssize_t i, j if version == -1: - for ij, x in data.iteritems(): - self.set_unsafe(ij[0], ij[1], x) + for (i, j), x in data.iteritems(): + self.set_unsafe(i, j, x) else: raise RuntimeError("unknown matrix version (=%s)" % version) @@ -641,7 +641,8 @@ cdef class Matrix_sparse(matrix.Matrix): [3 4 0] [1 2 3] sage: m.apply_morphism(phi).parent() - Full MatrixSpace of 3 by 3 sparse matrices over Finite Field of size 5 + Full MatrixSpace of 3 by 3 sparse matrices + over Finite Field of size 5 """ R = phi.codomain() M = sage.matrix.matrix_space.MatrixSpace(R, self._nrows, @@ -670,22 +671,26 @@ cdef class Matrix_sparse(matrix.Matrix): EXAMPLES:: sage: m = matrix(ZZ, 10000, {(1,2): 17}, sparse=True) + + sage: # needs sage.rings.finite_rings sage: k. = GF(9) sage: f = lambda x: k(x) sage: n = m.apply_map(f) sage: n.parent() - Full MatrixSpace of 10000 by 10000 sparse matrices over Finite Field in a of size 3^2 - sage: n[1,2] + Full MatrixSpace of 10000 by 10000 sparse matrices + over Finite Field in a of size 3^2 + sage: n[1, 2] 2 An example where the codomain is explicitly specified. :: - sage: n = m.apply_map(lambda x:x%3, GF(3)) + sage: n = m.apply_map(lambda x: x%3, GF(3)) sage: n.parent() - Full MatrixSpace of 10000 by 10000 sparse matrices over Finite Field of size 3 - sage: n[1,2] + Full MatrixSpace of 10000 by 10000 sparse matrices + over Finite Field of size 3 + sage: n[1, 2] 2 If we did not specify the codomain, the resulting matrix in the @@ -694,7 +699,7 @@ cdef class Matrix_sparse(matrix.Matrix): sage: n = m.apply_map(lambda x:x%3) sage: n.parent() Full MatrixSpace of 10000 by 10000 sparse matrices over Integer Ring - sage: n[1,2] + sage: n[1, 2] 2 If self is subdivided, the result will be as well:: @@ -805,8 +810,8 @@ cdef class Matrix_sparse(matrix.Matrix): EXAMPLES:: - sage: m = matrix(2, [x^i for i in range(4)], sparse=True) - sage: m._derivative(x) + sage: m = matrix(2, [x^i for i in range(4)], sparse=True) # needs sage.symbolic + sage: m._derivative(x) # needs sage.symbolic [ 0 1] [ 2*x 3*x^2] """ @@ -924,7 +929,6 @@ cdef class Matrix_sparse(matrix.Matrix): cdef Py_ssize_t nrows, ncols,k,r,i,j - r = 0 ncols = PyList_GET_SIZE(columns) nrows = PyList_GET_SIZE(rows) cdef Matrix_sparse A = self.new_matrix(nrows = nrows, ncols = ncols) @@ -958,7 +962,7 @@ cdef class Matrix_sparse(matrix.Matrix): i = get_ij(nz, k, 0) j = get_ij(nz, k, 1) if i in row_map and j in col_map: - entry = self.get_unsafe(i,j) + entry = self.get_unsafe(i, j) for new_row in row_map[i]: for new_col in col_map[j]: A.set_unsafe(new_row, new_col, entry) @@ -1174,8 +1178,9 @@ cdef class Matrix_sparse(matrix.Matrix): Check that the bug in :trac:`13854` has been fixed:: + sage: # needs sage.combinat sage: A. = FreeAlgebra(QQ, 2) - sage: P. = A.g_algebra(relations={y*x:-x*y}, order = 'lex') + sage: P. = A.g_algebra(relations={y*x: -x*y}, order='lex') sage: M = Matrix([[x]], sparse=True) sage: w = vector([y]) doctest:...: UserWarning: You are constructing a free module diff --git a/src/sage/matrix/matrix_window.pyx b/src/sage/matrix/matrix_window.pyx index 38745fc25f1..e6046919191 100644 --- a/src/sage/matrix/matrix_window.pyx +++ b/src/sage/matrix/matrix_window.pyx @@ -104,7 +104,6 @@ cdef class MatrixWindow: def __getitem__(self, ij): cdef Py_ssize_t i, j - cdef object x if isinstance(ij, tuple): # ij is a tuple, so we get i and j efficiently, construct corresponding integer entry. @@ -112,7 +111,7 @@ cdef class MatrixWindow: raise IndexError("index must be an integer or pair of integers") i = PyTuple_GET_ITEM(ij, 0) j = PyTuple_GET_ITEM(ij, 1) - if i<0 or i >= self._nrows or j<0 or j >= self._ncols: + if i < 0 or i >= self._nrows or j < 0 or j >= self._ncols: raise IndexError("matrix index out of range") return self.get_unsafe(i, j) else: diff --git a/src/sage/matrix/operation_table.py b/src/sage/matrix/operation_table.py index 79acaaf8390..69cc34d221e 100644 --- a/src/sage/matrix/operation_table.py +++ b/src/sage/matrix/operation_table.py @@ -81,8 +81,8 @@ class OperationTable(SageObject): In its most basic use, the table needs a structure and an operation:: sage: from sage.matrix.operation_table import OperationTable - sage: G=SymmetricGroup(3) - sage: OperationTable(G, operation=operator.mul) + sage: G = SymmetricGroup(3) # needs sage.groups + sage: OperationTable(G, operation=operator.mul) # needs sage.groups * a b c d e f +------------ a| a b c d e f @@ -96,7 +96,7 @@ class OperationTable(SageObject): want:: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(6) + sage: R = Integers(6) sage: OperationTable(R, operation=operator.add) + a b c d e f +------------ @@ -112,8 +112,8 @@ class OperationTable(SageObject): 26 elements. :: sage: from sage.matrix.operation_table import OperationTable - sage: G=DihedralGroup(14) - sage: OperationTable(G, operator.mul, names='letters') + sage: G = DihedralGroup(14) # needs sage.groups + sage: OperationTable(G, operator.mul, names='letters') # needs sage.groups * aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az ba bb +------------------------------------------------------------------------------------ aa| aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az ba bb @@ -149,8 +149,8 @@ class OperationTable(SageObject): zeros to make a common width. :: sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(4) - sage: OperationTable(G, operator.mul, names='digits') + sage: G = AlternatingGroup(4) # needs sage.groups + sage: OperationTable(G, operator.mul, names='digits') # needs sage.groups * 00 01 02 03 04 05 06 07 08 09 10 11 +------------------------------------ 00| 00 01 02 03 04 05 06 07 08 09 10 11 @@ -171,8 +171,8 @@ class OperationTable(SageObject): of the elements can be used. :: sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(3) - sage: OperationTable(G, operator.mul, names='elements') + sage: G = AlternatingGroup(3) # needs sage.groups + sage: OperationTable(G, operator.mul, names='elements') # needs sage.groups * () (1,2,3) (1,3,2) +------------------------ ()| () (1,2,3) (1,3,2) @@ -184,6 +184,7 @@ class OperationTable(SageObject): :meth:`~sage.matrix.operation_table.OperationTable.column_keys` method. :: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable sage: G = QuaternionGroup() sage: T = OperationTable(G, operator.mul) @@ -278,10 +279,10 @@ class OperationTable(SageObject): odd. The LaTeX version works much better. :: sage: from sage.matrix.operation_table import OperationTable - sage: L=FiniteSemigroups().example(()) + sage: L = FiniteSemigroups().example(()) sage: L An example of a finite semigroup: the left regular band generated by () - sage: T=OperationTable(L, operation=operator.mul) + sage: T = OperationTable(L, operation=operator.mul) sage: T * + @@ -301,8 +302,9 @@ class OperationTable(SageObject): structure, in forms that can be coerced into the structure. Here we demonstrate the proper use first:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: H=CyclicPermutationGroup(4) + sage: H = CyclicPermutationGroup(4) sage: H.list() [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)] sage: elts = ['()', '(1,3)(2,4)'] @@ -315,6 +317,7 @@ class OperationTable(SageObject): This can be rewritten so as to pass the actual elements of the group ``H``, using a simple ``for`` loop:: + sage: # needs sage.groups sage: L = H.list() #list of elements of the group H sage: elts = [L[i] for i in {0, 2}] sage: elts @@ -327,6 +330,7 @@ class OperationTable(SageObject): Here are a couple of improper uses:: + sage: # needs sage.groups sage: elts.append(5) sage: OperationTable(H, operator.mul, elements=elts) Traceback (most recent call last): @@ -345,13 +349,13 @@ class OperationTable(SageObject): Unusable functions should be recognized as such:: - sage: H=CyclicPermutationGroup(4) - sage: OperationTable(H, operator.add) + sage: H = CyclicPermutationGroup(4) # needs sage.groups + sage: OperationTable(H, operator.add) # needs sage.groups Traceback (most recent call last): ... TypeError: elements () and () of Cyclic group of order 4 as a permutation group are incompatible with operation: sage: from operator import xor - sage: OperationTable(H, xor) + sage: OperationTable(H, xor) # needs sage.groups Traceback (most recent call last): ... TypeError: elements () and () of Cyclic group of order 4 as a permutation group are incompatible with operation: @@ -359,9 +363,9 @@ class OperationTable(SageObject): We construct the multiplication table for a finite finitely presented group, where there is no normalization done when computing the hash:: - sage: GU. = FreeGroup() - sage: gr0 = GU / (s^(-2)*t*s*t, t^(-2)*s*t*s, s*t*s*t) - sage: gr0.multiplication_table() + sage: GU. = FreeGroup() # needs sage.groups + sage: gr0 = GU / (s^(-2)*t*s*t, t^(-2)*s*t*s, s*t*s*t) # needs sage.groups + sage: gr0.multiplication_table() # needs sage.groups * a b c d e f g h i j k l +------------------------ a| a b c d e f g h i j k l @@ -388,9 +392,9 @@ def __init__(self, S, operation, names='letters', elements=None): TESTS:: sage: from sage.matrix.operation_table import OperationTable - sage: G=SymmetricGroup(3) - sage: T=OperationTable(G, operator.mul) - sage: TestSuite(T).run() + sage: G = SymmetricGroup(3) # needs sage.groups + sage: T = OperationTable(G, operator.mul) # needs sage.groups + sage: TestSuite(T).run() # needs sage.groups """ # Determine the elements of S, specified or not # If elements are given, we check if they are all in S @@ -509,9 +513,10 @@ def _name_maker(self, names): and :meth:`change_names` methods. So we just demonstrate the nature of the output here. :: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=SymmetricGroup(3) - sage: T=OperationTable(G, operator.mul) + sage: G = SymmetricGroup(3) + sage: T = OperationTable(G, operator.mul) sage: w, l, d = T._name_maker('letters') sage: w 1 @@ -526,9 +531,10 @@ def _name_maker(self, names): doctests for the :class:`OperationTable` and :meth:`change_names` methods that rely on this one. :: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(3) - sage: T=OperationTable(G, operator.mul) + sage: G = AlternatingGroup(3) + sage: T = OperationTable(G, operator.mul) sage: T._name_maker(['x']) Traceback (most recent call last): ... @@ -607,9 +613,10 @@ def __getitem__(self, pair): EXAMPLES:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=DiCyclicGroup(3) - sage: T=OperationTable(G, operator.mul) + sage: G = DiCyclicGroup(3) + sage: T = OperationTable(G, operator.mul) sage: T.column_keys() ((), (5,6,7), ..., (1,4,2,3)(5,7)) sage: T[G('(1,2)(3,4)(5,6,7)'), G('(1,3,2,4)(5,7)')] @@ -617,6 +624,7 @@ def __getitem__(self, pair): TESTS:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable sage: G = DiCyclicGroup(3) sage: T = OperationTable(G, operator.mul) @@ -662,13 +670,14 @@ def __eq__(self, other): EXAMPLES:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=CyclicPermutationGroup(6) - sage: H=CyclicPermutationGroup(3) - sage: P=OperationTable(G, operator.mul) - sage: Q=OperationTable(G, operator.mul) - sage: R=OperationTable(H, operator.mul) - sage: S=OperationTable(G, operator.truediv) + sage: G = CyclicPermutationGroup(6) + sage: H = CyclicPermutationGroup(3) + sage: P = OperationTable(G, operator.mul) + sage: Q = OperationTable(G, operator.mul) + sage: R = OperationTable(H, operator.mul) + sage: S = OperationTable(G, operator.truediv) sage: P == P, P == Q, P == R, P == S (True, True, False, False) """ @@ -680,13 +689,14 @@ def __ne__(self, other): EXAMPLES:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=CyclicPermutationGroup(6) - sage: H=CyclicPermutationGroup(3) - sage: P=OperationTable(G, operator.mul) - sage: Q=OperationTable(G, operator.mul) - sage: R=OperationTable(H, operator.mul) - sage: S=OperationTable(G, operator.truediv) + sage: G = CyclicPermutationGroup(6) + sage: H = CyclicPermutationGroup(3) + sage: P = OperationTable(G, operator.mul) + sage: Q = OperationTable(G, operator.mul) + sage: R = OperationTable(H, operator.mul) + sage: S = OperationTable(G, operator.truediv) sage: P != P, P != Q, P != R, P != S (False, False, True, True) """ @@ -699,8 +709,8 @@ def _repr_(self): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(5) - sage: T=OperationTable(R, operation=operator.add) + sage: R = Integers(5) + sage: T = OperationTable(R, operation=operator.add) sage: print(T._repr_()) + a b c d e +---------- @@ -724,9 +734,10 @@ def set_print_symbols(self, ascii, latex): EXAMPLES:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(3) - sage: T=OperationTable(G, operator.mul) + sage: G = AlternatingGroup(3) + sage: T = OperationTable(G, operator.mul) sage: T.set_print_symbols('@', '\\times') sage: T @ a b c @@ -739,9 +750,10 @@ def set_print_symbols(self, ascii, latex): TESTS:: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(3) - sage: T=OperationTable(G, operator.mul) + sage: G = AlternatingGroup(3) + sage: T = OperationTable(G, operator.mul) sage: T.set_print_symbols('@', 5) Traceback (most recent call last): ... @@ -781,9 +793,9 @@ def column_keys(self): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(3) - sage: T=OperationTable(G, operator.mul) - sage: T.column_keys() + sage: G = AlternatingGroup(3) # needs sage.groups + sage: T = OperationTable(G, operator.mul) # needs sage.groups + sage: T.column_keys() # needs sage.groups ((), (1,2,3), (1,3,2)) """ return self._elts @@ -807,9 +819,9 @@ def translation(self): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: G=AlternatingGroup(3) - sage: T=OperationTable(G, operator.mul, names=['p','q','r']) - sage: T.translation() + sage: G = AlternatingGroup(3) # needs sage.groups + sage: T = OperationTable(G, operator.mul, names=['p','q','r']) # needs sage.groups + sage: T.translation() # needs sage.groups {'p': (), 'q': (1,2,3), 'r': (1,3,2)} """ return self._name_dict @@ -828,9 +840,9 @@ def table(self): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: C=CyclicPermutationGroup(3) - sage: T=OperationTable(C, operator.mul) - sage: T.table() + sage: C = CyclicPermutationGroup(3) # needs sage.groups + sage: T=OperationTable(C, operator.mul) # needs sage.groups + sage: T.table() # needs sage.groups [[0, 1, 2], [1, 2, 0], [2, 0, 1]] """ return self._table @@ -869,9 +881,10 @@ def change_names(self, names): :class:`OperationTable` since creating a new operation table uses the same routine. :: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable - sage: D=DihedralGroup(2) - sage: T=OperationTable(D, operator.mul) + sage: D = DihedralGroup(2) + sage: T = OperationTable(D, operator.mul) sage: T * a b c d +-------- @@ -926,6 +939,7 @@ def matrix_of_variables(self): The output here is from the doctests for the old ``cayley_table()`` method for permutation groups. :: + sage: # needs sage.groups sage: from sage.matrix.operation_table import OperationTable sage: G = PermutationGroup(['(1,2,3)', '(2,3)']) sage: T = OperationTable(G, operator.mul) @@ -963,8 +977,8 @@ def color_table(self, element_names=True, cmap=None, **options): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: OTa = OperationTable(SymmetricGroup(3), operation=operator.mul) # optional - sage.plot, sage.groups - sage: OTa.color_table() # optional - sage.plot, sage.groups + sage: OTa = OperationTable(SymmetricGroup(3), operation=operator.mul) # needs sage.groups sage.plot + sage: OTa.color_table() # needs sage.groups sage.plot Graphics object consisting of 37 graphics primitives .. PLOT:: @@ -1023,8 +1037,8 @@ def gray_table(self, **options): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: OTa = OperationTable(SymmetricGroup(3), operation=operator.mul) # optional - sage.plot, sage.groups - sage: OTa.gray_table() # optional - sage.plot, sage.groups + sage: OTa = OperationTable(SymmetricGroup(3), operation=operator.mul) # needs sage.groups sage.plot + sage: OTa.gray_table() # needs sage.groups sage.plot Graphics object consisting of 37 graphics primitives .. PLOT:: @@ -1043,8 +1057,8 @@ def _ascii_table(self): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(5) - sage: T=OperationTable(R, operator.add) + sage: R = Integers(5) + sage: T = OperationTable(R, operator.add) sage: print(T._ascii_table()) + a b c d e +---------- @@ -1058,8 +1072,8 @@ def _ascii_table(self): strings used to represent elements. :: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(10) - sage: T=OperationTable(R, operator.mul, names='digits') + sage: R = Integers(10) + sage: T = OperationTable(R, operator.mul, names='digits') sage: print(T._ascii_table()) * 0 1 2 3 4 5 6 7 8 9 +-------------------- @@ -1077,8 +1091,8 @@ def _ascii_table(self): :: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(11) - sage: T=OperationTable(R, operator.mul, names='digits') + sage: R = Integers(11) + sage: T = OperationTable(R, operator.mul, names='digits') sage: print(T._ascii_table()) * 00 01 02 03 04 05 06 07 08 09 10 +--------------------------------- @@ -1097,8 +1111,8 @@ def _ascii_table(self): :: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(4) - sage: T=OperationTable(R, operator.mul, names=['x','y','wwww', 'z']) + sage: R = Integers(4) + sage: T = OperationTable(R, operator.mul, names=['x','y','wwww', 'z']) sage: print(T._ascii_table()) * x y wwww z +-------------------- @@ -1135,8 +1149,8 @@ def _latex_(self): EXAMPLES:: sage: from sage.matrix.operation_table import OperationTable - sage: R=Integers(2) - sage: T=OperationTable(R, operation=operator.mul) + sage: R = Integers(2) + sage: T = OperationTable(R, operation=operator.mul) sage: T._latex_() '{\\setlength{\\arraycolsep}{2ex}\n\\begin{array}{r|*{2}{r}}\n\\multicolumn{1}{c|}{\\ast}&a&b\\\\\\hline\n{}a&a&a\\\\\n{}b&a&b\\\\\n\\end{array}}' """ diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index b85a4d29777..41b64965ca3 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -7,7 +7,7 @@ For example, here is a circulant matrix of order five:: - sage: matrix.circulant(SR.var('a b c d e')) + sage: matrix.circulant(SR.var('a b c d e')) # needs sage.symbolic [a b c d e] [e a b c d] [d e a b c] @@ -266,7 +266,7 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation An upper bound on the absolute value of the entries may be set when the ``algorithm`` is ``echelonizable`` or ``unimodular``. In these cases it is possible for this constructor to fail with - a ``ValueError``. If you *must* have this routine return + a :class:`ValueError`. If you *must* have this routine return successfully, do not set ``upper_bound``. This behavior can be partially controlled by a ``max_tries`` keyword. @@ -356,6 +356,7 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation ....: A = random_matrix(*args, **kwds) ....: density_sum += float(A.density()) + sage: # needs sage.libs.flint (otherwise timeout) sage: density_sum = 0.0 sage: total_count = 0.0 sage: add_sample(ZZ, 5, x=-10, y=10, density=0.75) @@ -365,12 +366,14 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation sage: while abs(density_sum/total_count - expected_density) > 0.001: ....: add_sample(ZZ, 5, x=-10, y=10, density=0.75) + sage: # needs sage.libs.flint (otherwise timeout) sage: density_sum = 0.0 sage: total_count = 0.0 sage: add_sample(ZZ, 5, x=20, y=30, density=0.75) sage: while abs(density_sum/total_count - expected_density) > 0.001: ....: add_sample(ZZ, 5, x=20, y=30, density=0.75) + sage: # needs sage.libs.flint (otherwise timeout) sage: density_sum = 0.0 sage: total_count = 0.0 sage: add_sample(ZZ, 100, x=20, y=30, density=0.75) @@ -383,7 +386,7 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation For a matrix with low density it may be advisable to insist on a sparse representation, as this representation is not selected automatically. :: - sage: A=random_matrix(ZZ, 5, 5) + sage: A = random_matrix(ZZ, 5, 5) sage: A.is_sparse() False sage: A = random_matrix(ZZ, 5, 5, sparse=True) @@ -393,15 +396,16 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation For algorithm testing you might want to control the number of bits, say 10,000 entries, each limited to 16 bits. :: + sage: # needs sage.libs.flint (otherwise timeout) sage: A = random_matrix(ZZ, 100, 100, x=2^16); A 100 x 100 dense matrix over Integer Ring (use the '.str()' method to see the entries) One can prescribe a specific matrix implementation:: - sage: K. = FiniteField(2^8) - sage: type(random_matrix(K, 2, 5)) + sage: K. = FiniteField(2^8) # needs sage.rings.finite_rings + sage: type(random_matrix(K, 2, 5)) # needs sage.libs.m4ri sage.rings.finite_rings - sage: type(random_matrix(K, 2, 5, implementation="generic")) + sage: type(random_matrix(K, 2, 5, implementation="generic")) # needs sage.rings.finite_rings Random rational matrices. Now ``num_bound`` and ``den_bound`` control the @@ -421,7 +425,7 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation ....: for a in A.list()) True - sage: A = random_matrix(QQ, 4, density = 0.5, sparse=True) + sage: A = random_matrix(QQ, 4, density=0.5, sparse=True) sage: type(A) sage: A.density() <= 0.5 @@ -460,11 +464,11 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation randomisation when using the optional meataxe package, we have to make sure that we use the default implementation in this test:: - sage: K.=FiniteField(3^2) - sage: A = random_matrix(K, 2, 5, implementation='generic') + sage: K. = FiniteField(3^2) # needs sage.rings.finite_rings + sage: A = random_matrix(K, 2, 5, implementation='generic') # needs sage.rings.finite_rings sage: type(A) - sage: A.base_ring() is K + sage: A.base_ring() is K # needs sage.rings.finite_rings True sage: TestSuite(A).run() @@ -544,14 +548,15 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation When the eigenvalues and dimensions are not specified the result will have randomly generated values for both that fit with the designated size. :: - sage: A = random_matrix(QQ, 5, algorithm='diagonalizable', eigenvalues=[2,3,-1], dimensions=[1,2,2]); A # random - sage: all(x in ZZ for x in (A-(2*identity_matrix(5))).rref().list()) + sage: A = random_matrix(QQ, 5, algorithm='diagonalizable', # random + ....: eigenvalues=[2,3,-1], dimensions=[1,2,2]); A + sage: all(x in ZZ for x in (A - (2*identity_matrix(5))).rref().list()) True - sage: all(x in ZZ for x in (A-(3*identity_matrix(5))).rref().list()) + sage: all(x in ZZ for x in (A - 3*identity_matrix(5)).rref().list()) True - sage: all(x in ZZ for x in (A-(-1*identity_matrix(5))).rref().list()) + sage: all(x in ZZ for x in (A - (-1)*identity_matrix(5)).rref().list()) True - sage: A.jordan_form() + sage: A.jordan_form() # needs sage.combinat [ 2| 0| 0| 0| 0] [--+--+--+--+--] [ 0| 3| 0| 0| 0] @@ -575,14 +580,14 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation contain only integer entries. If ``rank``, is not set, the rank of the matrix will be generated randomly. :: - sage: B = random_matrix(QQ, 5, 6, algorithm='subspaces', rank=3); B #random - sage: B_expanded=B.augment(identity_matrix(5)).rref() + sage: B = random_matrix(QQ, 5, 6, algorithm='subspaces', rank=3); B # random + sage: B_expanded = B.augment(identity_matrix(5)).rref() sage: (B.nrows(), B.ncols()) (5, 6) sage: all(x in ZZ for x in B_expanded.list()) True - sage: C=B_expanded.submatrix(0,0,B.nrows()-B.nullity(),B.ncols()) - sage: L=B_expanded.submatrix(B.nrows()-B.nullity(),B.ncols()) + sage: C = B_expanded.submatrix(0, 0, B.nrows() - B.nullity(), B.ncols()) + sage: L = B_expanded.submatrix(B.nrows() - B.nullity(), B.ncols()) sage: B.right_kernel() == C.right_kernel() True sage: B.row_space() == C.row_space() @@ -604,7 +609,7 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation or ``QQ`` the result has integer entries, whose magnitudes can be limited by the value of ``upper_bound``. :: - sage: C=random_matrix(QQ, 5, algorithm='unimodular', upper_bound=70); C # random + sage: C = random_matrix(QQ, 5, algorithm='unimodular', upper_bound=70); C # random sage: det(C) 1 sage: C.base_ring() @@ -624,7 +629,7 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation We return an error for a bogus value of ``algorithm``:: - sage: random_matrix(ZZ, 5, algorithm = 'bogus') + sage: random_matrix(ZZ, 5, algorithm='bogus') Traceback (most recent call last): ... ValueError: random matrix algorithm "bogus" is not recognized @@ -748,6 +753,7 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): NumPy arrays may be used as input. :: + sage: # needs numpy sage: import numpy sage: entries = numpy.array([1.2, 5.6]); entries array([1.2, 5.6]) @@ -758,6 +764,7 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): sage: A.parent() Full MatrixSpace of 3 by 3 sparse matrices over Real Double Field + sage: # needs numpy sage: j = complex(0,1) sage: entries = numpy.array([2.0+j, 8.1, 3.4+2.6*j]); entries array([2. +1.j , 8.1+0.j , 3.4+2.6j]) @@ -768,6 +775,7 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): sage: A.parent() Full MatrixSpace of 3 by 3 sparse matrices over Complex Double Field + sage: # needs numpy sage: entries = numpy.array([4, 5, 6]) sage: A = diagonal_matrix(entries); A [4 0 0] @@ -776,8 +784,8 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): sage: A.parent() Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring - sage: entries = numpy.array([4.1, 5.2, 6.3]) - sage: A = diagonal_matrix(ZZ, entries); A + sage: entries = numpy.array([4.1, 5.2, 6.3]) # needs numpy + sage: A = diagonal_matrix(ZZ, entries); A # needs numpy Traceback (most recent call last): ... TypeError: unable to convert 4.1 to an element of Integer Ring @@ -819,7 +827,7 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): Types for the entries need to be iterable (tuple, list, vector, NumPy array, etc):: - sage: diagonal_matrix(x^2) + sage: diagonal_matrix(x^2) # needs sage.symbolic Traceback (most recent call last): ... TypeError: 'sage.symbolic.expression.Expression' object is not iterable @@ -852,8 +860,14 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): entries = arg0 # sanity check for entries - from numpy import ndarray - if not isinstance(entries, (list, tuple, ndarray)): + types = (list, tuple) + try: + from numpy import ndarray + except ImportError: + pass + else: + types += (ndarray,) + if not isinstance(entries, types): entries = list(entries) # Reconcile matrix size and number of entries @@ -1275,14 +1289,18 @@ def elementary_matrix(arg0, arg1=None, **kwds): sage: E.parent() Full MatrixSpace of 4 by 4 dense matrices over Rational Field + sage: # needs sage.symbolic sage: E = elementary_matrix(4, row1=1, scale=I) sage: E.parent() - Full MatrixSpace of 4 by 4 dense matrices over Number Field in I with defining polynomial x^2 + 1 with I = 1*I + Full MatrixSpace of 4 by 4 dense matrices over + Number Field in I with defining polynomial x^2 + 1 with I = 1*I + sage: # needs sage.rings.complex_double sage.symbolic sage: E = elementary_matrix(4, row1=1, scale=CDF(I)) sage: E.parent() Full MatrixSpace of 4 by 4 dense matrices over Complex Double Field + sage: # needs sage.rings.number_field sage.symbolic sage: E = elementary_matrix(4, row1=1, scale=QQbar(I)) sage: E.parent() Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field @@ -1500,7 +1518,7 @@ def circulant(v, sparse=None): EXAMPLES:: - sage: v=[1,2,3,4,8] + sage: v = [1,2,3,4,8] sage: matrix.circulant(v) [1 2 3 4 8] [8 1 2 3 4] @@ -1546,7 +1564,7 @@ def _determine_block_matrix_grid(sub_matrices): Non-zero scalars are considered to be square matrices of any size, and zeroes are considered to be zero matrices of any size. - A ValueError is raised if there is insufficient or + A :class:`ValueError` is raised if there is insufficient or conflicting information. TESTS:: @@ -2267,14 +2285,16 @@ def companion_matrix(poly, format='right'): [ 1 0 -8] [ 0 1 4] + sage: # needs sage.symbolic sage: y = var('y') - sage: q = y^3 -2*y + 1 + sage: q = y^3 - 2*y + 1 sage: companion_matrix(q) Traceback (most recent call last): ... - TypeError: input must be a polynomial (not a symbolic expression, see docstring), or other iterable, not y^3 - 2*y + 1 - - sage: coeff_list = [q(y=0)] + [q.coefficient(y^k) for k in range(1, q.degree(y)+1)] + TypeError: input must be a polynomial (not a symbolic expression, see docstring), + or other iterable, not y^3 - 2*y + 1 + sage: coeff_list = [q(y=0)] + [q.coefficient(y^k) + ....: for k in range(1, q.degree(y) + 1)] sage: coeff_list [1, -2, 0, 1] sage: companion_matrix(coeff_list) @@ -2290,9 +2310,9 @@ def companion_matrix(poly, format='right'): sage: t = polygen(QQ, 't') sage: p = t^12 - 7*t^4 + 28*t^2 - 456 sage: C = companion_matrix(p, format='top') - sage: q = C.minpoly(var='t'); q + sage: q = C.minpoly(var='t'); q # needs sage.libs.pari t^12 - 7*t^4 + 28*t^2 - 456 - sage: p == q + sage: p == q # needs sage.libs.pari True sage: p = t^3 + 3*t - 8 @@ -2301,9 +2321,9 @@ def companion_matrix(poly, format='right'): ....: companion_matrix(p^2), ....: companion_matrix(q), ....: companion_matrix(q) ) - sage: A.charpoly(var='t').factor() + sage: A.charpoly(var='t').factor() # needs sage.libs.pari (t^3 + 3*t - 8)^3 * (t^5 + t - 17)^2 - sage: A.minpoly(var='t').factor() + sage: A.minpoly(var='t').factor() # needs sage.libs.pari (t^3 + 3*t - 8)^2 * (t^5 + t - 17) TESTS:: @@ -2313,18 +2333,20 @@ def companion_matrix(poly, format='right'): ... ValueError: format must be 'right', 'left', 'top' or 'bottom', not junk - sage: companion_matrix(sin(x)) + sage: companion_matrix(sin(x)) # needs sage.symbolic Traceback (most recent call last): ... - TypeError: input must be a polynomial (not a symbolic expression, see docstring), or other iterable, not sin(x) + TypeError: input must be a polynomial (not a symbolic expression, see docstring), + or other iterable, not sin(x) sage: companion_matrix([2, 3, 896]) Traceback (most recent call last): ... - ValueError: polynomial (or the polynomial implied by coefficients) must be monic, not a leading coefficient of 896 + ValueError: polynomial (or the polynomial implied by coefficients) must be monic, + not a leading coefficient of 896 - sage: F. = GF(2^2) - sage: companion_matrix([4/3, a+1, 1]) + sage: F. = GF(2^2) # needs sage.rings.finite_rings + sage: companion_matrix([4/3, a+1, 1]) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: unable to find common ring for coefficients from polynomial @@ -2417,7 +2439,7 @@ def random_rref_matrix(parent, num_pivots): sage: from sage.matrix.constructor import random_rref_matrix sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5, 6) - sage: A = random_rref_matrix(matrix_space, num_pivots=4); A # random + sage: A = random_rref_matrix(matrix_space, num_pivots=4); A # random [ 1 0 0 -6 0 -3] [ 0 1 0 2 0 3] [ 0 0 1 -4 0 -2] @@ -2436,10 +2458,11 @@ def random_rref_matrix(parent, num_pivots): Matrices can be generated over other exact rings. :: - sage: B = random_matrix(FiniteField(7), 4, 4, algorithm='echelon_form', num_pivots=3); B # random + sage: B = random_matrix(FiniteField(7), 4, 4, # random + ....: algorithm='echelon_form', num_pivots=3); B [1 0 0 0] [0 1 0 6] - [0 0 1 4] + [0 0 1 1] [0 0 0 0] sage: B.rank() == 3 True @@ -2602,14 +2625,14 @@ def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100): sage: A = random_echelonizable_matrix(matrix_space, rank=4, upper_bound=40) sage: A.rank() 4 - sage: max(map(abs,A.list()))<40 + sage: max(map(abs,A.list())) < 40 True sage: A.rref() == A.rref().change_ring(ZZ) True An example with default settings (i.e. no entry size control). :: - sage: C=random_matrix(QQ, 6, 7, algorithm='echelonizable', rank=5) + sage: C = random_matrix(QQ, 6, 7, algorithm='echelonizable', rank=5) sage: C.rank() 5 sage: C.rref() == C.rref().change_ring(ZZ) @@ -2617,7 +2640,7 @@ def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100): A matrix without size control may have very large entry sizes. :: - sage: D=random_matrix(ZZ, 7, 8, algorithm='echelonizable', rank=6); D # random + sage: D = random_matrix(ZZ, 7, 8, algorithm='echelonizable', rank=6); D # random [ 1 2 8 -35 -178 -239 -284 778] [ 4 9 37 -163 -827 -1111 -1324 3624] [ 5 6 21 -88 -454 -607 -708 1951] @@ -2628,8 +2651,10 @@ def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100): Matrices can be generated over any exact ring. :: - sage: F.=GF(2^3) - sage: B = random_matrix(F, 4, 5, algorithm='echelonizable', rank=4, upper_bound=None) + sage: # needs sage.rings.finite_rings + sage: F. = GF(2^3) + sage: B = random_matrix(F, 4, 5, algorithm='echelonizable', rank=4, + ....: upper_bound=None) sage: B.rank() 4 sage: B.base_ring() is F @@ -2671,7 +2696,7 @@ def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100): Works for rank==1, too. :: - sage: random_matrix( QQ, 3, 3, algorithm='echelonizable', rank=1).ncols() + sage: random_matrix(QQ, 3, 3, algorithm='echelonizable', rank=1).ncols() 3 @@ -2841,11 +2866,11 @@ def random_subspaces_matrix(parent, rank=None): (5, 7) sage: all(x in ZZ for x in A.list()) True - sage: A_expanded=A.augment(identity_matrix(5)).rref() + sage: A_expanded = A.augment(identity_matrix(5)).rref() sage: all(x in ZZ for x in A_expanded.list()) True - sage: C = A_expanded.submatrix(0,0,A.nrows()-A.nullity(), A.ncols()) - sage: L = A_expanded.submatrix(A.nrows()-A.nullity(), A.ncols()) + sage: C = A_expanded.submatrix(0, 0, A.nrows() - A.nullity(), A.ncols()) + sage: L = A_expanded.submatrix(A.nrows() - A.nullity(), A.ncols()) sage: A.right_kernel() == C.right_kernel() True sage: A.row_space() == C.row_space() @@ -2972,6 +2997,7 @@ def random_unimodular_matrix(parent, upper_bound=None, max_tries=100): A matrix over the number Field in `y` with defining polynomial `y^2-2y-2`. :: + sage: # needs sage.rings.number_field sage: y = polygen(ZZ, 'y') sage: K = NumberField(y^2 - 2*y - 2, 'y') sage: C = random_matrix(K, 3, algorithm='unimodular') @@ -2991,8 +3017,8 @@ def random_unimodular_matrix(parent, upper_bound=None, max_tries=100): Only matrices over ZZ and QQ can have size control. :: - sage: F.=GF(5^7) - sage: random_matrix(F, 5, algorithm='unimodular', upper_bound=20) + sage: F. = GF(5^7) # needs sage.rings.finite_rings + sage: random_matrix(F, 5, algorithm='unimodular', upper_bound=20) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: only matrices over ZZ or QQ can have size control. @@ -3028,11 +3054,11 @@ def random_diagonalizable_matrix(parent,eigenvalues=None,dimensions=None): If eigenvalues and dimensions are not specified in a list, they will be assigned randomly. - - ``parent`` - the desired size of the square matrix. + - ``parent`` -- the desired size of the square matrix. - - ``eigenvalues`` - the list of desired eigenvalues (default=None). + - ``eigenvalues`` -- the list of desired eigenvalues (default=None). - - ``dimensions`` - the list of dimensions corresponding to each + - ``dimensions`` -- the list of dimensions corresponding to each eigenspace (default=None). OUTPUT: @@ -3056,6 +3082,8 @@ def random_diagonalizable_matrix(parent,eigenvalues=None,dimensions=None): sage: from sage.matrix.constructor import random_diagonalizable_matrix sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5) sage: A = random_diagonalizable_matrix(matrix_space) + + sage: # needs sage.rings.number_field sage: eigenvalues = A.eigenvalues() sage: S = A.right_eigenmatrix()[1] sage: eigenvalues2 = (S.inverse()*A*S).diagonal() @@ -3067,13 +3095,16 @@ def random_diagonalizable_matrix(parent,eigenvalues=None,dimensions=None): entries would all be integers. :: sage: eigenvalues = [ZZ.random_element() for _ in range(3)] - sage: B = random_matrix(QQ, 6, algorithm='diagonalizable', eigenvalues=eigenvalues, dimensions=[2,3,1]) + sage: B = random_matrix(QQ, 6, algorithm='diagonalizable', + ....: eigenvalues=eigenvalues, dimensions=[2,3,1]) sage: all(x in ZZ for x in (B-(-12*identity_matrix(6))).rref().list()) True sage: all(x in ZZ for x in (B-(4*identity_matrix(6))).rref().list()) True sage: all(x in ZZ for x in (B-(6*identity_matrix(6))).rref().list()) True + + sage: # needs sage.rings.number_field sage: S = B.right_eigenmatrix()[1] sage: eigenvalues2 = (S.inverse()*B*S).diagonal() sage: all(e in eigenvalues for e in eigenvalues2) @@ -3083,7 +3114,8 @@ def random_diagonalizable_matrix(parent,eigenvalues=None,dimensions=None): Eigenvalues must all be integers. :: - sage: random_matrix(QQ,3,algorithm='diagonalizable', eigenvalues=[2+I,2-I,2],dimensions=[1,1,1]) + sage: random_matrix(QQ, 3, algorithm='diagonalizable', # needs sage.symbolic + ....: eigenvalues=[2+I, 2-I, 2], dimensions=[1,1,1]) Traceback (most recent call last): ... TypeError: eigenvalues must be integers. @@ -3259,15 +3291,16 @@ def vector_on_axis_rotation_matrix(v, i, ring=None): sage: from sage.matrix.constructor import vector_on_axis_rotation_matrix sage: v = vector((1,2,3)) - sage: vector_on_axis_rotation_matrix(v, 2) * v + sage: vector_on_axis_rotation_matrix(v, 2) * v # needs sage.symbolic (0, 0, sqrt(14)) - sage: vector_on_axis_rotation_matrix(v, 1) * v + sage: vector_on_axis_rotation_matrix(v, 1) * v # needs sage.symbolic (0, sqrt(14), 0) - sage: vector_on_axis_rotation_matrix(v, 0) * v + sage: vector_on_axis_rotation_matrix(v, 0) * v # needs sage.symbolic (sqrt(14), 0, 0) :: + sage: # needs sage.symbolic sage: x,y = var('x,y') sage: v = vector((x,y)) sage: vector_on_axis_rotation_matrix(v, 1) @@ -3284,7 +3317,7 @@ def vector_on_axis_rotation_matrix(v, i, ring=None): :: sage: v = vector((1,2,3,4)) - sage: vector_on_axis_rotation_matrix(v, 0) * v + sage: vector_on_axis_rotation_matrix(v, 0) * v # needs sage.symbolic (sqrt(30), 0, 0, 0) sage: vector_on_axis_rotation_matrix(v, 0, ring=RealField(10)) [ 0.18 0.37 0.55 0.73] @@ -3329,35 +3362,35 @@ def ith_to_zero_rotation_matrix(v, i, ring=None): sage: from sage.matrix.constructor import ith_to_zero_rotation_matrix sage: v = vector((1,2,3)) - sage: ith_to_zero_rotation_matrix(v, 2) + sage: ith_to_zero_rotation_matrix(v, 2) # needs sage.symbolic [ 1 0 0] [ 0 2/13*sqrt(13) 3/13*sqrt(13)] [ 0 -3/13*sqrt(13) 2/13*sqrt(13)] - sage: ith_to_zero_rotation_matrix(v, 2) * v + sage: ith_to_zero_rotation_matrix(v, 2) * v # needs sage.symbolic (1, sqrt(13), 0) :: - sage: ith_to_zero_rotation_matrix(v, 0) + sage: ith_to_zero_rotation_matrix(v, 0) # needs sage.symbolic [ 3/10*sqrt(10) 0 -1/10*sqrt(10)] [ 0 1 0] [ 1/10*sqrt(10) 0 3/10*sqrt(10)] - sage: ith_to_zero_rotation_matrix(v, 1) + sage: ith_to_zero_rotation_matrix(v, 1) # needs sage.symbolic [ 1/5*sqrt(5) 2/5*sqrt(5) 0] [-2/5*sqrt(5) 1/5*sqrt(5) 0] [ 0 0 1] - sage: ith_to_zero_rotation_matrix(v, 2) + sage: ith_to_zero_rotation_matrix(v, 2) # needs sage.symbolic [ 1 0 0] [ 0 2/13*sqrt(13) 3/13*sqrt(13)] [ 0 -3/13*sqrt(13) 2/13*sqrt(13)] :: - sage: ith_to_zero_rotation_matrix(v, 0) * v + sage: ith_to_zero_rotation_matrix(v, 0) * v # needs sage.symbolic (0, 2, sqrt(10)) - sage: ith_to_zero_rotation_matrix(v, 1) * v + sage: ith_to_zero_rotation_matrix(v, 1) * v # needs sage.symbolic (sqrt(5), 0, 3) - sage: ith_to_zero_rotation_matrix(v, 2) * v + sage: ith_to_zero_rotation_matrix(v, 2) * v # needs sage.symbolic (1, sqrt(13), 0) Other ring:: @@ -3373,6 +3406,7 @@ def ith_to_zero_rotation_matrix(v, i, ring=None): On the symbolic ring:: + sage: # needs sage.symbolic sage: x,y,z = var('x,y,z') sage: v = vector((x,y,z)) sage: ith_to_zero_rotation_matrix(v, 2) @@ -3478,7 +3512,7 @@ def vandermonde(v, ring=None): A Vandermonde matrix of order three over the symbolic ring:: - sage: matrix.vandermonde(SR.var(['x0', 'x1', 'x2'])) + sage: matrix.vandermonde(SR.var(['x0', 'x1', 'x2'])) # needs sage.symbolic [ 1 x0 x0^2] [ 1 x1 x1^2] [ 1 x2 x2^2] @@ -3565,7 +3599,7 @@ def hankel(c, r=None, ring=None): A Hankel matrix with symbolic entries:: - sage: matrix.hankel(SR.var('a, b, c, d, e')) + sage: matrix.hankel(SR.var('a, b, c, d, e')) # needs sage.symbolic [a b c d e] [b c d e 0] [c d e 0 0] @@ -3574,7 +3608,7 @@ def hankel(c, r=None, ring=None): We can also pass the elements of the last row, starting at the second column:: - sage: matrix.hankel(SR.var('a, b, c, d, e'), SR.var('f, g, h, i')) + sage: matrix.hankel(SR.var('a, b, c, d, e'), SR.var('f, g, h, i')) # needs sage.symbolic [a b c d e] [b c d e f] [c d e f g] diff --git a/src/sage/matrix/strassen.pyx b/src/sage/matrix/strassen.pyx index ab392d66cb1..13a8c152fd9 100644 --- a/src/sage/matrix/strassen.pyx +++ b/src/sage/matrix/strassen.pyx @@ -48,6 +48,7 @@ def strassen_window_multiply(C, A,B, cutoff): """ strassen_window_multiply_c(C, A, B, cutoff) + cdef strassen_window_multiply_c(MatrixWindow C, MatrixWindow A, MatrixWindow B, Py_ssize_t cutoff): # todo -- I'm not sure how to interpret "cutoff". Should it be... @@ -97,7 +98,6 @@ cdef strassen_window_multiply_c(MatrixWindow C, MatrixWindow A, cdef MatrixWindow S0, S1, S2, S3, T0, T1 ,T2, T3, P0, P1, P2, P3, P4, P5, P6, U0, U1, U2, U3, U4, U5, U6 cdef MatrixWindow X, Y - cdef Py_ssize_t tmp_cols, start_row X = A.new_empty_window(A_sub_nrows, max(A_sub_ncols,B_sub_ncols)) Y = B.new_empty_window(A_sub_ncols, B_sub_ncols) @@ -253,13 +253,11 @@ def strassen_echelon(MatrixWindow A, cutoff): INPUT: - - ``A`` - matrix window - ``cutoff`` - size at which algorithm reverts to naive Gaussian elimination and multiplication must be at least 1. - OUTPUT: The list of pivot columns EXAMPLES:: @@ -312,6 +310,7 @@ def strassen_echelon(MatrixWindow A, cutoff): strassen_echelon_c(A, cutoff, A._matrix._strassen_default_cutoff(A._matrix)) sig_off() + cdef strassen_echelon_c(MatrixWindow A, Py_ssize_t cutoff, Py_ssize_t mul_cutoff): # The following notation will be used in the comments below, which should be understood to give # the general idea of what's going on, as if there were no inconvenient non-pivot columns. diff --git a/src/sage/matrix/symplectic_basis.py b/src/sage/matrix/symplectic_basis.py index 4caee7a6da6..66dc1883a12 100644 --- a/src/sage/matrix/symplectic_basis.py +++ b/src/sage/matrix/symplectic_basis.py @@ -188,7 +188,12 @@ def symplectic_basis_over_field(M): An example over a finite field:: - sage: E = matrix(GF(7), 8, 8, [0, -1/2, -2, 1/2, 2, 0, -2, 1, 1/2, 0, -1, -3, 0, 2, 5/2, -3, 2, 1, 0, 3/2, -1, 0, -1, -2, -1/2, 3, -3/2, 0, 1, 3/2, -1/2, -1/2, -2, 0, 1, -1, 0, 0, 1, -1, 0, -2, 0, -3/2, 0, 0, 1/2, -2, 2, -5/2, 1, 1/2, -1, -1/2, 0, -1, -1, 3, 2, 1/2, 1, 2, 1, 0]); E + sage: E = matrix(GF(7), 8, 8, + ....: [0, -1/2, -2, 1/2, 2, 0, -2, 1, 1/2, 0, -1, -3, 0, 2, 5/2, + ....: -3, 2, 1, 0, 3/2, -1, 0, -1, -2, -1/2, 3, -3/2, 0, 1, 3/2, + ....: -1/2, -1/2, -2, 0, 1, -1, 0, 0, 1, -1, 0, -2, 0, -3/2, 0, + ....: 0, 1/2, -2, 2, -5/2, 1, 1/2, -1, -1/2, 0, -1, -1, 3, 2, + ....: 1/2, 1, 2, 1, 0]); E [0 3 5 4 2 0 5 1] [4 0 6 4 0 2 6 4] [2 1 0 5 6 0 6 5] @@ -211,7 +216,11 @@ def symplectic_basis_over_field(M): The tricky case of characteristic 2:: - sage: E = matrix(GF(2), 8, 8, [0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]); E + sage: E = matrix(GF(2), 8, 8, + ....: [0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + ....: 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, + ....: 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, + ....: 0, 1, 0, 0]); E [0 0 1 1 0 1 0 1] [0 0 0 0 0 0 0 0] [1 0 0 0 0 0 1 1] diff --git a/src/sage/matrix/tests.py b/src/sage/matrix/tests.py index 21b7920307a..9208a5d4d72 100644 --- a/src/sage/matrix/tests.py +++ b/src/sage/matrix/tests.py @@ -11,7 +11,7 @@ Vector space of degree 1 and dimension 1 over Rational Field Basis matrix: [1] - sage: matrix(GF(7),1,0).kernel() + sage: matrix(GF(7), 1, 0).kernel() Vector space of degree 1 and dimension 1 over Finite Field of size 7 Basis matrix: [1] @@ -28,7 +28,7 @@ Vector space of degree 0 and dimension 0 over Rational Field Basis matrix: [] - sage: matrix(GF(7),0,1).kernel() + sage: matrix(GF(7), 0, 1).kernel() Vector space of degree 0 and dimension 0 over Finite Field of size 7 Basis matrix: [] @@ -45,7 +45,7 @@ sage: matrix(QQ, 2, 2, [1, 1, 1, 1]) / (1/2) [2 2] [2 2] - sage: matrix(QQ['x,y'], 2, 2, [1, 1, 1, 1]) / x + sage: matrix(QQ['x,y'], 2, 2, [1, 1, 1, 1]) / x # needs sage.symbolic [1/x 1/x] [1/x 1/x] sage: A = matrix(CC, 2, 2, [1, 1, 1, 1]) / I; A diff --git a/src/sage/matroids/basis_exchange_matroid.pxd b/src/sage/matroids/basis_exchange_matroid.pxd index aec3bb54c42..28cc7ad868c 100644 --- a/src/sage/matroids/basis_exchange_matroid.pxd +++ b/src/sage/matroids/basis_exchange_matroid.pxd @@ -15,13 +15,13 @@ 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, l) - cdef __pack(self, bitset_t, X) + cdef _pack(self, bitset_t, X) cdef __unpack(self, bitset_t) - cdef bint __is_exchange_pair(self, long x, long y) except -1 - cdef int __exchange(self, long x, long y) except -1 - cdef int __move(self, bitset_t X, bitset_t Y) except -1 + cdef bint _is_exchange_pair(self, long x, long y) except -1 + cdef int _exchange(self, long x, long y) except -1 + cdef int _move(self, bitset_t X, bitset_t Y) except -1 cdef __fundamental_cocircuit(self, bitset_t, long x) cdef __fundamental_circuit(self, bitset_t, long y) @@ -30,7 +30,7 @@ cdef class BasisExchangeMatroid(Matroid): cdef __closure(self, bitset_t, bitset_t) cdef __max_coindependent(self, bitset_t, bitset_t) cdef __cocircuit(self, bitset_t, bitset_t) - cdef __coclosure(self, bitset_t, bitset_t) + cdef _coclosure_internal(self, bitset_t, bitset_t) cdef __augment(self, bitset_t, bitset_t, bitset_t) cdef bint __is_independent(self, bitset_t F) except -1 diff --git a/src/sage/matroids/basis_exchange_matroid.pyx b/src/sage/matroids/basis_exchange_matroid.pyx index 90d10842d46..015fa8b8df3 100644 --- a/src/sage/matroids/basis_exchange_matroid.pyx +++ b/src/sage/matroids/basis_exchange_matroid.pyx @@ -57,10 +57,10 @@ cdef class BasisExchangeMatroid(Matroid): This base exchange graph is not stored as such, but should be provided implicitly by the child class in the form of two methods - ``__is_exchange_pair(x, y)`` and ``__exchange(x, y)``, as well as an + ``_is_exchange_pair(x, y)`` and ``_exchange(x, y)``, as well as an initial basis. At any moment, BasisExchangeMatroid keeps a current basis - `B`. The method ``__is_exchange_pair(x, y)`` should return a boolean - indicating whether `B - x + y` is a basis. The method ``__exchange(x, y)`` + `B`. The method ``_is_exchange_pair(x, y)`` should return a boolean + indicating whether `B - x + y` is a basis. The method ``_exchange(x, y)`` is called when the current basis `B` is replaced by said `B-x + y`. It is up to the child class to update its internal data structure to make information relative to the new basis more accessible. For instance, a @@ -81,16 +81,16 @@ cdef class BasisExchangeMatroid(Matroid): - :class:`BasisMatroid `: keeps a list of all bases. - - ``__is_exchange_pair(x, y)`` reduces to a query whether `B - x + y` + - ``_is_exchange_pair(x, y)`` reduces to a query whether `B - x + y` is a basis. - - ``__exchange(x, y)`` has no work to do. + - ``_exchange(x, y)`` has no work to do. - :class:`LinearMatroid `: keeps a matrix representation `A` of the matroid so that `A[B] = I`. - - ``__is_exchange_pair(x, y)`` reduces to testing whether `A[r, y]` + - ``_is_exchange_pair(x, y)`` reduces to testing whether `A[r, y]` is nonzero, where `A[r, x]=1`. - - ``__exchange(x, y)`` should modify the matrix so that `A[B - x + y]` + - ``_exchange(x, y)`` should modify the matrix so that `A[B - x + y]` becomes `I`, which means pivoting on `A[r, y]`. - ``TransversalMatroid`` (not yet implemented): If `A` is a set of subsets @@ -100,17 +100,17 @@ cdef class BasisExchangeMatroid(Matroid): edge `(A_i,e)` if `e` is in the subset `A_i`. At any time you keep a maximum matching `M` of `G` covering the current basis `B`. - - ``__is_exchange_pair(x, y)`` checks for the existence of an + - ``_is_exchange_pair(x, y)`` checks for the existence of an `M`-alternating path `P` from `y` to `x`. - - ``__exchange(x, y)`` replaces `M` by the symmetric difference of + - ``_exchange(x, y)`` replaces `M` by the symmetric difference of `M` and `E(P)`. - ``AlgebraicMatroid`` (not yet implemented): keeps a list of polynomials in variables `E - B + e` for each variable `e` in `B`. - - ``__is_exchange_pair(x, y)`` checks whether the polynomial that + - ``_is_exchange_pair(x, y)`` checks whether the polynomial that relates `y` to `E-B` uses `x`. - - ``__exchange(x, y)`` make new list of polynomials by computing + - ``_exchange(x, y)`` make new list of polynomials by computing resultants. All but the first of the above matroids are algebraic, and all @@ -139,7 +139,7 @@ cdef class BasisExchangeMatroid(Matroid): This initializer sets up a correspondence between elements of ``groundset`` and ``range(len(groundset))``. ``BasisExchangeMatroid`` uses this correspondence for encoding of subsets of the groundset as - bitpacked sets of integers --- see ``__pack()`` and ``__unpack()``. In + bitpacked sets of integers --- see ``_pack()`` and ``__unpack()``. In general, methods of ``BasisExchangeMatroid`` having a name starting with two underscores deal with such encoded subsets. @@ -180,7 +180,7 @@ cdef class BasisExchangeMatroid(Matroid): self._idx[self._E[i]] = i if basis is not None: - self.__pack(self._current_basis, frozenset(basis)) + self._pack(self._current_basis, frozenset(basis)) def __dealloc__(self): bitset_free(self._current_basis) @@ -191,7 +191,7 @@ cdef class BasisExchangeMatroid(Matroid): bitset_free(self._output) bitset_free(self._temp) - cdef __relabel(self, l): + cdef _relabel(self, l): """ Relabel each element `e` as `l[e]`, where `l` is a given injective map. @@ -231,7 +231,7 @@ cdef class BasisExchangeMatroid(Matroid): self._heuristic_partition_var._relabel(l) # the engine - cdef __pack(self, bitset_t I, F): + cdef _pack(self, bitset_t I, F): """ Encode a subset F of the groundset into a bitpacked set of integers """ @@ -252,21 +252,21 @@ cdef class BasisExchangeMatroid(Matroid): return frozenset(F) # this method needs to be overridden by child class - cdef bint __is_exchange_pair(self, long x, long y) except -1: + cdef bint _is_exchange_pair(self, long x, long y) except -1: """ Test if current_basis-x + y is a basis """ raise NotImplementedError # if this method is overridden by a child class, the child class needs to call this method - cdef int __exchange(self, long x, long y) except -1: + cdef int _exchange(self, long x, long y) except -1: """ put current_basis <-- current_basis-x + y """ bitset_discard(self._current_basis, x) bitset_add(self._current_basis, y) - cdef int __move(self, bitset_t X, bitset_t Y) except -1: + cdef int _move(self, bitset_t X, bitset_t Y) except -1: """ Change current_basis to minimize intersection with ``X``, maximize intersection with ``Y``. """ @@ -275,8 +275,8 @@ cdef class BasisExchangeMatroid(Matroid): while x >= 0: y = bitset_first(Y) while y >= 0: - if self.__is_exchange_pair(x, y): - self.__exchange(x, y) + if self._is_exchange_pair(x, y): + self._exchange(x, y) bitset_discard(Y, y) bitset_discard(X, x) if bitset_isempty(Y): @@ -295,7 +295,7 @@ cdef class BasisExchangeMatroid(Matroid): bitset_complement(self._temp, self._current_basis) y = bitset_first(self._temp) while y >= 0: - if self.__is_exchange_pair(x, y): + if self._is_exchange_pair(x, y): bitset_add(C, y) y = bitset_next(self._temp, y + 1) bitset_add(C, x) @@ -308,7 +308,7 @@ cdef class BasisExchangeMatroid(Matroid): bitset_clear(C) x = bitset_first(self._current_basis) while x >= 0: - if self.__is_exchange_pair(x, y): + if self._is_exchange_pair(x, y): bitset_add(C, x) x = bitset_next(self._current_basis, x + 1) bitset_add(C, y) @@ -319,7 +319,7 @@ cdef class BasisExchangeMatroid(Matroid): """ bitset_difference(self._inside, self._current_basis, F) bitset_difference(self._outside, F, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_intersection(R, self._current_basis, F) cdef __circuit(self, bitset_t R, bitset_t F): @@ -335,8 +335,8 @@ cdef class BasisExchangeMatroid(Matroid): while y >= 0: x = bitset_first(self._inside) while x >= 0: - if self.__is_exchange_pair(x, y): - self.__exchange(x, y) + if self._is_exchange_pair(x, y): + self._exchange(x, y) bitset_discard(self._outside, y) bitset_discard(self._inside, x) if bitset_isempty(self._outside): @@ -355,7 +355,7 @@ cdef class BasisExchangeMatroid(Matroid): """ bitset_difference(self._inside, self._current_basis, F) bitset_difference(self._outside, F, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_set_first_n(R, self._groundset_size) cdef long x = bitset_first(self._inside) while x >= 0: @@ -370,7 +370,7 @@ cdef class BasisExchangeMatroid(Matroid): bitset_complement(R, F) bitset_difference(self._inside, self._current_basis, R) bitset_difference(self._outside, R, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_difference(R, F, self._current_basis) cdef __cocircuit(self, bitset_t R, bitset_t F): @@ -387,8 +387,8 @@ cdef class BasisExchangeMatroid(Matroid): while x >= 0: y = bitset_first(self._outside) while y >= 0: - if self.__is_exchange_pair(x, y): - self.__exchange(x, y) + if self._is_exchange_pair(x, y): + self._exchange(x, y) bitset_discard(self._outside, y) bitset_discard(self._inside, x) if bitset_isempty(self._inside): @@ -401,14 +401,14 @@ cdef class BasisExchangeMatroid(Matroid): return x = bitset_next(self._inside, x + 1) - cdef __coclosure(self, bitset_t R, bitset_t F): + cdef _coclosure_internal(self, bitset_t R, bitset_t F): """ Bitpacked version of ``closure``. """ bitset_complement(R, F) bitset_difference(self._inside, self._current_basis, R) bitset_difference(self._outside, R, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_set_first_n(R, self._groundset_size) cdef long y = bitset_first(self._outside) while y >= 0: @@ -422,10 +422,10 @@ cdef class BasisExchangeMatroid(Matroid): """ bitset_difference(self._inside, self._current_basis, X) bitset_difference(self._outside, X, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_difference(self._inside, self._inside, Y) bitset_difference(self._outside, Y, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_intersection(R, self._current_basis, Y) cdef bint __is_independent(self, bitset_t F) except -1: @@ -434,7 +434,7 @@ cdef class BasisExchangeMatroid(Matroid): """ bitset_difference(self._inside, self._current_basis, F) bitset_difference(self._outside, F, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) return bitset_isempty(self._outside) cdef __move_current_basis(self, bitset_t X, bitset_t Y): @@ -443,21 +443,21 @@ cdef class BasisExchangeMatroid(Matroid): """ bitset_difference(self._inside, self._current_basis, X) bitset_difference(self._outside, X, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_intersection(self._inside, self._current_basis, Y) bitset_complement(self._outside, self._current_basis) bitset_difference(self._outside, self._outside, Y) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) # functions for derived classes and for parent class cdef bint _set_current_basis(self, F): """ Set _current_basis to subset of the groundset ``F``. """ - self.__pack(self._input, F) + self._pack(self._input, F) bitset_difference(self._inside, self._current_basis, self._input) bitset_difference(self._outside, self._input, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) return bitset_isempty(self._outside) and bitset_isempty(self._inside) # groundset and full_rank @@ -630,8 +630,8 @@ cdef class BasisExchangeMatroid(Matroid): ['b', 'c', 'e', 'f'] """ - self.__pack(self._input, X) - self.__pack(self._input2, Y) + self._pack(self._input, X) + self._pack(self._input2, Y) self.__move_current_basis(self._input, self._input2) cpdef _max_independent(self, F): @@ -661,7 +661,7 @@ cdef class BasisExchangeMatroid(Matroid): see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__max_independent(self._output, self._input) return self.__unpack(self._output) @@ -692,7 +692,7 @@ cdef class BasisExchangeMatroid(Matroid): see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__max_independent(self._output, self._input) return bitset_len(self._output) @@ -729,7 +729,7 @@ cdef class BasisExchangeMatroid(Matroid): the input is indeed a subset of the ground set, see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__circuit(self._output, self._input) return self.__unpack(self._output) @@ -754,7 +754,7 @@ cdef class BasisExchangeMatroid(Matroid): sage: sorted(M._fundamental_circuit('abcd', 'e')) ['a', 'b', 'c', 'e'] """ - self.__pack(self._input, B) + self._pack(self._input, B) bitset_clear(self._input2) self.__move_current_basis(self._input, self._input2) self.__fundamental_circuit(self._output, self._idx[e]) @@ -787,7 +787,7 @@ cdef class BasisExchangeMatroid(Matroid): :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__closure(self._output, self._input) return self.__unpack(self._output) @@ -818,7 +818,7 @@ cdef class BasisExchangeMatroid(Matroid): see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__max_coindependent(self._output, self._input) return self.__unpack(self._output) @@ -848,7 +848,7 @@ cdef class BasisExchangeMatroid(Matroid): input is indeed a subset of the ground set, see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__max_coindependent(self._output, self._input) return bitset_len(self._output) @@ -885,7 +885,7 @@ cdef class BasisExchangeMatroid(Matroid): input is indeed a subset of the ground set, see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) self.__cocircuit(self._output, self._input) return self.__unpack(self._output) @@ -910,7 +910,7 @@ cdef class BasisExchangeMatroid(Matroid): sage: sorted(M._fundamental_cocircuit('efgh', 'e')) ['b', 'c', 'd', 'e'] """ - self.__pack(self._input, B) + self._pack(self._input, B) bitset_clear(self._input2) self.__move_current_basis(self._input, self._input2) self.__fundamental_cocircuit(self._output, self._idx[e]) @@ -943,8 +943,8 @@ cdef class BasisExchangeMatroid(Matroid): see :meth:``. """ - self.__pack(self._input, F) - self.__coclosure(self._output, self._input) + self._pack(self._input, F) + self._coclosure_internal(self._output, self._input) return self.__unpack(self._output) cpdef _augment(self, X, Y): @@ -973,8 +973,8 @@ cdef class BasisExchangeMatroid(Matroid): ['e', 'f', 'g'] """ - self.__pack(self._input, X) - self.__pack(self._input2, Y) + self._pack(self._input, X) + self._pack(self._input2, Y) self.__augment(self._output, self._input, self._input2) return self.__unpack(self._output) @@ -1006,7 +1006,7 @@ cdef class BasisExchangeMatroid(Matroid): the input is indeed a subset of the ground set, see :meth:``. """ - self.__pack(self._input, F) + self._pack(self._input, F) return self.__is_independent(self._input) # connectivity @@ -1142,8 +1142,8 @@ cdef class BasisExchangeMatroid(Matroid): cdef bitset_t SS, TT bitset_init(SS, self._groundset_size) bitset_init(TT, self._groundset_size) - self.__pack(SS,S) - self.__pack(TT,T) + self._pack(SS,S) + self._pack(TT,T) #F = set(self.groundset()) - (S | T) cdef bitset_t F, I bitset_init(F, self._groundset_size) @@ -1421,7 +1421,7 @@ cdef class BasisExchangeMatroid(Matroid): Rcoflats = SetSystem(self._E) i = 0 bitset_clear(todo[0]) - self.__coclosure(coflats[0], todo[0]) + self._coclosure_internal(coflats[0], todo[0]) bitset_complement(todo[0], coflats[0]) self._coflats_rec(Rcoflats, r, coflats, todo, 0, 0) for i in range(r + 1): @@ -1443,7 +1443,7 @@ cdef class BasisExchangeMatroid(Matroid): while e >= 0: bitset_copy(self._input, coflats[i]) bitset_add(self._input, e) - self.__coclosure(coflats[i + 1], self._input) + self._coclosure_internal(coflats[i + 1], self._input) bitset_difference(todo[i], todo[i], coflats[i + 1]) bitset_difference(todo[i + 1], coflats[i + 1], coflats[i]) if bitset_first(todo[i + 1]) == e: @@ -2397,7 +2397,7 @@ cdef class BasisExchangeMatroid(Matroid): # Set current basis to Y bitset_difference(self._inside, self._current_basis, BB._subsets[pointerY]) bitset_difference(self._outside, BB._subsets[pointerY], self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) if not bitset_eq(self._current_basis, BB._subsets[pointerY]): # We failed to set the current basis to Y through basis exchanges. # Therefore, the exchange axioms are violated! @@ -2409,7 +2409,7 @@ cdef class BasisExchangeMatroid(Matroid): foundpair = False y = bitset_first(self._input2) while y >= 0: # for y in Y-X - if self.__is_exchange_pair(y, x): + if self._is_exchange_pair(y, x): foundpair = True y = -1 else: diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 3ac43112627..6dff6506981 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -219,7 +219,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): raise ValueError("basis has wrong cardinality.") if not b.issubset(self._groundset): raise ValueError("basis is not a subset of the groundset") - self.__pack(self._b, b) + self._pack(self._b, b) i = set_to_index(self._b) if not bitset_in(self._bb, i): self._bcount += 1 @@ -234,7 +234,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): raise ValueError("nonbasis has wrong cardinality") if not b.issubset(self._groundset): raise ValueError("nonbasis is not a subset of the groundset") - self.__pack(self._b, b) + self._pack(self._b, b) i = set_to_index(self._b) if bitset_in(self._bb, i): self._bcount -= 1 @@ -263,7 +263,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): # support for parent BasisExchangeMatroid - cdef bint __is_exchange_pair(self, long x, long y) except -1: # test if current_basis-x + y is a basis + cdef bint _is_exchange_pair(self, long x, long y) except -1: # test if current_basis-x + y is a basis """ Test if `B-e + f` is a basis of the current matroid. @@ -326,7 +326,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): sage: M._is_basis(set(['a', 'b', 'c', 'd'])) False """ - self.__pack(self._b, X) + self._pack(self._b, X) return bitset_in(self._bb, set_to_index(self._b)) # dual and minors @@ -557,7 +557,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): """ M = BasisMatroid(M=self) - M.__relabel(l) + M._relabel(l) return M # enumeration @@ -868,8 +868,11 @@ cdef class BasisMatroid(BasisExchangeMatroid): Return if the application of a groundset morphism to this matroid yields a relaxation of the given matroid. - M is a relaxation of N if the set of bases of M is a subset of the - bases of N. + `M` is a relaxation of `N` if the set of bases of `M` is a superset of the + bases of `N`. + + This method assumes that ``self`` and ``other`` have the same rank + and does not check this condition. INPUT: @@ -922,7 +925,10 @@ cdef class BasisMatroid(BasisExchangeMatroid): cpdef _is_isomorphism(self, other, morphism): """ - Version of is_isomorphism() that does no type checking. + Version of :meth:`is_isomorphism` that does no type checking. + + This method assumes that ``self`` and ``other`` have the same rank + and does not check this condition. INPUT: @@ -1177,7 +1183,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): """ N = BasisMatroid(M=self) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo=None): @@ -1201,7 +1207,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): if memo is None: memo = {} N = BasisMatroid(M=self) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __reduce__(self): @@ -1230,7 +1236,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): """ import sage.matroids.unpickling BB = bitset_pickle(self._bb) - data = (self._E, self._matroid_rank, getattr(self, '__custom_name'), BB) + data = (self._E, self._matroid_rank, self.get_custom_name(), BB) version = 0 return sage.matroids.unpickling.unpickle_basis_matroid, (version, data) diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index 402822b2dc6..4e79b0575e2 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -513,8 +513,7 @@ cdef class CircuitClosuresMatroid(Matroid): N._groundset = self._groundset N._circuit_closures = self._circuit_closures N._matroid_rank = self._matroid_rank - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default copy - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo=None): @@ -539,8 +538,7 @@ cdef class CircuitClosuresMatroid(Matroid): from copy import deepcopy # Since matroids are immutable, N cannot reference itself in correct code, so no need to worry about the recursion. N = CircuitClosuresMatroid(groundset=deepcopy(self._groundset, memo), circuit_closures=deepcopy(self._circuit_closures, memo)) - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default deepcopy - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -570,7 +568,7 @@ cdef class CircuitClosuresMatroid(Matroid): 4: {{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}}} """ import sage.matroids.unpickling - data = (self._groundset, self._circuit_closures, getattr(self, '__custom_name')) + data = (self._groundset, self._circuit_closures, self.get_custom_name()) version = 0 return sage.matroids.unpickling.unpickle_circuit_closures_matroid, (version, data) diff --git a/src/sage/matroids/dual_matroid.py b/src/sage/matroids/dual_matroid.py index 804e43f035b..da6639827e4 100644 --- a/src/sage/matroids/dual_matroid.py +++ b/src/sage/matroids/dual_matroid.py @@ -519,9 +519,7 @@ def __copy__(self): """ N = DualMatroid(self._matroid) - if getattr(self, '__custom_name') is not None: - # because of name wrangling, this is not caught by the default copy - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo={}): @@ -543,10 +541,7 @@ def __deepcopy__(self, memo={}): """ from copy import deepcopy N = DualMatroid(deepcopy(self._matroid, memo)) - if getattr(self, '__custom_name') is not None: - # because of name wrangling, this is not caught by the - # default deepcopy - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -575,6 +570,6 @@ def __reduce__(self): 4: {{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}}}' """ import sage.matroids.unpickling - data = (self._matroid, getattr(self, '__custom_name')) + data = (self._matroid, self.get_custom_name()) version = 0 return sage.matroids.unpickling.unpickle_dual_matroid, (version, data) diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index 5216ef11517..c841bc7d9d1 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -481,8 +481,7 @@ def __copy__(self): False """ N = GraphicMatroid(self._G) - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default copy - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo={}): @@ -502,8 +501,7 @@ def __deepcopy__(self, memo={}): """ # The only real difference between this and __copy__() is the memo N = GraphicMatroid(deepcopy(self._G, memo)) - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default deepcopy - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -519,7 +517,7 @@ def __reduce__(self): Graphic matroid of rank 9 on 15 elements """ from .unpickling import unpickle_graphic_matroid - data = (self._G, getattr(self, '__custom_name')) + data = (self._G, self.get_custom_name()) version = 0 return unpickle_graphic_matroid, (version, data) @@ -895,7 +893,7 @@ def _circuit(self, X): OUTPUT: ``frozenset`` instance containing a subset of ``X``. - A ``ValueError`` is raised if the set contains no circuit. + A :class:`ValueError` is raised if the set contains no circuit. EXAMPLES:: diff --git a/src/sage/matroids/linear_matroid.pxd b/src/sage/matroids/linear_matroid.pxd index 014c8aef57d..9aebd446b68 100644 --- a/src/sage/matroids/linear_matroid.pxd +++ b/src/sage/matroids/linear_matroid.pxd @@ -15,7 +15,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): cpdef characteristic(self) cdef list _setup_internal_representation(self, matrix, reduced_matrix, ring, keep_initial_representation) - cdef __exchange_value(self, long x, long y) + cdef _exchange_value_internal(self, long x, long y) cpdef representation(self, B=*, reduced=*, labels=*, order=*, lift_map=*) cpdef _current_rows_cols(self, B=*) diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index 61452e80c48..36f563aa433 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -391,13 +391,13 @@ cdef class LinearMatroid(BasisExchangeMatroid): """ return characteristic(self._A) - cdef bint __is_exchange_pair(self, long x, long y) except -1: + cdef bint _is_exchange_pair(self, long x, long y) except -1: r""" Check if ``self.basis() - x + y`` is again a basis. Internal method. """ return self._A.is_nonzero(self._prow[x], self._prow[y]) - cdef int __exchange(self, long x, long y) except -1: + cdef int _exchange(self, long x, long y) except -1: """ Put element indexed by ``x`` into basis, taking out element ``y``. Assumptions are that this is a valid basis exchange. @@ -420,9 +420,9 @@ cdef class LinearMatroid(BasisExchangeMatroid): self._A.set_unsafe(px, py, pivi) self._prow[y] = px self._prow[x] = py - BasisExchangeMatroid.__exchange(self, x, y) + BasisExchangeMatroid._exchange(self, x, y) - cdef __exchange_value(self, long x, long y): + cdef _exchange_value_internal(self, long x, long y): r""" Return the (x, y) entry of the current representation. """ @@ -605,7 +605,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): self._representation = self._basic_representation(B) A = self._representation else: - B = self.__subset(B) + B = self._subset_internal(B) A = self._basic_representation(B) A = A.matrix_from_rows_and_columns(range(A.nrows()), order_idx) if lift_map is None: @@ -622,7 +622,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): if B is None: B = frozenset(self.basis()) else: - B = self.__subset(B) + B = self._subset_internal(B) A = self._reduced_representation(B) R, C = self._current_rows_cols() Ri = [] @@ -1493,7 +1493,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): sage: M._exchange_value(1, 3) 4 """ - return self.__exchange_value(self._idx[e], self._idx[f]) + return self._exchange_value_internal(self._idx[e], self._idx[f]) cpdef fundamental_cycle(self, B, e): """ @@ -2909,7 +2909,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): else: rows, cols = self._current_rows_cols() N = LinearMatroid(groundset=rows + cols, reduced_matrix=self._A) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo): @@ -2930,7 +2930,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): else: rows, cols = self._current_rows_cols() N = LinearMatroid(groundset=deepcopy(rows + cols, memo), reduced_matrix=deepcopy(self._A, memo)) - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -2979,7 +2979,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): rows, cols = self._current_rows_cols() gs = rows + cols reduced = True - data = (A, gs, reduced, getattr(self, '__custom_name')) + data = (A, gs, reduced, self.get_custom_name()) return sage.matroids.unpickling.unpickle_linear_matroid, (version, data) # Binary matroid @@ -3152,20 +3152,20 @@ cdef class BinaryMatroid(LinearMatroid): """ return 2 - cdef bint __is_exchange_pair(self, long x, long y) except -1: + cdef bint _is_exchange_pair(self, long x, long y) except -1: r""" Check if ``self.basis() - x + y`` is again a basis. Internal method. """ return (self._A).is_nonzero(self._prow[x], y) - cdef int __exchange(self, long x, long y) except -1: + cdef int _exchange(self, long x, long y) except -1: r""" Replace ``self.basis() with ``self.basis() - x + y``. Internal method, does no checks. """ cdef long p = self._prow[x] self._A.pivot(p, y) # Not a Sage matrix operation self._prow[y] = p - BasisExchangeMatroid.__exchange(self, x, y) + BasisExchangeMatroid._exchange(self, x, y) cdef __fundamental_cocircuit(self, bitset_t C, long x): r""" @@ -3173,18 +3173,18 @@ cdef class BinaryMatroid(LinearMatroid): """ bitset_copy(C, (self._A)._M[self._prow[x]]) - cdef __coclosure(self, bitset_t R, bitset_t F): + cdef _coclosure_internal(self, bitset_t R, bitset_t F): """ Bitpacked version of ``coclosure``. - This function overrides the internal function BasisExchangeMatroid.__coclosure() of the parent class. + This function overrides the internal function BasisExchangeMatroid._coclosure_internal() of the parent class. The implementation should be more efficient for BinaryMatroid, due to the fact that in this class, __fundamental_cocircuit is much faster than __fundamental_circuit. """ bitset_complement(R, F) bitset_difference(self._inside, self._current_basis, R) bitset_difference(self._outside, R, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_copy(R, F) bitset_difference(self._inside, self._current_basis, F) @@ -3196,7 +3196,7 @@ cdef class BinaryMatroid(LinearMatroid): bitset_add(R, y) y = bitset_next(self._inside, y + 1) - cdef __exchange_value(self, long x, long y): + cdef _exchange_value_internal(self, long x, long y): r""" Return the (x, y) entry of the current representation. """ @@ -3964,7 +3964,7 @@ cdef class BinaryMatroid(LinearMatroid): for e in self.basis(): basis[self._prow[self._idx[e]]] = e N = BinaryMatroid(groundset=self._E, matrix=self._A, basis=basis) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo): @@ -3989,7 +3989,7 @@ cdef class BinaryMatroid(LinearMatroid): for e in self.basis(): basis[self._prow[self._idx[e]]] = e N = BinaryMatroid(groundset=deepcopy(self._E, memo), matrix=deepcopy(self._A, memo), basis=deepcopy(basis, memo)) - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -4047,7 +4047,7 @@ cdef class BinaryMatroid(LinearMatroid): A = self._A # current basis ordered so matrix cols form identity matrix: basis = self._current_rows_cols()[0] - data = (A, gs, basis, getattr(self, '__custom_name')) + data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_binary_matroid, (version, data) cdef class TernaryMatroid(LinearMatroid): @@ -4220,20 +4220,20 @@ cdef class TernaryMatroid(LinearMatroid): """ return 3 - cdef bint __is_exchange_pair(self, long x, long y) except -1: + cdef bint _is_exchange_pair(self, long x, long y) except -1: r""" Check if ``self.basis() - x + y`` is again a basis. Internal method. """ return (self._A).is_nonzero(self._prow[x], y) - cdef int __exchange(self, long x, long y) except -1: + cdef int _exchange(self, long x, long y) except -1: r""" Replace ``self.basis() with ``self.basis() - x + y``. Internal method, does no checks. """ cdef long p = self._prow[x] self._A.pivot(p, y) # Not a Sage matrix operation self._prow[y] = p - BasisExchangeMatroid.__exchange(self, x, y) + BasisExchangeMatroid._exchange(self, x, y) cdef __fundamental_cocircuit(self, bitset_t C, long x): r""" @@ -4241,18 +4241,18 @@ cdef class TernaryMatroid(LinearMatroid): """ bitset_copy(C, (self._A)._M0[self._prow[x]]) - cdef __coclosure(self, bitset_t R, bitset_t F): + cdef _coclosure_internal(self, bitset_t R, bitset_t F): """ Bitpacked version of ``coclosure``. - This function overrides the internal function BasisExchangeMatroid.__coclosure() of the parent class. + This function overrides the internal function BasisExchangeMatroid._coclosure_internal() of the parent class. The implementation should be more efficient for TernaryMatroid, due to the fact that in this class, __fundamental_cocircuit is much faster than __fundamental_circuit. """ bitset_complement(R, F) bitset_difference(self._inside, self._current_basis, R) bitset_difference(self._outside, R, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_copy(R, F) bitset_difference(self._inside, self._current_basis, F) @@ -4264,7 +4264,7 @@ cdef class TernaryMatroid(LinearMatroid): bitset_add(R, y) y = bitset_next(self._inside, y + 1) - cdef __exchange_value(self, long x, long y): + cdef _exchange_value_internal(self, long x, long y): r""" Return the (x, y) entry of the current representation. """ @@ -4858,7 +4858,7 @@ cdef class TernaryMatroid(LinearMatroid): for e in self.basis(): basis[self._prow[self._idx[e]]] = e N = TernaryMatroid(groundset=self._E, matrix=self._A, basis=basis) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo): @@ -4883,7 +4883,7 @@ cdef class TernaryMatroid(LinearMatroid): for e in self.basis(): basis[self._prow[self._idx[e]]] = e N = TernaryMatroid(groundset=deepcopy(self._E, memo), matrix=deepcopy(self._A, memo), basis=deepcopy(basis, memo)) - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -4945,7 +4945,7 @@ cdef class TernaryMatroid(LinearMatroid): A = self._A # current basis ordered so matrix cols form identity matrix: basis = self._current_rows_cols()[0] - data = (A, gs, basis, getattr(self, '__custom_name')) + data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_ternary_matroid, (version, data) # Quaternary Matroids @@ -5122,20 +5122,20 @@ cdef class QuaternaryMatroid(LinearMatroid): """ return 2 - cdef bint __is_exchange_pair(self, long x, long y) except -1: + cdef bint _is_exchange_pair(self, long x, long y) except -1: r""" Check if ``self.basis() - x + y`` is again a basis. Internal method. """ return (self._A).is_nonzero(self._prow[x], y) - cdef int __exchange(self, long x, long y) except -1: + cdef int _exchange(self, long x, long y) except -1: r""" Replace ``self.basis() with ``self.basis() - x + y``. Internal method, does no checks. """ cdef long p = self._prow[x] self._A.pivot(p, y) # Not a Sage matrix operation self._prow[y] = p - BasisExchangeMatroid.__exchange(self, x, y) + BasisExchangeMatroid._exchange(self, x, y) cdef __fundamental_cocircuit(self, bitset_t C, long x): r""" @@ -5143,18 +5143,18 @@ cdef class QuaternaryMatroid(LinearMatroid): """ bitset_union(C, (self._A)._M0[self._prow[x]], (self._A)._M1[self._prow[x]]) - cdef __coclosure(self, bitset_t R, bitset_t F): + cdef _coclosure_internal(self, bitset_t R, bitset_t F): """ Bitpacked version of ``coclosure``. - This function overrides the internal function BasisExchangeMatroid.__coclosure() of the parent class. + This function overrides the internal function BasisExchangeMatroid._coclosure_internal() of the parent class. The implementation should be more efficient for QuaternaryMatroid, due to the fact that in this class, __fundamental_cocircuit is much faster than __fundamental_circuit. """ bitset_complement(R, F) bitset_difference(self._inside, self._current_basis, R) bitset_difference(self._outside, R, self._current_basis) - self.__move(self._inside, self._outside) + self._move(self._inside, self._outside) bitset_copy(R, F) bitset_difference(self._inside, self._current_basis, F) @@ -5166,7 +5166,7 @@ cdef class QuaternaryMatroid(LinearMatroid): bitset_add(R, y) y = bitset_next(self._inside, y + 1) - cdef __exchange_value(self, long x, long y): + cdef _exchange_value_internal(self, long x, long y): r""" Return the (x, y) entry of the current representation. """ @@ -5589,7 +5589,7 @@ cdef class QuaternaryMatroid(LinearMatroid): for e in self.basis(): basis[self._prow[self._idx[e]]] = e N = QuaternaryMatroid(groundset=self._E, matrix=self._A, basis=basis) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo): @@ -5614,7 +5614,7 @@ cdef class QuaternaryMatroid(LinearMatroid): for e in self.basis(): basis[self._prow[self._idx[e]]] = e N = QuaternaryMatroid(groundset=deepcopy(self._E, memo), matrix=deepcopy(self._A, memo), basis=deepcopy(basis, memo)) - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -5672,7 +5672,7 @@ cdef class QuaternaryMatroid(LinearMatroid): A = self._A # current basis ordered so matrix cols form identity matrix: basis = self._current_rows_cols()[0] - data = (A, gs, basis, getattr(self, '__custom_name')) + data = (A, gs, basis, self.get_custom_name()) return sage.matroids.unpickling.unpickle_quaternary_matroid, (version, data) # Regular Matroids @@ -5838,13 +5838,13 @@ cdef class RegularMatroid(LinearMatroid): """ return 0 - cdef bint __is_exchange_pair(self, long x, long y) except -1: + cdef bint _is_exchange_pair(self, long x, long y) except -1: r""" Check if ``self.basis() - x + y`` is again a basis. Internal method. """ return (self._A).is_nonzero(self._prow[x], self._prow[y]) - cdef int __exchange(self, long x, long y) except -1: + cdef int _exchange(self, long x, long y) except -1: """ Put element indexed by ``x`` into basis, taking out element ``y``. Assumptions are that this is a valid basis exchange. @@ -5867,9 +5867,9 @@ cdef class RegularMatroid(LinearMatroid): (self._A).set(px, py, pivi) # Not a Sage matrix operation self._prow[y] = px self._prow[x] = py - BasisExchangeMatroid.__exchange(self, x, y) + BasisExchangeMatroid._exchange(self, x, y) - cdef __exchange_value(self, long x, long y): + cdef _exchange_value_internal(self, long x, long y): r""" Return the (x, y) entry of the current representation. @@ -6524,7 +6524,7 @@ cdef class RegularMatroid(LinearMatroid): else: rows, cols = self._current_rows_cols() N = RegularMatroid(groundset=rows + cols, reduced_matrix=self._A) - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo): @@ -6544,7 +6544,7 @@ cdef class RegularMatroid(LinearMatroid): else: rows, cols = self._current_rows_cols() N = RegularMatroid(groundset=deepcopy(rows + cols, memo), reduced_matrix=deepcopy(self._A, memo)) - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -6593,5 +6593,5 @@ cdef class RegularMatroid(LinearMatroid): rows, cols = self._current_rows_cols() gs = rows + cols reduced = True - data = (A, gs, reduced, getattr(self, '__custom_name')) + data = (A, gs, reduced, self.get_custom_name()) return sage.matroids.unpickling.unpickle_regular_matroid, (version, data) diff --git a/src/sage/matroids/matroid.pxd b/src/sage/matroids/matroid.pxd index fe6c07e3b71..e9ddfec96ae 100644 --- a/src/sage/matroids/matroid.pxd +++ b/src/sage/matroids/matroid.pxd @@ -1,8 +1,7 @@ from sage.structure.sage_object cimport SageObject cdef class Matroid(SageObject): - cdef public __custom_name - cdef public _custom_name + cdef public _SageObject__custom_name cdef public _cached_info cdef int _stored_full_rank cdef int _stored_size @@ -37,7 +36,7 @@ cdef class Matroid(SageObject): cpdef _line_length(self, F) cpdef _extension(self, element, hyperplanes) - cdef inline __subset(self, X): + cdef inline _subset_internal(self, X): """ Convert ``X`` to a ``frozenset`` and check that it is a subset of the groundset. diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index dcee87ea49c..4d19c589bdf 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -563,7 +563,7 @@ cdef class Matroid(SageObject): OUTPUT: ``frozenset`` instance containing a subset of the groundset. - A ``ValueError`` is raised if the set contains no circuit. + A :class:`ValueError` is raised if the set contains no circuit. EXAMPLES:: @@ -708,7 +708,7 @@ cdef class Matroid(SageObject): OUTPUT: ``frozenset`` instance containing a subset of the groundset. - A ``ValueError`` is raised if the set contains no cocircuit. + A :class:`ValueError` is raised if the set contains no cocircuit. EXAMPLES:: @@ -1307,7 +1307,7 @@ cdef class Matroid(SageObject): TypeError: 'sage.rings.integer.Integer' object is not iterable """ # Call corresponding Cython method - return self.__subset(X) + return self._subset_internal(X) def _subset_all(self, X): """ @@ -1374,7 +1374,7 @@ cdef class Matroid(SageObject): """ if X is None: return self.full_rank() - return self._rank(self.__subset(X)) + return self._rank(self._subset_internal(X)) cpdef full_rank(self): r""" @@ -1453,7 +1453,7 @@ cdef class Matroid(SageObject): ... ValueError: ['x'] is not a subset of the groundset """ - return self._max_independent(self.__subset(X)) + return self._max_independent(self._subset_internal(X)) cpdef circuit(self, X=None): """ @@ -1558,7 +1558,7 @@ cdef class Matroid(SageObject): ... ValueError: ['x'] is not a subset of the groundset """ - return self._closure(self.__subset(X)) + return self._closure(self._subset_internal(X)) cpdef k_closure(self, X, k): r""" @@ -1597,7 +1597,7 @@ cdef class Matroid(SageObject): sage: sorted(M.k_closure({0,1}, 4)) [0, 1, 4] """ - X = self.__subset(X) + X = self._subset_internal(X) cdef int cur cdef frozenset S, cl cur = 0 @@ -1644,7 +1644,7 @@ cdef class Matroid(SageObject): ... ValueError: ['x'] is not a subset of the groundset """ - X = self.__subset(X) + X = self._subset_internal(X) Y = self.__subset_all(Y) return self._augment(X, Y.difference(X)) @@ -1781,7 +1781,7 @@ cdef class Matroid(SageObject): ... ValueError: ['x'] is not a subset of the groundset """ - return self._max_coindependent(self.__subset(X)) + return self._max_coindependent(self._subset_internal(X)) cpdef coclosure(self, X): """ @@ -1813,7 +1813,7 @@ cdef class Matroid(SageObject): ... ValueError: ['x'] is not a subset of the groundset """ - return self._coclosure(self.__subset(X)) + return self._coclosure(self._subset_internal(X)) cpdef cocircuit(self, X=None): """ @@ -1947,7 +1947,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return self._is_independent(self.__subset(X)) + return self._is_independent(self._subset_internal(X)) cpdef is_dependent(self, X): r""" @@ -1973,7 +1973,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return not self._is_independent(self.__subset(X)) + return not self._is_independent(self._subset_internal(X)) cpdef is_basis(self, X): r""" @@ -1999,7 +1999,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - X = self.__subset(X) + X = self._subset_internal(X) if len(X) != self.full_rank(): return False return self._is_basis(X) @@ -2035,7 +2035,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return self._is_closed(self.__subset(X)) + return self._is_closed(self._subset_internal(X)) cpdef is_subset_k_closed(self, X, int k): r""" @@ -2118,7 +2118,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return self._is_circuit(self.__subset(X)) + return self._is_circuit(self._subset_internal(X)) cpdef coloops(self): r""" @@ -2178,7 +2178,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return self._is_coindependent(self.__subset(X)) + return self._is_coindependent(self._subset_internal(X)) cpdef is_codependent(self, X): r""" @@ -2211,7 +2211,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return not self._is_coindependent(self.__subset(X)) + return not self._is_coindependent(self._subset_internal(X)) cpdef is_cobasis(self, X): r""" @@ -2245,7 +2245,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - X = self.__subset(X) + X = self._subset_internal(X) if len(X) != self.full_corank(): return False return self._is_cobasis(X) @@ -2282,7 +2282,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return self._is_cocircuit(self.__subset(X)) + return self._is_cocircuit(self._subset_internal(X)) cpdef is_coclosed(self, X): r""" @@ -2315,7 +2315,7 @@ cdef class Matroid(SageObject): ... ValueError: 'abcx' is not a subset of the groundset """ - return self._is_coclosed(self.__subset(X)) + return self._is_coclosed(self._subset_internal(X)) # verification @@ -3254,7 +3254,7 @@ cdef class Matroid(SageObject): OUTPUT: Boolean, - and, if certificate = True, a dictionary giving the isomorphism or None + and, if ``certificate=True``, a dictionary giving the isomorphism or ``None`` .. NOTE:: @@ -3419,6 +3419,15 @@ cdef class Matroid(SageObject): False sage: M1 == M3 True + + TESTS: + + Check that :issue:`35946` is fixed:: + + sage: M = matroids.Uniform(3,5) + sage: N = matroids.Uniform(2,5) + sage: M.equals(N) + False """ if self is other: return True @@ -3426,6 +3435,8 @@ cdef class Matroid(SageObject): raise TypeError("can only test for isomorphism between matroids.") if (self.size() != other.size() or other.groundset().difference(self.groundset())): return False + if self.full_rank() != other.full_rank(): + return False morphism = {e: e for e in self.groundset()} return self._is_isomorphism(other, morphism) @@ -3532,6 +3543,15 @@ cdef class Matroid(SageObject): sage: # needs sage.graphs sage: N.is_isomorphism(M, g) True + + TESTS: + + Check that :issue:`35946` is fixed:: + + sage: M = matroids.Uniform(3,5) + sage: N = matroids.Uniform(2,5) + sage: M.is_isomorphism(N, {e: e for e in M.groundset()}) + False """ from copy import copy if not isinstance(other, Matroid): @@ -3555,11 +3575,16 @@ cdef class Matroid(SageObject): raise ValueError("range of morphism does not contain groundset of other matroid.") if self is other: return self._is_isomorphism(copy(other), mf) + if self.full_rank() != other.full_rank(): + return False return self._is_isomorphism(other, mf) cpdef _is_isomorphism(self, other, morphism): r""" - Version of is_isomorphism() that does no type checking. + Version of :meth:`is_isomorphism` that does no type checking. + + This method assumes that ``self`` and ``other`` have the same rank + and does not check this condition. INPUT: @@ -4868,10 +4893,10 @@ cdef class Matroid(SageObject): sage: M.connectivity('ab', 'cd') 2 """ - S = self.__subset(S) + S = self._subset_internal(S) if T is None: return self._rank(S) + self._rank(self.groundset()-S) - self.full_rank() - T = self.__subset(T) + T = self._subset_internal(T) if S.intersection(T): raise ValueError("S and T are not disjoint") return len(self._link(S, T)[0]) - self.full_rank() + self._rank(S) + self._rank(T) @@ -4956,8 +4981,8 @@ cdef class Matroid(SageObject): sage: N.connectivity(S) 2 """ - S = self.__subset(S) - T = self.__subset(T) + S = self._subset_internal(S) + T = self._subset_internal(T) if not S.isdisjoint(T): raise ValueError("S and T are not disjoint") return self._link(S, T) diff --git a/src/sage/matroids/minor_matroid.py b/src/sage/matroids/minor_matroid.py index c0e756917f5..98856348ac1 100644 --- a/src/sage/matroids/minor_matroid.py +++ b/src/sage/matroids/minor_matroid.py @@ -486,8 +486,7 @@ def __copy__(self): True """ N = MinorMatroid(self._matroid, self._contractions, self._deletions) - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default copy - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo={}): @@ -512,8 +511,7 @@ def __deepcopy__(self, memo={}): from copy import deepcopy # Since matroids are immutable, N cannot reference itself in correct code, so no need to worry about the recursion. N = MinorMatroid(deepcopy(self._matroid, memo), deepcopy(self._contractions, memo), deepcopy(self._deletions, memo)) - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default deepcopy - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): @@ -534,6 +532,6 @@ def __reduce__(self): 4: {{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}}} """ import sage.matroids.unpickling - data = (self._matroid, self._contractions, self._deletions, getattr(self, '__custom_name')) + data = (self._matroid, self._contractions, self._deletions, self.get_custom_name()) version = 0 return sage.matroids.unpickling.unpickle_minor_matroid, (version, data) diff --git a/src/sage/matroids/rank_matroid.py b/src/sage/matroids/rank_matroid.py index 4633ff0a792..6c4e9470ada 100644 --- a/src/sage/matroids/rank_matroid.py +++ b/src/sage/matroids/rank_matroid.py @@ -267,9 +267,7 @@ def __copy__(self): N = RankMatroid(groundset=[], rank_function=None) N._groundset = self._groundset N._rank_function = self._rank_function - if getattr(self, '__custom_name') is not None: - # because of name wrangling, this is not caught by the default copy - N.rename(getattr(self, '__custom_name')) + N.rename(self.get_custom_name()) return N def __deepcopy__(self, memo={}): @@ -293,8 +291,7 @@ def __deepcopy__(self, memo={}): from copy import deepcopy # Since matroids are immutable, N cannot reference itself in correct code, so no need to worry about the recursion. N = RankMatroid(groundset=deepcopy(self._groundset), rank_function=deepcopy(self._rank_function)) - if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default deepcopy - N.rename(deepcopy(getattr(self, '__custom_name'), memo)) + N.rename(deepcopy(self.get_custom_name(), memo)) return N def __reduce__(self): diff --git a/src/sage/matroids/utilities.py b/src/sage/matroids/utilities.py index a8612dab29f..211c435c5ee 100644 --- a/src/sage/matroids/utilities.py +++ b/src/sage/matroids/utilities.py @@ -572,26 +572,28 @@ def lift_cross_ratios(A, lift_map=None): G = Graph([((r, 0), (c, 1), (r, c)) for r, c in A.nonzero_positions()]) # write the entries of (a scaled version of) A as products of cross ratios of A - T = set() + T = Graph() for C in G.connected_components_subgraphs(): - T.update(C.min_spanning_tree()) + T.add_edges(C.min_spanning_tree()) # - fix a tree of the support graph G to units (= empty dict, product of 0 terms) - F = {entry[2]: dict() for entry in T} - W = set(G.edge_iterator()) - set(T) - H = G.subgraph(edges=T) + F = {entry: dict() for entry in T.edge_labels()} + W = set(G.edge_iterator()) - set(T.edge_iterator()) + H = G.subgraph(edges=T.edge_iterator()) while W: # - find an edge in W to process, closing a circuit in H which is induced in G edge = W.pop() path = H.shortest_path(edge[0], edge[1]) + path_s = set(path) retry = True while retry: retry = False for edge2 in W: - if edge2[0] in path and edge2[1] in path: + if edge2[0] in path_s and edge2[1] in path_s: W.add(edge) edge = edge2 W.remove(edge) path = H.shortest_path(edge[0], edge[1]) + path_s = set(path) retry = True break entry = edge[2] diff --git a/src/sage/misc/binary_tree.pyx b/src/sage/misc/binary_tree.pyx index 0266699d02b..b23c9ee7266 100644 --- a/src/sage/misc/binary_tree.pyx +++ b/src/sage/misc/binary_tree.pyx @@ -1,13 +1,12 @@ """ Binary trees -Implements a binary tree in Cython. +This implements a binary tree in Cython. AUTHORS: - Tom Boothby (2007-02-15). Initial version free for any use (public domain). """ - from cysignals.memory cimport sig_malloc, sig_free from cpython.ref cimport PyObject, Py_INCREF, Py_XDECREF @@ -129,14 +128,14 @@ cdef binary_tree_node *binary_tree_head_excise(binary_tree_node *self): if self.left == NULL: return self.right if right: - #move right branch to left, return left + # move right branch to left, return left cur = self.left while cur.right != NULL: cur = cur.right cur.right = self.right cur = self.left else: - #move left branch to right, return right + # move left branch to right, return right cur = self.right while cur.left != NULL: cur = cur.left @@ -186,6 +185,7 @@ cdef class BinaryTree: """ def __cinit__(BinaryTree self): self.head = NULL + def __dealloc__(BinaryTree self): """ TESTS: @@ -206,14 +206,17 @@ cdef class BinaryTree: ....: return [(k,v) for (k,v) in post.items() if v>10] sage: test() # indirect doctest [] - """ binary_tree_dealloc(self.head) - def insert(BinaryTree self, object key, object value = None): + def insert(BinaryTree self, object key, object value=None): """ - Inserts a key-value pair into the BinaryTree. Duplicate keys are ignored. - The first parameter, key, should be an int, or coercible (one-to-one) into an int. + Insert a key-value pair into the BinaryTree. + + Duplicate keys are ignored. + + The first parameter, key, should be an int, or coercible (one-to-one) + into an int. EXAMPLES:: @@ -234,9 +237,10 @@ cdef class BinaryTree: self.head = BinaryTreeNode(ckey, value) else: binary_tree_insert(self.head, ckey, value) + def delete(BinaryTree self, int key): """ - Removes a the node corresponding to key, and returns the value + Remove a the node corresponding to key, and return the value associated with it. EXAMPLES:: @@ -277,28 +281,28 @@ cdef class BinaryTree: return r else: return binary_tree_delete(self.head, key) + def get(BinaryTree self, int key): """ - Returns the value associated with the key given. + Return the value associated with the key given. EXAMPLES:: sage: from sage.misc.binary_tree import BinaryTree sage: t = BinaryTree() - sage: t.insert(0,Matrix([[0,0],[1,1]])) - sage: t.insert(0,1) - sage: t.get(0) + sage: t.insert(0, Matrix([[0,0], [1,1]])) # needs sage.modules + sage: t.insert(0, 1) + sage: t.get(0) # needs sage.modules [0 0] [1 1] """ if self.head == NULL: return None - else: - return binary_tree_get(self.head, key) + return binary_tree_get(self.head, key) + def contains(BinaryTree self, int key): """ - Returns True if a node with the given key exists - in the tree, and False otherwise. + Return whether a node with the given key exists in the tree. EXAMPLES:: @@ -312,14 +316,11 @@ cdef class BinaryTree: """ if self.head == NULL: return False - else: - if binary_tree_get(self.head, key) is not None: - return True - else: - return False + return binary_tree_get(self.head, key) is not None + def get_max(BinaryTree self): """ - Returns the value of the node with the maximal key value. + Return the value of the node with the maximal key value. """ cdef binary_tree_node *cur if self.head == NULL: @@ -328,9 +329,10 @@ cdef class BinaryTree: while cur.right != NULL: cur = cur.right return cur.value + def get_min(BinaryTree self): """ - Returns the value of the node with the minimal key value. + Return the value of the node with the minimal key value. """ cdef binary_tree_node *cur if self.head == NULL: @@ -339,10 +341,11 @@ cdef class BinaryTree: while cur.left != NULL: cur = cur.left return cur.value + def pop_max(BinaryTree self): """ - Returns the value of the node with the maximal key value, - and removes that node from the tree. + Return the value of the node with the maximal key value, + and remove that node from the tree. EXAMPLES:: @@ -379,10 +382,11 @@ cdef class BinaryTree: max = cur.right.value cur.right = binary_tree_right_excise(cur.right) return max + def pop_min(BinaryTree self): """ - Returns the value of the node with the minimal key value, - and removes that node from the tree. + Return the value of the node with the minimal key value, + and remove that node from the tree. EXAMPLES:: @@ -422,7 +426,7 @@ cdef class BinaryTree: def is_empty(BinaryTree self): """ - Returns True if the tree has no nodes. + Return whether the tree has no nodes. EXAMPLES:: @@ -438,7 +442,9 @@ cdef class BinaryTree: def keys(BinaryTree self, order="inorder"): """ - Returns the keys sorted according to "order" parameter, which can be one of + Return the keys sorted according to "order" parameter. + + The order can be one of "inorder", "preorder", or "postorder" """ if self.head == NULL: @@ -455,7 +461,9 @@ cdef class BinaryTree: def values(BinaryTree self, order="inorder"): """ - Returns the keys sorted according to "order" parameter, which can be one of + Return the keys sorted according to "order" parameter. + + The order can be one of "inorder", "preorder", or "postorder" """ if self.head == NULL: @@ -473,13 +481,12 @@ cdef class BinaryTree: def _headkey_(BinaryTree self): """ Used by the stress tester. Don't think a user would care. + Email tom if you care what the headkey is. """ if self.head == NULL: return 0 - else: - return self.head.key - + return self.head.key class Test: @@ -488,11 +495,13 @@ class Test: def binary_tree(self, values = 100, cycles = 100000): """ - Performs a sequence of random operations, given random inputs - to stress test the binary tree structure. This was useful during - development to find memory leaks / segfaults. Cycles should be - at least 100 times as large as values, or the delete, contains, - and get methods won't hit very often. + Perform a sequence of random operations, given random inputs + to stress test the binary tree structure. + + This was useful during development to find memory leaks / + segfaults. Cycles should be at least 100 times as large as + values, or the delete, contains, and get methods won't hit + very often. INPUT: @@ -509,7 +518,7 @@ class Test: for i in range(cycles): r = randint(0, 8) s = randint(0, values) - if r==1: + if r == 1: t.insert(s) elif r == 2: t.delete(t._headkey_()) diff --git a/src/sage/misc/bindable_class.py b/src/sage/misc/bindable_class.py index d995ad65fc8..86d04bc8770 100644 --- a/src/sage/misc/bindable_class.py +++ b/src/sage/misc/bindable_class.py @@ -175,7 +175,7 @@ class BoundClass(functools.partial): .. warning:: - Since ``c`` is not a class (as tested by inspect.isclass), + Since ``c`` is not a class (as tested by :func:`inspect.isclass`), and has a ``__call__`` method, IPython's introspection (with ``c?``) insists on showing not only its documentation but also its class documentation and call @@ -183,14 +183,14 @@ class BoundClass(functools.partial): if available. Until a better approach is found, we reset the documentation - of ``BoundClass`` below, and make an exception for + of :class:`BoundClass` below, and make an exception for :meth:`__init__` to the strict rule that every method should be doctested:: sage: c.__class__.__doc__ sage: c.__class__.__init__.__doc__ - Make sure classes which inherit from functools.partial have the correct + Make sure classes which inherit from :class:`functools.partial` have the correct syntax, see :trac:`14748`:: sage: import warnings @@ -201,7 +201,7 @@ class BoundClass(functools.partial): sage: g() 8 - The following has correct syntax and no ``DeprecationWarning``:: + The following has correct syntax and no :class:`DeprecationWarning`:: sage: class mynewpartial(functools.partial): ....: def __init__(self, f, i, j): diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index ebadb070d1d..442dda7264f 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -196,21 +196,23 @@ key. We consider the smallest poset describing a class hierarchy admitting no MRO whatsoever:: - sage: P = Poset({10: [9,8,7], 9:[6,1], 8:[5,2], 7:[4,3], 6: [3,2], 5:[3,1], 4: [2,1] }, linear_extension=True, facade=True) + sage: P = Poset({10: [9,8,7], 9: [6,1], 8: [5,2], 7: [4,3], # needs sage.graphs + ....: 6: [3,2], 5: [3,1], 4: [2,1]}, + ....: linear_extension=True, facade=True) And build a :class:`HierarchyElement` from it:: sage: from sage.misc.c3_controlled import HierarchyElement - sage: x = HierarchyElement(10, P) + sage: x = HierarchyElement(10, P) # needs sage.graphs Here are its bases:: - sage: HierarchyElement(10, P)._bases + sage: HierarchyElement(10, P)._bases # needs sage.graphs [9, 8, 7] Using the standard ``C3`` algorithm fails:: - sage: x.mro_standard + sage: x.mro_standard # needs sage.graphs Traceback (most recent call last): ... ValueError: Cannot merge the items 3, 3, 2. @@ -219,16 +221,18 @@ We also get a failure when we relabel `P` according to another linear extension. For easy relabelling, we first need to set an appropriate default linear extension for `P`:: - sage: linear_extension = list(reversed(IntegerRange(1,11))) - sage: P = P.with_linear_extension(linear_extension) - sage: list(P) + sage: linear_extension = list(reversed(IntegerRange(1, 11))) + sage: P = P.with_linear_extension(linear_extension) # needs sage.graphs + sage: list(P) # needs sage.graphs [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] Now we play with a specific linear extension of `P`:: + sage: # needs sage.graphs sage: Q = P.linear_extension([10, 9, 8, 7, 6, 5, 4, 1, 2, 3]).to_poset() sage: Q.cover_relations() - [[10, 9], [10, 8], [10, 7], [9, 6], [9, 3], [8, 5], [8, 2], [7, 4], [7, 1], [6, 2], [6, 1], [5, 3], [5, 1], [4, 3], [4, 2]] + [[10, 9], [10, 8], [10, 7], [9, 6], [9, 3], [8, 5], [8, 2], [7, 4], + [7, 1], [6, 2], [6, 1], [5, 3], [5, 1], [4, 3], [4, 2]] sage: x = HierarchyElement(10, Q) sage: x.mro_standard Traceback (most recent call last): @@ -238,43 +242,43 @@ Now we play with a specific linear extension of `P`:: On the other hand, both the instrumented ``C3`` algorithm, and the controlled ``C3`` algorithm give the desired MRO:: - sage: x.mro + sage: x.mro # needs sage.graphs [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] - sage: x.mro_controlled + sage: x.mro_controlled # needs sage.graphs [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] The above checks, and more, can be run with:: - sage: x._test_mro() + sage: x._test_mro() # needs sage.graphs In practice, the control was achieved by adding the following bases:: - sage: x._bases + sage: x._bases # needs sage.graphs [9, 8, 7] - sage: x._bases_controlled + sage: x._bases_controlled # needs sage.graphs [9, 8, 7, 6, 5] Altogether, four bases were added for control:: - sage: sum(len(HierarchyElement(q, Q)._bases) for q in Q) + sage: sum(len(HierarchyElement(q, Q)._bases) for q in Q) # needs sage.graphs 15 - sage: sum(len(HierarchyElement(q, Q)._bases_controlled) for q in Q) + sage: sum(len(HierarchyElement(q, Q)._bases_controlled) for q in Q) # needs sage.graphs 19 This information can also be recovered with:: - sage: x.all_bases_len() + sage: x.all_bases_len() # needs sage.graphs 15 - sage: x.all_bases_controlled_len() + sage: x.all_bases_controlled_len() # needs sage.graphs 19 We now check that the ``C3`` algorithm fails for all linear extensions `l` of this poset, whereas both the instrumented and controlled ``C3`` algorithms succeed; along the way, we collect some statistics:: - sage: L = P.linear_extensions() + sage: L = P.linear_extensions() # needs sage.graphs sage: stats = [] - sage: for l in L: + sage: for l in L: # needs sage.graphs sage.modules ....: x = HierarchyElement(10, l.to_poset()) ....: try: # Check that x.mro_standard always fails with a ValueError ....: x.mro_standard @@ -291,7 +295,7 @@ Depending on the linear extension `l` it was necessary to add between one and five bases for control; for example, `216` linear extensions required the addition of four bases:: - sage: sorted(Word(stats).evaluation_sparse()) + sage: sorted(Word(stats).evaluation_sparse()) # needs sage.graphs sage.modules [(1, 36), (2, 108), (3, 180), (4, 216), (5, 180)] We now consider a hierarchy of categories:: @@ -336,7 +340,7 @@ list below does not change radically, it's fine to just update this doctest:: sage: from sage.categories.category import category_sample - sage: sorted([C for C in category_sample() + sage: sorted([C for C in category_sample() # needs sage.combinat sage.graphs sage.modules sage.rings.number_field ....: if len(C._super_categories_for_classes) != len(C.super_categories())], ....: key=str) [Category of affine weyl groups, @@ -488,6 +492,7 @@ cdef class CmpKey: True """ cdef int count + def __init__(self): """ Sets the internal category counter to zero. @@ -951,6 +956,7 @@ cpdef tuple C3_sorted_merge(list lists, key=identity): #assert C3_merge(lists[:-1]+[suggestion_list]) == out return (out, suggestion_list) + class HierarchyElement(object, metaclass=ClasscallMetaclass): """ A class for elements in a hierarchy. @@ -988,7 +994,7 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): :class:`HopfAlgebrasWithBasis`:: sage: from sage.misc.c3_controlled import HierarchyElement - sage: G = DiGraph({ + sage: G = DiGraph({ # needs sage.graphs ....: 44 : [43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], ....: 43 : [42, 41, 40, 36, 35, 39, 38, 37, 33, 32, 31, 30, 29, 28, 27, 26, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], ....: 42 : [36, 35, 37, 30, 29, 28, 27, 26, 15, 14, 12, 11, 9, 8, 5, 3, 2, 1, 0], @@ -1036,6 +1042,7 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): ....: 0 : [], ....: }) + sage: # needs sage.combinat sage.graphs sage: x = HierarchyElement(44, G) sage: x.mro [44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] @@ -1049,8 +1056,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): """ EXAMPLES:: + sage: # needs sage.combinat sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) sage: x = HierarchyElement(10, P) sage: x 10 @@ -1060,29 +1068,42 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): [10, 5, 2, 1] """ from sage.categories.sets_cat import Sets - from sage.combinat.posets.poset_examples import Posets - from sage.graphs.digraph import DiGraph - if succ in Posets(): - assert succ in Sets().Facade() - succ = succ.upper_covers - if isinstance(succ, DiGraph): - succ = succ.copy() - succ._immutable = True - succ = succ.neighbors_out + + try: + from sage.combinat.posets.poset_examples import Posets + except ImportError: + pass + else: + if succ in Posets(): + assert succ in Sets().Facade() + succ = succ.upper_covers + + try: + from sage.graphs.digraph import DiGraph + except ImportError: + pass + else: + if isinstance(succ, DiGraph): + succ = succ.copy() + succ._immutable = True + succ = succ.neighbors_out + if key is None: key = identity @cached_function def f(x): return typecall(cls, x, [f(y) for y in succ(x)], key, f) + return f(value) def __init__(self, value, bases, key, from_value): """ EXAMPLES:: + sage: # needs sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) sage: x = HierarchyElement(10, P) sage: x 10 @@ -1098,9 +1119,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): The ``_from_value`` attribute is a function that can be used to reconstruct an element of the hierarchy from its value:: - sage: x._from_value + sage: x._from_value # needs sage.graphs Cached version of .f at ...> - sage: x._from_value(x.value) is x + sage: x._from_value(x.value) is x # needs sage.graphs True """ self.value = value @@ -1115,9 +1136,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) - sage: x = HierarchyElement(10, P) - sage: x + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) # needs sage.graphs + sage: x = HierarchyElement(10, P) # needs sage.graphs + sage: x # needs sage.graphs 10 """ return repr(self.value) @@ -1133,8 +1154,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: + sage: # needs sage.combinat sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) sage: x = HierarchyElement(10, P) sage: x.bases [5, 2] @@ -1154,8 +1176,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement, C3_sorted_merge, identity - sage: P = Poset({7: [5,6], 5:[1,2], 6: [3,4]}, facade = True) + sage: P = Poset({7: [5, 6], 5: [1, 2], 6: [3, 4]}, facade=True) sage: x = HierarchyElement(5, P) sage: x.mro [5, 2, 1] @@ -1166,12 +1189,12 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): sage: x.mro [7, 6, 5, 4, 3, 2, 1] - sage: C3_sorted_merge([[6, 4, 3], [5, 2, 1], [6, 5]], identity) + sage: C3_sorted_merge([[6, 4, 3], [5, 2, 1], [6, 5]], identity) # needs sage.graphs ([6, 5, 4, 3, 2, 1], [6, 5, 4]) TESTS:: - sage: assert all(isinstance(v, Integer) for v in x.mro) + sage: assert all(isinstance(v, Integer) for v in x.mro) # needs sage.graphs """ bases = self._bases result, suggestion = C3_sorted_merge([base.mro for base in bases]+[[base.value for base in bases]], key=self._key) @@ -1190,8 +1213,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset({7: [5,6], 5:[1,2], 6: [3,4]}, facade = True) + sage: P = Poset({7: [5, 6], 5: [1, 2], 6: [3, 4]}, facade=True) sage: x = HierarchyElement(7, P) sage: x._bases [6, 5] @@ -1209,7 +1233,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.c3_controlled import HierarchyElement, C3_merge - sage: P = Poset({7: [5,6], 5:[1,2], 6: [3,4]}, facade=True) + + sage: # needs sage.graphs + sage: P = Poset({7: [5, 6], 5: [1, 2], 6: [3, 4]}, facade=True) sage: x = HierarchyElement(5, P) sage: x.mro_standard [5, 2, 1] @@ -1219,12 +1245,13 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): sage: x = HierarchyElement(7, P) sage: x.mro_standard [7, 6, 4, 3, 5, 2, 1] + sage: C3_merge([[6, 4, 3], [5, 2, 1], [6, 5]]) [6, 4, 3, 5, 2, 1] TESTS:: - sage: assert all(isinstance(v, Integer) for v in x.mro_standard) + sage: assert all(isinstance(v, Integer) for v in x.mro_standard) # needs sage.graphs """ bases = self._bases return [self.value] + C3_merge([base.mro_standard for base in bases]+[[base.value for base in bases]]) @@ -1238,7 +1265,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.c3_controlled import HierarchyElement, C3_merge - sage: P = Poset({7: [5,6], 5:[1,2], 6: [3,4]}, facade=True) + + sage: # needs sage.graphs + sage: P = Poset({7: [5, 6], 5: [1, 2], 6: [3, 4]}, facade=True) sage: x = HierarchyElement(5, P) sage: x.mro_controlled [5, 2, 1] @@ -1252,6 +1281,7 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): [6, 5] sage: x._bases_controlled [6, 5, 4] + sage: C3_merge([[6, 4, 3], [5, 2, 1], [6, 5]]) [6, 4, 3, 5, 2, 1] sage: C3_merge([[6, 4, 3], [5, 2, 1], [6, 5, 4]]) @@ -1259,14 +1289,14 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): TESTS:: - sage: assert all(isinstance(v, Integer) for v in x.mro_controlled) + sage: assert all(isinstance(v, Integer) for v in x.mro_controlled) # needs sage.graphs """ return [self.value] + C3_merge([base.mro_controlled for base in self._bases]+[self._bases_controlled]) @cached_method def _test_mro(self): r""" - Runs consistency tests. + Run consistency tests. This checks in particular that the instrumented ``C3`` and controlled ``C3`` algorithms give, as desired, the @@ -1281,9 +1311,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset({7: [5,6], 5:[1,2], 6: [3,4]}, facade=True) - sage: x = HierarchyElement(7, P) - sage: x._test_mro() + sage: P = Poset({7: [5, 6], 5: [1, 2], 6: [3, 4]}, facade=True) # needs sage.graphs + sage: x = HierarchyElement(7, P) # needs sage.graphs + sage: x._test_mro() # needs sage.graphs """ for b in self._bases: b._test_mro() @@ -1305,8 +1335,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) sage: x = HierarchyElement(1, P) sage: x.cls @@ -1332,8 +1363,9 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) sage: HierarchyElement(1, P).all_bases() {1} sage: HierarchyElement(10, P).all_bases() # random output @@ -1350,8 +1382,8 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) - sage: HierarchyElement(30, P).all_bases_len() + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) # needs sage.graphs + sage: HierarchyElement(30, P).all_bases_len() # needs sage.graphs 12 """ return sum( len(x._bases) for x in self.all_bases()) @@ -1363,8 +1395,8 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.c3_controlled import HierarchyElement - sage: P = Poset((divisors(30), lambda x,y: y.divides(x)), facade=True) - sage: HierarchyElement(30, P).all_bases_controlled_len() + sage: P = Poset((divisors(30), lambda x, y: y.divides(x)), facade=True) # needs sage.graphs + sage: HierarchyElement(30, P).all_bases_controlled_len() # needs sage.graphs 13 """ return sum( len(x._bases_controlled) for x in self.all_bases()) diff --git a/src/sage/misc/cachefunc.pxd b/src/sage/misc/cachefunc.pxd index d3cc677dece..8e5d9dfa42a 100644 --- a/src/sage/misc/cachefunc.pxd +++ b/src/sage/misc/cachefunc.pxd @@ -5,7 +5,7 @@ cpdef cache_key(o) cdef class CachedFunction(): cdef public str __name__ - cdef public str __module__ + cdef public str __cached_module__ cdef ArgumentFixer _argument_fixer cdef public f cdef public cache # not always of type @@ -20,7 +20,7 @@ cdef class CachedFunction(): cdef class CachedMethod(): cdef str _cache_name cdef public str __name__ - cdef public str __module__ + cdef public str __cached_module__ cdef CachedFunction _cachedfunc cdef Py_ssize_t nargs cpdef _get_instance_cache(self, inst) diff --git a/src/sage/misc/cachefunc.pyx b/src/sage/misc/cachefunc.pyx index dac4c684f47..8aa30a85272 100644 --- a/src/sage/misc/cachefunc.pyx +++ b/src/sage/misc/cachefunc.pyx @@ -46,26 +46,28 @@ the name that the wrapped method or function should have, since otherwise the name of the original function would be used:: - sage: cython('''cpdef test_funct(x): return -x''') # optional - sage.misc.cython - sage: wrapped_funct = cached_function(test_funct, name='wrapped_funct') # optional - sage.misc.cython - sage: wrapped_funct # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython('''cpdef test_funct(x): return -x''') + sage: wrapped_funct = cached_function(test_funct, name='wrapped_funct') + sage: wrapped_funct Cached version of - sage: wrapped_funct.__name__ # optional - sage.misc.cython + sage: wrapped_funct.__name__ 'wrapped_funct' - sage: wrapped_funct(5) # optional - sage.misc.cython + sage: wrapped_funct(5) -5 - sage: wrapped_funct(5) is wrapped_funct(5) # optional - sage.misc.cython + sage: wrapped_funct(5) is wrapped_funct(5) True We can proceed similarly for cached methods of Cython classes, provided that they allow attribute assignment or have a public -attribute ``__cached_methods`` of type ````. Since +attribute ``_cached_methods`` of type ````. Since :trac:`11115`, this is the case for all classes inheriting from :class:`~sage.structure.parent.Parent`. See below for a more explicit example. By :trac:`12951`, cached methods of extension classes can be defined by simply using the decorator. However, an indirect approach is still needed for cpdef methods:: + sage: # needs sage.misc.cython sage: cython_code = ['cpdef test_meth(self,x):', ....: ' "some doc for a wrapped cython method"', ....: ' return -x', @@ -77,21 +79,21 @@ approach is still needed for cpdef methods:: ....: ' "Some doc for direct method"', ....: ' return 2*x', ....: ' wrapped_method = cached_method(test_meth,name="wrapped_method")'] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython - sage: O = MyClass() # optional - sage.misc.cython - sage: O.direct_method # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) + sage: O = MyClass() + sage: O.direct_method Cached version of - sage: O.wrapped_method # optional - sage.misc.cython + sage: O.wrapped_method Cached version of - sage: O.wrapped_method.__name__ # optional - sage.misc.cython + sage: O.wrapped_method.__name__ 'wrapped_method' - sage: O.wrapped_method(5) # optional - sage.misc.cython + sage: O.wrapped_method(5) -5 - sage: O.wrapped_method(5) is O.wrapped_method(5) # optional - sage.misc.cython + sage: O.wrapped_method(5) is O.wrapped_method(5) True - sage: O.direct_method(5) # optional - sage.misc.cython + sage: O.direct_method(5) 10 - sage: O.direct_method(5) is O.direct_method(5) # optional - sage.misc.cython + sage: O.direct_method(5) is O.direct_method(5) True In some cases, one would only want to keep the result in cache as long @@ -129,8 +131,8 @@ category (previously, the cache would have been broken):: ....: " @cached_method", ....: " def invert(self, x):", ....: " return -x"] - sage: cython('\n'.join(cython_code)) # optional - sage.misc.cython - sage: C = MyCategory() # optional - sage.misc.cython + sage: cython('\n'.join(cython_code)) # needs sage.misc.cython + sage: C = MyCategory() # needs sage.misc.cython In order to keep the memory footprint of elements small, it was decided to not support the same freedom of using cached methods @@ -147,6 +149,7 @@ cached methods. We remark, however, that cached methods are hardly by used. :: + sage: # needs sage.misc.cython sage: cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod", "from cpython.object cimport PyObject_RichCompare", ....: "cdef class MyBrokenElement(Element):", ....: " cdef public object x", @@ -181,88 +184,92 @@ hardly by used. ....: "from sage.structure.parent cimport Parent", ....: "cdef class MyParent(Parent):", ....: " Element = MyElement"] - sage: cython('\n'.join(cython_code)) # optional - sage.misc.cython - sage: P = MyParent(category=C) # optional - sage.misc.cython - sage: ebroken = MyBrokenElement(P, 5) # optional - sage.misc.cython - sage: e = MyElement(P, 5) # optional - sage.misc.cython + sage: cython('\n'.join(cython_code)) + sage: P = MyParent(category=C) + sage: ebroken = MyBrokenElement(P, 5) + sage: e = MyElement(P, 5) The cached methods inherited by the parent works:: - sage: P.one() # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: P.one() <1> - sage: P.one() is P.one() # optional - sage.misc.cython + sage: P.one() is P.one() True - sage: P.invert(e) # optional - sage.misc.cython + sage: P.invert(e) <-5> - sage: P.invert(e) is P.invert(e) # optional - sage.misc.cython + sage: P.invert(e) is P.invert(e) True The cached methods inherited by ``MyElement`` works:: - sage: e.element_cache_test() # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: e.element_cache_test() <-5> - sage: e.element_cache_test() is e.element_cache_test() # optional - sage.misc.cython + sage: e.element_cache_test() is e.element_cache_test() True - sage: e.element_via_parent_test() # optional - sage.misc.cython + sage: e.element_via_parent_test() <-5> - sage: e.element_via_parent_test() is e.element_via_parent_test() # optional - sage.misc.cython + sage: e.element_via_parent_test() is e.element_via_parent_test() True The other element class can only inherit a ``cached_in_parent_method``, since the cache is stored in the parent. In fact, equal elements share the cache, even if they are of different types:: - sage: e == ebroken # optional - sage.misc.cython + sage: e == ebroken # needs sage.misc.cython True - sage: type(e) == type(ebroken) # optional - sage.misc.cython + sage: type(e) == type(ebroken) # needs sage.misc.cython False - sage: ebroken.element_via_parent_test() is e.element_via_parent_test() # optional - sage.misc.cython + sage: ebroken.element_via_parent_test() is e.element_via_parent_test() # needs sage.misc.cython True However, the cache of the other inherited method breaks, although the method as such works:: - sage: ebroken.element_cache_test() # optional - sage.misc.cython + sage: ebroken.element_cache_test() # needs sage.misc.cython <-5> - sage: ebroken.element_cache_test() is ebroken.element_cache_test() # optional - sage.misc.cython + sage: ebroken.element_cache_test() is ebroken.element_cache_test() # needs sage.misc.cython False The cache can be emptied:: - sage: a = test_pfunc(5) # optional - sage.misc.cython - sage: test_pfunc.clear_cache() # optional - sage.misc.cython - sage: a is test_pfunc(5) # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: a = test_pfunc(5) + sage: test_pfunc.clear_cache() + sage: a is test_pfunc(5) False - sage: a = P.one() # optional - sage.misc.cython - sage: P.one.clear_cache() # optional - sage.misc.cython - sage: a is P.one() # optional - sage.misc.cython + sage: a = P.one() + sage: P.one.clear_cache() + sage: a is P.one() False Since ``e`` and ``ebroken`` share the cache, when we empty it for one element it is empty for the other as well:: - sage: b = ebroken.element_via_parent_test() # optional - sage.misc.cython - sage: e.element_via_parent_test.clear_cache() # optional - sage.misc.cython - sage: b is ebroken.element_via_parent_test() # optional - sage.misc.cython + sage: b = ebroken.element_via_parent_test() # needs sage.misc.cython + sage: e.element_via_parent_test.clear_cache() # needs sage.misc.cython + sage: b is ebroken.element_via_parent_test() # needs sage.misc.cython False Introspection works:: + sage: # needs sage.misc.cython sage: from sage.misc.edit_module import file_and_line sage: from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource - sage: print(sage_getdoc(test_pfunc)) # optional - sage.misc.cython + sage: print(sage_getdoc(test_pfunc)) Some documentation - sage: print(sage_getdoc(O.wrapped_method)) # optional - sage.misc.cython + sage: print(sage_getdoc(O.wrapped_method)) some doc for a wrapped cython method - sage: print(sage_getdoc(O.direct_method)) # optional - sage.misc.cython + sage: print(sage_getdoc(O.direct_method)) Some doc for direct method - sage: print(sage_getsource(O.wrapped_method)) # optional - sage.misc.cython + sage: print(sage_getsource(O.wrapped_method)) cpdef test_meth(self,x): "some doc for a wrapped cython method" return -x - sage: print(sage_getsource(O.direct_method)) # optional - sage.misc.cython + sage: print(sage_getsource(O.direct_method)) def direct_method(self, x): "Some doc for direct method" return 2*x @@ -278,14 +285,14 @@ ought to be chosen. A typical example is (several arguments):: sage: P. = QQ[] - sage: I = P*[a,b] + sage: I = P * [a, b] sage: I.gens() [a, b] sage: I.gens() is I.gens() True - sage: I.groebner_basis() + sage: I.groebner_basis() # needs sage.libs.singular [a, b] - sage: I.groebner_basis() is I.groebner_basis() + sage: I.groebner_basis() is I.groebner_basis() # needs sage.libs.singular True sage: type(I.gens) @@ -294,21 +301,22 @@ ought to be chosen. A typical example is By :trac:`12951`, the cached_method decorator is also supported on non-c(p)def methods of extension classes, as long as they either support attribute assignment -or have a public attribute of type ```` called ``__cached_methods``. The +or have a public attribute of type ```` called ``_cached_methods``. The latter is easy:: + sage: # needs sage.misc.cython sage: cython_code = [ ....: "from sage.misc.cachefunc import cached_method", ....: "cdef class MyClass:", - ....: " cdef public dict __cached_methods", + ....: " cdef public dict _cached_methods", ....: " @cached_method", ....: " def f(self, a,b):", ....: " return a*b"] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython - sage: P = MyClass() # optional - sage.misc.cython - sage: P.f(2, 3) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) + sage: P = MyClass() + sage: P.f(2, 3) 6 - sage: P.f(2, 3) is P.f(2, 3) # optional - sage.misc.cython + sage: P.f(2, 3) is P.f(2, 3) True Providing attribute access is a bit more tricky, since it is needed that @@ -316,6 +324,7 @@ an attribute inherited by the instance from its class can be overridden on the instance. That is why providing a ``__getattr__`` would not be enough in the following example:: + sage: # needs sage.misc.cython sage: cython_code = [ ....: "from sage.misc.cachefunc import cached_method", ....: "cdef class MyOtherClass:", @@ -333,19 +342,19 @@ enough in the following example:: ....: " @cached_method", ....: " def f(self, a,b):", ....: " return a+b"] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython - sage: Q = MyOtherClass() # optional - sage.misc.cython - sage: Q.f(2, 3) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) + sage: Q = MyOtherClass() + sage: Q.f(2, 3) 5 - sage: Q.f(2, 3) is Q.f(2, 3) # optional - sage.misc.cython + sage: Q.f(2, 3) is Q.f(2, 3) True Note that supporting attribute access is somehow faster than the easier method:: - sage: timeit("a = P.f(2,3)") # random # optional - sage.misc.cython + sage: timeit("a = P.f(2,3)") # random # needs sage.misc.cython 625 loops, best of 3: 1.3 µs per loop - sage: timeit("a = Q.f(2,3)") # random # optional - sage.misc.cython + sage: timeit("a = Q.f(2,3)") # random # needs sage.misc.cython 625 loops, best of 3: 931 ns per loop Some immutable objects (such as `p`-adic numbers) cannot implement a @@ -353,18 +362,19 @@ reasonable hash function because their ``==`` operator has been modified to return ``True`` for objects which might behave differently in some computations:: - sage: K. = Qq(9) # optional - sage.rings.padics - sage: b = a.add_bigoh(1) # optional - sage.rings.padics - sage: c = a + 3 # optional - sage.rings.padics - sage: b # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K. = Qq(9) + sage: b = a.add_bigoh(1) + sage: c = a + 3 + sage: b a + O(3) - sage: c # optional - sage.rings.padics + sage: c a + 3 + O(3^20) - sage: b == c # optional - sage.rings.padics + sage: b == c True - sage: b == a # optional - sage.rings.padics + sage: b == a True - sage: c == a # optional - sage.rings.padics + sage: c == a False If such objects defined a non-trivial hash function, this would break @@ -372,20 +382,21 @@ caching in many places. However, such objects should still be usable in caches. This can be achieved by defining an appropriate method ``_cache_key``:: - sage: hash(b) # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: hash(b) Traceback (most recent call last): ... TypeError: unhashable type: 'sage.rings.padics.qadic_flint_CR.qAdicCappedRelativeElement' + sage: from sage.misc.cachefunc import cached_method sage: @cached_method ....: def f(x): return x == a - sage: f(b) # optional - sage.rings.padics + sage: f(b) True - sage: f(c) # if b and c were hashable, this would return True # optional - sage.rings.padics + sage: f(c) # if b and c were hashable, this would return True False - - sage: b._cache_key() # optional - sage.rings.padics + sage: b._cache_key() (..., ((0, 1),), 0, 1) - sage: c._cache_key() # optional - sage.rings.padics + sage: c._cache_key() (..., ((0, 1), (1,)), 0, 20) .. NOTE:: @@ -398,9 +409,9 @@ if ``a != b``, then also ``a._cache_key() != b._cache_key()``. In practice this means that the ``_cache_key`` should always include the parent as its first argument:: - sage: S. = Qq(4) # optional - sage.rings.padics - sage: d = a.add_bigoh(1) # optional - sage.rings.padics - sage: b._cache_key() == d._cache_key() # this would be True if the parents were not included # optional - sage.rings.padics + sage: S. = Qq(4) # needs sage.rings.padics + sage: d = a.add_bigoh(1) # needs sage.rings.padics + sage: b._cache_key() == d._cache_key() # this would be True if the parents were not included False """ @@ -460,9 +471,9 @@ def _cached_function_unpickle(module, name, cache=None): TESTS:: - sage: type(hilbert_class_polynomial) + sage: type(hilbert_class_polynomial) # needs sage.schemes - sage: loads(dumps(hilbert_class_polynomial)) is hilbert_class_polynomial #indirect doctest + sage: loads(dumps(hilbert_class_polynomial)) is hilbert_class_polynomial #indirect doctest # needs sage.schemes True Verify that the ``cache`` parameter works:: @@ -537,8 +548,8 @@ cpdef inline dict_key(o): sage: from sage.misc.cachefunc import dict_key sage: dict_key(42) 42 - sage: K. = Qq(9) # optional - sage.rings.padics - sage: dict_key(u) # optional - sage.rings.padics + sage: K. = Qq(9) # needs sage.rings.padics + sage: dict_key(u) # needs sage.rings.padics (, (..., 20)) """ try: @@ -561,24 +572,24 @@ cpdef inline cache_key(o): EXAMPLES:: sage: from sage.misc.cachefunc import cache_key - sage: K. = Qq(9) # optional - sage.rings.padics - sage: a = K(1); a # optional - sage.rings.padics + sage: K. = Qq(9) # needs sage.rings.padics + sage: a = K(1); a # needs sage.rings.padics 1 + O(3^20) - sage: cache_key(a) # optional - sage.rings.padics + sage: cache_key(a) # needs sage.rings.padics (..., ((1,),), 0, 20) This function works if ``o`` is a tuple. In this case it unpacks its entries recursively:: - sage: o = (1, 2, (3, a)) # optional - sage.rings.padics - sage: cache_key(o) # optional - sage.rings.padics + sage: o = (1, 2, (3, a)) # needs sage.rings.padics + sage: cache_key(o) # needs sage.rings.padics (1, 2, (3, (..., ((1,),), 0, 20))) Note that tuples are only partially unpacked if some of its entries are hashable:: - sage: o = (1/2, a) # optional - sage.rings.padics - sage: cache_key(o) # optional - sage.rings.padics + sage: o = (1/2, a) # needs sage.rings.padics + sage: cache_key(o) # needs sage.rings.padics (1/2, (..., ((1,),), 0, 20)) """ try: @@ -688,15 +699,17 @@ cdef class CachedFunction(): TESTS:: + sage: # needs sage.combinat sage: g = CachedFunction(number_of_partitions) sage: g.__name__ 'number_of_partitions' sage: 'partitions' in sage.misc.sageinspect.sage_getdoc(g) True - sage: g(5) + sage: g(5) # needs sage.libs.flint 7 - sage: g.cache + sage: g.cache # needs sage.libs.flint {((5, 'default'), ()): 7} + sage: def f(t=1): print(t) sage: h = CachedFunction(f) sage: w = walltime() @@ -761,13 +774,17 @@ cdef class CachedFunction(): else: self.__name__ = f.__name__ try: - self.__module__ = f.__module__ + self.__cached_module__ = f.__module__ except AttributeError: - self.__module__ = f.__objclass__.__module__ + self.__cached_module__ = f.__objclass__.__module__ if argument_fixer is not None: # it is None unless the argument fixer # was known previously. See #15038. self._argument_fixer = argument_fixer + @property + def __module__(self): + return self.__cached_module__ + cdef get_key_args_kwds(self, tuple args, dict kwds): """ Return the key in the cache to be used when ``args`` and @@ -823,12 +840,12 @@ cdef class CachedFunction(): TESTS:: - sage: type(hilbert_class_polynomial) + sage: type(hilbert_class_polynomial) # needs sage.schemes - sage: loads(dumps(hilbert_class_polynomial)) is hilbert_class_polynomial #indirect doctest + sage: loads(dumps(hilbert_class_polynomial)) is hilbert_class_polynomial #indirect doctest # needs sage.schemes True """ - return _cached_function_unpickle, (self.__module__, self.__name__, self.cache) + return _cached_function_unpickle, (self.__cached_module__, self.__name__, self.cache) ######### ## Introspection @@ -847,9 +864,9 @@ cdef class CachedFunction(): TESTS:: sage: P. = QQ[] - sage: I = P*[x,y] + sage: I = P * [x,y] sage: from sage.misc.sageinspect import sage_getdoc - sage: print(sage_getdoc(I.groebner_basis)) # indirect doctest + sage: print(sage_getdoc(I.groebner_basis)) # indirect doctest WARNING: the enclosing module is marked... Return the reduced Groebner basis of this ideal. ... @@ -897,8 +914,8 @@ cdef class CachedFunction(): TESTS:: sage: from sage.misc.sageinspect import sage_getsource - sage: g = CachedFunction(number_of_partitions) - sage: 'flint' in sage_getsource(g) # indirect doctest + sage: g = CachedFunction(number_of_partitions) # needs sage.combinat + sage: 'flint' in sage_getsource(g) # indirect doctest # needs sage.combinat True """ @@ -916,7 +933,7 @@ cdef class CachedFunction(): sage: I = P*[x,y] sage: from sage.misc.sageinspect import sage_getsourcelines sage: l = ' elif algorithm.startswith("macaulay2:"):\n' - sage: l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest + sage: l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest True """ @@ -949,6 +966,7 @@ cdef class CachedFunction(): TESTS:: + sage: # needs sage.combinat sage.libs.flint sage: g = CachedFunction(number_of_partitions) sage: a = g(5) sage: g.cache @@ -965,18 +983,19 @@ cdef class CachedFunction(): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: + sage: # needs sage.rings.padics sage: @cached_function ....: def f(x): return x+x - sage: K. = Qq(4) # optional - sage.rings.padics - sage: x = K(1,1); x # optional - sage.rings.padics + sage: K. = Qq(4) + sage: x = K(1,1); x 1 + O(2) - sage: y = K(1,2); y # optional - sage.rings.padics + sage: y = K(1,2); y 1 + O(2^2) - sage: x == y # optional - sage.rings.padics + sage: x == y True - sage: f(x) is f(x) # optional - sage.rings.padics + sage: f(x) is f(x) True - sage: f(y) is not f(x) # optional - sage.rings.padics + sage: f(y) is not f(x) True """ @@ -1046,16 +1065,17 @@ cdef class CachedFunction(): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: + sage: # needs sage.rings.padics sage: @cached_function ....: def f(x): return x - sage: K. = Qq(4) # optional - sage.rings.padics - sage: x = K(1,1); x # optional - sage.rings.padics + sage: K. = Qq(4) + sage: x = K(1,1); x 1 + O(2) - sage: f.is_in_cache(x) # optional - sage.rings.padics + sage: f.is_in_cache(x) False - sage: f(x) # optional - sage.rings.padics + sage: f(x) 1 + O(2) - sage: f.is_in_cache(x) # optional - sage.rings.padics + sage: f.is_in_cache(x) True """ @@ -1074,6 +1094,7 @@ cdef class CachedFunction(): EXAMPLES:: + sage: # needs sage.combinat sage.libs.flint sage: g = CachedFunction(number_of_partitions) sage: a = g(5) sage: g.cache @@ -1090,13 +1111,14 @@ cdef class CachedFunction(): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: + sage: # needs sage.rings.padics sage: @cached_function ....: def f(x): return x - sage: K. = Qq(4) # optional - sage.rings.padics - sage: x = K(1,1); x # optional - sage.rings.padics + sage: K. = Qq(4) + sage: x = K(1,1); x 1 + O(2) - sage: f.set_cache(x, x) # optional - sage.rings.padics - sage: f.is_in_cache(x) # optional - sage.rings.padics + sage: f.set_cache(x, x) + sage: f.is_in_cache(x) True DEVELOPER NOTE: @@ -1175,8 +1197,8 @@ cdef class CachedFunction(): """ EXAMPLES:: - sage: g = CachedFunction(number_of_partitions) - sage: g # indirect doctest + sage: g = CachedFunction(number_of_partitions) # needs sage.combinat + sage: g # indirect doctest # needs sage.combinat Cached version of """ try: @@ -1190,9 +1212,10 @@ cdef class CachedFunction(): EXAMPLES:: + sage: # needs sage.combinat sage: g = CachedFunction(number_of_partitions) - sage: a = g(5) - sage: g.cache + sage: a = g(5) # needs sage.libs.flint + sage: g.cache # needs sage.libs.flint {((5, 'default'), ()): 7} sage: g.clear_cache() sage: g.cache @@ -1315,20 +1338,21 @@ cdef class WeakCachedFunction(CachedFunction): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: + sage: # needs sage.rings.padics sage: from sage.misc.cachefunc import weak_cached_function sage: @weak_cached_function ....: def f(x): return x+x - sage: K. = Qq(4) # optional - sage.rings.padics - sage: R. = K[] # optional - sage.rings.padics - sage: x = t + K(1,1); x # optional - sage.rings.padics + sage: K. = Qq(4) + sage: R. = K[] + sage: x = t + K(1,1); x (1 + O(2^20))*t + 1 + O(2) - sage: y = t + K(1,2); y # optional - sage.rings.padics + sage: y = t + K(1,2); y (1 + O(2^20))*t + 1 + O(2^2) - sage: x == y # optional - sage.rings.padics + sage: x == y True - sage: f(x) is f(x) # optional - sage.rings.padics + sage: f(x) is f(x) True - sage: f(y) is not f(x) # optional - sage.rings.padics + sage: f(y) is not f(x) True Examples and tests for ``is_in_cache``:: @@ -1359,16 +1383,17 @@ cdef class WeakCachedFunction(CachedFunction): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: + sage: # needs sage.rings.padics sage: from sage.misc.cachefunc import weak_cached_function sage: @weak_cached_function ....: def f(x): return x - sage: K. = Qq(4) # optional - sage.rings.padics - sage: R. = K[] # optional - sage.rings.padics - sage: f.is_in_cache(t) # optional - sage.rings.padics + sage: K. = Qq(4) + sage: R. = K[] + sage: f.is_in_cache(t) False - sage: f(t) # optional - sage.rings.padics + sage: f(t) (1 + O(2^20))*t - sage: f.is_in_cache(t) # optional - sage.rings.padics + sage: f.is_in_cache(t) True Examples and tests for ``set_cache``:: @@ -1385,13 +1410,14 @@ cdef class WeakCachedFunction(CachedFunction): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: + sage: # needs sage.rings.padics sage: from sage.misc.cachefunc import weak_cached_function sage: @weak_cached_function ....: def f(x): return x - sage: K. = Qq(4) # optional - sage.rings.padics - sage: R. = K[] # optional - sage.rings.padics - sage: f.set_cache(t,t) # optional - sage.rings.padics - sage: f.is_in_cache(t) # optional - sage.rings.padics + sage: K. = Qq(4) + sage: R. = K[] + sage: f.set_cache(t,t) + sage: f.is_in_cache(t) True """ def __init__(self, f, *, classmethod=False, name=None, key=None, **kwds): @@ -1445,8 +1471,8 @@ class CachedMethodPickle(): EXAMPLES:: sage: R. = PolynomialRing(QQ, 3) - sage: I = R*(x^3 + y^3 + z^3,x^4-y^4) - sage: I.groebner_basis() + sage: I = R * (x^3 + y^3 + z^3, x^4 - y^4) + sage: I.groebner_basis() # needs sage.libs.singular [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6, x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6, x*y^3 + y^4 + x*z^3, x^3 + y^3 + z^3] @@ -1464,11 +1490,11 @@ class CachedMethodPickle(): placeholder, it replaces itself by the cached method, and the entries of the cache are actually preserved:: - sage: J.groebner_basis.is_in_cache() + sage: J.groebner_basis.is_in_cache() # needs sage.libs.singular True sage: J.groebner_basis Cached version of - sage: J.groebner_basis() == I.groebner_basis() + sage: J.groebner_basis() == I.groebner_basis() # needs sage.libs.singular True TESTS: @@ -1547,10 +1573,10 @@ class CachedMethodPickle(): TESTS:: sage: R. = PolynomialRing(QQ, 3) - sage: I = R*(x^3 + y^3 + z^3,x^4-y^4) - sage: G = I.groebner_basis() + sage: I = R * (x^3 + y^3 + z^3, x^4 - y^4) + sage: G = I.groebner_basis() # needs sage.libs.singular sage: J = loads(dumps(I)) - sage: J.groebner_basis #indirect doctest + sage: J.groebner_basis # indirect doctest Pickle of the cached method "groebner_basis" """ return 'Pickle of the cached method "{}"'.format(self._name) @@ -1563,8 +1589,8 @@ class CachedMethodPickle(): TESTS:: sage: R. = PolynomialRing(QQ, 3) - sage: I = R*(x^3 + y^3 + z^3,x^4-y^4) - sage: I.groebner_basis() + sage: I = R * (x^3 + y^3 + z^3, x^4 - y^4) + sage: I.groebner_basis() # needs sage.libs.singular [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6, x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6, x*y^3 + y^4 + x*z^3, x^3 + y^3 + z^3] @@ -1578,7 +1604,7 @@ class CachedMethodPickle(): sage: K = loads(dumps(J)) # indirect doctest sage: K.groebner_basis Pickle of the cached method "groebner_basis" - sage: K.groebner_basis.cache + sage: K.groebner_basis.cache # needs sage.libs.singular {(('', None, None, False), ()): [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6, x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6, @@ -1623,8 +1649,8 @@ class CachedMethodPickle(): TESTS:: sage: R. = PolynomialRing(QQ, 3) - sage: I = R*(x^3 + y^3 + z^3,x^4-y^4) - sage: G = I.groebner_basis() + sage: I = R * (x^3 + y^3 + z^3, x^4 - y^4) + sage: G = I.groebner_basis() # needs sage.libs.singular sage: J = loads(dumps(I)) sage: J.groebner_basis Pickle of the cached method "groebner_basis" @@ -1641,7 +1667,7 @@ class CachedMethodPickle(): In that way, the unpickling of the cached method is finally accomplished:: - sage: J.groebner_basis.is_in_cache() #indirect doctest + sage: J.groebner_basis.is_in_cache() # indirect doctest # needs sage.libs.singular True sage: J.groebner_basis Cached version of @@ -1757,12 +1783,12 @@ cdef class CachedMethodCaller(CachedFunction): TESTS:: sage: R. = PolynomialRing(QQ, 3) - sage: I = R*(x^3 + y^3 + z^3,x^4-y^4) - sage: G = I.groebner_basis() - sage: J = loads(dumps(I)) #indirect doctest + sage: I = R * (x^3 + y^3 + z^3, x^4 - y^4) + sage: G = I.groebner_basis() # needs sage.libs.singular + sage: J = loads(dumps(I)) # indirect doctest sage: J.groebner_basis Pickle of the cached method "groebner_basis" - sage: J.groebner_basis.is_in_cache() + sage: J.groebner_basis.is_in_cache() # needs sage.libs.singular True sage: J.groebner_basis Cached version of @@ -1779,12 +1805,12 @@ cdef class CachedMethodCaller(CachedFunction): EXAMPLES:: sage: P. = QQ[] - sage: I = P*[a,b] - sage: I.groebner_basis() + sage: I = P * [a, b] + sage: I.groebner_basis() # needs sage.libs.singular [a, b] - sage: I.groebner_basis._instance_call() is I.groebner_basis() + sage: I.groebner_basis._instance_call() is I.groebner_basis() # needs sage.libs.singular False - sage: I.groebner_basis._instance_call() == I.groebner_basis() + sage: I.groebner_basis._instance_call() == I.groebner_basis() # needs sage.libs.singular True :: @@ -1903,20 +1929,21 @@ cdef class CachedMethodCaller(CachedFunction): immutable unhashable objects which define :meth:`sage.structure.sage_object.SageObject._cache_key`:: - sage: K. = Qq(4) # optional - sage.rings.padics + sage: # needs sage.rings.padics + sage: K. = Qq(4) sage: class A(): ....: @cached_method ....: def f(self, x): return x+x sage: a = A() - sage: x = K(1,1); x # optional - sage.rings.padics + sage: x = K(1,1); x 1 + O(2) - sage: y = K(1,2); y # optional - sage.rings.padics + sage: y = K(1,2); y 1 + O(2^2) - sage: x == y # optional - sage.rings.padics + sage: x == y True - sage: a.f(x) is a.f(x) # optional - sage.rings.padics + sage: a.f(x) is a.f(x) True - sage: a.f(y) is not a.f(x) # optional - sage.rings.padics + sage: a.f(y) is not a.f(x) True """ @@ -1996,7 +2023,7 @@ cdef class CachedMethodCaller(CachedFunction): This getter attempts to assign a bound method as an attribute to the given instance. If this is not possible (for example, for some extension classes), - it is attempted to find an attribute ``__cached_methods``, + it is attempted to find an attribute ``_cached_methods``, and store/retrieve the bound method there. In that way, cached methods can be implemented for extension classes deriving from :class:`~sage.structure.parent.Parent` @@ -2062,7 +2089,7 @@ cdef class CachedMethodCaller(CachedFunction): """ # This is for Parents or Elements that do not allow attribute assignment try: - return (inst.__cached_methods)[self._cachedmethod._cachedfunc.__name__] + return (inst._cached_methods)[self._cachedmethod._cachedfunc.__name__] except (AttributeError, TypeError, KeyError): pass @@ -2077,10 +2104,10 @@ cdef class CachedMethodCaller(CachedFunction): except AttributeError: pass try: - if inst.__cached_methods is None: - inst.__cached_methods = {self._cachedmethod._cachedfunc.__name__ : Caller} + if inst._cached_methods is None: + inst._cached_methods = {self._cachedmethod._cachedfunc.__name__ : Caller} else: - (inst.__cached_methods)[self._cachedmethod._cachedfunc.__name__] = Caller + (inst._cached_methods)[self._cachedmethod._cachedfunc.__name__] = Caller except AttributeError: pass return Caller @@ -2255,7 +2282,7 @@ cdef class CachedMethodCallerNoArgs(CachedFunction): sage: J = loads(dumps(I)) sage: J.gens Pickle of the cached method "gens" - sage: J.gens.cache # the cache is dropped because gens is not marked with do_pickle=True + sage: J.gens.cache # the cache is dropped because gens is not marked with do_pickle=True sage: J.gens Cached version of """ @@ -2398,7 +2425,7 @@ cdef class CachedMethodCallerNoArgs(CachedFunction): This getter attempts to assign a bound method as an attribute to the given instance. If this is not possible (for example, for some extension classes), - it is attempted to find an attribute ``__cached_methods``, + it is attempted to find an attribute ``_cached_methods``, and store/retrieve the bound method there. In that way, cached methods can be implemented for extension classes deriving from :class:`~sage.structure.parent.Parent` @@ -2449,7 +2476,7 @@ cdef class CachedMethodCallerNoArgs(CachedFunction): """ # This is for Parents or Elements that do not allow attribute assignment try: - return (inst.__cached_methods)[self.__name__] + return (inst._cached_methods)[self.__name__] except (AttributeError, TypeError, KeyError): pass Caller = CachedMethodCallerNoArgs(inst, self.f, name=self.__name__, do_pickle=self.do_pickle) @@ -2459,10 +2486,10 @@ cdef class CachedMethodCallerNoArgs(CachedFunction): except AttributeError: pass try: - if inst.__cached_methods is None: - inst.__cached_methods = {self.__name__ : Caller} + if inst._cached_methods is None: + inst._cached_methods = {self.__name__ : Caller} else: - (inst.__cached_methods)[self.__name__] = Caller + (inst._cached_methods)[self.__name__] = Caller except AttributeError: pass return Caller @@ -2675,7 +2702,11 @@ cdef class CachedMethod(): self._cache_name = '_cache__' + (name or f.__name__) self._cachedfunc = CachedFunction(f, classmethod=True, name=name, key=key, do_pickle=do_pickle) self.__name__ = self._cachedfunc.__name__ - self.__module__ = self._cachedfunc.__module__ + self.__cached_module__ = self._cachedfunc.__module__ + + @property + def __module__(self): + return self.__cached_module__ def __call__(self, inst, *args, **kwds): """ @@ -2805,7 +2836,7 @@ cdef class CachedMethod(): except AttributeError: name = self.__name__ try: - return (inst.__cached_methods)[name] + return (inst._cached_methods)[name] except (AttributeError, TypeError, KeyError): pass # Apparently we need to construct the caller. @@ -2817,8 +2848,6 @@ cdef class CachedMethod(): try: if METH_NOARGS&PyCFunction_GetFlags(f.__get__(inst,cls)): self.nargs = 1 - else: - self.nargs = 2 except Exception: pass if self.nargs == 0: @@ -2841,10 +2870,10 @@ cdef class CachedMethod(): except AttributeError: pass try: - if inst.__cached_methods is None: - inst.__cached_methods = {name : Caller} + if inst._cached_methods is None: + inst._cached_methods = {name : Caller} else: - (inst.__cached_methods)[name] = Caller + (inst._cached_methods)[name] = Caller except AttributeError: pass return Caller @@ -2942,12 +2971,12 @@ cdef class CachedSpecialMethod(CachedMethod): D = inst.__dict__ except (TypeError, AttributeError): try: - D = inst.__cached_methods + D = inst._cached_methods except (TypeError, AttributeError): - raise TypeError("For a cached special method, either attribute assignment or a public '__cached_methods' attribute of type is needed") + raise TypeError("For a cached special method, either attribute assignment or a public '_cached_methods' attribute of type is needed") if D is None: - # This can only happen in the case of __cached_methods - D = inst.__cached_methods = {} + # This can only happen in the case of _cached_methods + D = inst._cached_methods = {} else: try: return D[name] @@ -3058,7 +3087,7 @@ def cached_method(f, name=None, key=None, do_pickle=None): sage: import __main__ sage: __main__.C = C sage: c = C() - sage: hash(c) # random output + sage: hash(c) # random output sage: d = loads(dumps(c)) sage: hash(d) == hash(c) True @@ -3073,7 +3102,7 @@ def cached_method(f, name=None, key=None, do_pickle=None): sage: __main__.C = C sage: c = C() - sage: hash(c) # random output + sage: hash(c) # random output sage: d = loads(dumps(c)) sage: hash(d) == hash(c) False @@ -3256,7 +3285,7 @@ cdef class CachedInParentMethod(CachedMethod): sage: c = Foo(3) sage: c.f() 27 - sage: c.f.cache is a.f.cache #indirect doctest + sage: c.f.cache is a.f.cache #indirect doctest True Note that the cache is also available as an @@ -3275,13 +3304,13 @@ cdef class CachedInParentMethod(CachedMethod): return P.__dict__.setdefault(self._cache_name, default) except AttributeError: pass - if not hasattr(P,'__cached_methods'): + if not hasattr(P,'_cached_methods'): raise TypeError("The parent of this element does not allow attribute assignment\n" + " and does not descend from the Parent base class.\n" + " Cannot use CachedInParentMethod.") - if P.__cached_methods is None: - P.__cached_methods = {} - return (P.__cached_methods).setdefault(self._cache_name, default) + if P._cached_methods is None: + P._cached_methods = {} + return (P._cached_methods).setdefault(self._cache_name, default) def __get__(self, inst, cls): """ @@ -3671,11 +3700,11 @@ class disk_cached_function: sage: dir = tmp_dir() sage: @disk_cached_function(dir) ....: def foo(x): return next_prime(2^x)%x - sage: x = foo(200);x + sage: x = foo(200); x # needs sage.libs.pari 11 sage: @disk_cached_function(dir) ....: def foo(x): return 1/x - sage: foo(200) + sage: foo(200) # needs sage.libs.pari 11 sage: foo.clear_cache() sage: foo(200) @@ -3688,12 +3717,12 @@ class disk_cached_function: sage: dir = tmp_dir() sage: @disk_cached_function(dir, memory_cache=True) ....: def foo(x): return next_prime(2^x) - sage: x = foo(200) - sage: x is foo(200) + sage: x = foo(200) # needs sage.libs.pari + sage: x is foo(200) # needs sage.libs.pari True sage: @disk_cached_function(dir, memory_cache=False) ....: def foo(x): return next_prime(2^x) - sage: x is foo(200) + sage: x is foo(200) # needs sage.libs.pari False """ self._dir = dir @@ -3707,7 +3736,7 @@ class disk_cached_function: sage: dir = tmp_dir() sage: @disk_cached_function(dir) ....: def foo(x): return ModularSymbols(x) - sage: foo(389) # optional - sage.modular + sage: foo(389) # needs sage.modular Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field """ diff --git a/src/sage/misc/call.py b/src/sage/misc/call.py index ddb48610e59..966ee34514b 100644 --- a/src/sage/misc/call.py +++ b/src/sage/misc/call.py @@ -40,11 +40,11 @@ def __call__(self, x, *args): EXAMPLES:: sage: core = attrcall('core', 3) - sage: core(Partition([4,2])) + sage: core(Partition([4,2])) # needs sage.combinat [4, 2] - sage: series = attrcall('series', x) - sage: series(sin(x), 4) + sage: series = attrcall('series', x) # needs sage.symbolic + sage: series(sin(x), 4) # needs sage.symbolic 1*x + (-1/6)*x^3 + Order(x^4) """ return getattr(x, self.name)(*(self.args + args), **self.kwds) @@ -159,7 +159,7 @@ def attrcall(name, *args, **kwds): sage: f = attrcall('core', 3); f *.core(3) - sage: [f(p) for p in Partitions(5)] + sage: [f(p) for p in Partitions(5)] # needs sage.combinat [[2], [1, 1], [1, 1], [3, 1, 1], [2], [2], [1, 1]] """ return AttrCallObject(name, args, kwds) @@ -181,5 +181,6 @@ def call_method(obj, name, *args, **kwds): """ return getattr(obj, name)(*args, **kwds) + from sage.misc.persist import register_unpickle_override register_unpickle_override("sage.misc.misc", "call_method", call_method) diff --git a/src/sage/misc/citation.pyx b/src/sage/misc/citation.pyx index a7cf5bef678..9377ce73636 100644 --- a/src/sage/misc/citation.pyx +++ b/src/sage/misc/citation.pyx @@ -71,9 +71,9 @@ def get_systems(cmd): sage: from sage.misc.citation import get_systems sage: get_systems('print("hello")') # random (may print warning) [] - sage: integrate(x^2, x) # Priming coercion model + sage: integrate(x^2, x) # Priming coercion model # needs sage.symbolic 1/3*x^3 - sage: get_systems('integrate(x^2, x)') + sage: get_systems('integrate(x^2, x)') # needs sage.symbolic ['Maxima', 'ginac'] sage: R. = QQ[] sage: I = R.ideal(x^2+y^2, z^2+y) diff --git a/src/sage/misc/classcall_metaclass.pyx b/src/sage/misc/classcall_metaclass.pyx index 191534f76ee..65351cb2756 100644 --- a/src/sage/misc/classcall_metaclass.pyx +++ b/src/sage/misc/classcall_metaclass.pyx @@ -79,7 +79,7 @@ cdef class ClasscallMetaclass(NestedClassMetaclass): TESTS:: - sage: PerfectMatchings(2).list() + sage: PerfectMatchings(2).list() # needs sage.combinat [[(1, 2)]] .. NOTE:: @@ -271,12 +271,12 @@ cdef class ClasscallMetaclass(NestedClassMetaclass): The benefit, compared with using a wrapper function, is that the user interface has a single handle for the class:: - sage: x = Partition([3,2,2]) - sage: isinstance(x, Partition) # todo: not implemented + sage: x = Partition([3,2,2]) # needs sage.combinat + sage: isinstance(x, Partition) # not implemented # needs sage.combinat instead of:: - sage: isinstance(x, sage.combinat.partition.Partition) + sage: isinstance(x, sage.combinat.partition.Partition) # needs sage.combinat True Another difference is that ``__classcall__`` is inherited by diff --git a/src/sage/misc/compat.py b/src/sage/misc/compat.py index d6e5adb431b..4ad6d3fe5ef 100644 --- a/src/sage/misc/compat.py +++ b/src/sage/misc/compat.py @@ -93,7 +93,7 @@ def find_library(name): EXAMPLES:: sage: from sage.misc.compat import find_library - sage: find_library('giac') + sage: find_library('giac') # needs sage.libs.giac '...giac...' """ diff --git a/src/sage/misc/converting_dict.py b/src/sage/misc/converting_dict.py index 7476555e210..39f66c9295a 100644 --- a/src/sage/misc/converting_dict.py +++ b/src/sage/misc/converting_dict.py @@ -26,8 +26,9 @@ This is used e.g. in the result of a variety, to allow access to the result no matter how a generator is identified:: + sage: # needs sage.rings.number_field sage: K. = QQ[] - sage: I = ideal([x^2+2*y-5,x+y+3]) + sage: I = ideal([x^2 + 2*y - 5, x + y + 3]) sage: V = sorted(I.variety(AA), key=str) sage: v = V[0] sage: v['x'], v['y'] diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index fea06f8a333..5f83f585c3a 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.misc.cython +# sage.doctest: needs sage.misc.cython """ Cython support functions @@ -646,9 +646,9 @@ def compile_and_load(code, **kwds): ....: cdef Polynomial_rational_flint res = f._new() ....: cdef unsigned long k ....: cdef Rational z = Rational(0) - ....: for k in range(fmpq_poly_length(f.__poly)): - ....: fmpq_poly_get_coeff_mpq(z.value, f.__poly, k) - ....: fmpq_poly_set_coeff_mpq(res.__poly, n*k, z.value) + ....: for k in range(fmpq_poly_length(f._poly)): + ....: fmpq_poly_get_coeff_mpq(z.value, f._poly, k) + ....: fmpq_poly_set_coeff_mpq(res._poly, n*k, z.value) ....: return res ....: ''' sage: module = compile_and_load(code) # long time diff --git a/src/sage/misc/decorators.py b/src/sage/misc/decorators.py index ef22aebb242..a13f1523c74 100644 --- a/src/sage/misc/decorators.py +++ b/src/sage/misc/decorators.py @@ -67,7 +67,7 @@ def sage_wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): ....: return x sage: g(2) 4 - sage: g(x) + sage: g(x) # needs sage.symbolic x^2 sage: g.__doc__ 'My little function' @@ -104,7 +104,7 @@ def sage_wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): sage: I = P*[x,y] sage: sage_getfile(I.interreduced_basis) # known bug '.../sage/rings/polynomial/multi_polynomial_ideal.py' - sage: sage_getsourcelines(I.interreduced_basis) + sage: sage_getsourcelines(I.interreduced_basis) # needs sage.libs.singular ([' @handle_AA_and_QQbar\n', ' @singular_gb_standard_options\n', ' @libsingular_gb_standard_options\n', @@ -151,7 +151,7 @@ def sage_wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): ....: return new_f sage: f = lambda x:x^2 sage: g = square(f) - sage: g(3) # this line used to fail for some people if these command were manually entered on the sage prompt + sage: g(3) # this line used to fail for some people if these command were manually entered on the sage prompt 81 """ @@ -192,13 +192,14 @@ class infix_operator(): ....: def dot(a, b): ....: '''Dot product.''' ....: return a.dot_product(b) - sage: u = vector([1, 2, 3]) - sage: v = vector([5, 4, 3]) - sage: u *dot* v + sage: u = vector([1, 2, 3]) # needs sage.modules + sage: v = vector([5, 4, 3]) # needs sage.modules + sage: u *dot* v # needs sage.modules 22 An infix element-wise addition operator:: + sage: # needs sage.modules sage: @infix_operator('add') ....: def eadd(a, b): ....: return a.parent([i + j for i, j in zip(a, b)]) @@ -214,7 +215,7 @@ class infix_operator(): sage: @infix_operator('or') ....: def thendo(a, b): ....: return b(a) - sage: x |thendo| cos |thendo| (lambda x: x^2) + sage: x |thendo| cos |thendo| (lambda x: x^2) # needs sage.symbolic cos(x)^2 """ diff --git a/src/sage/misc/derivative.pyx b/src/sage/misc/derivative.pyx index 45ee7a918c5..9788e82e06e 100644 --- a/src/sage/misc/derivative.pyx +++ b/src/sage/misc/derivative.pyx @@ -91,20 +91,20 @@ def derivative_parse(args): EXAMPLES:: - sage: x = var("x") - sage: y = var("y") + sage: x = var("x") # needs sage.symbolic + sage: y = var("y") # needs sage.symbolic sage: from sage.misc.derivative import derivative_parse Differentiate twice with respect to x, then once with respect to y, then once with respect to x:: - sage: derivative_parse([x, 2, y, x]) + sage: derivative_parse([x, 2, y, x]) # needs sage.symbolic [x, x, y, x] Differentiate twice with respect to x, then twice with respect to the 'default variable':: - sage: derivative_parse([x, 2, 2]) + sage: derivative_parse([x, 2, 2]) # needs sage.symbolic [x, x, None, None] Special case with empty input list:: @@ -119,7 +119,7 @@ def derivative_parse(args): Special case with single list argument provided:: - sage: derivative_parse(([x, y], )) + sage: derivative_parse(([x, y], )) # needs sage.symbolic [x, y] If only the count is supplied:: @@ -135,6 +135,7 @@ def derivative_parse(args): Various other cases:: + sage: # needs sage.symbolic sage: derivative_parse([x]) [x] sage: derivative_parse([x, x]) @@ -186,8 +187,8 @@ def multi_derivative(F, args): INPUT: - F -- any object with a _derivative(var) method. - args -- any tuple that can be processed by derivative_parse(). + - ``F`` -- any object with a ``_derivative(var)`` method. + - ``args`` -- any tuple that can be processed by :func:`derivative_parse`. EXAMPLES:: diff --git a/src/sage/misc/dev_tools.py b/src/sage/misc/dev_tools.py index bc127127208..e7bf176592c 100644 --- a/src/sage/misc/dev_tools.py +++ b/src/sage/misc/dev_tools.py @@ -203,15 +203,25 @@ def load_submodules(module=None, exclude_pattern=None): sys.stdout.write("failed\n") -def find_objects_from_name(name, module_name=None): +def find_objects_from_name(name, module_name=None, include_lazy_imports=False): r""" Return the list of objects from ``module_name`` whose name is ``name``. - If ``module_name`` is ``None``, the function runs through all - loaded modules and returns the list of objects whose name matches ``name``. + INPUT: + + - ``name`` -- string + + - ``module_name`` -- string or ``None``: + + - If ``module_name`` is ``None``, the function runs through all + loaded modules and returns the list of objects whose name matches ``name``. - If ``module_name`` is not ``None``, then search only in submodules of - ``module_name``. + - If ``module_name`` is a string, then search only in submodules of + ``module_name``. + + - ``include_lazy_imports`` -- boolean (default: ``False``); whether to + include unresolved lazy imports (i.e., :class:`~sage.misc.lazy_import.LazyImport` + objects) in the output. In order to search through more modules you might use the function :func:`load_submodules`. @@ -219,9 +229,10 @@ def find_objects_from_name(name, module_name=None): EXAMPLES:: sage: import sage.misc.dev_tools as dt - sage: dt.find_objects_from_name('FareySymbol') + sage: dt.find_objects_from_name('FareySymbol') # needs sage.modular [] + sage: # needs sympy sage: import sympy sage: dt.find_objects_from_name('RR') [Real Field with 53 bits of precision, RR] @@ -240,11 +251,22 @@ def find_objects_from_name(name, module_name=None): sage: dt.find_objects_from_name is dt.find_objects_from_name True + When ``include_lazy_imports=True`` is used, several + :class:`~sage.misc.lazy_import.LazyImport` objects that are resolving to the + same object may be included in the output:: + + sage: dt.find_objects_from_name('RR', include_lazy_imports=True) + [Real Field with 53 bits of precision, + ... + Real Field with 53 bits of precision, + RR] + .. NOTE:: It might be a good idea to move this function into :mod:`sage.misc.sageinspect`. """ + from sage.misc.lazy_import import LazyImport obj = [] for smodule_name, smodule in sys.modules.items(): @@ -252,7 +274,7 @@ def find_objects_from_name(name, module_name=None): continue if hasattr(smodule, '__dict__') and name in smodule.__dict__: u = smodule.__dict__[name] - if all(v is not u for v in obj): + if (not isinstance(u, LazyImport) or include_lazy_imports) and all(v is not u for v in obj): obj.append(u) return obj @@ -270,7 +292,7 @@ def find_object_modules(obj): EXAMPLES:: sage: from sage.misc.dev_tools import find_object_modules - sage: find_object_modules(RR) + sage: find_object_modules(RR) # needs sage.rings.real_mpfr {'sage.rings.real_mpfr': ['RR']} sage: find_object_modules(ZZ) {'sage.rings.integer_ring': ['Z', 'ZZ']} @@ -353,7 +375,7 @@ def import_statements(*objects, **kwds): EXAMPLES:: - sage: import_statements(WeylGroup, lazy_attribute) + sage: import_statements(WeylGroup, lazy_attribute) # needs sage.libs.gap from sage.combinat.root_system.weyl_group import WeylGroup from sage.misc.lazy_attribute import lazy_attribute @@ -363,7 +385,7 @@ def import_statements(*objects, **kwds): If ``lazy`` is True, then :func:`lazy_import` statements are displayed instead:: - sage: import_statements(WeylGroup, lazy_attribute, lazy=True) + sage: import_statements(WeylGroup, lazy_attribute, lazy=True) # needs sage.libs.gap from sage.misc.lazy_import import lazy_import lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup') lazy_import('sage.misc.lazy_attribute', 'lazy_attribute') @@ -381,7 +403,7 @@ def import_statements(*objects, **kwds): sage: import_statements(euler_phi) from sage.arith.misc import euler_phi - sage: import_statements(x) + sage: import_statements(x) # needs sage.symbolic from sage.calculus.predefined import x If you don't like the warning you can disable them with the option ``verbose``:: @@ -389,13 +411,13 @@ def import_statements(*objects, **kwds): sage: import_statements(ZZ, verbose=False) from sage.rings.integer_ring import Z - sage: import_statements(x, verbose=False) + sage: import_statements(x, verbose=False) # needs sage.symbolic from sage.calculus.predefined import x If the object has several names, an other way to get the import statement you expect is to use a string instead of the object:: - sage: import_statements(matrix) + sage: import_statements(matrix) # needs sage.modules # ** Warning **: several names for that object: Matrix, matrix from sage.matrix.constructor import Matrix @@ -410,7 +432,7 @@ def import_statements(*objects, **kwds): The strings are allowed to be comma-separated names, and parenthesis are stripped for convenience:: - sage: import_statements('(floor, ceil)') + sage: import_statements('(floor, ceil)') # needs sage.symbolic from sage.functions.other import floor, ceil Specifying a string is also useful for objects that are not @@ -487,9 +509,9 @@ def import_statements(*objects, **kwds): from sage.combinat.partition_algebra import SetPartitionsAk sage: import_statements(CIF) from sage.rings.cif import CIF - sage: import_statements(NaN) + sage: import_statements(NaN) # needs sage.symbolic from sage.symbolic.constants import NaN - sage: import_statements(pi) + sage: import_statements(pi) # needs sage.symbolic from sage.symbolic.constants import pi sage: import_statements('SAGE_ENV') from sage.env import SAGE_ENV @@ -547,10 +569,10 @@ def expand_comma_separated_names(obj): obj = [G[name]] else: # 1.b. object inside a submodule of sage - obj = find_objects_from_name(name, 'sage') + obj = find_objects_from_name(name, 'sage', include_lazy_imports=True) if not obj: # 1.c. object from something already imported - obj = find_objects_from_name(name) + obj = find_objects_from_name(name, include_lazy_imports=True) # remove lazy imported objects from list obj i = 0 diff --git a/src/sage/misc/edit_module.py b/src/sage/misc/edit_module.py index 5c1dfa6d7ae..9b03e7237a0 100644 --- a/src/sage/misc/edit_module.py +++ b/src/sage/misc/edit_module.py @@ -80,7 +80,7 @@ def file_and_line(obj): The following tests against a bug that was fixed in :trac:`11298`:: - sage: edit_module.file_and_line(x) + sage: edit_module.file_and_line(x) # needs sage.symbolic ('...sage/symbolic/expression...pyx', ...) """ # d = inspect.getdoc(obj) diff --git a/src/sage/misc/element_with_label.py b/src/sage/misc/element_with_label.py index 2410851c7de..831b012e31a 100644 --- a/src/sage/misc/element_with_label.py +++ b/src/sage/misc/element_with_label.py @@ -25,13 +25,15 @@ class ElementWithLabel(): EXAMPLES:: + sage: # needs sage.combinat sage.graphs sage: P = Poset({1: [2,3]}) sage: labs = {i: P.rank(i) for i in range(1, 4)} sage: print(labs) {1: 0, 2: 1, 3: 1} - sage: print(P.plot(element_labels=labs)) + sage: print(P.plot(element_labels=labs)) # needs sage.plot Graphics object consisting of 6 graphics primitives + sage: # needs sage.combinat sage.graphs sage.modules sage: from sage.misc.element_with_label import ElementWithLabel sage: W = WeylGroup("A1") sage: P = W.bruhat_poset(facade=True) @@ -65,11 +67,11 @@ def _latex_(self): TESTS:: - sage: var('a_1') + sage: var('a_1') # needs sage.symbolic a_1 sage: from sage.misc.element_with_label import ElementWithLabel - sage: e = ElementWithLabel(1, a_1) - sage: latex(e) + sage: e = ElementWithLabel(1, a_1) # needs sage.symbolic + sage: latex(e) # needs sage.symbolic a_{1} """ return latex(self.label) @@ -81,11 +83,11 @@ def __str__(self): TESTS:: - sage: var('a_1') + sage: var('a_1') # needs sage.symbolic a_1 sage: from sage.misc.element_with_label import ElementWithLabel - sage: e = ElementWithLabel(1, a_1) - sage: str(e) + sage: e = ElementWithLabel(1, a_1) # needs sage.symbolic + sage: str(e) # needs sage.symbolic 'a_1' """ return str(self.label) @@ -97,11 +99,11 @@ def __repr__(self): TESTS:: - sage: var('a_1') + sage: var('a_1') # needs sage.symbolic a_1 sage: from sage.misc.element_with_label import ElementWithLabel - sage: e = ElementWithLabel(1, a_1) - sage: repr(e) + sage: e = ElementWithLabel(1, a_1) # needs sage.symbolic + sage: repr(e) # needs sage.symbolic 'a_1' """ return repr(self.label) diff --git a/src/sage/misc/explain_pickle.py b/src/sage/misc/explain_pickle.py index c8d9e79c0d9..30c3988850b 100644 --- a/src/sage/misc/explain_pickle.py +++ b/src/sage/misc/explain_pickle.py @@ -213,7 +213,7 @@ def explain_pickle(pickle=None, file=None, compress=True, **kwargs): sage: explain_pickle(dumps({('a', 'b'): [1r, 2r]})) {('a', 'b'):[1r, 2r]} - sage: explain_pickle(dumps(RR(pi)), in_current_sage=True) + sage: explain_pickle(dumps(RR(pi)), in_current_sage=True) # needs sage.symbolic from sage.rings.real_mpfr import __create__RealNumber_version0 from sage.rings.real_mpfr import __create__RealField_version0 __create__RealNumber_version0(__create__RealField_version0(53r, False, 'RNDN'), '3.4gvml245kc0@0', 32r) @@ -294,6 +294,7 @@ def explain_pickle_string(pickle, in_current_sage=False, else: return ans + valid_name_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') def name_is_valid(name): r""" @@ -313,6 +314,7 @@ def name_is_valid(name): # Technically, we also need to reject keywords... return bool(valid_name_re.match(name)) + # The pickle interpreter can push and pop "marks" on the stack. # This string is used as the representation of a mark. the_mark = 'mark' @@ -851,7 +853,7 @@ def BINFLOAT(self, f): TESTS:: sage: from sage.misc.explain_pickle import * - sage: test_pickle(float(pi)) + sage: test_pickle(float(pi)) # needs sage.symbolic 0: \x80 PROTO 2 2: G BINFLOAT 3.141592653589793 11: . STOP @@ -3051,6 +3053,7 @@ def __repr__(self): """ return "TestGlobalFunnyName" + TestGlobalFunnyName.__name__ = "funny$name" #This crashed Sphinx. Instead, we manually execute this just before the test. #globals()['funny$name'] = TestGlobalFunnyName diff --git a/src/sage/misc/fast_methods.pyx b/src/sage/misc/fast_methods.pyx index d3fd260f55f..370cefc46a0 100644 --- a/src/sage/misc/fast_methods.pyx +++ b/src/sage/misc/fast_methods.pyx @@ -169,7 +169,7 @@ cdef class WithEqualityById: Check that :trac:`19628` is fixed:: sage: from sage.misc.lazy_import import LazyImport - sage: lazyQQ = LazyImport('sage.all', 'QQ') + sage: lazyQQ = LazyImport('sage.rings.rational_field', 'QQ') sage: PolynomialRing(lazyQQ, 'ijk') is PolynomialRing(QQ, 'ijk') True sage: PolynomialRing(QQ, 'ijkl') is PolynomialRing(lazyQQ, 'ijkl') diff --git a/src/sage/misc/flatten.py b/src/sage/misc/flatten.py index 8b8a7ce54b2..5ebc8c2ceaa 100644 --- a/src/sage/misc/flatten.py +++ b/src/sage/misc/flatten.py @@ -35,13 +35,13 @@ def flatten(in_list, ltypes=(list, tuple), max_level=sys.maxsize): In the following example, the vector is not flattened because it is not given in the ``ltypes`` input. :: - sage: flatten((['Hi',2,vector(QQ,[1,2,3])],(4,5,6))) + sage: flatten((['Hi', 2, vector(QQ, [1,2,3])], (4,5,6))) # needs sage.modules ['Hi', 2, (1, 2, 3), 4, 5, 6] We give the vector type and then even the vector gets flattened:: - sage: tV = sage.modules.vector_rational_dense.Vector_rational_dense - sage: flatten((['Hi',2,vector(QQ,[1,2,3])], (4,5,6)), + sage: tV = sage.modules.vector_rational_dense.Vector_rational_dense # needs sage.modules + sage: flatten((['Hi', 2, vector(QQ, [1,2,3])], (4,5,6)), # needs sage.modules ....: ltypes=(list, tuple, tV)) ['Hi', 2, 1, 2, 3, 4, 5, 6] @@ -52,7 +52,7 @@ def flatten(in_list, ltypes=(list, tuple), max_level=sys.maxsize): sage: flatten([GF(5)]) [Finite Field of size 5] sage: tGF = type(GF(5)) - sage: flatten([GF(5)], ltypes = (list, tuple, tGF)) + sage: flatten([GF(5)], ltypes=(list, tuple, tGF)) [0, 1, 2, 3, 4] Degenerate cases:: diff --git a/src/sage/misc/fpickle.pyx b/src/sage/misc/fpickle.pyx index 08212b996f9..37c26e431ba 100644 --- a/src/sage/misc/fpickle.pyx +++ b/src/sage/misc/fpickle.pyx @@ -107,11 +107,13 @@ def unpickle_function(pickled): def call_pickled_function(fpargs): - import sage.all - from sage.misc.fpickle import unpickle_function # used below + try: + import sage.all as toplevel + except ImportError: + import sage.all__sagemath_categories as toplevel (fp, (args, kwds)) = fpargs - f = eval("unpickle_function(fp)", sage.all.__dict__, {'fp': fp}) - res = eval("f(*args, **kwds)", sage.all.__dict__, + f = eval("unpickle_function(fp)", toplevel.__dict__, {'fp': fp}) + res = eval("f(*args, **kwds)", toplevel.__dict__, {'args': args, 'kwds': kwds, 'f': f}) return ((args, kwds), res) @@ -122,10 +124,12 @@ def call_pickled_function(fpargs): def pickleMethod(method): 'support function for copyreg to pickle method refs' - # Note: On Python 3 there is no .im_class but we can get the instance's - # class through .__self__.__class__ - cls = getattr(method, 'im_class', method.__self__.__class__) - return (unpickleMethod, (method.__func__.__name__, method.__self__, cls)) + if isinstance(method.__self__, type): + # This is a class method, so get it from the type directly + return (getattr, (method.__self__, method.__func__.__name__)) + else: + cls = method.__self__.__class__ + return (unpickleMethod, (method.__func__.__name__, method.__self__, cls)) def unpickleMethod(im_name, @@ -137,10 +141,7 @@ def unpickleMethod(im_name, if __self__ is None: return unbound - # Note: On Python 2 "unbound methods" are just functions, so they don't - # have a __func__ - bound = types.MethodType(getattr(unbound, '__func__', unbound), - __self__) + bound = types.MethodType(unbound, __self__) return bound except AttributeError: assert __self__ is not None, "No recourse: no instance to guess from." @@ -148,11 +149,8 @@ def unpickleMethod(im_name, # changed around since we pickled this method, we may still be # able to get it by looking on the instance's current class. unbound = getattr(__self__.__class__, im_name) - if __self__ is None: - return unbound - bound = types.MethodType(getattr(unbound, '__func__', unbound), - __self__) + bound = types.MethodType(unbound, __self__) return bound diff --git a/src/sage/misc/function_mangling.pyx b/src/sage/misc/function_mangling.pyx index e1bb7978953..1392fc4f2fd 100644 --- a/src/sage/misc/function_mangling.pyx +++ b/src/sage/misc/function_mangling.pyx @@ -157,8 +157,7 @@ cdef class ArgumentFixer: EXAMPLES:: sage: from sage.misc.function_mangling import ArgumentFixer - sage: g = ArgumentFixer(number_of_partitions) - sage: g + sage: g = ArgumentFixer(number_of_partitions); g # needs sage.combinat Argument Fixer of """ return "Argument Fixer of %s"%self.f diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py index 8da9d44e5f9..c922b8f6f12 100644 --- a/src/sage/misc/functional.py +++ b/src/sage/misc/functional.py @@ -2,7 +2,7 @@ """ Functional notation -These are functions so that you can write foo(x) instead of x.foo() +These are functions so that you can write ``foo(x)`` instead of ``x.foo()`` in certain common cases. AUTHORS: @@ -23,12 +23,14 @@ import builtins import math -from sage.rings.complex_double import CDF -from sage.rings.real_double import RDF, RealDoubleElement -from sage.rings.integer_ring import ZZ -from sage.rings.integer import Integer +from sage.misc.lazy_import import lazy_import from sage.misc.superseded import deprecation +lazy_import('sage.rings.complex_double', 'CDF') +lazy_import('sage.rings.real_double', ['RDF', 'RealDoubleElement']) +lazy_import('sage.rings.integer_ring', 'ZZ') +lazy_import('sage.rings.integer', 'Integer') + ############################################################################## # There are many functions on elements of a ring, which mathematicians # usually write f(x), e.g., it is weird to write x.log() and natural @@ -102,9 +104,9 @@ def basis(x): EXAMPLES:: - sage: V = VectorSpace(QQ,3) - sage: S = V.subspace([[1,2,0],[2,2,-1]]) - sage: basis(S) + sage: V = VectorSpace(QQ, 3) # needs sage.modules + sage: S = V.subspace([[1,2,0], [2,2,-1]]) # needs sage.modules + sage: basis(S) # needs sage.modules [ (1, 0, -1), (0, 1, 1/2) @@ -119,8 +121,8 @@ def category(x): EXAMPLES:: - sage: V = VectorSpace(QQ,3) - sage: category(V) + sage: V = VectorSpace(QQ, 3) # needs sage.modules + sage: category(V) # needs sage.modules Category of finite dimensional vector spaces with basis over (number fields and quotient fields and metric spaces) """ @@ -137,29 +139,31 @@ def characteristic_polynomial(x, var='x'): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,3) + sage: # needs sage.libs.pari sage.modules + sage: M = MatrixSpace(QQ, 3, 3) sage: A = M([1,2,3,4,5,6,7,8,9]) sage: charpoly(A) x^3 - 15*x^2 - 18*x sage: charpoly(A, 't') t^3 - 15*t^2 - 18*t - sage: k. = GF(7^10); k + sage: k. = GF(7^10); k # needs sage.rings.finite_rings Finite Field in alpha of size 7^10 - sage: alpha.charpoly('T') + sage: alpha.charpoly('T') # needs sage.rings.finite_rings T^10 + T^6 + T^5 + 4*T^4 + T^3 + 2*T^2 + 3*T + 3 - sage: characteristic_polynomial(alpha, 'T') + sage: characteristic_polynomial(alpha, 'T') # needs sage.rings.finite_rings T^10 + T^6 + T^5 + 4*T^4 + T^3 + 2*T^2 + 3*T + 3 Ensure the variable name of the polynomial does not conflict with variables used within the matrix, and that non-integral powers of variables do not confuse the computation (:trac:`14403`):: + sage: # needs sage.libs.pari sage.symbolic sage: y = var('y') - sage: a = matrix([[x,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]) + sage: a = matrix([[x,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]) sage: characteristic_polynomial(a).list() [x, -3*x - 1, 3*x + 3, -x - 3, 1] - sage: b = matrix([[y^(1/2),0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]) + sage: b = matrix([[y^(1/2),0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]) sage: charpoly(b).list() [sqrt(y), -3*sqrt(y) - 1, 3*sqrt(y) + 3, -sqrt(y) - 3, 1] """ @@ -195,6 +199,7 @@ def cyclotomic_polynomial(n, var='x'): EXAMPLES:: + sage: # needs sage.libs.pari sage: cyclotomic_polynomial(3) x^2 + x + 1 sage: cyclotomic_polynomial(4) @@ -215,19 +220,21 @@ def decomposition(x): EXAMPLES:: - sage: M = matrix([[2, 3], [3, 4]]) - sage: M.decomposition() + sage: M = matrix([[2, 3], [3, 4]]) # needs sage.libs.pari sage.modules + sage: M.decomposition() # needs sage.libs.pari sage.modules [ (Ambient free module of rank 2 over the principal ideal domain Integer Ring, True) ] + sage: # needs sage.groups sage: G. = DirichletGroup(20) - sage: c = a*b + 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 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 """ return x.decomposition() @@ -257,9 +264,9 @@ def det(x): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,3) - sage: A = M([1,2,3,4,5,6,7,8,9]) - sage: det(A) + sage: M = MatrixSpace(QQ, 3, 3) # needs sage.modules + sage: A = M([1,2,3, 4,5,6, 7,8,9]) # needs sage.modules + sage: det(A) # needs sage.modules 0 """ return x.det() @@ -271,9 +278,9 @@ def dimension(x): EXAMPLES:: - sage: V = VectorSpace(QQ,3) - sage: S = V.subspace([[1,2,0],[2,2,-1]]) - sage: dimension(S) + sage: V = VectorSpace(QQ, 3) # needs sage.modules + sage: S = V.subspace([[1,2,0], [2,2,-1]]) # needs sage.modules + sage: dimension(S) # needs sage.modules 2 """ return x.dimension() @@ -289,9 +296,9 @@ def discriminant(x): EXAMPLES:: sage: R. = PolynomialRing(QQ) - sage: S = R.quotient(x^29 - 17*x - 1, 'alpha') - sage: K = S.number_field() - sage: discriminant(K) + sage: S = R.quotient(x^29 - 17*x - 1, 'alpha') # needs sage.libs.pari + sage: K = S.number_field() # needs sage.libs.pari sage.rings.number_field + sage: discriminant(K) # needs sage.libs.pari sage.rings.number_field -15975100446626038280218213241591829458737190477345113376757479850566957249523 """ return x.discriminant() @@ -313,7 +320,7 @@ def eta(x): EXAMPLES:: - sage: eta(1+I) + sage: eta(1 + I) # needs sage.symbolic 0.7420487758365647 + 0.1988313702299107*I """ try: @@ -328,9 +335,9 @@ def fcp(x, var='x'): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,3) - sage: A = M([1,2,3,4,5,6,7,8,9]) - sage: fcp(A, 'x') + sage: M = MatrixSpace(QQ, 3, 3) # needs sage.modules + sage: A = M([1,2,3, 4,5,6, 7,8,9]) # needs sage.modules + sage: fcp(A, 'x') # needs sage.libs.pari sage.modules x * (x^2 - 15*x - 18) """ try: @@ -351,8 +358,8 @@ def gen(x): x sage: gen(GF(7)) 1 - sage: A = AbelianGroup(1, [23]) - sage: gen(A) + sage: A = AbelianGroup(1, [23]) # needs sage.groups + sage: gen(A) # needs sage.groups f """ return x.gen() @@ -364,13 +371,14 @@ def gens(x): EXAMPLES:: - sage: R. = SR[] - sage: R + sage: R. = SR[] # needs sage.symbolic + sage: R # needs sage.symbolic Multivariate Polynomial Ring in x, y over Symbolic Ring - sage: gens(R) + sage: gens(R) # needs sage.symbolic (x, y) - sage: A = AbelianGroup(5, [5,5,7,8,9]) - sage: gens(A) + + sage: A = AbelianGroup(5, [5,5,7,8,9]) # needs sage.groups + sage: gens(A) # needs sage.groups (f0, f1, f2, f3, f4) """ return x.gens() @@ -382,9 +390,10 @@ def hecke_operator(x, n): EXAMPLES:: - sage: M = ModularSymbols(1,12) - sage: hecke_operator(M,5) - Hecke operator T_5 on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field + sage: M = ModularSymbols(1,12) # needs sage.modular + sage: hecke_operator(M,5) # needs sage.modular + Hecke operator T_5 on Modular Symbols space of dimension 3 for Gamma_0(1) + of weight 12 with sign 0 over Rational Field """ return x.hecke_operator(n) @@ -395,9 +404,9 @@ def image(x): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,3) - sage: A = M([1,2,3,4,5,6,7,8,9]) - sage: image(A) + sage: M = MatrixSpace(QQ, 3, 3) # needs sage.modules + sage: A = M([1,2,3, 4,5,6, 7,8,9]) # needs sage.modules + sage: image(A) # needs sage.modules Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [ 1 0 -1] @@ -435,18 +444,18 @@ def symbolic_sum(expression, *args, **kwds): EXAMPLES:: - sage: k, n = var('k,n') - sage: sum(k, k, 1, n).factor() + sage: k, n = var('k,n') # needs sage.symbolic + sage: sum(k, k, 1, n).factor() # needs sage.symbolic 1/2*(n + 1)*n :: - sage: sum(1/k^4, k, 1, oo) + sage: sum(1/k^4, k, 1, oo) # needs sage.symbolic 1/90*pi^4 :: - sage: sum(1/k^5, k, 1, oo) + sage: sum(1/k^5, k, 1, oo) # needs sage.symbolic zeta(5) .. WARNING:: @@ -458,9 +467,9 @@ def symbolic_sum(expression, *args, **kwds): In particular, this does not work:: - sage: n = var('n') + sage: n = var('n') # needs sage.symbolic sage: mylist = [1,2,3,4,5] - sage: sum(mylist[n], n, 0, 3) + sage: sum(mylist[n], n, 0, 3) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert n to an integer @@ -472,95 +481,95 @@ def symbolic_sum(expression, *args, **kwds): Also, only a limited number of functions are recognized in symbolic sums:: - sage: sum(valuation(n,2),n,1,5) + sage: sum(valuation(n, 2), n, 1, 5) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert n to an integer Again, use python ``sum()``:: - sage: sum(valuation(n+1,2) for n in range(5)) + sage: sum(valuation(n + 1, 2) for n in range(5)) 3 (now back to the Sage ``sum`` examples) A well known binomial identity:: - sage: sum(binomial(n,k), k, 0, n) + sage: sum(binomial(n, k), k, 0, n) # needs sage.symbolic 2^n The binomial theorem:: - sage: x, y = var('x, y') - sage: sum(binomial(n,k) * x^k * y^(n-k), k, 0, n) + sage: x, y = var('x, y') # needs sage.symbolic + sage: sum(binomial(n, k) * x^k * y^(n-k), k, 0, n) # needs sage.symbolic (x + y)^n :: - sage: sum(k * binomial(n, k), k, 1, n) + sage: sum(k * binomial(n, k), k, 1, n) # needs sage.symbolic 2^(n - 1)*n :: - sage: sum((-1)^k*binomial(n,k), k, 0, n) + sage: sum((-1)^k * binomial(n, k), k, 0, n) # needs sage.symbolic 0 :: - sage: sum(2^(-k)/(k*(k+1)), k, 1, oo) + sage: sum(2^(-k)/(k*(k+1)), k, 1, oo) # needs sage.symbolic -log(2) + 1 Another binomial identity (:trac:`7952`):: - sage: t,k,i = var('t,k,i') - sage: sum(binomial(i+t,t),i,0,k) + sage: t, k, i = var('t,k,i') # needs sage.symbolic + sage: sum(binomial(i + t, t), i, 0, k) # needs sage.symbolic binomial(k + t + 1, t + 1) Summing a hypergeometric term:: - sage: sum(binomial(n, k) * factorial(k) / factorial(n+1+k), k, 0, n) + sage: sum(binomial(n, k) * factorial(k) / factorial(n+1+k), k, 0, n) # needs sage.symbolic 1/2*sqrt(pi)/factorial(n + 1/2) We check a well known identity:: - sage: bool(sum(k^3, k, 1, n) == sum(k, k, 1, n)^2) + sage: bool(sum(k^3, k, 1, n) == sum(k, k, 1, n)^2) # needs sage.symbolic True A geometric sum:: - sage: a, q = var('a, q') - sage: sum(a*q^k, k, 0, n) + sage: a, q = var('a, q') # needs sage.symbolic + sage: sum(a*q^k, k, 0, n) # needs sage.symbolic (a*q^(n + 1) - a)/(q - 1) The geometric series:: - sage: assume(abs(q) < 1) - sage: sum(a*q^k, k, 0, oo) + sage: assume(abs(q) < 1) # needs sage.symbolic + sage: sum(a * q^k, k, 0, oo) # needs sage.symbolic -a/(q - 1) A divergent geometric series. Don't forget to forget your assumptions:: - sage: forget() - sage: assume(q > 1) - sage: sum(a*q^k, k, 0, oo) + sage: forget() # needs sage.symbolic + sage: assume(q > 1) # needs sage.symbolic + sage: sum(a * q^k, k, 0, oo) # needs sage.symbolic Traceback (most recent call last): ... ValueError: Sum is divergent. This summation only Mathematica can perform:: - sage: sum(1/(1+k^2), k, -oo, oo, algorithm = 'mathematica') # optional - mathematica + sage: sum(1/(1+k^2), k, -oo, oo, algorithm='mathematica') # optional - mathematica, needs sage.symbolic pi*coth(pi) Use Maple as a backend for summation:: - sage: sum(binomial(n,k)*x^k, k, 0, n, algorithm = 'maple') # optional - maple + sage: sum(binomial(n, k) * x^k, k, 0, n, algorithm='maple') # optional - maple, needs sage.symbolic (x + 1)^n Python ints should work as limits of summation (:trac:`9393`):: - sage: sum(x, x, 1r, 5r) + sage: sum(x, x, 1r, 5r) # needs sage.symbolic 15 .. note:: @@ -573,9 +582,9 @@ def symbolic_sum(expression, *args, **kwds): Check that :trac:`34007` is fixed:: - sage: sum([1,2], start=1) + sage: sum([1, 2], start=1) 4 - sage: sum([[1],[2]], start=[]) + sage: sum([[1], [2]], start=[]) [1, 2] """ @@ -615,8 +624,9 @@ def symbolic_prod(expression, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: i, k, n = var('i,k,n') - sage: product(k,k,1,n) + sage: product(k, k, 1, n) factorial(n) sage: product(x + i*(i+1)/2, i, 1, 4) x^4 + 20*x^3 + 127*x^2 + 288*x + 180 @@ -628,7 +638,7 @@ def symbolic_prod(expression, *args, **kwds): sage: product(f(i), i, 1, n) product(f(i), i, 1, n) sage: assume(k>0) - sage: product(integrate (x^k, x, 0, 1), k, 1, n) + sage: product(integrate(x^k, x, 0, 1), k, 1, n) 1/factorial(n + 1) sage: product(f(i), i, 1, n).log().log_expand() sum(log(f(i)), i, 1, n) @@ -663,38 +673,38 @@ def integral(x, *args, **kwds): :: - sage: integral(sin(x),x) + sage: integral(sin(x), x) # needs sage.symbolic -cos(x) :: - sage: y = var('y') - sage: integral(sin(x),y) + sage: y = var('y') # needs sage.symbolic + sage: integral(sin(x), y) # needs sage.symbolic y*sin(x) :: - sage: integral(sin(x), x, 0, pi/2) + sage: integral(sin(x), x, 0, pi/2) # needs sage.symbolic 1 - sage: sin(x).integral(x, 0,pi/2) + sage: sin(x).integral(x, 0, pi/2) # needs sage.symbolic 1 - sage: integral(exp(-x), (x, 1, oo)) + sage: integral(exp(-x), (x, 1, oo)) # needs sage.symbolic e^(-1) Numerical approximation:: - sage: h = integral(tan(x)/x, (x, 1, pi/3)) + sage: h = integral(tan(x)/x, (x, 1, pi/3)) # needs sage.symbolic ... - sage: h + sage: h # needs sage.symbolic integrate(tan(x)/x, x, 1, 1/3*pi) - sage: h.n() + sage: h.n() # needs sage.symbolic 0.07571599101... Specific algorithm can be used for integration:: - sage: integral(sin(x)^2, x, algorithm='maxima') + sage: integral(sin(x)^2, x, algorithm='maxima') # needs sage.symbolic 1/2*x - 1/4*sin(2*x) - sage: integral(sin(x)^2, x, algorithm='sympy') + sage: integral(sin(x)^2, x, algorithm='sympy') # needs sage.symbolic -1/2*cos(x)*sin(x) + 1/2*x TESTS: @@ -702,8 +712,8 @@ def integral(x, *args, **kwds): A symbolic integral from :trac:`11445` that was incorrect in earlier versions of Maxima:: - sage: f = abs(x - 1) + abs(x + 1) - 2*abs(x) - sage: integrate(f, (x, -Infinity, Infinity)) + sage: f = abs(x - 1) + abs(x + 1) - 2*abs(x) # needs sage.symbolic + sage: integrate(f, (x, -Infinity, Infinity)) # needs sage.symbolic 2 Another symbolic integral, from :trac:`11238`, that used to return @@ -714,58 +724,66 @@ def integral(x, *args, **kwds): with the default settings, so we temporarily use the Maxima setting ``domain: real``:: + sage: # needs sage.symbolic sage: sage.calculus.calculus.maxima('domain: real') real sage: f = exp(-x) * sinh(sqrt(x)) - sage: t = integrate(f, x, 0, Infinity); t # long time - 1/4*sqrt(pi)*(erf(1) - 1)*e^(1/4) - 1/4*(sqrt(pi)*(erf(1) - 1) - sqrt(pi) + 2*e^(-1) - 2)*e^(1/4) + 1/4*sqrt(pi)*e^(1/4) - 1/2*e^(1/4) + 1/2*e^(-3/4) - sage: t.canonicalize_radical() # long time + sage: t = integrate(f, x, 0, Infinity); t # long time + 1/4*sqrt(pi)*(erf(1) - 1)*e^(1/4) + - 1/4*(sqrt(pi)*(erf(1) - 1) - sqrt(pi) + 2*e^(-1) - 2)*e^(1/4) + + 1/4*sqrt(pi)*e^(1/4) - 1/2*e^(1/4) + 1/2*e^(-3/4) + sage: t.canonicalize_radical() # long time 1/2*sqrt(pi)*e^(1/4) sage: sage.calculus.calculus.maxima('domain: complex') complex An integral which used to return -1 before maxima 5.28. See :trac:`12842`:: - sage: f = e^(-2*x)/sqrt(1-e^(-2*x)) - sage: integrate(f, x, 0, infinity) + sage: f = e^(-2*x)/sqrt(1-e^(-2*x)) # needs sage.symbolic + sage: integrate(f, x, 0, infinity) # needs sage.symbolic 1 This integral would cause a stack overflow in earlier versions of Maxima, crashing sage. See :trac:`12377`. We don't care about the result here, just that the computation completes successfully:: - sage: y = (x^2)*exp(x) / (1 + exp(x))^2 - sage: _ = integrate(y, x, -1000, 1000) + sage: y = (x^2)*exp(x) / (1 + exp(x))^2 # needs sage.symbolic + sage: _ = integrate(y, x, -1000, 1000) # needs sage.symbolic When SymPy cannot solve an integral it gives it back, so we must be able to convert SymPy's ``Integral`` (:trac:`14723`):: + sage: # needs sage.symbolic sage: x, y, z = var('x,y,z') sage: f = function('f') sage: integrate(f(x), x, algorithm='sympy') integrate(f(x), x) - sage: integrate(f(x), x, 0, 1,algorithm='sympy') + sage: integrate(f(x), x, 0, 1, algorithm='sympy') integrate(f(x), x, 0, 1) - sage: integrate(integrate(integrate(f(x,y,z), x, algorithm='sympy'), y, algorithm='sympy'), z, algorithm='sympy') + sage: integrate(integrate(integrate(f(x,y,z), x, algorithm='sympy'), + ....: y, algorithm='sympy'), + ....: z, algorithm='sympy') integrate(integrate(integrate(f(x, y, z), x), y), z) sage: integrate(sin(x)*tan(x)/(1-cos(x)), x, algorithm='sympy') -integrate(sin(x)*tan(x)/(cos(x) - 1), x) sage: _ = var('a,b,x') sage: integrate(sin(x)*tan(x)/(1-cos(x)), x, a, b, algorithm='sympy') -integrate(sin(x)*tan(x)/(cos(x) - 1), x, a, b) + + sage: # needs sympy sage: import sympy sage: x, y, z = sympy.symbols('x y z') sage: f = sympy.Function('f') - sage: SR(sympy.Integral(f(x,y,z), x, y, z)) + sage: SR(sympy.Integral(f(x,y,z), x, y, z)) # needs sage.symbolic integrate(integrate(integrate(f(x, y, z), x), y), z) Ensure that the following integral containing a signum term from :trac:`11590` can be integrated:: - sage: x = SR.symbol('x', domain='real') - sage: result = integrate(x * sgn(x^2 - 1/4), x, -1, 0) + sage: x = SR.symbol('x', domain='real') # needs sage.symbolic + sage: result = integrate(x * sgn(x^2 - 1/4), x, -1, 0) # needs sage.symbolic ... - sage: result + sage: result # needs sage.symbolic -1/4 """ @@ -787,11 +805,13 @@ def integral_closure(x): sage: integral_closure(QQ) Rational Field - sage: K. = QuadraticField(5) - sage: O2 = K.order(2*a); O2 - Order in Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? - sage: integral_closure(O2) - Maximal Order in Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790? + sage: K. = QuadraticField(5) # needs sage.rings.number_field + sage: O2 = K.order(2 * a); O2 # needs sage.rings.number_field + Order in Number Field in a + with defining polynomial x^2 - 5 with a = 2.236067977499790? + sage: integral_closure(O2) # needs sage.rings.number_field + Maximal Order in Number Field in a + with defining polynomial x^2 - 5 with a = 2.236067977499790? """ return x.integral_closure() @@ -875,9 +895,9 @@ def is_integrally_closed(x): See https://github.com/sagemath/sage/issues/32347 for details. True sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 + 189*x + 394) # optional - sage.rings.number_field - sage: R = K.order(2*a) # optional - sage.rings.number_field - sage: is_integrally_closed(R) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 + 189*x + 394) # needs sage.rings.number_field + sage: R = K.order(2*a) # needs sage.rings.number_field + sage: is_integrally_closed(R) # needs sage.rings.number_field False """ deprecation(32347, "use X.is_integrally_closed()") @@ -929,8 +949,9 @@ def kernel(x): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,2) - sage: A = M([1,2,3,4,5,6]) + sage: # needs sage.modules + sage: M = MatrixSpace(QQ, 3, 2) + sage: A = M([1,2, 3,4, 5,6]) sage: kernel(A) Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: @@ -942,7 +963,8 @@ def kernel(x): Here are two corner cases:: - sage: M = MatrixSpace(QQ,0,3) + sage: # needs sage.modules + sage: M = MatrixSpace(QQ, 0, 3) sage: A = M([]) sage: kernel(A) Vector space of degree 0 and dimension 0 over Rational Field @@ -968,7 +990,7 @@ def krull_dimension(x): 0 sage: krull_dimension(ZZ) 1 - sage: krull_dimension(ZZ[sqrt(5)]) + sage: krull_dimension(ZZ[sqrt(5)]) # needs sage.rings.number_field sage.symbolic 1 sage: U. = PolynomialRing(ZZ,3); U Multivariate Polynomial Ring in x, y, z over Integer Ring @@ -992,8 +1014,8 @@ def lift(x): We lift an element of a quotient polynomial ring:: sage: R. = QQ['x'] - sage: S. = R.quo(x^2 + 1) - sage: lift(xmod-7) + sage: S. = R.quo(x^2 + 1) # needs sage.libs.pari + sage: lift(xmod - 7) # needs sage.libs.pari x - 7 """ try: @@ -1020,7 +1042,7 @@ def log(*args, **kwds): EXAMPLES:: - sage: log(e^2) + sage: log(e^2) # needs sage.symbolic 2 To change the base of the logarithm, add a second parameter:: @@ -1030,6 +1052,7 @@ def log(*args, **kwds): The synonym ``ln`` can only take one argument:: + sage: # needs sage.symbolic sage: ln(RDF(10)) 2.302585092994046 sage: ln(2.718) @@ -1038,6 +1061,7 @@ def log(*args, **kwds): 0.693147180559945 sage: ln(float(-1)) 3.141592653589793j + sage: ln(complex(-1)) 3.141592653589793j @@ -1050,6 +1074,8 @@ def log(*args, **kwds): 10 sage: RDF(log(1024, 2)) 10.0 + + sage: # needs sage.symbolic sage: log(10, 4) 1/2*log(10)/log(2) sage: RDF(log(10, 4)) @@ -1067,15 +1093,16 @@ def log(*args, **kwds): numbers, and symbolic numbers too, picking the branch with angle between `-\\pi` and `\\pi`:: - sage: log(-1+0*I) + sage: log(-1+0*I) # needs sage.symbolic I*pi - sage: log(CC(-1)) + sage: log(CC(-1)) # needs sage.rings.real_mpfr 3.14159265358979*I - sage: log(-1.0) + sage: log(-1.0) # needs sage.symbolic 3.14159265358979*I Small integer powers are factored out immediately:: + sage: # needs sage.symbolic sage: log(4) 2*log(2) sage: log(1000000000) @@ -1087,7 +1114,8 @@ def log(*args, **kwds): The ``hold`` parameter can be used to prevent automatic evaluation:: - sage: log(-1,hold=True) + sage: # needs sage.symbolic + sage: log(-1, hold=True) log(-1) sage: log(-1) I*pi @@ -1098,23 +1126,24 @@ def log(*args, **kwds): For input zero, the following behavior occurs:: - sage: log(0) + sage: log(0) # needs sage.symbolic -Infinity - sage: log(CC(0)) + sage: log(CC(0)) # needs sage.rings.real_mpfr -infinity - sage: log(0.0) + sage: log(0.0) # needs sage.symbolic -infinity The log function also works in finite fields as long as the argument lies in the multiplicative group generated by the base:: + sage: # needs sage.libs.pari sage: F = GF(13); g = F.multiplicative_generator(); g 2 sage: a = F(8) - sage: log(a,g); g^log(a,g) + sage: log(a, g); g^log(a, g) 3 8 - sage: log(a,3) + sage: log(a, 3) Traceback (most recent call last): ... ValueError: no logarithm of 8 found to base 3 modulo 13 @@ -1124,11 +1153,11 @@ def log(*args, **kwds): The log function also works for p-adics (see documentation for p-adics for more information):: - sage: R = Zp(5); R + sage: R = Zp(5); R # needs sage.rings.padics 5-adic Ring with capped relative precision 20 - sage: a = R(16); a + sage: a = R(16); a # needs sage.rings.padics 1 + 3*5 + O(5^20) - sage: log(a) + sage: log(a) # needs sage.rings.padics 3*5 + 3*5^2 + 3*5^4 + 3*5^5 + 3*5^6 + 4*5^7 + 2*5^8 + 5^9 + 5^11 + 2*5^12 + 5^13 + 3*5^15 + 2*5^16 + 4*5^17 + 3*5^18 + 3*5^19 + O(5^20) @@ -1138,26 +1167,26 @@ def log(*args, **kwds): Check if :trac:`10136` is fixed:: - sage: ln(x).operator() is ln + sage: ln(x).operator() is ln # needs sage.symbolic True - sage: log(x).operator() is ln + sage: log(x).operator() is ln # needs sage.symbolic True sage: log(1000, 10) 3 - sage: log(3,-1) + sage: log(3, -1) # needs sage.symbolic -I*log(3)/pi - sage: log(int(8),2) + sage: log(int(8), 2) # needs sage.symbolic 3 - sage: log(8,int(2)) + sage: log(8, int(2)) 3 - sage: log(8,2) + sage: log(8, 2) 3 - sage: log(1/8,2) + sage: log(1/8, 2) -3 - sage: log(1/8,1/2) + sage: log(1/8, 1/2) 3 - sage: log(8,1/2) + sage: log(8, 1/2) -3 sage: log(1000, 10, base=5) @@ -1197,14 +1226,15 @@ def minimal_polynomial(x, var='x'): EXAMPLES:: + sage: # needs sage.libs.pari sage.modules sage: a = matrix(ZZ, 2, [1..4]) sage: minpoly(a) x^2 - 5*x - 2 - sage: minpoly(a,'t') + sage: minpoly(a, 't') t^2 - 5*t - 2 sage: minimal_polynomial(a) x^2 - 5*x - 2 - sage: minimal_polynomial(a,'theta') + sage: minimal_polynomial(a, 'theta') theta^2 - 5*theta - 2 """ try: @@ -1219,16 +1249,16 @@ def minimal_polynomial(x, var='x'): def multiplicative_order(x): r""" Return the multiplicative order of ``x``, if ``x`` is a unit, or - raise ``ArithmeticError`` otherwise. + raise :class:`ArithmeticError` otherwise. EXAMPLES:: - sage: a = mod(5,11) - sage: multiplicative_order(a) + sage: a = mod(5, 11) + sage: multiplicative_order(a) # needs sage.libs.pari 5 - sage: multiplicative_order(mod(2,11)) + sage: multiplicative_order(mod(2, 11)) # needs sage.libs.pari 10 - sage: multiplicative_order(mod(2,12)) + sage: multiplicative_order(mod(2, 12)) # needs sage.libs.pari Traceback (most recent call last): ... ArithmeticError: multiplicative order of 2 not defined since it is not a unit modulo 12 @@ -1242,12 +1272,12 @@ def ngens(x): EXAMPLES:: - sage: R. = SR[]; R + sage: R. = SR[]; R # needs sage.symbolic Multivariate Polynomial Ring in x, y over Symbolic Ring - sage: ngens(R) + sage: ngens(R) # needs sage.symbolic 2 - sage: A = AbelianGroup(5, [5,5,7,8,9]) - sage: ngens(A) + sage: A = AbelianGroup(5, [5,5,7,8,9]) # needs sage.groups + sage: ngens(A) # needs sage.groups 5 sage: ngens(ZZ) 1 @@ -1318,6 +1348,7 @@ def norm(x): The norm of vectors:: + sage: # needs sage.modules sage.symbolic sage: z = 1 + 2*I sage: norm(vector([z])) sqrt(5) @@ -1331,19 +1362,21 @@ def norm(x): The norm of matrices:: + sage: # needs sage.modules sage.symbolic sage: z = 1 + 2*I sage: norm(matrix([[z]])) 2.23606797749979 sage: M = matrix(ZZ, [[1,2,4,3], [-1,0,3,-10]]) sage: norm(M) # abs tol 1e-14 10.690331129154467 - sage: norm(CDF(z)) # optional - sage.modules + sage: norm(CDF(z)) 5.0 - sage: norm(CC(z)) # optional - sage.modules + sage: norm(CC(z)) 5.00000000000000 The norm of complex numbers:: + sage: # needs sage.symbolic sage: z = 2 - 3*I sage: norm(z) 13 @@ -1355,6 +1388,7 @@ def norm(x): The complex norm of symbolic expressions:: + sage: # needs sage.symbolic sage: a, b, c = var("a, b, c") sage: assume((a, 'real'), (b, 'real'), (c, 'real')) sage: z = a + b*I @@ -1416,6 +1450,7 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): EXAMPLES:: + sage: # needs sage.symbolic sage: numerical_approx(pi, 10) 3.1 sage: numerical_approx(pi, digits=10) @@ -1428,6 +1463,8 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): 12.5878862295484 sage: n(pi^2 + e, digits=50) 12.587886229548403854194778471228813633070946500941 + + sage: # needs sage.rings.real_mpfr sage: a = CC(-5).n(prec=40) sage: b = ComplexField(40)(-5) sage: a == b @@ -1439,17 +1476,18 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): You can also usually use method notation:: - sage: (pi^2 + e).n() + sage: (pi^2 + e).n() # needs sage.symbolic 12.5878862295484 - sage: (pi^2 + e).numerical_approx() + sage: (pi^2 + e).numerical_approx() # needs sage.symbolic 12.5878862295484 Vectors and matrices may also have their entries approximated:: - sage: v = vector(RDF, [1,2,3]) - sage: v.n() + sage: v = vector(RDF, [1,2,3]) # needs sage.modules + sage: v.n() # needs sage.modules (1.00000000000000, 2.00000000000000, 3.00000000000000) + sage: # needs sage.modules sage: v = vector(CDF, [1,2,3]) sage: v.n() (1.00000000000000, 2.00000000000000, 3.00000000000000) @@ -1458,12 +1496,13 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): sage: v.n(prec=20) (1.0000, 2.0000, 3.0000) - sage: u = vector(QQ, [1/2, 1/3, 1/4]) - sage: n(u, prec=15) + sage: u = vector(QQ, [1/2, 1/3, 1/4]) # needs sage.modules + sage: n(u, prec=15) # needs sage.modules (0.5000, 0.3333, 0.2500) - sage: n(u, digits=5) + sage: n(u, digits=5) # needs sage.modules (0.50000, 0.33333, 0.25000) + sage: # needs sage.modules sage: v = vector(QQ, [1/2, 0, 0, 1/3, 0, 0, 0, 1/4], sparse=True) sage: u = v.numerical_approx(digits=4) sage: u.is_sparse() @@ -1471,11 +1510,11 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): sage: u (0.5000, 0.0000, 0.0000, 0.3333, 0.0000, 0.0000, 0.0000, 0.2500) + sage: # needs sage.modules sage: A = matrix(QQ, 2, 3, range(6)) sage: A.n() [0.000000000000000 1.00000000000000 2.00000000000000] [ 3.00000000000000 4.00000000000000 5.00000000000000] - sage: B = matrix(Integers(12), 3, 8, srange(24)) sage: N(B, digits=2) [0.00 1.0 2.0 3.0 4.0 5.0 6.0 7.0] @@ -1486,28 +1525,28 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): Therefore, numbers which look the same in their decimal expansion might be different:: - sage: x=N(pi, digits=3); x + sage: x = N(pi, digits=3); x # needs sage.symbolic 3.14 - sage: y=N(3.14, digits=3); y + sage: y = N(3.14, digits=3); y # needs sage.rings.real_mpfr 3.14 - sage: x==y + sage: x == y # needs sage.rings.real_mpfr sage.symbolic False - sage: x.str(base=2) + sage: x.str(base=2) # needs sage.symbolic '11.001001000100' - sage: y.str(base=2) + sage: y.str(base=2) # needs sage.rings.real_mpfr '11.001000111101' Increasing the precision of a floating point number is not allowed:: - sage: CC(-5).n(prec=100) + sage: CC(-5).n(prec=100) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: cannot approximate to a precision of 100 bits, use at most 53 bits - sage: n(1.3r, digits=20) + sage: n(1.3r, digits=20) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: cannot approximate to a precision of 70 bits, use at most 53 bits - sage: RealField(24).pi().n() + sage: RealField(24).pi().n() # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: cannot approximate to a precision of 53 bits, use at most 24 bits @@ -1515,6 +1554,7 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): As an exceptional case, ``digits=1`` usually leads to 2 digits (one significant) in the decimal output (see :trac:`11647`):: + sage: # needs sage.symbolic sage: N(pi, digits=1) 3.2 sage: N(pi, digits=2) @@ -1527,33 +1567,33 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): In the following example, ``pi`` and ``3`` are both approximated to two bits of precision and then subtracted, which kills two bits of precision:: - sage: N(pi, prec=2) + sage: N(pi, prec=2) # needs sage.symbolic 3.0 - sage: N(3, prec=2) + sage: N(3, prec=2) # needs sage.rings.real_mpfr 3.0 - sage: N(pi - 3, prec=2) + sage: N(pi - 3, prec=2) # needs sage.symbolic 0.00 TESTS:: - sage: numerical_approx(I) + sage: numerical_approx(I) # needs sage.symbolic 1.00000000000000*I sage: x = QQ['x'].gen() - sage: F. = NumberField(x^2+2, embedding=sqrt(CC(2))*CC.0) - sage: numerical_approx(k) + sage: F. = NumberField(x^2 + 2, embedding=sqrt(CC(2))*CC.0) # needs sage.rings.number_field sage.symbolic + sage: numerical_approx(k) # needs sage.rings.number_field sage.symbolic 1.41421356237309*I - sage: type(numerical_approx(CC(1/2))) + sage: type(numerical_approx(CC(1/2))) # needs sage.rings.real_mpfr The following tests :trac:`10761`, in which ``n()`` would break when called on complex-valued algebraic numbers. :: - sage: E = matrix(3, [3,1,6,5,2,9,7,3,13]).eigenvalues(); E + sage: E = matrix(3, [3,1,6,5,2,9,7,3,13]).eigenvalues(); E # needs sage.modules sage.rings.number_field [18.16815365088822?, -0.08407682544410650? - 0.2190261484802906?*I, -0.08407682544410650? + 0.2190261484802906?*I] - sage: E[1].parent() + sage: E[1].parent() # needs sage.modules sage.rings.number_field Algebraic Field - sage: [a.n() for a in E] + sage: [a.n() for a in E] # needs sage.modules sage.rings.number_field [18.1681536508882, -0.0840768254441065 - 0.219026148480291*I, -0.0840768254441065 + 0.219026148480291*I] Make sure we've rounded up log(10,2) enough to guarantee @@ -1562,20 +1602,20 @@ def numerical_approx(x, prec=None, digits=None, algorithm=None): sage: ks = 4*10**5, 10**6 sage: check_str_length = lambda k: len(str(numerical_approx(1+10**-k,digits=k+1)))-1 >= k+1 sage: check_precision = lambda k: numerical_approx(1+10**-k,digits=k+1)-1 > 0 - sage: all(check_str_length(k) and check_precision(k) for k in ks) + sage: all(check_str_length(k) and check_precision(k) for k in ks) # needs sage.rings.real_mpfr True Testing we have sufficient precision for the golden ratio (:trac:`12163`), note that the decimal point adds 1 to the string length:: - sage: len(str(n(golden_ratio, digits=5000))) + sage: len(str(n(golden_ratio, digits=5000))) # needs sage.symbolic 5001 - sage: len(str(n(golden_ratio, digits=5000000))) # long time (4s on sage.math, 2012) + sage: len(str(n(golden_ratio, digits=5000000))) # long time (4s on sage.math, 2012), needs sage.symbolic 5000001 Check that :trac:`14778` is fixed:: - sage: n(0, algorithm='foo') + sage: n(0, algorithm='foo') # needs sage.rings.real_mpfr 0.000000000000000 """ if prec is None: @@ -1629,8 +1669,8 @@ def order(x): EXAMPLES:: - sage: C = CyclicPermutationGroup(10) - sage: order(C) + sage: C = CyclicPermutationGroup(10) # needs sage.groups + sage: order(C) # needs sage.groups 10 sage: F = GF(7) sage: order(F) @@ -1647,15 +1687,15 @@ def rank(x): We compute the rank of a matrix:: - sage: M = MatrixSpace(QQ,3,3) - sage: A = M([1,2,3,4,5,6,7,8,9]) - sage: rank(A) + sage: M = MatrixSpace(QQ, 3, 3) # needs sage.modules + sage: A = M([1,2,3, 4,5,6, 7,8,9]) # needs sage.modules + sage: rank(A) # needs sage.modules 2 We compute the rank of an elliptic curve:: - sage: E = EllipticCurve([0,0,1,-1,0]) - sage: rank(E) + sage: E = EllipticCurve([0,0,1,-1,0]) # needs sage.schemes + sage: rank(E) # needs sage.schemes 1 """ return x.rank() @@ -1668,9 +1708,9 @@ def regulator(x): EXAMPLES:: sage: x = polygen(ZZ, 'x') - sage: regulator(NumberField(x^2 - 2, 'a')) # optional - sage.rings.number_field + sage: regulator(NumberField(x^2 - 2, 'a')) # needs sage.rings.number_field 0.881373587019543 - sage: regulator(EllipticCurve('11a')) + sage: regulator(EllipticCurve('11a')) # needs sage.schemes 1.00000000000000 """ return x.regulator() @@ -1686,9 +1726,10 @@ def round(x, ndigits=0): EXAMPLES:: - sage: round(sqrt(2),2) + sage: # needs sage.symbolic + sage: round(sqrt(2), 2) 1.41 - sage: q = round(sqrt(2),5); q + sage: q = round(sqrt(2), 5); q 1.41421 sage: type(q) @@ -1698,6 +1739,7 @@ def round(x, ndigits=0): sage: round(pi) 3 + sage: b = 5.4999999999999999 sage: round(b) 5 @@ -1710,7 +1752,7 @@ def round(x, ndigits=0): Since we use floating-point with a limited range, some roundings can't be performed:: - sage: round(sqrt(Integer('1'*1000)),2) + sage: round(sqrt(Integer('1'*1000)), 2) # needs sage.symbolic +infinity IMPLEMENTATION: If ndigits is specified, it calls Python's builtin @@ -1754,8 +1796,8 @@ def quotient(x, y, *args, **kwds): 0.833333333333333 sage: R. = ZZ[]; R Univariate Polynomial Ring in x over Integer Ring - sage: I = Ideal(R, x^2+1) - sage: quotient(R, I) + sage: I = Ideal(R, x^2 + 1) + sage: quotient(R, I) # needs sage.libs.pari Univariate Quotient Polynomial Ring in xbar over Integer Ring with modulus x^2 + 1 """ try: @@ -1808,7 +1850,7 @@ def squarefree_part(x): sage: x = QQ['x'].0 sage: S = squarefree_part(-9*x*(x-6)^7*(x-3)^2); S -9*x^2 + 54*x - sage: S.factor() + sage: S.factor() # needs sage.libs.pari (-9) * (x - 6) * x :: @@ -1817,7 +1859,7 @@ def squarefree_part(x): x^10 - x^9 + 3*x^8 + 3*x^5 - 2*x^4 - x^3 - 2*x - 1 sage: g = squarefree_part(f); g x^4 - x^3 + x^2 - 1 - sage: g.factor() + sage: g.factor() # needs sage.libs.pari (x - 1) * (x^3 + x + 1) """ try: @@ -1836,43 +1878,42 @@ def squarefree_part(x): def _do_sqrt(x, prec=None, extend=True, all=False): r""" - Used internally to compute the square root of x. + Used internally to compute the square root of ``x``. INPUT: - - ``x`` - a number + - ``x`` -- a number - - ``prec`` - None (default) or a positive integer - (bits of precision) If not None, then compute the square root - numerically to prec bits of precision. + - ``prec`` -- a positive integer (default: ``None``); when specified, + compute the square root with ``prec`` bits of precision - - ``extend`` - bool (default: True); this is a place - holder, and is always ignored since in the symbolic ring everything + - ``extend`` -- bool (default: ``True``); this is a placeholder, and is + always ignored since in the symbolic ring everything has a square root. - - ``extend`` - bool (default: True); whether to extend + - ``extend`` -- bool (default: ``True``); whether to extend the base ring to find roots. The extend parameter is ignored if - prec is a positive integer. + ``prec`` is a positive integer. - - ``all`` - bool (default: False); whether to return - a list of all the square roots of x. + - ``all`` -- bool (default: ``False``); whether to return + a list of all the square roots of ``x``. EXAMPLES:: sage: from sage.misc.functional import _do_sqrt - sage: _do_sqrt(3) + sage: _do_sqrt(3) # needs sage.symbolic sqrt(3) - sage: _do_sqrt(3,prec=10) + sage: _do_sqrt(3, prec=10) # needs sage.rings.real_mpfr 1.7 - sage: _do_sqrt(3,prec=100) + sage: _do_sqrt(3, prec=100) # needs sage.rings.real_mpfr 1.7320508075688772935274463415 - sage: _do_sqrt(3,all=True) + sage: _do_sqrt(3, all=True) # needs sage.symbolic [sqrt(3), -sqrt(3)] Note that the extend parameter is ignored in the symbolic ring:: - sage: _do_sqrt(3,extend=False) + sage: _do_sqrt(3, extend=False) # needs sage.symbolic sqrt(3) """ if prec: @@ -1900,40 +1941,42 @@ def sqrt(x, *args, **kwds): r""" INPUT: - - ``x`` - a number + - ``x`` -- a number - - ``prec`` - integer (default: None): if None, returns + - ``prec`` -- integer (default: ``None``): if ``None``, returns an exact square root; otherwise returns a numerical square root if necessary, to the given bits of precision. - - ``extend`` - bool (default: True); this is a place - holder, and is always ignored or passed to the sqrt function for x, + - ``extend`` -- bool (default: ``True``); this is a placeholder, and + is always ignored or passed to the ``sqrt`` method of ``x``, since in the symbolic ring everything has a square root. - - ``all`` - bool (default: False); if True, return all - square roots of self, instead of just one. + - ``all`` -- bool (default: ``False``); if ``True``, return all + square roots of ``self``, instead of just one. EXAMPLES:: - sage: sqrt(-1) # optional - sage.symbolic - I - sage: sqrt(2) # optional - sage.symbolic - sqrt(2) - sage: sqrt(2)^2 # optional - sage.symbolic - 2 sage: sqrt(4) 2 sage: sqrt(4, all=True) [2, -2] - sage: sqrt(x^2) # optional - sage.symbolic + + sage: # needs sage.symbolic + sage: sqrt(-1) + I + sage: sqrt(2) + sqrt(2) + sage: sqrt(2)^2 + 2 + sage: sqrt(x^2) sqrt(x^2) For a non-symbolic square root, there are a few options. The best is to numerically approximate afterward:: - sage: sqrt(2).n() # optional - sage.symbolic + sage: sqrt(2).n() # needs sage.symbolic 1.41421356237310 - sage: sqrt(2).n(prec=100) # optional - sage.symbolic + sage: sqrt(2).n(prec=100) # needs sage.symbolic 1.4142135623730950488016887242 Or one can input a numerical type:: @@ -1948,7 +1991,7 @@ def sqrt(x, *args, **kwds): To prevent automatic evaluation, one can use the ``hold`` parameter after coercing to the symbolic ring:: - sage: sqrt(SR(4), hold=True) # optional - sage.symbolic + sage: sqrt(SR(4), hold=True) # needs sage.symbolic sqrt(4) sage: sqrt(4, hold=True) Traceback (most recent call last): @@ -1962,16 +2005,16 @@ def sqrt(x, *args, **kwds): Traceback (most recent call last): ... TypeError: ...sqrt() got an unexpected keyword argument 'prec' - sage: sqrt(a, prec=100) + sage: sqrt(a, prec=100) # needs sage.rings.real_mpfr 1.0488088481701515469914535137 - sage: sqrt(4.00, prec=250) + sage: sqrt(4.00, prec=250) # needs sage.rings.real_mpfr 2.0000000000000000000000000000000000000000000000000000000000000000000000000 One can use numpy input as well:: - sage: import numpy - sage: a = numpy.arange(2,5) - sage: sqrt(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2,5) # needs numpy + sage: sqrt(a) # needs numpy array([1.41421356, 1.73205081, 2. ]) """ if isinstance(x, float): @@ -1995,9 +2038,9 @@ def transpose(x): EXAMPLES:: - sage: M = MatrixSpace(QQ,3,3) - sage: A = M([1,2,3,4,5,6,7,8,9]) - sage: transpose(A) + sage: M = MatrixSpace(QQ, 3, 3) # needs sage.modules + sage: A = M([1,2,3, 4,5,6, 7,8,9]) # needs sage.modules + sage: transpose(A) # needs sage.modules [1 4 7] [2 5 8] [3 6 9] diff --git a/src/sage/misc/gperftools.py b/src/sage/misc/gperftools.py index d6e8123e8b2..b928ef18e08 100644 --- a/src/sage/misc/gperftools.py +++ b/src/sage/misc/gperftools.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.symbolic """ C Function Profiler Using Google Perftools diff --git a/src/sage/misc/inherit_comparison.pyx b/src/sage/misc/inherit_comparison.pyx index 7582215291a..aa97f664496 100644 --- a/src/sage/misc/inherit_comparison.pyx +++ b/src/sage/misc/inherit_comparison.pyx @@ -51,8 +51,11 @@ cdef class InheritComparisonMetaclass(type): EXAMPLES:: - sage: cython( # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython( ....: ''' + ....: cimport cython + ....: ....: from sage.misc.inherit_comparison cimport InheritComparisonMetaclass ....: ....: cdef class Base(): @@ -65,17 +68,18 @@ cdef class InheritComparisonMetaclass(type): ....: return 1 ....: ....: cdef class DerivedWithRichcmp(Base): + ....: @cython.always_allow_keywords(False) ....: def __getmetaclass__(_): ....: from sage.misc.inherit_comparison import InheritComparisonMetaclass ....: return InheritComparisonMetaclass ....: def __hash__(self): ....: return 1 ....: ''') - sage: a = Derived() # optional - sage.misc.cython - sage: a == a # optional - sage.misc.cython + sage: a = Derived() + sage: a == a True - sage: b = DerivedWithRichcmp() # optional - sage.misc.cython - sage: b == b # optional - sage.misc.cython + sage: b = DerivedWithRichcmp() + sage: b == b Calling Base.__richcmp__ True """ diff --git a/src/sage/misc/inline_fortran.py b/src/sage/misc/inline_fortran.py index 6e71016c427..0ace070510b 100644 --- a/src/sage/misc/inline_fortran.py +++ b/src/sage/misc/inline_fortran.py @@ -91,6 +91,7 @@ def eval(self, x, globals=None, locals=None): EXAMPLES:: + sage: # needs numpy sage: code = ''' ....: C FILE: FIB1.F ....: SUBROUTINE FIB(A,N) diff --git a/src/sage/misc/instancedoc.pyx b/src/sage/misc/instancedoc.pyx index 360d3f768b3..d8e1e4ac536 100644 --- a/src/sage/misc/instancedoc.pyx +++ b/src/sage/misc/instancedoc.pyx @@ -36,7 +36,8 @@ EXAMPLES:: For a Cython ``cdef class``, a decorator cannot be used. Instead, call :func:`instancedoc` as a function after defining the class:: - sage: cython(''' + sage: cython( # needs sage.misc.cython + ....: ''' ....: from sage.misc.instancedoc import instancedoc ....: cdef class Y: ....: "Class docstring" @@ -44,9 +45,9 @@ For a Cython ``cdef class``, a decorator cannot be used. Instead, call ....: return "Instance docstring" ....: instancedoc(Y) ....: ''') - sage: Y.__doc__ + sage: Y.__doc__ # needs sage.misc.cython 'File:...\nClass docstring' - sage: Y().__doc__ + sage: Y().__doc__ # needs sage.misc.cython 'Instance docstring' One can still add a custom ``__doc__`` attribute on a particular @@ -59,7 +60,7 @@ instance:: This normally does not work on extension types:: - sage: Y().__doc__ = "Very special doc" + sage: Y().__doc__ = "Very special doc" # needs sage.misc.cython Traceback (most recent call last): ... AttributeError: attribute '__doc__' of 'Y' objects is not writable diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index e4ada89f9e8..25b1ff557be 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -184,7 +184,8 @@ def list_function(x): '\\left[1, 2, 3\\right]' sage: latex([1,2,3]) # indirect doctest \left[1, 2, 3\right] - sage: latex([Matrix(ZZ,3,range(9)), Matrix(ZZ,3,range(9))]) # indirect doctest + sage: latex([Matrix(ZZ, 3, range(9)), # indirect doctest # needs sage.modules + ....: Matrix(ZZ, 3, range(9))]) \left[\left(\begin{array}{rrr} 0 & 1 & 2 \\ 3 & 4 & 5 \\ @@ -366,6 +367,7 @@ def dict_function(x): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.misc.latex import dict_function sage: x,y,z = var('x,y,z') sage: print(dict_function({x/2: y^2})) @@ -450,9 +452,9 @@ class LatexExpr(str): EXAMPLES:: - sage: latex(x^20 + 1) + sage: latex(x^20 + 1) # needs sage.symbolic x^{20} + 1 - sage: LatexExpr(r"\frac{x^2 + 1}{x - 2}") + sage: LatexExpr(r"\frac{x^2 + 1}{x - 2}") # needs sage.symbolic \frac{x^2 + 1}{x - 2} ``LatexExpr`` simply converts to string without doing anything @@ -465,15 +467,15 @@ class LatexExpr(str): The result of :func:`latex` is of type ``LatexExpr``:: - sage: L = latex(x^20 + 1) - sage: L + sage: L = latex(x^20 + 1) # needs sage.symbolic + sage: L # needs sage.symbolic x^{20} + 1 - sage: type(L) + sage: type(L) # needs sage.symbolic A ``LatexExpr`` can be converted to a plain string:: - sage: str(latex(x^20 + 1)) + sage: str(latex(x^20 + 1)) # needs sage.symbolic 'x^{20} + 1' """ def __add__(self, other): @@ -558,7 +560,7 @@ def has_latex_attr(x) -> bool: EXAMPLES:: sage: from sage.misc.latex import has_latex_attr - sage: has_latex_attr(identity_matrix(3)) + sage: has_latex_attr(identity_matrix(3)) # needs sage.modules True sage: has_latex_attr("abc") # strings have no _latex_ method False @@ -566,6 +568,7 @@ def has_latex_attr(x) -> bool: Types inherit the ``_latex_`` method of the class to which they refer, but calling it is broken:: + sage: # needs sage.modules sage: T = type(identity_matrix(3)); T sage: hasattr(T, '_latex_') @@ -918,12 +921,12 @@ def __call__(self, x, combine_all=False): 3 sage: latex(1==0) \mathrm{False} - sage: print(latex([x,2])) + sage: print(latex([x, 2])) # needs sage.symbolic \left[x, 2\right] Check that :trac:`11775` is fixed:: - sage: latex((x,2), combine_all=True) + sage: latex((x,2), combine_all=True) # needs sage.symbolic x 2 """ if has_latex_attr(x): @@ -962,9 +965,9 @@ class Latex(LatexCall): EXAMPLES:: - sage: latex(x^20 + 1) + sage: latex(x^20 + 1) # needs sage.symbolic x^{20} + 1 - sage: latex(FiniteField(25,'a')) + sage: latex(FiniteField(25,'a')) # needs sage.rings.finite_rings \Bold{F}_{5^{2}} sage: latex("hello") \text{\texttt{hello}} @@ -974,7 +977,7 @@ class Latex(LatexCall): LaTeX expressions can be added; note that a space is automatically inserted:: - sage: LatexExpr(r"y \neq") + latex(x^20 + 1) + sage: LatexExpr(r"y \neq") + latex(x^20 + 1) # needs sage.symbolic y \neq x^{20} + 1 """ def __init__(self, debug=False, slide=False, density=150, pdflatex=None, engine=None): @@ -1213,6 +1216,7 @@ def matrix_delimiters(self, left=None, right=None): EXAMPLES:: + sage: # needs sage.modules sage: a = matrix(1, 1, [17]) sage: latex(a) \left(\begin{array}{r} @@ -1274,6 +1278,7 @@ def vector_delimiters(self, left=None, right=None): EXAMPLES:: + sage: # needs sage.modules sage: a = vector(QQ, [1,2,3]) sage: latex(a) \left(1,\,2,\,3\right) @@ -1319,6 +1324,7 @@ def matrix_column_alignment(self, align=None): EXAMPLES:: + sage: # needs sage.modules sage: a = matrix(1, 1, [42]) sage: latex(a) \left(\begin{array}{r} @@ -1968,7 +1974,7 @@ def png(x, filename, density=150, debug=False, sage: from sage.misc.latex import png sage: import tempfile - sage: with tempfile.NamedTemporaryFile(suffix=".png") as f: # random, optional - latex imagemagick + sage: with tempfile.NamedTemporaryFile(suffix=".png") as f: # random # optional - imagemagick latex, needs sage.plot ....: png(ZZ[x], f.name) """ if not pdflatex: @@ -2020,7 +2026,7 @@ def coeff_repr(c): sage: from sage.misc.latex import coeff_repr sage: coeff_repr(QQ(1/2)) '\\frac{1}{2}' - sage: coeff_repr(-x^2) + sage: coeff_repr(-x^2) # needs sage.symbolic '\\left(-x^{2}\\right)' """ try: @@ -2068,9 +2074,9 @@ def repr_lincomb(symbols, coeffs): Verify that :trac:`17299` (latex representation of modular symbols) is fixed:: - sage: x = EllipticCurve('64a1').modular_symbol_space(sign=1).basis()[0] # optional - sage.schemes + sage: x = EllipticCurve('64a1').modular_symbol_space(sign=1).basis()[0] # needs sage.schemes sage: from sage.misc.latex import repr_lincomb - sage: latex(x.modular_symbol_rep()) # optional - sage.schemes + sage: latex(x.modular_symbol_rep()) # needs sage.schemes \left\{\frac{-3}{11}, \frac{-1}{4}\right\} - \left\{\frac{3}{13}, \frac{1}{4}\right\} Verify that it works when the symbols are numbers:: @@ -2199,8 +2205,8 @@ def latex_varify(a, is_fname=False): TESTS: - sage: abc = var('abc') - sage: latex((abc/(abc+1)+42)/(abc-1)) # trac #15870 + sage: abc = var('abc') # needs sage.symbolic + sage: latex((abc/(abc+1)+42)/(abc-1)) # trac #15870 # needs sage.symbolic \frac{\frac{\mathit{abc}}{\mathit{abc} + 1} + 42}{\mathit{abc} - 1} """ if a in common_varnames: @@ -2271,12 +2277,12 @@ def latex_variable_name(x, is_fname=False): TESTS:: - sage: latex_variable_name('_C') # trac #16007 + sage: latex_variable_name('_C') # trac #16007 # needs sage.symbolic 'C' - sage: latex_variable_name('_K1') + sage: latex_variable_name('_K1') # needs sage.symbolic 'K_{1}' - sage: latex_variable_name('5') + sage: latex_variable_name('5') # needs sage.symbolic '5' """ # if x is an integer (it might be the case for padics), we return x diff --git a/src/sage/misc/latex_standalone.py b/src/sage/misc/latex_standalone.py index 3ed2476fe9a..d1d9d77d864 100644 --- a/src/sage/misc/latex_standalone.py +++ b/src/sage/misc/latex_standalone.py @@ -174,7 +174,7 @@ Opening the image in a viewer can be turned off:: - sage: _ = t1.pdf(view=False) # long time (2s), optional - latex # needs sage.geometry.polyhedron sage.plot + sage: _ = t1.pdf(view=False) # long time (2s), optional - latex, needs sage.geometry.polyhedron sage.plot The same can be done with png format (translated from pdf with convert command which needs the installation of imagemagick):: diff --git a/src/sage/misc/lazy_attribute.pyx b/src/sage/misc/lazy_attribute.pyx index 4f0814f5cc2..bdbec3b3ba1 100644 --- a/src/sage/misc/lazy_attribute.pyx +++ b/src/sage/misc/lazy_attribute.pyx @@ -111,12 +111,12 @@ cdef class _lazy_attribute(): if a is None: # when doing cls.x for cls a class and x a lazy attribute return self try: - # __cached_methods is supposed to be a public Cython attribute. + # _cached_methods is supposed to be a public Cython attribute. # Apparently, these are *not* subject to name mangling. - CM = getattr(a, '__cached_methods') + CM = getattr(a, '_cached_methods') if CM is None: CM = {} - setattr(a, '__cached_methods', CM) + setattr(a, '_cached_methods', CM) except AttributeError as msg: CM = None if CM is not None: @@ -354,9 +354,9 @@ class lazy_attribute(_lazy_attribute): ....: "cdef class MyElement(Element): pass", ....: "cdef class MyParent(Parent):", ....: " Element = MyElement"] - sage: cython('\n'.join(cython_code)) # optional - sage.misc.cython - sage: P = MyParent(category=Rings()) # optional - sage.misc.cython - sage: P.element_class # indirect doctest # optional - sage.misc.cython + sage: cython('\n'.join(cython_code)) # needs sage.misc.cython + sage: P = MyParent(category=Rings()) # needs sage.misc.cython + sage: P.element_class # indirect doctest # needs sage.misc.cython .. rubric:: About descriptor specifications diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 3de82a88eaf..c33a1e74efd 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -355,7 +355,7 @@ cdef class LazyImport(): sage: from sage.misc.lazy_import import LazyImport sage: rm = LazyImport('sage.matrix.special', 'random_matrix') - sage: rm._sage_argspec_() + sage: rm._sage_argspec_() # needs sage.modules FullArgSpec(args=['ring', 'nrows', 'ncols', 'algorithm', 'implementation'], varargs='args', varkw='kwds', defaults=(None, 'randomize', None), kwonlyargs=[], kwonlydefaults=None, annotations={}) @@ -531,12 +531,12 @@ cdef class LazyImport(): We access the ``plot`` method:: - sage: Bar.plot + sage: Bar.plot # needs sage.plot Now ``plot`` has been replaced in the dictionary of ``Foo``:: - sage: type(Foo.__dict__['plot']) + sage: type(Foo.__dict__['plot']) # needs sage.plot <... 'function'> """ # Don't use the namespace of the class definition @@ -667,9 +667,10 @@ cdef class LazyImport(): """ TESTS:: + sage: # needs sympy sage: from sympy import Matrix sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = Matrix([[1,1],[0,1]]) + sage: sage.all__sagemath_objects.foo = Matrix([[1,1], [0,1]]) sage: lazy_import('sage.all__sagemath_objects', 'foo') sage: foo.__matmul__(foo) Matrix([ @@ -1064,15 +1065,16 @@ def lazy_import(module, names, as_=None, *, ....: pass sage: type(Foo.__dict__['plot']) - sage: 'EXAMPLES' in Bar.plot.__doc__ + sage: 'EXAMPLES' in Bar.plot.__doc__ # needs sage.plot True - sage: type(Foo.__dict__['plot']) + sage: type(Foo.__dict__['plot']) # needs sage.plot <... 'function'> If deprecated then a deprecation warning is issued:: - sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp', deprecation=14275) - sage: my_Qp(5) + sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp', + ....: deprecation=14275) + sage: my_Qp(5) # needs sage.rings.padics doctest:...: DeprecationWarning: Importing my_Qp from here is deprecated; please use "from sage.rings.padics.factory import Qp as my_Qp" instead. See https://github.com/sagemath/sage/issues/14275 for details. @@ -1080,8 +1082,9 @@ def lazy_import(module, names, as_=None, *, An example of deprecation with a message:: - sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp_msg', deprecation=(14275, "This is an example.")) - sage: my_Qp_msg(5) + sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp_msg', + ....: deprecation=(14275, "This is an example.")) + sage: my_Qp_msg(5) # needs sage.rings.padics doctest:...: DeprecationWarning: This is an example. See https://github.com/sagemath/sage/issues/14275 for details. 5-adic Field with capped relative precision 20 @@ -1089,8 +1092,9 @@ def lazy_import(module, names, as_=None, *, An example of an import relying on a feature:: sage: from sage.features import PythonModule - sage: lazy_import('ppl', 'equation', feature=PythonModule('ppl', spkg='pplpy', type='standard')) - sage: equation + sage: lazy_import('ppl', 'equation', + ....: feature=PythonModule('ppl', spkg='pplpy', type='standard')) + sage: equation # needs pplpy sage: lazy_import('PyNormaliz', 'NmzListConeProperties', feature=PythonModule('PyNormaliz', spkg='pynormaliz')) # optional - pynormaliz sage: NmzListConeProperties # optional - pynormaliz @@ -1155,7 +1159,7 @@ def get_star_imports(module_name): sage: from sage.misc.lazy_import import get_star_imports sage: 'get_star_imports' in get_star_imports('sage.misc.lazy_import') True - sage: 'EllipticCurve' in get_star_imports('sage.schemes.all') # optional - sage.schemes + sage: 'EllipticCurve' in get_star_imports('sage.schemes.all') # needs sage.schemes True TESTS:: @@ -1169,7 +1173,7 @@ def get_star_imports(module_name): sage: import sage.misc.lazy_import_cache as cache sage: cache.get_cache_file = (lambda: cache_file) sage: lazy.star_imports = None - sage: lazy.get_star_imports('sage.schemes.all') # optional - sage.schemes + sage: lazy.get_star_imports('sage.schemes.all') # needs sage.schemes doctest:...: UserWarning: star_imports cache is corrupted [...] sage: os.remove(cache_file) @@ -1247,6 +1251,7 @@ def clean_namespace(namespace=None): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.misc.lazy_import import attributes, clean_namespace sage: from sage.calculus.calculus import maxima as C sage: attributes(C)['_as_name'] diff --git a/src/sage/misc/lazy_list.pyx b/src/sage/misc/lazy_list.pyx index fb192443494..ba62c446b69 100644 --- a/src/sage/misc/lazy_list.pyx +++ b/src/sage/misc/lazy_list.pyx @@ -11,11 +11,11 @@ EXAMPLES:: sage: from sage.misc.lazy_list import lazy_list sage: P = lazy_list(Primes()) - sage: P[100] + sage: P[100] # needs sage.libs.pari 547 - sage: P[10:34] + sage: P[10:34] # needs sage.libs.pari lazy list [31, 37, 41, ...] - sage: P[12:23].list() + sage: P[12:23].list() # needs sage.libs.pari [41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83] sage: f = lazy_list((i**2 - 3*i for i in range(10))) @@ -305,6 +305,7 @@ def lazy_list_formatter(L, name='lazy list', :: + sage: # needs sage.libs.pari sage: from sage.misc.lazy_list import lazy_list sage: L = lazy_list(Primes()); L lazy list [2, 3, 5, ...] @@ -356,9 +357,9 @@ cdef class lazy_list_generic(): sage: from sage.misc.lazy_list import lazy_list sage: l = lazy_list(Primes()) - sage: l + sage: l # needs sage.libs.pari lazy list [2, 3, 5, ...] - sage: l[200] + sage: l[200] # needs sage.libs.pari 1229 """ @@ -415,7 +416,7 @@ cdef class lazy_list_generic(): sage: from sage.misc.lazy_list import lazy_list sage: P = lazy_list(Primes()) - sage: P[2:143:5].list() # optional - sage.libs.pari + sage: P[2:143:5].list() # needs sage.libs.pari [5, 19, 41, 61, 83, 107, 137, 163, 191, 223, 241, 271, 307, 337, 367, 397, 431, 457, 487, 521, 563, 593, 617, 647, 677, 719, 751, 787, 823] sage: P = lazy_list(iter([1,2,3])) @@ -431,11 +432,11 @@ cdef class lazy_list_generic(): Check that the cache is immutable:: sage: lazy = lazy_list(iter(Primes()))[:5] - sage: l = lazy.list(); l + sage: l = lazy.list(); l # needs sage.libs.pari [2, 3, 5, 7, 11] - sage: l[0] = -1; l + sage: l[0] = -1; l # needs sage.libs.pari [-1, 3, 5, 7, 11] - sage: lazy.list() + sage: lazy.list() # needs sage.libs.pari [2, 3, 5, 7, 11] """ self._fit(self.stop - self.step) @@ -454,9 +455,9 @@ cdef class lazy_list_generic(): start 10 stop 21474838 step 4 - sage: P[0] # optional - sage.libs.pari + sage: P[0] # needs sage.libs.pari 31 - sage: P._info() # optional - sage.libs.pari + sage: P._info() # needs sage.libs.pari cache length 11 start 10 stop 21474838 @@ -859,9 +860,9 @@ cdef class lazy_list_generic(): sage: from sage.misc.lazy_list import lazy_list sage: L = lazy_list(Primes())[2:] - sage: L._update_cache_up_to(4) # optional - sage.libs.pari + sage: L._update_cache_up_to(4) # needs sage.libs.pari 0 - sage: L._info() # optional - sage.libs.pari + sage: L._info() # needs sage.libs.pari cache length 5 start 2 stop 9223372036854775807 # 64-bit @@ -886,9 +887,9 @@ cdef class lazy_list_generic(): TESTS:: sage: from sage.misc.lazy_list import lazy_list - sage: L = lazy_list(Primes()); L # optional - sage.libs.pari + sage: L = lazy_list(Primes()); L # needs sage.libs.pari lazy list [2, 3, 5, ...] - sage: L._get_cache_() # optional - sage.libs.pari + sage: L._get_cache_() # needs sage.libs.pari [2, 3, 5, 7] """ return self.cache @@ -965,9 +966,9 @@ cdef class lazy_list_from_iterator(lazy_list_generic): sage: from sage.misc.lazy_list import lazy_list sage: L = lazy_list(iter(Primes()))[2:] - sage: L._update_cache_up_to(4) # optional - sage.libs.pari + sage: L._update_cache_up_to(4) # needs sage.libs.pari 0 - sage: L._info() # optional - sage.libs.pari + sage: L._info() # needs sage.libs.pari cache length 5 start 2 stop 9223372036854775807 # 64-bit @@ -1016,9 +1017,9 @@ cdef class lazy_list_from_function(lazy_list_generic): EXAMPLES:: sage: from sage.misc.lazy_list import lazy_list_from_function - sage: lazy_list_from_function(euler_phi) # optional - sage.libs.pari + sage: lazy_list_from_function(euler_phi) # needs sage.libs.pari lazy list [0, 1, 1, ...] - sage: lazy_list_from_function(divisors, [None]) # optional - sage.libs.pari + sage: lazy_list_from_function(divisors, [None]) lazy list [None, [1], [1, 2], ...] TESTS:: @@ -1058,16 +1059,20 @@ cdef class lazy_list_from_function(lazy_list_generic): step 1 """ while len(self.cache) <= i: - self.cache.append(self.callable(len(self.cache))) + try: + value = self.callable(len(self.cache)) + except StopIteration: + return 1 + self.cache.append(value) def __reduce__(self): r""" TESTS:: sage: from sage.misc.lazy_list import lazy_list_from_function - sage: loads(dumps(lazy_list_from_function(euler_phi))) # optional - sage.libs.pari + sage: loads(dumps(lazy_list_from_function(euler_phi))) # needs sage.libs.pari lazy list [0, 1, 1, ...] - sage: loads(dumps(lazy_list_from_function(divisors, [None]))) # optional - sage.libs.pari + sage: loads(dumps(lazy_list_from_function(divisors, [None]))) lazy list [None, [1], [1, 2], ...] """ if self.start != 0 or self.step != 1: diff --git a/src/sage/misc/lazy_string.pyx b/src/sage/misc/lazy_string.pyx index 0907fb34cff..dd92fb38142 100644 --- a/src/sage/misc/lazy_string.pyx +++ b/src/sage/misc/lazy_string.pyx @@ -519,23 +519,24 @@ cdef class _LazyString(): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: from sage.misc.lazy_string import lazy_string - sage: f = lambda op,A,B:"unsupported operand parent(s) for %s: '%s' and '%s'"%(op,A,B) + sage: def f(op, A, B): + ....: return "unsupported operand parent(s) for %s: '%s' and '%s'" % (op, A, B) sage: R = GF(5) sage: S = GF(3) - sage: D = lazy_string(f, '+', R, S) - sage: D + sage: D = lazy_string(f, '+', R, S); D l"unsupported operand parent(s) for +: 'Finite Field of size 5' and 'Finite Field of size 3'" sage: D.update_lazy_string(('+', S, R), {}) Apparently, the lazy string got changed in-place:: - sage: D + sage: D # needs sage.rings.finite_rings l"unsupported operand parent(s) for +: 'Finite Field of size 3' and 'Finite Field of size 5'" TESTS:: - sage: D.update_lazy_string(None, None) + sage: D.update_lazy_string(None, None) # needs sage.rings.finite_rings Traceback (most recent call last): ... TypeError: Expected tuple, got NoneType diff --git a/src/sage/misc/map_threaded.py b/src/sage/misc/map_threaded.py index c5eba670052..db525e0ef6f 100644 --- a/src/sage/misc/map_threaded.py +++ b/src/sage/misc/map_threaded.py @@ -10,6 +10,7 @@ def map_threaded(function, sequence): EXAMPLES:: + sage: # needs sage.symbolic sage: map_threaded(log, [[1,2], [3,e]]) [[0, log(2)], [log(3), 1]] sage: map_threaded(log, [(1,2), (3,e)]) @@ -22,7 +23,7 @@ def map_threaded(function, sequence): map_threaded also works on any object with an apply_map method, e.g., on matrices:: - sage: map_threaded(lambda x: x^2, matrix([[1,2], [3,4]])) + sage: map_threaded(lambda x: x^2, matrix([[1,2], [3,4]])) # needs sage.modules [ 1 4] [ 9 16] diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index 090dea33293..a4f8ebb826e 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -456,19 +456,19 @@ def compose(f, g): sage: def g(x): return 3*x sage: def f(x): return x + 1 - sage: h1 = compose(f,g) - sage: h2 = compose(g,f) - sage: _ = var ('x') - sage: h1(x) + sage: h1 = compose(f, g) + sage: h2 = compose(g, f) + sage: _ = var('x') # needs sage.symbolic + sage: h1(x) # needs sage.symbolic 3*x + 1 - sage: h2(x) + sage: h2(x) # needs sage.symbolic 3*x + 3 :: - sage: _ = function('f g') - sage: _ = var ('x') - sage: compose(f,g)(x) + sage: _ = function('f g') # needs sage.symbolic + sage: _ = var('x') # needs sage.symbolic + sage: compose(f, g)(x) # needs sage.symbolic f(g(x)) """ @@ -492,22 +492,22 @@ def nest(f, n, x): EXAMPLES:: sage: def f(x): return x^2 + 1 - sage: x = var('x') - sage: nest(f, 3, x) + sage: x = var('x') # needs sage.symbolic + sage: nest(f, 3, x) # needs sage.symbolic ((x^2 + 1)^2 + 1)^2 + 1 :: - sage: _ = function('f') - sage: _ = var('x') - sage: nest(f, 10, x) + sage: _ = function('f') # needs sage.symbolic + sage: _ = var('x') # needs sage.symbolic + sage: nest(f, 10, x) # needs sage.symbolic f(f(f(f(f(f(f(f(f(f(x)))))))))) :: - sage: _ = function('f') - sage: _ = var('x') - sage: nest(f, 0, x) + sage: _ = function('f') # needs sage.symbolic + sage: _ = var('x') # needs sage.symbolic + sage: nest(f, 0, x) # needs sage.symbolic x """ @@ -554,6 +554,7 @@ def __rmul__(self, left): """ EXAMPLES:: + sage: # needs sage.modules sage: A = random_matrix(ZZ, 4) sage: while A.rank() != 4: ....: A = random_matrix(ZZ, 4) @@ -572,6 +573,7 @@ def __mul__(self, right): r""" EXAMPLES:: + sage: # needs sage.modules sage: A = matrix(RDF, 5, 5, 2) sage: b = vector(RDF, 5, range(5)) sage: v = A \ b @@ -626,10 +628,10 @@ def is_iterator(it) -> bool: sage: list(x) [4, 3, 2, 1] - sage: P = Partitions(3) - sage: is_iterator(P) + sage: P = Partitions(3) # needs sage.combinat + sage: is_iterator(P) # needs sage.combinat False - sage: is_iterator(iter(P)) + sage: is_iterator(iter(P)) # needs sage.combinat True """ # see trac #7398 for a discussion diff --git a/src/sage/misc/misc_c.pyx b/src/sage/misc/misc_c.pyx index d5492ba1e00..1a856b4ea36 100644 --- a/src/sage/misc/misc_c.pyx +++ b/src/sage/misc/misc_c.pyx @@ -585,7 +585,7 @@ cpdef list normalize_index(object key, int size): raise IndexError("index out of range") return [index] elif isinstance(key, slice): - return list(xrange(*key.indices(size))) + return list(range(*key.indices(size))) elif type(key) is tuple: index_tuple = key elif type(key) is list: @@ -743,7 +743,7 @@ def cyflush(): EXAMPLES:: sage: R. = QQ[] - sage: t^(sys.maxsize//2) + sage: t^(sys.maxsize//2) # needs sage.libs.flint Traceback (most recent call last): ... RuntimeError: FLINT exception diff --git a/src/sage/misc/nested_class.pyx b/src/sage/misc/nested_class.pyx index b601d6f7276..4863fe45554 100644 --- a/src/sage/misc/nested_class.pyx +++ b/src/sage/misc/nested_class.pyx @@ -162,18 +162,19 @@ cpdef modify_for_nested_pickle(cls, str name_prefix, module, first_run=True): ....: " class B2:", ....: " class C2: pass"] sage: import os - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython Before :trac:`9107`, the name of ``A1.B1.C1`` would have been wrong:: - sage: A1.B1.C1.__name__ # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: A1.B1.C1.__name__ 'A1.B1.C1' - sage: A1.B2.C2.__name__ # optional - sage.misc.cython + sage: A1.B2.C2.__name__ 'A1.B2.C2' - sage: A_module = sys.modules[A1.__module__] # optional - sage.misc.cython - sage: getattr(A_module, 'A1.B1.C1', 'Not found').__name__ # optional - sage.misc.cython + sage: A_module = sys.modules[A1.__module__] + sage: getattr(A_module, 'A1.B1.C1', 'Not found').__name__ 'A1.B1.C1' - sage: getattr(A_module, 'A1.B2.C2', 'Not found').__name__ # optional - sage.misc.cython + sage: getattr(A_module, 'A1.B2.C2', 'Not found').__name__ 'A1.B2.C2' """ diff --git a/src/sage/misc/package.py b/src/sage/misc/package.py index 8cab8fbb8e0..dcae7d0c0fc 100644 --- a/src/sage/misc/package.py +++ b/src/sage/misc/package.py @@ -176,18 +176,19 @@ def pip_installed_packages(normalization=None): EXAMPLES:: + sage: # optional - sage_spkg sage: from sage.misc.package import pip_installed_packages - sage: d = pip_installed_packages() # optional - sage_spkg - sage: 'scipy' in d or 'SciPy' in d # optional - sage_spkg + sage: d = pip_installed_packages() + sage: 'scipy' in d or 'SciPy' in d True - sage: d['beautifulsoup4'] # optional - sage_spkg beautifulsoup4 + sage: d['beautifulsoup4'] # optional - beautifulsoup4 '...' - sage: d['prompt-toolkit'] # optional - sage_spkg + sage: d['prompt-toolkit'] '...' - sage: d = pip_installed_packages(normalization='spkg') # optional - sage_spkg - sage: d['prompt_toolkit'] # optional - sage_spkg + sage: d = pip_installed_packages(normalization='spkg') + sage: d['prompt_toolkit'] '...' - sage: d['scipy'] # optional - sage_spkg + sage: d['scipy'] '...' """ with open(os.devnull, 'w') as devnull: @@ -293,27 +294,29 @@ def list_packages(*pkg_types: str, pkg_sources: List[str] = ['normal', 'pip', 's EXAMPLES:: + sage: # optional - sage_spkg sage: from sage.misc.package import list_packages - sage: L = list_packages('standard') # optional - sage_spkg - sage: sorted(L.keys()) # optional - sage_spkg, random + sage: L = list_packages('standard') + sage: sorted(L.keys()) # random ['alabaster', 'arb', 'babel', ... 'zlib'] - sage: sage_conf_info = L['sage_conf'] # optional - sage_spkg - sage: sage_conf_info.type # optional - sage_spkg + sage: sage_conf_info = L['sage_conf'] + sage: sage_conf_info.type 'standard' - sage: sage_conf_info.is_installed() # optional - sage_spkg + sage: sage_conf_info.is_installed() True - sage: sage_conf_info.source # optional - sage_spkg + sage: sage_conf_info.source 'script' - sage: L = list_packages(pkg_sources=['pip'], local=True) # optional - sage_spkg internet - sage: bp_info = L['biopython'] # optional - sage_spkg internet - sage: bp_info.type # optional - sage_spkg internet + sage: # optional - sage_spkg internet + sage: L = list_packages(pkg_sources=['pip'], local=True) + sage: bp_info = L['biopython'] + sage: bp_info.type 'optional' - sage: bp_info.source # optional - sage_spkg internet + sage: bp_info.source 'pip' Check the option ``exclude_pip``:: @@ -424,10 +427,11 @@ def installed_packages(exclude_pip=True): records of Python packages. Our ``SAGE_VENV`` is not necessarily the main Sage venv; it could be a user-created venv or a venv created by tox.):: + sage: # optional - sage_spkg sage: from sage.misc.package import installed_packages - sage: sorted(installed_packages().keys()) # optional - sage_spkg + sage: sorted(installed_packages().keys()) [...'conway_polynomials', ...] - sage: installed_packages()['conway_polynomials'] # optional - sage_spkg, random + sage: installed_packages()['conway_polynomials'] # random '0.5' .. SEEALSO:: @@ -534,11 +538,12 @@ def package_versions(package_type, local=False): EXAMPLES:: + sage: # optional - sage_spkg sage: from sage.misc.package import package_versions - sage: std = package_versions('standard', local=True) # optional - sage_spkg - sage: 'gap' in std # optional - sage_spkg + sage: std = package_versions('standard', local=True) + sage: 'gap' in std True - sage: std['zlib'] # optional - sage_spkg, random + sage: std['zlib'] # random ('1.2.11.p0', '1.2.11.p0') """ return {pkg.name: (pkg.installed_version, pkg.remote_version) for pkg in list_packages(package_type, local=local).values()} @@ -597,12 +602,13 @@ def optional_packages(): EXAMPLES:: + sage: # optional - sage_spkg sage: from sage.misc.package import optional_packages - sage: installed, not_installed = optional_packages() # optional - sage_spkg + sage: installed, not_installed = optional_packages() doctest:...: DeprecationWarning: ... - sage: 'biopython' in installed + not_installed # optional - sage_spkg + sage: 'biopython' in installed + not_installed True - sage: 'biopython' in installed # optional - sage_spkg biopython + sage: 'biopython' in installed # optional - biopython True """ from sage.misc.superseded import deprecation @@ -661,11 +667,12 @@ def package_manifest(package): EXAMPLES:: + sage: # optional - sage_spkg sage: from sage.misc.package import package_manifest - sage: manifest = package_manifest('conway_polynomials') # optional - sage_spkg - sage: manifest['package_name'] == 'conway_polynomials' # optional - sage_spkg + sage: manifest = package_manifest('conway_polynomials') + sage: manifest['package_name'] == 'conway_polynomials' True - sage: 'files' in manifest # optional - sage_spkg + sage: 'files' in manifest True Test a nonexistent package:: diff --git a/src/sage/misc/package_dir.py b/src/sage/misc/package_dir.py index d4e5cb3bc7a..218949ca11e 100644 --- a/src/sage/misc/package_dir.py +++ b/src/sage/misc/package_dir.py @@ -177,9 +177,9 @@ def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None): Not a package:: - sage: directory = os.path.join(sage.symbolic.__path__[0], 'ginac'); directory + sage: directory = os.path.join(sage.symbolic.__path__[0], 'ginac'); directory # needs sage.symbolic '.../sage/symbolic/ginac' - sage: is_package_or_sage_namespace_package_dir(directory) + sage: is_package_or_sage_namespace_package_dir(directory) # needs sage.symbolic False """ if os.path.exists(os.path.join(path, '__init__.py')): # ordinary package diff --git a/src/sage/misc/parser.pyx b/src/sage/misc/parser.pyx index 78c2d6d0169..ee5b041383c 100644 --- a/src/sage/misc/parser.pyx +++ b/src/sage/misc/parser.pyx @@ -478,21 +478,22 @@ cdef class Parser: sage: p.parse("1+2 == 3") True - sage: p = Parser(make_var=var) - sage: p.parse("a*b^c - 3a") + sage: p = Parser(make_var=var) # needs sage.symbolic + sage: p.parse("a*b^c - 3a") # needs sage.symbolic a*b^c - 3*a sage: R. = QQ[] - sage: p = Parser(make_var = {'x': x }) + sage: p = Parser(make_var={'x': x}) sage: p.parse("(x+1)^5-x") x^5 + 5*x^4 + 10*x^3 + 10*x^2 + 4*x + 1 sage: p.parse("(x+1)^5-x").parent() is R True - sage: p = Parser(make_float=RR, make_var=var, make_function={'foo': (lambda x: x*x+x)}) - sage: p.parse("1.5 + foo(b)") + sage: p = Parser(make_float=RR, make_var=var, # needs sage.symbolic + ....: make_function={'foo': (lambda x: x*x+x)}) + sage: p.parse("1.5 + foo(b)") # needs sage.symbolic b^2 + b + 1.50000000000000 - sage: p.parse("1.9").parent() + sage: p.parse("1.9").parent() # needs sage.symbolic Real Field with 53 bits of precision """ self.integer_constructor = make_int @@ -511,8 +512,8 @@ cdef class Parser: EXAMPLES:: - sage: from sage.calculus.calculus import SR_parser - sage: SR_parser._variable_constructor() + sage: from sage.calculus.calculus import SR_parser # needs sage.symbolic + sage: SR_parser._variable_constructor() # needs sage.symbolic """ import sage.repl.load @@ -239,13 +239,15 @@ def save(obj, filename, compress=True, **kwargs): sage: import tempfile sage: d = tempfile.TemporaryDirectory() - sage: a = matrix(2, [1,2,3,-5/2]) + sage: a = matrix(2, [1,2, 3,-5/2]) # needs sage.modules sage: objfile = os.path.join(d.name, 'test.sobj') sage: objfile_short = os.path.join(d.name, 'test') - sage: save(a, objfile) - sage: load(objfile_short) + sage: save(a, objfile) # needs sage.modules + sage: load(objfile_short) # needs sage.modules [ 1 2] [ 3 -5/2] + + sage: # needs sage.plot sage.schemes sage: E = EllipticCurve([-1,0]) sage: P = plot(E) sage: save(P, objfile_short) # saves the plot to "test.sobj" @@ -253,9 +255,11 @@ def save(obj, filename, compress=True, **kwargs): sage: save(P, os.path.join(d.name, "filename.with.some.wrong.ext")) Traceback (most recent call last): ... - ValueError: allowed file extensions for images are '.eps', '.pdf', '.pgf', '.png', '.ps', '.sobj', '.svg'! + ValueError: allowed file extensions for images are + '.eps', '.pdf', '.pgf', '.png', '.ps', '.sobj', '.svg'! sage: print(load(objfile)) Graphics object consisting of 2 graphics primitives + sage: save("A python string", os.path.join(d.name, 'test')) sage: load(objfile) 'A python string' @@ -435,7 +439,7 @@ def register_unpickle_override(module, name, callable, call_name=None): ....: self.__dict__ = D sage: __main__.SweeterPickle = SweeterPickle sage: register_unpickle_override('__main__', 'SourPickle', SweeterPickle) - sage: loads(gherkin) + sage: loads(gherkin) # needs sage.combinat [1, 2, 3] sage: loads(dumps(SweeterPickle([1, 2, 3]))) # check that pickles work for SweeterPickle [1, 2, 3] @@ -574,7 +578,7 @@ def unpickle_global(module, name): Test that :func:`register_unpickle_override` calls in lazily imported modules are respected:: - sage: unpickle_global('sage.combinat.root_system.type_A', 'ambient_space') + sage: unpickle_global('sage.combinat.root_system.type_A', 'ambient_space') # needs sage.modules """ unpickler = unpickle_override.get((module, name)) @@ -919,9 +923,9 @@ def loads(s, compress=True, **kwargs): EXAMPLES:: - sage: a = matrix(2, [1,2,3,-4/3]) - sage: s = dumps(a) - sage: loads(s) + sage: a = matrix(2, [1,2, 3,-4/3]) # needs sage.modules + sage: s = dumps(a) # needs sage.modules + sage: loads(s) # needs sage.modules [ 1 2] [ 3 -4/3] @@ -1158,7 +1162,7 @@ def make_None(*args, **kwds): EXAMPLES:: sage: from sage.misc.persist import make_None - sage: print(make_None(42, pi, foo='bar')) + sage: print(make_None(42, pi, foo='bar')) # needs sage.symbolic None """ return None diff --git a/src/sage/misc/prandom.py b/src/sage/misc/prandom.py index 19662a47adb..800ed60aedd 100644 --- a/src/sage/misc/prandom.py +++ b/src/sage/misc/prandom.py @@ -142,9 +142,9 @@ def choice(seq): EXAMPLES:: - sage: s = [choice(list(primes(10, 100))) for i in range(5)]; s # random # optional - sage.libs.pari + sage: s = [choice(list(primes(10, 100))) for i in range(5)]; s # random # needs sage.libs.pari [17, 47, 11, 31, 47] - sage: all(t in primes(10, 100) for t in s) # optional - sage.libs.pari + sage: all(t in primes(10, 100) for t in s) # needs sage.libs.pari True """ return _pyrand().choice(seq) @@ -227,9 +227,9 @@ def uniform(a, b): sage: 0.0 <= s <= 1.0 True - sage: s = uniform(e, pi); s # random # optional - sage.symbolic + sage: s = uniform(e, pi); s # random # needs sage.symbolic 0.5143475134191677*pi + 0.48565248658083227*e - sage: bool(e <= s <= pi) # optional - sage.symbolic + sage: bool(e <= s <= pi) # needs sage.symbolic True """ return _pyrand().uniform(a, b) diff --git a/src/sage/misc/randstate.pyx b/src/sage/misc/randstate.pyx index f2f55bc5c2c..06d6f8ce894 100644 --- a/src/sage/misc/randstate.pyx +++ b/src/sage/misc/randstate.pyx @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups sage.libs.gap sage.libs.ntl sage.libs.pari +# sage.doctest: needs sage.groups sage.libs.gap sage.libs.ntl sage.libs.pari r""" Random Number States @@ -679,8 +679,8 @@ cdef class randstate: seed the generator itself. However, we put the call in to make the coverage tester happy. :: - sage: current_randstate().set_seed_ntl(False) # optional - sage.libs.ntl - sage: ntl.ZZ_random(10^40) # optional - sage.libs.ntl + sage: current_randstate().set_seed_ntl(False) + sage: ntl.ZZ_random(10^40) 1495283511775355459459209288047895196007 """ global _ntl_seed_randstate @@ -699,10 +699,10 @@ cdef class randstate: EXAMPLES:: sage: set_random_seed(99900000999) - sage: current_randstate().set_seed_gap() # optional - sage.libs.gap - sage: gap.Random(1, 10^50) # optional - sage.libs.gap + sage: current_randstate().set_seed_gap() + sage: gap.Random(1, 10^50) 1496738263332555434474532297768680634540939580077 - sage: gap(35).SCRRandomString() # optional - sage.libs.gap + sage: gap(35).SCRRandomString() [ 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1 ] """ @@ -737,8 +737,8 @@ cdef class randstate: EXAMPLES:: sage: set_random_seed(987654321) - sage: current_randstate().set_seed_gp() # optional - sage.libs.pari - sage: gp.random() # optional - sage.libs.pari + sage: current_randstate().set_seed_gp() + sage: gp.random() 23289294 """ if gp is None: @@ -784,8 +784,8 @@ cdef class randstate: EXAMPLES:: sage: set_random_seed(5551212) - sage: current_randstate().set_seed_pari() # optional - sage.libs.pari - sage: pari.getrand().type() # optional - sage.libs.pari + sage: current_randstate().set_seed_pari() + sage: pari.getrand().type() 't_INT' """ global _pari_seed_randstate diff --git a/src/sage/misc/repr.py b/src/sage/misc/repr.py index 80265ac3cc3..ae873edea95 100644 --- a/src/sage/misc/repr.py +++ b/src/sage/misc/repr.py @@ -20,11 +20,11 @@ def coeff_repr(c, is_latex=False): sage: from sage.misc.repr import coeff_repr sage: coeff_repr(QQ(1/2)) '1/2' - sage: coeff_repr(-x^2) + sage: coeff_repr(-x^2) # needs sage.symbolic '(-x^2)' sage: coeff_repr(QQ(1/2), is_latex=True) '\\frac{1}{2}' - sage: coeff_repr(-x^2, is_latex=True) + sage: coeff_repr(-x^2, is_latex=True) # needs sage.symbolic '\\left(-x^{2}\\right)' """ if not is_latex: @@ -131,12 +131,13 @@ def repr_lincomb(terms, is_latex=False, scalar_mult="*", strip_one=False, Verify that :trac:`31672` is fixed:: + sage: # needs sage.symbolic sage: alpha = var("alpha") sage: repr_lincomb([(x, alpha)], is_latex=True) '\\alpha x' sage: A. = PolynomialRing(QQ) - sage: B. = FreeAlgebra(A) - sage: (psi * t)._latex_() + sage: B. = FreeAlgebra(A) # needs sage.combinat sage.modules + sage: (psi * t)._latex_() # needs sage.combinat sage.modules '\\psi t' """ # Setting scalar_mult: symbol used for scalar multiplication diff --git a/src/sage/misc/reset.pyx b/src/sage/misc/reset.pyx index 50893dfea17..23cad11fb77 100644 --- a/src/sage/misc/reset.pyx +++ b/src/sage/misc/reset.pyx @@ -20,22 +20,22 @@ def reset(vars=None, attached=False): If vars is specified, just restore the value of vars and leave all other variables alone (i.e., call restore). - Note that the variables in the set sage.misc.reset.EXCLUDE are + Note that the variables in the set :obj:`sage.misc.reset.EXCLUDE` are excluded from being reset. INPUT: - - ``vars`` - a list, or space or comma separated string (default: - None), variables to restore + - ``vars`` -- a list, or space or comma separated string (default: + ``None``), variables to restore - - ``attached`` - boolean (default: False), if ``vars`` is not None, + - ``attached`` -- boolean (default: ``False``), if ``vars`` is not None, whether to detach all attached files EXAMPLES:: sage: x = 5 sage: reset() - sage: x + sage: x # needs sage.symbolic x sage: fn = tmp_filename(ext='foo.py') @@ -57,6 +57,7 @@ def reset(vars=None, attached=False): Confirm that assumptions don't survive a reset (:trac:`10855`):: + sage: # needs sage.symbolic sage: assume(x > 3) sage: assumptions() [x > 3] @@ -95,7 +96,7 @@ def restore(vars=None): INPUT: - - ``vars`` - string or list (default: None), if not None, restores + - ``vars`` -- string or list (default: ``None``), if not ``None``, restores just the given variables to the default value. EXAMPLES:: @@ -108,9 +109,9 @@ def restore(vars=None): Rational Field sage: x 10 - sage: y = var('y') + sage: y = var('y') # needs sage.symbolic sage: restore('x y') - sage: x + sage: x # needs sage.symbolic x sage: y Traceback (most recent call last): @@ -119,7 +120,7 @@ def restore(vars=None): sage: x = 10; y = 15/3; QQ='red' sage: ww = 15 sage: restore() - sage: x, QQ, ww + sage: x, QQ, ww # needs sage.symbolic (x, Rational Field, 15) sage: restore('ww') sage: ww diff --git a/src/sage/misc/rest_index_of_methods.py b/src/sage/misc/rest_index_of_methods.py index 2ddea66c2db..d1b102829c9 100644 --- a/src/sage/misc/rest_index_of_methods.py +++ b/src/sage/misc/rest_index_of_methods.py @@ -14,7 +14,7 @@ from sage.misc.sageinspect import is_function_or_cython_function as _isfunction -def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): +def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True, root=None): r""" Return a ReST table describing a list of functions. @@ -35,13 +35,19 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): precedence over the automatically computed name for the functions. Only used when ``list_of_entries`` is a list. - - ``sort`` (boolean; ``True``) -- whether to sort the list of methods - lexicographically. + - ``sort`` -- boolean (default: ``True``); whether to sort the list of + methods lexicographically. - - ``only_local_functions`` (boolean; ``True``) -- if ``list_of_entries`` is - a module, ``only_local_functions = True`` means that imported functions - will be filtered out. This can be useful to disable for making indexes of - e.g. catalog modules such as :mod:`sage.coding.codes_catalog`. + - ``only_local_functions`` -- boolean (default: ``True``); if + ``list_of_entries`` is a module, ``only_local_functions = True`` means + that imported functions will be filtered out. This can be useful to + disable for making indexes of e.g. catalog modules such as + :mod:`sage.coding.codes_catalog`. + + - ``root`` -- module or class (default: ``None``); the module, or class, + whose elements are to be listed. This is needed to recover the class when + this method is called from :meth:`gen_thematic_rest_table_index` (see + :issue:`36178`). .. WARNING:: @@ -52,7 +58,7 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): EXAMPLES:: sage: from sage.misc.rest_index_of_methods import gen_rest_table_index - sage: print(gen_rest_table_index([graphs.PetersenGraph])) + sage: print(gen_rest_table_index([graphs.PetersenGraph])) # needs sage.graphs .. csv-table:: :class: contentstable :widths: 30, 70 @@ -70,14 +76,14 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): :func:`~sage.misc.rest_index_of_methods.doc_index` @ Attribute an index name to a function. :func:`~sage.misc.rest_index_of_methods.gen_rest_table_index` @ Return a ReST table describing a list of functions. - :func:`~sage.misc.rest_index_of_methods.gen_thematic_rest_table_index` @ Return a ReST string of thematically sorted function (or methods) of a module (or class). - :func:`~sage.misc.rest_index_of_methods.list_of_subfunctions` @ Returns the functions (resp. methods) of a given module (resp. class) with their names. + :func:`~sage.misc.rest_index_of_methods.gen_thematic_rest_table_index` @ Return a ReST string of thematically sorted functions (or methods) of a module (or class). + :func:`~sage.misc.rest_index_of_methods.list_of_subfunctions` @ Return the functions (resp. methods) of a given module (resp. class) with their names. The table of a class:: - sage: print(gen_rest_table_index(Graph)) + sage: print(gen_rest_table_index(Graph)) # needs sage.graphs .. csv-table:: :class: contentstable :widths: 30, 70 @@ -103,6 +109,7 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): The inherited methods do not show up:: + sage: # needs sage.graphs sage: gen_rest_table_index(sage.combinat.posets.lattices.FiniteLatticePoset).count('\n') < 75 True sage: from sage.graphs.generic_graph import GenericGraph @@ -122,8 +129,8 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): :func:`~sage.misc.rest_index_of_methods.doc_index` @ Attribute an index name to a function. :func:`~sage.misc.rest_index_of_methods.gen_rest_table_index` @ Return a ReST table describing a list of functions. - :func:`~sage.misc.rest_index_of_methods.gen_thematic_rest_table_index` @ Return a ReST string of thematically sorted function (or methods) of a module (or class). - :func:`~sage.misc.rest_index_of_methods.list_of_subfunctions` @ Returns the functions (resp. methods) of a given module (resp. class) with their names. + :func:`~sage.misc.rest_index_of_methods.gen_thematic_rest_table_index` @ Return a ReST string of thematically sorted functions (or methods) of a module (or class). + :func:`~sage.misc.rest_index_of_methods.list_of_subfunctions` @ Return the functions (resp. methods) of a given module (resp. class) with their names. sage: print(gen_rest_table_index(sage.misc.rest_index_of_methods, only_local_functions=False)) @@ -133,18 +140,25 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): :delim: @ :func:`~sage.misc.rest_index_of_methods.doc_index` @ Attribute an index name to a function. - :func:`~sage.misc.rest_index_of_methods.gen_thematic_rest_table_index` @ Return a ReST string of thematically sorted function (or methods) of a module (or class). - :func:`~sage.misc.rest_index_of_methods.list_of_subfunctions` @ Returns the functions (resp. methods) of a given module (resp. class) with their names. + :func:`~sage.misc.rest_index_of_methods.gen_thematic_rest_table_index` @ Return a ReST string of thematically sorted functions (or methods) of a module (or class). + :func:`~sage.misc.rest_index_of_methods.list_of_subfunctions` @ Return the functions (resp. methods) of a given module (resp. class) with their names. A function that is imported into a class under a different name is listed under its 'new' name:: - sage: 'cliques_maximum' in gen_rest_table_index(Graph) + sage: 'cliques_maximum' in gen_rest_table_index(Graph) # needs sage.graphs True - sage: 'all_max_cliques`' in gen_rest_table_index(Graph) + sage: 'all_max_cliques`' in gen_rest_table_index(Graph) # needs sage.graphs False + + Check that :issue:`36178` is fixed:: + + sage: print(gen_rest_table_index(Graph)) # needs sage.graphs + ... + :meth:`~sage.graphs.graph.Graph.independent_set` @ Return a maximum independent set. + ... """ if names is None: names = {} @@ -168,14 +182,24 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): if sort: list_of_entries.sort(key=fname) + obj_or_root_is_class = False + if inspect.isclass(root): + obj_or_root_is_class = True + class_name = root.__name__ + module_name = root.__module__ + elif inspect.isclass(obj): + obj_or_root_is_class = True + class_name = obj.__name__ + module_name = obj.__module__ + for e in list_of_entries: if inspect.ismethod(e): link = ":meth:`~{module}.{cls}.{func}`".format( module=e.im_class.__module__, cls=e.im_class.__name__, func=fname(e)) - elif _isfunction(e) and inspect.isclass(obj): + elif _isfunction(e) and obj_or_root_is_class: link = ":meth:`~{module}.{cls}.{func}`".format( - module=obj.__module__, cls=obj.__name__, func=fname(e)) + module=module_name, cls=class_name, func=fname(e)) elif _isfunction(e): link = ":func:`~{module}.{func}`".format( module=e.__module__, func=fname(e)) @@ -203,15 +227,15 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): def list_of_subfunctions(root, only_local_functions=True): r""" - Returns the functions (resp. methods) of a given module (resp. class) with their names. + Return the functions (resp. methods) of a given module (resp. class) with their names. INPUT: - ``root`` -- the module, or class, whose elements are to be listed. - - ``only_local_functions`` (boolean; ``True``) -- if ``root`` is a module, - ``only_local_functions = True`` means that imported functions will be - filtered out. This can be useful to disable for making indexes of + - ``only_local_functions`` -- boolean (default: ``True``); if ``root`` is a + module, ``only_local_functions = True`` means that imported functions will + be filtered out. This can be useful to disable for making indexes of e.g. catalog modules such as :mod:`sage.coding.codes_catalog`. OUTPUT: @@ -223,17 +247,17 @@ def list_of_subfunctions(root, only_local_functions=True): EXAMPLES:: sage: from sage.misc.rest_index_of_methods import list_of_subfunctions - sage: l = list_of_subfunctions(Graph)[0] - sage: Graph.bipartite_color in l + sage: l = list_of_subfunctions(Graph)[0] # needs sage.graphs + sage: Graph.bipartite_color in l # needs sage.graphs True TESTS: A ``staticmethod`` is not callable. We must handle them correctly, however:: - sage: class A: + sage: class A: # needs sage.graphs ....: x = staticmethod(Graph.order) - sage: list_of_subfunctions(A) + sage: list_of_subfunctions(A) # needs sage.graphs ([], {: 'x'}) @@ -255,39 +279,49 @@ def local_filter(f,name): else: return inspect.isclass(root) or not (f is gen_rest_table_index) - functions = {getattr(root,name):name for name,f in root.__dict__.items() if - (not name.startswith('_') and # private functions - not hasattr(f,'issue_number') and # deprecated functions - not inspect.isclass(f) and # classes - callable(getattr(f,'__func__',f)) and # e.g. GenericGraph.graphics_array_defaults - local_filter(f,name)) # possibly filter imported functions + def can_import(f): + # poke it to provoke a lazy import to resolve + try: + hasattr(f, 'xyz') + except ImportError: + return False + return True + + functions = {getattr(root, name): name for name, f in root.__dict__.items() if + (not name.startswith('_') and # private functions + can_import(f) and # unresolved lazy imports + not hasattr(f, 'issue_number') and # deprecated functions + not inspect.isclass(f) and # classes + callable(getattr(f, '__func__', f)) and # e.g. GenericGraph.graphics_array_defaults + local_filter(f, name)) # possibly filter imported functions } return list(functions.keys()), functions -def gen_thematic_rest_table_index(root,additional_categories=None,only_local_functions=True): +def gen_thematic_rest_table_index(root, additional_categories=None, only_local_functions=True): r""" - Return a ReST string of thematically sorted function (or methods) of a module (or class). + Return a ReST string of thematically sorted functions (or methods) of a + module (or class). INPUT: - ``root`` -- the module, or class, whose elements are to be listed. - - ``additional_categories`` -- a dictionary associating a category (given as - a string) to a function's name. Can be used when the decorator - :func:`doc_index` does not work on a function. + - ``additional_categories`` -- dictionary (default: ``None``); a dictionary + associating a category (given as a string) to a function's name. Can be + used when the decorator :func:`doc_index` does not work on a function. - - ``only_local_functions`` (boolean; ``True``) -- if ``root`` is a module, - ``only_local_functions = True`` means that imported functions will be - filtered out. This can be useful to disable for making indexes of + - ``only_local_functions`` -- boolean (default: ``True``); if ``root`` is a + module, ``only_local_functions = True`` means that imported functions will + be filtered out. This can be useful to disable for making indexes of e.g. catalog modules such as :mod:`sage.coding.codes_catalog`. EXAMPLES:: sage: from sage.misc.rest_index_of_methods import gen_thematic_rest_table_index, list_of_subfunctions - sage: l = list_of_subfunctions(Graph)[0] - sage: Graph.bipartite_color in l + sage: l = list_of_subfunctions(Graph)[0] # needs sage.graphs + sage: Graph.bipartite_color in l # needs sage.graphs True """ from collections import defaultdict @@ -307,7 +341,7 @@ def gen_thematic_rest_table_index(root,additional_categories=None,only_local_fun except AttributeError: doc_ind = "Unsorted" theme_to_function[doc_ind].append(f) - s = ["**"+theme+"**\n\n"+gen_rest_table_index(list_of_functions,names=names) + s = ["**" + theme + "**\n\n" + gen_rest_table_index(list_of_functions, names=names, root=root) for theme, list_of_functions in sorted(theme_to_function.items())] return "\n\n".join(s) @@ -335,8 +369,10 @@ def doc_index(name): 'Wouhouuuuu' """ def hey(f): - setattr(f,"doc_index",name) + setattr(f, "doc_index", name) return f return hey -__doc__ = __doc__.format(INDEX_OF_FUNCTIONS=gen_rest_table_index([gen_rest_table_index])) + +__doc__ = __doc__.format(INDEX_OF_FUNCTIONS=gen_rest_table_index([gen_rest_table_index, + gen_thematic_rest_table_index])) diff --git a/src/sage/misc/sage_eval.py b/src/sage/misc/sage_eval.py index 8d0416a4cfd..ec6d94543f9 100644 --- a/src/sage/misc/sage_eval.py +++ b/src/sage/misc/sage_eval.py @@ -71,7 +71,7 @@ def sage_eval(source, locals=None, cmds='', preparse=True): 36 sage: eval('bernoulli(6)') 36 - sage: sage_eval('bernoulli(6)') + sage: sage_eval('bernoulli(6)') # needs sage.libs.flint 1/42 :: @@ -117,7 +117,7 @@ def sage_eval(source, locals=None, cmds='', preparse=True): :: - sage: sage_eval(('f(x) = x^2', 'f(3)')) + sage: sage_eval(('f(x) = x^2', 'f(3)')) # needs sage.symbolic 9 sage: vars = {'rt2': sqrt(2.0)} sage: sage_eval(('rt2 += 1', 'rt2', vars)) @@ -131,6 +131,7 @@ def sage_eval(source, locals=None, cmds='', preparse=True): :: + sage: # needs sage.libs.gap sage: R. = PolynomialRing(RationalField()) sage: gap.eval('R:=PolynomialRing(Rationals,["x"]);') 'Rationals[x]' @@ -212,8 +213,9 @@ def sageobj(x, vars=None): EXAMPLES:: - sage: type(sageobj(gp('34/56'))) + sage: type(sageobj(gp('34/56'))) # needs sage.libs.pari + sage: n = 5/2 sage: sageobj(n) is n True @@ -224,6 +226,7 @@ def sageobj(x, vars=None): This illustrates interfaces:: + sage: # needs sage.libs.pari sage: f = gp('2/3') sage: type(f) @@ -231,6 +234,8 @@ def sageobj(x, vars=None): 2/3 sage: type(f._sage_()) + + sage: # needs sage.libs.gap sage: a = gap(939393/2433) sage: a._sage_() 313131/811 diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py index f86cd1f8f46..66e78ecccbc 100644 --- a/src/sage/misc/sage_input.py +++ b/src/sage/misc/sage_input.py @@ -13,7 +13,7 @@ sage: sage_input(3) 3 - sage: sage_input((polygen(RR) + RR(pi))^2, verify=True) # optional - sage.symbolic + sage: sage_input((polygen(RR) + RR(pi))^2, verify=True) # needs sage.symbolic # Verified R. = RR[] x^2 + 6.2831853071795862*x + 9.869604401089358 @@ -172,6 +172,11 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.rings.real_mpfi', 'RealIntervalFieldElement') +lazy_import('sage.rings.complex_interval', 'ComplexIntervalFieldElement') + def sage_input(x, preparse=True, verify=False, allow_locals=False): r""" @@ -224,6 +229,7 @@ def sage_input(x, preparse=True, verify=False, allow_locals=False): The result of :func:`sage_input` is actually a pair of strings with a special ``__repr__`` method to print nicely.:: + sage: # needs sage.rings.real_mpfr sage.symbolic sage: r = sage_input(RealField(20)(pi), verify=True) sage: r # Verified @@ -373,9 +379,9 @@ def __call__(self, x, coerced=False): sage: sib = SageInputBuilder() sage: sib.result(sib(GF(17)(5), True)) 5 - sage: sib.result(sib(RealField(200)(1.5), True)) + sage: sib.result(sib(RealField(200)(1.5), True)) # needs sage.rings.real_mpfr 1.5000000000000000000000000000000000000000000000000000000000000 - sage: sib.result(sib(RealField(200)(1.5), 2)) + sage: sib.result(sib(RealField(200)(1.5), 2)) # needs sage.rings.real_mpfr 1.5 Since :func:`sage_input` directly calls this method, all @@ -395,13 +401,13 @@ def __call__(self, x, coerced=False): sage: sage_input(float(-infinity), preparse=True, verify=True) # Verified -float(infinity) - sage: sage_input(float(NaN), preparse=True, verify=True) + sage: sage_input(float(NaN), preparse=True, verify=True) # needs sage.symbolic # Verified float(NaN) - sage: sage_input(float(-pi), preparse=True, verify=True) + sage: sage_input(float(-pi), preparse=True, verify=True) # needs sage.symbolic # Verified float(-RR(3.1415926535897931)) - sage: sage_input(float(42), preparse=True, verify=True) + sage: sage_input(float(42), preparse=True, verify=True) # needs sage.rings.real_mpfr # Verified float(42) sage: sage_input("Hello, world\n", verify=True) @@ -422,7 +428,7 @@ def __call__(self, x, coerced=False): sage: sage_input('unicode with spectral: \u1234\U00012345', verify=True) # Verified 'unicode with spectral: \u1234\U00012345' - sage: sage_input((2, 3.5, 'Hi'), verify=True) + sage: sage_input((2, 3.5, 'Hi'), verify=True) # needs sage.rings.real_mpfr # Verified (2, 3.5, 'Hi') sage: sage_input(lambda x: x) @@ -581,7 +587,7 @@ def float_str(self, n): sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() - sage: sib.result(sib.float_str(repr(RR(e)))) + sage: sib.result(sib.float_str(repr(RR(e)))) # needs sage.symbolic 2.71828182845905 """ return SIE_literal_stringrep(self, n) @@ -1747,7 +1753,7 @@ class SIE_literal_stringrep(SIE_literal): sage: sib = SageInputBuilder() sage: isinstance(sib(3), SIE_literal_stringrep) True - sage: isinstance(sib(3.14159, True), SIE_literal_stringrep) + sage: isinstance(sib(3.14159, True), SIE_literal_stringrep) # needs sage.rings.real_mpfr True sage: isinstance(sib.name('pi'), SIE_literal_stringrep) True @@ -2153,7 +2159,7 @@ def __init__(self, sib, values, is_list): sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() - sage: sib((3.5, -2)) + sage: sib((3.5, -2)) # needs sage.rings.real_mpfr {tuple: ({atomic:3.5}, {unop:- {atomic:2}})} sage: sib(["Hello", "world"]) {list: ({atomic:'Hello'}, {atomic:'world'})} @@ -2238,10 +2244,12 @@ class SIE_dict(SageInputExpression): sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() - sage: sib.dict([('TeX', RR(pi)), ('Metafont', RR(e))]) - {dict: {{atomic:'TeX'}:{call: {atomic:RR}({atomic:3.1415926535897931})}, {atomic:'Metafont'}:{call: {atomic:RR}({atomic:2.7182818284590451})}}} + sage: sib.dict([('TeX', RR(pi)), ('Metafont', RR(e))]) # needs sage.symbolic + {dict: {{atomic:'TeX'}:{call: {atomic:RR}({atomic:3.1415926535897931})}, + {atomic:'Metafont'}:{call: {atomic:RR}({atomic:2.7182818284590451})}}} sage: sib.dict({-40:-40, 0:32, 100:212}) - {dict: {{unop:- {atomic:40}}:{unop:- {atomic:40}}, {atomic:0}:{atomic:32}, {atomic:100}:{atomic:212}}} + {dict: {{unop:- {atomic:40}}:{unop:- {atomic:40}}, + {atomic:0}:{atomic:32}, {atomic:100}:{atomic:212}}} """ def __init__(self, sib, entries): @@ -2812,14 +2820,14 @@ def _sie_add_command(self, sif): We also can't use the preparser syntax if there is a conflict between generator names. For example, this works:: - sage: sage_input((polygen(ZZ), polygen(GF(17), 'y'))) # optional - sage.rings.finite_rings + sage: sage_input((polygen(ZZ), polygen(GF(17), 'y'))) R1. = ZZ[] R2. = GF(17)[] (x, y) but this can't use the preparser syntax.:: - sage: sage_input((polygen(ZZ), polygen(GF(17)))) # optional - sage.rings.finite_rings + sage: sage_input((polygen(ZZ), polygen(GF(17)))) R1 = ZZ['x'] x1 = R1.gen() R2 = GF(17)['x'] @@ -3470,9 +3478,7 @@ def verify_same(a, b): assert(a.parent() == b.parent()) else: assert(type(a) is type(b)) - from sage.rings.real_mpfi import is_RealIntervalFieldElement - from sage.rings.complex_interval import is_ComplexIntervalFieldElement - if is_RealIntervalFieldElement(a) or is_ComplexIntervalFieldElement(a): + if isinstance(a, (RealIntervalFieldElement, ComplexIntervalFieldElement)): assert(a.endpoints() == b.endpoints()), "Expected %s == %s" % (a, b) return diff --git a/src/sage/misc/sage_timeit.py b/src/sage/misc/sage_timeit.py index 8250b461dd4..2f9c255543b 100644 --- a/src/sage/misc/sage_timeit.py +++ b/src/sage/misc/sage_timeit.py @@ -37,7 +37,7 @@ class SageTimeitResult(): EXAMPLES:: sage: from sage.misc.sage_timeit import SageTimeitResult - sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) + sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) # needs sage.symbolic 3 loops, best of 5: 3.1415927 ms per loop :: @@ -47,10 +47,10 @@ class SageTimeitResult(): sage: number = 7 sage: repeat = 13 sage: precision = int(5) - sage: best = pi / 10 ^ 9 + sage: best = pi / 10 ^ 9 # needs sage.symbolic sage: order = 3 - sage: stats = (number, repeat, precision, best * scaling[order], units[order]) - sage: SageTimeitResult(stats) + sage: stats = (number, repeat, precision, best * scaling[order], units[order]) # needs sage.symbolic + sage: SageTimeitResult(stats) # needs sage.symbolic 7 loops, best of 13: 3.1416 ns per loop If the third argument is not a Python integer, a ``TypeError`` is raised:: @@ -69,10 +69,10 @@ def __init__(self, stats, series=None): EXAMPLES:: sage: from sage.misc.sage_timeit import SageTimeitResult - sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) + sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) # needs sage.symbolic 3 loops, best of 5: 3.1415927 ms per loop - sage: s = SageTimeitResult( (3, 5, int(8), pi, 'ms'), [1.0,1.1,0.5]) - sage: s.series + sage: s = SageTimeitResult( (3, 5, int(8), pi, 'ms'), [1.0,1.1,0.5]) # needs sage.symbolic + sage: s.series # needs sage.symbolic [1.00000000000000, 1.10000000000000, 0.500000000000000] """ self.stats = stats @@ -85,8 +85,8 @@ def __repr__(self): EXAMPLES:: sage: from sage.misc.sage_timeit import SageTimeitResult - sage: stats = (1, 2, int(3), pi, 'ns') - sage: SageTimeitResult(stats) #indirect doctest + sage: stats = (1, 2, int(3), pi, 'ns') # needs sage.symbolic + sage: SageTimeitResult(stats) #indirect doctest # needs sage.symbolic 1 loop, best of 2: 3.14 ns per loop """ if self.stats[0] > 1: @@ -153,12 +153,12 @@ def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, prec sage: s = sage_timeit('10^2', globals(), repeat=1000) sage: len(s.series) 1000 - sage: mean(s.series) # random output + sage: mean(s.series) # random output # needs sage.modules 3.1298141479492283e-07 sage: min(s.series) # random output 2.9258728027343752e-07 - sage: t = stats.TimeSeries(s.series) - sage: t.scale(10^6).plot_histogram(bins=20,figsize=[12,6], ymax=2) + sage: t = stats.TimeSeries(s.series) # needs numpy sage.modules + sage: t.scale(10^6).plot_histogram(bins=20,figsize=[12,6], ymax=2) # needs numpy sage.modules sage.plot Graphics object consisting of 20 graphics primitives @@ -168,7 +168,7 @@ def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, prec sage: from sage.misc.sage_timeit import sage_timeit sage: from os import linesep as CR sage: # sage_timeit(r'a = 2\\nb=131\\nfactor(a^b-1)') - sage: sage_timeit('a = 2' + CR + 'b=131' + CR + 'factor(a^b-1)', + sage: sage_timeit('a = 2' + CR + 'b=131' + CR + 'factor(a^b-1)', # needs sage.libs.pari ....: globals(), number=10) 10 loops, best of 3: ... per loop diff --git a/src/sage/misc/sage_timeit_class.pyx b/src/sage/misc/sage_timeit_class.pyx index d6b038c9de9..5537148e358 100644 --- a/src/sage/misc/sage_timeit_class.pyx +++ b/src/sage/misc/sage_timeit_class.pyx @@ -40,7 +40,7 @@ class SageTimeit: The input can contain newlines:: - sage: timeit("a = 2\nb=131\nfactor(a^b-1)", number=25) + sage: timeit("a = 2\nb=131\nfactor(a^b-1)", number=25) # needs sage.libs.pari 25 loops, best of 3: ... per loop .. SEEALSO:: :func:`runsnake` diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 78a6e1fe3d3..fb11088dac9 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -20,7 +20,7 @@ sage: from sage.env import SAGE_DOC sage: docfilename = os.path.join(SAGE_DOC, 'html', 'en', 'reference', 'calculus', 'sage', 'symbolic', 'expression.html') - sage: with open(docfilename) as fobj: # optional - sagemath_doc_html + sage: with open(docfilename) as fobj: # needs sagemath_doc_html ....: for line in fobj: ....: if "#sage.symbolic.expression.Expression.numerical_approx" in line: ....: print(line) @@ -653,10 +653,10 @@ def format(s, embedded=False): EXAMPLES:: sage: from sage.misc.sagedoc import format - sage: identity_matrix(2).rook_vector.__doc__[191:263] + sage: identity_matrix(2).rook_vector.__doc__[191:263] # needs sage.modules 'Let `A` be an `m` by `n` (0,1)-matrix. We identify `A` with a chessboard' - sage: format(identity_matrix(2).rook_vector.__doc__[191:263]) + sage: format(identity_matrix(2).rook_vector.__doc__[191:263]) # needs sage.modules 'Let A be an m by n (0,1)-matrix. We identify A with a chessboard\n' If the first line of the string is 'nodetex', remove 'nodetex' but @@ -671,16 +671,16 @@ def format(s, embedded=False): '<<>>') 'identity_matrix>>>\n' - sage: format('<<>>') + sage: format('<<>>') # needs sage.modules '...Definition: identity_matrix(...' - sage: format('<<>>')[:28] # optional - sphinx + sage: format('<<>>')[:28] # needs sphinx 'Definition: identity_matrix(' TESTS: We check that the todo Sphinx extension is correctly activated:: - sage: sage.misc.sagedoc.format(sage.combinat.ranker.on_fly.__doc__) # optional - sphinx + sage: sage.misc.sagedoc.format(sage.combinat.ranker.on_fly.__doc__) # needs sphinx " Returns ... Todo: add tests as in combinat::rankers\n" In the following use case, the ``nodetex`` directive would have been ignored prior @@ -694,9 +694,9 @@ def format(s, embedded=False): ....: " `x \\geq y`", ....: " '''", ....: " return -x"] - sage: cython('\n'.join(cython_code)) # optional - sage.misc.cython + sage: cython('\n'.join(cython_code)) # needs sage.misc.cython sage: from sage.misc.sageinspect import sage_getdoc - sage: print(sage_getdoc(testfunc)) # optional - sage.misc.cython + sage: print(sage_getdoc(testfunc)) # needs sage.misc.cython This is a doc string with raw latex @@ -724,7 +724,7 @@ def format(s, embedded=False): Check that backslashes are preserved in code blocks (:trac:`29140`):: - sage: format('::\n' # optional - sphinx + sage: format('::\n' # needs sphinx ....: '\n' ....: r' sage: print(r"\\\\.")' '\n' ....: r' \\\\.') @@ -821,7 +821,7 @@ def format_src(s): sage: from sage.misc.sagedoc import format_src sage: format_src('unladen swallow') 'unladen swallow' - sage: format_src('<<>>')[5:15] + sage: format_src('<<>>')[5:15] # needs sage.combinat sage.modules 'Sq(*nums):' """ if not isinstance(s, str): @@ -907,7 +907,7 @@ def _search_src_or_doc(what, string, extra1='', extra2='', extra3='', sage: from sage.misc.sagedoc import _search_src_or_doc sage: len(_search_src_or_doc('src', r'matrix\(', 'incidence_structures', 'self', 'combinat', interact=False).splitlines()) > 1 True - sage: 'abvar/homology' in _search_src_or_doc('doc', 'homology', 'variety', interact=False) # optional - sagemath_doc_html, long time (4s on sage.math, 2012) + sage: 'abvar/homology' in _search_src_or_doc('doc', 'homology', 'variety', interact=False) # long time (4s on sage.math, 2012), needs sagemath_doc_html True sage: 'divisors' in _search_src_or_doc('src', '^ *def prime', interact=False) True @@ -1098,20 +1098,21 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', You can search for "matrix" by typing ``search_src("matrix")``. This particular search will produce many results:: - sage: len(search_src("matrix", interact=False).splitlines()) # random # long time + sage: len(search_src("matrix", interact=False).splitlines()) # random # long time 9522 You can restrict to the Sage calculus code with ``search_src("matrix", module="sage.calculus")``, and this produces many fewer results:: - sage: len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random + sage: len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random 26 Note that you can do tab completion on the ``module`` string. Another way to accomplish a similar search:: - sage: len(search_src("matrix", path_re="calc", interact=False).splitlines()) > 15 + sage: len(search_src("matrix", path_re="calc", # needs sage.modules + ....: interact=False).splitlines()) > 15 True The following produces an error because the string 'fetch(' is a @@ -1124,11 +1125,11 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', To fix this, *escape* the parenthesis with a backslash:: - sage: print(search_src(r" fetch\(", "def", interact=False)) # random # long time + sage: print(search_src(r" fetch\(", "def", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): matrix/matrix0.pxd: cdef fetch(self, key) - sage: print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time + sage: print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): As noted above, the search is case-insensitive, but you can make it @@ -1162,22 +1163,22 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', :: - sage: print(search_src(r'^ *sage[:] .*search_src\(', interact=False)) # long time - misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) # random # long time - misc/sagedoc.py:... len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random - misc/sagedoc.py:... len(search_src("matrix", path_re="calc", interact=False).splitlines()) > 15 - misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) - misc/sagedoc.py:... print(search_src(r" fetch\(", "def", interact=False)) # random # long time - misc/sagedoc.py:... print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time - misc/sagedoc.py:... s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0 - misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > 0 - misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix', interact=False, ignore_case=False); s.find('x') > 0 - misc/sagedoc.py:... len(search_src('log', 'derivative', interact=False).splitlines()) < 40 - misc/sagedoc.py:... len(search_src('log', 'derivative', interact=False, multiline=True).splitlines()) > 70 - misc/sagedoc.py:... print(search_src(r'^ *sage[:] .*search_src\(', interact=False)) # long time - misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) > 9000 # long time - misc/sagedoc.py:... print(search_src('matrix', 'column', 'row', 'sub', 'start', 'index', interact=False)) # random # long time - misc/sagedoc.py:... sage: results = search_src('format_search_as_html', # long time + sage: print(search_src(r'^ *sage[:] .*search_src\(', interact=False)) # long time + misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines())... + misc/sagedoc.py:... len(search_src("matrix", module="sage.calculus", interact=False).splitlines())... + misc/sagedoc.py:... len(search_src("matrix", path_re="calc"... + misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False))... + misc/sagedoc.py:... print(search_src(r" fetch\(", "def", interact=False))... + misc/sagedoc.py:... print(search_src(r" fetch\(", "def", "pyx", interact=False))... + misc/sagedoc.py:... s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0... + misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > 0... + misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix',... + misc/sagedoc.py:... len(search_src('log', 'derivative', interact=False).splitlines()) < 40... + misc/sagedoc.py:... len(search_src('log', 'derivative'... + misc/sagedoc.py:... print(search_src(r'^ *sage[:] .*search_src\(', interact=False))... + misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) > 9000... + misc/sagedoc.py:... print(search_src('matrix', 'column', 'row', 'sub',... + misc/sagedoc.py:... sage: results = search_src('format_search_as_html',... TESTS: @@ -1230,13 +1231,14 @@ def search_doc(string, extra1='', extra2='', extra3='', extra4='', counting the length of ``search_doc('tree', interact=False).splitlines()`` gives the number of matches. :: - sage: N = len(search_doc('tree', interact=False).splitlines()) # optional - sagemath_doc_html, long time - sage: L = search_doc('tree', whole_word=True, interact=False).splitlines() # optional - sagemath_doc_html, long time - sage: len(L) < N # optional - sagemath_doc_html, long time + sage: # long time, needs sagemath_doc_html + sage: N = len(search_doc('tree', interact=False).splitlines()) + sage: L = search_doc('tree', whole_word=True, interact=False).splitlines() + sage: len(L) < N True sage: import re sage: tree_re = re.compile(r'(^|\W)tree(\W|$)', re.I) - sage: all(tree_re.search(l) for l in L) # optional - sagemath_doc_html, long time + sage: all(tree_re.search(l) for l in L) True """ return _search_src_or_doc('doc', string, extra1=extra1, extra2=extra2, @@ -1265,11 +1267,11 @@ def search_def(name, extra1='', extra2='', extra3='', extra4='', See the documentation for :func:`search_src` for more examples. :: - sage: print(search_def("fetch", interact=False)) # random # long time + sage: print(search_def("fetch", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): matrix/matrix0.pxd: cdef fetch(self, key) - sage: print(search_def("fetch", path_re="pyx", interact=False)) # random # long time + sage: print(search_def("fetch", path_re="pyx", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): """ # since we convert name to a regular expression, we need to do the @@ -1396,8 +1398,8 @@ def my_getsource(obj, oname=''): EXAMPLES:: sage: from sage.misc.sagedoc import my_getsource - sage: s = my_getsource(identity_matrix) - sage: s[15:34] + sage: s = my_getsource(identity_matrix) # needs sage.modules + sage: s[15:34] # needs sage.modules 'def identity_matrix' """ try: @@ -1433,9 +1435,9 @@ class _sage_doc: EXAMPLES:: - sage: browse_sage_doc._open("reference", testing=True)[0] # optional - sagemath_doc_html, indirect doctest + sage: browse_sage_doc._open("reference", testing=True)[0] # needs sagemath_doc_html 'http://localhost:8000/doc/live/reference/index.html' - sage: browse_sage_doc(identity_matrix, 'rst')[-107:-47] + sage: browse_sage_doc(identity_matrix, 'rst')[-107:-47] # needs sage.modules 'Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring' """ def __init__(self): @@ -1463,19 +1465,19 @@ def __call__(self, obj, output='html', view=True): EXAMPLES:: - sage: browse_sage_doc(identity_matrix, 'rst') + sage: browse_sage_doc(identity_matrix, 'rst') # needs sage.modules "...**File:**...**Type:**...**Definition:** identity_matrix..." - sage: identity_matrix.__doc__ in browse_sage_doc(identity_matrix, 'rst') + sage: identity_matrix.__doc__ in browse_sage_doc(identity_matrix, 'rst') # needs sage.modules True - sage: browse_sage_doc(identity_matrix, 'html', False) # optional - sphinx sagemath_doc_html + sage: browse_sage_doc(identity_matrix, 'html', False) # needs sagemath_doc_html sphinx '...div...File:...Type:...Definition:...identity_matrix...' In the 'text' version, double colons have been replaced with single ones (among other things):: - sage: '::' in browse_sage_doc(identity_matrix, 'rst') + sage: '::' in browse_sage_doc(identity_matrix, 'rst') # needs sage.modules True - sage: '::' in browse_sage_doc(identity_matrix, 'text') # optional - sphinx + sage: '::' in browse_sage_doc(identity_matrix, 'text') # needs sphinx False """ if output != 'html' and view: @@ -1605,9 +1607,9 @@ def _open(self, name, testing=False): EXAMPLES:: - sage: browse_sage_doc._open("reference", testing=True)[0] # optional - sagemath_doc_html + sage: browse_sage_doc._open("reference", testing=True)[0] # needs sagemath_doc_html 'http://localhost:8000/doc/live/reference/index.html' - sage: browse_sage_doc._open("tutorial", testing=True)[1] # optional - sagemath_doc_html + sage: browse_sage_doc._open("tutorial", testing=True)[1] # needs sagemath_doc_html '.../html/en/tutorial/index.html' """ url = self._base_url + os.path.join(name, "index.html") @@ -1637,8 +1639,8 @@ def reference(self): EXAMPLES:: - sage: reference() # indirect doctest, not tested - sage: manual() # indirect doctest, not tested + sage: reference() # indirect doctest, not tested + sage: manual() # indirect doctest, not tested """ self._open("reference") diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 7511b28fbc9..88ac75ea843 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -105,10 +105,11 @@ By :trac:`9976` and :trac:`14017`, introspection also works for interactively defined Cython code, and with rather tricky argument lines:: - sage: cython('def foo(unsigned int x=1, a=\')"\', b={not (2+1==3):\'bar\'}, *args, **kwds): return') # optional - sage.misc.cython - sage: print(sage_getsource(foo)) # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython('def foo(unsigned int x=1, a=\')"\', b={not (2+1==3):\'bar\'}, *args, **kwds): return') + sage: print(sage_getsource(foo)) def foo(unsigned int x=1, a=')"', b={not (2+1==3):'bar'}, *args, **kwds): return - sage: sage_getargspec(foo) # optional - sage.misc.cython + sage: sage_getargspec(foo) FullArgSpec(args=['x', 'a', 'b'], varargs='args', varkw='kwds', defaults=(1, ')"', {False: 'bar'}), kwonlyargs=[], kwonlydefaults=None, annotations={}) """ @@ -162,8 +163,8 @@ def is_function_or_cython_function(obj): functions:: sage: from ipywidgets.widgets.interaction import signature - sage: from sage.dynamics.complex_dynamics.mandel_julia_helper import fast_mandelbrot_plot - sage: signature(fast_mandelbrot_plot) # random + sage: from sage.dynamics.complex_dynamics.mandel_julia_helper import fast_mandelbrot_plot # needs sage.symbolic + sage: signature(fast_mandelbrot_plot) # random # needs sage.symbolic """ # We use type(obj) instead of just obj to avoid __getattr__(). @@ -223,7 +224,11 @@ def isclassinstance(obj): return (not inspect.isclass(obj) and hasattr(obj, '__class__') and hasattr(obj.__class__, '__module__') and - obj.__class__.__module__ not in builtin_mods) + obj.__class__.__module__ not in builtin_mods and + # Starting with Cython 3, Cython's builtin types have __module__ set + # to the shared module names like _cython_3_0_0. + not (isinstance(obj.__class__.__module__, str) and + obj.__class__.__module__.startswith('_cython_'))) # Parse strings of form "File: sage/rings/rational.pyx (starting at line 1080)" @@ -252,16 +257,16 @@ def _extract_embedded_position(docstring): sage: from sage.misc.sageinspect import _extract_embedded_position sage: import inspect - sage: _extract_embedded_position(inspect.getdoc(var))[1][-21:] + sage: _extract_embedded_position(inspect.getdoc(var))[1][-21:] # needs sage.symbolic 'sage/calculus/var.pyx' TESTS: The following has been fixed in :trac:`13916`:: - sage: cython('''cpdef test_funct(x,y): return''') # optional - sage.misc.cython - sage: func_doc = inspect.getdoc(test_funct) # optional - sage.misc.cython - sage: with open(_extract_embedded_position(func_doc)[1]) as f: # optional - sage.misc.cython + sage: cython('''cpdef test_funct(x,y): return''') # needs sage.misc.cython + sage: func_doc = inspect.getdoc(test_funct) # needs sage.misc.cython + sage: with open(_extract_embedded_position(func_doc)[1]) as f: # needs sage.misc.cython ....: print(f.read()) cpdef test_funct(x,y): return @@ -272,10 +277,10 @@ def _extract_embedded_position(docstring): sage: from sage.env import DOT_SAGE sage: from sage.misc.sage_ostools import restore_cwd - sage: with restore_cwd(DOT_SAGE): # optional - sage.misc.cython + sage: with restore_cwd(DOT_SAGE): # needs sage.misc.cython ....: cython('''cpdef test_funct(x,y): return''') - sage: func_doc = inspect.getdoc(test_funct) # optional - sage.misc.cython - sage: with open(_extract_embedded_position(func_doc)[1]) as f: # optional - sage.misc.cython + sage: func_doc = inspect.getdoc(test_funct) # needs sage.misc.cython + sage: with open(_extract_embedded_position(func_doc)[1]) as f: # needs sage.misc.cython ....: print(f.read()) cpdef test_funct(x,y): return @@ -1118,7 +1123,7 @@ def _sage_getargspec_from_ast(source): FullArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, varkw=None, defaults=(2, {'a': [4, 5.5, False]}, (None, True)), kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: from_ast(s) == inspect.getfullargspec(context['f']) True - sage: set(from_ast(sms.sage_getsource(x)) == inspect.getfullargspec(x) for x in [factor, identity_matrix, Graph.__init__]) + sage: set(from_ast(sms.sage_getsource(x)) == inspect.getfullargspec(x) for x in [factor, identity_matrix, Graph.__init__]) # needs sage.graphs sage.modules {True} """ ast_args = ast.parse(source.lstrip()).body[0].args @@ -1203,17 +1208,21 @@ def _sage_getargspec_cython(source): sage: def dummy_python(self, *args, x=1): pass sage: sgc("def dummy_python(self, *args, x=1): pass") - FullArgSpec(args=['self', 'x'], varargs='args', varkw=None, defaults=(1,), kwonlyargs=[], kwonlydefaults=None, annotations={}) - sage: cython("def dummy_cython(self, *args, x=1): pass") + FullArgSpec(args=['self', 'x'], varargs='args', varkw=None, defaults=(1,), + kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: cython("def dummy_cython(self, *args, x=1): pass") # needs sage.misc.cython sage: sgc("def dummy_cython(self, *args, x=1): pass") - FullArgSpec(args=['self', 'x'], varargs='args', varkw=None, defaults=(1,), kwonlyargs=[], kwonlydefaults=None, annotations={}) + FullArgSpec(args=['self', 'x'], varargs='args', varkw=None, defaults=(1,), + kwonlyargs=[], kwonlydefaults=None, annotations={}) In some examples above, a syntax error was raised when a type definition contains a pointer. An exception is made for ``char*``, since C strings are acceptable input in public Cython functions:: sage: sgc('def f(char *x = "a string", z = {(1,2,3): True}): pass') - FullArgSpec(args=['x', 'z'], varargs=None, varkw=None, defaults=('a string', {(1, 2, 3): True}), kwonlyargs=[], kwonlydefaults=None, annotations={}) + FullArgSpec(args=['x', 'z'], varargs=None, varkw=None, + defaults=('a string', {(1, 2, 3): True}), + kwonlyargs=[], kwonlydefaults=None, annotations={}) AUTHORS: @@ -1352,34 +1361,33 @@ def sage_getfile(obj): sage: from sage.misc.sageinspect import sage_getfile sage: sage_getfile(sage.rings.rational) '...sage/rings/rational.pyx' - sage: sage_getfile(Sq) + sage: sage_getfile(Sq) # needs sage.combinat sage.modules '...sage/algebras/steenrod/steenrod_algebra.py' - sage: sage_getfile(x) + sage: sage_getfile(x) # needs sage.symbolic '...sage/symbolic/expression.pyx' The following tests against some bugs fixed in :trac:`9976`:: - sage: obj = sage.combinat.partition_algebra.SetPartitionsAk - sage: obj = sage.combinat.partition_algebra.SetPartitionsAk - sage: sage_getfile(obj) + sage: obj = sage.combinat.partition_algebra.SetPartitionsAk # needs sage.combinat sage.modules + sage: sage_getfile(obj) # needs sage.combinat sage.modules '...sage/combinat/partition_algebra.py' And here is another bug, fixed in :trac:`11298`:: sage: P. = QQ[] - sage: sage_getfile(P) + sage: sage_getfile(P) # needs sage.libs.singular '...sage/rings/polynomial/multi_polynomial_libsingular...' A problem fixed in :trac:`16309`:: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: class Bar: pass ....: cdef class Foo: pass ....: ''') - sage: sage_getfile(Bar) # optional - sage.misc.cython + sage: sage_getfile(Bar) # needs sage.misc.cython '...pyx' - sage: sage_getfile(Foo) # optional - sage.misc.cython + sage: sage_getfile(Foo) # needs sage.misc.cython '...pyx' By :trac:`18249`, we return an empty string for Python builtins. In that @@ -1433,9 +1441,9 @@ def sage_getfile_relative(obj): sage: from sage.misc.sageinspect import sage_getfile_relative sage: sage_getfile_relative(sage.rings.rational) 'sage/rings/rational.pyx' - sage: sage_getfile_relative(Sq) + sage: sage_getfile_relative(Sq) # needs sage.combinat sage.modules 'sage/algebras/steenrod/steenrod_algebra.py' - sage: sage_getfile_relative(x) + sage: sage_getfile_relative(x) # needs sage.symbolic 'sage/symbolic/expression.pyx' sage: sage_getfile_relative(range) '' @@ -1470,27 +1478,20 @@ def sage_getargspec(obj): INPUT: - ``obj``, any callable object + - ``obj`` -- any callable object OUTPUT: - An ``ArgSpec`` is returned. This is a named tuple - ``(args, varargs, keywords, defaults)``. - - - ``args`` is a list of the argument names (it may contain nested lists). - - - ``varargs`` and ``keywords`` are the names of the ``*`` and ``**`` - arguments or ``None``. - - - ``defaults`` is an `n`-tuple of the default values of the last `n` arguments. + A named tuple :class:`FullArgSpec` is returned, as specified by the + Python library function :func:`inspect.getfullargspec`. NOTE: - If the object has a method ``_sage_argspec_`` then the output of + If the object has a method ``_sage_argspec_``, then the output of that method is transformed into a named tuple and then returned. - If a class instance has a method ``_sage_src_`` then its output - is studied to determine the argspec. This is because currently + If a class instance has a method ``_sage_src_``, then its output + is studied to determine the argspec. This is because currently the :class:`~sage.misc.cachefunc.CachedMethod` decorator has no ``_sage_argspec_`` method. @@ -1500,50 +1501,63 @@ def sage_getargspec(obj): sage: def f(x, y, z=1, t=2, *args, **keywords): ....: pass sage: sage_getargspec(f) - FullArgSpec(args=['x', 'y', 'z', 't'], varargs='args', varkw='keywords', defaults=(1, 2), kwonlyargs=[], kwonlydefaults=None, annotations={}) + FullArgSpec(args=['x', 'y', 'z', 't'], varargs='args', varkw='keywords', + defaults=(1, 2), kwonlyargs=[], kwonlydefaults=None, annotations={}) We now run sage_getargspec on some functions from the Sage library:: - sage: sage_getargspec(identity_matrix) - FullArgSpec(args=['ring', 'n', 'sparse'], varargs=None, varkw=None, defaults=(0, False), kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: sage_getargspec(identity_matrix) # needs sage.modules + FullArgSpec(args=['ring', 'n', 'sparse'], varargs=None, varkw=None, + defaults=(0, False), kwonlyargs=[], kwonlydefaults=None, + annotations={}) sage: sage_getargspec(factor) - FullArgSpec(args=['n', 'proof', 'int_', 'algorithm', 'verbose'], varargs=None, varkw='kwds', defaults=(None, False, 'pari', 0), kwonlyargs=[], kwonlydefaults=None, annotations={}) + FullArgSpec(args=['n', 'proof', 'int_', 'algorithm', 'verbose'], + varargs=None, varkw='kwds', defaults=(None, False, 'pari', 0), + kwonlyargs=[], kwonlydefaults=None, annotations={}) - In the case of a class or a class instance, the ``ArgSpec`` of the + In the case of a class or a class instance, the :class:`FullArgSpec` of the ``__new__``, ``__init__`` or ``__call__`` method is returned:: sage: P. = QQ[] - sage: sage_getargspec(P) - FullArgSpec(args=['base_ring', 'n', 'names', 'order'], varargs=None, varkw=None, defaults=('degrevlex',), kwonlyargs=[], kwonlydefaults=None, annotations={}) - sage: sage_getargspec(P.__class__) - FullArgSpec(args=['self', 'x'], varargs='args', varkw='kwds', defaults=(0,), kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: sage_getargspec(P) # needs sage.libs.singular + FullArgSpec(args=['base_ring', 'n', 'names', 'order'], + varargs=None, varkw=None, defaults=('degrevlex',), + kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: sage_getargspec(P.__class__) # needs sage.libs.singular + FullArgSpec(args=['self', 'x'], varargs='args', varkw='kwds', defaults=(0,), + kwonlyargs=[], kwonlydefaults=None, annotations={}) The following tests against various bugs that were fixed in :trac:`9976`:: - sage: from sage.rings.polynomial.real_roots import bernstein_polynomial_factory_ratlist - sage: sage_getargspec(bernstein_polynomial_factory_ratlist.coeffs_bitsize) - FullArgSpec(args=['self'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) - sage: from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid - sage: sage_getargspec(BooleanMonomialMonoid.gen) - FullArgSpec(args=['self', 'i'], varargs=None, varkw=None, defaults=(0,), kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: from sage.rings.polynomial.real_roots import bernstein_polynomial_factory_ratlist # needs sage.modules + sage: sage_getargspec(bernstein_polynomial_factory_ratlist.coeffs_bitsize) # needs sage.modules + FullArgSpec(args=['self'], varargs=None, varkw=None, defaults=None, + kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid # needs sage.rings.polynomial.pbori + sage: sage_getargspec(BooleanMonomialMonoid.gen) # needs sage.rings.polynomial.pbori + FullArgSpec(args=['self', 'i'], varargs=None, varkw=None, defaults=(0,), + kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: I = P*[x,y] - sage: sage_getargspec(I.groebner_basis) + sage: sage_getargspec(I.groebner_basis) # needs sage.libs.singular FullArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'], - varargs='args', varkw='kwds', defaults=('', None, None, False), kwonlyargs=[], kwonlydefaults=None, annotations={}) - sage: cython("cpdef int foo(x,y) except -1: return 1") - sage: sage_getargspec(foo) - FullArgSpec(args=['x', 'y'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) - - If a ``functools.partial`` instance is involved, we see no other meaningful solution + varargs='args', varkw='kwds', defaults=('', None, None, False), + kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: cython("cpdef int foo(x,y) except -1: return 1") # needs sage.misc.cython + sage: sage_getargspec(foo) # needs sage.misc.cython + FullArgSpec(args=['x', 'y'], varargs=None, varkw=None, defaults=None, + kwonlyargs=[], kwonlydefaults=None, annotations={}) + + If a :func:`functools.partial` instance is involved, we see no other meaningful solution than to return the argspec of the underlying function:: - sage: def f(a,b,c,d=1): - ....: return a+b+c+d + sage: def f(a, b, c, d=1): + ....: return a + b + c + d sage: import functools - sage: f1 = functools.partial(f, 1,c=2) + sage: f1 = functools.partial(f, 1, c=2) sage: sage_getargspec(f1) - FullArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, varkw=None, defaults=(1,), kwonlyargs=[], kwonlydefaults=None, annotations={}) + FullArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, varkw=None, defaults=(1,), + kwonlyargs=[], kwonlydefaults=None, annotations={}) TESTS: @@ -1554,11 +1568,12 @@ def sage_getargspec(obj): an instance of that class does not coincide with the argspec of its call method. That behaviour is intended, since a decorated method appears to have the generic signature - ``*args,**kwds``, but in fact it is only supposed to be called + ``*args, **kwds``, but in fact it is only supposed to be called with the arguments requested by the underlying undecorated method. We saw an easy example above, namely ``I.groebner_basis``. Here is a more difficult one:: + sage: # needs sage.misc.cython sage: cython_code = [ ....: 'cdef class MyClass:', ....: ' def _sage_src_(self):', @@ -1576,26 +1591,32 @@ def foo(x, a=')"', b={(2+1):'bar', not 1:3, 3<<4:5}): return sage: sorted(spec.defaults[1].items(), key=lambda x: str(x)) [(3, 'bar'), (48, 5), (False, 3)] sage: sage.misc.sageinspect.sage_getargspec(O.__call__) - FullArgSpec(args=['self', 'm', 'n'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) + FullArgSpec(args=['self', 'm', 'n'], varargs=None, varkw=None, defaults=None, + kwonlyargs=[], kwonlydefaults=None, annotations={}) :: - sage: cython('def foo(x, a=\'\\\')"\', b={not (2+1==3):\'bar\'}): return') - sage: print(sage.misc.sageinspect.sage_getsource(foo)) + sage: cython('def foo(x, a=\'\\\')"\', b={not (2+1==3):\'bar\'}): return') # needs sage.misc.cython + sage: print(sage.misc.sageinspect.sage_getsource(foo)) # needs sage.misc.cython def foo(x, a='\')"', b={not (2+1==3):'bar'}): return - sage: sage.misc.sageinspect.sage_getargspec(foo) - FullArgSpec(args=['x', 'a', 'b'], varargs=None, varkw=None, defaults=('\')"', {False: 'bar'}), kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: sage.misc.sageinspect.sage_getargspec(foo) # needs sage.misc.cython + FullArgSpec(args=['x', 'a', 'b'], varargs=None, varkw=None, + defaults=('\')"', {False: 'bar'}), + kwonlyargs=[], kwonlydefaults=None, annotations={}) The following produced a syntax error before the patch at :trac:`11913`, see also :trac:`26906`:: - sage: sage.misc.sageinspect.sage_getargspec(r.lm) # optional - rpy2 - FullArgSpec(args=['self'], varargs='args', varkw='kwds', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: sage.misc.sageinspect.sage_getargspec(r.lm) # optional - rpy2 + FullArgSpec(args=['self'], varargs='args', varkw='kwds', defaults=None, + kwonlyargs=[], kwonlydefaults=None, annotations={}) The following was fixed in :trac:`16309`:: - sage: cython(''' # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython( + ....: ''' ....: class Foo: ....: @staticmethod ....: def join(categories, bint as_list = False, tuple ignore_axioms=(), tuple axioms=()): pass @@ -1613,8 +1634,9 @@ def foo(x, a='\')"', b={not (2+1==3):'bar'}): return Test that :trac:`17009` is fixed:: - sage: sage_getargspec(gap) - FullArgSpec(args=['self', 'x', 'name'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={}) + sage: sage_getargspec(gap) # needs sage.libs.gap + FullArgSpec(args=['self', 'x', 'name'], varargs=None, varkw=None, + defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={}) By :trac:`17814`, the following gives the correct answer (previously, the defaults would have been found ``None``):: @@ -1867,9 +1889,9 @@ def sage_getdef(obj, obj_name=''): EXAMPLES:: sage: from sage.misc.sageinspect import sage_getdef - sage: sage_getdef(identity_matrix) + sage: sage_getdef(identity_matrix) # needs sage.modules '(ring, n=0, sparse=False)' - sage: sage_getdef(identity_matrix, 'identity_matrix') + sage: sage_getdef(identity_matrix, 'identity_matrix') # needs sage.modules 'identity_matrix(ring, n=0, sparse=False)' Check that :trac:`6848` has been fixed:: @@ -2034,7 +2056,7 @@ def sage_getdoc_original(obj): If an instance of a class does not have its own docstring, the docstring of its class results:: - sage: sage_getdoc_original(sage.plot.colors.aliceblue) == sage_getdoc_original(sage.plot.colors.Color) + sage: sage_getdoc_original(sage.plot.colors.aliceblue) == sage_getdoc_original(sage.plot.colors.Color) # needs sage.plot True """ @@ -2077,7 +2099,7 @@ def sage_getdoc(obj, obj_name='', embedded=False): EXAMPLES:: sage: from sage.misc.sageinspect import sage_getdoc - sage: sage_getdoc(identity_matrix)[87:124] + sage: sage_getdoc(identity_matrix)[87:124] # needs sage.modules 'Return the n x n identity matrix over' sage: def f(a,b,c,d=1): return a+b+c+d ... @@ -2130,9 +2152,9 @@ def sage_getsource(obj): EXAMPLES:: sage: from sage.misc.sageinspect import sage_getsource - sage: sage_getsource(identity_matrix)[19:60] + sage: sage_getsource(identity_matrix)[19:60] # needs sage.modules 'identity_matrix(ring, n=0, sparse=False):' - sage: sage_getsource(identity_matrix)[19:60] + sage: sage_getsource(identity_matrix)[19:60] # needs sage.modules 'identity_matrix(ring, n=0, sparse=False):' AUTHORS: @@ -2177,7 +2199,9 @@ class ParentMethods: The following was fixed in :trac:`16309`:: - sage: cython(''' # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython( + ....: ''' ....: class A: ....: def __init__(self): ....: "some init doc" @@ -2309,25 +2333,25 @@ def sage_getsourcelines(obj): EXAMPLES:: sage: from sage.misc.sageinspect import sage_getsourcelines - sage: sage_getsourcelines(matrix)[1] + sage: sage_getsourcelines(matrix)[1] # needs sage.modules 21 - sage: sage_getsourcelines(matrix)[0][0] + sage: sage_getsourcelines(matrix)[0][0] # needs sage.modules 'def matrix(*args, **kwds):\n' Some classes customize this using a ``_sage_src_lines_`` method, which gives the source lines of a class instance, but not the class itself. We demonstrate this for :class:`CachedFunction`:: - sage: cachedfib = cached_function(fibonacci) - sage: sage_getsourcelines(cachedfib)[0][0] + sage: cachedfib = cached_function(fibonacci) # needs sage.combinat + sage: sage_getsourcelines(cachedfib)[0][0] # needs sage.combinat 'def fibonacci(n, algorithm="pari") -> Integer:\n' - sage: sage_getsourcelines(type(cachedfib))[0][0] + sage: sage_getsourcelines(type(cachedfib))[0][0] # needs sage.combinat 'cdef class CachedFunction():\n' TESTS:: - sage: cython('''cpdef test_funct(x,y): return''') # optional - sage.misc.cython - sage: sage_getsourcelines(test_funct) # optional - sage.misc.cython + sage: cython('''cpdef test_funct(x,y): return''') # needs sage.misc.cython + sage: sage_getsourcelines(test_funct) # needs sage.misc.cython (['cpdef test_funct(x,y): return\n'], 1) The following tests that an instance of ``functools.partial`` is correctly @@ -2345,22 +2369,22 @@ def sage_getsourcelines(obj): sage: P. = QQ[] sage: I = P*[x,y] - sage: sage_getsourcelines(P) + sage: sage_getsourcelines(P) # needs sage.libs.singular (['cdef class MPolynomialRing_libsingular(MPolynomialRing_base):\n', '\n', ' def __cinit__(self):\n', ...) - sage: sage_getsourcelines(I) + sage: sage_getsourcelines(I) # needs sage.libs.singular ([...'class MPolynomialIdeal(MPolynomialIdeal_singular_repr,\n', ...) - sage: x = var('x') - sage: lines, lineno = sage_getsourcelines(x); lines[0:5] + sage: x = var('x') # needs sage.symbolic + sage: lines, lineno = sage_getsourcelines(x); lines[0:5] # needs sage.symbolic ['cdef class Expression(...):\n', '\n', ' cdef GEx _gobj\n', '\n', ' cpdef object pyobject(self):\n'] - sage: lines[-1] # last line + sage: lines[-1] # last line # needs sage.symbolic ' return S\n' We show some enhancements provided by :trac:`11768`. First, we @@ -2547,6 +2571,7 @@ def sage_getvariablename(self, omit_underscore_names=True): EXAMPLES:: + sage: # needs sage.modules sage: from sage.misc.sageinspect import sage_getvariablename sage: A = random_matrix(ZZ, 100) sage: sage_getvariablename(A) @@ -2557,7 +2582,7 @@ def sage_getvariablename(self, omit_underscore_names=True): If an object is not assigned to a variable, an empty list is returned:: - sage: sage_getvariablename(random_matrix(ZZ, 60)) + sage: sage_getvariablename(random_matrix(ZZ, 60)) # needs sage.modules [] """ result = [] diff --git a/src/sage/misc/session.pyx b/src/sage/misc/session.pyx index de649f80425..31454dac993 100644 --- a/src/sage/misc/session.pyx +++ b/src/sage/misc/session.pyx @@ -80,6 +80,8 @@ from sage.misc.persist import load, save, loads, dumps state_at_init = None +CythonFunctionType = type(lambda: None) + def init(state=None): """ Initialize some dictionaries needed by the :func:`show_identifiers`, @@ -311,7 +313,7 @@ def save_session(name='sage_session', verbose=False): for k in show_identifiers(hidden = True): try: x = state[k] - if isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType, type)): + if isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType, CythonFunctionType, type)): raise TypeError('{} is a function, method, class or type'.format(k)) # We attempt to pickle *and* unpickle every variable to diff --git a/src/sage/misc/sh.py b/src/sage/misc/sh.py index a16c987731f..968cb48cb74 100644 --- a/src/sage/misc/sh.py +++ b/src/sage/misc/sh.py @@ -32,5 +32,6 @@ def eval(self, code, globals=None, locals=None): # gets printed when doing %sh in the notebook. return '' + # Create the sh object, so that %sh mode works in the notebook. sh = Sh() diff --git a/src/sage/misc/superseded.py b/src/sage/misc/superseded.py index c158317ca5a..6a9b38159cb 100644 --- a/src/sage/misc/superseded.py +++ b/src/sage/misc/superseded.py @@ -107,7 +107,8 @@ def deprecation_cython(issue_number, message, stacklevel=3): with the same callsite reference as `deprecation` in a python function, whereas `deprecation` in a cython function does not:: - sage: cython( # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython( ....: ''' ....: from sage.misc.superseded import deprecation_cython, deprecation ....: def foo1(): @@ -117,7 +118,7 @@ def deprecation_cython(issue_number, message, stacklevel=3): ....: ''') sage: def foo3(): ....: deprecation(100, "boo") - sage: if True: # Execute the three "with" blocks as one doctest # optional - sage.misc.cython + sage: if True: # Execute the three "with" blocks as one doctest ....: with warnings.catch_warnings(record=True) as w1: ....: warnings.simplefilter("always") ....: foo1() @@ -127,9 +128,9 @@ def deprecation_cython(issue_number, message, stacklevel=3): ....: with warnings.catch_warnings(record=True) as w3: ....: warnings.simplefilter("always") ....: foo3() - sage: w1[0].filename == w3[0].filename # optional - sage.misc.cython + sage: w1[0].filename == w3[0].filename True - sage: w2[0].filename == w3[0].filename # optional - sage.misc.cython + sage: w2[0].filename == w3[0].filename False """ warning(issue_number, message, DeprecationWarning, stacklevel) @@ -353,9 +354,9 @@ def __init__(self, issue_number, func, module, instance=None, unbound=None): TESTS:: sage: from sage.misc.superseded import deprecated_function_alias - sage: g = deprecated_function_alias(13109, number_of_partitions) + sage: g = deprecated_function_alias(13109, number_of_partitions) # needs sage.combinat sage: from sage.misc.superseded import deprecated_function_alias - sage: g.__doc__ + sage: g.__doc__ # needs sage.combinat 'Deprecated: Use :func:`number_of_partitions` instead.\nSee :trac:`13109` for details.\n\n' """ _check_issue_number(issue_number) @@ -383,8 +384,8 @@ def __name__(self): TESTS:: sage: from sage.misc.superseded import deprecated_function_alias - sage: g = deprecated_function_alias(13109, number_of_partitions) - sage: g.__name__ + sage: g = deprecated_function_alias(13109, number_of_partitions) # needs sage.combinat + sage: g.__name__ # needs sage.combinat 'g' sage: from sage.misc.superseded import deprecated_function_alias @@ -396,14 +397,14 @@ def __name__(self): sage: cls().old_meth.__name__ 'old_meth' - sage: cython('\n'.join([ # optional - sage.misc.cython + sage: cython('\n'.join([ # needs sage.misc.cython ....: r"from sage.misc.superseded import deprecated_function_alias", ....: r"cdef class cython_cls():", ....: r" def new_cython_meth(self):", ....: r" return 1", ....: r" old_cython_meth = deprecated_function_alias(13109, new_cython_meth)" ....: ])) - sage: cython_cls().old_cython_meth.__name__ # optional - sage.misc.cython + sage: cython_cls().old_cython_meth.__name__ # needs sage.misc.cython 'old_cython_meth' """ # first look through variables in stack frames @@ -515,9 +516,10 @@ def deprecated_function_alias(issue_number, func): EXAMPLES:: sage: from sage.misc.superseded import deprecated_function_alias - sage: g = deprecated_function_alias(13109, number_of_partitions) - sage: g(5) - doctest:...: DeprecationWarning: g is deprecated. Please use sage.combinat.partition.number_of_partitions instead. + sage: g = deprecated_function_alias(13109, number_of_partitions) # needs sage.combinat sage.libs.flint + sage: g(5) # needs sage.combinat sage.libs.flint + doctest:...: DeprecationWarning: g is deprecated. + Please use sage.combinat.partition.number_of_partitions instead. See https://github.com/sagemath/sage/issues/13109 for details. 7 diff --git a/src/sage/misc/table.py b/src/sage/misc/table.py index 978a29f65ec..34410b103d2 100644 --- a/src/sage/misc/table.py +++ b/src/sage/misc/table.py @@ -106,7 +106,8 @@ class table(SageObject): information. The same goes for ``header_column``. Passing lists for both arguments simultaneously is not supported. :: - sage: table([(x,n(sin(x), digits=2)) for x in [0..3]], header_row=["$x$", r"$\sin(x)$"], frame=True) + sage: table([(x,n(sin(x), digits=2)) for x in [0..3]], # needs sage.symbolic + ....: header_row=["$x$", r"$\sin(x)$"], frame=True) +-----+-----------+ | $x$ | $\sin(x)$ | +=====+===========+ @@ -122,7 +123,9 @@ class table(SageObject): You can create the transpose of this table in several ways, for example, "by hand," that is, changing the data defining the table:: - sage: table(rows=[[x for x in [0..3]], [n(sin(x), digits=2) for x in [0..3]]], header_column=['$x$', r'$\sin(x)$'], frame=True) + sage: table(rows=[[x for x in [0..3]], # needs sage.symbolic + ....: [n(sin(x), digits=2) for x in [0..3]]], + ....: header_column=['$x$', r'$\sin(x)$'], frame=True) +-----------++------+------+------+------+ | $x$ || 0 | 1 | 2 | 3 | +-----------++------+------+------+------+ @@ -132,7 +135,8 @@ class table(SageObject): or by passing the original data as the ``columns`` of the table and using ``header_column`` instead of ``header_row``:: - sage: table(columns=[(x,n(sin(x), digits=2)) for x in [0..3]], header_column=['$x$', r'$\sin(x)$'], frame=True) + sage: table(columns=[(x, n(sin(x), digits=2)) for x in [0..3]], # needs sage.symbolic + ....: header_column=['$x$', r'$\sin(x)$'], frame=True) +-----------++------+------+------+------+ | $x$ || 0 | 1 | 2 | 3 | +-----------++------+------+------+------+ @@ -141,7 +145,8 @@ class table(SageObject): or by taking the :meth:`transpose` of the original table:: - sage: table(rows=[(x,n(sin(x), digits=2)) for x in [0..3]], header_row=['$x$', r'$\sin(x)$'], frame=True).transpose() + sage: table(rows=[(x, n(sin(x), digits=2)) for x in [0..3]], # needs sage.symbolic + ....: header_row=['$x$', r'$\sin(x)$'], frame=True).transpose() +-----------++------+------+------+------+ | $x$ || 0 | 1 | 2 | 3 | +-----------++------+------+------+------+ @@ -170,7 +175,9 @@ class table(SageObject): To generate HTML you should use ``html(table(...))``:: - sage: data = [["$x$", r"$\sin(x)$"]] + [(x, n(sin(x), digits=2)) for x in [0..3]] # optional - sage.symbolic + sage: # needs sage.symbolic + sage: data = [["$x$", r"$\sin(x)$"]] + [(x, n(sin(x), digits=2)) + ....: for x in [0..3]] sage: output = html(table(data, header_row=True, frame=True)) sage: type(output) @@ -233,8 +240,8 @@ class table(SageObject): TESTS:: - sage: TestSuite(table([["$x$", r"$\sin(x)$"]] + - ....: [(x,n(sin(x), digits=2)) for x in [0..3]], + sage: TestSuite(table([["$x$", r"$\sin(x)$"]] + # needs sage.symbolic + ....: [(x, n(sin(x), digits=2)) for x in [0..3]], ....: header_row=True, frame=True)).run() .. automethod:: _rich_repr_ @@ -286,6 +293,7 @@ def __eq__(self, other): EXAMPLES:: + sage: # needs sage.modules sage.plot sage: rows = [['a', 'b', 'c'], [1,plot(sin(x)),3], [4,5,identity_matrix(2)]] sage: T = table(rows, header_row=True) sage: T2 = table(rows, header_row=True) @@ -561,8 +569,9 @@ def _latex_(self): EXAMPLES:: sage: from sage.misc.table import table - sage: a = [[r'$\sin(x)$', '$x$', 'text'], [1,34342,3], [identity_matrix(2),5,6]] - sage: latex(table(a)) # indirect doctest + sage: a = [[r'$\sin(x)$', '$x$', 'text'], # needs sage.modules + ....: [1, 34342, 3], [identity_matrix(2), 5, 6]] + sage: latex(table(a)) # indirect doctest # needs sage.modules \begin{tabular}{lll} $\sin(x)$ & $x$ & text \\ $1$ & $34342$ & $3$ \\ @@ -571,7 +580,7 @@ def _latex_(self): 0 & 1 \end{array}\right)$ & $5$ & $6$ \\ \end{tabular} - sage: latex(table(a, frame=True, align='center')) + sage: latex(table(a, frame=True, align='center')) # needs sage.modules \begin{tabular}{|c|c|c|} \hline $\sin(x)$ & $x$ & text \\ \hline $1$ & $34342$ & $3$ \\ \hline @@ -640,10 +649,11 @@ def _html_(self): EXAMPLES:: - sage: T = table([[r'$\sin(x)$', '$x$', 'text'], [1,34342,3], [identity_matrix(2),5,6]]) - sage: T._html_() + sage: T = table([[r'$\sin(x)$', '$x$', 'text'], # needs sage.modules + ....: [1, 34342, 3], [identity_matrix(2), 5, 6]]) + sage: T._html_() # needs sage.modules '' - sage: print(T._html_()) + sage: print(T._html_()) # needs sage.modules
@@ -672,8 +682,10 @@ def _html_(self): Note that calling ``html(table(...))`` has the same effect as calling ``table(...)._html_()``:: - sage: T = table([["$x$", r"$\sin(x)$"]] + [(x,n(sin(x), digits=2)) for x in [0..3]], header_row=True, frame=True) - sage: T + sage: T = table([["$x$", r"$\sin(x)$"]] # needs sage.symbolic + ....: + [(x,n(sin(x), digits=2)) for x in [0..3]], + ....: header_row=True, frame=True) + sage: T # needs sage.symbolic +-----+-----------+ | $x$ | $\sin(x)$ | +=====+===========+ @@ -685,7 +697,7 @@ def _html_(self): +-----+-----------+ | 3 | 0.14 | +-----+-----------+ - sage: print(html(T)) + sage: print(html(T)) # needs sage.symbolic
@@ -780,11 +792,15 @@ def _html_table_row(self, file, row, header=False): """ - from sage.plot.all import Graphics from .latex import latex from .html import math_parse import types + try: + from sage.plot.all import Graphics + except ImportError: + Graphics = () + if isinstance(row, types.GeneratorType): row = list(row) elif not isinstance(row, (list, tuple)): diff --git a/src/sage/misc/test_nested_class.py b/src/sage/misc/test_nested_class.py index a8dcdb11125..40712bfc9fb 100644 --- a/src/sage/misc/test_nested_class.py +++ b/src/sage/misc/test_nested_class.py @@ -186,6 +186,7 @@ class C(): """ pass + C = ALB.C diff --git a/src/sage/misc/timing.py b/src/sage/misc/timing.py index 64d8547e64d..cc2753e50b8 100644 --- a/src/sage/misc/timing.py +++ b/src/sage/misc/timing.py @@ -54,17 +54,17 @@ def cputime(t=0, subprocesses=False): EXAMPLES:: sage: t = cputime() - sage: F = gp.factor(2^199-1) # optional - sage.libs.pari + sage: F = gp.factor(2^199-1) # needs sage.libs.pari sage: cputime(t) # somewhat random 0.010999000000000092 sage: t = cputime(subprocesses=True) - sage: F = gp.factor(2^199-1) # optional - sage.libs.pari + sage: F = gp.factor(2^199-1) # needs sage.libs.pari sage: cputime(t) # somewhat random 0.091999 sage: w = walltime() - sage: F = gp.factor(2^199-1) # optional - sage.libs.pari + sage: F = gp.factor(2^199-1) # needs sage.libs.pari sage: walltime(w) # somewhat random 0.58425593376159668 @@ -138,8 +138,8 @@ class GlobalCputime: sage: t = cputime(subprocesses=True) sage: P = PolynomialRing(QQ,7,'x') - sage: I = sage.rings.ideal.Katsura(P) # optional - sage.libs.singular - sage: gb = I.groebner_basis() # calls Singular # optional - sage.libs.singular + sage: I = sage.rings.ideal.Katsura(P) # needs sage.libs.singular + sage: gb = I.groebner_basis() # calls Singular # needs sage.libs.singular sage: cputime(subprocesses=True) - t # output random 0.462987 @@ -184,8 +184,8 @@ def __add__(self, other): sage: t = cputime(subprocesses=True) sage: P = PolynomialRing(QQ,7,'x') - sage: I = sage.rings.ideal.Katsura(P) # optional - sage.libs.singular - sage: gb = I.groebner_basis() # calls Singular # optional - sage.libs.singular + sage: I = sage.rings.ideal.Katsura(P) # needs sage.libs.singular + sage: gb = I.groebner_basis() # calls Singular # needs sage.libs.singular sage: cputime(subprocesses=True) + t # output random 2.798708 """ @@ -200,8 +200,8 @@ def __sub__(self, other): sage: t = cputime(subprocesses=True) sage: P = PolynomialRing(QQ,7,'x') - sage: I = sage.rings.ideal.Katsura(P) # optional - sage.libs.singular - sage: gb = I.groebner_basis() # calls Singular # optional - sage.libs.singular + sage: I = sage.rings.ideal.Katsura(P) # needs sage.libs.singular + sage: gb = I.groebner_basis() # calls Singular # needs sage.libs.singular sage: cputime(subprocesses=True) - t # output random 0.462987 """ @@ -240,7 +240,7 @@ def walltime(t=0): EXAMPLES:: sage: w = walltime() - sage: F = factor(2^199-1) # optional - sage.libs.pari + sage: F = factor(2^199-1) # needs sage.libs.pari sage: walltime(w) # somewhat random 0.8823847770690918 """ diff --git a/src/sage/misc/trace.py b/src/sage/misc/trace.py index 0466afb0042..6807cfb1940 100644 --- a/src/sage/misc/trace.py +++ b/src/sage/misc/trace.py @@ -54,6 +54,7 @@ def trace(code, preparse=True): The only real way to test this is via pexpect spawning a sage subprocess that uses IPython:: + sage: # needs pexpect sage.all sage: import pexpect sage: s = pexpect.spawn('sage') sage: _ = s.sendline("from sage.misc.trace import trace; trace('print(factor(10))'); print(3+97)") @@ -64,7 +65,7 @@ def trace(code, preparse=True): Seeing the ipdb prompt and the 2 \* 5 in the output below is a strong indication that the trace command worked correctly:: - sage: print(s.before[s.before.find(b'--'):].decode()) + sage: print(s.before[s.before.find(b'--'):].decode()) # needs pexpect sage.all --... ...ipdb> c ...2 * 5... diff --git a/src/sage/misc/viewer.py b/src/sage/misc/viewer.py index de84f31ddf4..439dedc5e75 100644 --- a/src/sage/misc/viewer.py +++ b/src/sage/misc/viewer.py @@ -30,6 +30,7 @@ VIEWERS = ['browser', 'dvi_viewer', 'pdf_viewer', 'png_viewer'] + def default_viewer(viewer=None): """ Set up default programs for opening web pages, PDFs, PNGs, and DVI files. @@ -138,6 +139,7 @@ def default_viewer(viewer=None): # _viewer_prefs: a dictionary holding global preferences for viewers. _viewer_prefs = {} + class Viewer(SageObject): """ Set defaults for various viewing applications: a web browser, a @@ -301,8 +303,10 @@ def __call__(self, x=None): elif x.startswith('pdf'): return self.pdf_viewer() + viewer = Viewer() + def browser(): """ Return the program used to open a web page. By default, the @@ -319,6 +323,7 @@ def browser(): """ return viewer.browser() + def dvi_viewer(): """ Return the program used to display a dvi file. By default, the @@ -336,6 +341,7 @@ def dvi_viewer(): viewer() return viewer.dvi_viewer() + def pdf_viewer(): """ Return the program used to display a pdf file. By default, the @@ -356,6 +362,7 @@ def pdf_viewer(): viewer() return viewer.pdf_viewer() + def png_viewer(): """ Return the program used to display a png file. By default, the diff --git a/src/sage/misc/weak_dict.pyx b/src/sage/misc/weak_dict.pyx index 59a399fed20..1d4e9f24093 100644 --- a/src/sage/misc/weak_dict.pyx +++ b/src/sage/misc/weak_dict.pyx @@ -162,6 +162,7 @@ cdef class WeakValueDictEraser: - Nils Bruin (2013-11) """ cdef D + def __init__(self, D): """ INPUT: @@ -337,7 +338,8 @@ cdef class WeakValueDictionary(dict): EXAMPLES:: - sage: L = [(p,GF(p)) for p in prime_range(10)] + sage: # needs sage.rings.finite_rings + sage: L = [(p, GF(p)) for p in prime_range(10)] sage: import sage.misc.weak_dict sage: D = sage.misc.weak_dict.WeakValueDictionary() sage: len(D) @@ -363,7 +365,7 @@ cdef class WeakValueDictionary(dict): sage: D = sage.misc.weak_dict.WeakValueDictionary() sage: D[1] = QQ sage: D[2] = ZZ - sage: D[None] = CC + sage: D[None] = CC # needs sage.rings.real_mpfr sage: E = copy(D) # indirect doctest sage: set(E.items()) == set(D.items()) True @@ -427,13 +429,16 @@ cdef class WeakValueDictionary(dict): EXAMPLES:: sage: import sage.misc.weak_dict - sage: L = [(p,GF(p)) for p in prime_range(10)] + + sage: # needs sage.libs.pari + sage: L = [(p, GF(p)) for p in prime_range(10)] sage: D = sage.misc.weak_dict.WeakValueDictionary(L) sage: len(D) 4 The value for an existing key is returned and not overridden:: + sage: # needs sage.libs.pari sage: D.setdefault(5, ZZ) Finite Field of size 5 sage: D[5] @@ -441,6 +446,7 @@ cdef class WeakValueDictionary(dict): For a non-existing key, the default value is stored and returned:: + sage: # needs sage.libs.pari sage: 4 in D False sage: D.setdefault(4, ZZ) @@ -458,7 +464,7 @@ cdef class WeakValueDictionary(dict): raised for unhashable objects:: sage: D = sage.misc.weak_dict.WeakValueDictionary() - sage: D.setdefault(matrix([]),ZZ) + sage: D.setdefault(matrix([]), ZZ) # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -533,7 +539,7 @@ cdef class WeakValueDictionary(dict): raised for unhashable objects:: sage: D = sage.misc.weak_dict.WeakValueDictionary() - sage: D[matrix([])] = ZZ + sage: D[matrix([])] = ZZ # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -558,6 +564,8 @@ cdef class WeakValueDictionary(dict): EXAMPLES:: sage: import sage.misc.weak_dict + + sage: # needs sage.libs.pari sage: L = [GF(p) for p in prime_range(10^3)] sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(L)) sage: 20 in D @@ -577,7 +585,7 @@ cdef class WeakValueDictionary(dict): raised for unhashable objects:: sage: D = sage.misc.weak_dict.WeakValueDictionary() - sage: D.pop(matrix([])) + sage: D.pop(matrix([])) # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -634,6 +642,8 @@ cdef class WeakValueDictionary(dict): EXAMPLES:: sage: import sage.misc.weak_dict + + sage: # needs sage.libs.pari sage: L = [GF(p) for p in prime_range(10^3)] sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(L)) sage: 100 in D @@ -652,8 +662,9 @@ cdef class WeakValueDictionary(dict): Check that :trac:`15956` has been fixed, i.e., a ``TypeError`` is raised for unhashable objects:: + sage: # needs sage.libs.pari sage: D = sage.misc.weak_dict.WeakValueDictionary() - sage: D.get(matrix([])) + sage: D.get(matrix([])) # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -693,7 +704,7 @@ cdef class WeakValueDictionary(dict): raised for unhashable objects:: sage: D = sage.misc.weak_dict.WeakValueDictionary() - sage: D[matrix([])] + sage: D[matrix([])] # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -737,7 +748,7 @@ cdef class WeakValueDictionary(dict): raised for unhashable objects:: sage: D = sage.misc.weak_dict.WeakValueDictionary() - sage: matrix([]) in D + sage: matrix([]) in D # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -1191,13 +1202,13 @@ cdef class CachedWeakValueDictionary(WeakValueDictionary): EXAMPLES:: - sage: L = [(p,GF(p)) for p in prime_range(10)] + sage: L = [(p, GF(p)) for p in prime_range(10)] # needs sage.libs.pari sage: from sage.misc.weak_dict import CachedWeakValueDictionary sage: D = CachedWeakValueDictionary() sage: len(D) 0 - sage: D = CachedWeakValueDictionary(L) - sage: len(D) == len(L) + sage: D = CachedWeakValueDictionary(L) # needs sage.libs.pari + sage: len(D) == len(L) # needs sage.libs.pari True A :class:`CachedWeakValueDictionary` with a cache size of zero diff --git a/src/sage/modular/abvar/homspace.py b/src/sage/modular/abvar/homspace.py index 6d96cc0fabe..8e89399d611 100644 --- a/src/sage/modular/abvar/homspace.py +++ b/src/sage/modular/abvar/homspace.py @@ -148,14 +148,15 @@ :: - sage: T = E.image_of_hecke_algebra() # long time - sage: T.gens() # long time + sage: # long time + sage: T = E.image_of_hecke_algebra() + sage: T.gens() (Abelian variety endomorphism of Abelian variety J0(33) of dimension 3, Abelian variety endomorphism of Abelian variety J0(33) of dimension 3, Abelian variety endomorphism of Abelian variety J0(33) of dimension 3) - sage: T.index_in(E) # long time + sage: T.index_in(E) +Infinity - sage: T.index_in_saturation() # long time + sage: T.index_in_saturation() 1 AUTHORS: diff --git a/src/sage/modular/arithgroup/congroup.pyx b/src/sage/modular/arithgroup/congroup.pyx index 318996805ca..002e3bb02da 100644 --- a/src/sage/modular/arithgroup/congroup.pyx +++ b/src/sage/modular/arithgroup/congroup.pyx @@ -132,7 +132,7 @@ def degeneracy_coset_representatives_gamma0(int N, int M, int t): dd = dd / g # Test if we've found a new coset representative. is_new = 1 - for i from 0 <= i < k: + for i in range(k): j = 4*i if (R[j+1]*aa - R[j]*bb) % t == 0 and \ (R[j+3]*cc - R[j+2]*dd) % Ndivt == 0: @@ -237,7 +237,7 @@ def degeneracy_coset_representatives_gamma1(int N, int M, int t): continue # Test if we've found a new coset representative. is_new = 1 - for i from 0 <= i < k: + for i in range(k): j = 4*i if (R[j] - aa) % t == 0 and \ (R[j+1] - bb) % t == 0 and \ @@ -258,7 +258,7 @@ def degeneracy_coset_representatives_gamma1(int N, int M, int t): # Return the list left multiplied by T. S = [] - for i from 0 <= i < k: + for i in range(k): j = 4*i S.append([R[j], R[j+1], R[j+2]*t, R[j+3]*t]) sig_free(R) diff --git a/src/sage/modular/arithgroup/congroup_gamma.py b/src/sage/modular/arithgroup/congroup_gamma.py index bc1cbb6afd6..bba5868dab6 100644 --- a/src/sage/modular/arithgroup/congroup_gamma.py +++ b/src/sage/modular/arithgroup/congroup_gamma.py @@ -240,6 +240,12 @@ def reduce_cusp(self, c): sage: G = Gamma(50) sage: all(c == G.reduce_cusp(c) for c in G.cusps()) True + + We test that :trac:`36163` is fixed:: + + sage: Gamma(7).reduce_cusp(Cusp(6,7)) + Infinity + """ N = self.level() c = Cusp(c) @@ -341,7 +347,7 @@ def _lift_pair(U,V,N): u = U % N v = V % N if v == 0: - if u == 1: + if u == 1 or u == N-1: return (1,0) else: v = N diff --git a/src/sage/modular/arithgroup/congroup_gamma0.py b/src/sage/modular/arithgroup/congroup_gamma0.py index 5bc0a6e4b3a..e960ce477d3 100644 --- a/src/sage/modular/arithgroup/congroup_gamma0.py +++ b/src/sage/modular/arithgroup/congroup_gamma0.py @@ -39,6 +39,7 @@ def is_Gamma0(x): """ return isinstance(x, Gamma0_class) + _gamma0_cache = {} def Gamma0_constructor(N): """ diff --git a/src/sage/modular/arithgroup/farey.cpp b/src/sage/modular/arithgroup/farey.cpp index 34f5e5727db..209391676de 100644 --- a/src/sage/modular/arithgroup/farey.cpp +++ b/src/sage/modular/arithgroup/farey.cpp @@ -1010,7 +1010,7 @@ PyObject* FareySymbol::word_problem(const mpz_t a, const mpz_t b, LLT_algorithm(M, p, beta1); wd = PyList_New(p.size()); for(i=0; i::const_iterator i=p.begin(); i!=p.end(); i++) { vector::const_iterator j = find(pairing.begin(), pairing.end(), *i); vector::const_iterator k = find(j+1, pairing.end(), *i); - PyObject* J = PyInt_FromLong(long(j-pairing.begin())); - PyObject* K = PyInt_FromLong(long(k-pairing.begin())); + PyObject* J = PyLong_FromLong(long(j-pairing.begin())); + PyObject* K = PyLong_FromLong(long(k-pairing.begin())); PyObject* tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, J); PyTuple_SetItem(tuple, 1, K); diff --git a/src/sage/modular/arithgroup/farey.hpp b/src/sage/modular/arithgroup/farey.hpp index 076d5cd0504..03c03cf1434 100644 --- a/src/sage/modular/arithgroup/farey.hpp +++ b/src/sage/modular/arithgroup/farey.hpp @@ -29,9 +29,6 @@ #include #include "sl2z.hpp" -#define PyInt_FromLong PyLong_FromLong -#define PyInt_AsLong PyLong_AsLong -#define PyInt_AS_LONG PyLong_AS_LONG //--- pure virtual base class for helper class for membership test -------- diff --git a/src/sage/modular/cusps_nf.py b/src/sage/modular/cusps_nf.py index 7e8ffa6658c..8d8b580a74e 100644 --- a/src/sage/modular/cusps_nf.py +++ b/src/sage/modular/cusps_nf.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.number_field r""" The set `\mathbb{P}^1(K)` of cusps of a number field `K` @@ -62,7 +63,7 @@ sage: Gamma0_NFCusps(N) [Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5, - Cusp [1: 3] of Number Field in a with defining polynomial x^2 + 5, + Cusp [1: 3] of Number Field in a with defining polynomial x^2 + 5, ...] """ # **************************************************************************** @@ -859,7 +860,7 @@ def ABmatrix(self): sage: M = alpha.ABmatrix() sage: M # random [-a^2 - a - 1, -3*a - 7, 8, -2*a^2 - 3*a + 4] - sage: M[0] == alpha.numerator() and M[2]==alpha.denominator() + sage: M[0] == alpha.numerator() and M[2] == alpha.denominator() True An AB-matrix associated to a cusp alpha will send Infinity to alpha: @@ -870,7 +871,7 @@ def ABmatrix(self): sage: M = alpha.ABmatrix() sage: (k.ideal(M[1], M[3])*alpha.ideal()).is_principal() True - sage: M[0] == alpha.numerator() and M[2]==alpha.denominator() + sage: M[0] == alpha.numerator() and M[2] == alpha.denominator() True sage: NFCusp(k, oo).apply(M) == alpha True @@ -1249,7 +1250,8 @@ def units_mod_ideal(I): sage: from sage.modular.cusps_nf import units_mod_ideal sage: k. = NumberField(x^3 + 11) sage: k.unit_group() - Unit group with structure C2 x Z of Number Field in a with defining polynomial x^3 + 11 + Unit group with structure C2 x Z of + Number Field in a with defining polynomial x^3 + 11 sage: I = k.ideal(5, a + 1) sage: units_mod_ideal(I) [1, @@ -1261,7 +1263,8 @@ def units_mod_ideal(I): sage: from sage.modular.cusps_nf import units_mod_ideal sage: k. = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133) sage: k.unit_group() - Unit group with structure C6 x Z of Number Field in a with defining polynomial x^4 - x^3 - 21*x^2 + 17*x + 133 + Unit group with structure C6 x Z of + Number Field in a with defining polynomial x^4 - x^3 - 21*x^2 + 17*x + 133 sage: I = k.ideal(3) sage: U = units_mod_ideal(I) sage: all(U[j].is_unit() and (U[j] not in I) for j in range(len(U))) diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index caf47f48362..9785c18963f 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -1201,7 +1201,12 @@ def conrey_number(self): sage: eps2 = DirichletGroup(5,QQ)([-1]) sage: eps1.conrey_number() == eps2.conrey_number() True + sage: chi = DirichletGroup(1)[0] + sage: chi.conrey_number() + 1 """ + if self.modulus() == 1: + return 1 G, v = self._pari_init_() return pari.znconreyexp(G, v).sage() diff --git a/src/sage/modular/modform/constructor.py b/src/sage/modular/modform/constructor.py index c30a28354ca..023f9a380d2 100644 --- a/src/sage/modular/modform/constructor.py +++ b/src/sage/modular/modform/constructor.py @@ -134,6 +134,7 @@ def canonical_parameters(group, level, weight, base_ring): # forms spaces. return level, group, weight, base_ring + _cache = {} def ModularForms_clear_cache(): diff --git a/src/sage/modular/modform/eis_series_cython.pyx b/src/sage/modular/modform/eis_series_cython.pyx index dfcc8a123ff..c29fef9cef7 100644 --- a/src/sage/modular/modform/eis_series_cython.pyx +++ b/src/sage/modular/modform/eis_series_cython.pyx @@ -93,7 +93,7 @@ cpdef Ek_ZZ(int k, int prec=10): while True: continue_flag = 0 # do the first p-1 - for i from 0 < i < p: + for i in range(1, p): ind += p if (ind >= prec): continue_flag = 1 @@ -215,7 +215,7 @@ cpdef eisenstein_series_poly(int k, int prec = 10) : mpz_clear(last_m1) fmpz_poly_set_coeff_mpz(res.poly, prec-1, val[prec-1]) - for i from 1 <= i < prec - 1 : + for i in range(1, prec - 1): fmpz_poly_set_coeff_mpz(res.poly, i, val[i]) fmpz_poly_scalar_mul_mpz(res.poly, res.poly, ((a0.denominator())).value) diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index fba61a0fdd8..6d10fdf47c3 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -2315,13 +2315,14 @@ def minimal_twist(self, p=None): sage: f.twist(chi, level=11) == g True - sage: f = Newforms(575, 2, names='a')[4] # long time - sage: g, chi = f.minimal_twist(5) # long time - sage: g # long time + sage: # long time + sage: f = Newforms(575, 2, names='a')[4] + sage: g, chi = f.minimal_twist(5) + sage: g q + a*q^2 - a*q^3 - 2*q^4 + (1/2*a + 2)*q^5 + O(q^6) - sage: chi # long time + sage: chi Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 1/2*a - sage: f.twist(chi, level=g.level()) == g # long time + sage: f.twist(chi, level=g.level()) == g True """ if p is None: diff --git a/src/sage/modular/modform/l_series_gross_zagier_coeffs.pyx b/src/sage/modular/modform/l_series_gross_zagier_coeffs.pyx index 87caa9ff8ab..f91a3e256f0 100644 --- a/src/sage/modular/modform/l_series_gross_zagier_coeffs.pyx +++ b/src/sage/modular/modform/l_series_gross_zagier_coeffs.pyx @@ -68,7 +68,7 @@ def bqf_theta_series(Q, long bound, var=None): cdef long a, b, c a, b, c = Q cdef long* terms = bqf_theta_series_c(NULL, bound, a, b, c) - L = [terms[i] for i from 0 <= i <= bound] + L = [terms[i] for i in range(bound + 1)] sig_free(terms) return to_series(L, var) @@ -85,13 +85,13 @@ cdef long* bqf_theta_series_c(long* terms, long bound, long a, long b, long c) e terms = check_calloc(1 + bound, sizeof(long)) sig_on() - for x from -xmax <= x <= xmax: + for x in range(-xmax, xmax + 1): yD = b * b * x * x - 4 * c * (a * x * x - bound) if yD > 0: sqrt_yD = sqrt(yD) ymin = ceil((-b * x - sqrt_yD) / (2 * c)) ymax = floor((-b * x + sqrt_yD) / (2 * c)) - for y from ymin <= y <= ymax: + for y in range(ymin, ymax + 1): terms[a * x * x + b * x * y + c * y * y] += 1 sig_off() return terms @@ -161,7 +161,7 @@ def gross_zagier_L_series(an_list, Q, long N, long u, var=None): i += 1 sig_on() memcpy(terms, con_terms, sizeof(long) * bound) # m = 1 - for m from 2 <= m <= sqrt(bound): + for m in range(2, sqrt(bound) + 1): if arith.c_gcd_longlong(D * N, m) == 1: me = m * kronecker_symbol(D, m) j = 0 diff --git a/src/sage/modular/modform_hecketriangle/analytic_type.py b/src/sage/modular/modform_hecketriangle/analytic_type.py index 7b2618991df..0c809b3328c 100644 --- a/src/sage/modular/modform_hecketriangle/analytic_type.py +++ b/src/sage/modular/modform_hecketriangle/analytic_type.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs r""" Analytic types of modular forms diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py index a5e72e0eaa0..917ebb0cf02 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py @@ -145,7 +145,7 @@ def element_repr_method(self, method=None): - ``method`` -- If ``method=None`` (default) the current default representation method is returned. Otherwise the default method is set to ``method``. - If ``method`` is not available a ValueError is raised. Possible methods are: + If ``method`` is not available a :class:`ValueError` is raised. Possible methods are: ``default``: Use the usual representation method for matrix group elements. diff --git a/src/sage/modular/modsym/apply.pyx b/src/sage/modular/modsym/apply.pyx index 4d1b093ee61..40488868b37 100644 --- a/src/sage/modular/modsym/apply.pyx +++ b/src/sage/modular/modsym/apply.pyx @@ -103,7 +103,7 @@ def apply_to_monomial(int i, int j, int a, int b, int c, int d): cdef Integer res v = [] - for k from 0 <= k <= j: + for k in range(j + 1): res = PY_NEW(Integer) fmpz_poly_get_coeff_mpz(res.value, pr, k) v.append(int(res)) diff --git a/src/sage/modular/modsym/p1list.pxd b/src/sage/modular/modsym/p1list.pxd index cc24a33139b..b66f28b8ad6 100644 --- a/src/sage/modular/modsym/p1list.pxd +++ b/src/sage/modular/modsym/p1list.pxd @@ -21,7 +21,7 @@ cdef class P1List: # Here we use a pointer to a function, so the if logic # for normalizing an element does not need to be used # every time the user calls the normalize function. - cdef int (*__normalize)(int N, int u, int v, + cdef int (*_normalize)(int N, int u, int v, int* uu, int* vv, int* ss, int compute_s) except -1 cpdef index(self, int u, int v) diff --git a/src/sage/modular/modsym/p1list.pyx b/src/sage/modular/modsym/p1list.pyx index 78f1c6d647c..30a8f7471dd 100644 --- a/src/sage/modular/modsym/p1list.pyx +++ b/src/sage/modular/modsym/p1list.pyx @@ -108,7 +108,7 @@ cdef int c_p1_normalize_int(int N, int u, int v, Ng = N/g vNg = (v*Ng) % N t = 1 - for k from 2 <= k <= g: + for k in range(2, g + 1): v = (v + vNg) % N t = (t + Ng) % N if v ((v * Ng) % ll_N) t = 1 - for k from 2 <= k <= g: + for k in range(2, g + 1): v = (v + vNg) % N t = (t + Ng) % N - if v(ll_s % ll_N) self.t[i] = (ll_t % ll_N) @@ -921,7 +921,7 @@ cdef class P1List(): """ cdef int u, v, uu, vv, ss u,v = self.__list[i] - self.__normalize(self.__N, -u, v, &uu, &vv, &ss, 0) + self._normalize(self.__N, -u, v, &uu, &vv, &ss, 0) _, j = search(self.__list, (uu,vv)) return j @@ -954,7 +954,7 @@ cdef class P1List(): """ cdef int u, v, uu, vv, ss u,v = self.__list[i] - self.__normalize(self.__N, -v, u, &uu, &vv, &ss, 0) + self._normalize(self.__N, -v, u, &uu, &vv, &ss, 0) _, j = search(self.__list, (uu,vv)) return j @@ -987,7 +987,7 @@ cdef class P1List(): """ cdef int u, v, uu, vv, ss u,v = self.__list[i] - self.__normalize(self.__N, v, -u-v, &uu, &vv, &ss, 0) + self._normalize(self.__N, v, -u-v, &uu, &vv, &ss, 0) _, j = search(self.__list, (uu,vv)) return j @@ -1153,7 +1153,7 @@ cdef class P1List(): True """ cdef int uu, vv, ss - self.__normalize(self.__N, u, v, &uu, &vv, &ss, 0) + self._normalize(self.__N, u, v, &uu, &vv, &ss, 0) return (uu,vv) def normalize_with_scalar(self, int u, int v): @@ -1186,7 +1186,7 @@ cdef class P1List(): True """ cdef int uu, vv, ss - self.__normalize(self.__N, u, v, &uu, &vv, &ss, 1) + self._normalize(self.__N, u, v, &uu, &vv, &ss, 1) return (uu, vv, ss) def N(self): diff --git a/src/sage/modular/modsym/relation_matrix_pyx.pyx b/src/sage/modular/modsym/relation_matrix_pyx.pyx index f5a18c464eb..46d8d716e62 100644 --- a/src/sage/modular/modsym/relation_matrix_pyx.pyx +++ b/src/sage/modular/modsym/relation_matrix_pyx.pyx @@ -57,7 +57,7 @@ def sparse_2term_quotient_only_pm1(rels, n): tm = verbose("Starting optimized integer sparse 2-term quotient...") cdef int c0, c1, i, die - cdef list free = list(xrange(n)) + cdef list free = list(range(n)) cdef list coef = [1] * n cdef list related_to_me = [[] for i in range(n)] diff --git a/src/sage/modular/overconvergent/weightspace.py b/src/sage/modular/overconvergent/weightspace.py index 8f0ecc8b8c0..e9478c40a90 100644 --- a/src/sage/modular/overconvergent/weightspace.py +++ b/src/sage/modular/overconvergent/weightspace.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.rings.padics r""" The space of `p`-adic weights @@ -17,7 +17,8 @@ sage: W = pAdicWeightSpace(17) sage: W - Space of 17-adic weight-characters defined over 17-adic Field with capped relative precision 20 + Space of 17-adic weight-characters + defined over 17-adic Field with capped relative precision 20 sage: R. = QQ[] sage: L = Qp(17).extension(x^2 - 17, names='a'); L.rename('L') sage: W.base_extend(L) @@ -101,7 +102,8 @@ def WeightSpace_constructor(p, base_ring=None): EXAMPLES:: sage: pAdicWeightSpace(3) # indirect doctest - Space of 3-adic weight-characters defined over 3-adic Field with capped relative precision 20 + Space of 3-adic weight-characters + defined over 3-adic Field with capped relative precision 20 sage: pAdicWeightSpace(3, QQ) Space of 3-adic weight-characters defined over Rational Field sage: pAdicWeightSpace(10) @@ -248,11 +250,13 @@ def base_extend(self, R): sage: W = pAdicWeightSpace(3, QQ) sage: W.base_extend(Qp(3)) - Space of 3-adic weight-characters defined over 3-adic Field with capped relative precision 20 + Space of 3-adic weight-characters + defined over 3-adic Field with capped relative precision 20 sage: W.base_extend(IntegerModRing(12)) Traceback (most recent call last): ... - TypeError: No coercion map from 'Rational Field' to 'Ring of integers modulo 12' is defined + TypeError: No coercion map from 'Rational Field' + to 'Ring of integers modulo 12' is defined """ if R.has_coerce_map_from(self.base_ring()): return WeightSpace_constructor(self.prime(), R) @@ -356,7 +360,9 @@ def pAdicEisensteinSeries(self, ring, prec=20): sage: kappa = pAdicWeightSpace(3)(3, DirichletGroup(3,QQ).0) sage: kappa.pAdicEisensteinSeries(QQ[['q']], 20) - 1 - 9*q + 27*q^2 - 9*q^3 - 117*q^4 + 216*q^5 + 27*q^6 - 450*q^7 + 459*q^8 - 9*q^9 - 648*q^10 + 1080*q^11 - 117*q^12 - 1530*q^13 + 1350*q^14 + 216*q^15 - 1845*q^16 + 2592*q^17 + 27*q^18 - 3258*q^19 + O(q^20) + 1 - 9*q + 27*q^2 - 9*q^3 - 117*q^4 + 216*q^5 + 27*q^6 - 450*q^7 + 459*q^8 + - 9*q^9 - 648*q^10 + 1080*q^11 - 117*q^12 - 1530*q^13 + 1350*q^14 + 216*q^15 + - 1845*q^16 + 2592*q^17 + 27*q^18 - 3258*q^19 + O(q^20) """ if not self.is_even(): raise ValueError("Eisenstein series not defined for odd weight-characters") @@ -570,7 +576,8 @@ def chi(self): sage: kappa = pAdicWeightSpace(29)(13, DirichletGroup(29, Qp(29)).0^14) sage: kappa.chi() - Dirichlet character modulo 29 of conductor 29 mapping 2 |--> 28 + 28*29 + 28*29^2 + ... + O(29^20) + Dirichlet character modulo 29 of conductor 29 + mapping 2 |--> 28 + 28*29 + 28*29^2 + ... + O(29^20) """ return self._chi @@ -667,7 +674,8 @@ def Lvalue(self): sage: pAdicWeightSpace(7)(5, DirichletGroup(7, Qp(7)).0^4).Lvalue() 0 sage: pAdicWeightSpace(7)(6, DirichletGroup(7, Qp(7)).0^4).Lvalue() - 1 + 2*7 + 7^2 + 3*7^3 + 3*7^5 + 4*7^6 + 2*7^7 + 5*7^8 + 2*7^9 + 3*7^10 + 6*7^11 + 2*7^12 + 3*7^13 + 5*7^14 + 6*7^15 + 5*7^16 + 3*7^17 + 6*7^18 + O(7^19) + 1 + 2*7 + 7^2 + 3*7^3 + 3*7^5 + 4*7^6 + 2*7^7 + 5*7^8 + 2*7^9 + 3*7^10 + 6*7^11 + + 2*7^12 + 3*7^13 + 5*7^14 + 6*7^15 + 5*7^16 + 3*7^17 + 6*7^18 + O(7^19) """ if self._k > 0: return -self._chi.bernoulli(self._k) / self._k diff --git a/src/sage/modular/pollack_stevens/distributions.py b/src/sage/modular/pollack_stevens/distributions.py index 55a5ec72663..274cdfa87a4 100644 --- a/src/sage/modular/pollack_stevens/distributions.py +++ b/src/sage/modular/pollack_stevens/distributions.py @@ -224,6 +224,7 @@ def create_object(self, version, key): """ return Symk_class(*key) + OverconvergentDistributions = OverconvergentDistributions_factory('OverconvergentDistributions') Symk = Symk_factory('Symk') diff --git a/src/sage/modular/pollack_stevens/fund_domain.py b/src/sage/modular/pollack_stevens/fund_domain.py index 3e25c950b30..4bd2638d5a6 100644 --- a/src/sage/modular/pollack_stevens/fund_domain.py +++ b/src/sage/modular/pollack_stevens/fund_domain.py @@ -56,6 +56,7 @@ def M2Z(x): x.set_immutable() return x + Id = M2Z([1, 0, 0, 1]) sig = M2Z([0, 1, -1, 0]) tau = M2Z([0, -1, 1, -1]) diff --git a/src/sage/modular/pollack_stevens/padic_lseries.py b/src/sage/modular/pollack_stevens/padic_lseries.py index 396a96af90e..748b5dc9993 100644 --- a/src/sage/modular/pollack_stevens/padic_lseries.py +++ b/src/sage/modular/pollack_stevens/padic_lseries.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.ring.padics r""" `p`-adic `L`-series attached to overconvergent eigensymbols diff --git a/src/sage/modular/pollack_stevens/sigma0.py b/src/sage/modular/pollack_stevens/sigma0.py index ab8e24959cd..bd203ec8600 100644 --- a/src/sage/modular/pollack_stevens/sigma0.py +++ b/src/sage/modular/pollack_stevens/sigma0.py @@ -162,6 +162,7 @@ def create_object(self, version, key): """ return Sigma0_class(*key) + Sigma0 = Sigma0_factory('sage.modular.pollack_stevens.sigma0.Sigma0') diff --git a/src/sage/modular/pollack_stevens/space.py b/src/sage/modular/pollack_stevens/space.py index 43e396b03c8..88b7be6d2cd 100644 --- a/src/sage/modular/pollack_stevens/space.py +++ b/src/sage/modular/pollack_stevens/space.py @@ -189,6 +189,7 @@ def create_object(self, version, key): """ return PollackStevensModularSymbolspace(*key) + PollackStevensModularSymbols = PollackStevensModularSymbols_factory('PollackStevensModularSymbols') diff --git a/src/sage/modules/complex_double_vector.py b/src/sage/modules/complex_double_vector.py index faf935694a6..88ad6bb6d67 100644 --- a/src/sage/modules/complex_double_vector.py +++ b/src/sage/modules/complex_double_vector.py @@ -7,10 +7,9 @@ TESTS:: - sage: v = vector(CDF,[(1,-1), (2,pi), (3,5)]) - sage: v + sage: v = vector(CDF,[(1,-1), (2,pi), (3,5)]); v # needs sage.symbolic (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) - sage: loads(dumps(v)) == v + sage: loads(dumps(v)) == v # needs sage.symbolic True """ diff --git a/src/sage/modules/diamond_cutting.py b/src/sage/modules/diamond_cutting.py index b18fc315754..786a783fabf 100644 --- a/src/sage/modules/diamond_cutting.py +++ b/src/sage/modules/diamond_cutting.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.geometry.polyhedron """ Diamond cutting implementation diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index 0a0f435d779..dbb13dadbad 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -21,7 +21,7 @@ # This adds extra maybe-not-necessary checks in the code, but could # slow things down. It can impact what happens in more than just this # file. -DEBUG=True +DEBUG = True class FGP_Element(ModuleElement): diff --git a/src/sage/modules/fg_pid/fgp_module.py b/src/sage/modules/fg_pid/fgp_module.py index c0e9181a141..1ca35212682 100644 --- a/src/sage/modules/fg_pid/fgp_module.py +++ b/src/sage/modules/fg_pid/fgp_module.py @@ -1084,7 +1084,7 @@ def gens_to_smith(self): EXAMPLES:: sage: L2 = IntegralLattice(3 * matrix([[-2,0,0], [0,1,0], [0,0,-4]])) - sage: D = L2.discriminant_group().normal_form(); D # optional - sage.libs.pari sage.rings.padics + sage: D = L2.discriminant_group().normal_form(); D # needs sage.libs.pari sage.rings.padics Finite quadratic module over Integer Ring with invariants (3, 6, 12) Gram matrix of the quadratic form with values in Q/Z: [1/2 0 0 0 0] @@ -1092,13 +1092,13 @@ def gens_to_smith(self): [ 0 0 1/3 0 0] [ 0 0 0 1/3 0] [ 0 0 0 0 2/3] - sage: D.gens_to_smith() # optional - sage.libs.pari sage.rings.padics + sage: D.gens_to_smith() # needs sage.libs.pari sage.rings.padics [0 3 0] [0 0 3] [0 4 0] [1 2 0] [0 0 4] - sage: T = D.gens_to_smith() * D.smith_to_gens(); T # optional - sage.libs.pari sage.rings.padics + sage: T = D.gens_to_smith() * D.smith_to_gens(); T # needs sage.libs.pari sage.rings.padics [ 3 0 3 0 0] [ 0 33 0 0 3] [ 4 0 4 0 0] @@ -1107,9 +1107,9 @@ def gens_to_smith(self): The matrix `T` now satisfies a certain congruence:: - sage: for i in range(T.nrows()): # optional - sage.libs.pari sage.rings.padics + sage: for i in range(T.nrows()): # needs sage.libs.pari sage.rings.padics ....: T[:,i] = T[:,i] % D.gens()[i].order() - sage: T # optional - sage.libs.pari sage.rings.padics + sage: T # needs sage.libs.pari sage.rings.padics [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] @@ -1135,7 +1135,7 @@ def smith_to_gens(self): EXAMPLES:: sage: L2 = IntegralLattice(3 * matrix([[-2,0,0], [0,1,0], [0,0,-4]])) - sage: D = L2.discriminant_group().normal_form(); D # optional - sage.libs.pari sage.rings.padics + sage: D = L2.discriminant_group().normal_form(); D # needs sage.libs.pari sage.rings.padics Finite quadratic module over Integer Ring with invariants (3, 6, 12) Gram matrix of the quadratic form with values in Q/Z: [1/2 0 0 0 0] @@ -1143,33 +1143,33 @@ def smith_to_gens(self): [ 0 0 1/3 0 0] [ 0 0 0 1/3 0] [ 0 0 0 0 2/3] - sage: D.smith_to_gens() # optional - sage.libs.pari sage.rings.padics + sage: D.smith_to_gens() # needs sage.libs.pari sage.rings.padics [ 0 0 1 1 0] [ 1 0 1 0 0] [ 0 11 0 0 1] - sage: T = D.smith_to_gens() * D.gens_to_smith(); T # optional - sage.libs.pari sage.rings.padics + sage: T = D.smith_to_gens() * D.gens_to_smith(); T # needs sage.libs.pari sage.rings.padics [ 1 6 0] [ 0 7 0] [ 0 0 37] This matrix satisfies the congruence:: - sage: for i in range(T.ncols()): # optional - sage.libs.pari sage.rings.padics + sage: for i in range(T.ncols()): # needs sage.libs.pari sage.rings.padics ....: T[:, i] = T[:, i] % D.smith_form_gens()[i].order() - sage: T # optional - sage.libs.pari sage.rings.padics + sage: T # needs sage.libs.pari sage.rings.padics [1 0 0] [0 1 0] [0 0 1] We create some element of our FGP module:: - sage: x = D.linear_combination_of_smith_form_gens((1,2,3)); x # optional - sage.libs.pari sage.rings.padics + sage: x = D.linear_combination_of_smith_form_gens((1,2,3)); x # needs sage.libs.pari sage.rings.padics (1, 2, 3) and want to know some (it is not unique) linear combination of the user defined generators that is ``x``:: - sage: x.vector() * D.smith_to_gens() # optional - sage.libs.pari sage.rings.padics + sage: x.vector() * D.smith_to_gens() # needs sage.libs.pari sage.rings.padics (2, 33, 3, 1, 3) """ if self.base_ring() != ZZ: @@ -1228,17 +1228,17 @@ def gens_vector(self, x, reduce=False): In our generators:: - sage: v = D.gens_vector(x); v + sage: v = D.gens_vector(x); v # needs sage.libs.pari (2, 9, 3, 1, 33) The output can be further reduced:: - sage: D.gens_vector(x, reduce=True) + sage: D.gens_vector(x, reduce=True) # needs sage.libs.pari (0, 1, 0, 1, 0) Let us check:: - sage: x == sum(v[i]*D.gen(i) for i in range(len(D.gens()))) + sage: x == sum(v[i]*D.gen(i) for i in range(len(D.gens()))) # needs sage.libs.pari True """ x = self(x) @@ -1867,6 +1867,8 @@ def construction(self): sage: T2 = A2 / B2 sage: t1 = T1.an_element() sage: t2 = T2.an_element() + + sage: # needs sage.libs.flint (o/w infinite recursion) sage: t1 + t2 (1, 1) """ @@ -2068,8 +2070,10 @@ def _test_morphism_0(*args, **kwds): sage: set_random_seed(s); v = [fgp._test_morphism_0(1) for _ in range(30)] sage: set_random_seed(s); v = [fgp._test_morphism_0(2) for _ in range(30)] sage: set_random_seed(s); v = [fgp._test_morphism_0(3) for _ in range(10)] + + sage: # needs sage.libs.flint (o/w timeout) sage: set_random_seed(s); v = [fgp._test_morphism_0(i) for i in range(1,20)] - sage: set_random_seed(s); v = [fgp._test_morphism_0(4) for _ in range(50)] # long time + sage: set_random_seed(s); v = [fgp._test_morphism_0(4) for _ in range(50)] # long time """ phi = random_fgp_morphism_0(*args, **kwds) K = phi.kernel() diff --git a/src/sage/modules/fg_pid/fgp_morphism.py b/src/sage/modules/fg_pid/fgp_morphism.py index 71b43dcdc1a..d1c8b221994 100644 --- a/src/sage/modules/fg_pid/fgp_morphism.py +++ b/src/sage/modules/fg_pid/fgp_morphism.py @@ -127,7 +127,7 @@ def _repr_(self): sage: phi._repr_() 'Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(1, 3), (0, 11)]' """ - return "Morphism from module over %s with invariants %s to module with invariants %s that sends the generators to %s"%( + return "Morphism from module over %s with invariants %s to module with invariants %s that sends the generators to %s" % ( self.domain().base_ring(), self.domain().invariants(), self.codomain().invariants(), list(self.im_gens())) @@ -453,6 +453,7 @@ def lift(self, x): assert self(y) == x, "bug in phi.lift()" return y + from sage.categories.homset import Homset import sage.misc.weak_dict diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index f30b3f058c6..8bd7e986ced 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -83,17 +83,17 @@ Any field can be used as the vector space base. For example a finite field:: - sage: F. = GF(5^3) - sage: r1 = (a, 0, F(5)); r1 + sage: F. = GF(5^3) # needs sage.rings.finite_rings + sage: r1 = (a, 0, F(5)); r1 # needs sage.rings.finite_rings (a, 0, 0) - sage: FilteredVectorSpace([r1, r2, r3], {0:[0,1], oo:[1]}, base_ring=F) + sage: FilteredVectorSpace([r1, r2, r3], {0:[0,1], oo:[1]}, base_ring=F) # needs sage.rings.finite_rings GF(125)^2 >= GF(125)^1 in GF(125)^3 Or the algebraic field:: - sage: r1 = (1, 0, 1+QQbar(I)); r1 + sage: r1 = (1, 0, 1+QQbar(I)); r1 # needs sage.rings.number_field (1, 0, I + 1) - sage: FilteredVectorSpace([r1, r2, r3], {0:[0,1], oo:[1]}, base_ring=QQbar) + sage: FilteredVectorSpace([r1, r2, r3], {0:[0,1], oo:[1]}, base_ring=QQbar) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Field >= Vector space of dimension 1 over Algebraic Field in Vector space of dimension 3 over Algebraic Field @@ -111,7 +111,6 @@ from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ from sage.rings.real_double import RDF -from sage.rings.real_mpfr import RR from sage.rings.integer import Integer from sage.rings.infinity import InfinityRing, infinity, minus_infinity from sage.categories.fields import Fields @@ -119,6 +118,11 @@ from sage.matrix.constructor import matrix from sage.misc.cachefunc import cached_method +try: + from sage.rings.real_mpfr import RR +except ImportError: + RR = None + def is_FilteredVectorSpace(X): """ @@ -784,11 +788,11 @@ def _repr_field_name(self): sage: FilteredVectorSpace(2, base_ring=QQ)._repr_field_name() 'QQ' - sage: F. = GF(9) - sage: FilteredVectorSpace(2, base_ring=F)._repr_field_name() + sage: F. = GF(9) # needs sage.rings.finite_rings + sage: FilteredVectorSpace(2, base_ring=F)._repr_field_name() # needs sage.rings.finite_rings 'GF(9)' - sage: FilteredVectorSpace(2, base_ring=AA)._repr_field_name() + sage: FilteredVectorSpace(2, base_ring=AA)._repr_field_name() # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError @@ -825,8 +829,8 @@ def _repr_vector_space(self, dim): sage: F3 = FilteredVectorSpace(3, base_ring=GF(3)) sage: F3._repr_vector_space(1234) 'GF(3)^1234' - sage: F3 = FilteredVectorSpace(3, base_ring=AA) - sage: F3._repr_vector_space(1234) + sage: F3 = FilteredVectorSpace(3, base_ring=AA) # needs sage.rings.number_field + sage: F3._repr_vector_space(1234) # needs sage.rings.number_field 'Vector space of dimension 1234 over Algebraic Real Field' """ if dim == 0: @@ -882,7 +886,7 @@ def _repr_(self): QQ^1 >= 0 in QQ^2 sage: FilteredVectorSpace({1:[(1,0), (-1,1)], 3:[(1,0)]}, base_ring=GF(3)) GF(3)^2 >= GF(3)^1 >= GF(3)^1 >= 0 - sage: FilteredVectorSpace({1:[(1,0), (-1,1)], 3:[(1,0)]}, base_ring=AA) + sage: FilteredVectorSpace({1:[(1,0), (-1,1)], 3:[(1,0)]}, base_ring=AA) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field >= Vector space of dimension 1 over Algebraic Real Field >= Vector space of dimension 1 over Algebraic Real Field >= 0 @@ -918,12 +922,13 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.geometry.polyhedron sage.schemes sage: P = toric_varieties.P2() sage: T_P = P.sheaves.tangent_bundle() sage: O_P = P.sheaves.trivial_bundle(1) sage: S1 = T_P + O_P sage: S2 = O_P + T_P - sage: S1._filt[0].is_isomorphic(S2._filt[0]) # known bug + sage: S1._filt[0].is_isomorphic(S2._filt[0]) # known bug True sage: FilteredVectorSpace(2, base_ring=QQ) == FilteredVectorSpace(2, base_ring=GF(5)) @@ -1107,7 +1112,7 @@ def _power_operation(self, n, operation): QQ^2 >= QQ^1 >= 0 sage: F._power_operation(2, 'symmetric') QQ^3 >= QQ^2 >= QQ^1 >= 0 - sage: F._power_operation(2, 'antisymmetric') + sage: F._power_operation(2, 'antisymmetric') # needs sage.groups QQ^1 >= 0 """ from sage.modules.tensor_operations import VectorCollection, TensorOperation @@ -1145,6 +1150,7 @@ def exterior_power(self, n): EXAMPLES:: + sage: # needs sage.groups sage: F = FilteredVectorSpace(1, 1) + FilteredVectorSpace(1, 2); F QQ^2 >= QQ^1 >= 0 sage: F.exterior_power(1) diff --git a/src/sage/modules/finite_submodule_iter.pyx b/src/sage/modules/finite_submodule_iter.pyx index eb433546f23..bb4a730cad9 100644 --- a/src/sage/modules/finite_submodule_iter.pyx +++ b/src/sage/modules/finite_submodule_iter.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings r""" Iterators over finite submodules of a `\ZZ`-module diff --git a/src/sage/modules/fp_graded/element.py b/src/sage/modules/fp_graded/element.py index e4f288f3264..5e348276c33 100755 --- a/src/sage/modules/fp_graded/element.py +++ b/src/sage/modules/fp_graded/element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Elements of finitely presented graded modules diff --git a/src/sage/modules/fp_graded/free_module.py b/src/sage/modules/fp_graded/free_module.py index 3f87d6b9c6f..f8f2fac3f72 100755 --- a/src/sage/modules/fp_graded/free_module.py +++ b/src/sage/modules/fp_graded/free_module.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Finitely generated free graded left modules over connected graded algebras diff --git a/src/sage/modules/fp_graded/homspace.py b/src/sage/modules/fp_graded/homspace.py index 08e30a17dba..6edb4bb7dd6 100755 --- a/src/sage/modules/fp_graded/homspace.py +++ b/src/sage/modules/fp_graded/homspace.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Homsets of finitely presented graded modules diff --git a/src/sage/modules/fp_graded/module.py b/src/sage/modules/fp_graded/module.py index 914a4ad1dc1..cb715523ad7 100755 --- a/src/sage/modules/fp_graded/module.py +++ b/src/sage/modules/fp_graded/module.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Finitely presented graded modules diff --git a/src/sage/modules/fp_graded/morphism.py b/src/sage/modules/fp_graded/morphism.py index fde00303230..47f74fd49e5 100755 --- a/src/sage/modules/fp_graded/morphism.py +++ b/src/sage/modules/fp_graded/morphism.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Homomorphisms of finitely presented graded modules diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 946c354e764..8f584a211ef 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -243,11 +243,11 @@ def create_object(self, version, key): sage: R. = QQ[] sage: Q = R.quo(R.ideal([x^2 - y^2 - 1])) - sage: Q.is_integral_domain() + sage: Q.is_integral_domain() # needs sage.libs.singular True - sage: Q2 = FreeModule(Q, 2) + sage: Q2 = FreeModule(Q, 2) # needs sage.libs.singular sage: from sage.modules.free_module import FreeModule_ambient_domain - sage: isinstance(Q2, FreeModule_ambient_domain) + sage: isinstance(Q2, FreeModule_ambient_domain) # needs sage.libs.singular True """ base_ring, rank, sparse, inner_product_matrix = key @@ -291,6 +291,7 @@ def create_object(self, version, key): return FreeModule_ambient(base_ring, rank, sparse=sparse) + FreeModuleFactory_with_standard_basis = FreeModuleFactory("FreeModule") def FreeModule(base_ring, rank_or_basis_keys=None, sparse=False, inner_product_matrix=None, *, @@ -385,7 +386,7 @@ def FreeModule(base_ring, rank_or_basis_keys=None, sparse=False, inner_product_m Vector space of dimension 10 over Rational Field sage: FreeModule(ZZ,10) Ambient free module of rank 10 over the principal ideal domain Integer Ring - sage: FreeModule(FiniteField(5),10) + sage: FreeModule(FiniteField(5), 10) Vector space of dimension 10 over Finite Field of size 5 sage: FreeModule(Integers(7),10) Vector space of dimension 10 over Ring of integers modulo 7 @@ -613,8 +614,9 @@ def span(gens, base_ring=None, check=True, already_echelonized=False): [ 1 0 -3] [ 0 1 4] - sage: span([V.gen(0)], QuadraticField(-7,'a')) - Vector space of degree 3 and dimension 1 over Number Field in a with defining polynomial x^2 + 7 with a = 2.645751311064591?*I + sage: span([V.gen(0)], QuadraticField(-7,'a')) # needs sage.rings.number_field + Vector space of degree 3 and dimension 1 over Number Field in a + with defining polynomial x^2 + 7 with a = 2.645751311064591?*I Basis matrix: [ 1 0 -3] @@ -1013,8 +1015,8 @@ def some_elements(self): ... (46/103823, -46/103823, 103823/46)) - sage: F = FreeModule(SR, 2) - sage: tuple(F.some_elements()) + sage: F = FreeModule(SR, 2) # needs sage.symbolic + sage: tuple(F.some_elements()) # needs sage.symbolic ((1, 0), (some_variable, some_variable)) """ yield self.an_element() @@ -1187,19 +1189,21 @@ def __richcmp__(self, other, op): More exotic comparisons:: + sage: # needs sage.symbolic sage: R1 = ZZ[sqrt(2)] sage: F1 = R1^3 - sage: V1 = F1.span([[sqrt(2),sqrt(2),0]]) + sage: V1 = F1.span([[sqrt(2), sqrt(2), 0]]) sage: F2 = ZZ^3 sage: V2 = F2.span([[2,2,0]]) sage: V2 <= V1 # Different ambient vector spaces False sage: V1 <= V2 False - sage: R2 = GF(5)[x] + + sage: R2. = GF(5)[] sage: F3 = R2^3 - sage: V3 = F3.span([[x^5-1,1+x+x^2+x^3+x^4,0]]) - sage: W3 = F3.span([[1,1,0],[0,4,0]]) + sage: V3 = F3.span([[x^5 - 1, 1 + x + x^2 + x^3 + x^4, 0]]) + sage: W3 = F3.span([[1,1,0], [0,4,0]]) sage: V3 <= W3 True sage: W3 <= V3 @@ -1568,11 +1572,11 @@ def span(self, gens, base_ring=None, check=True, already_echelonized=False): EXAMPLES:: sage: V = VectorSpace(GF(7), 3) - sage: W = V.subspace([[2,3,4]]); W + sage: W = V.subspace([[2, 3, 4]]); W Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [1 5 2] - sage: W.span([[1,1,1]]) + sage: W.span([[1, 1, 1]]) Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [1 1 1] @@ -1636,19 +1640,19 @@ def span(self, gens, base_ring=None, check=True, already_echelonized=False): TESTS:: - sage: V = FreeModule(RDF,3) + sage: V = FreeModule(RDF, 3) sage: W = V.submodule([V.gen(0)]) sage: W.span([V.gen(1)], base_ring=GF(7)) Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: [0 1 0] - sage: v = V((1, pi, log(2))); v + sage: v = V((1, pi, log(2))); v # needs sage.symbolic (1.0, 3.141592653589793, 0.6931471805599453) - sage: W.span([v], base_ring=GF(7)) + sage: W.span([v], base_ring=GF(7)) # needs sage.rings.finite_rings sage.symbolic Traceback (most recent call last): ... ValueError: argument gens (= [(1.0, 3.141592653589793, 0.6931471805599453)]) is not compatible with base_ring (= Finite Field of size 7) - sage: W = V.submodule([v]) + sage: W = V.submodule([v]) # needs sage.symbolic sage: W.span([V.gen(2)], base_ring=GF(7)) Vector space of degree 3 and dimension 1 over Finite Field of size 7 Basis matrix: @@ -1810,10 +1814,9 @@ def free_resolution(self, *args, **kwds): sage: S. = PolynomialRing(QQ) sage: M = S**2 sage: N = M.submodule([vector([x - y, z]), vector([y * z, x * z])]) - sage: res = N.free_resolution() - sage: res + sage: res = N.free_resolution(); res # needs sage.libs.singular S^2 <-- S^2 <-- 0 - sage: ascii_art(res.chain_complex()) + sage: ascii_art(res.chain_complex()) # needs sage.libs.singular [x - y y*z] [ z x*z] 0 <-- C_0 <-------------- C_1 <-- 0 @@ -1842,13 +1845,13 @@ def graded_free_resolution(self, *args, **kwds): sage: S. = PolynomialRing(QQ) sage: M = S**2 sage: N = M.submodule([vector([x - y, z]), vector([y * z, x * z])]) - sage: N.graded_free_resolution(shifts=[1, -1]) + sage: N.graded_free_resolution(shifts=[1, -1]) # needs sage.libs.singular S(-1)⊕S(1) <-- S(-2)⊕S(-3) <-- 0 - sage: N.graded_free_resolution(shifts=[2, 3]) + sage: N.graded_free_resolution(shifts=[2, 3]) # needs sage.libs.singular S(-2)⊕S(-3) <-- S(-3)⊕S(-4) <-- 0 sage: N = M.submodule([vector([x^3 - y^6, z^2]), vector([y * z, x])]) - sage: N.graded_free_resolution(degrees=[2, 1, 3], shifts=[2, 3]) + sage: N.graded_free_resolution(degrees=[2, 1, 3], shifts=[2, 3]) # needs sage.libs.singular S(-2)⊕S(-3) <-- S(-6)⊕S(-8) <-- 0 """ from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular @@ -1893,16 +1896,18 @@ class FreeModule_generic(Module_free_ambient): EXAMPLES:: sage: PolynomialRing(QQ,3,'x')^3 - Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring in x0, x1, x2 over Rational Field + Ambient free module of rank 3 over the integral domain + Multivariate Polynomial Ring in x0, x1, x2 over Rational Field - sage: FreeModule(GF(7),3).category() + sage: FreeModule(GF(7), 3).category() Category of enumerated finite dimensional vector spaces with basis over (finite enumerated fields and subquotients of monoids and quotients of semigroups) sage: V = QQ^4; V.category() Category of finite dimensional vector spaces with basis over (number fields and quotient fields and metric spaces) sage: V = GF(5)**20; V.category() - Category of enumerated finite dimensional vector spaces with basis over (finite enumerated fields and subquotients of monoids and quotients of semigroups) + Category of enumerated finite dimensional vector spaces with basis over + (finite enumerated fields and subquotients of monoids and quotients of semigroups) sage: FreeModule(ZZ,3).category() Category of finite dimensional modules with basis over (euclidean domains and infinite enumerated sets @@ -1958,7 +1963,7 @@ def __init__(self, base_ring, rank, degree, sparse=False, rank = sage.rings.integer.Integer(rank) if rank < 0: - raise ValueError("rank (=%s) must be nonnegative"%rank) + raise ValueError("rank (=%s) must be nonnegative" % rank) Module_free_ambient.__init__(self, base_ring, degree=degree, sparse=sparse, category=category) self.__coordinate_ring = coordinate_ring @@ -2355,14 +2360,16 @@ def __iter__(self): EXAMPLES:: - sage: V = VectorSpace(GF(4,'a'),2) - sage: [x for x in V] - [(0, 0), (a, 0), (a + 1, 0), (1, 0), (0, a), (a, a), (a + 1, a), (1, a), (0, a + 1), (a, a + 1), (a + 1, a + 1), (1, a + 1), (0, 1), (a, 1), (a + 1, 1), (1, 1)] + sage: V = VectorSpace(GF(4, 'a'), 2) # needs sage.rings.finite_rings + sage: [x for x in V] # needs sage.rings.finite_rings + [(0, 0), (a, 0), (a + 1, 0), (1, 0), (0, a), (a, a), (a + 1, a), (1, a), + (0, a + 1), (a, a + 1), (a + 1, a + 1), (1, a + 1), (0, 1), (a, 1), + (a + 1, 1), (1, 1)] :: - sage: W = V.subspace([V([1,1])]) - sage: [x for x in W] + sage: W = V.subspace([V([1, 1])]) # needs sage.rings.finite_rings + sage: [x for x in W] # needs sage.rings.finite_rings [(0, 0), (a, a), (a + 1, a + 1), (1, 1)] Free modules over enumerated infinite rings (i.e., those in the @@ -2379,7 +2386,7 @@ def __iter__(self): TESTS:: - sage: V = VectorSpace(GF(2,'a'),2) + sage: V = VectorSpace(GF(2, 'a'), 2) sage: V.list() [(0, 0), (1, 0), (0, 1), (1, 1)] @@ -2462,17 +2469,20 @@ def cardinality(self): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: k. = FiniteField(9) - sage: V = VectorSpace(k,3) + sage: V = VectorSpace(k, 3) sage: V.cardinality() 729 - sage: W = V.span([[1,2,1],[0,1,1]]) + sage: W = V.span([[1,2,1], [0,1,1]]) sage: W.cardinality() 81 + sage: R = IntegerModRing(12) - sage: M = FreeModule(R,2) + sage: M = FreeModule(R, 2) sage: M.cardinality() 144 + sage: (QQ^3).cardinality() +Infinity @@ -2533,7 +2543,7 @@ def basis_matrix(self, ring=None): :: - sage: M = FreeModule(GF(7),3).span([[2,3,4],[1,1,1]]); M + sage: M = FreeModule(GF(7), 3).span([[2,3,4], [1,1,1]]); M Vector space of degree 3 and dimension 2 over Finite Field of size 7 Basis matrix: [1 0 6] @@ -2544,7 +2554,7 @@ def basis_matrix(self, ring=None): :: - sage: M = FreeModule(GF(7),3).span_of_basis([[2,3,4],[1,1,1]]) + sage: M = FreeModule(GF(7), 3).span_of_basis([[2,3,4], [1,1,1]]) sage: M.basis_matrix() [2 3 4] [1 1 1] @@ -2770,6 +2780,7 @@ def coordinate_module(self, V): function to write a submodule in terms of integral cuspidal modular symbols:: + sage: # needs sage.modular sage: M = ModularSymbols(54) sage: S = M.cuspidal_subspace() sage: K = S.integral_structure(); K @@ -2867,8 +2878,9 @@ def base_field(self): Finite Field of size 3 sage: FreeModule(ZZ, 2).base_field() Rational Field - sage: FreeModule(PolynomialRing(GF(7),'x'), 2).base_field() - Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 7 + sage: FreeModule(PolynomialRing(GF(7), 'x'), 2).base_field() + Fraction Field of Univariate Polynomial Ring in x + over Finite Field of size 7 """ return self.base_ring().fraction_field() @@ -3346,91 +3358,95 @@ def _magma_init_(self, magma): :: + sage: # optional - magma sage: A = matrix([[1,0],[0,-1]]) sage: M = FreeModule(ZZ,2,inner_product_matrix=A); M Ambient free quadratic module of rank 2 over the principal ideal domain Integer Ring Inner product matrix: [ 1 0] [ 0 -1] - sage: M._magma_init_(magma) # optional - magma + sage: M._magma_init_(magma) 'RSpace(_sage_[...],2,_sage_ref...)' - sage: m = magma(M); m # optional - magma + sage: m = magma(M); m Full RSpace of degree 2 over Integer Ring Inner Product Matrix: [ 1 0] [ 0 -1] - sage: m.Type() # optional - magma + sage: m.Type() ModTupRng - sage: m.sage() # optional - magma + sage: m.sage() Ambient free quadratic module of rank 2 over the principal ideal domain Integer Ring Inner product matrix: [ 1 0] [ 0 -1] - sage: m.sage() is M # optional - magma + sage: m.sage() is M True Now over a field:: + sage: # optional - magma sage: N = FreeModule(QQ,2,inner_product_matrix=A); N Ambient quadratic space of dimension 2 over Rational Field Inner product matrix: [ 1 0] [ 0 -1] - sage: n = magma(N); n # optional - magma + sage: n = magma(N); n Full Vector space of degree 2 over Rational Field Inner Product Matrix: [ 1 0] [ 0 -1] - sage: n.Type() # optional - magma + sage: n.Type() ModTupFld - sage: n.sage() # optional - magma + sage: n.sage() Ambient quadratic space of dimension 2 over Rational Field Inner product matrix: [ 1 0] [ 0 -1] - sage: n.sage() is N # optional - magma + sage: n.sage() is N True How about some inexact fields:: + sage: # optional - magma, needs sage.symbolic sage: v = vector(RR, [1, pi, 5/6]) sage: F = v.parent() - sage: M = magma(F); M # optional - magma + sage: M = magma(F); M Full Vector space of degree 3 over Real field of precision 15 - sage: M.Type() # optional - magma + sage: M.Type() ModTupFld - sage: m = M.sage(); m # optional - magma + sage: m = M.sage(); m Vector space of dimension 3 over Real Field with 53 bits of precision - sage: m is F # optional - magma + sage: m is F True For interval fields, we can convert to Magma but there is no interval field in Magma so we cannot convert back:: + sage: # optional - magma, needs sage.symbolic sage: v = vector(RealIntervalField(100), [1, pi, 0.125]) sage: F = v.parent() - sage: M = magma(v.parent()); M # optional - magma + sage: M = magma(v.parent()); M Full Vector space of degree 3 over Real field of precision 30 - sage: M.Type() # optional - magma + sage: M.Type() ModTupFld - sage: m = M.sage(); m # optional - magma + sage: m = M.sage(); m Vector space of dimension 3 over Real Field with 100 bits of precision - sage: m is F # optional - magma + sage: m is F False """ K = magma(self.base_ring()) if not self._inner_product_is_dot_product(): M = magma(self.inner_product_matrix()) - return "RSpace(%s,%s,%s)"%(K.name(), self.rank(), M._ref()) + return "RSpace(%s,%s,%s)" % (K.name(), self.rank(), M._ref()) else: - return "RSpace(%s,%s)"%(K.name(), self.rank()) + return "RSpace(%s,%s)" % (K.name(), self.rank()) def _macaulay2_(self, macaulay2=None): r""" EXAMPLES:: sage: R = QQ^2 - sage: macaulay2(R) # optional - macaulay2 + sage: macaulay2(R) # optional - macaulay2 2 QQ """ @@ -3531,7 +3547,8 @@ def _mul_(self, other, switch_sides=False): sage: W = V.subspace([[1, 0]]) sage: x = matrix(GF(2), [[1, 1], [0, 1]]) sage: W*x - Vector space of degree 2 and dimension 1 over Finite Field of size 2 + Vector space of degree 2 and dimension 1 + over Finite Field of size 2 Basis matrix: [1 1] @@ -3571,9 +3588,12 @@ def __init__(self, base_ring, rank, degree, sparse=False, coordinate_ring=None, EXAMPLES:: sage: FreeModule(ZZ, 2) - Ambient free module of rank 2 over the principal ideal domain Integer Ring - sage: FreeModule(PolynomialRing(GF(7),'x'), 2) - Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Finite Field of size 7 + Ambient free module of rank 2 + over the principal ideal domain Integer Ring + sage: FreeModule(PolynomialRing(GF(7), 'x'), 2) + Ambient free module of rank 2 + over the principal ideal domain Univariate Polynomial Ring in x + over Finite Field of size 7 """ FreeModule_generic.__init__(self, base_ring, rank, degree, sparse, coordinate_ring, category=category) @@ -3648,7 +3668,7 @@ def __add__(self, other): if not isinstance(other, FreeModule_generic): if other == 0: return self - raise TypeError("other (=%s) must be a free module"%other) + raise TypeError("other (=%s) must be a free module" % other) if not (self.ambient_vector_space() == other.ambient_vector_space()): raise TypeError("ambient vector spaces must be equal") return self.span(self.basis() + other.basis()) @@ -3665,9 +3685,12 @@ def __init__(self, base_ring, rank, degree, sparse=False, coordinate_ring=None, EXAMPLES:: sage: FreeModule(ZZ, 2) - Ambient free module of rank 2 over the principal ideal domain Integer Ring - sage: FreeModule(PolynomialRing(GF(7),'x'), 2) - Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Finite Field of size 7 + Ambient free module of rank 2 + over the principal ideal domain Integer Ring + sage: FreeModule(PolynomialRing(GF(7), 'x'), 2) + Ambient free module of rank 2 + over the principal ideal domain Univariate Polynomial Ring in x + over Finite Field of size 7 """ super().__init__(base_ring, rank, degree, sparse, coordinate_ring, category=category) @@ -3796,6 +3819,7 @@ def intersection(self, other): We intersect two modules over the ring of integers of a number field:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') sage: L. = NumberField(x^2 - x + 2) sage: OL = L.ring_of_integers() @@ -4080,7 +4104,7 @@ def span_of_basis(self, basis, base_ring=None, check=True, already_echelonized=F try: return M.span_of_basis(basis) except TypeError: - raise ValueError("Argument gens (= %s) is not compatible "%basis + + raise ValueError("Argument gens (= %s) is not compatible " % basis + "with base_ring (= %s)." % base_ring) def submodule_with_basis(self, basis, check=True, already_echelonized=False): @@ -4194,10 +4218,11 @@ def vector_space_span(self, gens, check=True): :: sage: R. = QQ[] - sage: K = NumberField(x^2 + 1, 'a'); a = K.gen() - sage: V = VectorSpace(K, 3) - sage: V.vector_space_span([2*V.gen(0) + 3*V.gen(2)]) - Vector space of degree 3 and dimension 1 over Number Field in a with defining polynomial x^2 + 1 + sage: K = NumberField(x^2 + 1, 'a'); a = K.gen() # needs sage.rings.number_field + sage: V = VectorSpace(K, 3) # needs sage.rings.number_field + sage: V.vector_space_span([2*V.gen(0) + 3*V.gen(2)]) # needs sage.rings.number_field + Vector space of degree 3 and dimension 1 + over Number Field in a with defining polynomial x^2 + 1 Basis matrix: [ 1 0 3/2] @@ -4304,7 +4329,7 @@ def __init__(self, base_field, dimension, degree, sparse=False, category=None): ) failed: NotImplementedError> """ if not isinstance(base_field, ring.Field): - raise TypeError("The base_field (=%s) must be a field"%base_field) + raise TypeError("The base_field (=%s) must be a field" % base_field) super().__init__(base_field, dimension, degree, sparse=sparse, category=category) def _Hom_(self, Y, category): @@ -4689,7 +4714,7 @@ def subspaces(self, dim): :: sage: V = VectorSpace(GF(3), 5) - sage: V = V.subspace([V([1,1,0,0,0]),V([0,0,1,1,0])]) + sage: V = V.subspace([V([1,1,0,0,0]), V([0,0,1,1,0])]) sage: list(V.subspaces(1)) [Vector space of degree 5 and dimension 1 over Finite Field of size 3 Basis matrix: @@ -4797,10 +4822,9 @@ def complement(self): we can get complements which are only isomorphic to a vector space decomposition complement. :: - sage: F2 = GF(2,x) + sage: F2 = GF(2, 'x') sage: V = F2^6 - sage: W = V.span([[1,1,0,0,0,0]]) - sage: W + sage: W = V.span([[1,1,0,0,0,0]]); W Vector space of degree 6 and dimension 1 over Finite Field of size 2 Basis matrix: [1 1 0 0 0 0] @@ -5226,8 +5250,8 @@ def quotient_abstract(self, sub, check=True, **kwds): EXAMPLES:: sage: V = GF(19)^3 - sage: W = V.span_of_basis([ [1,2,3], [1,0,1] ]) - sage: U,pi,lift = V.quotient_abstract(W) + sage: W = V.span_of_basis([[1,2,3], [1,0,1]]) + sage: U, pi, lift = V.quotient_abstract(W) sage: pi(V.2) (18) sage: pi(V.0) @@ -5297,6 +5321,7 @@ def __init__(self, base_ring, rank, sparse=False, coordinate_ring=None, category We check that the creation of a submodule does not trigger the construction of a basis of the ambient space. See :trac:`15953`:: + sage: # needs sage.rings.finite_rings sage: F. = GF(4) sage: V = VectorSpace(F, 1) sage: v = V.random_element() @@ -5572,9 +5597,9 @@ def _repr_(self): Ambient free module of rank 12 over Ring of integers modulo 12 """ if self.is_sparse(): - return "Ambient sparse free module of rank %s over %s"%(self.rank(), self.base_ring()) + return "Ambient sparse free module of rank %s over %s" % (self.rank(), self.base_ring()) else: - return "Ambient free module of rank %s over %s"%(self.rank(), self.base_ring()) + return "Ambient free module of rank %s over %s" % (self.rank(), self.base_ring()) def _latex_(self): r""" @@ -5582,19 +5607,19 @@ def _latex_(self): EXAMPLES:: - sage: latex(QQ^3) # indirect doctest + sage: latex(QQ^3) # indirect doctest \Bold{Q}^{3} :: sage: A = GF(5)^20 - sage: latex(A) # indirect doctest + sage: latex(A) # indirect doctest \Bold{F}_{5}^{20} :: - sage: A = PolynomialRing(QQ,3,'x') ^ 20 - sage: latex(A) #indirect doctest + sage: A = PolynomialRing(QQ, 3, 'x')^20 + sage: latex(A) # indirect doctest (\Bold{Q}[x_{0}, x_{1}, x_{2}])^{20} """ t = "%s" % latex.latex(self.base_ring()) @@ -5959,9 +5984,9 @@ def _sympy_(self): EXAMPLES:: - sage: sZZ3 = (ZZ^3)._sympy_(); sZZ3 + sage: sZZ3 = (ZZ^3)._sympy_(); sZZ3 # needs sympy ProductSet(Integers, Integers, Integers) - sage: (1, 2, 3) in sZZ3 + sage: (1, 2, 3) in sZZ3 # needs sympy True """ from sympy import ProductSet @@ -5982,7 +6007,7 @@ class FreeModule_ambient_domain(FreeModule_generic_domain, FreeModule_ambient): EXAMPLES:: - sage: FreeModule(PolynomialRing(GF(5),'x'), 3) + sage: FreeModule(PolynomialRing(GF(5), 'x'), 3) Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in x over Finite Field of size 5 """ @@ -6038,10 +6063,10 @@ def _repr_(self): Ambient free module of rank 7 over the integral domain Univariate Polynomial Ring in x over Integer Ring """ if self.is_sparse(): - return "Ambient sparse free module of rank %s over the integral domain %s"%( + return "Ambient sparse free module of rank %s over the integral domain %s" % ( self.rank(), self.base_ring()) else: - return "Ambient free module of rank %s over the integral domain %s"%( + return "Ambient free module of rank %s over the integral domain %s" % ( self.rank(), self.base_ring()) def ambient_vector_space(self): @@ -6230,10 +6255,10 @@ def _repr_(self): Ambient free module of rank 7 over the principal ideal domain Integer Ring """ if self.is_sparse(): - return "Ambient sparse free module of rank %s over the principal ideal domain %s"%( + return "Ambient sparse free module of rank %s over the principal ideal domain %s" % ( self.rank(), self.base_ring()) else: - return "Ambient free module of rank %s over the principal ideal domain %s"%( + return "Ambient free module of rank %s over the principal ideal domain %s" % ( self.rank(), self.base_ring()) @@ -6307,9 +6332,9 @@ def _repr_(self): Vector space of dimension 7 over Rational Field """ if self.is_sparse(): - return "Sparse vector space of dimension %s over %s"%(self.dimension(), self.base_ring()) + return "Sparse vector space of dimension %s over %s" % (self.dimension(), self.base_ring()) else: - return "Vector space of dimension %s over %s"%(self.dimension(), self.base_ring()) + return "Vector space of dimension %s over %s" % (self.dimension(), self.base_ring()) def ambient_vector_space(self): """ @@ -6341,9 +6366,9 @@ def _element_constructor_(self, e, *args, **kwds): EXAMPLES:: - sage: k. = GF(3^4) - sage: VS = k.vector_space(map=False) - sage: VS(a) + sage: k. = GF(3^4) # needs sage.rings.finite_rings + sage: VS = k.vector_space(map=False) # needs sage.rings.finite_rings + sage: VS(a) # needs sage.rings.finite_rings (0, 1, 0, 0) """ try: @@ -6454,8 +6479,8 @@ def __init__(self, ambient, basis, check=True, :trac:`10250` is solved as well:: sage: V = (QQ^2).span_of_basis([[1,1]]) - sage: w = sqrt(2) * V([1,1]) - sage: 3 * w + sage: w = sqrt(2) * V([1,1]) # needs sage.symbolic + sage: 3 * w # needs sage.symbolic (3*sqrt(2), 3*sqrt(2)) TESTS: @@ -6675,9 +6700,9 @@ def _echelonized_basis(self, ambient, basis): sage: W = V.submodule_with_basis([[1,1,0],[0,2,1]]) sage: W._echelonized_basis(V,W.basis()) [(1, 0, -1/2), (0, 1, 1/2)] - sage: V = SR^3 + sage: V = SR^3 # needs sage.symbolic sage: W = V.submodule_with_basis([[1,0,1]]) - sage: W._echelonized_basis(V,W.basis()) + sage: W._echelonized_basis(V, W.basis()) [(1, 0, 1)] """ # Return the first rank rows (i.e., the nonzero rows). @@ -6758,11 +6783,11 @@ def _repr_(self): [-1 0 0 0 0 0 0 1] """ if self.is_sparse(): - s = "Sparse free module of degree %s and rank %s over %s\n"%( + s = "Sparse free module of degree %s and rank %s over %s\n" % ( self.degree(), self.rank(), self.base_ring()) + \ "User basis matrix:\n%r" % self.basis_matrix() else: - s = "Free module of degree %s and rank %s over %s\n"%( + s = "Free module of degree %s and rank %s over %s\n" % ( self.degree(), self.rank(), self.base_ring()) + \ "User basis matrix:\n%r" % self.basis_matrix() return s @@ -6778,7 +6803,7 @@ def _latex_(self): sage: M._latex_() '\\mathrm{RowSpan}_{\\Bold{Z}}\\left(\\begin{array}{rrr}\n1 & 2 & 3 \\\\\n4 & 5 & 6\n\\end{array}\\right)' """ - return "\\mathrm{RowSpan}_{%s}%s"%(latex.latex(self.base_ring()), latex.latex(self.basis_matrix())) + return "\\mathrm{RowSpan}_{%s}%s" % (latex.latex(self.base_ring()), latex.latex(self.basis_matrix())) def ambient_module(self): """ @@ -7580,13 +7605,13 @@ def _repr_(self): [ 0 0 0 0 0 0 1 -1] """ if self.is_sparse(): - s = "Sparse free module of degree %s and rank %s over %s\n"%( + s = "Sparse free module of degree %s and rank %s over %s\n" % ( self.degree(), self.rank(), self.base_ring()) + \ - "Echelon basis matrix:\n%s"%self.basis_matrix() + "Echelon basis matrix:\n%s" % self.basis_matrix() else: - s = "Free module of degree %s and rank %s over %s\n"%( + s = "Free module of degree %s and rank %s over %s\n" % ( self.degree(), self.rank(), self.base_ring()) + \ - "Echelon basis matrix:\n%s"%self.basis_matrix() + "Echelon basis matrix:\n%s" % self.basis_matrix() return s def coordinate_vector(self, v, check=True): @@ -7641,6 +7666,7 @@ def has_user_basis(self): """ return False + FreeModule_generic_pid._submodule_class = FreeModule_submodule_pid @@ -7783,11 +7809,11 @@ def _repr_(self): [ 0 0 0 1 -1] """ if self.is_sparse(): - return "Sparse vector space of degree %s and dimension %s over %s\n"%( + return "Sparse vector space of degree %s and dimension %s over %s\n" % ( self.degree(), self.dimension(), self.base_field()) + \ "User basis matrix:\n%r" % self.basis_matrix() else: - return "Vector space of degree %s and dimension %s over %s\n"%( + return "Vector space of degree %s and dimension %s over %s\n" % ( self.degree(), self.dimension(), self.base_field()) + \ "User basis matrix:\n%r" % self.basis_matrix() @@ -7982,11 +8008,11 @@ def _repr_(self): [ 0 0 0 1 -1] """ if self.is_sparse(): - return "Sparse vector space of degree %s and dimension %s over %s\n"%( + return "Sparse vector space of degree %s and dimension %s over %s\n" % ( self.degree(), self.dimension(), self.base_field()) + \ "Basis matrix:\n%r" % self.basis_matrix() else: - return "Vector space of degree %s and dimension %s over %s\n"%( + return "Vector space of degree %s and dimension %s over %s\n" % ( self.degree(), self.dimension(), self.base_field()) + \ "Basis matrix:\n%r" % self.basis_matrix() @@ -8033,7 +8059,7 @@ def echelon_coordinates(self, v, check=True): if not isinstance(v, free_module_element.FreeModuleElement): v = self.ambient_vector_space()(v) if v.degree() != self.degree(): - raise ArithmeticError("v (=%s) is not in self"%v) + raise ArithmeticError("v (=%s) is not in self" % v) E = self.echelonized_basis_matrix() P = E.pivots() if not P: @@ -8118,6 +8144,7 @@ def has_user_basis(self): """ return False + FreeModule_generic_field._submodule_class = FreeModule_submodule_field @@ -8142,7 +8169,7 @@ def element_class(R, is_sparse): sage: sage.modules.free_module.element_class(FF, is_sparse=True) - sage: sage.modules.free_module.element_class(FF, is_sparse=False) + sage: sage.modules.free_module.element_class(FF, is_sparse=False) # needs sage.rings.finite_rings sage: sage.modules.free_module.element_class(GF(7), is_sparse=False) @@ -8159,14 +8186,21 @@ def element_class(R, is_sparse): from .vector_rational_dense import Vector_rational_dense return Vector_rational_dense elif isinstance(R, sage.rings.abc.IntegerModRing) and not is_sparse: - from .vector_mod2_dense import Vector_mod2_dense if R.order() == 2: - return Vector_mod2_dense - from .vector_modn_dense import Vector_modn_dense, MAX_MODULUS - if R.order() < MAX_MODULUS: - return Vector_modn_dense + try: + from .vector_mod2_dense import Vector_mod2_dense + except ImportError: + pass + else: + return Vector_mod2_dense + try: + from .vector_modn_dense import Vector_modn_dense, MAX_MODULUS + except ImportError: + pass else: - return free_module_element.FreeModuleElement_generic_dense + if R.order() < MAX_MODULUS: + return Vector_modn_dense + return free_module_element.FreeModuleElement_generic_dense elif isinstance(R, sage.rings.abc.RealDoubleField) and not is_sparse: try: from sage.modules.vector_real_double_dense import Vector_real_double_dense diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index f813b37cf70..d5e8256b68c 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -63,7 +63,9 @@ Since there is no canonical coercion map to the finite field from sage: V.0 + M.0 Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for +: 'Vector space of dimension 5 over Rational Field' and 'Vector space of dimension 5 over Finite Field of size 7' + TypeError: unsupported operand parent(s) for +: + 'Vector space of dimension 5 over Rational Field' and + 'Vector space of dimension 5 over Finite Field of size 7' However, there is a map from `\ZZ` to the finite field, so the following is defined, and the result is in the finite @@ -93,7 +95,7 @@ TESTS:: sage: u = 7 sage: R = Integers(D) sage: p = matrix(R,[[84, 97, 55, 58, 51]]) - sage: 2*p.row(0) + sage: 2*p.row(0) # needs sage.libs.pari (168, 194, 110, 116, 102) This is a test from :trac:`20211`:: @@ -345,6 +347,7 @@ def vector(arg0, arg1=None, arg2=None, sparse=None, immutable=False): must be contiguous, so column-wise slices of numpy matrices will raise an exception. :: + sage: # needs numpy sage: import numpy sage: x = numpy.random.randn(10) sage: y = vector(x) @@ -363,6 +366,7 @@ def vector(arg0, arg1=None, arg2=None, sparse=None, immutable=False): Multi-dimensional arrays are not supported:: + sage: # needs numpy sage: import numpy as np sage: a = np.array([[1, 2, 3], [4, 5, 6]], np.float64) sage: vector(a) @@ -382,27 +386,29 @@ def vector(arg0, arg1=None, arg2=None, sparse=None, immutable=False): (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) sage: v[3].parent() Integer Ring - sage: v = vector([float(23.4), int(2), complex(2+7*I), 1]); v + sage: v = vector([float(23.4), int(2), complex(2+7*I), 1]); v # needs sage.symbolic (23.4, 2.0, 2.0 + 7.0*I, 1.0) - sage: v[1].parent() + sage: v[1].parent() # needs sage.symbolic Complex Double Field If the argument is a vector, it doesn't change the base ring. This fixes :trac:`6643`:: + sage: # needs sage.rings.number_field sage: K. = QuadraticField(3) - sage: u = vector(K, (1/2, sqrt3/2) ) + sage: u = vector(K, (1/2, sqrt3/2)) sage: vector(u).base_ring() Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878? - sage: v = vector(K, (0, 1) ) + sage: v = vector(K, (0, 1)) sage: vector(v).base_ring() Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878? Constructing a vector from a numpy array behaves as expected:: + sage: # needs numpy sage: import numpy - sage: a=numpy.array([1,2,3]) - sage: v=vector(a); v + sage: a = numpy.array([1,2,3]) + sage: v = vector(a); v (1, 2, 3) sage: parent(v) Ambient free module of rank 3 over the principal ideal domain Integer Ring @@ -450,8 +456,10 @@ def vector(arg0, arg1=None, arg2=None, sparse=None, immutable=False): sage: v = vector(QQ, w, immutable=True) sage: v.is_immutable() True + + sage: # needs numpy sage: import numpy as np - sage: w = np.array([1, 2, pi], float) + sage: w = np.array([1, 2, pi], float) # needs sage.symbolic sage: v = vector(w, immutable=True) sage: v.is_immutable() True @@ -464,9 +472,9 @@ def vector(arg0, arg1=None, arg2=None, sparse=None, immutable=False): We check that :trac:`31470` is fixed:: - sage: k. = GF(5^3) - sage: S. = k['x', k.frobenius_endomorphism()] - sage: vector(S, 3) + sage: k. = GF(5^3) # needs sage.rings.finite_rings + sage: S. = k['x', k.frobenius_endomorphism()] # needs sage.rings.finite_rings + sage: vector(S, 3) # needs sage.rings.finite_rings ... (0, 0, 0) """ @@ -624,25 +632,27 @@ def prepare(v, R, degree=None): EXAMPLES:: sage: from sage.modules.free_module_element import prepare - sage: prepare([1,2/3,5],None) + sage: prepare([1, 2/3, 5], None) ([1, 2/3, 5], Rational Field) - sage: prepare([1,2/3,5],RR) - ([1.00000000000000, 0.666666666666667, 5.00000000000000], Real Field with 53 bits of precision) + sage: prepare([1, 2/3, 5], RR) + ([1.00000000000000, 0.666666666666667, 5.00000000000000], + Real Field with 53 bits of precision) - sage: prepare({1:4, 3:-2}, ZZ, 6) + sage: prepare({1: 4, 3: -2}, ZZ, 6) ([0, 4, 0, -2, 0, 0], Integer Ring) - sage: prepare({3:1, 5:3}, QQ, 6) + sage: prepare({3: 1, 5: 3}, QQ, 6) ([0, 0, 0, 1, 0, 3], Rational Field) - sage: prepare([1,2/3,'10',5],RR) - ([1.00000000000000, 0.666666666666667, 10.0000000000000, 5.00000000000000], Real Field with 53 bits of precision) + sage: prepare([1, 2/3, '10', 5], RR) + ([1.00000000000000, 0.666666666666667, 10.0000000000000, 5.00000000000000], + Real Field with 53 bits of precision) - sage: prepare({},QQ, 0) + sage: prepare({}, QQ, 0) ([], Rational Field) - sage: prepare([1,2/3,'10',5],None) + sage: prepare([1, 2/3, '10', 5], None) Traceback (most recent call last): ... TypeError: unable to find a common ring for all elements @@ -650,8 +660,8 @@ def prepare(v, R, degree=None): Some objects can be converted to sequences even if they are not always thought of as sequences. :: - sage: c = CDF(2+3*I) - sage: prepare(c, None) + sage: c = CDF(2 + 3*I) # needs sage.symbolic + sage: prepare(c, None) # needs sage.symbolic ([2.0, 3.0], Real Double Field) This checks a bug listed at :trac:`10595`. Without good evidence @@ -744,7 +754,7 @@ def zero_vector(arg0, arg1=None): Garbage instead of a ring will be recognized as such. :: - sage: zero_vector(x^2, 5) + sage: zero_vector(x^2, 5) # needs sage.symbolic Traceback (most recent call last): ... TypeError: first argument must be a ring @@ -875,9 +885,13 @@ def random_vector(ring, degree=None, *args, **kwds): sage: w1 = vector(ZZ.random_element(distribution="1/n") for _ in range(20)) sage: w2 = vector(ZZ.random_element(x=-1000, y=1000) for _ in range(15)) sage: w3 = vector(QQ.random_element() for _ in range(10)) + sage: [v1, v2, v3] == [w1, w2, w3] + True sage: w4 = vector(FiniteField(17).random_element() for _ in range(10)) + sage: v4 == w4 + True sage: w5 = vector(RR.random_element() for _ in range(10)) - sage: [v1, v2, v3, v4, v5] == [w1, w2, w3, w4, w5] + sage: v5 == w5 True Inputs get checked before constructing the vector. :: @@ -938,20 +952,20 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: sage: v = vector(ZZ, 4, range(4)) - sage: giac(v)+v + sage: giac(v) + v # needs sage.libs.giac [0,2,4,6] :: sage: v = vector(QQ, 3, [2/3, 0, 5/4]) - sage: giac(v) + sage: giac(v) # needs sage.libs.giac [2/3,0,5/4] :: sage: P. = ZZ[] sage: v = vector(P, 3, [x^2 + 2, 2*x + 1, -2*x^2 + 4*x]) - sage: giac(v) + sage: giac(v) # needs sage.libs.giac [sageVARx^2+2,2*sageVARx+1,-2*sageVARx^2+4*sageVARx] """ return self.list() @@ -967,15 +981,15 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: sage: v = vector(range(4)) - sage: v.__pari__() + sage: v.__pari__() # needs sage.libs.pari [0, 1, 2, 3] - sage: v.__pari__().type() + sage: v.__pari__().type() # needs sage.libs.pari 't_VEC' A list of vectors:: sage: L = [vector(i^n for i in range(4)) for n in [1,3,5]] - sage: pari(L) + sage: pari(L) # needs sage.libs.pari [[0, 1, 2, 3], [0, 1, 8, 27], [0, 1, 32, 243]] """ from sage.libs.pari.all import pari @@ -993,11 +1007,12 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: sage: v = vector(range(4)) - sage: v._pari_init_() + sage: v._pari_init_() # needs sage.libs.pari '[0,1,2,3]' Create the multiplication table of `GF(4)` using GP:: + sage: # needs sage.libs.pari sage: k. = GF(4, impl="pari_ffelt") sage: v = gp(vector(list(k))) sage: v @@ -1063,22 +1078,24 @@ cdef class FreeModuleElement(Vector): # abstract base class INPUT: - ``dtype`` -- the `numpy dtype `_ - of the returned array + of the returned array EXAMPLES:: + sage: # needs numpy sage: v = vector([1,2,3]) sage: v.numpy() array([1, 2, 3], dtype=object) sage: v.numpy() * v.numpy() array([1, 4, 9], dtype=object) - sage: vector(QQ, [1, 2, 5/6]).numpy() + sage: vector(QQ, [1, 2, 5/6]).numpy() # needs numpy array([1, 2, 5/6], dtype=object) - By default the ``object`` `dtype `_ is used. + By default, the ``object`` `dtype `_ is used. Alternatively, the desired dtype can be passed in as a parameter:: + sage: # needs numpy sage: v = vector(QQ, [1, 2, 5/6]) sage: v.numpy() array([1, 2, 5/6], dtype=object) @@ -1093,26 +1110,29 @@ cdef class FreeModuleElement(Vector): # abstract base class Passing a dtype of None will let numpy choose a native type, which can be more efficient but may have unintended consequences:: + sage: # needs numpy sage: v.numpy(dtype=None) array([1. , 2. , 0.83333333]) sage: w = vector(ZZ, [0, 1, 2^63 -1]); w (0, 1, 9223372036854775807) - sage: wn = w.numpy(dtype=None); wn + sage: wn = w.numpy(dtype=None); wn # needs numpy array([ 0, 1, 9223372036854775807]...) - sage: wn.dtype + sage: wn.dtype # needs numpy dtype('int64') sage: w.dot_product(w) 85070591730234615847396907784232501250 - sage: wn.dot(wn) # overflow + sage: wn.dot(wn) # overflow # needs numpy 2 Numpy can give rather obscure errors; we wrap these to give a bit of context:: - sage: vector([1, 1/2, QQ['x'].0]).numpy(dtype=float) + sage: vector([1, 1/2, QQ['x'].0]).numpy(dtype=float) # needs numpy Traceback (most recent call last): ... - ValueError: Could not convert vector over Univariate Polynomial Ring in x over Rational Field to numpy array of type <... 'float'>: setting an array element with a sequence. + ValueError: Could not convert vector over Univariate Polynomial Ring in x + over Rational Field to numpy array of type <... 'float'>: + setting an array element with a sequence. """ from numpy import array try: @@ -1127,6 +1147,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector([1,2/3,pi]) sage: v.__hash__() Traceback (most recent call last): @@ -1155,7 +1176,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: vector(vector((1, 6.8))) (1.00000000000000, 6.80000000000000) - sage: vector(vector(SR, (1, sqrt(2)) ) ) + sage: vector(vector(SR, (1, sqrt(2)) ) ) # needs sage.symbolic (1, sqrt(2)) """ if R is None: @@ -1168,7 +1189,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: sage_input(vector(RR, [pi, e, 0.5]), verify=True) + sage: sage_input(vector(RR, [pi, e, 0.5]), verify=True) # needs sage.symbolic # Verified vector(RR, [3.1415926535897931, 2.7182818284590451, 0.5]) sage: sage_input(vector(GF(5), [1, 2, 3, 4, 5]), verify=True) @@ -1186,7 +1207,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: from sage.misc.sage_input import SageInputBuilder sage: vector(ZZ, [42, 389])._sage_input_(SageInputBuilder(), False) {call: {atomic:vector}({atomic:ZZ}, {list: ({atomic:42}, {atomic:389})})} - sage: vector(RDF, {1:pi, 1000:e})._sage_input_(SageInputBuilder(), False) + sage: vector(RDF, {1:pi, 1000:e})._sage_input_(SageInputBuilder(), False) # needs sage.symbolic {call: {atomic:vector}({atomic:RDF}, {dict: {{atomic:1}:{atomic:3.1415926535897931}, {atomic:1000}:{atomic:2.718281828459045...}}})} """ # Not a lot of room for prettiness here. @@ -1375,7 +1396,7 @@ cdef class FreeModuleElement(Vector): # abstract base class then taking a transpose. Notice that supplying a vector to the matrix constructor demonstrates Sage's preference for rows. :: - sage: x = vector(RDF, [sin(i*pi/20) for i in range(10)]) + sage: x = vector(RDF, [sin(i*pi/20) for i in range(10)]) # needs sage.symbolic sage: x.row() == matrix(x) True sage: x.row() == x.column().transpose() @@ -1384,10 +1405,10 @@ cdef class FreeModuleElement(Vector): # abstract base class Sparse or dense implementations are preserved. :: sage: d = vector(RR, [1.0, 2.0, 3.0]) - sage: s = vector(CDF, {2:5.0+6.0*I}) + sage: s = vector(CDF, {2: 5.0+6.0*I}) # needs sage.symbolic sage: dm = d.row() - sage: sm = s.row() - sage: all([d.is_dense(), dm.is_dense(), s.is_sparse(), sm.is_sparse()]) + sage: sm = s.row() # needs sage.symbolic + sage: all([d.is_dense(), dm.is_dense(), s.is_sparse(), sm.is_sparse()]) # needs sage.symbolic True TESTS: @@ -1447,7 +1468,7 @@ cdef class FreeModuleElement(Vector): # abstract base class then taking a transpose. Notice that supplying a vector to the matrix constructor demonstrates Sage's preference for rows. :: - sage: x = vector(RDF, [sin(i*pi/20) for i in range(10)]) + sage: x = vector(RDF, [sin(i*pi/20) for i in range(10)]) # needs sage.libs.pari sage.symbolic sage: x.column() == matrix(x).transpose() True sage: x.column() == x.row().transpose() @@ -1456,10 +1477,10 @@ cdef class FreeModuleElement(Vector): # abstract base class Sparse or dense implementations are preserved. :: sage: d = vector(RR, [1.0, 2.0, 3.0]) - sage: s = vector(CDF, {2:5.0+6.0*I}) + sage: s = vector(CDF, {2: 5.0+6.0*I}) # needs sage.symbolic sage: dm = d.column() - sage: sm = s.column() - sage: all([d.is_dense(), dm.is_dense(), s.is_sparse(), sm.is_sparse()]) + sage: sm = s.column() # needs sage.symbolic + sage: all([d.is_dense(), dm.is_dense(), s.is_sparse(), sm.is_sparse()]) # needs sage.symbolic True TESTS: @@ -1517,6 +1538,7 @@ cdef class FreeModuleElement(Vector): # abstract base class """ EXAMPLES:: + sage: # needs sage.symbolic sage: var('a,b,d,e') (a, b, d, e) sage: v = vector([a, b, d, e]) @@ -1541,7 +1563,7 @@ cdef class FreeModuleElement(Vector): # abstract base class Check for :trac:`29630`:: sage: v = vector(QQ, 4, {0:1}, sparse=True) - sage: v.change_ring(AA).is_sparse() + sage: v.change_ring(AA).is_sparse() # needs sage.rings.number_field True """ if self.base_ring() is R: @@ -1610,17 +1632,17 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: v = vector([1,2/3,pi]) - sage: v.items() + sage: v = vector([1,2/3,pi]) # needs sage.symbolic + sage: v.items() # needs sage.symbolic - sage: list(v.items()) + sage: list(v.items()) # needs sage.symbolic [(0, 1), (1, 2/3), (2, pi)] TESTS: Using iteritems as an alias:: - sage: list(v.iteritems()) + sage: list(v.iteritems()) # needs sage.symbolic [(0, 1), (1, 2/3), (2, pi)] """ cdef dict d = self.dict(copy=False) @@ -1635,7 +1657,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: v = vector([1..5]); abs(v) + sage: v = vector([1..5]); abs(v) # needs sage.symbolic sqrt(55) sage: v = vector(RDF, [1..5]); abs(v) 7.416198487095663 @@ -1648,12 +1670,12 @@ cdef class FreeModuleElement(Vector): # abstract base class INPUT: - - ``p`` - default: 2 - ``p`` can be a real number greater than 1, + - ``p`` - default: 2 -- ``p`` can be a real number greater than 1, infinity (``oo`` or ``Infinity``), or a symbolic expression. - - `p=1`: the taxicab (Manhattan) norm - - `p=2`: the usual Euclidean norm (the default) - - `p=\infty`: the maximum entry (in absolute value) + - `p=1`: the taxicab (Manhattan) norm + - `p=2`: the usual Euclidean norm (the default) + - `p=\infty`: the maximum entry (in absolute value) .. NOTE:: @@ -1662,14 +1684,14 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: sage: v = vector([1,2,-3]) - sage: v.norm(5) + sage: v.norm(5) # needs sage.symbolic 276^(1/5) The default is the usual Euclidean norm. :: - sage: v.norm() + sage: v.norm() # needs sage.symbolic sqrt(14) - sage: v.norm(2) + sage: v.norm(2) # needs sage.symbolic sqrt(14) The infinity norm is the maximum size (in absolute value) @@ -1685,9 +1707,11 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v=vector(RDF,[1,2,3]) sage: v.norm(5) 3.077384885394063 - sage: v.norm(pi/2) #abs tol 1e-15 + + sage: # needs sage.symbolic + sage: v.norm(pi/2) # abs tol 1e-15 4.216595864704748 - sage: _=var('a b c d p'); v=vector([a, b, c, d]) + sage: _ = var('a b c d p'); v = vector([a, b, c, d]) sage: v.norm(p) (abs(a)^p + abs(b)^p + abs(c)^p + abs(d)^p)^(1/p) @@ -1701,6 +1725,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: nrm.parent() Rational Field + sage: # needs sage.symbolic sage: v = vector(QQ, [3, 5]) sage: nrm = v.norm(); nrm sqrt(34) @@ -1725,7 +1750,7 @@ cdef class FreeModuleElement(Vector): # abstract base class Norm works with Python integers (see :trac:`13502`). :: sage: v = vector(QQ, [1,2]) - sage: v.norm(int(2)) + sage: v.norm(int(2)) # needs sage.symbolic sqrt(5) """ abs_self = [abs(x) for x in self] @@ -1741,6 +1766,7 @@ cdef class FreeModuleElement(Vector): # abstract base class """ EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector(SR, [0,0,0,0]) sage: v == 0 True @@ -1766,6 +1792,7 @@ cdef class FreeModuleElement(Vector): # abstract base class Verify that :trac:`33697` is fixed:: + sage: # needs sage.symbolic sage: v = vector(SR, [x]) sage: w = vector(SR, [1]) sage: v == w @@ -1830,7 +1857,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: vector(SR, [1/2,2/5,0]).get(0) + sage: vector(SR, [1/2,2/5,0]).get(0) # needs sage.symbolic 1/2 """ return self.get_unsafe(i) @@ -1893,9 +1920,9 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: v = vector(SR, [1/2,2/5,0]); v + sage: v = vector(SR, [1/2,2/5,0]); v # needs sage.symbolic (1/2, 2/5, 0) - sage: v.set(2, pi); v + sage: v.set(2, pi); v # needs sage.symbolic (1/2, 2/5, pi) """ assert value.parent() is self.coordinate_ring() @@ -1908,7 +1935,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: vector([1,2/3,pi]).__invert__() + sage: vector([1,2/3,pi]).__invert__() # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError @@ -1990,8 +2017,8 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: v = vector([1,2/3,pi]) - sage: v.list_from_positions([0,0,0,2,1]) + sage: v = vector([1, 2/3, pi]) # needs sage.symbolic + sage: v.list_from_positions([0,0,0,2,1]) # needs sage.symbolic [1, 1, 1, pi, 2/3] """ cdef Py_ssize_t i @@ -2105,10 +2132,10 @@ cdef class FreeModuleElement(Vector): # abstract base class :: - sage: x = var('x') - sage: v = vector([x/(2*x)+sqrt(2)+var('theta')^3,x/(2*x)]); v + sage: x = var('x') # needs sage.symbolic + sage: v = vector([x/(2*x)+sqrt(2)+var('theta')^3,x/(2*x)]); v # needs sage.symbolic (theta^3 + sqrt(2) + 1/2, 1/2) - sage: v._repr_() + sage: v._repr_() # needs sage.symbolic '(theta^3 + sqrt(2) + 1/2, 1/2)' """ cdef Py_ssize_t d = self._degree @@ -2282,13 +2309,14 @@ cdef class FreeModuleElement(Vector): # abstract base class The following both plot the given vector:: sage: v = vector(RDF, (1,2)) - sage: A = plot(v) - sage: B = v.plot() - sage: A+B # should just show one vector + sage: A = plot(v) # needs sage.plot + sage: B = v.plot() # needs sage.plot + sage: A + B # should just show one vector # needs sage.plot Graphics object consisting of 2 graphics primitives Examples of the plot types:: + sage: # needs sage.plot sage: A = plot(v, plot_type='arrow') sage: B = plot(v, plot_type='point', color='green', size=20) sage: C = plot(v, plot_type='step') # calls v.plot_step() @@ -2298,68 +2326,69 @@ cdef class FreeModuleElement(Vector): # abstract base class You can use the optional arguments for :meth:`plot_step`:: sage: eps = 0.1 - sage: plot(v, plot_type='step', eps=eps, xmax=5, hue=0) + sage: plot(v, plot_type='step', eps=eps, xmax=5, hue=0) # needs sage.plot Graphics object consisting of 1 graphics primitive Three-dimensional examples:: sage: v = vector(RDF, (1,2,1)) - sage: plot(v) # defaults to an arrow plot + sage: plot(v) # defaults to an arrow plot # needs sage.plot Graphics3d Object :: - sage: plot(v, plot_type='arrow') + sage: plot(v, plot_type='arrow') # needs sage.plot Graphics3d Object :: - sage: from sage.plot.plot3d.shapes2 import frame3d - sage: plot(v, plot_type='point')+frame3d((0,0,0), v.list()) + sage: from sage.plot.plot3d.shapes2 import frame3d # needs sage.plot + sage: plot(v, plot_type='point')+frame3d((0,0,0), v.list()) # needs sage.plot Graphics3d Object :: - sage: plot(v, plot_type='step') # calls v.plot_step() + sage: plot(v, plot_type='step') # calls v.plot_step() # needs sage.plot Graphics object consisting of 1 graphics primitive :: - sage: plot(v, plot_type='step', eps=eps, xmax=5, hue=0) + sage: plot(v, plot_type='step', eps=eps, xmax=5, hue=0) # needs sage.plot Graphics object consisting of 1 graphics primitive With greater than three coordinates, it defaults to a step plot:: sage: v = vector(RDF, (1,2,3,4)) - sage: plot(v) + sage: plot(v) # needs sage.plot Graphics object consisting of 1 graphics primitive One dimensional vectors are plotted along the horizontal axis of the coordinate plane:: - sage: plot(vector([1])) + sage: plot(vector([1])) # needs sage.plot Graphics object consisting of 1 graphics primitive An optional start argument may also be specified by a tuple, list, or vector:: sage: u = vector([1,2]); v = vector([2,5]) - sage: plot(u, start=v) + sage: plot(u, start=v) # needs sage.plot Graphics object consisting of 1 graphics primitive TESTS:: sage: u = vector([1,1]); v = vector([2,2,2]); z=(3,3,3) - sage: plot(u) #test when start=None + sage: plot(u) #test when start=None # needs sage.plot Graphics object consisting of 1 graphics primitive :: + sage: # needs sage.plot sage: plot(u, start=v) #test when coordinate dimension mismatch exists Traceback (most recent call last): ... ValueError: vector coordinates are not of the same dimension - sage: P = plot(v, start=z) #test when start coordinates are passed as a tuple - sage: P = plot(v, start=list(z)) #test when start coordinates are passed as a list + sage: P = plot(v, start=z) # test when start coordinates are passed as a tuple + sage: P = plot(v, start=list(z)) # test when start coordinates are passed as a list """ # Give sensible defaults based on the vector length if plot_type is None: @@ -2430,9 +2459,9 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: eps=0.1 + sage: eps = 0.1 sage: v = vector(RDF, [sin(n*eps) for n in range(100)]) - sage: v.plot_step(eps=eps, xmax=5, hue=0) + sage: v.plot_step(eps=eps, xmax=5, hue=0) # needs sage.plot Graphics object consisting of 1 graphics primitive """ import math @@ -2558,7 +2587,7 @@ cdef class FreeModuleElement(Vector): # abstract base class The dot product of a vector with itself is the 2-norm, squared. :: sage: v = vector(QQ, [3, 4, 7]) - sage: v.dot_product(v) - v.norm()^2 + sage: v.dot_product(v) - v.norm()^2 # needs sage.symbolic 0 TESTS: @@ -2595,7 +2624,11 @@ cdef class FreeModuleElement(Vector): # abstract base class Check for :trac:`33814`:: - sage: for R in [ZZ, QQ, RDF, RR, GF(2), GF(3), GF(4), ZZ['x']]: + sage: rings = [ZZ, QQ, RDF, ZZ['x']] + sage: rings += [RR] # needs sage.rings.real_mpfr + sage: rings += [GF(2), GF(3)] + sage: rings += [GF(4)] # needs sage.rings.finite_rings + sage: for R in rings: ....: _ = (R**0)().dot_product((R**0)()) """ cdef FreeModuleElement r = right @@ -2754,6 +2787,7 @@ cdef class FreeModuleElement(Vector): # abstract base class TESTS:: + sage: # needs sage.rings.finite_rings sage: F = GF(previous_prime(2^32)) sage: v = random_vector(F, 3) sage: w = random_vector(F, 3) @@ -2828,7 +2862,7 @@ cdef class FreeModuleElement(Vector): # abstract base class :: - sage: W = VectorSpace(GF(3),3) + sage: W = VectorSpace(GF(3), 3) sage: w = W([0,1,2]) sage: w.pairwise_product(v) (0, 2, 0) @@ -2845,8 +2879,6 @@ cdef class FreeModuleElement(Vector): # abstract base class TESTS:: - sage: x, y = var('x, y') - :: sage: parent(vector(ZZ,[1,2]).pairwise_product(vector(ZZ,[1,2]))) @@ -2868,42 +2900,56 @@ cdef class FreeModuleElement(Vector): # abstract base class :: sage: parent(vector(QQ,[1,2,3,4]).pairwise_product(vector(ZZ['x']['y'],[1,2,3,4]))) - Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 4 over the integral domain + Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field sage: parent(vector(ZZ['x']['y'],[1,2,3,4]).pairwise_product(vector(QQ,[1,2,3,4]))) - Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 4 over the integral domain + Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field :: sage: parent(vector(QQ['x'],[1,2,3,4]).pairwise_product(vector(ZZ['x']['y'],[1,2,3,4]))) - Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 4 over the integral domain + Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field sage: parent(vector(ZZ['x']['y'],[1,2,3,4]).pairwise_product(vector(QQ['x'],[1,2,3,4]))) - Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 4 over the integral domain + Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field :: sage: parent(vector(QQ['y'],[1,2,3,4]).pairwise_product(vector(ZZ['x']['y'],[1,2,3,4]))) - Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 4 over the integral domain + Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field sage: parent(vector(ZZ['x']['y'],[1,2,3,4]).pairwise_product(vector(QQ['y'],[1,2,3,4]))) - Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field + Ambient free module of rank 4 over the integral domain + Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Rational Field :: sage: parent(vector(ZZ['x'],[1,2,3,4]).pairwise_product(vector(ZZ['y'],[1,2,3,4]))) Traceback (most recent call last): ... - TypeError: no common canonical parent for objects with parents: 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Integer Ring' + TypeError: no common canonical parent for objects with parents: + 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and + 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Integer Ring' sage: parent(vector(ZZ['x'],[1,2,3,4]).pairwise_product(vector(QQ['y'],[1,2,3,4]))) Traceback (most recent call last): ... - TypeError: no common canonical parent for objects with parents: 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field' + TypeError: no common canonical parent for objects with parents: + 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in x over Integer Ring' and + 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field' sage: parent(vector(QQ['x'],[1,2,3,4]).pairwise_product(vector(ZZ['y'],[1,2,3,4]))) Traceback (most recent call last): ... - TypeError: no common canonical parent for objects with parents: 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Integer Ring' + TypeError: no common canonical parent for objects with parents: + 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and + 'Ambient free module of rank 4 over the integral domain Univariate Polynomial Ring in y over Integer Ring' sage: parent(vector(QQ['x'],[1,2,3,4]).pairwise_product(vector(QQ['y'],[1,2,3,4]))) Traceback (most recent call last): ... - TypeError: no common canonical parent for objects with parents: 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field' + TypeError: no common canonical parent for objects with parents: + 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and + 'Ambient free module of rank 4 over the principal ideal domain Univariate Polynomial Ring in y over Rational Field' sage: v = vector({1: 1, 3: 2}) # test sparse vectors sage: w = vector({0: 6, 3: -4}) sage: v.pairwise_product(w) @@ -2926,12 +2972,12 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: R. = QQ[] sage: vector([x, y, 3])._variables() [x, y, z] - sage: vector(SR, [x, y, 3])._variables() + sage: vector(SR, [x, y, 3])._variables() # needs sage.symbolic Traceback (most recent call last): ... ValueError: Unable to determine ordered variable names for Symbolic Ring - sage: v(x, y, z) = (-y, x, 0) - sage: v._variables() + sage: v(x, y, z) = (-y, x, 0) # needs sage.symbolic + sage: v._variables() # needs sage.symbolic [(x, y, z) |--> x, (x, y, z) |--> y, (x, y, z) |--> z] """ R = self._parent.base_ring() @@ -2964,11 +3010,11 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: vector([x*y, y*z, z*x]).div([x, y, w]) y + z - sage: vector(SR, [x*y, y*z, z*x]).div() + sage: vector(SR, [x*y, y*z, z*x]).div() # needs sage.symbolic Traceback (most recent call last): ... ValueError: Unable to determine ordered variable names for Symbolic Ring - sage: vector(SR, [x*y, y*z, z*x]).div([x, y, z]) + sage: vector(SR, [x*y, y*z, z*x]).div([x, y, z]) # needs sage.symbolic x + y + z .. SEEALSO:: @@ -3005,21 +3051,21 @@ cdef class FreeModuleElement(Vector): # abstract base class For rings where the variable order is not well defined, it must be defined explicitly:: - sage: v = vector(SR, [-y, x, 0]) - sage: v.curl() + sage: v = vector(SR, [-y, x, 0]) # needs sage.symbolic + sage: v.curl() # needs sage.symbolic Traceback (most recent call last): ... ValueError: Unable to determine ordered variable names for Symbolic Ring - sage: v.curl([x, y, z]) + sage: v.curl([x, y, z]) # needs sage.symbolic (0, 0, 2) Note that callable vectors have well defined variable orderings:: - sage: v(x, y, z) = (-y, x, 0) - sage: v.curl() + sage: v(x, y, z) = (-y, x, 0) # needs sage.symbolic + sage: v.curl() # needs sage.symbolic (x, y, z) |--> (0, 0, 2) - In two-dimensions, this returns a scalar value:: + In two dimensions, this returns a scalar value:: sage: R. = QQ[] sage: vector([-y, x]).curl() @@ -3101,14 +3147,14 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: sage: v = vector(QQ, [4, 1, 3, 2]) - sage: v.normalized() + sage: v.normalized() # needs sage.symbolic (2/15*sqrt(30), 1/30*sqrt(30), 1/10*sqrt(30), 1/15*sqrt(30)) sage: sum(v.normalized(1)) 1 Note that normalizing the vector may change the base ring:: - sage: v.base_ring() == v.normalized().base_ring() + sage: v.base_ring() == v.normalized().base_ring() # needs sage.symbolic False sage: u = vector(RDF, [-3, 4, 6, 9]) sage: u.base_ring() == u.normalized().base_ring() @@ -3129,10 +3175,10 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: v = vector(CDF, [2.3 - 5.4*I, -1.7 + 3.6*I]) - sage: w = v.conjugate(); w + sage: v = vector(CDF, [2.3 - 5.4*I, -1.7 + 3.6*I]) # needs sage.symbolic + sage: w = v.conjugate(); w # needs sage.symbolic (2.3 + 5.4*I, -1.7 - 3.6*I) - sage: w.parent() + sage: w.parent() # needs sage.symbolic Vector space of dimension 2 over Complex Double Field Even if conjugation seems nonsensical over a certain ring, this @@ -3146,6 +3192,7 @@ cdef class FreeModuleElement(Vector): # abstract base class such as the cyclotomic fields. This example uses such a field containing a primitive 7-th root of unity named ``a``. :: + sage: # needs sage.rings.number_field sage: F. = CyclotomicField(7) sage: v = vector(F, [a^i for i in range(7)]) sage: v @@ -3155,6 +3202,7 @@ cdef class FreeModuleElement(Vector): # abstract base class Sparse vectors are returned as such. :: + sage: # needs sage.symbolic sage: v = vector(CC, {1: 5 - 6*I, 3: -7*I}); v (0.000000000000000, 5.00000000000000 - 6.00000000000000*I, 0.000000000000000, -7.00000000000000*I) sage: v.is_sparse() @@ -3167,17 +3215,17 @@ cdef class FreeModuleElement(Vector): # abstract base class TESTS:: sage: n = 15 - sage: x = vector(CDF, [sin(i*pi/n)+cos(i*pi/n)*I for i in range(n)]) - sage: x + x.conjugate() in RDF^n + sage: x = vector(CDF, [sin(i*pi/n)+cos(i*pi/n)*I for i in range(n)]) # needs sage.symbolic + sage: x + x.conjugate() in RDF^n # needs sage.symbolic True - sage: I*(x - x.conjugate()) in RDF^n + sage: I*(x - x.conjugate()) in RDF^n # needs sage.symbolic True The parent of the conjugate is the same as that of the original vector. We test this by building a specialized vector space with a non-standard inner product, and constructing a test vector in this space. :: - sage: V = VectorSpace(CDF, 2, inner_product_matrix = [[2,1],[1,5]]) + sage: V = VectorSpace(CDF, 2, inner_product_matrix=[[2,1],[1,5]]) sage: v = vector(CDF, [2-3*I, 4+5*I]) sage: w = V(v) sage: w.parent() @@ -3246,11 +3294,11 @@ cdef class FreeModuleElement(Vector): # abstract base class through to subspaces. :: sage: ipm = matrix(ZZ,[[2,0,-1], [0,2,0], [-1,0,6]]) - sage: M = FreeModule(ZZ, 3, inner_product_matrix = ipm) + sage: M = FreeModule(ZZ, 3, inner_product_matrix=ipm) sage: v = M([1,0,0]) sage: v.inner_product(v) 2 - sage: K = M.span_of_basis([[0/2,-1/2,-1/2], [0,1/2,-1/2],[2,0,0]]) + sage: K = M.span_of_basis([[0/2,-1/2,-1/2], [0,1/2,-1/2], [2,0,0]]) sage: (K.0).inner_product(K.0) 2 sage: w = M([1,3,-1]) @@ -3286,7 +3334,7 @@ cdef class FreeModuleElement(Vector): # abstract base class But with an inner product defined, this method will check that the input is a vector or free module element. :: - sage: W = VectorSpace(RDF, 2, inner_product_matrix = matrix(RDF, 2, [1.0,2.0,3.0,4.0])) + sage: W = VectorSpace(RDF, 2, inner_product_matrix=matrix(RDF, 2, [1.0,2.0,3.0,4.0])) sage: v = W([2.0, 4.0]) sage: v.inner_product(5) Traceback (most recent call last): @@ -3403,10 +3451,12 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: w = vector(GF(5), [1,2]) sage: v = vector(GF(7), [1,2,3,4]) - sage: z = w.outer_product(v) + sage: z = w.outer_product(v) # needs sage.rings.finite_rings Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 2 by 1 dense matrices over Finite Field of size 5' and 'Full MatrixSpace of 1 by 4 dense matrices over Finite Field of size 7' + TypeError: unsupported operand parent(s) for *: + 'Full MatrixSpace of 2 by 1 dense matrices over Finite Field of size 5' and + 'Full MatrixSpace of 1 by 4 dense matrices over Finite Field of size 7' And some inputs don't make any sense at all. :: @@ -3414,7 +3464,8 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: z=w.outer_product(6) Traceback (most recent call last): ... - TypeError: right operand in an outer product must be a vector, not an element of Integer Ring + TypeError: right operand in an outer product must be a vector, + not an element of Integer Ring """ if not isinstance(right, FreeModuleElement): raise TypeError('right operand in an outer product must be a vector, not an element of %s' % right.parent()) @@ -3455,6 +3506,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector(CDF, [2+3*I, 5-4*I]) sage: w = vector(CDF, [6-4*I, 2+3*I]) sage: v.hermitian_inner_product(w) @@ -3465,6 +3517,7 @@ cdef class FreeModuleElement(Vector): # abstract base class the base rings have a conjugate method, then the Hermitian inner product will be available. :: + sage: # needs sage.rings.number_field sage: Q. = QuadraticField(-7) sage: a^2 -7 @@ -3478,6 +3531,7 @@ cdef class FreeModuleElement(Vector): # abstract base class in each argument (with conjugation on the first scalar), and anti-commutative. :: + sage: # needs sage.symbolic sage: alpha = CDF(5.0 + 3.0*I) sage: u = vector(CDF, [2+4*I, -3+5*I, 2-7*I]) sage: v = vector(CDF, [-1+3*I, 5+4*I, 9-2*I]) @@ -3517,15 +3571,15 @@ cdef class FreeModuleElement(Vector): # abstract base class def is_dense(self): """ - Return True if this is a dense vector, which is just a + Return ``True`` if this is a dense vector, which is just a statement about the data structure, not the number of nonzero entries. EXAMPLES:: - sage: vector([1/2,2/5,0]).is_dense() + sage: vector([1/2, 2/5, 0]).is_dense() True - sage: vector([1/2,2/5,0],sparse=True).is_dense() + sage: vector([1/2, 2/5, 0], sparse=True).is_dense() False """ return self.is_dense_c() @@ -3535,15 +3589,15 @@ cdef class FreeModuleElement(Vector): # abstract base class def is_sparse(self): """ - Return True if this is a sparse vector, which is just a + Return ``True`` if this is a sparse vector, which is just a statement about the data structure, not the number of nonzero entries. EXAMPLES:: - sage: vector([1/2,2/5,0]).is_sparse() + sage: vector([1/2, 2/5, 0]).is_sparse() False - sage: vector([1/2,2/5,0],sparse=True).is_sparse() + sage: vector([1/2, 2/5, 0], sparse=True).is_sparse() True """ return self.is_sparse_c() @@ -3553,11 +3607,11 @@ cdef class FreeModuleElement(Vector): # abstract base class def is_vector(self): """ - Return True, since this is a vector. + Return ``True``, since this is a vector. EXAMPLES:: - sage: vector([1/2,2/5,0]).is_vector() + sage: vector([1/2, 2/5, 0]).is_vector() True """ return True @@ -3568,17 +3622,17 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: vector(QQ, [1, 2, 3])._macaulay2_() # optional - macaulay2 + sage: vector(QQ, [1, 2, 3])._macaulay2_() # optional - macaulay2 | 1 | | 2 | | 3 | - sage: _.ring() # optional - macaulay2 + sage: _.ring() # optional - macaulay2 QQ :: sage: R. = QQ[] - sage: macaulay2(vector(R, [1, x+y])) # optional - macaulay2 + sage: macaulay2(vector(R, [1, x+y])) # optional - macaulay2 | 1 | | x+y | @@ -3603,9 +3657,10 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: + sage: # optional - mathematica, needs sage.symbolic sage: vector((1,2,3), QQ)._mathematica_init_() '{1/1, 2/1, 3/1}' - sage: mathematica(vector((1,2,3), QQ)) # optional - mathematica + sage: mathematica(vector((1,2,3), QQ)) {1, 2, 3} sage: a = vector(SR, 5, [1, x, x^2, sin(x), pi]); a (1, x, x^2, sin(x), pi) @@ -3627,16 +3682,16 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v = vector([1, 2, 3]); v (1, 2, 3) - sage: sv = v._sympy_(); sv + sage: sv = v._sympy_(); sv # needs sympy Matrix([ [1], [2], [3]]) - sage: type(sv) + sage: type(sv) # needs sympy sage: w = vector({1: 1, 5: -1}, sparse=True) - sage: sw = w._sympy_(); sw + sage: sw = w._sympy_(); sw # needs sympy Matrix([ [ 0], [ 1], @@ -3644,26 +3699,26 @@ cdef class FreeModuleElement(Vector): # abstract base class [ 0], [ 0], [-1]]) - sage: type(sw) + sage: type(sw) # needs sympy If ``self`` was immutable, then converting the result to Sage gives back ``self``:: sage: immv = vector([1, 2, 3], immutable=True) - sage: immv._sympy_()._sage_() is immv + sage: immv._sympy_()._sage_() is immv # needs sympy True If ``self`` was mutable, then converting back to Sage creates a new matrix (column vector):: - sage: sv._sage_() + sage: sv._sage_() # needs sympy [1] [2] [3] - sage: sv._sage_() is v + sage: sv._sage_() is v # needs sympy False - sage: sv._sage_() == v + sage: sv._sage_() == v # needs sympy False """ from sage.interfaces.sympy import sympy_init @@ -3816,17 +3871,17 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: m = vector([1,x,sin(x+1)]) - sage: m.apply_map(lambda x: x^2) + sage: m = vector([1,x,sin(x+1)]) # needs sage.symbolic + sage: m.apply_map(lambda x: x^2) # needs sage.symbolic (1, x^2, sin(x + 1)^2) - sage: m.apply_map(sin) + sage: m.apply_map(sin) # needs sage.symbolic (sin(1), sin(x), sin(sin(x + 1))) :: sage: m = vector(ZZ, 9, range(9)) - sage: k. = GF(9) - sage: m.apply_map(k) + sage: k. = GF(9) # needs sage.rings.finite_rings + sage: m.apply_map(k) # needs sage.rings.finite_rings (0, 1, 2, 0, 1, 2, 0, 1, 2) In this example, we explicitly specify the codomain. @@ -3835,9 +3890,9 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: s = GF(3) sage: f = lambda x: s(x) - sage: n = m.apply_map(f, k); n + sage: n = m.apply_map(f, k); n # needs sage.rings.finite_rings (0, 1, 2, 0, 1, 2, 0, 1, 2) - sage: n.parent() + sage: n.parent() # needs sage.rings.finite_rings Vector space of dimension 9 over Finite Field in a of size 3^2 If your map sends 0 to a non-zero value, then your resulting @@ -3872,8 +3927,8 @@ cdef class FreeModuleElement(Vector): # abstract base class TESTS:: - sage: m = vector(SR,[]) - sage: m.apply_map(lambda x: x*x) == m + sage: m = vector(SR,[]) # needs sage.symbolic + sage: m.apply_map(lambda x: x*x) == m # needs sage.symbolic True Check that we don't unnecessarily apply phi to 0 in the sparse case:: @@ -3893,8 +3948,9 @@ cdef class FreeModuleElement(Vector): # abstract base class Check that the bug in :trac:`14558` has been fixed:: + sage: # needs sage.rings.finite_rings sage: F. = GF(9) - sage: v = vector([a, 0,0,0], sparse=True) + sage: v = vector([a, 0, 0, 0], sparse=True) sage: f = F.hom([a**3]) sage: v.apply_map(f) (2*a + 1, 0, 0, 0) @@ -3950,6 +4006,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector([1,x,x^2]) sage: v._derivative(x) (0, 1, 2*x) @@ -3965,7 +4022,8 @@ cdef class FreeModuleElement(Vector): # abstract base class symbolic expressions, then calculate the matrix derivative (i.e., the Jacobian matrix):: - sage: T(r,theta)=[r*cos(theta),r*sin(theta)] + sage: # needs sage.symbolic + sage: T(r,theta) = [r*cos(theta), r*sin(theta)] sage: T (r, theta) |--> (r*cos(theta), r*sin(theta)) sage: T.diff() # matrix derivative @@ -3998,6 +4056,7 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector([1,x,x^2]) sage: v.derivative(x) (0, 1, 2*x) @@ -4024,13 +4083,14 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: t=var('t') - sage: r=vector([t,t^2,sin(t)]) + sage: # needs sage.symbolic + sage: t = var('t') + sage: r = vector([t,t^2,sin(t)]) sage: r.integral(t) (1/2*t^2, 1/3*t^3, -cos(t)) - sage: integrate(r,t) + sage: integrate(r, t) (1/2*t^2, 1/3*t^3, -cos(t)) - sage: r.integrate(t,0,1) + sage: r.integrate(t, 0, 1) (1/2, 1/3, -cos(1) + 1) """ @@ -4050,19 +4110,25 @@ cdef class FreeModuleElement(Vector): # abstract base class EXAMPLES:: - sage: t=var('t') - sage: r=vector([t,t^2,sin(t)]) - sage: vec,answers=r.nintegral(t,0,1) - sage: vec # abs tol 1e-15 + sage: # needs sage.symbolic + sage: t = var('t') + sage: r = vector([t,t^2,sin(t)]) + sage: vec, answers = r.nintegral(t,0,1) + sage: vec # abs tol 1e-15 (0.5, 0.3333333333333334, 0.4596976941318602) sage: type(vec) sage: answers - [(0.5, 5.55111512312578...e-15, 21, 0), (0.3333333333333..., 3.70074341541719...e-15, 21, 0), (0.45969769413186..., 5.10366964392284...e-15, 21, 0)] + [(0.5, 5.55111512312578...e-15, 21, 0), + (0.3333333333333..., 3.70074341541719...e-15, 21, 0), + (0.45969769413186..., 5.10366964392284...e-15, 21, 0)] - sage: r=vector([t,0,1], sparse=True) - sage: r.nintegral(t,0,1) - ((0.5, 0.0, 1.0), {0: (0.5, 5.55111512312578...e-15, 21, 0), 2: (1.0, 1.11022302462515...e-14, 21, 0)}) + sage: # needs sage.symbolic + sage: r = vector([t,0,1], sparse=True) + sage: r.nintegral(t, 0, 1) + ((0.5, 0.0, 1.0), + {0: (0.5, 5.55111512312578...e-15, 21, 0), + 2: (1.0, 1.11022302462515...e-14, 21, 0)}) """ # If Cython supported lambda functions, we would just do @@ -4150,13 +4216,13 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): :: - sage: v = vector([1,2/3,pi]) + sage: v = vector([1,2/3,pi]) # needs sage.symbolic sage: v == v True :: - sage: v = vector(RR, [1,2/3,pi]) + sage: v = vector(RR, [1,2/3,pi]) # needs sage.symbolic sage: v.set_immutable() sage: isinstance(hash(v), int) True @@ -4191,6 +4257,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): EXAMPLES:: + sage: # needs sage.symbolic sage: v = vector([-1,0,3,pi]) sage: type(v) @@ -4199,11 +4266,11 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: v.__copy__() is v False - sage: copy(v) + sage: copy(v) # needs sage.symbolic (-1, 0, 3, pi) - sage: copy(v) == v + sage: copy(v) == v # needs sage.symbolic True - sage: copy(v) is v + sage: copy(v) is v # needs sage.symbolic False """ return self._new_c(list(self._entries)) @@ -4212,17 +4279,17 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): """ EXAMPLES:: - sage: type(vector(RR, [-1,0,2/3,pi,oo])) + sage: type(vector(RR, [-1,0,2/3,pi,oo])) # needs sage.symbolic We can initialize with lists, tuples and derived types:: sage: from sage.modules.free_module_element import FreeModuleElement_generic_dense - sage: FreeModuleElement_generic_dense(RR^5, [-1,0,2/3,pi,oo]) + sage: FreeModuleElement_generic_dense(RR^5, [-1,0,2/3,pi,oo]) # needs sage.symbolic (-1.00000000000000, 0.000000000000000, 0.666666666666667, 3.14159265358979, +infinity) - sage: FreeModuleElement_generic_dense(RR^5, (-1,0,2/3,pi,oo)) + sage: FreeModuleElement_generic_dense(RR^5, (-1,0,2/3,pi,oo)) # needs sage.symbolic (-1.00000000000000, 0.000000000000000, 0.666666666666667, 3.14159265358979, +infinity) - sage: FreeModuleElement_generic_dense(RR^5, Sequence([-1,0,2/3,pi,oo])) + sage: FreeModuleElement_generic_dense(RR^5, Sequence([-1,0,2/3,pi,oo])) # needs sage.symbolic (-1.00000000000000, 0.000000000000000, 0.666666666666667, 3.14159265358979, +infinity) sage: FreeModuleElement_generic_dense(RR^0, 0) () @@ -4231,11 +4298,12 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): Disabling coercion can lead to illegal objects:: - sage: FreeModuleElement_generic_dense(RR^5, [-1,0,2/3,pi,oo], coerce=False) + sage: FreeModuleElement_generic_dense(RR^5, [-1,0,2/3,pi,oo], coerce=False) # needs sage.symbolic (-1, 0, 2/3, pi, +Infinity) We test the ``copy`` flag:: + sage: # needs sage.symbolic sage: from sage.modules.free_module_element import FreeModuleElement_generic_dense sage: L = [RR(x) for x in (-1,0,2/3,pi,oo)] sage: FreeModuleElement_generic_dense(RR^5, tuple(L), coerce=False, copy=False) @@ -4247,6 +4315,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): :: + sage: # needs sage.symbolic sage: L = [RR(x) for x in (-1,0,2/3,pi,oo)] sage: v = FreeModuleElement_generic_dense(RR^5, L, coerce=False, copy=True) sage: L[4] = 42.0 @@ -4308,8 +4377,8 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): EXAMPLES:: - sage: v = vector([1,2/3,pi]); w = vector([-2/3,pi^2,1]) - sage: v._add_(w) + sage: v = vector([1,2/3,pi]); w = vector([-2/3,pi^2,1]) # needs sage.symbolic + sage: v._add_(w) # needs sage.symbolic (1/3, pi^2 + 2/3, pi + 1) """ cdef list a = left._entries @@ -4355,10 +4424,10 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([-1,0,3,pi]) - sage: v._lmul_(2/3) + sage: v = vector([-1,0,3,pi]) # needs sage.symbolic + sage: v._lmul_(2/3) # needs sage.symbolic (-2/3, 0, 2, 2/3*pi) - sage: v * (2/3) + sage: v * (2/3) # needs sage.symbolic (-2/3, 0, 2, 2/3*pi) """ if right._parent is self._parent._base: @@ -4391,9 +4460,10 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([-1,0,3,pi]) - sage: v.__reduce__() - (, (Vector space of dimension 4 over Symbolic Ring, [-1, 0, 3, pi], 4, True)) + sage: v = vector([-1,0,3,pi]) # needs sage.symbolic + sage: v.__reduce__() # needs sage.symbolic + (, + (Vector space of dimension 4 over Symbolic Ring, [-1, 0, 3, pi], 4, True)) """ return (make_FreeModuleElement_generic_dense_v1, (self._parent, self._entries, self._degree, not self._is_immutable)) @@ -4404,8 +4474,8 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): """ EXAMPLES:: - sage: v = vector(RR, [-1,0,2/3,pi]) - sage: v.get(3) + sage: v = vector(RR, [-1,0,2/3,pi]) # needs sage.symbolic + sage: v.get(3) # needs sage.symbolic 3.14159265358979 :: @@ -4441,9 +4511,9 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): """ EXAMPLES:: - sage: v = vector(RR, [-1,0,2/3,pi]) - sage: v.set(3, RR(1)) - sage: v + sage: v = vector(RR, [-1, 0, 2/3, pi]) # needs sage.symbolic + sage: v.set(3, RR(1)) # needs sage.symbolic + sage: v # needs sage.symbolic (-1.00000000000000, 0.000000000000000, 0.666666666666667, 1.00000000000000) """ self._entries[i] = value @@ -4484,6 +4554,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): EXAMPLES:: + sage: # needs sage.symbolic sage: x, y = var('x,y') sage: f = x^2 + y^2 sage: g = f.gradient() @@ -4508,9 +4579,10 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): EXAMPLES:: - sage: x,y=var('x,y') - sage: v=vector([x,y,x*sin(y)]) - sage: w=v.function([x,y]); w + sage: # needs sage.symbolic + sage: x, y = var('x,y') + sage: v = vector([x, y, x*sin(y)]) + sage: w = v.function([x,y]); w (x, y) |--> (x, y, x*sin(y)) sage: w.coordinate_ring() Callable function ring with arguments (x, y) @@ -4523,9 +4595,10 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): :: - sage: x,y=var('x,y') - sage: v=vector([x,y,x*sin(y)]) - sage: w=v.function([x]); w + sage: # needs sage.symbolic + sage: x,y = var('x,y') + sage: v = vector([x, y, x*sin(y)]) + sage: w = v.function([x]); w x |--> (x, y, x*sin(y)) sage: w.coordinate_ring() Callable function ring with argument x @@ -4581,9 +4654,9 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): TESTS:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v.set_immutable() - sage: isinstance(hash(v), int) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v.set_immutable() # needs sage.symbolic + sage: isinstance(hash(v), int) # needs sage.symbolic True Pickling works:: @@ -4633,8 +4706,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v.__copy__() + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v.__copy__() # needs sage.symbolic (1, 2/3, pi) """ return self._new_c(dict(self._entries)) @@ -4653,6 +4726,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): sage: from sage.modules.free_module_element import FreeModuleElement_generic_sparse sage: def S(R,n): ....: return FreeModule(R, n, sparse=True) + + sage: # needs sage.symbolic sage: FreeModuleElement_generic_sparse(S(RR,5), {0:-1, 2:2/3, 3:pi, 4:oo}) (-1.00000000000000, 0.000000000000000, 0.666666666666667, 3.14159265358979, +infinity) sage: FreeModuleElement_generic_sparse(S(RR,5), [-1,0,2/3,pi,oo]) @@ -4661,8 +4736,10 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): (-1.00000000000000, 0.000000000000000, 0.666666666666667, 3.14159265358979, +infinity) sage: FreeModuleElement_generic_sparse(S(RR,5), Sequence([-1,0,2/3,pi,oo])) (-1.00000000000000, 0.000000000000000, 0.666666666666667, 3.14159265358979, +infinity) + sage: FreeModuleElement_generic_sparse(S(RR,0), 0) () + sage: from collections import defaultdict sage: D = defaultdict(RR) sage: D[0] = -1 @@ -4698,13 +4775,14 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): Test that :trac:`17101` is fixed:: + sage: # needs sage.rings.real_interval_field sage: v = vector([RIF(-1, 1)], sparse=True) sage: v.is_zero() False We correctly initialize values which become 0 only after coercion:: - sage: v = FreeModuleElement_generic_sparse(S(GF(3),6), [1,2,3,4,5,6]) + sage: v = FreeModuleElement_generic_sparse(S(GF(3), 6), [1,2,3,4,5,6]) sage: v.nonzero_positions() [0, 1, 3, 4] """ @@ -4757,8 +4835,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v._add_(v) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v._add_(v) # needs sage.symbolic (2, 4/3, 2*pi) """ cdef dict v = dict((right)._entries) @@ -4777,8 +4855,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v._sub_(v) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v._sub_(v) # needs sage.symbolic (0, 0, 0) """ cdef dict v = dict(left._entries) # dict to make a copy @@ -4797,8 +4875,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v._lmul_(SR(3)) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v._lmul_(SR(3)) # needs sage.symbolic (3, 2, 3*pi) """ cdef dict v = {} @@ -4813,8 +4891,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v._rmul_(SR(3)) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v._rmul_(SR(3)) # needs sage.symbolic (3, 2, 3*pi) """ cdef dict v = {} @@ -4881,8 +4959,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True); w = vector([-2/3,pi^2,1],sparse=True) - sage: v._pairwise_product_(w) + sage: v = vector([1,2/3,pi], sparse=True); w = vector([-2/3,pi^2,1],sparse=True) # needs sage.symbolic + sage: v._pairwise_product_(w) # needs sage.symbolic (-2/3, 2/3*pi^2, pi) """ # Component wise vector * vector multiplication. @@ -4906,14 +4984,14 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): TESTS:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: w = vector([1,2/3,pi], sparse=True) - sage: w == v + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: w = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: w == v # needs sage.symbolic True Check that the bug in :trac:`13929` has been fixed:: - sage: V = FreeModule( GF(3), 2, sparse=True) + sage: V = FreeModule(GF(3), 2, sparse=True) sage: a = V([0,1]) sage: b = V([1,0]) sage: a < b @@ -4930,17 +5008,17 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: next(v.items()) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: next(v.items()) # needs sage.symbolic (0, 1) - sage: list(v.items()) + sage: list(v.items()) # needs sage.symbolic [(0, 1), (1, 2/3), (2, pi)] TESTS: Using iteritems as an alias:: - sage: list(v.iteritems()) + sage: list(v.iteritems()) # needs sage.symbolic [(0, 1), (1, 2/3), (2, pi)] """ return iter(self._entries.iteritems()) @@ -4951,9 +5029,10 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([1,2/3,pi], sparse=True) - sage: v.__reduce__() - (, (Sparse vector space of dimension 3 over Symbolic Ring, {0: 1, 1: 2/3, 2: pi}, 3, True)) + sage: v = vector([1,2/3,pi], sparse=True) # needs sage.symbolic + sage: v.__reduce__() # needs sage.symbolic + (, + (Sparse vector space of dimension 3 over Symbolic Ring, {0: 1, 1: 2/3, 2: pi}, 3, True)) """ return (make_FreeModuleElement_generic_sparse_v1, (self._parent, self._entries, self._degree, not self._is_immutable)) @@ -5029,15 +5108,15 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ EXAMPLES:: - sage: v = vector([-1,0,2/3,pi], sparse=True) - sage: v.get(1) + sage: v = vector([-1,0,2/3,pi], sparse=True) # needs sage.symbolic + sage: v.get(1) # needs sage.symbolic 0 - sage: v.get(2) + sage: v.get(2) # needs sage.symbolic 2/3 For this class, 0 is returned if the access is out of bounds:: - sage: v.get(10) + sage: v.get(10) # needs sage.symbolic 0 """ try: @@ -5058,13 +5137,14 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): (4, 5, 6) sage: parent(w[39893]) Finite Field of size 17 - sage: w[39893] = sqrt(2) + sage: w[39893] = sqrt(2) # needs sage.rings.finite_rings sage.symbolic Traceback (most recent call last): ... TypeError: self must be a numeric expression :: + sage: # needs sage.symbolic sage: v = vector([1,2/3,pi], sparse=True) sage: v.set(1, pi^3) sage: v @@ -5075,12 +5155,13 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): This assignment is illegal:: - sage: v.set(10, pi) + sage: v.set(10, pi) # needs sage.symbolic This lack of bounds checking causes trouble later:: - sage: v - ) failed: IndexError: list assignment index out of range> + sage: v # needs sage.symbolic + ) failed: + IndexError: list assignment index out of range> """ if value: self._entries[i] = value diff --git a/src/sage/modules/free_module_homspace.py b/src/sage/modules/free_module_homspace.py index f019bee9ba8..79c2b226436 100644 --- a/src/sage/modules/free_module_homspace.py +++ b/src/sage/modules/free_module_homspace.py @@ -54,7 +54,7 @@ See :trac:`13321`:: - sage: (GF(7)^2).hom([[20,0],[0,21]],ZZ^2) + sage: (GF(7)^2).hom([[20, 0], [0, 21]], ZZ^2) Traceback (most recent call last): ... TypeError: nontrivial morphisms require a coercion map from the base ring diff --git a/src/sage/modules/free_module_integer.py b/src/sage/modules/free_module_integer.py index 2e9db90bbe6..c16e747a53f 100644 --- a/src/sage/modules/free_module_integer.py +++ b/src/sage/modules/free_module_integer.py @@ -38,7 +38,11 @@ from sage.misc.cachefunc import cached_method from sage.modules.free_module import FreeModule_submodule_with_basis_pid, FreeModule_ambient_pid from sage.modules.free_module_element import vector -from sage.rings.number_field.number_field_element import OrderElement_absolute + +try: + from sage.rings.number_field.number_field_element import OrderElement_absolute +except ImportError: + OrderElement_absolute = () def IntegerLattice(basis, lll_reduce=True): @@ -107,9 +111,11 @@ def IntegerLattice(basis, lll_reduce=True): We construct an ideal lattice from an element of an absolute order:: + sage: # needs sage.rings.number_field sage: K. = CyclotomicField(17) sage: O = K.ring_of_integers() - sage: f = O(-a^15 + a^13 + 4*a^12 - 12*a^11 - 256*a^10 + a^9 - a^7 - 4*a^6 + a^5 + 210*a^4 + 2*a^3 - 2*a^2 + 2*a - 2) + sage: f = O(-a^15 + a^13 + 4*a^12 - 12*a^11 - 256*a^10 + a^9 - a^7 + ....: - 4*a^6 + a^5 + 210*a^4 + 2*a^3 - 2*a^2 + 2*a - 2) sage: from sage.modules.free_module_integer import IntegerLattice sage: IntegerLattice(f) Free module of degree 16 and rank 16 over Integer Ring @@ -151,6 +157,7 @@ def IntegerLattice(basis, lll_reduce=True): Sage also interfaces with fpylll's lattice generator:: + sage: # needs fpylll sage: from sage.modules.free_module_integer import IntegerLattice sage: from fpylll import IntegerMatrix sage: A = IntegerMatrix.random(8, "simdioph", bits=20, bits2=10) @@ -197,7 +204,8 @@ class FreeModule_submodule_with_basis_integer(FreeModule_submodule_with_basis_pi EXAMPLES:: sage: from sage.modules.free_module_integer import IntegerLattice - sage: L = IntegerLattice(sage.crypto.gen_lattice(type='modular', m=10, seed=1337, dual=True)); L + sage: L = IntegerLattice(sage.crypto.gen_lattice(type='modular', m=10, + ....: seed=1337, dual=True)); L Free module of degree 10 and rank 10 over Integer Ring User basis matrix: [-1 1 2 -2 0 1 0 -1 2 1] @@ -259,11 +267,12 @@ def __init__(self, ambient, basis, check=True, echelonize=False, sage: M.row_space() == L.matrix().row_space() True + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^8 + 1) # optional - sage.rings.number_field - sage: O = K.ring_of_integers() # optional - sage.rings.number_field - sage: f = O(a^7 - a^6 + 4*a^5 - a^4 + a^3 + 1) # optional - sage.rings.number_field - sage: IntegerLattice(f) # optional - sage.rings.number_field + sage: K. = NumberField(x^8 + 1) + sage: O = K.ring_of_integers() + sage: f = O(a^7 - a^6 + 4*a^5 - a^4 + a^3 + 1) + sage: IntegerLattice(f) Free module of degree 8 and rank 8 over Integer Ring User basis matrix: [ 0 1 0 1 0 3 3 0] @@ -365,10 +374,10 @@ def LLL(self, *args, **kwds): ... sage: L.reduced_basis == A True - sage: old = L.reduced_basis[0].norm().n() + sage: old = L.reduced_basis[0].norm().n() # needs sage.symbolic sage: _ = L.LLL() - sage: new = L.reduced_basis[0].norm().n() - sage: new <= old + sage: new = L.reduced_basis[0].norm().n() # needs sage.symbolic + sage: new <= old # needs sage.symbolic True """ basis = self.reduced_basis @@ -398,21 +407,18 @@ def BKZ(self, *args, **kwds): EXAMPLES:: + sage: # needs sage.libs.flint (o/w timeout) sage: from sage.modules.free_module_integer import IntegerLattice sage: A = sage.crypto.gen_lattice(type='random', n=1, m=60, q=2^60, seed=42) sage: L = IntegerLattice(A, lll_reduce=False) sage: min(v.norm().n() for v in L.reduced_basis) 4.17330740711759e15 - sage: L.LLL() 60 x 60 dense matrix over Integer Ring (use the '.str()' method to see the entries) - sage: min(v.norm().n() for v in L.reduced_basis) 5.19615242270663 - sage: L.BKZ(block_size=10) 60 x 60 dense matrix over Integer Ring (use the '.str()' method to see the entries) - sage: min(v.norm().n() for v in L.reduced_basis) 4.12310562561766 @@ -558,21 +564,21 @@ def shortest_vector(self, update_reduced_basis=True, algorithm="fplll", *args, * sage: from sage.modules.free_module_integer import IntegerLattice sage: A = sage.crypto.gen_lattice(type='random', n=1, m=30, q=2^40, seed=42) sage: L = IntegerLattice(A, lll_reduce=False) - sage: min(v.norm().n() for v in L.reduced_basis) + sage: min(v.norm().n() for v in L.reduced_basis) # needs sage.symbolic 6.03890756700000e10 - sage: L.shortest_vector().norm().n() + sage: L.shortest_vector().norm().n() # needs sage.symbolic 3.74165738677394 sage: L = IntegerLattice(A, lll_reduce=False) - sage: min(v.norm().n() for v in L.reduced_basis) + sage: min(v.norm().n() for v in L.reduced_basis) # needs sage.symbolic 6.03890756700000e10 - sage: L.shortest_vector(algorithm="pari").norm().n() + sage: L.shortest_vector(algorithm="pari").norm().n() # needs sage.symbolic 3.74165738677394 sage: L = IntegerLattice(A, lll_reduce=True) - sage: L.shortest_vector(algorithm="pari").norm().n() + sage: L.shortest_vector(algorithm="pari").norm().n() # needs sage.symbolic 3.74165738677394 """ if algorithm == "pari": @@ -649,7 +655,10 @@ def voronoi_cell(self, radius=None): sage: L = IntegerLattice([[1, 0], [0, 1]]) sage: V = L.voronoi_cell() sage: V.Vrepresentation() - (A vertex at (1/2, -1/2), A vertex at (1/2, 1/2), A vertex at (-1/2, 1/2), A vertex at (-1/2, -1/2)) + (A vertex at (1/2, -1/2), + A vertex at (1/2, 1/2), + A vertex at (-1/2, 1/2), + A vertex at (-1/2, -1/2)) The volume of the Voronoi cell is the square root of the discriminant of the lattice:: @@ -661,8 +670,8 @@ def voronoi_cell(self, radius=None): [ 1 -1 2 1] [ -6 0 3 3] [ -6 -24 -6 -5] - sage: V = L.voronoi_cell() # long time - sage: V.volume() # long time + sage: V = L.voronoi_cell() # long time + sage: V.volume() # long time 678 sage: sqrt(L.discriminant()) 678 @@ -672,7 +681,10 @@ def voronoi_cell(self, radius=None): sage: L = IntegerLattice([[2, 0, 0], [0, 2, 0]]) sage: V = L.voronoi_cell() sage: V.Hrepresentation() - (An inequality (-1, 0, 0) x + 1 >= 0, An inequality (0, -1, 0) x + 1 >= 0, An inequality (1, 0, 0) x + 1 >= 0, An inequality (0, 1, 0) x + 1 >= 0) + (An inequality (-1, 0, 0) x + 1 >= 0, + An inequality (0, -1, 0) x + 1 >= 0, + An inequality (1, 0, 0) x + 1 >= 0, + An inequality (0, 1, 0) x + 1 >= 0) ALGORITHM: @@ -777,7 +789,7 @@ def projection(M, v): def CVPP_2V(t, V, voronoi_cell): t_new = t while not voronoi_cell.contains(t_new.list()): - v = max(V, key=lambda v: t_new * v / v.norm() ** 2) + v = max(V, key=lambda v: t_new * v / v.dot_product(v)) t_new = t_new - v return t - t_new diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index f7508ebeb97..cdc933f23d0 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -9,12 +9,12 @@ TESTS:: - sage: V = ZZ^2; f = V.hom([V.1,-2*V.0]) + sage: V = ZZ^2; f = V.hom([V.1, -2*V.0]) sage: loads(dumps(f)) Free module morphism defined by the matrix [ 0 1] [-2 0] - Domain: Ambient free module of rank 2 over the principal ideal domain ... + Domain: Ambient free module of rank 2 over the principal ideal domain ... Codomain: Ambient free module of rank 2 over the principal ideal domain ... sage: loads(dumps(f)) == f True @@ -53,7 +53,7 @@ def is_FreeModuleMorphism(x): """ EXAMPLES:: - sage: V = ZZ^2; f = V.hom([V.1,-2*V.0]) + sage: V = ZZ^2; f = V.hom([V.1, -2*V.0]) sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(f) True sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(0) @@ -158,7 +158,7 @@ def _repr_(self): sage: phi Vector space morphism represented by the matrix: 40 x 40 dense matrix over Rational Field - Domain: Vector space of dimension 40 over Rational Field + Domain: Vector space of dimension 40 over Rational Field Codomain: Vector space of dimension 40 over Rational Field The representation displays which side of the vectors the matrix is acting:: @@ -169,14 +169,14 @@ def _repr_(self): [0 1 0] [0 0 1] [1 0 0] - Domain: Ambient free module of rank 3 over the principal ideal domain Integer Ring + Domain: Ambient free module of rank 3 over the principal ideal domain Integer Ring Codomain: Ambient free module of rank 3 over the principal ideal domain Integer Ring sage: h2 = V.hom([V.1, V.2, V.0], side="right"); h2 Free module morphism defined as left-multiplication by the matrix [0 0 1] [1 0 0] [0 1 0] - Domain: Ambient free module of rank 3 over the principal ideal domain Integer Ring + Domain: Ambient free module of rank 3 over the principal ideal domain Integer Ring Codomain: Ambient free module of rank 3 over the principal ideal domain Integer Ring """ r = "Free module morphism defined {}by the matrix\n{!r}\nDomain: {}\nCodomain: {}" @@ -187,13 +187,15 @@ def _repr_(self): def change_ring(self, R): """ - Change the ring over which this morphism is defined. This changes the ring of the - domain, codomain, and underlying matrix. + Change the ring over which this morphism is defined. + + This changes the ring of the domain, codomain, and underlying matrix. EXAMPLES:: - sage: V0 = span([[0,0,1],[0,2,0]],ZZ); V1 = span([[1/2,0],[0,2]],ZZ); W = span([[1,0],[0,6]],ZZ) - sage: h = V0.hom([-3*V1.0-3*V1.1, -3*V1.0-3*V1.1]) + sage: V0 = span([[0,0,1],[0,2,0]], ZZ); V1 = span([[1/2,0],[0,2]], ZZ) + sage: W = span([[1,0],[0,6]], ZZ) + sage: h = V0.hom([-3*V1.0 - 3*V1.1, -3*V1.0 - 3*V1.1]) sage: h.base_ring() Integer Ring sage: h @@ -206,26 +208,26 @@ def change_ring(self, R): Vector space morphism represented by the matrix: [-3 -3] [-3 -3] - Domain: Vector space of degree 3 and dimension 2 over Rational Field - Basis matrix: - [0 1 0] - [0 0 1] + Domain: Vector space of degree 3 and dimension 2 over Rational Field + Basis matrix: + [0 1 0] + [0 0 1] Codomain: Vector space of degree 2 and dimension 2 over Rational Field - Basis matrix: - [1 0] - [0 1] + Basis matrix: + [1 0] + [0 1] sage: f = h.change_ring(GF(7)); f Vector space morphism represented by the matrix: [4 4] [4 4] - Domain: Vector space of degree 3 and dimension 2 over Finite Field of size 7 - Basis matrix: - [0 1 0] - [0 0 1] + Domain: Vector space of degree 3 and dimension 2 over Finite Field of size 7 + Basis matrix: + [0 1 0] + [0 0 1] Codomain: Vector space of degree 2 and dimension 2 over Finite Field of size 7 - Basis matrix: - [1 0] - [0 1] + Basis matrix: + [1 0] + [0 1] """ D = self.domain().change_ring(R) C = self.codomain().change_ring(R) @@ -262,8 +264,9 @@ def inverse_image(self, V): We test computing inverse images between two spaces embedded in different ambient spaces.:: - sage: V0 = span([[0,0,1],[0,2,0]],ZZ); V1 = span([[1/2,0],[0,2]],ZZ); W = span([[1,0],[0,6]],ZZ) - sage: h = V0.hom([-3*V1.0-3*V1.1, -3*V1.0-3*V1.1]) + sage: V0 = span([[0,0,1],[0,2,0]],ZZ); V1 = span([[1/2,0],[0,2]],ZZ) + sage: W = span([[1,0],[0,6]],ZZ) + sage: h = V0.hom([-3*V1.0 - 3*V1.1, -3*V1.0 - 3*V1.1]) sage: h.inverse_image(W) Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: @@ -282,7 +285,7 @@ def inverse_image(self, V): We test computing inverse images over the integers:: sage: V = QQ^3; W = V.span_of_basis([[2,2,3],[-1,2,5/3]], ZZ) - sage: phi = W.hom([W.0, W.0-W.1]) + sage: phi = W.hom([W.0, W.0 - W.1]) sage: Z = W.span([2*W.1]); Z Free module of degree 3 and rank 1 over Integer Ring Echelon basis matrix: @@ -352,7 +355,7 @@ def inverse_image(self, V): else: if not hasattr(A, 'hermite_form'): - raise NotImplementedError("base ring (%s) must have hermite_form algorithm in order to compute inverse image"%R) + raise NotImplementedError("base ring (%s) must have hermite_form algorithm in order to compute inverse image" % R) # 1. Compute H such that U*A = H = hnf(A) without zero # rows. What this "does" is find a basis for the image of @@ -395,7 +398,7 @@ def lift(self, x): sage: V = X.span([[2, 0], [0, 8]], ZZ) sage: W = (QQ**1).span([[1/12]], ZZ) sage: f = V.hom([W([1/3]), W([1/2])], W) - sage: l=f.lift([1/3]); l # random + sage: l=f.lift([1/3]); l # random (8, -16) sage: f(l) (1/3) @@ -440,7 +443,7 @@ def lift(self, x): :: sage: V = QQ^2; m = matrix(2, [1, 1, 0, 1]) - sage: V.hom(m, side="right").lift(V.0+V.1) + sage: V.hom(m, side="right").lift(V.0 + V.1) (0, 1) sage: V.hom(m).lift(V.0+V.1) (1, 0) @@ -460,7 +463,7 @@ def lift(self, x): else: # see inverse_image for similar code but with comments if not hasattr(A, 'hermite_form'): - raise NotImplementedError("base ring (%s) must have hermite_form algorithm in order to compute inverse image"%R) + raise NotImplementedError("base ring (%s) must have hermite_form algorithm in order to compute inverse image" % R) H, U = A.hermite_form(transformation=True,include_zero_rows=False) Y = H.solve_left(vector(self.codomain().coordinates(x))) C = Y*U @@ -473,7 +476,7 @@ def lift(self, x): preimage_representative = lift - def eigenvalues(self,extend=True): + def eigenvalues(self, extend=True): r""" Returns a list with the eigenvalues of the endomorphism of vector spaces. @@ -486,18 +489,18 @@ def eigenvalues(self,extend=True): We compute the eigenvalues of an endomorphism of `\QQ^3`:: - sage: V=QQ^3 - sage: H=V.endomorphism_ring()([[1,-1,0],[-1,1,1],[0,3,1]]) - sage: H.eigenvalues() + sage: V = QQ^3 + sage: H = V.endomorphism_ring()([[1,-1,0], [-1,1,1], [0,3,1]]) + sage: H.eigenvalues() # needs sage.rings.number_field [3, 1, -1] Note the effect of the ``extend`` option:: - sage: V=QQ^2 - sage: H=V.endomorphism_ring()([[0,-1],[1,0]]) - sage: H.eigenvalues() + sage: V = QQ^2 + sage: H = V.endomorphism_ring()([[0,-1], [1,0]]) + sage: H.eigenvalues() # needs sage.rings.number_field [-1*I, 1*I] - sage: H.eigenvalues(extend=False) + sage: H.eigenvalues(extend=False) # needs sage.libs.pari [] """ if self.base_ring().is_field(): @@ -508,7 +511,7 @@ def eigenvalues(self,extend=True): else: raise NotImplementedError("module must be a vector space") - def eigenvectors(self,extend=True): + def eigenvectors(self, extend=True): """ Computes the subspace of eigenvectors of a given eigenvalue. @@ -525,61 +528,42 @@ def eigenvectors(self,extend=True): EXAMPLES:: - sage: V=(QQ^4).subspace([[0,2,1,4],[1,2,5,0],[1,1,1,1]]) - sage: H=(V.Hom(V))(matrix(QQ, [[0,1,0],[-1,0,0],[0,0,3]])) + sage: # needs sage.rings.number_field + sage: V = (QQ^4).subspace([[0,2,1,4], [1,2,5,0], [1,1,1,1]]) + sage: H = (V.Hom(V))(matrix(QQ, [[0,1,0], [-1,0,0], [0,0,3]])) sage: H.eigenvectors() - [(3, [ - (0, 0, 1, -6/7) - ], 1), (-1*I, [ - (1, 1*I, 0, -0.571428571428572? + 2.428571428571429?*I) - ], 1), (1*I, [ - (1, -1*I, 0, -0.571428571428572? - 2.428571428571429?*I) - ], 1)] + [(3, [ (0, 0, 1, -6/7) ], 1), + (-1*I, [ (1, 1*I, 0, -0.571428571428572? + 2.428571428571429?*I) ], 1), + (1*I, [ (1, -1*I, 0, -0.571428571428572? - 2.428571428571429?*I) ], 1)] sage: H.eigenvectors(extend=False) - [(3, [ - (0, 0, 1, -6/7) - ], 1)] - sage: H1=(V.Hom(V))(matrix(QQ, [[2,1,0],[0,2,0],[0,0,3]])) + [(3, [ (0, 0, 1, -6/7) ], 1)] + sage: H1 = (V.Hom(V))(matrix(QQ, [[2,1,0],[0,2,0],[0,0,3]])) sage: H1.eigenvectors() - [(3, [ - (0, 0, 1, -6/7) - ], 1), (2, [ - (0, 1, 0, 17/7) - ], 2)] + [(3, [ (0, 0, 1, -6/7) ], 1), + (2, [ (0, 1, 0, 17/7) ], 2)] sage: H1.eigenvectors(extend=False) - [(3, [ - (0, 0, 1, -6/7) - ], 1), (2, [ - (0, 1, 0, 17/7) - ], 2)] + [(3, [ (0, 0, 1, -6/7) ], 1), + (2, [ (0, 1, 0, 17/7) ], 2)] :: sage: V = QQ^2 sage: m = matrix(2, [1, 1, 0, 1]) - sage: V.hom(m, side="right").eigenvectors() - [(1, - [ - (1, 0) - ], - 2)] - sage: V.hom(m).eigenvectors() - [(1, - [ - (0, 1) - ], - 2)] + sage: V.hom(m, side="right").eigenvectors() # needs sage.rings.number_field + [(1, [ (1, 0) ], 2)] + sage: V.hom(m).eigenvectors() # needs sage.rings.number_field + [(1, [ (0, 1) ], 2)] """ if self.base_ring().is_field(): if self.is_endomorphism(): if self.side() == "right": - seigenvec=self.matrix().eigenvectors_right(extend=extend) + seigenvec = self.matrix().eigenvectors_right(extend=extend) else: - seigenvec=self.matrix().eigenvectors_left(extend=extend) - resu=[] + seigenvec = self.matrix().eigenvectors_left(extend=extend) + resu = [] for i in seigenvec: - V=self.domain().base_extend(i[0].parent()) - svectors=Sequence([V(j * V.basis_matrix()) for j in i[1]], cr=True) + V = self.domain().base_extend(i[0].parent()) + svectors = Sequence([V(j * V.basis_matrix()) for j in i[1]], cr=True) resu.append((i[0],svectors,i[2])) return resu else: @@ -587,7 +571,7 @@ def eigenvectors(self,extend=True): else: raise NotImplementedError("module must be a vector space") - def eigenspaces(self,extend=True): + def eigenspaces(self, extend=True): """ Compute a list of subspaces formed by eigenvectors of ``self``. @@ -603,56 +587,51 @@ def eigenspaces(self,extend=True): EXAMPLES:: sage: V = QQ^3 - sage: h = V.hom([[1,0,0],[0,0,1],[0,-1,0]], V) - sage: h.eigenspaces() - [(1, - Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [1 0 0]), - (-1*I, - Vector space of degree 3 and dimension 1 over Algebraic Field - Basis matrix: - [ 0 1 1*I]), - (1*I, - Vector space of degree 3 and dimension 1 over Algebraic Field - Basis matrix: - [ 0 1 -1*I])] - - sage: h.eigenspaces(extend=False) + sage: h = V.hom([[1,0,0], [0,0,1], [0,-1,0]], V) + sage: h.eigenspaces() # needs sage.rings.number_field + [(1, Vector space of degree 3 and dimension 1 over Rational Field + Basis matrix: + [1 0 0]), + (-1*I, Vector space of degree 3 and dimension 1 over Algebraic Field + Basis matrix: + [ 0 1 1*I]), + (1*I, Vector space of degree 3 and dimension 1 over Algebraic Field + Basis matrix: + [ 0 1 -1*I])] + + sage: h.eigenspaces(extend=False) # needs sage.rings.number_field [(1, Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [1 0 0])] sage: h = V.hom([[2,1,0], [0,2,0], [0,0,-1]], V) - sage: h.eigenspaces() + sage: h.eigenspaces() # needs sage.rings.number_field [(-1, Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [0 0 1]), + Basis matrix: + [0 0 1]), (2, Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [0 1 0])] + Basis matrix: + [0 1 0])] sage: h = V.hom([[2,1,0], [0,2,0], [0,0,2]], V) - sage: h.eigenspaces() + sage: h.eigenspaces() # needs sage.rings.number_field [(2, Vector space of degree 3 and dimension 2 over Rational Field - Basis matrix: - [0 1 0] - [0 0 1])] + Basis matrix: + [0 1 0] + [0 0 1])] :: sage: V = QQ^2; m = matrix(2, [1, 1, 0, 1]) - sage: V.hom(m, side="right").eigenspaces() - [(1, - Vector space of degree 2 and dimension 1 over Rational Field - Basis matrix: - [1 0])] - sage: V.hom(m).eigenspaces() - [(1, - Vector space of degree 2 and dimension 1 over Rational Field - Basis matrix: - [0 1])] + sage: V.hom(m, side="right").eigenspaces() # needs sage.rings.number_field + [(1, Vector space of degree 2 and dimension 1 over Rational Field + Basis matrix: + [1 0])] + sage: V.hom(m).eigenspaces() # needs sage.rings.number_field + [(1, Vector space of degree 2 and dimension 1 over Rational Field + Basis matrix: + [0 1])] """ ev = self.eigenvectors(extend) return [(vec[0], Sequence(vec[1]).universe().subspace(vec[1])) @@ -676,20 +655,20 @@ def minimal_polynomial(self,var='x'): 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: 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 + 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() + sage: H.minpoly() # needs sage.libs.pari x^3 + 6*x^2 + 6*x + 1 - sage: H.minimal_polynomial() + 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 @@ -697,7 +676,7 @@ def minimal_polynomial(self,var='x'): [0 0 0] [0 0 0] [0 0 0] - Domain: Vector space of dimension 3 over Finite Field of size 7 + 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(): @@ -717,7 +696,8 @@ class BaseIsomorphism1D(Morphism): sage: V, from_V, to_V = R.free_module(R) sage: from_V Isomorphism morphism: - From: Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field + From: Ambient free module of rank 1 over the integral domain + Multivariate Polynomial Ring in x, y over Rational Field To: Multivariate Polynomial Ring in x, y over Rational Field """ def _repr_type(self): diff --git a/src/sage/modules/free_quadratic_module.py b/src/sage/modules/free_quadratic_module.py index b512db6ffbc..ff112b9a5c2 100644 --- a/src/sage/modules/free_quadratic_module.py +++ b/src/sage/modules/free_quadratic_module.py @@ -1141,8 +1141,8 @@ def __init__(self, base_field, dimension, inner_product_matrix, sparse=False): Check for :trac:`10606`:: sage: D = matrix.diagonal(ZZ, [1,1]) - sage: V = VectorSpace(GF(46349), 2, inner_product_matrix=D) - sage: deepcopy(V) + sage: V = VectorSpace(GF(46349), 2, inner_product_matrix=D) # needs sage.rings.finite_rings + sage: deepcopy(V) # needs sage.rings.finite_rings Ambient quadratic space of dimension 2 over Finite Field of size 46349 Inner product matrix: diff --git a/src/sage/modules/free_quadratic_module_integer_symmetric.py b/src/sage/modules/free_quadratic_module_integer_symmetric.py index cc1576ab626..e4959cc7a55 100644 --- a/src/sage/modules/free_quadratic_module_integer_symmetric.py +++ b/src/sage/modules/free_quadratic_module_integer_symmetric.py @@ -155,6 +155,7 @@ def IntegralLattice(data, basis=None): (see :mod:`Cartan types ` and :class:`CartanMatrix`):: + sage: # needs sage.graphs sage: IntegralLattice(["E", 7]) Lattice of degree 7 and rank 7 over Integer Ring Standard basis @@ -199,7 +200,7 @@ def IntegralLattice(data, basis=None): Inner product matrix: [0 1] [1 0] - sage: IntegralLattice(["A", 3], [[1,1,1]]) + sage: IntegralLattice(["A", 3], [[1,1,1]]) # needs sage.graphs Lattice of degree 3 and rank 1 over Integer Ring Basis matrix: [1 1 1] @@ -212,7 +213,7 @@ def IntegralLattice(data, basis=None): Basis matrix: [1 1 1 1] Standard scalar product - sage: IntegralLattice("A2", [[1,1]]) + sage: IntegralLattice("A2", [[1,1]]) # needs sage.graphs Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] @@ -222,11 +223,11 @@ def IntegralLattice(data, basis=None): TESTS:: - sage: IntegralLattice(["A", 1, 1]) + sage: IntegralLattice(["A", 1, 1]) # needs sage.graphs Traceback (most recent call last): ... ValueError: lattices must be nondegenerate; use FreeQuadraticModule instead - sage: IntegralLattice(["D", 3, 1]) + sage: IntegralLattice(["D", 3, 1]) # needs sage.graphs Traceback (most recent call last): ... ValueError: lattices must be nondegenerate; use FreeQuadraticModule instead @@ -271,6 +272,7 @@ def IntegralLatticeDirectSum(Lattices, return_embeddings=False): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeDirectSum sage: L1 = IntegralLattice("D4") sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) @@ -308,7 +310,7 @@ def IntegralLatticeDirectSum(Lattices, return_embeddings=False): TESTS:: - sage: IntegralLatticeDirectSum([IntegralLattice("D4")]) + sage: IntegralLatticeDirectSum([IntegralLattice("D4")]) # needs sage.graphs Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: @@ -318,9 +320,9 @@ def IntegralLatticeDirectSum(Lattices, return_embeddings=False): [ 0 -1 0 2] sage: L1 = IntegralLattice(2 * matrix.identity(2), [[1/2, 1/2]]) - sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) - sage: [L, phi] = IntegralLatticeDirectSum([L1, L2], True) - sage: L + sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) # needs sage.graphs + sage: [L, phi] = IntegralLatticeDirectSum([L1, L2], True) # needs sage.graphs + sage: L # needs sage.graphs Lattice of degree 5 and rank 2 over Integer Ring Basis matrix: [1/2 1/2 0 0 0] @@ -416,6 +418,7 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): Inner product matrix: [4]]] + sage: # needs sage.graphs sage: L1 = IntegralLattice([[2]]) sage: L2 = IntegralLattice([[2]]) sage: AL1 = L1.discriminant_group() @@ -436,6 +439,7 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): [2 0] [0 2] + sage: # needs sage.graphs sage: L1 = IntegralLattice("A4") sage: L2 = IntegralLattice("A4") sage: g1 = L1.discriminant_group().gens()[0] @@ -481,6 +485,7 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): Different gluings can be composed:: + sage: # needs sage.graphs sage: D4 = IntegralLattice("D4") sage: D4.discriminant_group() Finite quadratic module over Integer Ring with invariants (2, 2) @@ -507,7 +512,7 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): sage: E8, psi = IntegralLatticeGluing([D6, L2], [[f1, f2], [g1, g2]], True) sage: D4embed = E8.sublattice(psi[0](phi[0].image()).basis_matrix()) sage: x = D4([1, 0, 0, 0]) - sage: psi[0](phi[0](x)).inner_product(psi[0](phi[0](x)))==x.inner_product(x) + sage: psi[0](phi[0](x)).inner_product(psi[0](phi[0](x))) == x.inner_product(x) True sage: D4embed Lattice of degree 8 and rank 4 over Integer Ring @@ -528,6 +533,7 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): The input may be a list of three or more lattices:: + sage: # needs sage.graphs sage: A7 = IntegralLattice("A7") sage: D5 = IntegralLattice("D5") sage: gA7 = A7.discriminant_group().gens()[0] @@ -538,16 +544,18 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): sage: L.determinant() 1 sage: B = phi[0].matrix() - sage: B*L.gram_matrix()*B.transpose()==A7.gram_matrix() + sage: B*L.gram_matrix()*B.transpose() == A7.gram_matrix() True The gluing takes place in the direct sum of the respective ambient spaces:: + sage: # needs sage.graphs sage: L1 = IntegralLattice("D4", [[1, 1, 0, 0], [0, 1, 1, 0]]) sage: L2 = IntegralLattice("E6", [[0, 2, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1]]) sage: [f1, f2] = L1.discriminant_group().gens() sage: [g1, g2] = L2.discriminant_group().gens() - sage: [L, phi] = IntegralLatticeGluing([L1, L2], [[f1, g1], [f2, 2 * g2]], True) + sage: [L, phi] = IntegralLatticeGluing([L1, L2], + ....: [[f1, g1], [f2, 2 * g2]], True) sage: phi[0] Free module morphism defined by the matrix [ 2 2 -2 -1] @@ -579,13 +587,13 @@ def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): [ 0 0 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 0 0 -1 2] sage: B = phi[0].matrix() - sage: B * L.gram_matrix() * B.transpose()==L1.gram_matrix() + sage: B * L.gram_matrix() * B.transpose() == L1.gram_matrix() True """ [direct_sum, phi] = IntegralLatticeDirectSum(Lattices, return_embeddings=True) N = len(Lattices) for g in glue: - if not len(g)==N: + if not len(g) == N: raise ValueError("the lengths of the lists do not match") for i in range(N): ALi = Lattices[i].discriminant_group() @@ -684,7 +692,7 @@ def _mul_(self, other, switch_sides=False): B = self.basis_matrix() B = other * B if switch_sides else B * other # check whether it is integral - if other in ZZ or other.denominator()==1: + if other in ZZ or other.denominator() == 1: return self.sublattice(B.rows()) else: return self.span(B.rows()) @@ -695,8 +703,8 @@ def _repr_(self): EXAMPLES:: - sage: A2 = IntegralLattice("A2") - sage: A2 + sage: A2 = IntegralLattice("A2") # needs sage.graphs + sage: A2 # needs sage.graphs Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: @@ -731,8 +739,8 @@ def is_even(self): sage: L = IntegralLattice(G) sage: L.is_even() False - sage: L = IntegralLattice("A2") - sage: L.is_even() + sage: L = IntegralLattice("A2") # needs sage.graphs + sage: L.is_even() # needs sage.graphs True """ return all(d % 2 == 0 for d in self.gram_matrix().diagonal()) @@ -750,8 +758,8 @@ def dual_lattice(self): EXAMPLES:: - sage: L = IntegralLattice("A2") - sage: Ldual = L.dual_lattice(); Ldual + sage: L = IntegralLattice("A2") # needs sage.graphs + sage: Ldual = L.dual_lattice(); Ldual # needs sage.graphs Free module of degree 2 and rank 2 over Integer Ring Echelon basis matrix: [1/3 2/3] @@ -759,7 +767,7 @@ def dual_lattice(self): Since our lattices are always integral, a lattice is contained in its dual:: - sage: L.is_submodule(Ldual) + sage: L.is_submodule(Ldual) # needs sage.graphs True """ return self.span(self.gram_matrix().inverse()*self.basis_matrix()) @@ -807,13 +815,13 @@ def discriminant_group(self, s=0): sage: import gc sage: gc.freeze() - sage: L = IntegralLattice("A2") + sage: L = IntegralLattice("A2") # needs sage.graphs sage: for k in range(1,500): # long time ....: G = L.twist(k) ....: D = G.discriminant_group() sage: tmp = gc.collect() sage: tmp = gc.collect() - sage: len([a for a in gc.get_objects() if type(a)==type(L)])<=300 + sage: len([a for a in gc.get_objects() if type(a) == type(L)]) <= 300 True sage: gc.unfreeze() """ @@ -849,8 +857,8 @@ def signature_pair(self): EXAMPLES:: - sage: A2 = IntegralLattice("A2") - sage: A2.signature_pair() + sage: A2 = IntegralLattice("A2") # needs sage.graphs + sage: A2.signature_pair() # needs sage.graphs (2, 0) """ from sage.quadratic_forms.quadratic_form import QuadraticForm @@ -1029,6 +1037,7 @@ def maximal_overlattice(self, p=None): EXAMPLES:: + sage: # needs sage.graphs sage: L = IntegralLattice("A4").twist(25*89) sage: L.maximal_overlattice().determinant() 5 @@ -1039,6 +1048,7 @@ def maximal_overlattice(self, p=None): TESTS:: + sage: # needs sage.libs.flint (otherwise timeout) sage: L = IntegralLattice(matrix.diagonal([2,4,4,8])) sage: L.maximal_overlattice().is_even() True @@ -1048,7 +1058,7 @@ def maximal_overlattice(self, p=None): # it might speed up things to use the algorithms given in # https://arxiv.org/abs/1208.2481 # and trac:11940 - if not self.is_even() and (p is None or p==2): + if not self.is_even() and (p is None or p == 2): raise ValueError("this lattice must be even to admit an even overlattice") from sage.rings.finite_rings.finite_field_constructor import GF L = self @@ -1164,8 +1174,8 @@ def orthogonal_group(self, gens=None, is_finite=None): EXAMPLES:: - sage: A4 = IntegralLattice("A4") - sage: Aut = A4.orthogonal_group(); Aut + sage: A4 = IntegralLattice("A4") # needs sage.graphs + sage: Aut = A4.orthogonal_group(); Aut # needs sage.graphs sage.libs.gap Group of isometries with 4 generators ( [0 0 0 1] [-1 -1 -1 0] [ 1 0 0 0] [ 1 0 0 0] [0 0 1 0] [ 0 0 0 -1] [-1 -1 -1 -1] [ 0 1 0 0] @@ -1175,6 +1185,7 @@ def orthogonal_group(self, gens=None, is_finite=None): The group acts from the right on the lattice and its discriminant group:: + sage: # needs sage.graphs sage.libs.gap sage: x = A4.an_element() sage: g = Aut.an_element(); g [-1 -1 -1 0] @@ -1193,6 +1204,7 @@ def orthogonal_group(self, gens=None, is_finite=None): If the group is finite we can compute the usual things:: + sage: # needs sage.graphs sage.libs.gap sage: Aut.order() 240 sage: conj = Aut.conjugacy_classes_representatives() @@ -1203,8 +1215,9 @@ def orthogonal_group(self, gens=None, is_finite=None): The lattice can live in a larger ambient space:: - sage: A2 = IntegralLattice(matrix.identity(3), Matrix(ZZ, 2, 3, [1,-1,0,0,1,-1])) - sage: A2.orthogonal_group() + sage: A2 = IntegralLattice(matrix.identity(3), + ....: Matrix(ZZ, 2, 3, [1,-1,0,0,1,-1])) + sage: A2.orthogonal_group() # needs sage.libs.gap Group of isometries with 2 generators ( [ 2/3 2/3 -1/3] [1 0 0] [ 2/3 -1/3 2/3] [0 0 1] @@ -1214,15 +1227,15 @@ def orthogonal_group(self, gens=None, is_finite=None): It can be negative definite as well:: sage: A2m = IntegralLattice(-Matrix(ZZ, 2, [2,1,1,2])) - sage: G = A2m.orthogonal_group() - sage: G.order() + sage: G = A2m.orthogonal_group() # needs sage.libs.gap + sage: G.order() # needs sage.libs.gap 12 If the lattice is indefinite, sage does not know how to compute generators. Can you teach it?:: sage: U = IntegralLattice(Matrix(ZZ, 2, [0,1,1,0])) - sage: U.orthogonal_group() + sage: U.orthogonal_group() # needs sage.libs.gap Traceback (most recent call last): ... NotImplementedError: currently, we can only compute generators @@ -1232,7 +1245,7 @@ def orthogonal_group(self, gens=None, is_finite=None): sage: S = IntegralLattice(Matrix(ZZ, 2, [2, 3, 3, 2])) sage: f = Matrix(ZZ, 2, [0,1,-1,3]) - sage: S.orthogonal_group([f]) + sage: S.orthogonal_group([f]) # needs sage.libs.gap Group of isometries with 1 generator ( [ 0 1] [-1 3] @@ -1243,7 +1256,7 @@ def orthogonal_group(self, gens=None, is_finite=None): We can handle the trivial group:: sage: S = IntegralLattice(Matrix(ZZ, 2, [2, 3, 3, 2])) - sage: S.orthogonal_group([]) + sage: S.orthogonal_group([]) # needs sage.libs.gap Group of isometries with 1 generator ( [1 0] [0 1] @@ -1293,7 +1306,7 @@ def orthogonal_group(self, gens=None, is_finite=None): invariant_quotient_module=D) return G - automorphisms=orthogonal_group + automorphisms = orthogonal_group def genus(self): r""" @@ -1302,7 +1315,7 @@ def genus(self): EXAMPLES:: sage: L = IntegralLattice("U") - sage: L.genus() + sage: L.genus() # needs sage.padics Genus of [0 1] [1 0] @@ -1324,6 +1337,7 @@ def tensor_product(self, other, discard_basis=False): EXAMPLES:: + sage: # needs sage.graphs sage: L = IntegralLattice("D3", [[1,-1,0], [0,1,-1]]) sage: L1 = L.tensor_product(L); L1 Lattice of degree 9 and rank 4 over Integer Ring @@ -1378,8 +1392,8 @@ def quadratic_form(self): EXAMPLES:: - sage: L = IntegralLattice("A2") - sage: q = L.quadratic_form(); q + sage: L = IntegralLattice("A2") # needs sage.graphs + sage: q = L.quadratic_form(); q # needs sage.graphs Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 -2 ] [ * 2 ] @@ -1398,10 +1412,10 @@ def minimum(self): EXAMPLES:: - sage: L = IntegralLattice('A2') - sage: L.minimum() + sage: L = IntegralLattice('A2') # needs sage.graphs + sage: L.minimum() # needs sage.graphs 2 - sage: L.twist(-1).minimum() + sage: L.twist(-1).minimum() # needs sage.graphs -Infinity """ p, n = self.signature_pair() @@ -1424,10 +1438,10 @@ def maximum(self): EXAMPLES:: - sage: L = IntegralLattice('A2') - sage: L.maximum() + sage: L = IntegralLattice('A2') # needs sage.graphs + sage: L.maximum() # needs sage.graphs +Infinity - sage: L.twist(-1).maximum() + sage: L.twist(-1).maximum() # needs sage.graphs -2 """ if self.rank() == 0: @@ -1448,13 +1462,14 @@ def LLL(self): EXAMPLES:: - sage: L = IntegralLattice('A2') - sage: L.lll() == L + sage: L = IntegralLattice('A2') # needs sage.graphs + sage: L.lll() == L # needs sage.graphs True + sage: G = matrix(ZZ, 3, [0,1,0, 1,0,0, 0,0,7]) sage: V = matrix(ZZ, 3, [-14,-15,-15, -4,1,16, -5,-5,-4]) sage: L = IntegralLattice(V * G * V.T) - sage: L.lll().gram_matrix() + sage: L.lll().gram_matrix() # needs sage.libs.gap [0 0 1] [0 7 0] [1 0 0] @@ -1466,7 +1481,7 @@ def LLL(self): from sage.libs.pari import pari m = self.gram_matrix().__pari__() gp.read(SAGE_EXTCODE + "/pari/simon/qfsolve.gp") - m = gp.eval('qflllgram_indefgoon(%s)'%m) + m = gp.eval('qflllgram_indefgoon(%s)' % m) # convert the output string to sage G, U = pari(m).sage() U = U.T @@ -1495,10 +1510,10 @@ def short_vectors(self, n, **kwargs): EXAMPLES:: - sage: A2 = IntegralLattice('A2') - sage: A2.short_vectors(3) + sage: A2 = IntegralLattice('A2') # needs sage.graphs + sage: A2.short_vectors(3) # needs sage.graphs [[(0, 0)], [], [(1, 1), (-1, -1), (0, 1), (0, -1), (1, 0), (-1, 0)]] - sage: A2.short_vectors(3,up_to_sign_flag=True) + sage: A2.short_vectors(3,up_to_sign_flag=True) # needs sage.graphs [[(0, 0)], [], [(1, 1), (0, 1), (1, 0)]] """ p, m = self.signature_pair() @@ -1525,8 +1540,8 @@ def twist(self, s, discard_basis=False): EXAMPLES:: - sage: L = IntegralLattice("A4") - sage: L.twist(3) + sage: L = IntegralLattice("A4") # needs sage.graphs + sage: L.twist(3) # needs sage.graphs Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: @@ -1557,7 +1572,7 @@ def twist(self, s, discard_basis=False): s = self.base_ring()(s) except TypeError: raise ValueError("the scaling factor must be an element of the base ring.") - if s==0: + if s == 0: raise ValueError("the scaling factor must be non zero") if discard_basis: return IntegralLattice(s * self.gram_matrix()) @@ -1587,6 +1602,7 @@ def local_modification(M, G, p, check=True): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.modules.free_quadratic_module_integer_symmetric import local_modification sage: L = IntegralLattice("A3").twist(15) sage: M = L.maximal_overlattice() diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index b400cc4afd0..b9d45e9755f 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -21,13 +21,13 @@ [0 0 1] sage: is_MatrixMorphism(m) True - sage: m.charpoly('x') + sage: m.charpoly('x') # needs sage.libs.pari x^3 - 3*x^2 + 3*x - 1 sage: m.base_ring() Rational Field sage: m.det() 1 - sage: m.fcp('x') + sage: m.fcp('x') # needs sage.libs.pari (x - 1)^3 sage: m.matrix() [1 0 0] @@ -188,7 +188,7 @@ def _call_(self, x): if parent(x) is not self.domain(): x = self.domain()(x) except TypeError: - raise TypeError("%s must be coercible into %s"%(x,self.domain())) + raise TypeError("%s must be coercible into %s" % (x,self.domain())) if self.domain().is_ambient(): x = x.element() else: @@ -523,10 +523,11 @@ def __mul__(self, right): Composite maps can be formed with matrix morphisms:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 + 23) # optional - sage.rings.number_field - sage: V, VtoK, KtoV = K.vector_space() # optional - sage.rings.number_field - sage: f = V.hom([V.0 - V.1, V.0 + V.1])*KtoV; f # optional - sage.rings.number_field + sage: K. = NumberField(x^2 + 23) + sage: V, VtoK, KtoV = K.vector_space() + sage: f = V.hom([V.0 - V.1, V.0 + V.1])*KtoV; f Composite map: From: Number Field in a with defining polynomial x^2 + 23 To: Vector space of dimension 2 over Rational Field @@ -836,7 +837,7 @@ def decomposition(self, *args, **kwds): EXAMPLES:: sage: V = ZZ^2; phi = V.hom([V.0+V.1, 2*V.1]) - sage: phi.decomposition() + sage: phi.decomposition() # needs sage.libs.pari [ Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: @@ -846,7 +847,7 @@ def decomposition(self, *args, **kwds): [ 1 -1] ] sage: phi2 = V.hom(phi.matrix(), side="right") - sage: phi2.decomposition() + sage: phi2.decomposition() # needs sage.libs.pari [ Free module of degree 2 and rank 1 over Integer Ring Echelon basis matrix: @@ -905,10 +906,10 @@ def fcp(self, var='x'): EXAMPLES:: - sage: V = ZZ^2; phi = V.hom([V.0+V.1, 2*V.1]) - sage: phi.fcp() + 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') + sage: phi.fcp('T') # needs sage.libs.pari (T - 2) * (T - 1) """ return self.charpoly(var).factor() @@ -1741,7 +1742,7 @@ def is_surjective(self): An example over a PID that is not `\ZZ`. :: - sage: R = PolynomialRing(QQ, 'x') + sage: R. = PolynomialRing(QQ) sage: A = R^2 sage: B = R^2 sage: H = A.hom([B([x^2-1, 1]), B([x^2, 1])]) diff --git a/src/sage/modules/module.pyx b/src/sage/modules/module.pyx index 20c51d19079..818d139c3ba 100644 --- a/src/sage/modules/module.pyx +++ b/src/sage/modules/module.pyx @@ -27,7 +27,8 @@ A minimal example of a module:: ....: def _repr_(self): ....: return repr(self.x) - sage: class MyModule(sage.modules.module.Module): + sage: from sage.modules.module import Module + sage: class MyModule(Module): ....: Element = MyElement ....: def _element_constructor_(self, x): ....: if isinstance(x, MyElement): x = x.x @@ -106,6 +107,7 @@ cdef class Module(Parent): We check that :trac:`8119` has been resolved:: + sage: # needs sage.modules sage: M = ZZ^3 sage: h = M.__hash__() sage: M.rename('toto') @@ -161,7 +163,7 @@ cdef class Module(Parent): Make sure :trac:`3638` is fixed:: - sage: vector(ZZ,[1,2,11])==vector(Zmod(8),[1,2,3]) + sage: vector(ZZ,[1,2,11]) == vector(Zmod(8),[1,2,3]) # needs sage.modules True AUTHORS: @@ -186,8 +188,8 @@ cdef class Module(Parent): EXAMPLES:: - sage: from sage.modular.modform.space import ModularFormsSpace # optional - sage.modular - sage: ModularFormsSpace(Gamma0(11), 2, # optional - sage.modular sage.rings.finite_rings + sage: from sage.modular.modform.space import ModularFormsSpace # needs sage.modular + sage: ModularFormsSpace(Gamma0(11), 2, # needs sage.modular sage.rings.finite_rings ....: DirichletGroup(1)[0], QQ).change_ring(GF(7)) Traceback (most recent call last): ... @@ -212,33 +214,34 @@ cdef class Module(Parent): EXAMPLES:: - sage: V = ZZ^7 - sage: V.base_extend(QQ) + sage: V = ZZ^7 # needs sage.modules + sage: V.base_extend(QQ) # needs sage.modules Vector space of dimension 7 over Rational Field TESTS:: - sage: N = ModularForms(6, 4) # optional - sage.modular - sage: N.base_extend(CyclotomicField(7)) # optional - sage.modular sage.rings.number_field + sage: N = ModularForms(6, 4) # needs sage.modular + sage: N.base_extend(CyclotomicField(7)) # needs sage.modular sage.rings.number_field Modular Forms space of dimension 5 for Congruence Subgroup Gamma0(6) of weight 4 over Cyclotomic Field of order 7 and degree 6 - sage: m = ModularForms(DirichletGroup(13).0^2,2); m # optional - sage.modular sage.rings.number_field + sage: m = ModularForms(DirichletGroup(13).0^2,2); m # needs sage.modular sage.rings.number_field Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2 - sage: m.base_extend(CyclotomicField(12)) # optional - sage.modular sage.rings.number_field + sage: m.base_extend(CyclotomicField(12)) # needs sage.modular sage.rings.number_field Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 12 and degree 4 - sage: chi = DirichletGroup(109, CyclotomicField(3)).0 # optional - sage.modular sage.rings.number_field - sage: S3 = CuspForms(chi, 2) # optional - sage.modular sage.rings.number_field - sage: S9 = S3.base_extend(CyclotomicField(9)); S9 # optional - sage.modular sage.rings.number_field + sage: # needs sage.modular sage.rings.number_field + sage: chi = DirichletGroup(109, CyclotomicField(3)).0 + sage: S3 = CuspForms(chi, 2) + sage: S9 = S3.base_extend(CyclotomicField(9)); S9 Cuspidal subspace of dimension 8 of Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 9 and degree 6 - sage: S9.has_coerce_map_from(S3) # not implemented # optional - sage.modular sage.rings.number_field + sage: S9.has_coerce_map_from(S3) # not implemented True - sage: S9.base_extend(CyclotomicField(3)) # optional - sage.modular sage.rings.number_field + sage: S9.base_extend(CyclotomicField(3)) Traceback (most recent call last): ... TypeError: Base extension of self (over 'Cyclotomic Field of order 9 and degree 6') @@ -278,8 +281,8 @@ def is_Module(x): EXAMPLES:: sage: from sage.modules.module import is_Module - sage: M = FreeModule(RationalField(),30) - sage: is_Module(M) + sage: M = FreeModule(RationalField(),30) # needs sage.modules + sage: is_Module(M) # needs sage.modules True sage: is_Module(10) False @@ -297,6 +300,7 @@ def is_VectorSpace(x): EXAMPLES:: + sage: # needs sage.modules sage: from sage.modules.module import is_Module, is_VectorSpace sage: M = FreeModule(RationalField(),30) sage: is_VectorSpace(M) diff --git a/src/sage/modules/quotient_module.py b/src/sage/modules/quotient_module.py index 10db2189997..c50c1d044fc 100644 --- a/src/sage/modules/quotient_module.py +++ b/src/sage/modules/quotient_module.py @@ -163,12 +163,13 @@ def _coerce_map_from_(self, M): sage: Q.coerce_map_from(M) Coercion map: From: Ambient free module of rank 2 over the integral domain - Multivariate Polynomial Ring in x, y, z over Rational Field - To: Quotient module by Submodule of Ambient free module of rank 2 - over the integral domain Multivariate Polynomial Ring in x, y, z over Rational Field - Generated by the rows of the matrix: - [x - y z] - [ y*z x*z] + Multivariate Polynomial Ring in x, y, z over Rational Field + To: Quotient module by Submodule of + Ambient free module of rank 2 over the integral domain + Multivariate Polynomial Ring in x, y, z over Rational Field + Generated by the rows of the matrix: + [x - y z] + [ y*z x*z] """ if isinstance(M, FreeModule_ambient): return (self.base_ring().has_coerce_map_from(M.base_ring()) and @@ -277,7 +278,8 @@ def free_relations(self): sage: NQ = Q.submodule([Q([1, x])]) sage: QNQ = Q / NQ sage: QNQ.free_relations() - Submodule of Ambient free module of rank 2 over the integral domain Multivariate Polynomial Ring in x, y, z over Rational Field + Submodule of Ambient free module of rank 2 over the integral domain + Multivariate Polynomial Ring in x, y, z over Rational Field Generated by the rows of the matrix: [ 1 x] [x - y z] @@ -307,43 +309,53 @@ class FreeModule_ambient_field_quotient(FreeModule_ambient_field): EXAMPLES:: + sage: # needs sage.rings.number_field sage: k. = QuadraticField(-1) sage: A = k^3; V = A.span([[1,0,i], [2,i,0]]) sage: W = A.span([[3,i,i]]) sage: U = V/W; U - Vector space quotient V/W of dimension 1 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I where - V: Vector space of degree 3 and dimension 2 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 0 i] - [ 0 1 -2] - W: Vector space of degree 3 and dimension 1 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 1/3*i 1/3*i] + Vector space quotient V/W of dimension 1 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I where + V: Vector space of degree 3 and dimension 2 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 0 i] + [ 0 1 -2] + W: Vector space of degree 3 and dimension 1 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 1/3*i 1/3*i] sage: U.V() - Vector space of degree 3 and dimension 2 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 0 i] - [ 0 1 -2] + Vector space of degree 3 and dimension 2 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 0 i] + [ 0 1 -2] sage: U.W() - Vector space of degree 3 and dimension 1 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 1/3*i 1/3*i] + Vector space of degree 3 and dimension 1 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 1/3*i 1/3*i] sage: U.quotient_map() Vector space morphism represented by the matrix: [ 1] [3*i] - Domain: Vector space of degree 3 and dimension 2 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 0 i] - [ 0 1 -2] - Codomain: Vector space quotient V/W of dimension 1 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I where - V: Vector space of degree 3 and dimension 2 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 0 i] - [ 0 1 -2] - W: Vector space of degree 3 and dimension 1 over Number Field in i with defining polynomial x^2 + 1 with i = 1*I - Basis matrix: - [ 1 1/3*i 1/3*i] + Domain: Vector space of degree 3 and dimension 2 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 0 i] + [ 0 1 -2] + Codomain: Vector space quotient V/W of dimension 1 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I where + V: Vector space of degree 3 and dimension 2 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 0 i] + [ 0 1 -2] + W: Vector space of degree 3 and dimension 1 over Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + Basis matrix: + [ 1 1/3*i 1/3*i] sage: Z = V.quotient(W) sage: Z == U True @@ -366,7 +378,7 @@ class FreeModule_ambient_field_quotient(FreeModule_ambient_field): TESTS:: - sage: A = QQ^0; V = A.span([]) # corner case + sage: A = QQ^0; V = A.span([]) # corner case sage: W = A.span([]) sage: U = V/W @@ -432,19 +444,20 @@ def _repr_(self): We create a quotient vector space over a finite field:: + sage: # needs sage.rings.finite_rings sage: k. = GF(9); A = k^3; V = A.span_of_basis([[1,0,a], [a,a,1]]); W = V.span([V.1]) sage: Q = V/W Note the type:: - sage: type(Q) + sage: type(Q) # needs sage.rings.finite_rings The string representation mentions that this is a quotient `V/W`, that the quotient has dimension 1 and is over a finite field, and also describes `V` and `W`:: - sage: Q._repr_() + sage: Q._repr_() # needs sage.rings.finite_rings 'Vector space quotient V/W of dimension 1 over Finite Field in a of size 3^2 where\nV: Vector space of degree 3 and dimension 2 over Finite Field in a of size 3^2\nUser basis matrix:\n[1 0 a]\n[a a 1]\nW: Vector space of degree 3 and dimension 1 over Finite Field in a of size 3^2\nBasis matrix:\n[ 1 1 a + 2]' """ return "%s space quotient V/W of dimension %s over %s where\nV: %s\nW: %s" % ( @@ -539,23 +552,23 @@ def _coerce_map_from_(self, M): Composite map: From: Ambient free module of rank 2 over the principal ideal domain Integer Ring To: Vector space quotient V/W of dimension 1 over Rational Field where - V: Vector space of dimension 2 over Rational Field - W: Vector space of degree 2 and dimension 1 over Rational Field - Basis matrix: - [1 2] + V: Vector space of dimension 2 over Rational Field + W: Vector space of degree 2 and dimension 1 over Rational Field + Basis matrix: + [1 2] Defn: Coercion map: From: Ambient free module of rank 2 over the principal ideal domain Integer Ring To: Vector space of dimension 2 over Rational Field then Vector space morphism represented by the matrix: - [ 1] - [-1/2] - Domain: Vector space of dimension 2 over Rational Field - Codomain: Vector space quotient V/W of dimension 1 over Rational Field where - V: Vector space of dimension 2 over Rational Field - W: Vector space of degree 2 and dimension 1 over Rational Field - Basis matrix: - [1 2] + [ 1] + [-1/2] + Domain: Vector space of dimension 2 over Rational Field + Codomain: Vector space quotient V/W of dimension 1 over Rational Field where + V: Vector space of dimension 2 over Rational Field + W: Vector space of degree 2 and dimension 1 over Rational Field + Basis matrix: + [1 2] Make sure :trac:`10513` is fixed (no coercion from an abstract vector space to an isomorphic quotient vector space):: @@ -592,12 +605,12 @@ def quotient_map(self): [ 1 0] [ 0 1] [-1/3 -2/3] - Domain: Vector space of dimension 3 over Rational Field + Domain: Vector space of dimension 3 over Rational Field Codomain: Vector space quotient V/W of dimension 2 over Rational Field where - V: Vector space of dimension 3 over Rational Field - W: Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [1 2 3] + V: Vector space of dimension 3 over Rational Field + W: Vector space of degree 3 and dimension 1 over Rational Field + Basis matrix: + [1 2 3] sage: M.quotient_map()( (QQ^3)([1,2,3]) ) (0, 0) @@ -616,11 +629,11 @@ def lift_map(self): Vector space morphism represented by the matrix: [1 0 0] [0 1 0] - Domain: Vector space quotient V/W of dimension 2 over Rational Field where - V: Vector space of dimension 3 over Rational Field - W: Vector space of degree 3 and dimension 1 over Rational Field - Basis matrix: - [1 2 3] + Domain: Vector space quotient V/W of dimension 2 over Rational Field where + V: Vector space of dimension 3 over Rational Field + W: Vector space of degree 3 and dimension 1 over Rational Field + Basis matrix: + [1 2 3] Codomain: Vector space of dimension 3 over Rational Field """ return self.__lift_map diff --git a/src/sage/modules/tensor_operations.py b/src/sage/modules/tensor_operations.py index fafd5cc3a89..41743870ca7 100644 --- a/src/sage/modules/tensor_operations.py +++ b/src/sage/modules/tensor_operations.py @@ -119,7 +119,7 @@ def antisymmetrized_coordinate_sums(dim, n): EXAMPLES:: sage: from sage.modules.tensor_operations import antisymmetrized_coordinate_sums - sage: antisymmetrized_coordinate_sums(3, 2) + sage: antisymmetrized_coordinate_sums(3, 2) # needs sage.groups ((0, 1) - (1, 0), (0, 2) - (2, 0), (1, 2) - (2, 1)) """ from sage.structure.formal_sum import FormalSum @@ -379,8 +379,8 @@ def _init_power_operation_vectors(self, i, linear_combinations): sage: Sym2_R = TensorOperation([R,R], operation='symmetric') sage: Sym2_R.vectors() # indirect doctest ((1, 0, 0), (1, 2, 0), (-1, -2, 0), (1, 4, 4), (-1, -4, -4)) - sage: Alt2_R = TensorOperation([R, R], operation='antisymmetric') - sage: Alt2_R.vectors() # indirect doctest + sage: Alt2_R = TensorOperation([R, R], operation='antisymmetric') # needs sage.groups + sage: Alt2_R.vectors() # indirect doctest # needs sage.groups ((2), (-2)) """ rays = [self._V[j].vectors()[k] for j, k in enumerate(i)] @@ -453,8 +453,8 @@ def _init_antisymmetric(self): sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) - sage: Alt2_R = TensorOperation([R, R], operation='antisymmetric') # indirect doctest - sage: sorted(Alt2_R._index_map.items()) + sage: Alt2_R = TensorOperation([R, R], operation='antisymmetric') # indirect doctest # needs sage.groups + sage: sorted(Alt2_R._index_map.items()) # needs sage.groups [((0, 1), 0), ((0, 2), 1)] """ n = len(self._V) @@ -517,17 +517,17 @@ def index_map(self, *i): sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (0,1), (-2,-3)], QQ, 2) - sage: detR = TensorOperation([R]*2, 'antisymmetric') - sage: detR.index_map(1, 0) + sage: detR = TensorOperation([R]*2, 'antisymmetric') # needs sage.groups + sage: detR.index_map(1, 0) # needs sage.groups 0 - sage: detR.index_map(0, 1) + sage: detR.index_map(0, 1) # needs sage.groups 0 TESTS:: - sage: sorted(detR._index_map.items()) + sage: sorted(detR._index_map.items()) # needs sage.groups [((0, 1), 0), ((0, 2), 1), ((1, 2), 2)] - sage: detR.vectors() + sage: detR.vectors() # needs sage.groups ((1), (-3), (2)) """ if len(i) == 1 and isinstance(i[0], (list, tuple)): @@ -553,10 +553,10 @@ def preimage(self): sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (0,1), (-2,-3)], QQ, 2) - sage: detR = TensorOperation([R]*2, 'antisymmetric') - sage: sorted(detR.preimage()) + sage: detR = TensorOperation([R]*2, 'antisymmetric') # needs sage.groups + sage: sorted(detR.preimage()) # needs sage.groups [(0, 1), (0, 2), (1, 2)] - sage: sorted(detR.codomain()) + sage: sorted(detR.codomain()) # needs sage.groups [0, 1, 2] """ return self._index_map.keys() @@ -574,10 +574,10 @@ def codomain(self): sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (0,1), (-2,-3)], QQ, 2) - sage: detR = TensorOperation([R]*2, 'antisymmetric') - sage: sorted(detR.preimage()) + sage: detR = TensorOperation([R]*2, 'antisymmetric') # needs sage.groups + sage: sorted(detR.preimage()) # needs sage.groups [(0, 1), (0, 2), (1, 2)] - sage: sorted(detR.codomain()) + sage: sorted(detR.codomain()) # needs sage.groups [0, 1, 2] """ return self._index_map.values() diff --git a/src/sage/modules/torsion_quadratic_module.py b/src/sage/modules/torsion_quadratic_module.py index 1b9825703f3..b98e6f89c4b 100644 --- a/src/sage/modules/torsion_quadratic_module.py +++ b/src/sage/modules/torsion_quadratic_module.py @@ -21,7 +21,6 @@ from sage.modules.free_quadratic_module import FreeQuadraticModule from sage.arith.misc import gcd from sage.rings.integer_ring import ZZ -from sage.rings.padics.factory import Zp from sage.rings.rational_field import QQ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.groups.additive_abelian.qmodnz import QmodnZ @@ -375,8 +374,8 @@ def all_submodules(self): EXAMPLES:: - sage: D = IntegralLattice("D4").discriminant_group() - sage: D.all_submodules() + sage: D = IntegralLattice("D4").discriminant_group() # needs sage.combinat + sage: D.all_submodules() # needs sage.combinat [Finite quadratic module over Integer Ring with invariants () Gram matrix of the quadratic form with values in Q/2Z: [], @@ -429,9 +428,9 @@ def brown_invariant(self): EXAMPLES:: - sage: L = IntegralLattice("D4") - sage: D = L.discriminant_group() - sage: D.brown_invariant() + sage: L = IntegralLattice("D4") # needs sage.combinat + sage: D = L.discriminant_group() # needs sage.combinat + sage: D.brown_invariant() # needs sage.combinat 4 We require the quadratic form to be defined modulo `2 \ZZ`:: @@ -552,24 +551,25 @@ def genus(self, signature_pair): EXAMPLES:: - sage: L = IntegralLattice("D4").direct_sum(IntegralLattice("A2")) # optional - sage.combinat - sage: D = L.discriminant_group() # optional - sage.combinat - sage: genus = D.genus(L.signature_pair()) # optional - sage.combinat sage.libs.pari - sage: genus # optional - sage.combinat sage.libs.pari + sage: # needs sage.combinat + sage: L = IntegralLattice("D4").direct_sum(IntegralLattice("A2")) + sage: D = L.discriminant_group() + sage: genus = D.genus(L.signature_pair()) # needs sage.libs.pari + sage: genus # needs sage.libs.pari Genus of None Signature: (6, 0) Genus symbol at 2: 1^4:2^-2 Genus symbol at 3: 1^-5 3^-1 - sage: genus == L.genus() # optional - sage.combinat sage.libs.pari + sage: genus == L.genus() # needs sage.libs.pari True Let `H` be an even unimodular lattice of signature `(9, 1)`. Then `L = D_4 + A_2` is primitively embedded in `H`. We compute the discriminant form of the orthogonal complement of `L` in `H`:: - sage: DK = D.twist(-1) # optional - sage.combinat sage.libs.pari - sage: DK # optional - sage.combinat sage.libs.pari + sage: DK = D.twist(-1) # needs sage.combinat sage.libs.pari + sage: DK # needs sage.combinat sage.libs.pari Finite quadratic module over Integer Ring with invariants (2, 6) Gram matrix of the quadratic form with values in Q/2Z: [ 1 1/2] @@ -578,7 +578,7 @@ def genus(self, signature_pair): We know that `K` has signature `(5, 1)` and thus we can compute the genus of `K` as:: - sage: DK.genus((3,1)) # optional - sage.combinat sage.libs.pari + sage: DK.genus((3,1)) # needs sage.combinat sage.libs.pari Genus of None Signature: (3, 1) @@ -588,9 +588,9 @@ def genus(self, signature_pair): We can also compute the genus of an odd lattice from its discriminant form:: - sage: L = IntegralLattice(matrix.diagonal(range(1,5))) + sage: L = IntegralLattice(matrix.diagonal(range(1, 5))) sage: D = L.discriminant_group() - sage: D.genus((4,0)) # optional - sage.libs.pari + sage: D.genus((4,0)) # needs sage.libs.pari Genus of None Signature: (4, 0) @@ -599,20 +599,21 @@ def genus(self, signature_pair): TESTS:: - sage: L.genus() == D.genus((4,0)) # optional - sage.libs.pari + sage: L.genus() == D.genus((4,0)) # needs sage.libs.pari True - sage: D.genus((1,0)) # optional - sage.libs.pari + sage: D.genus((1,0)) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: this discriminant form and signature do not define a genus A systematic test of lattices of small ranks and determinants:: - sage: from sage.quadratic_forms.genera.genus import genera # optional - sage.libs.pari - sage: signatures = [(1,0), (1,1), (1,2), (3,0), (0,4)] # optional - sage.libs.pari - sage: dets = range(1, 33) # optional - sage.libs.pari - sage: genera = flatten([genera(s, d, even=False) for d in dets for s in signatures]) # long time # optional - sage.libs.pari - sage: all(g == g.discriminant_form().genus(g.signature_pair()) for g in genera) # long time # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: from sage.quadratic_forms.genera.genus import genera + sage: signatures = [(1,0), (1,1), (1,2), (3,0), (0,4)] + sage: dets = range(1, 33) + sage: genera = flatten([genera(s, d, even=False) for d in dets for s in signatures]) # long time + sage: all(g == g.discriminant_form().genus(g.signature_pair()) for g in genera) # long time True """ from sage.quadratic_forms.genera.genus import (Genus_Symbol_p_adic_ring, @@ -756,17 +757,17 @@ def is_genus(self, signature_pair, even=True): EXAMPLES:: sage: L3 = IntegralLattice(3 * Matrix(ZZ, 2, [2,1,1,2])) - sage: L = IntegralLattice("D4").direct_sum(L3) - sage: D = L.discriminant_group() - sage: D.is_genus((6,0)) + sage: L = IntegralLattice("D4").direct_sum(L3) # needs sage.combinat + sage: D = L.discriminant_group() # needs sage.combinat + sage: D.is_genus((6,0)) # needs sage.combinat True Let us see if there is a lattice in the genus defined by the same discriminant form but with a different signature:: - sage: D.is_genus((4,2)) + sage: D.is_genus((4,2)) # needs sage.combinat False - sage: D.is_genus((16,2)) + sage: D.is_genus((16,2)) # needs sage.combinat True """ s_plus = ZZ(signature_pair[0]) @@ -836,33 +837,34 @@ def orthogonal_group(self, gens=None, check=False): sage: D = TorsionQuadraticForm(matrix.identity(2)/2) sage: f = matrix(2, [0,1,1,0]) - sage: D.orthogonal_group(gens=[f]).order() # optional - sage.groups + sage: D.orthogonal_group(gens=[f]).order() # needs sage.groups 2 If no generators are given a slow brute force approach is used to calculate the full orthogonal group:: sage: D = TorsionQuadraticForm(matrix.identity(3)/2) - sage: OD = D.orthogonal_group() # optional - sage.groups - sage: OD.order() # optional - sage.groups + sage: OD = D.orthogonal_group() # needs sage.groups + sage: OD.order() # needs sage.groups 6 - sage: fd = D.hom([D.1, D.0, D.2]) - sage: OD(fd) # optional - sage.groups + sage: fd = D.hom([D.1, D.0, D.2]) # needs sage.symbolic + sage: OD(fd) # needs sage.groups sage.symbolic [0 1 0] [1 0 0] [0 0 1] We compute the kernel of the action of the orthogonal group of `L` on the discriminant group:: - sage: L = IntegralLattice('A4') # optional - sage.combinat - sage: O = L.orthogonal_group() # optional - sage.combinat sage.groups - sage: D = L.discriminant_group() # optional - sage.combinat sage.groups - sage: Obar = D.orthogonal_group(O.gens()) # optional - sage.combinat sage.groups - sage: O.order() # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: L = IntegralLattice('A4') + sage: O = L.orthogonal_group() + sage: D = L.discriminant_group() + sage: Obar = D.orthogonal_group(O.gens()) + sage: O.order() 240 - sage: Obar.order() # optional - sage.combinat sage.groups + sage: Obar.order() 2 - sage: phi = O.hom(Obar.gens()) # optional - sage.combinat sage.groups - sage: phi.kernel().order() # optional - sage.combinat sage.groups + sage: phi = O.hom(Obar.gens()) + sage: phi.kernel().order() 120 """ from sage.groups.fqf_orthogonal import FqfOrthogonalGroup, _isom_fqf @@ -990,13 +992,13 @@ def normal_form(self, partial=False): EXAMPLES:: sage: L1 = IntegralLattice(matrix([[-2,0,0], [0,1,0], [0,0,4]])) - sage: L1.discriminant_group().normal_form() + sage: L1.discriminant_group().normal_form() # needs sage.rings.padics Finite quadratic module over Integer Ring with invariants (2, 4) Gram matrix of the quadratic form with values in Q/Z: [1/2 0] [ 0 1/4] sage: L2 = IntegralLattice(matrix([[-2,0,0], [0,1,0], [0,0,-4]])) - sage: L2.discriminant_group().normal_form() + sage: L2.discriminant_group().normal_form() # needs sage.rings.padics Finite quadratic module over Integer Ring with invariants (2, 4) Gram matrix of the quadratic form with values in Q/Z: [1/2 0] @@ -1008,13 +1010,13 @@ def normal_form(self, partial=False): sage: AL1 = L1.discriminant_group() sage: L2 = IntegralLattice(matrix([[-4,0,0], [0,-4,0], [0,0,2]])) sage: AL2 = L2.discriminant_group() - sage: AL1.normal_form() + sage: AL1.normal_form() # needs sage.rings.padics Finite quadratic module over Integer Ring with invariants (2, 4, 4) Gram matrix of the quadratic form with values in Q/2Z: [1/2 0 0] [ 0 1/4 0] [ 0 0 5/4] - sage: AL2.normal_form() + sage: AL2.normal_form() # needs sage.libs.pari sage.rings.padics Finite quadratic module over Integer Ring with invariants (2, 4, 4) Gram matrix of the quadratic form with values in Q/2Z: [1/2 0 0] @@ -1034,7 +1036,7 @@ def normal_form(self, partial=False): [ 1/12 1/6 1/36 1/9] [ 5/36 1/36 1/36 11/72] [ 1/36 1/9 11/72 1/36] - sage: T.normal_form() + sage: T.normal_form() # needs sage.libs.pari sage.rings.padics Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12) Gram matrix of the quadratic form with values in Q/(1/3)Z: [ 1/6 1/12 0 0 0 0 0 0] @@ -1051,7 +1053,7 @@ def normal_form(self, partial=False): A degenerate case:: sage: T = TorsionQuadraticModule((1/6)*D4dual, D4, modulus=1/36) - sage: T.normal_form() + sage: T.normal_form() # needs sage.libs.pari sage.rings.padics Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12) Gram matrix of the quadratic form with values in Q/(1/18)Z: [1/36 1/72 0 0 0 0 0 0] @@ -1063,8 +1065,10 @@ def normal_form(self, partial=False): [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0] """ - gens = [] from sage.quadratic_forms.genera.normal_form import p_adic_normal_form, _normalize + from sage.rings.padics.factory import Zp + + gens = [] for p in self.annihilator().gen().prime_divisors(): D_p = self.primary_part(p) q_p = D_p.gram_matrix_quadratic() diff --git a/src/sage/modules/tutorial_free_modules.py b/src/sage/modules/tutorial_free_modules.py index d58acd4ae9f..8fe8cd8c7df 100644 --- a/src/sage/modules/tutorial_free_modules.py +++ b/src/sage/modules/tutorial_free_modules.py @@ -40,7 +40,8 @@ sage: F = CombinatorialFreeModule(ZZ, CC); F.an_element() B[1.00000000000000*I] - sage: F = CombinatorialFreeModule(ZZ, Partitions(NonNegativeIntegers(), max_part=3)); F.an_element() + sage: F = CombinatorialFreeModule(ZZ, Partitions(NonNegativeIntegers(), # needs sage.combinat + ....: max_part=3)); F.an_element() 2*B[[]] + 2*B[[1]] + 3*B[[2]] sage: F = CombinatorialFreeModule(ZZ, ['spam', 'eggs', '42']); F.an_element() 3*B['42'] + 2*B['eggs'] + 2*B['spam'] @@ -89,7 +90,9 @@ module:: sage: a = F.basis(); a - Lazy family (Term map from Ring of integers modulo 5 to Free module generated by Ring of integers modulo 5 over Integer Ring(i))_{i in Ring of integers modulo 5} + Lazy family (Term map from Ring of integers modulo 5 + to Free module generated by Ring of integers modulo 5 + over Integer Ring(i))_{i in Ring of integers modulo 5} This gadget models the :class:`family ` `(B_i)_{i \in \ZZ_5}`. In particular, one can run through its elements:: diff --git a/src/sage/modules/vector_callable_symbolic_dense.py b/src/sage/modules/vector_callable_symbolic_dense.py index 306982c2cc3..1929eabcf46 100644 --- a/src/sage/modules/vector_callable_symbolic_dense.py +++ b/src/sage/modules/vector_callable_symbolic_dense.py @@ -69,7 +69,7 @@ def _repr_(self): """ ring = self.coordinate_ring() args = ring.arguments() - repr_x=self.change_ring(SR)._repr_() + repr_x = self.change_ring(SR)._repr_() if len(args) == 1: return "%s |--> %s" % (args[0], repr_x) else: diff --git a/src/sage/modules/vector_complex_double_dense.pyx b/src/sage/modules/vector_complex_double_dense.pyx index 43f3322d627..d9715fbdc82 100644 --- a/src/sage/modules/vector_complex_double_dense.pyx +++ b/src/sage/modules/vector_complex_double_dense.pyx @@ -1,10 +1,11 @@ +# sage.doctest: optional - numpy r""" Dense complex double vectors using a NumPy backend EXAMPLES:: - sage: v = vector(CDF,[(1,-1), (2,pi), (3,5)]) - sage: v + sage: # needs sage.symbolic + sage: v = vector(CDF, [(1,-1), (2,pi), (3,5)]); v (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: type(v) @@ -54,10 +55,9 @@ cdef class Vector_complex_double_dense(Vector_double_dense): EXAMPLES:: - sage: v = vector(CDF,[(1,-1), (2,pi), (3,5)]) - sage: v + sage: v = vector(CDF, [(1,-1), (2,pi), (3,5)]); v # needs sage.symbolic (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) - sage: v*v # rel tol 1e-15 + sage: v*v # rel tol 1e-15 # needs sage.symbolic -21.86960440108936 + 40.56637061435917*I """ def __cinit__(self, parent, entries, coerce=True, copy=True): diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx index 2d581606980..551da99669e 100644 --- a/src/sage/modules/vector_double_dense.pyx +++ b/src/sage/modules/vector_double_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy r""" Dense vectors using a NumPy backend @@ -6,8 +7,8 @@ Complex Double Field EXAMPLES:: - sage: v = vector(CDF,[(1,-1), (2,pi), (3,5)]) - sage: v + sage: # needs sage.symbolic + sage: v = vector(CDF,[(1,-1), (2,pi), (3,5)]); v (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: type(v) @@ -18,6 +19,7 @@ EXAMPLES:: (5.0, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: loads(dumps(v)) == v True + sage: v = vector(RDF, [1,2,3,4]); v (1.0, 2.0, 3.0, 4.0) sage: loads(dumps(v)) == v @@ -471,10 +473,10 @@ cdef class Vector_double_dense(Vector_numpy_dense): # p = 0 returns integer *count* of non-zero entries return RDF(n) - ############################# # statistics ############################# + def mean(self): """ Calculate the arithmetic mean of the vector. diff --git a/src/sage/modules/vector_integer_dense.pyx b/src/sage/modules/vector_integer_dense.pyx index 22709019993..177ada5dea1 100644 --- a/src/sage/modules/vector_integer_dense.pyx +++ b/src/sage/modules/vector_integer_dense.pyx @@ -314,10 +314,10 @@ cdef class Vector_integer_dense(free_module_element.FreeModuleElement): sage: A = random_matrix(ZZ,1,3) sage: v = A.row(0) - sage: vs = singular(v) - sage: vs._repr_() == '{},\n{},\n{}'.format(*v) + sage: vs = singular(v) # needs sage.libs.singular + sage: vs._repr_() == '{},\n{},\n{}'.format(*v) # needs sage.libs.singular True - sage: vs.type() + sage: vs.type() # needs sage.libs.singular 'intvec' """ if singular is None: diff --git a/src/sage/modules/vector_modn_dense.pyx b/src/sage/modules/vector_modn_dense.pyx index 7b4123709e7..8608672031d 100644 --- a/src/sage/modules/vector_modn_dense.pyx +++ b/src/sage/modules/vector_modn_dense.pyx @@ -46,7 +46,7 @@ We make a large zero vector:: We multiply a vector by a matrix:: sage: a = (GF(97)^5)(range(5)) - sage: m = matrix(GF(97),5,range(25)) + sage: m = matrix(GF(97), 5, range(25)) sage: a*m (53, 63, 73, 83, 93) @@ -58,20 +58,20 @@ TESTS:: sage: v = vector(Integers(389), [1,2,3,4,5]) sage: loads(dumps(v)) == v True - sage: v = vector(Integers(next_prime(10^20)), [1,2,3,4,5]) + sage: v = vector(Integers(next_prime(10^20)), [1,2,3,4,5]) # needs sage.libs.pari sage: loads(dumps(v)) == v True - sage: K = GF(previous_prime(2^31)) - sage: v = vector(K, [42]); type(v[0]) + sage: K = GF(previous_prime(2^31)) # needs sage.rings.finite_rings + sage: v = vector(K, [42]); type(v[0]) # needs sage.rings.finite_rings - sage: ~v[0] + sage: ~v[0] # needs sage.rings.finite_rings 2096353084 - sage: K = GF(next_prime(2^31)) - sage: v = vector(K, [42]); type(v[0]) + sage: K = GF(next_prime(2^31)) # needs sage.rings.finite_rings + sage: v = vector(K, [42]); type(v[0]) # needs sage.rings.finite_rings - sage: ~v[0] + sage: ~v[0] # needs sage.rings.finite_rings 1482786336 sage: w = vector(GF(11), [-1,0,0,0]) @@ -81,6 +81,7 @@ TESTS:: Test that :trac:`28042` is fixed:: + sage: # needs sage.rings.finite_rings sage: p = 193379 sage: K = GF(p) sage: a = K(1) @@ -88,7 +89,7 @@ Test that :trac:`28042` is fixed:: sage: c = K(109320) sage: d = K(167667) sage: e = 103937 - sage: a*c+b*d-e + sage: a*c + b*d - e 102041 sage: vector([a,b]) * vector([c,d]) - e 102041 diff --git a/src/sage/modules/vector_modn_sparse.pyx b/src/sage/modules/vector_modn_sparse.pyx index 746f9897db2..e2dd1d7c1a6 100644 --- a/src/sage/modules/vector_modn_sparse.pyx +++ b/src/sage/modules/vector_modn_sparse.pyx @@ -7,8 +7,6 @@ from cysignals.memory cimport sig_malloc, sig_free -from sage.modules.vector_modn_sparse cimport c_vector_modint - cdef int allocate_c_vector_modint(c_vector_modint* v, Py_ssize_t num_nonzero) except -1: """ diff --git a/src/sage/modules/vector_numpy_dense.pyx b/src/sage/modules/vector_numpy_dense.pyx index 6c72c98c0c2..f0e2224b96d 100644 --- a/src/sage/modules/vector_numpy_dense.pyx +++ b/src/sage/modules/vector_numpy_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy r""" Dense vectors using a NumPy backend. diff --git a/src/sage/modules/vector_numpy_integer_dense.pyx b/src/sage/modules/vector_numpy_integer_dense.pyx index b5cca74081f..ba3537436d5 100644 --- a/src/sage/modules/vector_numpy_integer_dense.pyx +++ b/src/sage/modules/vector_numpy_integer_dense.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - numpy r""" Dense integer vectors using a NumPy backend. diff --git a/src/sage/modules/vector_real_double_dense.pyx b/src/sage/modules/vector_real_double_dense.pyx index 7a3d674e1eb..bf7c75f1605 100644 --- a/src/sage/modules/vector_real_double_dense.pyx +++ b/src/sage/modules/vector_real_double_dense.pyx @@ -1,10 +1,11 @@ +# sage.doctest: optional - numpy r""" Dense real double vectors using a NumPy backend EXAMPLES:: - sage: v = vector(RDF,[1, pi, sqrt(2)]) - sage: v + sage: # needs sage.symbolic + sage: v = vector(RDF, [1, pi, sqrt(2)]); v (1.0, 3.141592653589793, 1.414213562373095) sage: type(v) diff --git a/src/sage/modules/vector_space_morphism.py b/src/sage/modules/vector_space_morphism.py index 8044ed8dd4c..2685462a74e 100644 --- a/src/sage/modules/vector_space_morphism.py +++ b/src/sage/modules/vector_space_morphism.py @@ -29,7 +29,7 @@ Vector space morphism represented by the matrix: [-1 2 3] [ 4 2 0] - Domain: Vector space of dimension 2 over Rational Field + Domain: Vector space of dimension 2 over Rational Field Codomain: Vector space of dimension 3 over Rational Field sage: phi([2, -3]) (-14, -2, 6) @@ -38,6 +38,7 @@ linear transformation, along with explicit descriptions of the domain and codomain. :: + sage: # needs sage.symbolic sage: F = Integers(13) sage: D = F^3 sage: C = F^2 @@ -65,11 +66,12 @@ [ 2 -1] [ 4 0] [ 3 7] - Domain: Vector space of dimension 4 over Rational Field + Domain: Vector space of dimension 4 over Rational Field Codomain: Vector space of dimension 2 over Rational Field A homomorphism may also be created via a method on the domain. :: + sage: # needs sage.rings.number_field sage.symbolic sage: F = QQ[sqrt(3)] sage: a = F.gen(0) sage: D = F^2 @@ -80,8 +82,10 @@ Vector space morphism represented by the matrix: [ sqrt3 1] [2*sqrt3 2] - Domain: Vector space of dimension 2 over Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878? - Codomain: Vector space of dimension 2 over Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878? + Domain: Vector space of dimension 2 over Number Field in sqrt3 + with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878? + Codomain: Vector space of dimension 2 over Number Field in sqrt3 + with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878? sage: psi([1, 4]) (9*sqrt3, 9) @@ -149,10 +153,10 @@ matrix representation used to represent linear transformations are relative to the bases of both the domain and codomain. :: - sage: A = graphs.PetersenGraph().adjacency_matrix() + sage: A = graphs.PetersenGraph().adjacency_matrix() # needs sage.graphs sage: V = QQ^10 - sage: phi = linear_transformation(V, V, A) - sage: phi + sage: phi = linear_transformation(V, V, A) # needs sage.graphs + sage: phi # needs sage.graphs Vector space morphism represented by the matrix: [0 1 0 0 1 1 0 0 0 0] [1 0 1 0 0 0 1 0 0 0] @@ -164,9 +168,10 @@ [0 0 1 0 0 1 0 0 0 1] [0 0 0 1 0 1 1 0 0 0] [0 0 0 0 1 0 1 1 0 0] - Domain: Vector space of dimension 10 over Rational Field + Domain: Vector space of dimension 10 over Rational Field Codomain: Vector space of dimension 10 over Rational Field + sage: # needs sage.graphs sage: B1 = [V.gen(i) + V.gen(i+1) for i in range(9)] + [V.gen(9)] sage: B2 = [V.gen(0)] + [-V.gen(i-1) + V.gen(i) for i in range(1,10)] sage: D = V.subspace_with_basis(B1) @@ -185,42 +190,42 @@ [6 6 6 5 4 4 2 1 1 1] [6 6 6 6 5 4 3 1 0 0] [3 3 3 3 3 2 2 1 0 0] - Domain: Vector space of degree 10 and dimension 10 over Rational Field - User basis matrix: - [1 1 0 0 0 0 0 0 0 0] - [0 1 1 0 0 0 0 0 0 0] - [0 0 1 1 0 0 0 0 0 0] - [0 0 0 1 1 0 0 0 0 0] - [0 0 0 0 1 1 0 0 0 0] - [0 0 0 0 0 1 1 0 0 0] - [0 0 0 0 0 0 1 1 0 0] - [0 0 0 0 0 0 0 1 1 0] - [0 0 0 0 0 0 0 0 1 1] - [0 0 0 0 0 0 0 0 0 1] + Domain: Vector space of degree 10 and dimension 10 over Rational Field + User basis matrix: + [1 1 0 0 0 0 0 0 0 0] + [0 1 1 0 0 0 0 0 0 0] + [0 0 1 1 0 0 0 0 0 0] + [0 0 0 1 1 0 0 0 0 0] + [0 0 0 0 1 1 0 0 0 0] + [0 0 0 0 0 1 1 0 0 0] + [0 0 0 0 0 0 1 1 0 0] + [0 0 0 0 0 0 0 1 1 0] + [0 0 0 0 0 0 0 0 1 1] + [0 0 0 0 0 0 0 0 0 1] Codomain: Vector space of degree 10 and dimension 10 over Rational Field - User basis matrix: - [ 1 0 0 0 0 0 0 0 0 0] - [-1 1 0 0 0 0 0 0 0 0] - [ 0 -1 1 0 0 0 0 0 0 0] - [ 0 0 -1 1 0 0 0 0 0 0] - [ 0 0 0 -1 1 0 0 0 0 0] - [ 0 0 0 0 -1 1 0 0 0 0] - [ 0 0 0 0 0 -1 1 0 0 0] - [ 0 0 0 0 0 0 -1 1 0 0] - [ 0 0 0 0 0 0 0 -1 1 0] - [ 0 0 0 0 0 0 0 0 -1 1] + User basis matrix: + [ 1 0 0 0 0 0 0 0 0 0] + [-1 1 0 0 0 0 0 0 0 0] + [ 0 -1 1 0 0 0 0 0 0 0] + [ 0 0 -1 1 0 0 0 0 0 0] + [ 0 0 0 -1 1 0 0 0 0 0] + [ 0 0 0 0 -1 1 0 0 0 0] + [ 0 0 0 0 0 -1 1 0 0 0] + [ 0 0 0 0 0 0 -1 1 0 0] + [ 0 0 0 0 0 0 0 -1 1 0] + [ 0 0 0 0 0 0 0 0 -1 1] An endomorphism is a linear transformation with an equal domain and codomain, and here each needs to have the same basis. We are using a matrix that has well-behaved eigenvalues, as part of showing that these do not change as the representation changes. :: + sage: # needs sage.graphs sage: A = graphs.PetersenGraph().adjacency_matrix() sage: V = QQ^10 sage: phi = linear_transformation(V, V, A) sage: phi.eigenvalues() [3, -2, -2, -2, -2, 1, 1, 1, 1, 1] - sage: B1 = [V.gen(i) + V.gen(i+1) for i in range(9)] + [V.gen(9)] sage: C = V.subspace_with_basis(B1) sage: zeta = phi.restrict(C) @@ -236,31 +241,30 @@ [ 0 0 1 0 0 2 -1 1 -1 2] [ 0 0 0 1 0 1 1 0 0 0] [ 0 0 0 0 1 -1 2 -1 1 -1] - Domain: Vector space of degree 10 and dimension 10 over Rational Field - User basis matrix: - [1 1 0 0 0 0 0 0 0 0] - [0 1 1 0 0 0 0 0 0 0] - [0 0 1 1 0 0 0 0 0 0] - [0 0 0 1 1 0 0 0 0 0] - [0 0 0 0 1 1 0 0 0 0] - [0 0 0 0 0 1 1 0 0 0] - [0 0 0 0 0 0 1 1 0 0] - [0 0 0 0 0 0 0 1 1 0] - [0 0 0 0 0 0 0 0 1 1] - [0 0 0 0 0 0 0 0 0 1] + Domain: Vector space of degree 10 and dimension 10 over Rational Field + User basis matrix: + [1 1 0 0 0 0 0 0 0 0] + [0 1 1 0 0 0 0 0 0 0] + [0 0 1 1 0 0 0 0 0 0] + [0 0 0 1 1 0 0 0 0 0] + [0 0 0 0 1 1 0 0 0 0] + [0 0 0 0 0 1 1 0 0 0] + [0 0 0 0 0 0 1 1 0 0] + [0 0 0 0 0 0 0 1 1 0] + [0 0 0 0 0 0 0 0 1 1] + [0 0 0 0 0 0 0 0 0 1] Codomain: Vector space of degree 10 and dimension 10 over Rational Field - User basis matrix: - [1 1 0 0 0 0 0 0 0 0] - [0 1 1 0 0 0 0 0 0 0] - [0 0 1 1 0 0 0 0 0 0] - [0 0 0 1 1 0 0 0 0 0] - [0 0 0 0 1 1 0 0 0 0] - [0 0 0 0 0 1 1 0 0 0] - [0 0 0 0 0 0 1 1 0 0] - [0 0 0 0 0 0 0 1 1 0] - [0 0 0 0 0 0 0 0 1 1] - [0 0 0 0 0 0 0 0 0 1] - + User basis matrix: + [1 1 0 0 0 0 0 0 0 0] + [0 1 1 0 0 0 0 0 0 0] + [0 0 1 1 0 0 0 0 0 0] + [0 0 0 1 1 0 0 0 0 0] + [0 0 0 0 1 1 0 0 0 0] + [0 0 0 0 0 1 1 0 0 0] + [0 0 0 0 0 0 1 1 0 0] + [0 0 0 0 0 0 0 1 1 0] + [0 0 0 0 0 0 0 0 1 1] + [0 0 0 0 0 0 0 0 0 1] sage: zeta.eigenvalues() [3, -2, -2, -2, -2, 1, 1, 1, 1, 1] @@ -495,6 +499,7 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): Domain: Vector space of dimension 3 over Rational Field Codomain: Vector space of dimension 2 over Rational Field + sage: # needs sage.symbolic sage: x, y, z = var('x y z') sage: h(x, y, z) = [2*x + z, 5*y] sage: zeta = linear_transformation(QQ^3, QQ^2, h) @@ -503,12 +508,12 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): [2 0] [0 5] [1 0] - Domain: Vector space of dimension 3 over Rational Field + Domain: Vector space of dimension 3 over Rational Field Codomain: Vector space of dimension 2 over Rational Field sage: phi == rho True - sage: rho == zeta + sage: rho == zeta # needs sage.symbolic True @@ -536,6 +541,7 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): [2 5] [3 7] + sage: # needs sage.symbolic sage: s, t = var('s t') sage: h(s, t) = [(-4/5)*s + (1/5)*t, (97/5)*s + (-13/5)*t] sage: zeta = linear_transformation(D, C, h) @@ -546,8 +552,9 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): Finally, we can give an explicit list of images for the basis elements of the domain. :: + sage: # needs sage.rings.number_field sage: x = polygen(QQ) - sage: F. = NumberField(x^3+x+1) + sage: F. = NumberField(x^3 + x + 1) sage: u = vector(F, [1, a, a^2]) sage: v = vector(F, [a, a^2, 2]) sage: w = u + v @@ -655,26 +662,27 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): A Sage symbolic function can come in a variety of forms that are not representative of a linear transformation. :: - sage: x, y = var('x, y') - sage: f(x, y) = [y, x, y] - sage: linear_transformation(QQ^3, QQ^3, f) + sage: x, y = var('x, y') # needs sage.symbolic + sage: f(x, y) = [y, x, y] # needs sage.symbolic + sage: linear_transformation(QQ^3, QQ^3, f) # needs sage.symbolic Traceback (most recent call last): ... ValueError: symbolic function has the wrong number of inputs for domain - sage: linear_transformation(QQ^2, QQ^2, f) + sage: linear_transformation(QQ^2, QQ^2, f) # needs sage.symbolic Traceback (most recent call last): ... ValueError: symbolic function has the wrong number of outputs for codomain - sage: x, y = var('x y') - sage: f(x, y) = [y, x*y] - sage: linear_transformation(QQ^2, QQ^2, f) + sage: x, y = var('x y') # needs sage.symbolic + sage: f(x, y) = [y, x*y] # needs sage.symbolic + sage: linear_transformation(QQ^2, QQ^2, f) # needs sage.symbolic Traceback (most recent call last): ... ValueError: symbolic function must be linear in all the inputs: unable to convert y to a rational + sage: # needs sage.symbolic sage: x, y = var('x y') sage: f(x, y) = [x, 2*y] sage: C = (QQ^2).span([vector(QQ, [1, 1])]) @@ -822,7 +830,7 @@ def __init__(self, homspace, A, side="left"): [0 1] [2 3] [4 5] - Domain: Vector space of dimension 3 over Rational Field + Domain: Vector space of dimension 3 over Rational Field Codomain: Vector space of dimension 2 over Rational Field See the constructor, @@ -902,6 +910,7 @@ def is_invertible(self): A non-invertible linear transformation, an endomorphism of a vector space over a finite field. :: + sage: # needs sage.rings.finite_rings sage: F. = GF(11^2) sage: A = matrix(F, [[6*a + 3, 8*a + 2, 10*a + 3], ....: [2*a + 7, 4*a + 3, 2*a + 3], diff --git a/src/sage/modules/vector_symbolic_dense.py b/src/sage/modules/vector_symbolic_dense.py index e4d9efff0b3..ce134c0462e 100644 --- a/src/sage/modules/vector_symbolic_dense.py +++ b/src/sage/modules/vector_symbolic_dense.py @@ -108,6 +108,7 @@ def apply(self, *args, **kwds): class Vector_symbolic_dense(free_module_element.FreeModuleElement_generic_dense): pass + # Add elementwise methods. for method in ['simplify', 'simplify_factorial', 'simplify_log', 'simplify_rational', diff --git a/src/sage/modules/vector_symbolic_sparse.py b/src/sage/modules/vector_symbolic_sparse.py index 30ec55214c6..73cb41ae611 100644 --- a/src/sage/modules/vector_symbolic_sparse.py +++ b/src/sage/modules/vector_symbolic_sparse.py @@ -110,6 +110,7 @@ def apply(self, *args, **kwds): class Vector_symbolic_sparse(free_module_element.FreeModuleElement_generic_sparse): pass + # Add elementwise methods. for method in ['simplify', 'simplify_factorial', 'simplify_log', 'simplify_rational', diff --git a/src/sage/modules/with_basis/cell_module.py b/src/sage/modules/with_basis/cell_module.py index c51d43c32b6..66d72f648f8 100644 --- a/src/sage/modules/with_basis/cell_module.py +++ b/src/sage/modules/with_basis/cell_module.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat r""" Cell modules """ diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index d5f2159b9e8..90f7b8ec580 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -77,9 +77,9 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: [i for i in sorted(f)] [('a', 1), ('c', 3)] - sage: s = SymmetricFunctions(QQ).schur() - sage: a = s([2,1]) + s([3]) - sage: [i for i in sorted(a)] + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat + sage: a = s([2,1]) + s([3]) # needs sage.combinat + sage: [i for i in sorted(a)] # needs sage.combinat [([2, 1], 1), ([3], 1)] """ return iter(self._monomial_coefficients.items()) @@ -102,6 +102,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: 'b' in f False + sage: # needs sage.combinat sage: s = SymmetricFunctions(QQ).schur() sage: a = s([2,1]) + s([3]) sage: Partition([2,1]) in a @@ -128,6 +129,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: hash(f) == hash(B['a'] + 4*B['c']) False + sage: # needs sage.combinat sage: F = RootSystem(['A',2]).ambient_space() sage: f = F.simple_root(0) sage: hash(f) == hash(F.simple_root(0)) @@ -259,6 +261,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): :: + sage: # needs sage.combinat sage: s = SymmetricFunctions(QQ).schur() sage: a = s([2,1])+2*s([3,2]) sage: d = a.monomial_coefficients() @@ -342,6 +345,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): """ TESTS:: + sage: # needs sage.combinat sage: M = QuasiSymmetricFunctions(QQ).M() sage: ascii_art(M[1,3]**2) # indirect doctest 4*M + 2*M + 2*M + 2*M + 2*M + M @@ -419,8 +423,8 @@ cdef class IndexedFreeModuleElement(ModuleElement): """ TESTS:: - sage: M = QuasiSymmetricFunctions(QQ).M() - sage: unicode_art(M[1,1]**2) # indirect doctest + sage: M = QuasiSymmetricFunctions(QQ).M() # needs sage.combinat + sage: unicode_art(M[1,1]**2) # indirect doctest # needs sage.combinat 6*M + 2*M + 2*M + 2*M + M ┌┐ ┌┬┐ ┌┐ ┌┐ ┌┬┐ ├┤ ├┼┘ ┌┼┤ ├┤ ┌┼┼┘ @@ -430,7 +434,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): The following test failed before :trac:`26850`:: - sage: unicode_art([M.zero()]) # indirect doctest + sage: unicode_art([M.zero()]) # indirect doctest # needs sage.combinat [ 0 ] """ from sage.misc.repr import coeff_repr @@ -501,9 +505,9 @@ cdef class IndexedFreeModuleElement(ModuleElement): :: - sage: QS3 = SymmetricGroupAlgebra(QQ,3) - sage: a = 2 + QS3([2,1,3]) - sage: latex(a) #indirect doctest + sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # needs sage.combinat + sage: a = 2 + QS3([2,1,3]) # needs sage.combinat + sage: latex(a) #indirect doctest # needs sage.combinat 2 [1, 2, 3] + [2, 1, 3] :: @@ -563,6 +567,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): :: + sage: # needs sage.combinat sage: s = SymmetricFunctions(QQ).schur() sage: a = s([2,1]) sage: b = s([1,1,1]) @@ -590,6 +595,8 @@ cdef class IndexedFreeModuleElement(ModuleElement): Traceback (most recent call last): ... TypeError: do not know how to make x (= 0) an element of self (=Free module generated by {1, 2, 3} over Rational Field) + + sage: # needs sage.combinat sage: F = AlgebrasWithBasis(QQ).example() sage: F.one() == 1 True @@ -600,10 +607,10 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: int(2) == 2 * F.one() True - sage: S = SymmetricFunctions(QQ); s = S.s(); p = S.p() - sage: p[2] == s[2] - s[1, 1] + sage: S = SymmetricFunctions(QQ); s = S.s(); p = S.p() # needs sage.combinat + sage: p[2] == s[2] - s[1, 1] # needs sage.combinat True - sage: p[2] == s[2] + sage: p[2] == s[2] # needs sage.combinat False This feature is disputable, in particular since it can make @@ -613,6 +620,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): can vary because their indices are incomparable with ``cmp``. The following test did fail before :trac:`12489` :: + sage: # needs sage.combinat sage: F = CombinatorialFreeModule(QQ, Subsets([1,2,3])) sage: x = F.an_element() sage: (x+F.zero()).terms() # random @@ -625,7 +633,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): TESTS:: sage: TestSuite(F1).run() - sage: TestSuite(F).run() + sage: TestSuite(F).run() # needs sage.combinat """ cdef IndexedFreeModuleElement elt = other @@ -653,6 +661,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): :: + sage: # needs sage.combinat sage: s = SymmetricFunctions(QQ).schur() sage: s([2,1]) + s([5,4]) # indirect doctest s[2, 1] + s[5, 4] @@ -676,8 +685,8 @@ cdef class IndexedFreeModuleElement(ModuleElement): :: - sage: s = SymmetricFunctions(QQ).schur() - sage: -s([2,1]) # indirect doctest + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat + sage: -s([2,1]) # indirect doctest # needs sage.combinat -s[2, 1] """ return type(self)(self._parent, negate(self._monomial_coefficients)) @@ -693,8 +702,8 @@ cdef class IndexedFreeModuleElement(ModuleElement): :: - sage: s = SymmetricFunctions(QQ).schur() - sage: s([2,1]) - s([5,4]) # indirect doctest + sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat + sage: s([2,1]) - s([5,4]) # indirect doctest # needs sage.combinat s[2, 1] - s[5, 4] """ return type(self)(self._parent, @@ -708,6 +717,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): EXAMPLES:: + sage: # needs sage.combinat sage: p = Partition([2,1]) sage: q = Partition([1,1,1]) sage: s = SymmetricFunctions(QQ).schur() @@ -765,6 +775,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): More examples:: + sage: # needs sage.combinat sage: QS3 = SymmetricGroupAlgebra(QQ, 3) sage: a = 2*QS3([1,2,3]) + 4*QS3([3,2,1]) sage: a._vector_() @@ -781,7 +792,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): If ``new_base_ring`` is specified, then a vector over ``new_base_ring`` is returned:: - sage: a._vector_(RDF) + sage: a._vector_(RDF) # needs sage.combinat (2.0, 0.0, 0.0, 0.0, 0.0, 4.0) .. NOTE:: @@ -864,6 +875,7 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: (3/2)*el 3/2*B[[3, 1, 2]] + sage: # needs sage.combinat sage: P. = QQ['q'] sage: F = FractionField(P) sage: V = CombinatorialFreeModule(F, Words()) diff --git a/src/sage/modules/with_basis/invariant.py b/src/sage/modules/with_basis/invariant.py index 12565a411e2..71a4c938424 100644 --- a/src/sage/modules/with_basis/invariant.py +++ b/src/sage/modules/with_basis/invariant.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups r""" Invariant modules """ diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index d6b4586ce83..b94629a8dfe 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -691,9 +691,9 @@ def __init__(self, triangular="upper", unitriangular=False, self._inverse_on_support = inverse_on_support if invertible is None and (domain.basis().keys() == codomain.basis().keys()) and \ - (self._inverse_on_support==identity or domain in Modules.FiniteDimensional): + (self._inverse_on_support == identity or domain in Modules.FiniteDimensional): invertible = True - self._invertible=invertible + self._invertible = invertible def _richcmp_(self, other, op): r""" @@ -772,10 +772,10 @@ def _test_triangular(self, **options): bs, co = self._dominant_item(on_basis(x)) if self._unitriangular: tester.assertEqual(co, self.domain().base_ring().one(), - LazyFormat("morphism is not unitriangular on %s")%(x)) + LazyFormat("morphism is not unitriangular on %s") % (x)) xback = self._inverse_on_support(bs) tester.assertEqual(x, xback, - LazyFormat("morphism is not triangular on %s")%(x)) + LazyFormat("morphism is not triangular on %s") % (x)) def __invert__(self): """ @@ -1452,12 +1452,12 @@ def __init__(self, domain, diagonal, codomain=None, category=None): "and the same basis indexing") from collections.abc import Callable if not isinstance(diagonal, Callable): - raise ValueError("diagonal (=%s) should be a function"%diagonal) + raise ValueError("diagonal (=%s) should be a function" % diagonal) if category is None: category = ModulesWithBasis(domain.base_ring()) ModuleMorphismByLinearity.__init__( self, domain=domain, codomain=codomain, category=category) - self._diagonal=diagonal + self._diagonal = diagonal def _richcmp_(self, other, op): r""" diff --git a/src/sage/modules/with_basis/representation.py b/src/sage/modules/with_basis/representation.py index 44b9f6115e2..a781fc39ec3 100644 --- a/src/sage/modules/with_basis/representation.py +++ b/src/sage/modules/with_basis/representation.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups """ Representations of a semigroup diff --git a/src/sage/monoids/string_monoid.py b/src/sage/monoids/string_monoid.py index 5f4e3819b5e..91cb82e4229 100644 --- a/src/sage/monoids/string_monoid.py +++ b/src/sage/monoids/string_monoid.py @@ -247,6 +247,7 @@ def encoding(self, S, padic=False): # """ # return 2 + BinaryStrings = BinaryStringMonoid @@ -309,6 +310,7 @@ def __call__(self, x, check=True): else: raise TypeError("Argument x (= %s) is of the wrong type." % x) + OctalStrings = OctalStringMonoid @@ -421,6 +423,7 @@ def encoding(self, S, padic=False): hex_string.extend(hex_chars) return self(hex_string) + HexadecimalStrings = HexadecimalStringMonoid @@ -487,6 +490,7 @@ def __call__(self, x, check=True): else: raise TypeError("Argument x (= %s) is of the wrong type." % x) + Radix64Strings = Radix64StringMonoid @@ -798,4 +802,5 @@ def encoding(self, S): """ return self(strip_encoding(S)) + AlphabeticStrings = AlphabeticStringMonoid diff --git a/src/sage/numerical/backends/generic_backend.pyx b/src/sage/numerical/backends/generic_backend.pyx index 547dbea951a..74cc99cb9e5 100644 --- a/src/sage/numerical/backends/generic_backend.pyx +++ b/src/sage/numerical/backends/generic_backend.pyx @@ -721,7 +721,7 @@ cdef class GenericBackend: tester = p._tester(**options) # From doctest of GenericBackend.solve: tester.assertIsNone(p.add_linear_constraints(5, 0, None)) - tester.assertIsNone(p.add_col(list(xrange(5)), list(xrange(5)))) + tester.assertIsNone(p.add_col(list(range(5)), list(range(5)))) tester.assertEqual(p.solve(), 0) tester.assertIsNone(p.objective_coefficient(0,1)) from sage.numerical.mip import MIPSolverException @@ -1288,8 +1288,8 @@ cdef class GenericBackend: del cp self._do_test_problem_data(tester, cpcp) - # TODO: We should have a more systematic way of generating MIPs for testing. + @classmethod def _test_copy_some_mips(cls, tester=None, **options): p = cls() # fresh instance of the backend @@ -1299,7 +1299,7 @@ cdef class GenericBackend: p.add_linear_constraints(5, 0, None) try: # p.add_col(range(5), range(5)) -- bad test because COIN sparsifies the 0s away on copy - p.add_col(list(xrange(5)), list(xrange(1, 6))) + p.add_col(list(range(5)), list(range(1, 6))) except NotImplementedError: # Gurobi does not implement add_col pass diff --git a/src/sage/numerical/gauss_legendre.pyx b/src/sage/numerical/gauss_legendre.pyx index 5325797c7aa..96708c5b1ac 100644 --- a/src/sage/numerical/gauss_legendre.pyx +++ b/src/sage/numerical/gauss_legendre.pyx @@ -117,8 +117,8 @@ def nodes_uncached(degree, prec): raise ValueError("degree=%s not supported (degree must be 3 or even)" % degree) R = RealField(int(prec*3/2)) Rout = RealField(prec) - mpfr_init2(u,R.__prec) - mpfr_init2(v,R.__prec) + mpfr_init2(u,R._prec) + mpfr_init2(v,R._prec) ZERO = R.zero() ONE = R.one() HALF = ONE/2 diff --git a/src/sage/numerical/linear_functions.pyx b/src/sage/numerical/linear_functions.pyx index 5549ff436f5..f3fc6fe419c 100644 --- a/src/sage/numerical/linear_functions.pyx +++ b/src/sage/numerical/linear_functions.pyx @@ -1579,7 +1579,10 @@ cdef class LinearConstraint(LinearFunctionOrConstraint): while True: yield (lhs, rhs) lhs = rhs - rhs = next(term_iter) + try: + rhs = next(term_iter) + except StopIteration: + return def inequalities(self): """ @@ -1612,7 +1615,10 @@ cdef class LinearConstraint(LinearFunctionOrConstraint): while True: yield (lhs, rhs) lhs = rhs - rhs = next(term_iter) + try: + rhs = next(term_iter) + except StopIteration: + return def _repr_(self): r""" diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index dae234c15bf..3711d9562cf 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -993,11 +993,11 @@ cdef class MixedIntegerLinearProgram(SageObject): cdef str s cdef GenericBackend b = self._backend - result = list() + result = [] # If indices is None, we actually want to return all constraints if indices is None: - indices = list(xrange(b.nrows())) + indices = list(range(b.nrows())) # Only one constraint if isinstance(indices, (int, Integer)): diff --git a/src/sage/parallel/decorate.py b/src/sage/parallel/decorate.py index 97c612b4e45..5b8572d3f60 100644 --- a/src/sage/parallel/decorate.py +++ b/src/sage/parallel/decorate.py @@ -107,8 +107,8 @@ def __call__(self, f): sage: from sage.parallel.decorate import Parallel sage: p = Parallel() - sage: f = x^2-1 - sage: p(f) + sage: f = x^2 - 1 # needs sage.symbolic + sage: p(f) # needs sage.symbolic sage: P = sage.parallel.decorate.Parallel() @@ -342,7 +342,7 @@ def parallel(p_iter='fork', ncpus=None, **kwds): sage: @parallel(ncpus=3, timeout=10) ....: def fac(n): return factor(2^n-1) - sage: for X, Y in sorted(list(fac([101,119,151,197,209]))): print((X,Y)) + sage: for X, Y in sorted(list(fac([101,119,151,197,209]))): print((X,Y)) # needs sage.libs.pari (((101,), {}), 7432339208719 * 341117531003194129) (((119,), {}), 127 * 239 * 20231 * 131071 * 62983048367 * 131105292137) (((151,), {}), 18121 * 55871 * 165799 * 2332951 * 7289088383388253664437433) @@ -531,6 +531,7 @@ def fork(f=None, timeout=0, verbose=False): We illustrate that the state of the pexpect interface is not altered by forked functions (they get their own new pexpect interfaces!):: + sage: # needs sage.libs.pari sage: gp.eval('a = 5') '5' sage: @fork() @@ -545,21 +546,21 @@ def fork(f=None, timeout=0, verbose=False): We illustrate that the forked function has its own pexpect interface:: - sage: gp.eval('a = 15') + sage: gp.eval('a = 15') # needs sage.libs.pari '15' sage: @fork() ....: def g(): return gp.eval('a') - sage: g() + sage: g() # needs sage.libs.pari 'a' We illustrate that segfaulting subprocesses are no trouble at all:: - sage: cython('def f(): print(0)') # optional - sage.misc.cython + sage: cython('def f(): print(0)') # needs sage.misc.cython sage: @fork ....: def g(): ....: os.environ["CYSIGNALS_CRASH_NDEBUG"]="yes" # skip enhanced backtrace (it is slow) ....: f() - sage: print("this works"); g() # optional - sage.misc.cython + sage: print("this works"); g() # needs sage.misc.cython this works... ------------------------------------------------------------------------ diff --git a/src/sage/parallel/map_reduce.py b/src/sage/parallel/map_reduce.py index 47833d9f386..11e0673ee91 100644 --- a/src/sage/parallel/map_reduce.py +++ b/src/sage/parallel/map_reduce.py @@ -184,8 +184,8 @@ Compare:: - sage: from sage.combinat.q_analogues import q_factorial - sage: q_factorial(5) + sage: from sage.combinat.q_analogues import q_factorial # needs sage.combinat + sage: q_factorial(5) # needs sage.combinat q^10 + 4*q^9 + 9*q^8 + 15*q^7 + 20*q^6 + 22*q^5 + 20*q^4 + 15*q^3 + 9*q^2 + 4*q + 1 * **Listing the objects.** One can also compute the list of objects in a @@ -1653,14 +1653,14 @@ def steal(self): sage: EX = RESetMPExample(maxl=6) sage: EX.setup_workers(2) + sage: # known bug (Issue #27537) sage: w0, w1 = EX._workers sage: w0._todo.append(42) sage: thief0 = Thread(target = w0._thief, name="Thief") - sage: thief0.start() # known bug (Issue #27537) - - sage: w1.steal() # known bug (Issue #27537) + sage: thief0.start() + sage: w1.steal() 42 - sage: w0._todo # known bug (Issue #27537) + sage: w0._todo deque([]) """ self._mapred._signal_task_done() diff --git a/src/sage/parallel/use_fork.py b/src/sage/parallel/use_fork.py index bf38df167f9..ce240acf9d8 100644 --- a/src/sage/parallel/use_fork.py +++ b/src/sage/parallel/use_fork.py @@ -301,7 +301,12 @@ def _subprocess(self, f, dir, args, kwds={}): # The pexpect interfaces (and objects defined in them) are # not valid. if self.reset_interfaces: - sage.interfaces.quit.invalidate_all() + try: + from sage.interfaces.quit import invalidate_all + except ImportError: + pass + else: + invalidate_all() # Now evaluate the function f. value = f(*args, **kwds) diff --git a/src/sage/plot/animate.py b/src/sage/plot/animate.py index 49f2ecd87d5..c917452e2be 100644 --- a/src/sage/plot/animate.py +++ b/src/sage/plot/animate.py @@ -327,7 +327,7 @@ def _repr_(self): num = len(self) except TypeError: num = "unknown number of" - return "Animation with %s frames"%num + return "Animation with %s frames" % num def __add__(self, other): """ @@ -498,7 +498,7 @@ def png(self, dir=None): dir = tmp_dir() i = 0 for frame in self._frames: - filename = '%s/%08d.png'%(dir,i) + filename = '%s/%08d.png' % (dir,i) try: save_image = frame.save_image except AttributeError: diff --git a/src/sage/plot/circle.py b/src/sage/plot/circle.py index 512080a6ed8..41281b66735 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 "Circle defined by (%s,%s) with r=%s" % (self.x, self.y, self.r) def _render_on_subplot(self, subplot): """ @@ -148,7 +148,7 @@ def _render_on_subplot(self, subplot): options = self.options() p = patches.Circle((float(self.x), float(self.y)), float(self.r), clip_on=options['clip']) if not options['clip']: - self._bbox_extra_artists=[p] + self._bbox_extra_artists = [p] p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) a = float(options['alpha']) diff --git a/src/sage/plot/density_plot.py b/src/sage/plot/density_plot.py index b9f993239d0..8d6123ff226 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 %s x %s data grid" % (self.xy_array_row, self.xy_array_col) def _render_on_subplot(self, subplot): """ diff --git a/src/sage/plot/ellipse.py b/src/sage/plot/ellipse.py index 6d99cc90401..791b719fe68 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 (%s, %s) with radii (%s, %s) and angle %s" % (self.x, self.y, self.r1, self.r2, self.angle) def _render_on_subplot(self, subplot): """ @@ -362,7 +362,7 @@ def ellipse(center, r1, r2, angle=0, **options): if options['legend_label']: g.legend(True) g._legend_colors = [options['legend_color']] - if len(center)==2: + if len(center) == 2: return g - elif len(center)==3: + elif len(center) == 3: raise NotImplementedError("plotting ellipse in 3D is not implemented") diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 614505f89ac..59f10f6b13f 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -1104,8 +1104,8 @@ def __radd__(self, other): Compute and return other + this graphics object. This only works when other is a Python int equal to 0. In all other - cases a TypeError is raised. The main reason for this function is - to make summing a list of graphics objects easier. + cases a :class:`TypeError` is raised. The main reason for this + function is to make summing a list of graphics objects easier. EXAMPLES:: diff --git a/src/sage/plot/hyperbolic_regular_polygon.py b/src/sage/plot/hyperbolic_regular_polygon.py index a20d7d5a002..9be2169ab63 100644 --- a/src/sage/plot/hyperbolic_regular_polygon.py +++ b/src/sage/plot/hyperbolic_regular_polygon.py @@ -110,14 +110,14 @@ def __init__(self, sides, i_angle, center, options): """ self.center = CC(center) if self.center.imag() <= 0: - raise ValueError("center: %s is not a valid point in the upper half plane model of the hyperbolic plane"%(self.center)) + raise ValueError("center: %s is not a valid point in the upper half plane model of the hyperbolic plane" % (self.center)) if sides < 3: raise ValueError("degenerated polygons (sides<=2) are not supported") if i_angle <= 0 or i_angle >= pi: - raise ValueError("interior angle %s must be in (0, pi) interval"%(i_angle)) + 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=%s the interior angle must be less than %s" % (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 @@ -151,7 +151,7 @@ def __init__(self, sides, i_angle, center, options): new_z_k = self._i_rotation(z_k[-1], beta).n(digits=8) z_k = z_k + [new_z_k] d_z_k = d_z_k + [new_z_k * scale + h_disp] - r_z_k=[-(new_z_k).conjugate() * scale + h_disp] + r_z_k + r_z_k = [-(new_z_k).conjugate() * scale + h_disp] + r_z_k if is_odd(self.sides): HyperbolicPolygon.__init__(self, d_z_k + r_z_k, "UHP", options) else: diff --git a/src/sage/plot/matrix_plot.py b/src/sage/plot/matrix_plot.py index d34bd473829..f113f5aaa62 100644 --- a/src/sage/plot/matrix_plot.py +++ b/src/sage/plot/matrix_plot.py @@ -121,9 +121,9 @@ def get_minmax_data(self): # for example, the square representing the (0,0) entry is centered on # the origin. if not xrange: - xrange = (-.5, self.xy_array_col -.5) + xrange = (-.5, self.xy_array_col - .5) if not yrange: - yrange = (-.5, self.xy_array_row -.5) + yrange = (-.5, self.xy_array_row - .5) return minmax_data(xrange, yrange, dict=True) def _allowed_options(self): @@ -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 %s x %s data grid" % (self.xy_array_row, self.xy_array_col) def _render_on_subplot(self, subplot): """ @@ -175,29 +175,29 @@ def _render_on_subplot(self, subplot): cmap = get_cmap(options.pop('cmap',None)) flip_y = options['flip_y'] - norm=options['norm'] + norm = options['norm'] - if norm=='value': + if norm == 'value': import matplotlib - norm=matplotlib.colors.NoNorm() + norm = matplotlib.colors.NoNorm() - lim=self.get_minmax_data() + lim = self.get_minmax_data() if options['subdivisions']: - subdiv_options=options['subdivision_options'] + subdiv_options = options['subdivision_options'] if isinstance(subdiv_options['boundaries'], (list, tuple)): - rowsub,colsub=subdiv_options['boundaries'] + rowsub,colsub = subdiv_options['boundaries'] else: - rowsub=subdiv_options['boundaries'] - colsub=subdiv_options['boundaries'] + rowsub = subdiv_options['boundaries'] + colsub = subdiv_options['boundaries'] if isinstance(subdiv_options['style'], (list, tuple)): - rowstyle,colstyle=subdiv_options['style'] + rowstyle,colstyle = subdiv_options['style'] else: - rowstyle=subdiv_options['style'] - colstyle=subdiv_options['style'] + rowstyle = subdiv_options['style'] + colstyle = subdiv_options['style'] if rowstyle is None: - rowstyle=dict() + rowstyle = dict() if colstyle is None: - colstyle=dict() + colstyle = dict() # Make line objects for subdivisions from .line import line2d @@ -215,7 +215,7 @@ def _render_on_subplot(self, subplot): if hasattr(self.xy_data_array, 'tocoo'): # Sparse matrix -- use spy - opts=options.copy() + opts = options.copy() for opt in ['vmin', 'vmax', 'norm', 'flip_y', 'subdivisions', 'subdivision_options', 'colorbar', 'colorbar_options']: del opts[opt] @@ -233,7 +233,7 @@ def _render_on_subplot(self, subplot): if options.get('colorbar', False): colorbar_options = options['colorbar_options'] from matplotlib import colorbar - cax,kwds=colorbar.make_axes_gridspec(subplot,**colorbar_options) + cax,kwds = colorbar.make_axes_gridspec(subplot,**colorbar_options) colorbar.Colorbar(cax, image, **kwds) if flip_y: @@ -569,7 +569,7 @@ def matrix_plot(mat, xrange=None, yrange=None, **options): from sage.plot.all import Graphics from sage.structure.element import is_Matrix from sage.rings.real_double import RDF - orig_mat=mat + orig_mat = mat if is_Matrix(mat): sparse = mat.is_sparse() if sparse: @@ -612,7 +612,7 @@ def matrix_plot(mat, xrange=None, yrange=None, **options): yrange = tuple(float(v) for v in yrange) if options['subdivisions'] and options['subdivision_options']['boundaries'] is None: - options['subdivision_options']['boundaries']=orig_mat.get_subdivisions() + options['subdivision_options']['boundaries'] = orig_mat.get_subdivisions() # Custom position the title. Otherwise it overlaps with tick labels if options['flip_y'] and 'title_pos' not in options: diff --git a/src/sage/plot/misc.py b/src/sage/plot/misc.py index 72ee2c049b0..fa06484c4cf 100644 --- a/src/sage/plot/misc.py +++ b/src/sage/plot/misc.py @@ -259,8 +259,8 @@ def unify_arguments(funcs): sage: sage.plot.misc.unify_arguments((x+y,x-y)) ((x, y), (x, y)) """ - vars=set() - free_variables=set() + vars = set() + free_variables = set() if not isinstance(funcs, (list, tuple)): funcs = [funcs] @@ -317,7 +317,7 @@ def _multiple_of_constant(n, pos, const): k = 1 while cf.quotient(k) != Infinity and cf.denominator(k) < 12: k += 1 - return '$%s$'%latex(cf.convergent(k-1)*const) + return '$%s$' % latex(cf.convergent(k-1)*const) def get_matplotlib_linestyle(linestyle, return_type): @@ -404,9 +404,9 @@ def get_matplotlib_linestyle(linestyle, return_type): '--', ':', '-.', ''} """ - long_to_short_dict={'solid' : '-','dashed' : '--', 'dotted' : ':', + long_to_short_dict = {'solid' : '-','dashed' : '--', 'dotted' : ':', 'dashdot':'-.'} - short_to_long_dict={'-' : 'solid','--' : 'dashed', ':' : 'dotted', + short_to_long_dict = {'-' : 'solid','--' : 'dashed', ':' : 'dotted', '-.':'dashdot'} # We need this to take care of region plot. Essentially, if None is @@ -441,7 +441,7 @@ def get_matplotlib_linestyle(linestyle, return_type): raise ValueError("WARNING: Unrecognized linestyle '%s'. " "Possible linestyle options are:\n{'solid', " "'dashed', 'dotted', dashdot', 'None'}, " - "respectively {'-', '--', ':', '-.', ''}"% + "respectively {'-', '--', ':', '-.', ''}" % (linestyle)) elif return_type == 'long': @@ -455,7 +455,7 @@ def get_matplotlib_linestyle(linestyle, return_type): raise ValueError("WARNING: Unrecognized linestyle '%s'. " "Possible linestyle options are:\n{'solid', " "'dashed', 'dotted', dashdot', 'None'}, " - "respectively {'-', '--', ':', '-.', ''}"% + "respectively {'-', '--', ':', '-.', ''}" % (linestyle)) diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 69e78f16ab4..b614b2ef3db 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -736,8 +736,8 @@ def __init__(self, formatter, skip_values): sage: with NamedTemporaryFile(suffix=".png") as f: ....: fig.savefig(f.name) """ - self.formatter=formatter - self.skip_values=skip_values + self.formatter = formatter + self.skip_values = skip_values def set_locs(self, locs): """ @@ -2175,7 +2175,7 @@ def _plot(funcs, xrange, parametric=False, options['plot_points'], imaginary_tolerance=imag_tol) xmin, xmax, delta = ranges[0] - xrange=ranges[0][:2] + xrange = ranges[0][:2] # parametric_plot will be a list or tuple of two functions (f,g) # and will plotted as (f(x), g(x)) for all x in the given range if parametric: @@ -2314,7 +2314,7 @@ def golden_rainbow(i,lightness=0.4): if i < len(legend_color_temp): legend_color_entry = legend_color_temp[i] elif legend_color_temp == 'automatic': - if len(funcs)>1: + if len(funcs) > 1: legend_color_entry = golden_rainbow(i) elif legend_color_temp is not None: legend_color_entry = legend_color_temp @@ -2858,7 +2858,7 @@ def polar_plot(funcs, *args, **kwds): sphinx_plot(g) """ - kwds['polar']=True + kwds['polar'] = True return plot(funcs, *args, **kwds) @options(aspect_ratio='automatic') @@ -3903,14 +3903,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("%s\nUnable to compute f(%s)" % (msg, 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("%s\nUnable to compute f(%s)" % (msg, x), 1) # give up for this branch if excluded: return [(x, 'NaN')] diff --git a/src/sage/plot/plot3d/index_face_set.pyx b/src/sage/plot/plot3d/index_face_set.pyx index 7c2c9fb535b..3968db3ab51 100644 --- a/src/sage/plot/plot3d/index_face_set.pyx +++ b/src/sage/plot/plot3d/index_face_set.pyx @@ -1722,14 +1722,13 @@ cdef class IndexFaceSet(PrimitiveObject): sage: S = B.stickers(['red','yellow','blue'], 0.1, 0.05) sage: S.show() sage: (S+B).show() - """ all = [] n = self.fcount ct = len(colors) for k in range(len(colors)): if colors[k]: - all.append(self.sticker(list(xrange(k, n, ct)), width, hover, + all.append(self.sticker(list(range(k, n, ct)), width, hover, texture=colors[k])) return Graphics3dGroup(all) diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index 41a1ad5de53..5687c6f9c8c 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -263,7 +263,7 @@ def __init__(self, dep_var, indep_vars): """ all_vars = sage_getargspec(self.transform).args[1:] if set(all_vars) != set(indep_vars + [dep_var]): - raise ValueError('variables were specified incorrectly for this coordinate system; incorrect variables were %s'%list(set(all_vars).symmetric_difference(set(indep_vars+[dep_var])))) + raise ValueError('variables were specified incorrectly for this coordinate system; incorrect variables were %s' % list(set(all_vars).symmetric_difference(set(indep_vars+[dep_var])))) self.dep_var = dep_var self.indep_vars = indep_vars @@ -953,6 +953,7 @@ def smooth_triangle(self, a, b, c, da, db, dc, color=None): """ return [a,b,c] + from . import parametric_plot3d def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): """ @@ -1371,11 +1372,11 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): from sage.modules.vector_callable_symbolic_dense import Vector_callable_symbolic_dense if isinstance(transformation, (tuple, list,Vector_callable_symbolic_dense)): - if len(transformation)==3: + if len(transformation) == 3: if params is None: raise ValueError("must specify independent variable names in the ranges when using generic transformation") indep_vars = params - elif len(transformation)==4: + elif len(transformation) == 4: indep_vars = transformation[3] transformation = transformation[0:3] else: @@ -1383,8 +1384,8 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): # find out which variable is the function variable by # eliminating the parameter variables. all_vars = set(sum([list(s.variables()) for s in transformation],[])) - dep_var=all_vars - set(indep_vars) - if len(dep_var)==1: + dep_var = all_vars - set(indep_vars) + if len(dep_var) == 1: dep_var = dep_var.pop() transformation = _ArbitraryCoordinates(transformation, dep_var, indep_vars) else: diff --git a/src/sage/plot/plot3d/shapes.pyx b/src/sage/plot/plot3d/shapes.pyx index 9c820deda2b..f5c98fe3929 100644 --- a/src/sage/plot/plot3d/shapes.pyx +++ b/src/sage/plot/plot3d/shapes.pyx @@ -535,11 +535,10 @@ cdef class Cylinder(ParametricSurface): name = render_params.unique_name('line') return [""" draw %s width %s {%s %s %s} {%s %s %s}\n%s -""" % (name, - rad, +""" % (name, rad, base[0], base[1], base[2], - top [0], top [1], top [2], - self.texture.jmol_str("$" + name)) ] + top[0], top[1], top[2], + self.texture.jmol_str("$" + name))] def get_endpoints(self, transform=None): """ diff --git a/src/sage/plot/plot3d/tri_plot.py b/src/sage/plot/plot3d/tri_plot.py index 0841f9dc730..da719020117 100644 --- a/src/sage/plot/plot3d/tri_plot.py +++ b/src/sage/plot/plot3d/tri_plot.py @@ -64,7 +64,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 "%s %s %s %s" % (self._a, self._b, self._c, self._color) def set_color(self, color): """ @@ -135,7 +135,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 "%s %s %s %s %s %s %s" % (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 28d509fe156..9b2746c5a27 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 %s x %s vector grid" % ( self._options['plot_points'], self._options['plot_points']) def _render_on_subplot(self, subplot): diff --git a/src/sage/probability/probability_distribution.pyx b/src/sage/probability/probability_distribution.pyx index 53f99fc4fd8..1f120cd6089 100644 --- a/src/sage/probability/probability_distribution.pyx +++ b/src/sage/probability/probability_distribution.pyx @@ -1,14 +1,14 @@ -""" +r""" Probability Distributions This module provides three types of probability distributions: -- ``RealDistribution``: various real-valued probability distributions. +- :class:`RealDistribution`: various real-valued probability distributions. -- ``SphericalDistribution``: uniformly distributed points on the +- :class:`SphericalDistribution`: uniformly distributed points on the surface of an `n-1` sphere in `n` dimensional euclidean space. -- ``GeneralDiscreteDistribution``: user-defined discrete distributions. +- :class:`GeneralDiscreteDistribution`: user-defined discrete distributions. AUTHORS: @@ -46,8 +46,7 @@ import sage.rings.real_double from sage.modules.free_module_element import vector # TODO: Add more distributions available in gsl -# available but not currently wrapped are exponential, laplace, cauchy, landau, gamma, -# gamma, beta logistic. +# available but not currently wrapped are laplace, cauchy, landau, logistic. cdef enum: uniform @@ -61,15 +60,17 @@ cdef enum: exppow weibull beta + exponential + gamma cdef class ProbabilityDistribution: - """ + r""" Concrete probability distributions should be derived from this abstract class. """ def __init__(self): - """ + r""" To be implemented by a derived class:: sage: P = sage.probability.probability_distribution.ProbabilityDistribution() @@ -78,7 +79,7 @@ cdef class ProbabilityDistribution: pass def get_random_element(self): - """ + r""" To be implemented by a derived class:: sage: P = sage.probability.probability_distribution.ProbabilityDistribution() @@ -91,15 +92,15 @@ cdef class ProbabilityDistribution: raise NotImplementedError("implement in derived class") def generate_histogram_data(self, num_samples=1000, bins=50): - """ + r""" Compute a histogram of the probability distribution. INPUT: - - ``num_samples`` - (optional) number of times to sample from + - ``num_samples`` -- (optional) number of times to sample from the probability distribution - - ``bins`` - (optional) number of bins to divide the samples + - ``bins`` -- (optional) number of bins to divide the samples into. OUTPUT: @@ -114,8 +115,8 @@ cdef class ProbabilityDistribution: sage: from sage.probability.probability_distribution import GeneralDiscreteDistribution sage: P = [0.3, 0.4, 0.3] sage: X = GeneralDiscreteDistribution(P) - sage: h, b = X.generate_histogram_data(bins = 10) - sage: h # rel tol 1e-08 + sage: h, b = X.generate_histogram_data(bins=10) # needs sage.plot + sage: h # rel tol 1e-08 # needs sage.plot [1.6299999999999999, 0.0, 0.0, @@ -126,7 +127,7 @@ cdef class ProbabilityDistribution: 0.0, 0.0, 1.4650000000000003] - sage: b + sage: b # needs sage.plot [0.0, 0.2, 0.4, @@ -144,19 +145,19 @@ cdef class ProbabilityDistribution: S = pylab.hist(ell, bins, density=True) return [list(S[0]), list(S[1])] - def generate_histogram_plot(self, name, num_samples = 1000, bins = 50): - """ + def generate_histogram_plot(self, name, num_samples=1000, bins=50): + r""" Save the histogram from :func:`generate_histogram_data() ` to a file. INPUT: - - ``name`` - file to save the histogram plot (as a PNG). + - ``name`` -- file to save the histogram plot (as a PNG). - - ``num_samples`` - (optional) number of times to sample from + - ``num_samples`` -- (optional) number of times to sample from the probability distribution - - ``bins`` - (optional) number of bins to divide the samples + - ``bins`` -- (optional) number of bins to divide the samples into. EXAMPLES: @@ -167,7 +168,7 @@ cdef class ProbabilityDistribution: sage: import tempfile sage: P = [0.3, 0.4, 0.3] sage: X = GeneralDiscreteDistribution(P) - sage: with tempfile.NamedTemporaryFile() as f: + sage: with tempfile.NamedTemporaryFile() as f: # needs sage.plot ....: X.generate_histogram_plot(f.name) """ import pylab @@ -177,13 +178,13 @@ cdef class ProbabilityDistribution: cdef class SphericalDistribution(ProbabilityDistribution): - """ + r""" This class is capable of producing random points uniformly distributed - on the surface of an ``n-1`` sphere in ``n`` dimensional euclidean space. The - dimension, ``n`` is selected via the keyword ``dimension``. The random + on the surface of an `(n-1)`-sphere in `n`-dimensional euclidean space. The + dimension `n` is selected via the keyword ``dimension``. The random number generator which drives it can be selected using the keyword - ``rng``. Valid choices are ``default`` which uses the Mersenne-Twister, - ``luxury`` which uses RANDLXS, and ``taus`` which uses the tausworth + ``rng``. Valid choices are ``'default'`` which uses the Mersenne-Twister, + ``'luxury'`` which uses RANDLXS, and ``'taus'`` which uses the tausworth generator. The default dimension is ``3``. EXAMPLES:: @@ -252,19 +253,19 @@ cdef class SphericalDistribution(ProbabilityDistribution): self.vec = sig_malloc(self.dimension*(sizeof(double))) def set_seed(self, seed): - """ + r""" Set the seed for the underlying random number generator. EXAMPLES:: - sage: T = SphericalDistribution(seed = 0) + sage: T = SphericalDistribution(seed=0) sage: T.set_seed(100) """ gsl_rng_set(self.r, seed) self.seed = seed def set_random_number_generator(self, rng='default'): - """ + r""" Set the gsl random number generator to be one of ``default``, ``luxury``, or ``taus``. @@ -295,12 +296,12 @@ cdef class SphericalDistribution(ProbabilityDistribution): sig_free(self.vec) def get_random_element(self): - """ + r""" Get a random sample from the probability distribution. EXAMPLES:: - sage: T = SphericalDistribution(seed = 0) + sage: T = SphericalDistribution(seed=0) sage: T.get_random_element() # rel tol 4e-16 (0.07961564104639995, -0.05237671627581255, 0.9954486572862178) """ @@ -312,17 +313,23 @@ cdef class SphericalDistribution(ProbabilityDistribution): return vector(sage.rings.real_double.RDF, v) # This could be made more efficient by directly constructing the vector, TODO. def reset_distribution(self): - """ + r""" This method resets the distribution. EXAMPLES:: - sage: T = SphericalDistribution(seed = 0) + sage: T = SphericalDistribution(seed=0) sage: [T.get_random_element() for _ in range(4)] # rel tol 4e-16 - [(0.07961564104639995, -0.05237671627581255, 0.9954486572862178), (0.4123599490593727, 0.5606817859360097, -0.7180495855658982), (-0.9619860891623148, -0.2726473494040498, -0.015690351211529927), (0.5674297579435619, -0.011206783800420301, -0.8233455397322326)] + [(0.07961564104639995, -0.05237671627581255, 0.9954486572862178), + (0.4123599490593727, 0.5606817859360097, -0.7180495855658982), + (-0.9619860891623148, -0.2726473494040498, -0.015690351211529927), + (0.5674297579435619, -0.011206783800420301, -0.8233455397322326)] sage: T.reset_distribution() sage: [T.get_random_element() for _ in range(4)] # rel tol 4e-16 - [(0.07961564104639995, -0.05237671627581255, 0.9954486572862178), (0.4123599490593727, 0.5606817859360097, -0.7180495855658982), (-0.9619860891623148, -0.2726473494040498, -0.015690351211529927), (0.5674297579435619, -0.011206783800420301, -0.8233455397322326)] + [(0.07961564104639995, -0.05237671627581255, 0.9954486572862178), + (0.4123599490593727, 0.5606817859360097, -0.7180495855658982), + (-0.9619860891623148, -0.2726473494040498, -0.015690351211529927), + (0.5674297579435619, -0.011206783800420301, -0.8233455397322326)] """ if self.r != NULL: gsl_rng_free(self.r) @@ -331,8 +338,8 @@ cdef class SphericalDistribution(ProbabilityDistribution): # gsl_rng_env_setup() cdef class RealDistribution(ProbabilityDistribution): - """ - The ``RealDistribution`` class provides a number of routines for sampling + r""" + The :class:`RealDistribution` class provides a number of routines for sampling from and analyzing and visualizing probability distributions. For precise definitions of the distributions and their parameters see the gsl reference manuals chapter on random number generators @@ -495,6 +502,31 @@ cdef class RealDistribution(ProbabilityDistribution): sage: T.cum_distribution_function(1) 1.0 + The exponential distribution has one parameter ``mu``:: + + sage: mu = 2 + sage: T = RealDistribution('exponential', mu) + sage: s = T.get_random_element() + sage: 0 <= s + True + sage: s.parent() + Real Double Field + sage: T.distribution_function(0) + 0.5 + + The gamma distribution has two parameters ``a`` and ``b``:: + + sage: a = 2 + sage: b = 2 + sage: T = RealDistribution('gamma', [a, b]) + sage: s = T.get_random_element() + sage: 0 <= s + True + sage: s.parent() + Real Double Field + sage: T.distribution_function(0) + 0.0 + The weibull distribution has two parameters ``a`` and ``b``:: sage: a = 1 @@ -517,10 +549,10 @@ cdef class RealDistribution(ProbabilityDistribution): twister. Also available are the RANDLXS algorithm and the Tausworthe generator (see the gsl reference manual for more details). These are all supposed to be simulation quality - generators. For RANDLXS use ``rng = 'luxury'`` and for - tausworth use ``rng = 'taus'``:: + generators. For RANDLXS use ``rng='luxury'`` and for + tausworth use ``rng='taus'``:: - sage: T = RealDistribution('gaussian', 1, rng = 'luxury', seed = 10) + sage: T = RealDistribution('gaussian', 1, rng='luxury', seed=10) To change the seed at a later time use ``set_seed``:: @@ -551,7 +583,7 @@ cdef class RealDistribution(ProbabilityDistribution): r""" EXAMPLES:: - sage: T = RealDistribution('gaussian', 1, seed = 0) + sage: T = RealDistribution('gaussian', 1, seed=0) sage: T.get_random_element() # rel tol 4e-16 0.13391860811867587 @@ -583,22 +615,22 @@ cdef class RealDistribution(ProbabilityDistribution): self.set_distribution(type, parameters) def set_seed(self, seed): - """ + r""" Set the seed for the underlying random number generator. EXAMPLES:: - sage: T = RealDistribution('gaussian', 1, rng = 'luxury', seed = 10) + sage: T = RealDistribution('gaussian', 1, rng='luxury', seed=10) sage: T.set_seed(100) """ gsl_rng_set(self.r, seed) self.seed = seed - def set_random_number_generator(self, rng = 'default'): - """ - Set the gsl random number generator to be one of ``default``, - ``luxury``, or ``taus``. + def set_random_number_generator(self, rng='default'): + r""" + Set the gsl random number generator to be one of ``'default'``, + ``'luxury'``, or ``'taus'``. EXAMPLES:: @@ -627,7 +659,7 @@ cdef class RealDistribution(ProbabilityDistribution): sig_free(self.parameters) def __str__(self): - """ + r""" Return the name of the current distribution. EXAMPLES:: @@ -642,12 +674,12 @@ cdef class RealDistribution(ProbabilityDistribution): return self.name def get_random_element(self): - """ + r""" Get a random sample from the probability distribution. EXAMPLES:: - sage: T = RealDistribution('gaussian', 1, seed = 0) + sage: T = RealDistribution('gaussian', 1, seed=0) sage: T.get_random_element() # rel tol 4e-16 0.13391860811867587 @@ -676,13 +708,17 @@ cdef class RealDistribution(ProbabilityDistribution): result = gsl_ran_weibull(self.r, self.parameters[0], self.parameters[1]) elif self.distribution_type == beta: result = gsl_ran_beta(self.r, self.parameters[0], self.parameters[1]) + elif self.distribution_type == exponential: + result = gsl_ran_exponential(self.r, self.parameters[0]) + elif self.distribution_type == gamma: + result = gsl_ran_gamma(self.r, self.parameters[0], self.parameters[1]) else: raise TypeError("Not a supported probability distribution") return sage.rings.real_double.RDF(result) def set_distribution(self, name='uniform', parameters=None): - """ + r""" This method can be called to change the current probability distribution. EXAMPLES:: @@ -726,7 +762,6 @@ cdef class RealDistribution(ProbabilityDistribution): self.parameters[1] = float(parameters[1]) self.distribution_type = pareto elif name == 'rayleigh': - self.distribution_type = rayleigh try: float(parameters) except Exception: @@ -807,6 +842,25 @@ cdef class RealDistribution(ProbabilityDistribution): self.parameters[0] = float(parameters[0]) self.parameters[1] = float(parameters[1]) self.distribution_type = beta + elif name == 'exponential': + try: + float(parameters) + except Exception: + raise TypeError("exponential distribution requires parameter mu coercible to float") + self.parameters = sig_malloc(sizeof(double)) + self.parameters[0] = float(parameters) + self.distribution_type = exponential + elif name == 'gamma': + if len(parameters) != 2: + raise TypeError("gamma distribution requires two real parameters") + try: + map(float, parameters) + except Exception: + raise TypeError("gamma distribution requires real parameters") + self.parameters = sig_malloc(sizeof(double)*2) + self.parameters[0] = float(parameters[0]) + self.parameters[1] = float(parameters[1]) + self.distribution_type = gamma else: raise TypeError("Not a supported probability distribution") @@ -815,12 +869,12 @@ cdef class RealDistribution(ProbabilityDistribution): # def _get_random_element_c(): def reset_distribution(self): - """ - This method resets the distribution. + r""" + Reset the distribution. EXAMPLES:: - sage: T = RealDistribution('gaussian', 1, seed = 10) + sage: T = RealDistribution('gaussian', 1, seed=10) sage: [T.get_random_element() for _ in range(10)] # rel tol 4e-16 [-0.7460999595745819, -0.004644606626413462, -0.8720538317207641, 0.6916259921666037, 2.67668674666043, 0.6325002813661014, -0.7974263521959355, -0.5284976893366636, 1.1353119849528792, 0.9912505673230749] sage: T.reset_distribution() @@ -834,7 +888,7 @@ cdef class RealDistribution(ProbabilityDistribution): # gsl_rng_env_setup() def distribution_function(self, x): - """ + r""" Evaluate the distribution function of the probability distribution at ``x``. @@ -872,11 +926,15 @@ cdef class RealDistribution(ProbabilityDistribution): return sage.rings.real_double.RDF(gsl_ran_weibull_pdf(x, self.parameters[0], self.parameters[1])) elif self.distribution_type == beta: return sage.rings.real_double.RDF(gsl_ran_beta_pdf(x, self.parameters[0], self.parameters[1])) + elif self.distribution_type == exponential: + return sage.rings.real_double.RDF(gsl_ran_exponential_pdf(x, self.parameters[0])) + elif self.distribution_type == gamma: + return sage.rings.real_double.RDF(gsl_ran_gamma_pdf(x, self.parameters[0], self.parameters[1])) else: raise TypeError("Not a supported probability distribution") def cum_distribution_function(self, x): - """ + r""" Evaluate the cumulative distribution function of the probability distribution at ``x``. @@ -908,11 +966,15 @@ cdef class RealDistribution(ProbabilityDistribution): return sage.rings.real_double.RDF(gsl_cdf_weibull_P(x, self.parameters[0], self.parameters[1])) elif self.distribution_type == beta: return sage.rings.real_double.RDF(gsl_cdf_beta_P(x, self.parameters[0], self.parameters[1])) + elif self.distribution_type == exponential: + return sage.rings.real_double.RDF(gsl_cdf_exponential_P(x, self.parameters[0])) + elif self.distribution_type == gamma: + return sage.rings.real_double.RDF(gsl_cdf_gamma_P(x, self.parameters[0], self.parameters[1])) else: raise TypeError("Not a supported probability distribution") def cum_distribution_function_inv(self, x): - """ + r""" Evaluate the inverse of the cumulative distribution distribution function of the probability distribution at ``x``. @@ -945,11 +1007,15 @@ cdef class RealDistribution(ProbabilityDistribution): return sage.rings.real_double.RDF(gsl_cdf_weibull_Pinv(x, self.parameters[0], self.parameters[1])) elif self.distribution_type == beta: return sage.rings.real_double.RDF(gsl_cdf_beta_Pinv(x, self.parameters[0], self.parameters[1])) + elif self.distribution_type == exponential: + return sage.rings.real_double.RDF(gsl_cdf_exponential_Pinv(x, self.parameters[0])) + elif self.distribution_type == gamma: + return sage.rings.real_double.RDF(gsl_cdf_gamma_Pinv(x, self.parameters[0], self.parameters[1])) else: raise TypeError("Not a supported probability distribution") def plot(self, *args, **kwds): - """ + r""" Plot the distribution function for the probability distribution. Parameters to :func:`sage.plot.plot.plot` can be passed through ``*args`` and ``**kwds``. @@ -957,25 +1023,25 @@ cdef class RealDistribution(ProbabilityDistribution): EXAMPLES:: sage: T = RealDistribution('uniform', [0, 2]) - sage: P = T.plot() + sage: P = T.plot() # needs sage.plot """ from sage.plot.plot import plot return plot(self.distribution_function, *args, **kwds) cdef class GeneralDiscreteDistribution(ProbabilityDistribution): - """ + r""" Create a discrete probability distribution. INPUT: - - ``P`` - list of probabilities. The list will automatically be + - ``P`` -- list of probabilities. The list will automatically be normalised if ``sum(P)`` is not equal to 1. - - ``rng`` - (optional) random number generator to use. May be + - ``rng`` -- (optional) random number generator to use. May be one of ``'default'``, ``'luxury'``, or ``'taus'``. - - ``seed`` - (optional) seed to use with the random number + - ``seed`` -- (optional) seed to use with the random number generator. OUTPUT: @@ -985,7 +1051,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): EXAMPLES: - Constructs a ``GeneralDiscreteDistribution`` with the probability + Construct a ``GeneralDiscreteDistribution`` with the probability distribution `P` where `P(0) = 0.3`, `P(1) = 0.4`, `P(2) = 0.3`:: sage: P = [0.3, 0.4, 0.3] @@ -1007,7 +1073,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): The distribution probabilities will automatically be normalised:: sage: P = [0.1, 0.3] - sage: X = GeneralDiscreteDistribution(P, seed = 0) + sage: X = GeneralDiscreteDistribution(P, seed=0) sage: counts = [0, 0] sage: for _ in range(10000): ....: counts[X.get_random_element()] += 1 @@ -1036,7 +1102,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): cdef gsl_ran_discrete_t *dist cdef long seed - def __init__(self, P, rng = 'default', seed = None): + def __init__(self, P, rng='default', seed=None): r""" Given a list of probabilities P construct an instance of a gsl discrete random variable generator. @@ -1102,7 +1168,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): sig_free(P_vec) def set_seed(self, seed): - """ + r""" Set the seed to be used by the random number generator. EXAMPLES:: @@ -1115,8 +1181,8 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): gsl_rng_set(self.r, seed) self.seed = seed - def set_random_number_generator(self, rng = 'default'): - """ + def set_random_number_generator(self, rng='default'): + r""" Set the random number generator to be used by gsl. EXAMPLES:: @@ -1141,7 +1207,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): gsl_ran_discrete_free(self.dist) def get_random_element(self): - """ + r""" Get a random sample from the probability distribution. EXAMPLES:: @@ -1156,7 +1222,7 @@ cdef class GeneralDiscreteDistribution(ProbabilityDistribution): return sage.rings.integer.Integer(gsl_ran_discrete(self.r, self.dist)) def reset_distribution(self): - """ + r""" This method resets the distribution. EXAMPLES:: diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index 11dc4ca3cf7..4a385e55150 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -326,7 +326,7 @@ def __init__(self, X, P, codomain=None, check=False): (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) sage: X.set() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - sage: X.entropy().n() + sage: X.entropy().n() # needs sage.libs.pari 1.99993896484375 A probability space can be defined on any list of elements:: @@ -337,7 +337,7 @@ def __init__(self, X, P, codomain=None, check=False): sage: X = DiscreteProbabilitySpace(S,P) sage: X Discrete probability space defined by {'A': 1/2, 'B': 1/4, 'C': 1/4} - sage: X.entropy().n() + sage: X.entropy().n() # needs sage.libs.pari 1.50000000000000 """ if codomain is None: diff --git a/src/sage/quadratic_forms/binary_qf.py b/src/sage/quadratic_forms/binary_qf.py index 6ac49bda89c..f80b3bfa23a 100755 --- a/src/sage/quadratic_forms/binary_qf.py +++ b/src/sage/quadratic_forms/binary_qf.py @@ -11,7 +11,7 @@ x^2 + 2*x*y + 3*y^2 sage: Q.discriminant() -8 - sage: Q.reduced_form() # optional - sage.libs.pari + sage: Q.reduced_form() # needs sage.libs.pari x^2 + 2*y^2 sage: Q(1, 1) 6 @@ -166,13 +166,15 @@ def _pari_init_(self): 2*x^2 + 3*x*y + 4*y^2 sage: f._pari_init_() 'Qfb(2,3,4)' - sage: pari(f) # optional - sage.libs.pari + + sage: # needs sage.libs.pari + sage: pari(f) Qfb(2, 3, 4) - sage: type(pari(f)) # optional - sage.libs.pari + sage: type(pari(f)) <... 'cypari2.gen.Gen'> - sage: gp(f) # optional - sage.libs.pari + sage: gp(f) Qfb(2, 3, 4) - sage: type(gp(f)) # optional - sage.libs.pari + sage: type(gp(f)) """ return 'Qfb(%s,%s,%s)' % (self._a, self._b, self._c) @@ -188,16 +190,18 @@ def __mul__(self, right): We explicitly compute in the group of classes of positive definite binary quadratic forms of discriminant -23:: + sage: # needs sage.libs.pari sage: R = BinaryQF_reduced_representatives(-23, primitive_only=False); R [x^2 + x*y + 6*y^2, 2*x^2 - x*y + 3*y^2, 2*x^2 + x*y + 3*y^2] - sage: R[0] * R[0] # optional - sage.libs.pari + sage: R[0] * R[0] x^2 + x*y + 6*y^2 - sage: R[1] * R[1] # optional - sage.libs.pari + sage: R[1] * R[1] 4*x^2 + 3*x*y + 2*y^2 - sage: (R[1] * R[1]).reduced_form() # optional - sage.libs.pari + sage: (R[1] * R[1]).reduced_form() 2*x^2 + x*y + 3*y^2 - sage: (R[1] * R[1] * R[1]).reduced_form() # optional - sage.libs.pari + sage: (R[1] * R[1] * R[1]).reduced_form() x^2 + x*y + 6*y^2 + sage: q1 = BinaryQF(1, 1, 4) sage: M = Matrix(ZZ, [[1, 3], [0, 1]]) sage: q1*M @@ -601,13 +605,13 @@ def has_fundamental_discriminant(self): sage: Q = BinaryQF([1, 0, 1]) sage: Q.discriminant() -4 - sage: Q.has_fundamental_discriminant() # optional - sage.libs.pari + sage: Q.has_fundamental_discriminant() # needs sage.libs.pari True sage: Q = BinaryQF([2, 0, 2]) sage: Q.discriminant() -16 - sage: Q.has_fundamental_discriminant() # optional - sage.libs.pari + sage: Q.has_fundamental_discriminant() # needs sage.libs.pari False """ return self.discriminant().is_fundamental_discriminant() @@ -816,17 +820,17 @@ def reduced_form(self, transformation=False, algorithm="default"): sage: a = BinaryQF([33, 11, 5]) sage: a.is_reduced() False - sage: b = a.reduced_form(); b # optional - sage.libs.pari + sage: b = a.reduced_form(); b # needs sage.libs.pari 5*x^2 - x*y + 27*y^2 - sage: b.is_reduced() # optional - sage.libs.pari + sage: b.is_reduced() # needs sage.libs.pari True sage: a = BinaryQF([15, 0, 15]) sage: a.is_reduced() True - sage: b = a.reduced_form(); b # optional - sage.libs.pari + sage: b = a.reduced_form(); b # needs sage.libs.pari 15*x^2 + 15*y^2 - sage: b.is_reduced() # optional - sage.libs.pari + sage: b.is_reduced() # needs sage.libs.pari True Examples of reducing indefinite forms:: @@ -834,26 +838,26 @@ def reduced_form(self, transformation=False, algorithm="default"): sage: f = BinaryQF(1, 0, -3) sage: f.is_reduced() False - sage: g = f.reduced_form(); g # optional - sage.libs.pari + sage: g = f.reduced_form(); g # needs sage.libs.pari x^2 + 2*x*y - 2*y^2 - sage: g.is_reduced() # optional - sage.libs.pari + sage: g.is_reduced() # needs sage.libs.pari True sage: q = BinaryQF(1, 0, -1) - sage: q.reduced_form() # optional - sage.libs.pari + sage: q.reduced_form() # needs sage.libs.pari x^2 + 2*x*y - sage: BinaryQF(1, 9, 4).reduced_form(transformation=True) # optional - sage.libs.pari + sage: BinaryQF(1, 9, 4).reduced_form(transformation=True) # needs sage.libs.pari ( [ 0 -1] 4*x^2 + 7*x*y - y^2, [ 1 2] ) - sage: BinaryQF(3, 7, -2).reduced_form(transformation=True) # optional - sage.libs.pari + sage: BinaryQF(3, 7, -2).reduced_form(transformation=True) # needs sage.libs.pari ( [1 0] 3*x^2 + 7*x*y - 2*y^2, [0 1] ) - sage: BinaryQF(-6, 6, -1).reduced_form(transformation=True) # optional - sage.libs.pari + sage: BinaryQF(-6, 6, -1).reduced_form(transformation=True) # needs sage.libs.pari ( [ 0 -1] -x^2 + 2*x*y + 2*y^2, [ 1 -4] @@ -863,12 +867,12 @@ def reduced_form(self, transformation=False, algorithm="default"): Check for :trac:`34229`:: - sage: BinaryQF([1,2,3]).reduced_form(transformation=True) # optional - sage.libs.pari + sage: BinaryQF([1,2,3]).reduced_form(transformation=True) # needs sage.libs.pari ( [ 1 -1] x^2 + 2*y^2, [ 0 1] ) - sage: BinaryQF([-225, -743, -743]).reduced_form().is_reduced() + sage: BinaryQF([-225, -743, -743]).reduced_form().is_reduced() # needs sage.libs.pari True Some randomized testing:: @@ -877,7 +881,8 @@ def reduced_form(self, transformation=False, algorithm="default"): ....: f = BinaryQF([randrange(-10^3, 10^3) for _ in 'abc']) ....: if not f.discriminant().is_square(): ....: break - sage: algos = ['default', 'pari'] + sage: algos = ['default'] + sage: assert pari; algos.append('pari') # needs sage.libs.pari sage: if f.discriminant() > 0: ....: algos.append('sage') sage: a = choice(algos) @@ -1258,38 +1263,40 @@ def is_equivalent(self, other, proper=True): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q3 = BinaryQF(4, 4, 15) sage: Q2 = BinaryQF(4, -4, 15) - sage: Q2.is_equivalent(Q3) # optional - sage.libs.pari + sage: Q2.is_equivalent(Q3) True sage: a = BinaryQF([33, 11, 5]) - sage: b = a.reduced_form(); b # optional - sage.libs.pari + sage: b = a.reduced_form(); b 5*x^2 - x*y + 27*y^2 - sage: a.is_equivalent(b) # optional - sage.libs.pari + sage: a.is_equivalent(b) True - sage: a.is_equivalent(BinaryQF((3, 4, 5))) # optional - sage.libs.pari + sage: a.is_equivalent(BinaryQF((3, 4, 5))) False Some indefinite examples:: sage: Q1 = BinaryQF(9, 8, -7) sage: Q2 = BinaryQF(9, -8, -7) - sage: Q1.is_equivalent(Q2, proper=True) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2, proper=True) # needs sage.libs.pari False - sage: Q1.is_equivalent(Q2, proper=False) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2, proper=False) # needs sage.libs.pari True TESTS: We check that :trac:`25888` is fixed:: + sage: # needs sage.libs.pari sage: Q1 = BinaryQF(3, 4, -2) sage: Q2 = BinaryQF(-2, 4, 3) - sage: Q1.is_equivalent(Q2) == Q2.is_equivalent(Q1) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2) == Q2.is_equivalent(Q1) True - sage: Q1.is_equivalent(Q2, proper=False) == Q2.is_equivalent(Q1, proper=False) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2, proper=False) == Q2.is_equivalent(Q1, proper=False) True - sage: Q1.is_equivalent(Q2, proper=True) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2, proper=True) True We check that the first part of :trac:`29028` is fixed:: @@ -1297,22 +1304,22 @@ def is_equivalent(self, other, proper=True): sage: Q = BinaryQF(0, 2, 0) sage: Q.discriminant() 4 - sage: Q.is_equivalent(Q, proper=True) # optional - sage.libs.pari + sage: Q.is_equivalent(Q, proper=True) # needs sage.libs.pari True - sage: Q.is_equivalent(Q, proper=False) # optional - sage.libs.pari + sage: Q.is_equivalent(Q, proper=False) # needs sage.libs.pari True A test for rational forms:: sage: Q1 = BinaryQF(0, 4, 2) sage: Q2 = BinaryQF(2, 4, 0) - sage: Q1.is_equivalent(Q2, proper=False) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2, proper=False) # needs sage.libs.pari True Test another part of :trac:`28989`:: sage: Q1, Q2 = BinaryQF(1, 1, -1), BinaryQF(-1, 1, 1) - sage: Q1.is_equivalent(Q2, proper=True) # optional - sage.libs.pari + sage: Q1.is_equivalent(Q2, proper=True) # needs sage.libs.pari True """ if not isinstance(other, BinaryQF): @@ -1454,7 +1461,7 @@ def complex_point(self): EXAMPLES:: sage: Q = BinaryQF([1, 0, 1]) - sage: Q.complex_point() + sage: Q.complex_point() # needs sage.libs.pari 1.00000000000000*I """ if self.discriminant() >= 0: @@ -1525,10 +1532,10 @@ def small_prime_value(self, Bmax=1000): EXAMPLES:: - sage: [Q.small_prime_value() # optional - sage.libs.pari + sage: [Q.small_prime_value() # needs sage.libs.pari ....: for Q in BinaryQF_reduced_representatives(-23, primitive_only=True)] [23, 2, 2] - sage: [Q.small_prime_value() # optional - sage.libs.pari + sage: [Q.small_prime_value() # needs sage.libs.pari ....: for Q in BinaryQF_reduced_representatives(-47, primitive_only=True)] [47, 2, 2, 3, 3] """ @@ -1569,7 +1576,7 @@ def solve_integer(self, n, *, algorithm="general"): EXAMPLES:: sage: Q = BinaryQF([1, 0, 419]) - sage: Q.solve_integer(773187972) # optional - sage.libs.pari + sage: Q.solve_integer(773187972) # needs sage.libs.pari (4919, 1337) If `Q` is of the form `[1,0,c]` as above and `n` is a prime @@ -1579,9 +1586,9 @@ def solve_integer(self, n, *, algorithm="general"): sage: Q = BinaryQF([1, 0, 12345]) sage: n = 2^99 + 5273 - sage: Q.solve_integer(n) + sage: Q.solve_integer(n) # needs sage.libs.pari (-67446480057659, 7139620553488) - sage: Q.solve_integer(n, algorithm='cornacchia') + sage: Q.solve_integer(n, algorithm='cornacchia') # needs sage.libs.pari (67446480057659, 7139620553488) sage: timeit('Q.solve_integer(n)') # not tested 125 loops, best of 3: 3.13 ms per loop @@ -1590,14 +1597,15 @@ def solve_integer(self, n, *, algorithm="general"): :: - sage: Qs = BinaryQF_reduced_representatives(-23, primitive_only=True) # optional - sage.libs.pari - sage: Qs # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: Qs = BinaryQF_reduced_representatives(-23, primitive_only=True) + sage: Qs [x^2 + x*y + 6*y^2, 2*x^2 - x*y + 3*y^2, 2*x^2 + x*y + 3*y^2] - sage: [Q.solve_integer(3) for Q in Qs] # optional - sage.libs.pari + sage: [Q.solve_integer(3) for Q in Qs] [None, (0, -1), (0, -1)] - sage: [Q.solve_integer(5) for Q in Qs] # optional - sage.libs.pari + sage: [Q.solve_integer(5) for Q in Qs] [None, None, None] - sage: [Q.solve_integer(6) for Q in Qs] # optional - sage.libs.pari + sage: [Q.solve_integer(6) for Q in Qs] [(1, -1), (1, -1), (-1, -1)] TESTS: @@ -1606,29 +1614,27 @@ def solve_integer(self, n, *, algorithm="general"): sage: Q = BinaryQF([randrange(-10^3, 10^3) for _ in 'abc']) sage: n = randrange(-10^9, 10^9) - sage: xy = Q.solve_integer(n) # optional - sage.libs.pari - sage: xy is None or Q(*xy) == n # optional - sage.libs.pari + sage: xy = Q.solve_integer(n) # needs sage.libs.pari + sage: xy is None or Q(*xy) == n # needs sage.libs.pari True Also when using the ``"cornacchia"`` algorithm:: + sage: # needs sage.libs.pari sage: n = random_prime(10^9) sage: c = randrange(1, 10^3) - sage: Q1 = BinaryQF(1, 0, c) sage: xy = Q1.solve_integer(n, algorithm='cornacchia') sage: xy is None or Q1(*xy) == n True sage: (xy is None) == (Q1.solve_integer(n) is None) True - sage: Q3 = BinaryQF(1, 0, 4*c+3) sage: xy = Q3.solve_integer(n, algorithm='cornacchia') sage: xy is None or Q3(*xy) == n True sage: (xy is None) == (Q3.solve_integer(n) is None) True - sage: xy = Q3.solve_integer(4*n, algorithm='cornacchia') sage: xy is None or Q3(*xy) == 4*n True @@ -1645,14 +1651,14 @@ def solve_integer(self, n, *, algorithm="general"): sage: Q = Q.matrix_action_right(U) sage: Q.discriminant().is_square() True - sage: xy = Q.solve_integer(n) # optional - sage.libs.pari - sage: Q(*xy) == n # optional - sage.libs.pari + sage: xy = Q.solve_integer(n) # needs sage.libs.pari + sage: Q(*xy) == n # needs sage.libs.pari True Also test the `n=0` special case separately:: - sage: xy = Q.solve_integer(0) # optional - sage.libs.pari - sage: Q(*xy) # optional - sage.libs.pari + sage: xy = Q.solve_integer(0) # needs sage.libs.pari + sage: Q(*xy) # needs sage.libs.pari 0 """ n = ZZ(n) @@ -1666,7 +1672,7 @@ def solve_integer(self, n, *, algorithm="general"): w = self.discriminant().sqrt() r = (-self._b + (w if w != self._b else -w)) / (2*self._a) p, q = r.as_integer_ratio() - g, u, v = p.xgcd(q) + _, u, v = p.xgcd(q) M = Matrix(ZZ, [[v, p], [-u, q]]) elif self._c: M = Matrix(ZZ, [[0, 1], [1, 0]]) @@ -1754,15 +1760,16 @@ def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): sage: len(BinaryQF_reduced_representatives(-13*4)) 2 - sage: QuadraticField(-13*4, 'a').class_number() + sage: QuadraticField(-13*4, 'a').class_number() # needs sage.rings.number_field 2 + + sage: # needs sage.libs.pari sage: p = next_prime(2^20); p 1048583 - sage: len(BinaryQF_reduced_representatives(-p)) # optional - sage.libs.pari + sage: len(BinaryQF_reduced_representatives(-p)) 689 - sage: QuadraticField(-p, 'a').class_number() # optional - sage.libs.pari sage.rings.number_field + sage: QuadraticField(-p, 'a').class_number() # needs sage.rings.number_field 689 - sage: BinaryQF_reduced_representatives(-23*9) [x^2 + x*y + 52*y^2, 2*x^2 - x*y + 26*y^2, @@ -1773,7 +1780,7 @@ def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): 6*x^2 - 3*x*y + 9*y^2, 6*x^2 + 3*x*y + 9*y^2, 8*x^2 + 7*x*y + 8*y^2] - sage: BinaryQF_reduced_representatives(-23*9, primitive_only=True) # optional - sage.libs.pari + sage: BinaryQF_reduced_representatives(-23*9, primitive_only=True) [x^2 + x*y + 52*y^2, 2*x^2 - x*y + 26*y^2, 2*x^2 + x*y + 26*y^2, @@ -1785,7 +1792,7 @@ def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): sage: BinaryQF_reduced_representatives(73) [4*x^2 + 3*x*y - 4*y^2] - sage: BinaryQF_reduced_representatives(76, primitive_only=True) # optional - sage.libs.pari + sage: BinaryQF_reduced_representatives(76, primitive_only=True) # needs sage.libs.pari [-3*x^2 + 4*x*y + 5*y^2, 3*x^2 + 4*x*y - 5*y^2] sage: BinaryQF_reduced_representatives(136) @@ -1800,9 +1807,9 @@ def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): sage: BinaryQF_reduced_representatives(148, proper=False, primitive_only=False) [x^2 + 12*x*y - y^2, 4*x^2 + 6*x*y - 7*y^2, 6*x^2 + 2*x*y - 6*y^2] - sage: BinaryQF_reduced_representatives(148, proper=False, primitive_only=True) # optional - sage.libs.pari + sage: BinaryQF_reduced_representatives(148, proper=False, primitive_only=True) # needs sage.libs.pari [x^2 + 12*x*y - y^2, 4*x^2 + 6*x*y - 7*y^2] - sage: BinaryQF_reduced_representatives(148, proper=True, primitive_only=True) # optional - sage.libs.pari + sage: BinaryQF_reduced_representatives(148, proper=True, primitive_only=True) # needs sage.libs.pari [-7*x^2 + 6*x*y + 4*y^2, x^2 + 12*x*y - y^2, 4*x^2 + 6*x*y - 7*y^2] sage: BinaryQF_reduced_representatives(148, proper=True, primitive_only=False) [-7*x^2 + 6*x*y + 4*y^2, @@ -1821,9 +1828,9 @@ def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): x^2 + 10*x*y, 2*x^2 + 10*x*y, 5*x^2 + 10*x*y] - sage: BinaryQF_reduced_representatives(10^2, proper=False, primitive_only=True) # optional - sage.libs.pari + sage: BinaryQF_reduced_representatives(10^2, proper=False, primitive_only=True) # needs sage.libs.pari [-3*x^2 + 10*x*y, -x^2 + 10*x*y, x^2 + 10*x*y] - sage: BinaryQF_reduced_representatives(10^2, proper=True, primitive_only=True) # optional - sage.libs.pari + sage: BinaryQF_reduced_representatives(10^2, proper=True, primitive_only=True) # needs sage.libs.pari [-3*x^2 + 10*x*y, -x^2 + 10*x*y, x^2 + 10*x*y, 3*x^2 + 10*x*y] sage: BinaryQF_reduced_representatives(10^2, proper=True, primitive_only=False) [-4*x^2 + 10*x*y, diff --git a/src/sage/quadratic_forms/constructions.py b/src/sage/quadratic_forms/constructions.py index 48a4d056e28..2fe117d2e29 100644 --- a/src/sage/quadratic_forms/constructions.py +++ b/src/sage/quadratic_forms/constructions.py @@ -32,7 +32,7 @@ def BezoutianQuadraticForm(f, g): sage: R = PolynomialRing(ZZ, 'x') sage: f = R([1,2,3]) sage: g = R([2,5]) - sage: Q = BezoutianQuadraticForm(f, g); Q # optional - sage.libs.singular + sage: Q = BezoutianQuadraticForm(f, g); Q # needs sage.libs.singular Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 -12 ] [ * -15 ] diff --git a/src/sage/quadratic_forms/extras.py b/src/sage/quadratic_forms/extras.py index a64e3518207..7bdba23c32e 100644 --- a/src/sage/quadratic_forms/extras.py +++ b/src/sage/quadratic_forms/extras.py @@ -151,7 +151,7 @@ def least_quadratic_nonresidue(p): sage: least_quadratic_nonresidue(5) 2 - sage: [least_quadratic_nonresidue(p) for p in prime_range(3, 100)] # optional - sage.libs.pari + sage: [least_quadratic_nonresidue(p) for p in prime_range(3, 100)] # needs sage.libs.pari [2, 2, 3, 2, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 2, 2, 2, 7, 5, 3, 2, 3, 5] TESTS: diff --git a/src/sage/quadratic_forms/genera/genus.py b/src/sage/quadratic_forms/genera/genus.py index 86942da84e1..d9c298f5f0a 100644 --- a/src/sage/quadratic_forms/genera/genus.py +++ b/src/sage/quadratic_forms/genera/genus.py @@ -1,8 +1,7 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari r""" Genus - AUTHORS: - David Kohel & Gabriele Nebe (2007): First created @@ -20,6 +19,8 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +from copy import copy, deepcopy + from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.misc.cachefunc import cached_method @@ -27,10 +28,9 @@ from sage.arith.misc import fundamental_discriminant from sage.matrix.matrix_space import MatrixSpace from sage.matrix.constructor import matrix -from sage.rings.integer_ring import IntegerRing, ZZ -from sage.rings.rational_field import RationalField, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.integer import Integer -from copy import copy, deepcopy from sage.misc.verbose import verbose from sage.quadratic_forms.special_values import quadratic_L_function__exact lazy_import('sage.quadratic_forms.genera.normal_form', '_min_nonsquare') @@ -81,7 +81,6 @@ def genera(sig_pair, determinant, max_scale=None, even=False): """ from sage.misc.mrange import mrange_iter # input checks - ZZ = IntegerRing() determinant = ZZ(determinant) sig_pair = (ZZ(sig_pair[0]), ZZ(sig_pair[1])) even = bool(even) @@ -175,8 +174,8 @@ def _local_genera(p, rank, det_val, max_scale, even): """ from sage.misc.mrange import cantor_product from sage.combinat.integer_lists.invlex import IntegerListsLex - scales_rks = [] # contains possibilities for scales and ranks - for rkseq in IntegerListsLex(rank, length=max_scale+1): # rank sequences + scales_rks = [] # contains possibilities for scales and ranks + for rkseq in IntegerListsLex(rank, length=max_scale + 1): # rank sequences # sum(rkseq) = rank # len(rkseq) = max_scale + 1 # now assure that we get the right determinant @@ -279,7 +278,7 @@ def _blocks(b, even_only=False): # odd case if not even_only: # format (det, oddity) - for s in [(1,2), (5,6), (1,6), (5,2), (7,0), (3,4)]: + for s in [(1, 2), (5, 6), (1, 6), (5, 2), (7, 0), (3, 4)]: b1 = copy(b) b1[2] = s[0] b1[3] = 1 @@ -290,22 +289,22 @@ def _blocks(b, even_only=False): b1 = copy(b) b1[3] = 0 b1[4] = 0 - d = (-1)**(rk//2) % 8 + d = (-1)**(rk // 2) % 8 for det in [d, d * (-3) % 8]: b1 = copy(b1) b1[2] = det blocks.append(b1) # odd case if not even_only: - for s in [(1,2), (5,6), (1,6), (5,2), (7,0), (3,4)]: + for s in [(1, 2), (5, 6), (1, 6), (5, 2), (7, 0), (3, 4)]: b1 = copy(b) - b1[2] = s[0]*(-1)**(rk//2 -1) % 8 + b1[2] = s[0]*(-1)**(rk // 2 - 1) % 8 b1[3] = 1 b1[4] = s[1] blocks.append(b1) - for s in [(1,4), (5,0)]: + for s in [(1, 4), (5, 0)]: b1 = copy(b) - b1[2] = s[0]*(-1)**(rk//2 - 2) % 8 + b1[2] = s[0]*(-1)**(rk // 2 - 2) % 8 b1[3] = 1 b1[4] = s[1] blocks.append(b1) @@ -440,18 +439,20 @@ def is_GlobalGenus(G): sym = loc._symbol v = sum([ss[0] * ss[1] for ss in sym]) a = D // (p**v) - b = Integer(prod([ss[2] for ss in sym])) + b = ZZ.prod(ss[2] for ss in sym) if p == 2: if not is_2_adic_genus(sym): verbose(mesg="False in is_2_adic_genus(sym)", level=2) return False if (a*b).kronecker(p) != 1: - verbose(mesg="False in (%s*%s).kronecker(%s)"%(a,b,p), level=2) + verbose(mesg="False in (%s*%s).kronecker(%s)" % (a, b, p), + level=2) return False oddity -= loc.excess() else: if a.kronecker(p) != b: - verbose(mesg="False in %s.kronecker(%s) != *%s"%(a,p,b), level=2) + verbose(mesg="False in %s.kronecker(%s) != *%s" % (a, p, b), + level=2) return False oddity += loc.excess() if oddity % 8 != 0: @@ -513,7 +514,7 @@ def is_2_adic_genus(genus_symbol_quintuple_list): if s[2] % 8 in (3, 5): if not s[4] in (2, 4, 6): return False - if (s[1] - s[4])% 2 == 1: + if (s[1] - s[4]) % 2 == 1: return False if s[3] == 0 and s[4] != 0: return False @@ -587,6 +588,7 @@ def canonical_2_adic_compartments(genus_symbol_quintuple_list): i += 1 return compartments + def canonical_2_adic_trains(genus_symbol_quintuple_list, compartments=None): r""" Given a `2`-adic local symbol (as the underlying list of quintuples) @@ -659,7 +661,7 @@ def canonical_2_adic_trains(genus_symbol_quintuple_list, compartments=None): # avoid a special case for the end of symbol # if a jordan component has rank zero it is considered even. symbol = genus_symbol_quintuple_list - symbol.append([symbol[-1][0]+1, 0, 1, 0, 0]) #We have just modified the input globally! + symbol.append([symbol[-1][0]+1, 0, 1, 0, 0]) # We have just modified the input globally! # Hence, we have to remove the last entry of symbol at the end. try: @@ -685,9 +687,10 @@ def canonical_2_adic_trains(genus_symbol_quintuple_list, compartments=None): trains.append(new_train) return trains finally: - #revert the input list to its original state + # revert the input list to its original state symbol.pop() + def canonical_2_adic_reduction(genus_symbol_quintuple_list): r""" Given a `2`-adic local symbol (as the underlying list of quintuples) @@ -750,18 +753,18 @@ def canonical_2_adic_reduction(genus_symbol_quintuple_list): # Canonical determinants: for i in range(len(genus_symbol_quintuple_list)): d = genus_symbol_quintuple_list[i][2] - if d in (1,7): + if d in (1, 7): canonical_symbol[i][2] = 1 else: canonical_symbol[i][2] = -1 # Oddity fusion: compartments = canonical_2_adic_compartments(genus_symbol_quintuple_list) for compart in compartments: - oddity = sum([ genus_symbol_quintuple_list[i][4] for i in compart ]) % 8 + oddity = sum([genus_symbol_quintuple_list[i][4] for i in compart]) % 8 for i in compart: genus_symbol_quintuple_list[i][4] = 0 genus_symbol_quintuple_list[compart[0]][4] = oddity - verbose(mesg="End oddity fusion: %s" %canonical_symbol, level=2) + verbose(mesg="End oddity fusion: %s" % canonical_symbol, level=2) # Sign walking: trains = canonical_2_adic_trains(genus_symbol_quintuple_list) for train in trains: @@ -775,7 +778,7 @@ def canonical_2_adic_reduction(genus_symbol_quintuple_list): if t1-1 in compart or t1 in compart: o = canonical_symbol[compart[0]][4] canonical_symbol[compart[0]][4] = (o+4) % 8 - verbose(mesg="End sign walking: %s" %canonical_symbol, level=2) + verbose(mesg="End sign walking: %s" % canonical_symbol, level=2) return canonical_symbol @@ -906,38 +909,38 @@ def p_adic_symbol(A, p, val): from sage.rings.finite_rings.finite_field_constructor import FiniteField - m0 = min([ c.valuation(p) for c in A.list() ]) + m0 = min(c.valuation(p) for c in A.list()) q = p**m0 n = A.nrows() - A = MatrixSpace(IntegerRing(), n, n)([ c // q for c in A.list() ]) + A = MatrixSpace(ZZ, n, n)([c // q for c in A.list()]) A_p = MatrixSpace(FiniteField(p), n, n)(A) B_p = A_p.kernel().echelonized_basis_matrix() if B_p.nrows() == 0: e0 = Integer(A_p.det()).kronecker(p) n0 = A.nrows() - return [ [m0, n0, e0] ] + return [[m0, n0, e0]] else: C_p = basis_complement(B_p) e0 = Integer((C_p * A_p * C_p.transpose()).det()).kronecker(p) n0 = C_p.nrows() - sym = [ [0, n0, e0] ] + sym = [[0, n0, e0]] r = B_p.nrows() - B = MatrixSpace(IntegerRing(), r, n)(B_p) - C = MatrixSpace(IntegerRing(), n - r, n)(C_p) + B = MatrixSpace(ZZ, r, n)(B_p) + C = MatrixSpace(ZZ, n - r, n)(C_p) # Construct the blocks for the Jordan decomposition [F,X;X,A_new] - F = MatrixSpace(RationalField(), n - r, n - r)(C * A * C.transpose()) + F = MatrixSpace(QQ, n - r, n - r)(C * A * C.transpose()) U = F**-1 - d = LCM([ c.denominator() for c in U.list() ]) - R = IntegerRing().quotient_ring(Integer(p)**(val + 3)) + d = LCM([c.denominator() for c in U.list()]) + R = ZZ.quotient_ring(Integer(p)**(val + 3)) u = R(d)**-1 - MatR = MatrixSpace(R, n - r , n - r) - MatZ = MatrixSpace(IntegerRing(), n - r, n - r) + MatR = MatrixSpace(R, n - r, n - r) + MatZ = MatrixSpace(ZZ, n - r, n - r) U = MatZ(MatR(MatZ(U * d)) * u) # X = C*A*B.transpose() # A = B*A*B.transpose() - X.transpose()*U*X X = C * A - A = B * (A - X.transpose()*U*X) * B.transpose() - return [ [s[0]+m0] + s[1:] for s in sym + p_adic_symbol(A, p, val) ] + A = B * (A - X.transpose() * U * X) * B.transpose() + return [[s[0]+m0] + s[1:] for s in sym + p_adic_symbol(A, p, val)] def is_even_matrix(A): @@ -966,7 +969,7 @@ def is_even_matrix(A): (True, -1) """ for i in range(A.nrows()): - if A[i,i] % 2 == 1: + if A[i, i] % 2: return False, i return True, -1 @@ -1017,39 +1020,39 @@ def split_odd(A): """ n0 = A.nrows() if n0 == 1: - return A[0, 0], MatrixSpace(IntegerRing(), 0, A.ncols())([]) + return A[0, 0], MatrixSpace(ZZ, 0, A.ncols())([]) even, i = is_even_matrix(A) R = A.parent().base_ring() C = MatrixSpace(R, n0 - 1, n0)(0) - u = A[i,i] + u = A[i, i] for j in range(n0-1): if j < i: - C[j,j] = 1 - C[j,i] = -A[j,i] * u + C[j, j] = 1 + C[j, i] = -A[j, i] * u else: - C[j,j+1] = 1 - C[j,i] = -A[j+1,i] * u + C[j, j+1] = 1 + C[j, i] = -A[j+1, i] * u B = C*A*C.transpose() even, j = is_even_matrix(B) if even: I = A.parent()(1) # TODO: we could manually (re)construct the kernel here... if i == 0: - I[1,0] = 1 - A[1,0]*u + I[1, 0] = 1 - A[1, 0]*u i = 1 else: - I[0,i] = 1 - A[0,i]*u + I[0, i] = 1 - A[0, i]*u i = 0 A = I*A*I.transpose() - u = A[i,i] - C = MatrixSpace(R,n0-1,n0)(0) + u = A[i, i] + C = MatrixSpace(R, n0-1, n0)(0) for j in range(n0-1): if j < i: - C[j,j] = 1 - C[j,i] = -A[j,i] * u + C[j, j] = 1 + C[j, i] = -A[j, i] * u else: - C[j,j+1] = 1 - C[j,i] = -A[j+1,i] * u + C[j, j+1] = 1 + C[j, i] = -A[j+1, i] * u B = C * A * C.transpose() even, j = is_even_matrix(B) if even: @@ -1098,7 +1101,7 @@ def trace_diag_mod_8(A): while A.nrows(): u, A = split_odd(A) tr += u - return IntegerRing()(tr) + return ZZ(tr) def two_adic_symbol(A, val): @@ -1138,10 +1141,9 @@ def two_adic_symbol(A, val): # deal with the empty matrix if n == 0: return [[0, 0, 1, 0, 0]] - m0 = min([ c.valuation(2) for c in A.list() ]) + m0 = min([c.valuation(2) for c in A.list()]) q = 2**m0 - A = A.parent()([ c // q for c in A.list() ]) - ZZ = IntegerRing() + A = A.parent()([c // q for c in A.list()]) A_2 = MatrixSpace(FiniteField(2), n, n)(A) K_2 = A_2.kernel() R_8 = ZZ.quotient_ring(Integer(8)) @@ -1156,7 +1158,7 @@ def two_adic_symbol(A, val): print("A:") print(A) assert False - even, i = is_even_matrix(A_2) # Determine whether the matrix is even or odd. + even, _ = is_even_matrix(A_2) # Determine whether the matrix is even or odd. if even: return [[m0, n0, d0, 0, 0]] else: @@ -1168,36 +1170,36 @@ def two_adic_symbol(A, val): B_2 = K_2.echelonized_basis_matrix() C_2 = basis_complement(B_2) n0 = C_2.nrows() - C = MatrixSpace(ZZ,n0,n)(C_2) + C = MatrixSpace(ZZ, n0, n)(C_2) A_new = C * A * C.transpose() # compute oddity modulo 8: A_8 = MatrixSpace(R_8, n0, n0)(A_new) # d0 = A_8.det() # no determinant over Z/8Z - d0 = ZZ(R_8(MatrixSpace(ZZ,n0,n0)(A_8).determinant())) + d0 = ZZ(R_8(MatrixSpace(ZZ, n0, n0)(A_8).determinant())) if d0 == 0: print("A:") print(A_new) assert False - even, i = is_even_matrix(A_new) + even, _ = is_even_matrix(A_new) if even: sym = [[0, n0, d0, 0, 0]] else: tr8 = trace_diag_mod_8(A_8) sym = [[0, n0, d0, 1, tr8]] r = B_2.nrows() - B = MatrixSpace(ZZ,r,n)(B_2) - C = MatrixSpace(IntegerRing(), n - r, n)(C_2) - F = MatrixSpace(RationalField(), n - r, n - r)(C * A * C.transpose()) + B = MatrixSpace(ZZ, r, n)(B_2) + C = MatrixSpace(ZZ, n - r, n)(C_2) + F = MatrixSpace(QQ, n - r, n - r)(C * A * C.transpose()) U = F**-1 - d = LCM([ c.denominator() for c in U.list() ]) - R = IntegerRing().quotient_ring(Integer(2)**(val + 3)) + d = LCM([c.denominator() for c in U.list()]) + R = ZZ.quotient_ring(Integer(2)**(val + 3)) u = R(d)**-1 MatR = MatrixSpace(R, n - r, n - r) - MatZ = MatrixSpace(IntegerRing(), n - r, n - r) + MatZ = MatrixSpace(ZZ, n - r, n - r) U = MatZ(MatR(MatZ(U * d)) * u) X = C * A A = B * (A - X.transpose()*U*X) * B.transpose() - return [ [s[0]+m0] + s[1:] for s in sym + two_adic_symbol(A, val) ] + return [[s[0]+m0] + s[1:] for s in sym + two_adic_symbol(A, val)] class Genus_Symbol_p_adic_ring(): @@ -1334,14 +1336,14 @@ def __repr__(self): Genus symbol at 2: [1^2]_0 2^2 Genus symbol at 3: 1^2 3^2 """ - p=self._prime + p = self._prime CS_string = "" if p == 2: CS = self.canonical_symbol() for train in self.trains(): - #mark the beginning of a train with a colon + # mark the beginning of a train with a colon CS_string += " :" - #collect the indices where compartments begin and end + # collect the indices where compartments begin and end compartment_begins = [] compartment_ends = [] for comp in self.compartments(): @@ -1350,24 +1352,24 @@ def __repr__(self): for block_index in train: if block_index in compartment_begins: - #mark the beginning of this compartment with [ + # mark the beginning of this compartment with [ CS_string += "[" block = CS[block_index] block_string = "%s^%s " % (p**block[0], block[2] * block[1]) CS_string += block_string if block_index in compartment_ends: - #close this compartment with ] and remove a space + # close this compartment with ] and remove a space CS_string = CS_string[:-1] + "]" # the oddity belongs to the compartment # and is saved in its first block i = compartment_ends.index(block_index) compartment_start = compartment_begins[i] oddity = CS[compartment_start][4] - CS_string +="_%s " % oddity + CS_string += "_%s " % oddity # remove the first colon CS_string = CS_string[2:] # remove some unnecessary whitespace - CS_string = CS_string.replace(" :",":") + CS_string = CS_string.replace(" :", ":") else: for s in self._symbol: @@ -1388,7 +1390,7 @@ def _latex_(self): sage: latex(g) \mbox{Genus symbol at } 2\mbox{: }1^{4} [2^{2} 4^{1}]_{3} :16^{4} [32^{1}]_{1} """ - p=self._prime + p = self._prime CS_string = "" if p == 2: CS = self.canonical_symbol() @@ -1417,14 +1419,14 @@ def _latex_(self): i = compartment_ends.index(block_index) compartment_start = compartment_begins[i] oddity = CS[compartment_start][4] - CS_string +="_{%s}" % oddity - #remove the first colon + CS_string += "_{%s}" % oddity + # remove the first colon CS_string = CS_string[2:] else: for s in self._symbol: CS_string += " {%s}^{%s}" % (p**s[0], s[2]*s[1]) - return r"\mbox{Genus symbol at } %s\mbox{: }%s" % (p,CS_string) + return r"\mbox{Genus symbol at } %s\mbox{: }%s" % (p, CS_string) def __eq__(self, other): r""" @@ -1491,16 +1493,15 @@ def __ne__(self, other): False sage: G3 != G3 False - """ return not self == other # Added these two methods to make this class iterable... - #def __getitem__(self, i): - # return self._symbol[i] + # def __getitem__(self, i): + # return self._symbol[i] # - #def len(self): - # return len(self._symbol) + # def len(self): + # return len(self._symbol) # ------------------------------------------------------ def automorphous_numbers(self): @@ -1610,11 +1611,11 @@ def automorphous_numbers(self): II = [] for block in collect_small_blocks(G): if block.ncols() == 1: - u = block[0,0] + u = block[0, 0] if I.count(u) < 2: - I.append(block[0,0]) - else: # rank2 - q = block[0,1] + I.append(block[0, 0]) + else: # rank2 + q = block[0, 1] II += [2*q, 3*2*q, 5*2*q, 7*2*q] L = I + II @@ -1646,9 +1647,9 @@ def automorphous_numbers(self): v, u = r.val_unit(ZZ(2)) u = u % 8 assert v >= 0 - if v==0 and u==1: + if v == 0 and u == 1: automorphs.append(ZZ(2)) - if v==0 and u==5: + if v == 0 and u == 5: automorphs.append(ZZ(6)) if v in [0, 2, 4]: # this overlaps with the first two cases! automorphs.append(ZZ(5)) @@ -1795,7 +1796,7 @@ def mass(self): p = self.prime() sym = self._symbol ############## - #diagonal product + # diagonal product ############## # diagonal factors @@ -1879,14 +1880,14 @@ def _species_list(self): for k in range(sym[-1][0] + 1): if sym[s][0] == k: symbols.append(sym[s]) - s +=1 + s += 1 else: symbols.append([k, 0, 1, 0, 0]) # avoid a case distinction - sym = [[-2, 0, 1, 0, 0],[-1, 0, 1, 0, 0]] + symbols + [[sym[-1][0]+1, 0, 1, 0, 0],[sym[-1][0] + 2, 0, 1, 0, 0]] + sym = [[-2, 0, 1, 0, 0], [-1, 0, 1, 0, 0]] + symbols + [[sym[-1][0]+1, 0, 1, 0, 0], [sym[-1][0] + 2, 0, 1, 0, 0]] for k in range(1, len(sym)-1): free = True - if sym[k-1][3]==1 or sym[k+1][3]==1: + if sym[k-1][3] == 1 or sym[k+1][3] == 1: free = False n = sym[k][1] o = sym[k][4] @@ -2038,7 +2039,7 @@ def determinant(self): 3 """ p = self._prime - return prod([ p**(s[0]*s[1]) for s in self._symbol ]) + return prod([p**(s[0] * s[1]) for s in self._symbol]) det = determinant @@ -2067,7 +2068,7 @@ def dimension(self): sage: G3.dimension() 4 """ - return sum([ s[1] for s in self._symbol ]) + return sum([s[1] for s in self._symbol]) dim = dimension rank = dimension @@ -2195,13 +2196,13 @@ def excess(self): for s in self._symbol: if s[0] % 2 == 1 and s[2] in (3, 5): k += 1 - return Integer(sum([ s[4] for s in self._symbol ]) + 4*k).mod(8) + return Integer(sum([s[4] for s in self._symbol]) + 4*k).mod(8) else: k = 0 for s in self._symbol: if s[0] % 2 == 1 and s[2] == -1: k += 1 - return Integer(sum([ s[1] * (p**s[0]-1) for s in self._symbol]) + 4*k).mod(8) + return Integer(sum([s[1] * (p**s[0]-1) for s in self._symbol]) + 4*k).mod(8) def scale(self): r""" @@ -2373,7 +2374,7 @@ def __init__(self, signature_pair, local_symbols, representative=None, check=Tru if not all(isinstance(sym, Genus_Symbol_p_adic_ring) for sym in local_symbols): raise TypeError("local symbols must be a list of local genus symbols") n = signature_pair[0] + signature_pair[1] - if not all(sym.dimension()==n for sym in local_symbols): + if not all(sym.dimension() == n for sym in local_symbols): raise TypeError("all local symbols must be of the same dimension") if representative is not None: if not representative.is_symmetric(): @@ -2386,7 +2387,7 @@ def __init__(self, signature_pair, local_symbols, representative=None, check=Tru raise ValueError("the first symbol must be 2-adic") if representative is not None: if representative.base_ring() != ZZ: - representative = matrix(ZZ,representative) + representative = matrix(ZZ, representative) representative.set_immutable() self._representative = representative self._signature = signature_pair @@ -2424,8 +2425,8 @@ def __repr__(self): """ rep = "Genus" if self.dimension() <= 20: - rep += " of\n%s" %self._representative - rep += "\nSignature: %s"%(self._signature,) + rep += " of\n%s" % self._representative + rep += "\nSignature: %s" % (self._signature,) for s in self._local_symbols: rep += "\n" + s.__repr__() return rep @@ -2448,10 +2449,10 @@ def _latex_(self): """ rep = r"\mbox{Genus" if self.dimension() <= 20: - rep += r" of}\\ %s" %self._representative._latex_() + rep += r" of}\\ %s" % self._representative._latex_() else: - rep +=r"}" - rep += r"\\ \mbox{Signature: } %s"%(self._signature,) + rep += r"}" + rep += r"\\ \mbox{Signature: } %s" % (self._signature,) for s in self._local_symbols: rep += r"\\ " + s._latex_() return rep @@ -2684,7 +2685,7 @@ def spinor_generators(self, proper): if p.divides(self.determinant()): continue g = Q(A.delta(p)) - if g.gap() in U.gap(): # containment in sage is broken + if g.gap() in U.gap(): # containment in sage is broken continue else: spinor_gens.append(p) @@ -2727,15 +2728,15 @@ def _proper_is_improper(self): P = [s.prime() for s in self._local_symbols] while True: x = V.random_element() - q = x * G* x + q = x * G * x if q != 0 and all(q.valuation(p) == norm.valuation(p) for p in P): break - Q = [p for p in q.prime_factors() if (norm.valuation(p) + q.valuation(p)) % 2 != 0] + Q = [p for p in q.prime_factors() if (norm.valuation(p) + q.valuation(p)) % 2] r = ZZ.prod(Q) # M = \tau_x(L) # q = [L: L & M] A, K = self._proper_spinor_kernel() - j = A.delta(r) # diagonal embedding of r + j = A.delta(r) # diagonal embedding of r return j in K, j def signature(self): @@ -2757,10 +2758,11 @@ def signature(self): def determinant(self): r""" - Return the determinant of this genus, where the determinant - is the Hessian determinant of the quadratic form whose Gram - matrix is the Gram matrix giving rise to this global genus - symbol. + Return the determinant of this genus. + + The determinant is the Hessian determinant of the quadratic + form whose Gram matrix is the Gram matrix giving rise to this + global genus symbol. OUTPUT: an integer @@ -2771,8 +2773,8 @@ def determinant(self): sage: GS.determinant() -24 """ - p, n = self.signature_pair() - return (-1)**n*prod([ G.determinant() for G in self._local_symbols ]) + _, n = self.signature_pair() + return (-1)**n * ZZ.prod(G.determinant() for G in self._local_symbols) det = determinant @@ -2891,7 +2893,7 @@ def rational_representative(self): for sym in self._local_symbols: p = sym._prime # it is important to use the definition of Cassels here! - if QuadraticForm(QQ,2*sym.gram_matrix()).hasse_invariant(p) == -1: + if QuadraticForm(QQ, 2*sym.gram_matrix()).hasse_invariant(p) == -1: P.append(p) q = quadratic_form_from_invariants(F=QQ, rk=m, det=det, P=P, sminus=sminus) @@ -2946,7 +2948,7 @@ def _compute_representative(self, LLL=True): m = pari(L) gp.read(SAGE_EXTCODE + "/pari/simon/qfsolve.gp") - m = gp.eval('qflllgram_indefgoon(%s)'%m) + m = gp.eval('qflllgram_indefgoon(%s)' % m) # convert the output string to sage L = pari(m).sage()[0] elif sig[1] != 0: @@ -3086,7 +3088,7 @@ def representatives(self, backend=None, algorithm=None): e = ZZ(2) if self.signature_pair()[0] == 0: e *= ZZ(-1) - Q = QuadraticForm(ZZ,e*self.representative()) + Q = QuadraticForm(ZZ, e * self.representative()) seeds = [Q] for p in self.spinor_generators(proper=False): v = Q.find_primitive_p_divisible_vector__next(p) @@ -3162,7 +3164,7 @@ def _standard_mass(self): sage: A = matrix.diagonal(ZZ, [1, 1, 1, 1]) sage: GS = Genus(A) - sage: GS._standard_mass() # optional - sage.symbolic + sage: GS._standard_mass() # needs sage.symbolic 1/48 """ @@ -3215,7 +3217,7 @@ def mass(self, backend='sage'): sage: from sage.quadratic_forms.genera.genus import genera sage: G = genera((8,0), 1, even=True)[0] - sage: G.mass() # optional - sage.symbolic + sage: G.mass() # needs sage.symbolic 1/696729600 sage: G.mass(backend='magma') # optional - magma 1/696729600 @@ -3254,22 +3256,22 @@ def mass(self, backend='sage'): if pos * neg != 0: raise ValueError("the genus must be definite.") if pos + neg == 1: - return QQ(1)/QQ(2) + return QQ(1) / QQ(2) if backend == 'sage': mass = self._standard_mass() for sym in self._local_symbols: - mass *= sym.mass()/sym._standard_mass() + mass *= sym.mass() / sym._standard_mass() return QQ(mass.canonicalize_radical()) elif backend == 'magma': - e = 1 # lattices in magma are positive definite - if neg !=0: + e = 1 # lattices in magma are positive definite + if neg != 0: e = -1 # for some reason LatticeWithGram wants a dense matrix - L = magma(e*self.representative().dense_matrix()) + L = magma(e * self.representative().dense_matrix()) L = L.LatticeWithGram() return QQ(L.Mass()) else: - raise ValueError("unknown backend: %s"%backend) + raise ValueError("unknown backend: %s" % backend) def level(self): r""" @@ -3375,18 +3377,18 @@ def _gram_from_jordan_block(p, block, discr_form=False): if p == 2: o = ZZ(block[3]) t = ZZ(block[4]) - U = matrix(QQ, 2, [0,1, 1,0]) - V = matrix(QQ, 2, [2,1, 1,2]) + U = matrix(QQ, 2, [0, 1, 1, 0]) + V = matrix(QQ, 2, [2, 1, 1, 2]) W = matrix(QQ, 1, [1]) if o == 0: if det in [1, 7]: qL = (rk // 2) * [U] else: - qL = (rk//2 - 1)*[U] + [V] + qL = (rk // 2 - 1) * [U] + [V] if o == 1: if rk % 2 == 1: qL = max(0, (rk - 3) // 2) * [U] - if t*det % 8 in [3, 5]: + if t * det % 8 in [3, 5]: qL += [V] elif rk >= 3: qL += [U] @@ -3397,21 +3399,21 @@ def _gram_from_jordan_block(p, block, discr_form=False): else: det = 1 qL = max(0, (rk - 4) // 2) * [U] - if (det , t) == (1, 0): + if (det, t) == (1, 0): qL += [U, 1 * W, 7 * W] - if (det , t) == (1, 2): + if (det, t) == (1, 2): qL += [U, 1 * W, 1 * W] - if (det , t) == (1, 4): + if (det, t) == (1, 4): qL += [V, 1 * W, 3 * W] - if (det , t) == (1, 6): + if (det, t) == (1, 6): qL += [U, 7 * W, 7 * W] - if (det , t) == (-1, 0): + if (det, t) == (-1, 0): qL += [V, 1 * W, 7 * W] - if (det , t) == (-1, 2): + if (det, t) == (-1, 2): qL += [U, 3 * W, 7 * W] - if (det , t) == (-1, 4): + if (det, t) == (-1, 4): qL += [U, 1 * W, 3 * W] - if (det , t) == (-1, 6): + if (det, t) == (-1, 6): qL += [U, 1 * W, 5 * W] # if the rank is 2 there is a U too much if rk == 2: @@ -3426,16 +3428,17 @@ def _gram_from_jordan_block(p, block, discr_form=False): d = 2**(rk % 2) if Integer(d).kronecker(p) != det: u = ZZ(_min_nonsquare(p)) - q[0,0] = u + q[0, 0] = u q = q * (2 / p**level) if p != 2 and not discr_form: q = matrix.identity(QQ, rk) if det != 1: u = ZZ(_min_nonsquare(p)) - q[0,0] = u + q[0, 0] = u q = q * p**level return q + # Helper functions for mass computations def M_p(species, p): @@ -3504,7 +3507,7 @@ def M_p(species, p): return QQ(1) n = species.abs() s = (n + 1) // ZZ(2) - mp = ZZ(2) * ZZ.prod(ZZ(1) - p**(-2*k) for k in range(1, s)) + mp = ZZ(2) * ZZ.prod(ZZ(1) - p**(-2 * k) for k in range(1, s)) if n % 2 == 0: - mp *= ZZ(1) - species.sign() * p**(-s) - return QQ(1) / mp + mp *= ZZ.one() - species.sign() * p**(-s) + return QQ.one() / mp diff --git a/src/sage/quadratic_forms/genera/normal_form.py b/src/sage/quadratic_forms/genera/normal_form.py index e072adff683..829b4783226 100644 --- a/src/sage/quadratic_forms/genera/normal_form.py +++ b/src/sage/quadratic_forms/genera/normal_form.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari sage.rings.padics +# sage.doctest: needs sage.libs.pari sage.rings.padics r""" Normal forms for `p`-adic quadratic and bilinear forms @@ -1374,7 +1374,7 @@ def _relations(G, n): e1 = G[0, 0].unit_part() e2 = G[1, 1].unit_part() B = Matrix(R, 2, 2, [1, 1, -4 * e2, e1]) - D, B1 = _normalize(B * G * B.T) + _, B1 = _normalize(B * G * B.T) return B1 * B diff --git a/src/sage/quadratic_forms/genera/spinor_genus.py b/src/sage/quadratic_forms/genera/spinor_genus.py index 7e6afff21a0..f049496965d 100644 --- a/src/sage/quadratic_forms/genera/spinor_genus.py +++ b/src/sage/quadratic_forms/genera/spinor_genus.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.groups +# sage.doctest: needs sage.groups r""" Spinor genus computations. diff --git a/src/sage/quadratic_forms/qfsolve.py b/src/sage/quadratic_forms/qfsolve.py index f8d82f48cbb..85116e43f9e 100644 --- a/src/sage/quadratic_forms/qfsolve.py +++ b/src/sage/quadratic_forms/qfsolve.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari """ Solving quadratic equations @@ -16,7 +16,7 @@ - Tyler Gaona (2015-11-14): added the `solve` method """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2008 Nick Alexander # Copyright (C) 2014 Jeroen Demeyer # @@ -24,8 +24,8 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ @@ -80,6 +80,7 @@ def qfsolve(G): return vector(QQ, ret) return ZZ(ret) + def qfparam(G, sol): r""" Parametrize the conic defined by the matrix `G`. @@ -220,8 +221,8 @@ def solve(self, c=0): N = Matrix(self.base_ring(), d+1, d+1) for i in range(d): for j in range(d): - N[i,j] = M[i,j] - N[d,d] = -c + N[i, j] = M[i, j] + N[d, d] = -c # Find a solution x to Q(x) = 0, using qfsolve() x = qfsolve(N) diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py index 4eb377365fc..3db01b9fe2f 100644 --- a/src/sage/quadratic_forms/quadratic_form.py +++ b/src/sage/quadratic_forms/quadratic_form.py @@ -100,25 +100,24 @@ def quadratic_form_from_invariants(F, rk, det, P, sminus): EXAMPLES:: sage: P = [3,5] - sage: q = quadratic_form_from_invariants(QQ,2,-15,P,1) - sage: q + sage: q = quadratic_form_from_invariants(QQ,2,-15,P,1); q # needs sage.rings.padics Quadratic form in 2 variables over Rational Field with coefficients: [ 5 0 ] [ * -3 ] - sage: all(q.hasse_invariant(p) == -1 for p in P) + sage: all(q.hasse_invariant(p) == -1 for p in P) # needs sage.rings.padics True TESTS: This shows that :trac:`28955` is fixed:: - sage: quadratic_form_from_invariants(QQ,3,2,[2],2) + sage: quadratic_form_from_invariants(QQ,3,2,[2],2) # needs sage.rings.padics Quadratic form in 3 variables over Rational Field with coefficients: [ -1 0 0 ] [ * 1 0 ] [ * * -2 ] - sage: quadratic_form_from_invariants(QQ,4,2,[2],4) + sage: quadratic_form_from_invariants(QQ,4,2,[2],4) # needs sage.rings.padics Traceback (most recent call last): ... ValueError: invariants do not define a rational quadratic form @@ -669,23 +668,26 @@ def list_external_initializations(self): sage: Q = QuadraticForm(ZZ, 2, [1,0,5]) sage: Q.list_external_initializations() [] - sage: T = Q.theta_series() # optional - sage.libs.pari - sage: Q.list_external_initializations() # optional - sage.libs.pari + + sage: # needs sage.libs.pari + sage: T = Q.theta_series() + sage: Q.list_external_initializations() [] - sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=False, # optional - sage.libs.pari + sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=False, ....: number_of_automorphisms=3, determinant=0) - sage: Q.list_external_initializations() # optional - sage.libs.pari + sage: Q.list_external_initializations() [] :: - sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=False, # optional - sage.libs.pari + sage: # needs sage.libs.pari + sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=False, ....: number_of_automorphisms=3, determinant=0) - sage: Q.list_external_initializations() # optional - sage.libs.pari + sage: Q.list_external_initializations() [] - sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=True, # optional - sage.libs.pari + sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=True, ....: number_of_automorphisms=3, determinant=0) - sage: Q.list_external_initializations() # optional - sage.libs.pari + sage: Q.list_external_initializations() ['number_of_automorphisms', 'determinant'] """ return deepcopy(self._external_initialization_list) @@ -697,7 +699,7 @@ def __pari__(self): EXAMPLES:: sage: Q = QuadraticForm(ZZ, 2, [1,0,5]) - sage: Q.__pari__() # optional - sage.libs.pari + sage: Q.__pari__() # needs sage.libs.pari [2, 0; 0, 10] """ @@ -710,7 +712,7 @@ def _pari_init_(self): EXAMPLES:: sage: Q = QuadraticForm(ZZ, 2, [1,0,5]) - sage: Q._pari_init_() # optional - sage.libs.pari + sage: Q._pari_init_() # needs sage.libs.pari 'Mat([2,0;0,10])' """ return self.matrix()._pari_init_() @@ -837,10 +839,10 @@ def __hash__(self): sage: Q1 = QuadraticForm(QQ, 2, [1,1,1]) sage: Q2 = QuadraticForm(QQ, 2, [1,1,1]) - sage: Q3 = QuadraticForm(QuadraticField(2), 2, [1,1,1]) # optional - sage.rings.number_field + sage: Q3 = QuadraticForm(QuadraticField(2), 2, [1,1,1]) # needs sage.rings.number_field sage: hash(Q1) == hash(Q2) True - sage: hash(Q1) == hash(Q3) # optional - sage.rings.number_field + sage: hash(Q1) == hash(Q3) # needs sage.rings.number_field False """ return hash(self.__base_ring) ^ hash(tuple(self.__coeffs)) @@ -1309,20 +1311,21 @@ def polynomial(self,names='x'): :: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: F. = NumberField(x^2 - 5) # optional - sage.rings.number_field - sage: Z = F.ring_of_integers() # optional - sage.rings.number_field - sage: Q = QuadraticForm(Z, 3, [2*a, 3*a, 0, 1 - a, 0, 2*a + 4]) # optional - sage.rings.number_field - sage: P = Q.polynomial(names='y'); P # optional - sage.rings.number_field + sage: F. = NumberField(x^2 - 5) + sage: Z = F.ring_of_integers() + sage: Q = QuadraticForm(Z, 3, [2*a, 3*a, 0, 1 - a, 0, 2*a + 4]) + sage: P = Q.polynomial(names='y'); P 2*a*y0^2 + 3*a*y0*y1 + (-a + 1)*y1^2 + (2*a + 4)*y2^2 - sage: Q = QuadraticForm(F, 4, # optional - sage.rings.number_field + sage: Q = QuadraticForm(F, 4, ....: [a, 3*a, 0, 1 - a, a - 3, 0, 2*a + 4, 4 + a, 0, 1]) - sage: Q.polynomial(names='z') # optional - sage.rings.number_field + sage: Q.polynomial(names='z') a*z0^2 + (3*a)*z0*z1 + (a - 3)*z1^2 + (a + 4)*z2^2 + (-a + 1)*z0*z3 + (2*a + 4)*z1*z3 + z3^2 - sage: B. = QuaternionAlgebra(F,-1,-1) # optional - sage.rings.number_field - sage: Q = QuadraticForm(B, 3, [2*a, 3*a, i, 1 - a, 0, 2*a + 4]) # optional - sage.rings.number_field - sage: Q.polynomial() # optional - sage.rings.number_field + sage: B. = QuaternionAlgebra(F,-1,-1) + sage: Q = QuadraticForm(B, 3, [2*a, 3*a, i, 1 - a, 0, 2*a + 4]) + sage: Q.polynomial() Traceback (most recent call last): ... ValueError: Can only create polynomial rings over commutative rings. @@ -1724,10 +1727,11 @@ def bilinear_map(self, v, w): This does not work if the characteristic is 2:: - sage: Q = DiagonalQuadraticForm(GF(2), [1,1,1]) # optional - sage.rings.finite_rings - sage: v = vector((1,1,1)) # optional - sage.rings.finite_rings - sage: w = vector((1,1,1)) # optional - sage.rings.finite_rings - sage: Q.bilinear_map(v, w) # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: Q = DiagonalQuadraticForm(GF(2), [1,1,1]) + sage: v = vector((1,1,1)) + sage: w = vector((1,1,1)) + sage: Q.bilinear_map(v, w) Traceback (most recent call last): ... TypeError: not defined for rings of characteristic 2 diff --git a/src/sage/quadratic_forms/quadratic_form__automorphisms.py b/src/sage/quadratic_forms/quadratic_form__automorphisms.py index d12fc95eb5c..d0bf38f71a5 100644 --- a/src/sage/quadratic_forms/quadratic_form__automorphisms.py +++ b/src/sage/quadratic_forms/quadratic_form__automorphisms.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari """ Automorphisms of Quadratic Forms """ diff --git a/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py b/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py index 5b0ff64b778..7b109b3dc01 100644 --- a/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py +++ b/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py @@ -47,14 +47,15 @@ def is_globally_equivalent_to(self, other, return_matrix=False): sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: M = Matrix(ZZ, 4, 4, [1,2,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]) sage: Q1 = Q(M) - sage: Q.is_globally_equivalent_to(Q1) + sage: Q.is_globally_equivalent_to(Q1) # needs sage.libs.pari True - sage: MM = Q.is_globally_equivalent_to(Q1, return_matrix=True) - sage: Q(MM) == Q1 + sage: MM = Q.is_globally_equivalent_to(Q1, return_matrix=True) # needs sage.libs.pari + sage: Q(MM) == Q1 # needs sage.libs.pari True :: + sage: # needs sage.libs.pari sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q2 = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3]) sage: Q3 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2]) @@ -74,7 +75,7 @@ def is_globally_equivalent_to(self, other, return_matrix=False): :: sage: Q = DiagonalQuadraticForm(ZZ, [1, -1]) - sage: Q.is_globally_equivalent_to(Q) + sage: Q.is_globally_equivalent_to(Q) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: not a definite form in QuadraticForm.is_globally_equivalent_to() @@ -88,9 +89,9 @@ def is_globally_equivalent_to(self, other, return_matrix=False): sage: Q = QuadraticForm(ZZ, 2, [2, 3, 5]) sage: P = QuadraticForm(ZZ, 2, [8, 6, 5]) - sage: Q.is_globally_equivalent_to(P) + sage: Q.is_globally_equivalent_to(P) # needs sage.libs.pari False - sage: P.is_globally_equivalent_to(Q) + sage: P.is_globally_equivalent_to(Q) # needs sage.libs.pari False """ from sage.quadratic_forms.quadratic_form import QuadraticForm @@ -132,9 +133,9 @@ def is_locally_equivalent_to(self, other, check_primes_only=False, force_jordan_ sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q2 = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3]) - sage: Q1.is_globally_equivalent_to(Q2) + sage: Q1.is_globally_equivalent_to(Q2) # needs sage.libs.pari False - sage: Q1.is_locally_equivalent_to(Q2) + sage: Q1.is_locally_equivalent_to(Q2) # needs sage.libs.pari True """ # TO IMPLEMENT: @@ -189,17 +190,19 @@ def has_equivalent_Jordan_decomposition_at_prime(self, other, p): sage: Q3 = QuadraticForm(ZZ, 3, [1, 0, 0, 1, 0, 11]) sage: [Q1.level(), Q2.level(), Q3.level()] [44, 44, 44] - sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, 2) # optional - sage.libs.pari + + sage: # needs sage.libs.pari + sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, 2) False - sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, 11) # optional - sage.libs.pari + sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, 11) False - sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, 2) # optional - sage.libs.pari + sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, 2) False - sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, 11) # optional - sage.libs.pari + sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, 11) True - sage: Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, 2) # optional - sage.libs.pari + sage: Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, 2) True - sage: Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, 11) # optional - sage.libs.pari + sage: Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, 11) False """ # Sanity Checks @@ -318,34 +321,36 @@ def is_rationally_isometric(self, other, return_matrix=False): sage: V = DiagonalQuadraticForm(QQ, [1, 1, 2]) sage: W = DiagonalQuadraticForm(QQ, [2, 2, 2]) - sage: V.is_rationally_isometric(W) # optional - sage.libs.pari + sage: V.is_rationally_isometric(W) # needs sage.libs.pari True :: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3) # optional - sage.rings.number_field - sage: V = QuadraticForm(K, 4, [1, 0, 0, 0, 2*a, 0, 0, a, 0, 2]); V # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3) + sage: V = QuadraticForm(K, 4, [1, 0, 0, 0, 2*a, 0, 0, a, 0, 2]); V Quadratic form in 4 variables over Number Field in a with defining polynomial x^2 - 3 with coefficients: [ 1 0 0 0 ] [ * 2*a 0 0 ] [ * * a 0 ] [ * * * 2 ] - sage: W = QuadraticForm(K, 4, [1, 2*a, 4, 6, 3, 10, 2, 1, 2, 5]); W # optional - sage.rings.number_field + sage: W = QuadraticForm(K, 4, [1, 2*a, 4, 6, 3, 10, 2, 1, 2, 5]); W Quadratic form in 4 variables over Number Field in a with defining polynomial x^2 - 3 with coefficients: [ 1 2*a 4 6 ] [ * 3 10 2 ] [ * * 1 2 ] [ * * * 5 ] - sage: V.is_rationally_isometric(W) # optional - sage.rings.number_field + sage: V.is_rationally_isometric(W) False :: - sage: K. = NumberField(x^4 + 2*x + 6) # optional - sage.rings.number_field - sage: V = DiagonalQuadraticForm(K, [a, 2, 3, 2, 1]); V # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^4 + 2*x + 6) + sage: V = DiagonalQuadraticForm(K, [a, 2, 3, 2, 1]); V Quadratic form in 5 variables over Number Field in a with defining polynomial x^4 + 2*x + 6 with coefficients: [ a 0 0 0 0 ] @@ -353,7 +358,7 @@ def is_rationally_isometric(self, other, return_matrix=False): [ * * 3 0 0 ] [ * * * 2 0 ] [ * * * * 1 ] - sage: W = DiagonalQuadraticForm(K, [a, a, a, 2, 1]); W # optional - sage.rings.number_field + sage: W = DiagonalQuadraticForm(K, [a, a, a, 2, 1]); W Quadratic form in 5 variables over Number Field in a with defining polynomial x^4 + 2*x + 6 with coefficients: [ a 0 0 0 0 ] @@ -361,88 +366,92 @@ def is_rationally_isometric(self, other, return_matrix=False): [ * * a 0 0 ] [ * * * 2 0 ] [ * * * * 1 ] - sage: V.is_rationally_isometric(W) # optional - sage.rings.number_field + sage: V.is_rationally_isometric(W) False :: - sage: K. = NumberField(x^2 - 3) # optional - sage.rings.number_field - sage: V = DiagonalQuadraticForm(K, [-1, a, -2*a]) # optional - sage.rings.number_field - sage: W = DiagonalQuadraticForm(K, [-1, -a, 2*a]) # optional - sage.rings.number_field - sage: V.is_rationally_isometric(W) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^2 - 3) + sage: V = DiagonalQuadraticForm(K, [-1, a, -2*a]) + sage: W = DiagonalQuadraticForm(K, [-1, -a, 2*a]) + sage: V.is_rationally_isometric(W) True - sage: V = DiagonalQuadraticForm(QQ, [1, 1, 2]) # optional - sage.rings.number_field - sage: W = DiagonalQuadraticForm(QQ, [2, 2, 2]) # optional - sage.rings.number_field - sage: T = V.is_rationally_isometric(W, True); T # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: V = DiagonalQuadraticForm(QQ, [1, 1, 2]) + sage: W = DiagonalQuadraticForm(QQ, [2, 2, 2]) + sage: T = V.is_rationally_isometric(W, True); T [ 0 0 1] [-1/2 -1/2 0] [ 1/2 -1/2 0] - sage: V.Gram_matrix() == T.transpose() * W.Gram_matrix() * T # optional - sage.rings.number_field + sage: V.Gram_matrix() == T.transpose() * W.Gram_matrix() * T True - sage: T = W.is_rationally_isometric(V, True); T # optional - sage.rings.number_field + sage: T = W.is_rationally_isometric(V, True); T # needs sage.rings.number_field [ 0 -1 1] [ 0 -1 -1] [ 1 0 0] - sage: W.Gram_matrix() == T.T * V.Gram_matrix() * T # optional - sage.rings.number_field + sage: W.Gram_matrix() == T.T * V.Gram_matrix() * T # needs sage.rings.number_field True :: sage: L = QuadraticForm(QQ, 3, [2, 2, 0, 2, 2, 5]) sage: M = QuadraticForm(QQ, 3, [2, 2, 0, 3, 2, 3]) - sage: L.is_rationally_isometric(M, True) # optional - sage.libs.pari + sage: L.is_rationally_isometric(M, True) # needs sage.libs.pari False :: sage: A = DiagonalQuadraticForm(QQ, [1, 5]) sage: B = QuadraticForm(QQ, 2, [1, 12, 81]) - sage: T = A.is_rationally_isometric(B, True); T # optional - sage.libs.pari + sage: T = A.is_rationally_isometric(B, True); T # needs sage.libs.pari [ 1 -2] [ 0 1/3] - sage: A.Gram_matrix() == T.T * B.Gram_matrix() * T # optional - sage.libs.pari + sage: A.Gram_matrix() == T.T * B.Gram_matrix() * T # needs sage.libs.pari True :: sage: C = DiagonalQuadraticForm(QQ, [1, 5, 9]) sage: D = DiagonalQuadraticForm(QQ, [6, 30, 1]) - sage: T = C.is_rationally_isometric(D, True); T # optional - sage.libs.pari + sage: T = C.is_rationally_isometric(D, True); T # needs sage.libs.pari [ 0 -5/6 1/2] [ 0 1/6 1/2] [ -1 0 0] - sage: C.Gram_matrix() == T.T * D.Gram_matrix() * T # optional - sage.libs.pari + sage: C.Gram_matrix() == T.T * D.Gram_matrix() * T # needs sage.libs.pari True :: sage: E = DiagonalQuadraticForm(QQ, [1, 1]) sage: F = QuadraticForm(QQ, 2, [17, 94, 130]) - sage: T = F.is_rationally_isometric(E, True); T # optional - sage.libs.pari + sage: T = F.is_rationally_isometric(E, True); T # needs sage.libs.pari [ -4 -189/17] [ -1 -43/17] - sage: F.Gram_matrix() == T.T * E.Gram_matrix() * T # optional - sage.libs.pari + sage: F.Gram_matrix() == T.T * E.Gram_matrix() * T # needs sage.libs.pari True TESTS:: - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: V = DiagonalQuadraticForm(K, [1, 2]) # optional - sage.rings.number_field - sage: W = DiagonalQuadraticForm(K, [1, 0]) # optional - sage.rings.number_field - sage: V.is_rationally_isometric(W) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(3) + sage: V = DiagonalQuadraticForm(K, [1, 2]) + sage: W = DiagonalQuadraticForm(K, [1, 0]) + sage: V.is_rationally_isometric(W) Traceback (most recent call last): ... NotImplementedError: This only tests regular forms Forms must have the same base ring otherwise a `TypeError` is raised:: - sage: K1. = QuadraticField(5) # optional - sage.rings.number_field - sage: K2. = QuadraticField(7) # optional - sage.rings.number_field - sage: V = DiagonalQuadraticForm(K1, [1, a]) # optional - sage.rings.number_field - sage: W = DiagonalQuadraticForm(K2, [1, b]) # optional - sage.rings.number_field - sage: V.is_rationally_isometric(W) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K1. = QuadraticField(5) + sage: K2. = QuadraticField(7) + sage: V = DiagonalQuadraticForm(K1, [1, a]) + sage: W = DiagonalQuadraticForm(K2, [1, b]) + sage: V.is_rationally_isometric(W) Traceback (most recent call last): ... TypeError: forms must have the same base ring. @@ -456,18 +465,20 @@ def is_rationally_isometric(self, other, return_matrix=False): Forms whose determinants do not differ by a square in the base field are not isometric:: - sage: K. = NumberField(x^2 - 3) # optional - sage.rings.number_field - sage: V = DiagonalQuadraticForm(K, [-1, a, -2*a]) # optional - sage.rings.number_field - sage: W = DiagonalQuadraticForm(K, [-1, a, 2*a]) # optional - sage.rings.number_field - sage: V.is_rationally_isometric(W) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^2 - 3) + sage: V = DiagonalQuadraticForm(K, [-1, a, -2*a]) + sage: W = DiagonalQuadraticForm(K, [-1, a, 2*a]) + sage: V.is_rationally_isometric(W) False :: - sage: K. = NumberField(x^5 - x + 2, 'a') # optional - sage.rings.number_field - sage: Q = QuadraticForm(K, 3, [a, 1, 0, -a**2, -a**3, -1]) # optional - sage.rings.number_field - sage: m = Q.matrix() # optional - sage.rings.number_field - sage: for _ in range(5): # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = NumberField(x^5 - x + 2, 'a') + sage: Q = QuadraticForm(K, 3, [a, 1, 0, -a**2, -a**3, -1]) + sage: m = Q.matrix() + sage: for _ in range(5): ....: t = random_matrix(ZZ, 3, algorithm='unimodular') ....: m2 = t*m*t.transpose() ....: Q2 = QuadraticForm(K, 3, [m2[i,j] / (2 if i==j else 1) @@ -565,18 +576,18 @@ def _diagonal_isometry(V, W): sage: Q = DiagonalQuadraticForm(QQ, [1, 2, 4]) sage: F = DiagonalQuadraticForm(QQ, [2, 2, 2]) - sage: T = _diagonal_isometry(Q, F); T # optional - sage.libs.pari + sage: T = _diagonal_isometry(Q, F); T # needs sage.libs.pari [ 0 1 0] [-1/2 0 1] [ 1/2 0 1] - sage: Q.Gram_matrix() == T.T * F.Gram_matrix() * T # optional - sage.libs.pari + sage: Q.Gram_matrix() == T.T * F.Gram_matrix() * T # needs sage.libs.pari True - sage: T = _diagonal_isometry(F, Q); T # optional - sage.libs.pari + sage: T = _diagonal_isometry(F, Q); T # needs sage.libs.pari [ 0 -1 -1] [ 1 0 0] [ 0 -1/2 1/2] - sage: F.Gram_matrix() == T.T * Q.Gram_matrix() * T # optional - sage.libs.pari + sage: F.Gram_matrix() == T.T * Q.Gram_matrix() * T # needs sage.libs.pari True """ import copy diff --git a/src/sage/quadratic_forms/quadratic_form__genus.py b/src/sage/quadratic_forms/quadratic_form__genus.py index 9f6371b5cdb..8727645b453 100644 --- a/src/sage/quadratic_forms/quadratic_form__genus.py +++ b/src/sage/quadratic_forms/quadratic_form__genus.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari """ Local and Global Genus Symbols """ diff --git a/src/sage/quadratic_forms/quadratic_form__local_density_congruence.py b/src/sage/quadratic_forms/quadratic_form__local_density_congruence.py index 0ab0050d046..a39637df8f0 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_density_congruence.py +++ b/src/sage/quadratic_forms/quadratic_form__local_density_congruence.py @@ -208,9 +208,9 @@ def local_good_density_congruence_even(self, m, Zvec, NZvec): [ * 10 5 6 ] [ * * 15 8 ] [ * * * 20 ] - sage: Q.theta_series(20) # optional - sage.libs.pari + sage: Q.theta_series(20) # needs sage.libs.pari 1 + 2*q^5 + 2*q^10 + 2*q^14 + 2*q^15 + 2*q^16 + 2*q^18 + O(q^20) - sage: Q.local_normal_form(2) # optional - sage.libs.pari sage.rings.padics + sage: Q.local_normal_form(2) # needs sage.libs.pari sage.rings.padics Quadratic form in 4 variables over Integer Ring with coefficients: [ 0 1 0 0 ] [ * 0 0 0 ] diff --git a/src/sage/quadratic_forms/quadratic_form__local_density_interfaces.py b/src/sage/quadratic_forms/quadratic_form__local_density_interfaces.py index 4bfe7ebe6a7..ec39e489494 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_density_interfaces.py +++ b/src/sage/quadratic_forms/quadratic_form__local_density_interfaces.py @@ -92,7 +92,7 @@ def local_primitive_density(self, p, m): [ * 10 5 6 ] [ * * 15 8 ] [ * * * 20 ] - sage: Q.theta_series(20) # optional - sage.libs.pari + sage: Q.theta_series(20) # needs sage.libs.pari 1 + 2*q^5 + 2*q^10 + 2*q^14 + 2*q^15 + 2*q^16 + 2*q^18 + O(q^20) sage: Q.local_normal_form(2) Quadratic form in 4 variables over Integer Ring with coefficients: diff --git a/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py b/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py index 5c2beb6f7b6..35f64198113 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py +++ b/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py @@ -367,9 +367,8 @@ def signature(self): [ * * * 9 ] sage: Q.signature() 2 - """ - (p, n, z) = self.signature_vector() + p, n, _ = self.signature_vector() return p - n @@ -411,33 +410,33 @@ def hasse_invariant(self, p): Quadratic form in 2 variables over Rational Field with coefficients: [ 1 0 ] [ * 2 ] - sage: [Q.hasse_invariant(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] - sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] :: sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) - sage: [Q.hasse_invariant(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] - sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] :: sage: Q = DiagonalQuadraticForm(ZZ, [1,-1,5]) - sage: [Q.hasse_invariant(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] - sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] :: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 23) # optional - sage.rings.number_field - sage: Q = DiagonalQuadraticForm(K, [-a, a + 2]) # optional - sage.rings.number_field - sage: [Q.hasse_invariant(p) for p in K.primes_above(19)] # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 23) # needs sage.rings.number_field + sage: Q = DiagonalQuadraticForm(K, [-a, a + 2]) # needs sage.rings.number_field + sage: [Q.hasse_invariant(p) for p in K.primes_above(19)] # needs sage.rings.number_field [-1, 1] """ # TO DO: Need to deal with the case n=1 separately somewhere! @@ -494,33 +493,33 @@ def hasse_invariant__OMeara(self, p): Quadratic form in 2 variables over Rational Field with coefficients: [ 1 0 ] [ * 2 ] - sage: [Q.hasse_invariant(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] - sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] :: sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) - sage: [Q.hasse_invariant(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] - sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] :: sage: Q = DiagonalQuadraticForm(ZZ,[1,-1,-1]) - sage: [Q.hasse_invariant(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] - sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # optional - sage.libs.pari + sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] :: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 23) # optional - sage.rings.number_field - sage: Q = DiagonalQuadraticForm(K, [-a, a + 2]) # optional - sage.rings.number_field - sage: [Q.hasse_invariant__OMeara(p) for p in K.primes_above(19)] # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 23) # needs sage.rings.number_field + sage: Q = DiagonalQuadraticForm(K, [-a, a + 2]) # needs sage.rings.number_field + sage: [Q.hasse_invariant__OMeara(p) for p in K.primes_above(19)] # needs sage.rings.number_field [1, 1] """ # TO DO: Need to deal with the case n=1 separately somewhere! @@ -563,18 +562,19 @@ def is_hyperbolic(self, p): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) - sage: Q.is_hyperbolic(-1) # optional - sage.libs.pari + sage: Q.is_hyperbolic(-1) False - sage: Q.is_hyperbolic(2) # optional - sage.libs.pari + sage: Q.is_hyperbolic(2) False - sage: Q.is_hyperbolic(3) # optional - sage.libs.pari + sage: Q.is_hyperbolic(3) False - sage: Q.is_hyperbolic(5) # Here -1 is a square, so it's true. # optional - sage.libs.pari + sage: Q.is_hyperbolic(5) # Here -1 is a square, so it's true. True - sage: Q.is_hyperbolic(7) # optional - sage.libs.pari + sage: Q.is_hyperbolic(7) False - sage: Q.is_hyperbolic(13) # Here -1 is a square, so it's true. # optional - sage.libs.pari + sage: Q.is_hyperbolic(13) # Here -1 is a square, so it's true. True """ # False for odd-dim'l forms @@ -614,33 +614,33 @@ def is_anisotropic(self, p): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) - sage: Q.is_anisotropic(2) # optional - sage.libs.pari + sage: Q.is_anisotropic(2) # needs sage.libs.pari True - sage: Q.is_anisotropic(3) # optional - sage.libs.pari + sage: Q.is_anisotropic(3) # needs sage.libs.pari True - sage: Q.is_anisotropic(5) # optional - sage.libs.pari + sage: Q.is_anisotropic(5) # needs sage.libs.pari False :: sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) - sage: Q.is_anisotropic(2) # optional - sage.libs.pari + sage: Q.is_anisotropic(2) # needs sage.libs.pari False - sage: Q.is_anisotropic(3) # optional - sage.libs.pari + sage: Q.is_anisotropic(3) # needs sage.libs.pari False - sage: Q.is_anisotropic(5) # optional - sage.libs.pari + sage: Q.is_anisotropic(5) # needs sage.libs.pari False :: - sage: [DiagonalQuadraticForm(ZZ, # optional - sage.libs.pari + sage: [DiagonalQuadraticForm(ZZ, # needs sage.libs.pari ....: [1, -least_quadratic_nonresidue(p)]).is_anisotropic(p) ....: for p in prime_range(3, 30)] [True, True, True, True, True, True, True, True, True] :: - sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), # optional - sage.libs.pari + sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), # needs sage.libs.pari ....: p, -p*least_quadratic_nonresidue(p)]).is_anisotropic(p) ....: for p in prime_range(3, 30)] [True, True, True, True, True, True, True, True, True] @@ -684,33 +684,33 @@ def is_isotropic(self, p): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) - sage: Q.is_isotropic(2) # optional - sage.libs.pari + sage: Q.is_isotropic(2) # needs sage.libs.pari False - sage: Q.is_isotropic(3) # optional - sage.libs.pari + sage: Q.is_isotropic(3) # needs sage.libs.pari False - sage: Q.is_isotropic(5) # optional - sage.libs.pari + sage: Q.is_isotropic(5) # needs sage.libs.pari True :: sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) - sage: Q.is_isotropic(2) # optional - sage.libs.pari + sage: Q.is_isotropic(2) # needs sage.libs.pari True - sage: Q.is_isotropic(3) # optional - sage.libs.pari + sage: Q.is_isotropic(3) # needs sage.libs.pari True - sage: Q.is_isotropic(5) # optional - sage.libs.pari + sage: Q.is_isotropic(5) # needs sage.libs.pari True :: - sage: [DiagonalQuadraticForm(ZZ, # optional - sage.libs.pari + sage: [DiagonalQuadraticForm(ZZ, # needs sage.libs.pari ....: [1, -least_quadratic_nonresidue(p)]).is_isotropic(p) ....: for p in prime_range(3, 30)] [False, False, False, False, False, False, False, False, False] :: - sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), # optional - sage.libs.pari + sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), # needs sage.libs.pari ....: p, -p*least_quadratic_nonresidue(p)]).is_isotropic(p) ....: for p in prime_range(3, 30)] [False, False, False, False, False, False, False, False, False] @@ -728,15 +728,15 @@ def anisotropic_primes(self): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) - sage: Q.anisotropic_primes() # optional - sage.libs.pari + sage: Q.anisotropic_primes() # needs sage.libs.pari [2, -1] sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) - sage: Q.anisotropic_primes() # optional - sage.libs.pari + sage: Q.anisotropic_primes() # needs sage.libs.pari [2, -1] sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1]) - sage: Q.anisotropic_primes() # optional - sage.libs.pari + sage: Q.anisotropic_primes() # needs sage.libs.pari [-1] """ # Look at all prime divisors of 2 * Det(Q) to find the diff --git a/src/sage/quadratic_forms/quadratic_form__local_normal_form.py b/src/sage/quadratic_forms/quadratic_form__local_normal_form.py index a74dccc3fb3..5770a3c22f0 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_normal_form.py +++ b/src/sage/quadratic_forms/quadratic_form__local_normal_form.py @@ -1,7 +1,6 @@ """ Local Normal Form """ - # **************************************************************************** # Copyright (C) 2007 William Stein and Jonathan Hanke # @@ -18,18 +17,19 @@ # **************************************************************************** import copy + from sage.rings.infinity import Infinity -from sage.rings.integer_ring import IntegerRing, ZZ +from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.arith.misc import GCD -from sage.arith.misc import valuation -from sage.arith.misc import is_prime +from sage.arith.misc import GCD, valuation, is_prime def find_entry_with_minimal_scale_at_prime(self, p): r""" - Finds the entry of the quadratic form with minimal scale at the - prime `p`, preferring diagonal entries in case of a tie. (I.e. If + Find the entry of the quadratic form with minimal scale at the + prime `p`, preferring diagonal entries in case of a tie. + + (I.e. If we write the quadratic form as a symmetric matrix `M`, then this entry ``M[i,j]`` has the minimal valuation at the prime `p`.) @@ -56,14 +56,13 @@ def find_entry_with_minimal_scale_at_prime(self, p): (1, 1) sage: Q.find_entry_with_minimal_scale_at_prime(5) (0, 0) - """ n = self.dim() min_val = Infinity ij_index = None val_2 = valuation(2, p) for d in range(n): # d = difference j-i - for e in range(n - d): # e is the length of the diagonal with value d. + for e in range(n - d): # e is the length of the diagonal with value d. # Compute the valuation of the entry if d == 0: @@ -121,9 +120,9 @@ def local_normal_form(self, p): [ * 6 ] """ # Sanity Checks - if (self.base_ring() != IntegerRing()): + if self.base_ring() != ZZ: raise NotImplementedError("this currently only works for quadratic forms defined over ZZ") - if not ((p>=2) and is_prime(p)): + if not (p >= 2 and is_prime(p)): raise TypeError("p is not a positive prime number") # Some useful local variables @@ -145,12 +144,12 @@ def local_normal_form(self, p): min_val = valuation(Q[min_i, min_j], p) # Error if we still haven't seen non-zero coefficients! - if (min_val == Infinity): + if min_val == Infinity: raise RuntimeError("the original matrix is degenerate") # Step 2: Arrange for the upper leftmost entry to have minimal valuation # ---------------------------------------------------------------------- - if (min_i == min_j): + if min_i == min_j: block_size = 1 Q.swap_variables(0, min_i, in_place=True) else: @@ -159,7 +158,7 @@ def local_normal_form(self, p): Q.swap_variables(1, min_j, in_place=True) # 1x1 => make upper left the smallest - if (p != 2): + if p != 2: block_size = 1 Q.add_symmetric(1, 0, 1, in_place=True) # 2x2 => replace it with the appropriate 2x2 matrix @@ -171,8 +170,8 @@ def local_normal_form(self, p): min_scale = p ** min_val # This is the minimal valuation of the Hessian matrix entries. # Perform cancellation over Z by ensuring divisibility - if (block_size == 1): - a = 2 * Q[0,0] + if block_size == 1: + a = 2 * Q[0, 0] for j in range(block_size, n): b = Q[0, j] g = GCD(a, b) @@ -181,16 +180,16 @@ def local_normal_form(self, p): if valuation(g, p) != valuation(a, p): raise RuntimeError("we have a problem with our rescaling not preserving p-integrality") - Q.multiply_variable(ZZ(a/g), j, in_place=True) # Ensures that the new b entry is divisible by a - Q.add_symmetric(ZZ(-b/g), j, 0, in_place=True) # Performs the cancellation + Q.multiply_variable(ZZ(a / g), j, in_place=True) # Ensures that the new b entry is divisible by a + Q.add_symmetric(ZZ(-b / g), j, 0, in_place=True) # Performs the cancellation - elif (block_size == 2): - a1 = 2 * Q[0,0] + elif block_size == 2: + a1 = 2 * Q[0, 0] a2 = Q[0, 1] b1 = Q[1, 0] # This is the same as a2 b2 = 2 * Q[1, 1] - big_det = (a1*b2 - a2*b1) + big_det = a1 * b2 - a2 * b1 small_det = big_det / (min_scale * min_scale) # Cancels out the rows/columns of the 2x2 block @@ -202,18 +201,18 @@ def local_normal_form(self, p): Q.multiply_variable(big_det, j, in_place=True) # Performs the cancellation (by producing -big_det * jth row/column) - Q.add_symmetric(ZZ(-(a*b2 - b*a2)), j, 0, in_place=True) - Q.add_symmetric(ZZ(-(-a*b1 + b*a1)), j, 1, in_place=True) + Q.add_symmetric(ZZ(-(a * b2 - b * a2)), j, 0, in_place=True) + Q.add_symmetric(ZZ(-(-a * b1 + b * a1)), j, 1, in_place=True) # Now remove the extra factor (non p-unit factor) in big_det we introduced above Q.divide_variable(ZZ(min_scale * min_scale), j, in_place=True) # Uses Cassels's proof to replace the remaining 2 x 2 block - if (((1 + small_det) % 8) == 0): + if (1 + small_det) % 8 == 0: Q[0, 0] = 0 Q[1, 1] = 0 Q[0, 1] = min_scale - elif (((5 + small_det) % 8) == 0): + elif (5 + small_det) % 8 == 0: Q[0, 0] = min_scale Q[1, 1] = min_scale Q[0, 1] = min_scale @@ -223,7 +222,7 @@ def local_normal_form(self, p): # Check that the cancellation worked, extract the upper-left block, and trim Q to handle the next block. for i in range(block_size): for j in range(block_size, n): - if Q[i,j] != 0: + if Q[i, j] != 0: raise RuntimeError(f"the cancellation did not work properly at entry ({i},{j})") Q_Jordan = Q_Jordan + Q.extract_variables(range(block_size)) Q = Q.extract_variables(range(block_size, n)) @@ -300,7 +299,7 @@ def jordan_blocks_by_scale_and_unimodular(self, p, safe_flag=True): return copy.deepcopy(self.__jordan_blocks_by_scale_and_unimodular_dict[p]) else: return self.__jordan_blocks_by_scale_and_unimodular_dict[p] - except Exception: + except (KeyError, AttributeError): # Initialize the global dictionary if it doesn't exist if not hasattr(self, '__jordan_blocks_by_scale_and_unimodular_dict'): self.__jordan_blocks_by_scale_and_unimodular_dict = {} @@ -317,28 +316,28 @@ def jordan_blocks_by_scale_and_unimodular(self, p, safe_flag=True): tmp_Jordan_list = [] i = 0 start_ind = 0 - if (n >= 2) and (Q1[0,1] != 0): - start_scale = valuation(Q1[0,1], p) - 1 + if n >= 2 and Q1[0, 1] != 0: + start_scale = valuation(Q1[0, 1], p) - 1 else: - start_scale = valuation(Q1[0,0], p) + start_scale = valuation(Q1[0, 0], p) - while (i < n): + while i < n: # Determine the size of the current block - if (i == n-1) or (Q1[i,i+1] == 0): + if i == n - 1 or Q1[i, i + 1] == 0: block_size = 1 else: block_size = 2 # Determine the valuation of the current block if block_size == 1: - block_scale = valuation(Q1[i,i], p) + block_scale = valuation(Q1[i, i], p) else: - block_scale = valuation(Q1[i,i+1], p) - 1 + block_scale = valuation(Q1[i, i + 1], p) - 1 # Process the previous block if the valuation increased if block_scale > start_scale: - tmp_Jordan_list += [(start_scale, Q1.extract_variables(range(start_ind, i)).scale_by_factor(ZZ(1) / (QQ(p)**(start_scale))))] + tmp_Jordan_list += [(start_scale, Q1.extract_variables(range(start_ind, i)).scale_by_factor(ZZ.one() / QQ(p)**start_scale))] start_ind = i start_scale = block_scale @@ -346,7 +345,7 @@ def jordan_blocks_by_scale_and_unimodular(self, p, safe_flag=True): i += block_size # Add the last block - tmp_Jordan_list += [(start_scale, Q1.extract_variables(range(start_ind, n)).scale_by_factor(ZZ(1) / QQ(p)**(start_scale)))] + tmp_Jordan_list += [(start_scale, Q1.extract_variables(range(start_ind, n)).scale_by_factor(ZZ.one() / QQ(p)**start_scale))] # Cache the result self.__jordan_blocks_by_scale_and_unimodular_dict[p] = tmp_Jordan_list diff --git a/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py b/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py index ccff02a6368..888f4ae2832 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py +++ b/src/sage/quadratic_forms/quadratic_form__local_representation_conditions.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari sage.rings.number_field +# sage.doctest: needs sage.libs.pari sage.rings.number_field """ Local Representation Conditions """ diff --git a/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py b/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py index 86e33d1d9c9..894ee68cec9 100644 --- a/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +++ b/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py @@ -555,13 +555,13 @@ def conway_standard_mass(self): EXAMPLES:: sage: Q = QuadraticForm(ZZ, 3, [2, -2, 0, 3, -5, 4]) - sage: Q.conway_standard_mass() # optional - sage.symbolic + sage: Q.conway_standard_mass() # needs sage.symbolic 1/6 :: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) - sage: Q.conway_standard_mass() # optional - sage.symbolic + sage: Q.conway_standard_mass() # needs sage.symbolic 1/6 """ from sage.quadratic_forms.special_values import gamma__exact, zeta__exact, quadratic_L_function__exact @@ -595,19 +595,19 @@ def conway_mass(self): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) - sage: Q.conway_mass() # optional - sage.symbolic + sage: Q.conway_mass() # needs sage.symbolic 1/48 sage: Q = DiagonalQuadraticForm(ZZ, [7,1,1]) - sage: Q.conway_mass() # optional - sage.symbolic + sage: Q.conway_mass() # needs sage.symbolic 3/16 sage: Q = QuadraticForm(ZZ, 3, [7, 2, 2, 2, 0, 2]) + DiagonalQuadraticForm(ZZ, [1]) - sage: Q.conway_mass() # optional - sage.symbolic + sage: Q.conway_mass() # needs sage.symbolic 3/32 sage: Q = QuadraticForm(Matrix(ZZ, 2, [2,1,1,2])) - sage: Q.conway_mass() # optional - sage.symbolic + sage: Q.conway_mass() # needs sage.symbolic 1/12 """ # Try to use the cached result diff --git a/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py b/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py index 2281139adaf..a99eb439e0f 100644 --- a/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +++ b/src/sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py @@ -47,17 +47,17 @@ def mass__by_Siegel_densities(self, odd_algorithm="Pall", even_algorithm="Watson EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) - sage: m = Q.mass__by_Siegel_densities(); m # optional - sage.symbolic + sage: m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic 1/384 - sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # optional - sage.symbolic + sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # needs sage.symbolic 0 :: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) - sage: m = Q.mass__by_Siegel_densities(); m # optional - sage.symbolic + sage: m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic 1/48 - sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # optional - sage.symbolic + sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # needs sage.symbolic 0 """ from sage.symbolic.constants import pi @@ -181,7 +181,7 @@ def Watson_mass_at_2(self): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) - sage: Q.Watson_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! # optional - sage.symbolic + sage: Q.Watson_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! # needs sage.symbolic 384 """ from sage.functions.all import sgn diff --git a/src/sage/quadratic_forms/quadratic_form__neighbors.py b/src/sage/quadratic_forms/quadratic_form__neighbors.py index 4a490717863..94f6559d51a 100644 --- a/src/sage/quadratic_forms/quadratic_form__neighbors.py +++ b/src/sage/quadratic_forms/quadratic_form__neighbors.py @@ -131,6 +131,7 @@ def find_primitive_p_divisible_vector__next(self, p, v=None): if a in ZZ and (a % p == 0): return w + def find_p_neighbor_from_vec(self, p, y): r""" Return the `p`-neighbor of ``self`` defined by ``y``. @@ -151,7 +152,7 @@ def find_p_neighbor_from_vec(self, p, y): sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: v = vector([0,2,1,1]) - sage: X = Q.find_p_neighbor_from_vec(3, v); X # optional - sage.libs.pari + sage: X = Q.find_p_neighbor_from_vec(3, v); X # needs sage.libs.pari Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 1 4 4 ] @@ -164,7 +165,7 @@ def find_p_neighbor_from_vec(self, p, y): sage: Q = QuadraticForm(QQ, matrix.diagonal([1,1,1,1])) sage: v = vector([1,1,1,1]) - sage: Q.find_p_neighbor_from_vec(2, v) # optional - sage.libs.pari + sage: Q.find_p_neighbor_from_vec(2, v) # needs sage.libs.pari Quadratic form in 4 variables over Rational Field with coefficients: [ 1/2 1 1 1 ] [ * 1 1 2 ] @@ -173,7 +174,7 @@ def find_p_neighbor_from_vec(self, p, y): """ p = ZZ(p) if not p.divides(self(y)): - raise ValueError("y=%s must be of square divisible by p=%s"%(y,p)) + raise ValueError("y=%s must be of square divisible by p=%s" % (y, p)) if self.base_ring() not in [ZZ, QQ]: raise NotImplementedError("the base ring of this form must be the integers or the rationals") @@ -197,14 +198,14 @@ def find_p_neighbor_from_vec(self, p, y): z = (ZZ**n).gen(k) break else: - raise ValueError("either y is not primitive or self is not maximal at %s"%p) + raise ValueError("either y is not primitive or self is not maximal at %s" % p) z *= (2*y*G*z).inverse_mod(p) y = y - b*z # assert y*G*y % p^2 == 0 if p == 2: val = b.valuation(p) if val <= 1: - raise ValueError("y=%s must be of square divisible by 2"%y) + raise ValueError("y=%s must be of square divisible by 2" % y) if val == 2 and not odd: # modify it to have square 4 for k in range(n): @@ -262,28 +263,30 @@ def neighbor_iteration(seeds, p, mass=None, max_classes=ZZ(10)**3, sage: Q = QuadraticForm(ZZ, 3, [1, 0, 0, 2, 1, 3]) sage: Q.det() 46 - sage: mass = Q.conway_mass() # optional - sage.symbolic - sage: g1 = neighbor_iteration([Q], 3, # long time # optional - sage.symbolic + + sage: # needs sage.symbolic + sage: mass = Q.conway_mass() + sage: g1 = neighbor_iteration([Q], 3, # long time ....: mass=mass, algorithm='random') - sage: g2 = neighbor_iteration([Q], 3, algorithm='exhaustion') # long time - sage: g3 = neighbor_iteration([Q], 3, algorithm='orbits') # optional - sage.libs.gap - sage: mass == sum(1/q.number_of_automorphisms() for q in g1) # long time # optional - sage.symbolic + sage: g2 = neighbor_iteration([Q], 3, algorithm='exhaustion') # long time + sage: g3 = neighbor_iteration([Q], 3, algorithm='orbits') # needs sage.libs.gap + sage: mass == sum(1/q.number_of_automorphisms() for q in g1) # long time True - sage: mass == sum(1/q.number_of_automorphisms() for q in g2) # long time # optional - sage.symbolic + sage: mass == sum(1/q.number_of_automorphisms() for q in g2) # long time True - sage: mass == sum(1/q.number_of_automorphisms() for q in g3) # optional - sage.libs.gap sage.symbolic + sage: mass == sum(1/q.number_of_automorphisms() for q in g3) # needs sage.libs.gap True TESTS:: sage: from sage.quadratic_forms.quadratic_form__neighbors import neighbor_iteration sage: Q = QuadraticForm(ZZ, 3, [1, 0, 0, 2, 1, 3]) - sage: g = neighbor_iteration([Q], 3, mass=Q.conway_mass(), max_classes=2) # optional - sage.symbolic + sage: g = neighbor_iteration([Q], 3, mass=Q.conway_mass(), max_classes=2) # needs sage.symbolic ... UserWarning: reached the maximum number of isometry classes=2. Increase the optional argument max_classes to obtain more. Warning: not all classes in the genus were found - sage: neighbor_iteration([Q], 3, # optional - sage.symbolic + sage: neighbor_iteration([Q], 3, # needs sage.symbolic ....: mass=Q.conway_mass(), max_neighbors=0, algorithm='random') Warning: not all classes in the genus were found [] @@ -346,7 +349,7 @@ def p_divisible_vectors(Q, max_neighbors): break if len(isom_classes) >= max_classes: - warn("reached the maximum number of isometry classes=%s. Increase the optional argument max_classes to obtain more." %max_classes) + warn("reached the maximum number of isometry classes=%s. Increase the optional argument max_classes to obtain more." % max_classes) if mass is not None: assert mass_count <= mass @@ -354,6 +357,7 @@ def p_divisible_vectors(Q, max_neighbors): print("Warning: not all classes in the genus were found") return isom_classes + def orbits_lines_mod_p(self, p): r""" Let `(L, q)` be a lattice. This returns representatives of the @@ -369,14 +373,14 @@ def orbits_lines_mod_p(self, p): sage: from sage.quadratic_forms.quadratic_form__neighbors import orbits_lines_mod_p sage: Q = QuadraticForm(ZZ, 3, [1, 0, 0, 2, 1, 3]) - sage: Q.orbits_lines_mod_p(2) # optional - sage.libs.gap sage.libs.pari + sage: Q.orbits_lines_mod_p(2) # needs sage.libs.gap sage.libs.pari [(0, 0, 1), - (0, 1, 0), - (0, 1, 1), - (1, 0, 0), - (1, 0, 1), - (1, 1, 0), - (1, 1, 1)] + (0, 1, 0), + (0, 1, 1), + (1, 0, 0), + (1, 0, 1), + (1, 1, 0), + (1, 1, 1)] """ from sage.libs.gap.libgap import libgap from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF diff --git a/src/sage/quadratic_forms/quadratic_form__reduction_theory.py b/src/sage/quadratic_forms/quadratic_form__reduction_theory.py index ebf18b15adc..87323962097 100644 --- a/src/sage/quadratic_forms/quadratic_form__reduction_theory.py +++ b/src/sage/quadratic_forms/quadratic_form__reduction_theory.py @@ -18,7 +18,7 @@ def reduced_binary_form1(self): EXAMPLES:: - sage: QuadraticForm(ZZ, 2, [5,5,2]).reduced_binary_form1() # optional - sage.symbolic + sage: QuadraticForm(ZZ, 2, [5,5,2]).reduced_binary_form1() # needs sage.symbolic ( Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 -1 ] @@ -30,12 +30,12 @@ def reduced_binary_form1(self): TESTS:: - sage: QuadraticForm(ZZ, 2, [4,-7,6]).reduced_binary_form1()[0] # optional - sage.symbolic + sage: QuadraticForm(ZZ, 2, [4,-7,6]).reduced_binary_form1()[0] # needs sage.symbolic Quadratic form in 2 variables over Integer Ring with coefficients: [ 3 -1 ] [ * 4 ] - sage: QuadraticForm(ZZ, 3, [1,2,3,4,5,6]).reduced_binary_form1() # optional - sage.symbolic + sage: QuadraticForm(ZZ, 3, [1,2,3,4,5,6]).reduced_binary_form1() # needs sage.symbolic Traceback (most recent call last): ... TypeError: only available for binary forms @@ -92,7 +92,7 @@ def reduced_binary_form(self): EXAMPLES:: - sage: QuadraticForm(ZZ, 2, [5,5,2]).reduced_binary_form() # optional - sage.symbolic + sage: QuadraticForm(ZZ, 2, [5,5,2]).reduced_binary_form() # needs sage.symbolic ( Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 -1 ] diff --git a/src/sage/quadratic_forms/quadratic_form__siegel_product.py b/src/sage/quadratic_forms/quadratic_form__siegel_product.py index fd5f539c36b..c439a93f33b 100644 --- a/src/sage/quadratic_forms/quadratic_form__siegel_product.py +++ b/src/sage/quadratic_forms/quadratic_form__siegel_product.py @@ -1,15 +1,15 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari """ Siegel Products """ -#***************************************************************************** +# **************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.arith.misc import (bernoulli, fundamental_discriminant, @@ -21,16 +21,17 @@ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -#/*! \brief Computes the product of all local densities for comparison with independently computed Eisenstein coefficients. +# /*! \brief Computes the product of all local densities for comparison with independently computed Eisenstein coefficients. # * # * \todo We fixed the generic factors to compensate for using the matrix of 2Q, but we need to document this better! =) # */ -#///////////////////////////////////////////////////////////////// -#/// -#///////////////////////////////////////////////////////////////// +# ///////////////////////////////////////////////////////////////// +# /// +# ///////////////////////////////////////////////////////////////// + +# mpq_class Matrix_mpz::siegel_product(mpz_class u) const { -#mpq_class Matrix_mpz::siegel_product(mpz_class u) const { def siegel_product(self, u): """ @@ -124,15 +125,15 @@ def siegel_product(self, u): f = abs(d1) # DIAGNOSTIC - #cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl; - #cout << " f = " << f << " and d1 = " << d1 << endl; + # cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl; + # cout << " f = " << f << " and d1 = " << d1 << endl; genericfactor = m / QQ(sqrt(f*d)) \ * ((u/2) ** (m-1)) * (f ** m) \ / abs(QuadraticBernoulliNumber(m, d1)) \ * (2 ** m) # This last factor compensates for using the matrix of 2*Q - ##return genericfactor + # return genericfactor # Omit the generic factors in S and compute them separately omit = 1 @@ -141,9 +142,9 @@ def siegel_product(self, u): S_divisors = prime_divisors(S) # DIAGNOSTIC - #cout << "\n S is " << S << endl; - #cout << " The Prime divisors of S are :"; - #PrintV(S_divisors); + # cout << "\n S is " << S << endl; + # cout << " The Prime divisors of S are :"; + # PrintV(S_divisors); for p in S_divisors: Q_normal = self.local_normal_form(p) @@ -158,36 +159,36 @@ def siegel_product(self, u): verbose(" Q_normal is \n" + str(Q_normal) + "\n") verbose(" Q_normal = \n" + str(Q_normal)) verbose(" p = " + str(p) + "\n") - verbose(" u = " +str(u) + "\n") + verbose(" u = " + str(u) + "\n") verbose(" include = " + str(include) + "\n") include *= Q_normal.local_density(p, u) # DIAGNOSTIC - #cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl; + # cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl; # DIAGNOSTIC verbose(" --- Exiting loop \n") - #// **************** Important ******************* - #// Additional fix (only included for n=4) to deal - #// with the power of 2 introduced at the real place - #// by working with Q instead of 2*Q. This needs to - #// be done for all other n as well... - #/* - #if (n==4) + # // **************** Important ******************* + # // Additional fix (only included for n=4) to deal + # // with the power of 2 introduced at the real place + # // by working with Q instead of 2*Q. This needs to + # // be done for all other n as well... + # /* + # if (n==4) # genericfactor = 4 * genericfactor; - #*/ + # */ # DIAGNOSTIC - #cout << endl; - #cout << " generic factor = " << genericfactor << endl; - #cout << " omit = " << omit << endl; - #cout << " include = " << include << endl; - #cout << endl; + # cout << endl; + # cout << " generic factor = " << genericfactor << endl; + # cout << " omit = " << omit << endl; + # cout << " include = " << include << endl; + # cout << endl; # DIAGNOSTIC - #// cout << "siegel_product Break 3. " << endl; + # // cout << "siegel_product Break 3. " << endl; # Return the final factor (and divide by 2 if n=2) if n == 2: diff --git a/src/sage/quadratic_forms/quadratic_form__split_local_covering.py b/src/sage/quadratic_forms/quadratic_form__split_local_covering.py index 65076096db2..61f8c1a027f 100644 --- a/src/sage/quadratic_forms/quadratic_form__split_local_covering.py +++ b/src/sage/quadratic_forms/quadratic_form__split_local_covering.py @@ -143,7 +143,7 @@ def vectors_by_length(self, bound): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) - sage: Q.vectors_by_length(5) # optional - sage.symbolic + sage: Q.vectors_by_length(5) # needs sage.symbolic [[[0, 0]], [[0, -1], [-1, 0]], [[-1, -1], [1, -1]], @@ -154,7 +154,7 @@ def vectors_by_length(self, bound): :: sage: Q1 = DiagonalQuadraticForm(ZZ, [1,3,5,7]) - sage: Q1.vectors_by_length(5) # optional - sage.symbolic + sage: Q1.vectors_by_length(5) # needs sage.symbolic [[[0, 0, 0, 0]], [[-1, 0, 0, 0]], [], @@ -165,13 +165,13 @@ def vectors_by_length(self, bound): :: sage: Q = QuadraticForm(ZZ, 4, [1,1,1,1, 1,0,0, 1,0, 1]) - sage: list(map(len, Q.vectors_by_length(2))) # optional - sage.symbolic + sage: list(map(len, Q.vectors_by_length(2))) # needs sage.symbolic [1, 12, 12] :: sage: Q = QuadraticForm(ZZ, 4, [1,-1,-1,-1, 1,0,0, 4,-3, 4]) - sage: list(map(len, Q.vectors_by_length(3))) # optional - sage.symbolic + sage: list(map(len, Q.vectors_by_length(3))) # needs sage.symbolic [1, 3, 0, 3] """ # pari uses eps = 1e-6 ; nothing bad should happen if eps is too big @@ -377,7 +377,7 @@ def split_local_cover(self): EXAMPLES:: sage: Q1 = DiagonalQuadraticForm(ZZ, [7,5,3]) - sage: Q1.split_local_cover() # optional - sage.symbolic + sage: Q1.split_local_cover() # needs sage.symbolic Quadratic form in 3 variables over Integer Ring with coefficients: [ 3 0 0 ] [ * 5 0 ] diff --git a/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py b/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py index 9b8dfcecf7b..6ec8bd8022f 100644 --- a/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +++ b/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py @@ -150,7 +150,7 @@ def antiadjoint(self): [ 1 0 -1 ] [ * 2 -1 ] [ * * 5 ] - sage: Q.antiadjoint() # optional - sage.symbolic + sage: Q.antiadjoint() # needs sage.symbolic Traceback (most recent call last): ... ValueError: not an adjoint @@ -174,7 +174,7 @@ def is_adjoint(self) -> bool: EXAMPLES:: sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) - sage: Q.is_adjoint() # optional - sage.symbolic + sage: Q.is_adjoint() # needs sage.symbolic False sage: Q.adjoint().is_adjoint() True @@ -293,17 +293,18 @@ def hasse_conductor(self): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) - sage: Q.hasse_invariant(2) # optional - sage.libs.pari + sage: Q.hasse_invariant(2) -1 - sage: Q.hasse_invariant(37) # optional - sage.libs.pari + sage: Q.hasse_invariant(37) -1 - sage: Q.hasse_conductor() # optional - sage.libs.pari + sage: Q.hasse_conductor() 74 - sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor() # optional - sage.libs.pari + sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor() # needs sage.libs.pari 1 - sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor() # optional - sage.libs.pari + sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor() # needs sage.libs.pari 10 """ return prod([x[0] for x in factor(2 * self.level()) @@ -322,14 +323,15 @@ def clifford_invariant(self, p): For hyperbolic spaces, the Clifford invariant is +1:: + sage: # needs sage.libs.pari sage: H = QuadraticForm(ZZ, 2, [0, 1, 0]) - sage: H.clifford_invariant(2) # optional - sage.libs.pari + sage: H.clifford_invariant(2) 1 - sage: (H + H).clifford_invariant(2) # optional - sage.libs.pari + sage: (H + H).clifford_invariant(2) 1 - sage: (H + H + H).clifford_invariant(2) # optional - sage.libs.pari + sage: (H + H + H).clifford_invariant(2) 1 - sage: (H + H + H + H).clifford_invariant(2) # optional - sage.libs.pari + sage: (H + H + H + H).clifford_invariant(2) 1 """ n = self.dim() % 8 @@ -356,29 +358,31 @@ def clifford_conductor(self): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) - sage: Q.clifford_invariant(2) # optional - sage.libs.pari + sage: Q.clifford_invariant(2) 1 - sage: Q.clifford_invariant(37) # optional - sage.libs.pari + sage: Q.clifford_invariant(37) -1 - sage: Q.clifford_conductor() # optional - sage.libs.pari + sage: Q.clifford_conductor() 37 - sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).clifford_conductor() # optional - sage.libs.pari + sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).clifford_conductor() # needs sage.libs.pari 2 - sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor() # optional - sage.libs.pari + sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor() # needs sage.libs.pari 30 For hyperbolic spaces, the Clifford conductor is 1:: + sage: # needs sage.libs.pari sage: H = QuadraticForm(ZZ, 2, [0, 1, 0]) - sage: H.clifford_conductor() # optional - sage.libs.pari + sage: H.clifford_conductor() 1 - sage: (H + H).clifford_conductor() # optional - sage.libs.pari + sage: (H + H).clifford_conductor() 1 - sage: (H + H + H).clifford_conductor() # optional - sage.libs.pari + sage: (H + H + H).clifford_conductor() 1 - sage: (H + H + H + H).clifford_conductor() # optional - sage.libs.pari + sage: (H + H + H + H).clifford_conductor() 1 """ return prod([x[0] for x in factor(2 * self.level()) @@ -460,10 +464,10 @@ def xi(self, p): sage: Q2 = QuadraticForm(ZZ, 3, [2, -1, 0, 2, 0, 50]) sage: [Q1.omega(), Q2.omega()] [5, 5] - sage: [Q1.hasse_invariant(5), # equivalent over Q_5 # optional - sage.libs.pari + sage: [Q1.hasse_invariant(5), # equivalent over Q_5 # needs sage.libs.pari ....: Q2.hasse_invariant(5)] [1, 1] - sage: [Q1.xi(5), Q2.xi(5)] # not equivalent over Z_5 # optional - sage.libs.pari + sage: [Q1.xi(5), Q2.xi(5)] # not equivalent over Z_5 # needs sage.libs.pari [1, -1] """ if self.dim() == 2 and self.disc() % p: @@ -481,20 +485,21 @@ def xi_rec(self,p): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q1 = QuadraticForm(ZZ, 3, [1, 1, 1, 14, 3, 14]) sage: Q2 = QuadraticForm(ZZ, 3, [2, -1, 0, 2, 0, 50]) - sage: [Q1.clifford_conductor(), # equivalent over Q # optional - sage.libs.pari + sage: [Q1.clifford_conductor(), # equivalent over Q ....: Q2.clifford_conductor()] [3, 3] - sage: Q1.is_locally_equivalent_to(Q2) # not in the same genus # optional - sage.libs.pari + sage: Q1.is_locally_equivalent_to(Q2) # not in the same genus False - sage: [Q1.delta(), Q2.delta()] # optional - sage.libs.pari + sage: [Q1.delta(), Q2.delta()] [480, 480] - sage: factor(480) # optional - sage.libs.pari + sage: factor(480) 2^5 * 3 * 5 - sage: list(map(Q1.xi_rec, [-1,2,3,5])) # optional - sage.libs.pari + sage: list(map(Q1.xi_rec, [-1,2,3,5])) [-1, -1, -1, 1] - sage: list(map(Q2.xi_rec, [-1,2,3,5])) # optional - sage.libs.pari + sage: list(map(Q2.xi_rec, [-1,2,3,5])) [-1, -1, -1, -1] """ return self.reciprocal().xi(p) @@ -509,7 +514,7 @@ def lll(self): sage: Q = QuadraticForm(ZZ, 4, range(1,11)) sage: Q.is_definite() True - sage: Q.lll() + sage: Q.lll() # needs sage.libs.pari Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 1 0 ] [ * 4 3 3 ] @@ -526,7 +531,7 @@ def representation_number_list(self, B): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1,1,1,1]) - sage: Q.representation_number_list(10) # optional - sage.libs.pari + sage: Q.representation_number_list(10) # needs sage.libs.pari [1, 16, 112, 448, 1136, 2016, 3136, 5504, 9328, 12112] """ from sage.libs.pari.all import pari @@ -543,8 +548,9 @@ def representation_vector_list(self, B, maxvectors=10**8): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q = DiagonalQuadraticForm(ZZ, [1, 1]) - sage: Q.representation_vector_list(10) # optional - sage.libs.pari + sage: Q.representation_vector_list(10) [[(0, 0)], [(0, 1), (0, -1), (1, 0), (-1, 0)], [(1, 1), (-1, -1), (1, -1), (-1, 1)], @@ -555,20 +561,20 @@ def representation_vector_list(self, B, maxvectors=10**8): [], [(2, 2), (-2, -2), (2, -2), (-2, 2)], [(0, 3), (0, -3), (3, 0), (-3, 0)]] - sage: list(map(len, _)) # optional - sage.libs.pari + sage: list(map(len, _)) [1, 4, 4, 0, 4, 8, 0, 0, 4, 4] - sage: Q.representation_number_list(10) # optional - sage.libs.pari + sage: Q.representation_number_list(10) [1, 4, 4, 0, 4, 8, 0, 0, 4, 4] TESTS:: sage: R = QuadraticForm(ZZ, 2, [-4,-3,0]) - sage: R.representation_vector_list(10) # optional - sage.libs.pari + sage: R.representation_vector_list(10) # needs sage.libs.pari Traceback (most recent call last): ... PariError: domain error in minim0: form is not positive definite """ - n, m, vs = self.__pari__().qfminim(2 * (B - 1), maxvectors) + n, _, vs = self.__pari__().qfminim(2 * (B - 1), maxvectors) if n != 2 * len(vs): raise RuntimeError("insufficient number of vectors") diff --git a/src/sage/quadratic_forms/quadratic_form__theta.py b/src/sage/quadratic_forms/quadratic_form__theta.py index 98b955f60e4..7aa257d5e71 100644 --- a/src/sage/quadratic_forms/quadratic_form__theta.py +++ b/src/sage/quadratic_forms/quadratic_form__theta.py @@ -43,10 +43,10 @@ def theta_series(self, Max=10, var_str='q', safe_flag=True): EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) - sage: Q.theta_series() # optional - sage.libs.pari + sage: Q.theta_series() # needs sage.libs.pari 1 + 2*q + 2*q^3 + 6*q^4 + 2*q^5 + 4*q^6 + 6*q^7 + 8*q^8 + 14*q^9 + O(q^10) - sage: Q.theta_series(25) # optional - sage.libs.pari + sage: Q.theta_series(25) # needs sage.libs.pari 1 + 2*q + 2*q^3 + 6*q^4 + 2*q^5 + 4*q^6 + 6*q^7 + 8*q^8 + 14*q^9 + 4*q^10 + 12*q^11 + 18*q^12 + 12*q^13 + 12*q^14 + 8*q^15 + 34*q^16 + 12*q^17 + 8*q^18 + 32*q^19 + 10*q^20 + 28*q^21 + 16*q^23 + 44*q^24 + O(q^25) @@ -98,10 +98,10 @@ def theta_by_pari(self, Max, var_str='q', safe_flag=True): sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Prec = 100 - sage: compute = Q.theta_by_pari(Prec, '') # optional - sage.libs.pari - sage: exact = [1] + [8 * sum([d for d in divisors(i) if d % 4 != 0]) # optional - sage.libs.pari + sage: compute = Q.theta_by_pari(Prec, '') # needs sage.libs.pari + sage: exact = [1] + [8 * sum([d for d in divisors(i) if d % 4 != 0]) # needs sage.libs.pari ....: for i in range(1, Prec)] - sage: compute == exact # optional - sage.libs.pari + sage: compute == exact # needs sage.libs.pari True """ @@ -287,6 +287,7 @@ def theta_series_degree_2(Q, prec): EXAMPLES:: + sage: # needs sage.symbolic sage: Q2 = QuadraticForm(ZZ, 4, [1,1,1,1, 1,0,0, 1,0, 1]) sage: S = Q2.theta_series_degree_2(10) sage: S[(0,0,2)] diff --git a/src/sage/quadratic_forms/special_values.py b/src/sage/quadratic_forms/special_values.py index 93a56c45c8c..2ee775e053d 100644 --- a/src/sage/quadratic_forms/special_values.py +++ b/src/sage/quadratic_forms/special_values.py @@ -38,22 +38,24 @@ def gamma__exact(n): sage: gamma__exact(1) 1 - sage: gamma__exact(1/2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: gamma__exact(1/2) sqrt(pi) - sage: gamma__exact(3/2) # optional - sage.symbolic + sage: gamma__exact(3/2) 1/2*sqrt(pi) - sage: gamma__exact(5/2) # optional - sage.symbolic + sage: gamma__exact(5/2) 3/4*sqrt(pi) - sage: gamma__exact(7/2) # optional - sage.symbolic + sage: gamma__exact(7/2) 15/8*sqrt(pi) - sage: gamma__exact(-1/2) # optional - sage.symbolic + sage: # needs sage.symbolic + sage: gamma__exact(-1/2) -2*sqrt(pi) - sage: gamma__exact(-3/2) # optional - sage.symbolic + sage: gamma__exact(-3/2) 4/3*sqrt(pi) - sage: gamma__exact(-5/2) # optional - sage.symbolic + sage: gamma__exact(-5/2) -8/15*sqrt(pi) - sage: gamma__exact(-7/2) # optional - sage.symbolic + sage: gamma__exact(-7/2) 16/105*sqrt(pi) TESTS:: @@ -89,6 +91,7 @@ def gamma__exact(n): raise TypeError("you must give an integer or half-integer argument") + # ------------- The Riemann Zeta Function -------------- def zeta__exact(n): @@ -105,8 +108,9 @@ def zeta__exact(n): Let us test the accuracy for negative special values:: sage: RR = RealField(100) - sage: for i in range(1,10): - ....: print("zeta({}): {}".format(1-2*i, RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i)))) + sage: for i in range(1,10): # needs sage.symbolic + ....: print("zeta({}): {}".format(1 - 2*i, + ....: RR(zeta__exact(1-2*i)) - zeta(RR(1-2*i)))) zeta(-1): 0.00000000000000000000000000000 zeta(-3): 0.00000000000000000000000000000 zeta(-5): 0.00000000000000000000000000000 @@ -119,12 +123,13 @@ def zeta__exact(n): Let us test the accuracy for positive special values:: - sage: all(abs(RR(zeta__exact(2*i)) - zeta(RR(2*i))) < 10**(-28) for i in range(1,10)) + sage: all(abs(RR(zeta__exact(2*i)) - zeta(RR(2*i))) < 10**(-28) # needs sage.symbolic + ....: for i in range(1,10)) True TESTS:: - sage: zeta__exact(4) # optional - sage.symbolic + sage: zeta__exact(4) # needs sage.symbolic 1/90*pi^4 sage: zeta__exact(-3) 1/120 @@ -155,6 +160,7 @@ def zeta__exact(n): elif n == 0: return QQ((-1, 2)) + # ---------- Dirichlet L-functions with quadratic characters ---------- def QuadraticBernoulliNumber(k, d): @@ -166,13 +172,13 @@ def QuadraticBernoulliNumber(k, d): Let us create a list of some odd negative fundamental discriminants:: - sage: test_set = [d for d in srange(-163, -3, 4) # optional - sage.libs.pari + sage: test_set = [d for d in srange(-163, -3, 4) # needs sage.libs.pari ....: if d.is_fundamental_discriminant()] In general, we have `B_{1, \chi_d} = -2 h/w` for odd negative fundamental discriminants:: - sage: all(QuadraticBernoulliNumber(1, d) # optional - sage.libs.pari + sage: all(QuadraticBernoulliNumber(1, d) # needs sage.libs.pari ....: == -len(BinaryQF_reduced_representatives(d)) ....: for d in test_set) True @@ -207,16 +213,16 @@ def quadratic_L_function__exact(n, d): EXAMPLES:: - sage: quadratic_L_function__exact(1, -4) # optional - sage.libs.pari sage.symbolic + sage: quadratic_L_function__exact(1, -4) # needs sage.libs.pari sage.symbolic 1/4*pi - sage: quadratic_L_function__exact(-4, -4) # optional - sage.libs.pari + sage: quadratic_L_function__exact(-4, -4) # needs sage.libs.pari 5/2 - sage: quadratic_L_function__exact(2, 1) # optional - sage.libs.pari sage.symbolic + sage: quadratic_L_function__exact(2, 1) # needs sage.libs.pari sage.symbolic 1/6*pi^2 TESTS:: - sage: quadratic_L_function__exact(2, -4) # optional - sage.libs.pari + sage: quadratic_L_function__exact(2, -4) # needs sage.libs.pari Traceback (most recent call last): ... TypeError: n must be a critical value (i.e. odd > 0 or even <= 0) @@ -228,7 +234,7 @@ def quadratic_L_function__exact(n, d): - [Was1997]_ """ if n <= 0: - return QuadraticBernoulliNumber(1-n,d)/(n-1) + return QuadraticBernoulliNumber(1-n, d)/(n-1) elif n >= 1: # Compute the kind of critical values (p10) if kronecker_symbol(fundamental_discriminant(d), -1) == 1: @@ -251,7 +257,7 @@ def quadratic_L_function__exact(n, d): ans *= (2*pi/f)**n ans *= GS # Evaluate the Gauss sum here! =0 ans *= QQ.one()/(2 * I**delta) - ans *= QuadraticBernoulliNumber(n,d)/factorial(n) + ans *= QuadraticBernoulliNumber(n, d)/factorial(n) return ans else: if delta == 0: @@ -270,7 +276,7 @@ def quadratic_L_function__numerical(n, d, num_terms=1000): First, let us test several values for a given character:: sage: RR = RealField(100) - sage: for i in range(5): + sage: for i in range(5): # needs sage.symbolic ....: print("L({}, (-4/.)): {}".format(1+2*i, ....: RR(quadratic_L_function__exact(1+2*i, -4)) ....: - quadratic_L_function__numerical(RR(1+2*i), -4, 10000))) @@ -291,7 +297,7 @@ def quadratic_L_function__numerical(n, d, num_terms=1000): Test for several characters that the result agrees with the exact value, to a given accuracy :: - sage: for d in range(-20,0): # long time (2s on sage.math 2014) + sage: for d in range(-20,0): # long time (2s on sage.math 2014), needs sage.symbolic ....: if abs(RR(quadratic_L_function__numerical(1, d, 10000) ....: - quadratic_L_function__exact(1, d))) > 0.001: ....: print("We have a problem at d = {}: exact = {}, numerical = {}".format(d, @@ -310,6 +316,6 @@ def quadratic_L_function__numerical(n, d, num_terms=1000): d1 = fundamental_discriminant(d) ans = R.zero() - for i in range(1,num_terms): - ans += R(kronecker_symbol(d1,i) / R(i)**n) + for i in range(1, num_terms): + ans += R(kronecker_symbol(d1, i) / R(i)**n) return ans diff --git a/src/sage/quadratic_forms/ternary.pyx b/src/sage/quadratic_forms/ternary.pyx index 93b248becf6..ddcfbfdb6a9 100644 --- a/src/sage/quadratic_forms/ternary.pyx +++ b/src/sage/quadratic_forms/ternary.pyx @@ -477,10 +477,10 @@ def pseudorandom_primitive_zero_mod_p(a, b, c, r, s, t, p): sage: Q = TernaryQF([1, 2, 2, -1, 0, 0]) sage: p = 1009 sage: from sage.quadratic_forms.ternary import pseudorandom_primitive_zero_mod_p - sage: v = pseudorandom_primitive_zero_mod_p(1, 2, 2, -1, 0, 0, p) # optional - sage.libs.pari - sage: v[2] # optional - sage.libs.pari + sage: v = pseudorandom_primitive_zero_mod_p(1, 2, 2, -1, 0, 0, p) # needs sage.libs.pari + sage: v[2] # needs sage.libs.pari 1 - sage: Q(v)%p # optional - sage.libs.pari + sage: Q(v)%p # needs sage.libs.pari 0 """ # [a, b, c, r, s, t] = Q.coefficients() @@ -579,19 +579,20 @@ def _find_zeros_mod_p(a, b, c, r, s, t, p): EXAMPLES:: + sage: # needs sage.libs.pari sage: from sage.quadratic_forms.ternary import _find_zeros_mod_p sage: Q = TernaryQF([1, 2, 2, -1, 0, 0]) sage: p = 1009 - sage: zeros_1009 = _find_zeros_mod_p(1, 2, 2, -1, 0, 0, p) # optional - sage.libs.pari - sage: len(zeros_1009) # optional - sage.libs.pari + sage: zeros_1009 = _find_zeros_mod_p(1, 2, 2, -1, 0, 0, p) + sage: len(zeros_1009) 1010 - sage: zeros_1009.sort() # optional - sage.libs.pari - sage: zeros_1009[0] # optional - sage.libs.pari + sage: zeros_1009.sort() + sage: zeros_1009[0] (0, 32, 1) sage: Q((0, 32, 1)) 2018 - sage: zeros_2 = _find_zeros_mod_p(1, 2, 2, -1, 0, 0, 2) # optional - sage.libs.pari - sage: zeros_2 # optional - sage.libs.pari + sage: zeros_2 = _find_zeros_mod_p(1, 2, 2, -1, 0, 0, 2) + sage: zeros_2 [(0, 1, 0), (0, 0, 1), (1, 1, 1)] """ if p == 2: @@ -913,7 +914,7 @@ def _find_p_neighbor_from_vec(a, b, c, r, s, t, p, v, mat=False): sage: Q.disc() 29 sage: v = (9, 7, 1) - sage: v in Q.find_zeros_mod_p(11) # optional - sage.libs.pari + sage: v in Q.find_zeros_mod_p(11) # needs sage.libs.pari True sage: q11, M = _find_p_neighbor_from_vec(1, 3, 3, -2, 0, -1, 11, v, mat=True) sage: Q11 = TernaryQF(q11) diff --git a/src/sage/quadratic_forms/ternary_qf.py b/src/sage/quadratic_forms/ternary_qf.py index ce74661ffdd..119e8dfdc24 100644 --- a/src/sage/quadratic_forms/ternary_qf.py +++ b/src/sage/quadratic_forms/ternary_qf.py @@ -815,10 +815,10 @@ def pseudorandom_primitive_zero_mod_p(self, p): (1, 2, 1) sage: Q((1, 2, 1)) 15 - sage: v = Q.pseudorandom_primitive_zero_mod_p(1009) # optional - sage.libs.pari - sage: Q(v) % 1009 # optional - sage.libs.pari + sage: v = Q.pseudorandom_primitive_zero_mod_p(1009) # needs sage.libs.pari + sage: Q(v) % 1009 # needs sage.libs.pari 0 - sage: v[2] # optional - sage.libs.pari + sage: v[2] # needs sage.libs.pari 1 """ [a,b,c,r,s,t] = self.coefficients() @@ -851,10 +851,10 @@ def find_zeros_mod_p(self, p): 3 * 13 * 19 sage: Q.find_zeros_mod_p(2) [(1, 0, 0), (1, 1, 0), (0, 0, 1)] - sage: zeros_17 = Q.find_zeros_mod_p(17) # optional - sage.libs.pari - sage: len(zeros_17) # optional - sage.libs.pari + sage: zeros_17 = Q.find_zeros_mod_p(17) # needs sage.libs.pari + sage: len(zeros_17) # needs sage.libs.pari 18 - sage: [Q(v)%17 for v in zeros_17] # optional - sage.libs.pari + sage: [Q(v)%17 for v in zeros_17] # needs sage.libs.pari [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] """ @@ -883,6 +883,7 @@ def find_p_neighbor_from_vec(self, p, v, mat=False): EXAMPLES:: + sage: # needs sage.libs.pari sage: Q = TernaryQF([1, 3, 3, -2, 0, -1]); Q Ternary quadratic form with integer coefficients: [1 3 3] @@ -890,18 +891,18 @@ def find_p_neighbor_from_vec(self, p, v, mat=False): sage: Q.disc() 29 sage: v = (9, 7, 1) - sage: v in Q.find_zeros_mod_p(11) # optional - sage.libs.pari + sage: v in Q.find_zeros_mod_p(11) True - sage: Q11, M = Q.find_p_neighbor_from_vec(11, v, mat=True) # optional - sage.libs.pari - sage: Q11 # optional - sage.libs.pari + sage: Q11, M = Q.find_p_neighbor_from_vec(11, v, mat=True) + sage: Q11 Ternary quadratic form with integer coefficients: [1 2 4] [-1 -1 0] - sage: M # optional - sage.libs.pari + sage: M [ -1 -5/11 7/11] [ 0 -10/11 3/11] [ 0 -3/11 13/11] - sage: Q(M) == Q11 # optional - sage.libs.pari + sage: Q(M) == Q11 True """ if mat: @@ -918,21 +919,21 @@ def find_p_neighbors(self, p, mat=False): EXAMPLES:: - sage: Q0 = TernaryQF([1, 3, 3, -2, 0, -1]) - sage: Q0 + sage: # needs sage.libs.pari + sage: Q0 = TernaryQF([1, 3, 3, -2, 0, -1]); Q0 Ternary quadratic form with integer coefficients: [1 3 3] [-2 0 -1] - sage: neig = Q0.find_p_neighbors(5) # optional - sage.libs.pari - sage: len(neig) # optional - sage.libs.pari + sage: neig = Q0.find_p_neighbors(5) + sage: len(neig) 6 sage: Q1 = TernaryQF([1, 1, 10, 1, 1, 1]) sage: Q2 = TernaryQF([1, 2, 4, -1, -1, 0]) - sage: neig.count(Q0) # optional - sage.libs.pari + sage: neig.count(Q0) 2 - sage: neig.count(Q1) # optional - sage.libs.pari + sage: neig.count(Q1) 1 - sage: neig.count(Q2) # optional - sage.libs.pari + sage: neig.count(Q2) 3 """ @@ -1669,14 +1670,16 @@ def _automorphisms_reduced_slow(self): sage: Q = TernaryQF([1, 1, 7, 0, 0, 0]) sage: Q.is_eisenstein_reduced() True - sage: auts = Q._automorphisms_reduced_slow() # long time (3s on sage.math, 2014) - sage: len(auts) # long time + + sage: # long time + sage: auts = Q._automorphisms_reduced_slow() # 3s on sage.math, 2014 + sage: len(auts) 8 - sage: A = auts[randint(0,7)] # long time - sage: Q(A) == Q # long time + sage: A = auts[randint(0,7)] + sage: Q(A) == Q True sage: Q = TernaryQF([3, 4, 5, 3, 3, 2]) - sage: Q._automorphisms_reduced_slow() # long time + sage: Q._automorphisms_reduced_slow() [ [1 0 0] [0 1 0] diff --git a/src/sage/quivers/representation.py b/src/sage/quivers/representation.py index 9c11eb8ad0e..db82cbd7c86 100644 --- a/src/sage/quivers/representation.py +++ b/src/sage/quivers/representation.py @@ -1297,10 +1297,7 @@ def copy(self): sage: v.get_element(1) (1, 0) """ - if hasattr(self, '__custom_name'): - name = self.__custom_name - else: - name = None + name = self.get_custom_name() return self.parent()(self._elems.copy(), name) #################################################################### diff --git a/src/sage/repl/configuration.py b/src/sage/repl/configuration.py index 1890dc207d4..cb255ef65b3 100644 --- a/src/sage/repl/configuration.py +++ b/src/sage/repl/configuration.py @@ -7,11 +7,11 @@ the IPython simple prompt is being used:: sage: cmd = 'print([sys.stdin.isatty(), sys.stdout.isatty()])' - sage: import pexpect - sage: output = pexpect.run( + sage: import pexpect # needs pexpect + sage: output = pexpect.run( # needs pexpect ....: 'bash -c \'echo "{0}" | sage\''.format(cmd), ....: ).decode('utf-8', 'surrogateescape') - sage: 'sage: [False, True]' in output + sage: 'sage: [False, True]' in output # needs pexpect True """ diff --git a/src/sage/repl/display/fancy_repr.py b/src/sage/repl/display/fancy_repr.py index 5c1191dc4f1..77949a4b578 100644 --- a/src/sage/repl/display/fancy_repr.py +++ b/src/sage/repl/display/fancy_repr.py @@ -181,19 +181,20 @@ def __call__(self, obj, p, cycle): EXAMPLES:: + sage: # needs sage.modules sage: from sage.repl.display.fancy_repr import LargeMatrixHelpRepr sage: M = identity_matrix(40) sage: pp = LargeMatrixHelpRepr() sage: pp.format_string(M) - "40 x 40 dense matrix over Integer Ring (use the '.str()' method to see the entries)" + "40 x 40 dense matrix over Integer Ring (use the '.str()' method...)" sage: pp.format_string([M, M]) '--- object not handled by representer ---' Leads to:: - sage: M - 40 x 40 dense matrix over Integer Ring (use the '.str()' method to see the entries) - sage: [M, M] + sage: M # needs sage.modules + 40 x 40 dense matrix over Integer Ring (use the '.str()' method...) + sage: [M, M] # needs sage.modules [40 x 40 dense matrix over Integer Ring, 40 x 40 dense matrix over Integer Ring] """ @@ -312,7 +313,7 @@ def __call__(self, obj, p, cycle): sage: from sage.repl.display.fancy_repr import TallListRepr sage: format_list = TallListRepr().format_string - sage: format_list([1, 2, identity_matrix(2)]) + sage: format_list([1, 2, identity_matrix(2)]) # needs sage.modules '[\n [1 0]\n1, 2, [0 1]\n]' Check that :trac:`18743` is fixed:: diff --git a/src/sage/repl/display/formatter.py b/src/sage/repl/display/formatter.py index f8a47d3636b..822a9edfaba 100644 --- a/src/sage/repl/display/formatter.py +++ b/src/sage/repl/display/formatter.py @@ -24,17 +24,17 @@ sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell('%display ascii_art') - sage: shell.run_cell('integral(x^2/pi^x, x)') + sage: shell.run_cell('integral(x^2/pi^x, x)') # needs sage.symbolic -x / 2 2 \ -pi *\x *log (pi) + 2*x*log(pi) + 2/ -------------------------------------- 3 log (pi) - sage: shell.run_cell("i = var('i')") - sage: shell.run_cell('sum(i*x^i, i, 0, 10)') + sage: shell.run_cell("i = var('i')") # needs sage.symbolic + sage: shell.run_cell('sum(i*x^i, i, 0, 10)') # needs sage.symbolic 10 9 8 7 6 5 4 3 2 10*x + 9*x + 8*x + 7*x + 6*x + 5*x + 4*x + 3*x + 2*x + x - sage: shell.run_cell('StandardTableaux(4).list()') + sage: shell.run_cell('StandardTableaux(4).list()') # needs sage.combinat [ [ 1 4 1 3 [ 1 3 4 1 2 4 1 2 3 1 3 1 2 2 2 @@ -121,7 +121,7 @@ def format(self, obj, include=None, exclude=None): EXAMPLES:: - sage: [identity_matrix(i) for i in range(3,7)] + sage: [identity_matrix(i) for i in range(3,7)] # needs sage.modules [ [1 0 0 0 0 0] [1 0 0 0 0] [0 1 0 0 0 0] @@ -133,8 +133,8 @@ def format(self, obj, include=None, exclude=None): sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell('%display ascii_art') # indirect doctest - sage: shell.run_cell("i = var('i')") - sage: shell.run_cell('sum(i*x^i, i, 0, 10)') + sage: shell.run_cell("i = var('i')") # needs sage.symbolic + sage: shell.run_cell('sum(i*x^i, i, 0, 10)') # needs sage.symbolic 10 9 8 7 6 5 4 3 2 10*x + 9*x + 8*x + 7*x + 6*x + 5*x + 4*x + 3*x + 2*x + x sage: shell.run_cell('%display default') @@ -229,11 +229,11 @@ def _ipython_float_precision_changed(change): sage: shell = get_test_shell() sage: shell.run_cell('%precision 4') '%.4f' - sage: shell.run_cell('matrix.options.precision') # indirect doctest + sage: shell.run_cell('matrix.options.precision') # indirect doctest # needs sage.modules 4 sage: shell.run_cell('%precision') '%r' - sage: shell.run_cell('matrix.options.precision') # indirect doctest + sage: shell.run_cell('matrix.options.precision') # indirect doctest # needs sage.modules None """ from sage.matrix.constructor import options @@ -305,8 +305,8 @@ def __call__(self, obj): sage: fmt(2) ---- calling ipython formatter ---- '2' - sage: a = identity_matrix(ZZ, 2) - sage: fmt([a, a]) + sage: a = identity_matrix(ZZ, 2) # needs sage.modules + sage: fmt([a, a]) # needs sage.modules ---- calling ipython formatter ---- '[\n[1 0] [1 0]\n[0 1], [0 1]\n]' """ diff --git a/src/sage/repl/display/jsmol_iframe.py b/src/sage/repl/display/jsmol_iframe.py index 4775d2a02e7..f8e69cfcb59 100644 --- a/src/sage/repl/display/jsmol_iframe.py +++ b/src/sage/repl/display/jsmol_iframe.py @@ -112,7 +112,7 @@ def __init__(self, jmol, path_to_jsmol=None, width='100%', height='100%'): EXAMPLES:: sage: from sage.repl.display.jsmol_iframe import JSMolHtml - sage: JSMolHtml(sphere(), width=500, height=300) + sage: JSMolHtml(sphere(), width=500, height=300) # needs sage.plot JSmol Window 500x300 """ from sage.repl.rich_output.output_graphics3d import OutputSceneJmol diff --git a/src/sage/repl/display/util.py b/src/sage/repl/display/util.py index ac8f3191723..a2033c69f4f 100644 --- a/src/sage/repl/display/util.py +++ b/src/sage/repl/display/util.py @@ -74,7 +74,7 @@ def try_format(self, the_list): TESTS:: sage: from sage.repl.display.util import format_list - sage: print(format_list.try_format( + sage: print(format_list.try_format( # needs sage.modules ....: [matrix([[1, 2, 3, 4], [5, 6, 7, 8]]) for i in range(7)])) [ [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] diff --git a/src/sage/repl/interface_magic.py b/src/sage/repl/interface_magic.py index 9662603cbdd..b77bc09e972 100644 --- a/src/sage/repl/interface_magic.py +++ b/src/sage/repl/interface_magic.py @@ -121,9 +121,9 @@ def register_all(cls, shell=None): ... ('maxima', 'line') ('maxima', 'cell') - sage: 'gap' in MockShell.magics + sage: 'gap' in MockShell.magics # needs sage.libs.gap True - sage: 'maxima' in MockShell.magics + sage: 'maxima' in MockShell.magics # needs sage.symbolic True """ if shell is None: @@ -159,7 +159,7 @@ def find(cls, name): EXAMPLES:: sage: from sage.repl.interface_magic import InterfaceMagic - sage: InterfaceMagic.find('gap') + sage: InterfaceMagic.find('gap') # needs sage.libs.gap """ for magic in cls.all_iter(): @@ -183,7 +183,7 @@ def __init__(self, name, interface): EXAMPLES:: sage: from sage.repl.interface_magic import InterfaceMagic - sage: InterfaceMagic.find('gap') + sage: InterfaceMagic.find('gap') # needs sage.libs.gap """ self._name = name @@ -199,6 +199,7 @@ def line_magic_factory(self): EXAMPLES:: + sage: # needs sage.libs.gap sage: from sage.repl.interface_magic import InterfaceMagic sage: line_magic = InterfaceMagic.find('gap').line_magic_factory() sage: output = line_magic('1+1') @@ -211,9 +212,9 @@ def line_magic_factory(self): sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() - sage: shell.run_cell('%gap 1+1') + sage: shell.run_cell('%gap 1+1') # needs sage.libs.gap 2 - sage: shell.run_cell('%gap?') + sage: shell.run_cell('%gap?') # needs sage.libs.gap Docstring: Interact with gap @@ -243,6 +244,7 @@ def cell_magic_factory(self): EXAMPLES:: + sage: # needs sage.libs.gap sage: from sage.repl.interface_magic import InterfaceMagic sage: cell_magic = InterfaceMagic.find('gap').cell_magic_factory() sage: output = cell_magic('', '1+1;') @@ -258,15 +260,15 @@ def cell_magic_factory(self): sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() - sage: shell.run_cell('%%gap\nG:=SymmetricGroup(5);\n1+1;Order(G);') + sage: shell.run_cell('%%gap\nG:=SymmetricGroup(5);\n1+1;Order(G);') # needs sage.libs.gap Sym( [ 1 .. 5 ] ) 2 120 - sage: shell.run_cell('%%gap foo\n1+1;\n') + sage: shell.run_cell('%%gap foo\n1+1;\n') # needs sage.libs.gap ...File...... SyntaxError: Interface magics have no options, got "foo" - sage: shell.run_cell('%%gap?') + sage: shell.run_cell('%%gap?') # needs sage.libs.gap Docstring: Interact with gap diff --git a/src/sage/repl/interpreter.py b/src/sage/repl/interpreter.py index 8ef2341ebfb..c8fd27b35fa 100644 --- a/src/sage/repl/interpreter.py +++ b/src/sage/repl/interpreter.py @@ -508,6 +508,7 @@ def __init__(self, *args, **kwds): TESTS:: + sage: # needs sage.symbolic sage: from sage.repl.interpreter import interface_shell_embed sage: shell = interface_shell_embed(maxima) sage: ift = shell.prefilter_manager.transformers[0] @@ -535,9 +536,11 @@ def preparse_imports_from_sage(self, line): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer sage: shell = interface_shell_embed(maxima) - sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager) + sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, + ....: prefilter_manager=shell.prefilter_manager) sage: ift.shell.ex('a = 3') sage: ift.preparse_imports_from_sage('2 + sage(a)') '2 + sage0 ' @@ -551,9 +554,11 @@ def preparse_imports_from_sage(self, line): Since :trac:`28439`, this also works with more complicated expressions containing nested parentheses:: + sage: # needs sage.libs.gap sage.symbolic sage: shell = interface_shell_embed(gap) sage: shell.user_ns = locals() - sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager) + sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, + ....: prefilter_manager=shell.prefilter_manager) sage: line = '2 + sage((1+2)*gap(-(5-3)^2).sage()) - gap(1+(2-1))' sage: line = ift.preparse_imports_from_sage(line) sage: gap.eval(line) @@ -587,9 +592,11 @@ def transform(self, line, continue_prompt): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer sage: shell = interface_shell_embed(maxima) - sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager) + sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, + ....: prefilter_manager=shell.prefilter_manager) sage: ift.transform('2+2', False) # note: output contains triple quotation marks 'sage.repl.interpreter.logstr(r"""4""")' sage: ift.shell.ex('a = 4') @@ -597,8 +604,9 @@ def transform(self, line, continue_prompt): 'sage.repl.interpreter.logstr(r"""8""")' sage: ift.temporary_objects set() - sage: shell = interface_shell_embed(gap) - sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager) + sage: shell = interface_shell_embed(gap) # needs sage.libs.gap + sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, # needs sage.libs.gap + ....: prefilter_manager=shell.prefilter_manager) sage: ift.transform('2+2', False) 'sage.repl.interpreter.logstr(r"""4""")' @@ -607,14 +615,17 @@ def transform(self, line, continue_prompt): Check that whitespace is not stripped and that special characters are escaped (:trac:`28439`):: - sage: shell = interface_shell_embed(gap) - sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager) - sage: ift.transform(r'Print(" -\n\\\\- ");', False) + sage: shell = interface_shell_embed(gap) # needs sage.libs.gap sage.symbolic + sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, # needs sage.libs.gap sage.symbolic + ....: prefilter_manager=shell.prefilter_manager) + sage: ift.transform(r'Print(" -\n\\\\- ");', False) # needs sage.symbolic 'sage.repl.interpreter.logstr(r""" -\n\\\\-""")' - sage: shell = interface_shell_embed(macaulay2) # optional - macaulay2 - sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager) # optional - macaulay2 - sage: ift.transform('net(ZZ^2)', False) # optional - macaulay2 + sage: # optional - macaulay2 + sage: shell = interface_shell_embed(macaulay2) + sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, + ....: prefilter_manager=shell.prefilter_manager) + sage: ift.transform('net(ZZ^2)', False) 'sage.repl.interpreter.logstr(r""" 2\nZZ""")' ''' line = self.preparse_imports_from_sage(line) @@ -644,8 +655,8 @@ def interface_shell_embed(interface): EXAMPLES:: sage: from sage.repl.interpreter import interface_shell_embed - sage: shell = interface_shell_embed(gap) - sage: shell.run_cell('List( [1..10], IsPrime )') + sage: shell = interface_shell_embed(gap) # needs sage.libs.gap + sage: shell.run_cell('List( [1..10], IsPrime )') # needs sage.libs.gap [ false, true, true, false, true, false, true, false, false, false ] """ diff --git a/src/sage/repl/ipython_extension.py b/src/sage/repl/ipython_extension.py index 4ea72a97b1b..14c945a8517 100644 --- a/src/sage/repl/ipython_extension.py +++ b/src/sage/repl/ipython_extension.py @@ -221,8 +221,8 @@ def display(self, args): That means you do not have to use :func:`ascii_art` to get an ASCII art output:: - sage: shell.run_cell("i = var('i')") - sage: shell.run_cell('sum(i^2*x^i, i, 0, 10)') + sage: shell.run_cell("i = var('i')") # needs sage.symbolic + sage: shell.run_cell('sum(i^2*x^i, i, 0, 10)') # needs sage.symbolic 10 9 8 7 6 5 4 3 2 100*x + 81*x + 64*x + 49*x + 36*x + 25*x + 16*x + 9*x + 4*x + x @@ -230,14 +230,14 @@ def display(self, args): sage: shell.run_cell('%display text plain') sage: shell.run_cell('%display plain') # shortcut for "text plain" - sage: shell.run_cell('sum(i^2*x^i, i, 0, 10)') + sage: shell.run_cell('sum(i^2*x^i, i, 0, 10)') # needs sage.symbolic 100*x^10 + 81*x^9 + 64*x^8 + 49*x^7 + 36*x^6 + 25*x^5 + 16*x^4 + 9*x^3 + 4*x^2 + x Sometime you could have to use a special output width and you could specify it:: sage: shell.run_cell('%display ascii_art') - sage: shell.run_cell('StandardTableaux(4).list()') + sage: shell.run_cell('StandardTableaux(4).list()') # needs sage.combinat [ [ 1 4 1 3 [ 1 3 4 1 2 4 1 2 3 1 3 1 2 2 2 @@ -248,7 +248,7 @@ def display(self, args): 3 3 ] 4 , 4 ] sage: shell.run_cell('%display ascii_art 50') - sage: shell.run_cell('StandardTableaux(4).list()') + sage: shell.run_cell('StandardTableaux(4).list()') # needs sage.combinat [ [ [ 1 3 4 1 2 4 1 2 3 @@ -352,12 +352,13 @@ def cython(self, line, cell): sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() - sage: shell.run_cell(''' + sage: shell.run_cell( # needs sage.misc.cython + ....: ''' ....: %%cython ....: def f(): ....: print('test') ....: ''') - sage: f() + sage: f() # needs sage.misc.cython test """ from sage.misc.cython import cython_compile @@ -383,6 +384,7 @@ def fortran(self, line, cell): EXAMPLES:: + sage: # needs numpy sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell(''' diff --git a/src/sage/repl/ipython_kernel/interact.py b/src/sage/repl/ipython_kernel/interact.py index f13d488ff93..0551c83480e 100644 --- a/src/sage/repl/ipython_kernel/interact.py +++ b/src/sage/repl/ipython_kernel/interact.py @@ -51,7 +51,6 @@ def f(x=(0, 10)): from collections import OrderedDict from collections.abc import Iterable, Iterator from .widgets import EvalText, SageColorPicker -from .widgets_sagenb import input_grid from sage.structure.element import parent import sage.rings.abc from sage.misc.lazy_import import lazy_import @@ -182,16 +181,18 @@ def widget_from_single_value(cls, abbrev, *args, **kwds): sage: from sage.repl.ipython_kernel.interact import sage_interactive sage: sage_interactive.widget_from_single_value("sin(x)") ...Text(value='sin(x)') - sage: sage_interactive.widget_from_single_value(sin(x)) + sage: sage_interactive.widget_from_single_value(sin(x)) # needs sage.symbolic ...EvalText(value='sin(x)') - sage: from sage.plot.colors import Color - sage: sage_interactive.widget_from_single_value(matrix([[1, 2], [3, 4]])) + sage: sage_interactive.widget_from_single_value(matrix([[1, 2], [3, 4]])) # needs sage.modules ...Grid(value=[[1, 2], [3, 4]], children=(Label(value=''), VBox(children=(EvalText(value='1', layout=Layout(max_width='5em')), EvalText(value='3', layout=Layout(max_width='5em')))), VBox(children=(EvalText(value='2', layout=Layout(max_width='5em')), EvalText(value='4', layout=Layout(max_width='5em')))))) - sage: sage_interactive.widget_from_single_value(Color('cornflowerblue')) + sage: from sage.plot.colors import Color # needs sage.plot + sage: sage_interactive.widget_from_single_value(Color('cornflowerblue')) # needs sage.plot ...SageColorPicker(value='#6495ed') """ # Support Sage matrices and colors if isinstance(abbrev, Matrix): + from .widgets_sagenb import input_grid + return input_grid(abbrev.nrows(), abbrev.ncols(), default=abbrev.list(), to_value=abbrev.parent()) if isinstance(abbrev, Color): @@ -226,15 +227,15 @@ def widget_from_tuple(cls, abbrev, *args, **kwds): ...IntSlider(value=3, max=10) sage: sage_interactive.widget_from_tuple((2, [('one', 1), ('two', 2), ('three', 3)])) ...Dropdown(index=1, options=(('one', 1), ('two', 2), ('three', 3)), value=2) - sage: sage_interactive.widget_from_tuple( (sqrt(2), pi) ) + sage: sage_interactive.widget_from_tuple( (sqrt(2), pi) ) # needs sage.symbolic ...FloatSlider(value=2.277903107981444, max=3.141592653589793, min=1.4142135623730951) TESTS: Symbolic subrings:: - sage: SCR = SR.subring(no_variables=True) - sage: sage_interactive.widget_from_tuple( (SCR(sqrt(2)), SCR(pi)) ) + sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic + sage: sage_interactive.widget_from_tuple( (SCR(sqrt(2)), SCR(pi)) ) # needs sage.symbolic ...FloatSlider(value=2.277903107981444, max=3.141592653589793, min=1.4142135623730951) """ # Support (description, abbrev) diff --git a/src/sage/repl/ipython_kernel/widgets.py b/src/sage/repl/ipython_kernel/widgets.py index 3ba45df9b04..14c879373a5 100644 --- a/src/sage/repl/ipython_kernel/widgets.py +++ b/src/sage/repl/ipython_kernel/widgets.py @@ -173,7 +173,7 @@ class EvalWidget(TransformWidget): sage: w = EvalToggleButtons(options=["pi", "e"], transform=lambda x: x+x) sage: w EvalToggleButtons(options=('pi', 'e'), value='pi') - sage: w.get_interact_value() + sage: w.get_interact_value() # needs sage.symbolic 2*pi """ def get_value(self): @@ -225,7 +225,7 @@ class TransformFloatSlider(TransformWidget, FloatSlider): sage: w = TransformFloatSlider(min=0, max=100, value=7, transform=lambda x: sqrt(x)) sage: w TransformFloatSlider(value=7.0) - sage: w.get_interact_value() + sage: w.get_interact_value() # needs sage.symbolic 2.6457513110645907 """ pass @@ -310,7 +310,7 @@ class EvalText(EvalWidget, Text): sage: w = EvalText(value="pi", transform=lambda x: x^2) sage: w EvalText(value='pi') - sage: w.get_interact_value() + sage: w.get_interact_value() # needs sage.symbolic pi^2 """ pass @@ -327,7 +327,7 @@ class EvalTextarea(EvalWidget, Textarea): sage: w = EvalTextarea(value="pi", transform=lambda x: x^2) sage: w EvalTextarea(value='pi') - sage: w.get_interact_value() + sage: w.get_interact_value() # needs sage.symbolic pi^2 """ pass @@ -351,7 +351,7 @@ def get_interact_value(self): EXAMPLES:: sage: from sage.repl.ipython_kernel.widgets import SageColorPicker - sage: SageColorPicker().get_interact_value() + sage: SageColorPicker().get_interact_value() # needs sage.plot RGB color (0.0, 0.0, 0.0) """ return Color(self.value) @@ -395,11 +395,13 @@ def __init__(self, nrows, ncols, make_widget, description=u"", transform=None): EXAMPLES:: sage: from sage.repl.ipython_kernel.widgets import Grid, EvalText - sage: w = Grid(2, 2, lambda i,j: EvalText(str(j+4*i)), - ....: description="2x2 matrix", transform=matrix) - sage: w - Grid(value=[[0, 1], [4, 5]], children=(Label(value='2x2 matrix'), VBox(children=(EvalText(value='0'), EvalText(value='4'))), VBox(children=(EvalText(value='1'), EvalText(value='5'))))) - sage: w.get_interact_value() + sage: w = Grid(2, 2, lambda i,j: EvalText(str(j+4*i)), # needs sage.modules + ....: description="2x2 matrix", transform=matrix); w + Grid(value=[[0, 1], [4, 5]], + children=(Label(value='2x2 matrix'), + VBox(children=(EvalText(value='0'), EvalText(value='4'))), + VBox(children=(EvalText(value='1'), EvalText(value='5'))))) + sage: w.get_interact_value() # needs sage.modules [0 1] [4 5] diff --git a/src/sage/repl/load.py b/src/sage/repl/load.py index d43363682b0..64329bfab11 100644 --- a/src/sage/repl/load.py +++ b/src/sage/repl/load.py @@ -132,7 +132,7 @@ def load(filename, globals, attach=False): sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 - sage: sage.repl.load.load(t, globals()) + sage: sage.repl.load.load(t, globals()) # needs sage.misc.cython Compiling ... ('hi', 1) sage: z diff --git a/src/sage/repl/preparse.py b/src/sage/repl/preparse.py index a051ec6e198..18ab18fdeaa 100644 --- a/src/sage/repl/preparse.py +++ b/src/sage/repl/preparse.py @@ -82,18 +82,19 @@ Symbolic functional notation:: - sage: a=10; f(theta, beta) = theta + beta; b = x^2 + theta # optional - sage.symbolic - sage: f # optional - sage.symbolic + sage: # needs sage.symbolic + sage: a=10; f(theta, beta) = theta + beta; b = x^2 + theta + sage: f (theta, beta) |--> beta + theta - sage: a # optional - sage.symbolic + sage: a 10 - sage: b # optional - sage.symbolic + sage: b x^2 + theta - sage: f(theta,theta) # optional - sage.symbolic + sage: f(theta,theta) 2*theta - sage: a = 5; f(x,y) = x*y*sqrt(a) # optional - sage.symbolic - sage: f # optional - sage.symbolic + sage: a = 5; f(x,y) = x*y*sqrt(a) # needs sage.symbolic + sage: f # needs sage.symbolic (x, y) |--> sqrt(5)*x*y This involves an =-, but should still be turned into a symbolic @@ -101,8 +102,8 @@ sage: preparse('a(x) =- 5') '__tmp__=var("x"); a = symbolic_expression(- Integer(5)).function(x)' - sage: f(x)=-x # optional - sage.symbolic - sage: f(10) # optional - sage.symbolic + sage: f(x)=-x # needs sage.symbolic + sage: f(10) # needs sage.symbolic -10 This involves -=, which should not be turned into a symbolic @@ -1719,7 +1720,7 @@ def preparse(line, reset=True, do_time=False, ignore_prompts=False, "ZZ = ZZ['u,v']; (x, y,) = ZZ._first_ngens(2)" sage: preparse("ZZ. = QQ[2^(1/3)]") 'ZZ = QQ[Integer(2)**(Integer(1)/Integer(3))]; (x,) = ZZ._first_ngens(1)' - sage: QQ[2^(1/3)] + sage: QQ[2^(1/3)] # needs sage.rings.number_field sage.symbolic Number Field in a with defining polynomial x^3 - 2 with a = 1.259921049894873? sage: preparse("a^b") @@ -1920,7 +1921,7 @@ def preparse_file(contents, globals=None, numeric_literals=True): ....: file.write(file_contents) 137 sage: load(t) - sage: sorted(list(func([11,17]))) + sage: sorted(list(func([11,17]))) # needs sage.modular [(((11,), {}), None), (((17,), {}), None)] """ if not isinstance(contents, str): diff --git a/src/sage/repl/rich_output/backend_base.py b/src/sage/repl/rich_output/backend_base.py index 73eac559668..9d76fc1ed76 100644 --- a/src/sage/repl/rich_output/backend_base.py +++ b/src/sage/repl/rich_output/backend_base.py @@ -459,6 +459,7 @@ def latex_formatter(self, obj, **kwds): sage: out.html.get_str() '\\(\\displaystyle \\frac{1}{2}\\)' + sage: # needs sage.symbolic sage: out = backend.latex_formatter([1/2, x, 3/4, ZZ], concatenate=False) sage: out.html.get_str() '\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\frac{1}{2}, x, \\frac{3}{4}, \\Bold{Z}\\right]\\)' diff --git a/src/sage/repl/rich_output/backend_doctest.py b/src/sage/repl/rich_output/backend_doctest.py index da9cb737a2a..69905f7b067 100644 --- a/src/sage/repl/rich_output/backend_doctest.py +++ b/src/sage/repl/rich_output/backend_doctest.py @@ -164,14 +164,14 @@ def displayhook(self, plain_text, rich_output): This ends up calling the displayhook:: - sage: plt = plot(sin) - sage: plt + sage: plt = plot(sin) # needs sage.plot sage.symbolic + sage: plt # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: plt.show() + sage: plt.show() # needs sage.plot sage.symbolic sage: from sage.repl.rich_output import get_display_manager sage: dm = get_display_manager() - sage: dm.displayhook(plt) # indirect doctest + sage: dm.displayhook(plt) # indirect doctest # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive """ self.validate(rich_output) @@ -198,14 +198,14 @@ def display_immediately(self, plain_text, rich_output): displayhook, the plot is still shown. Nothing is shown during doctests:: - sage: plt = plot(sin) - sage: plt + sage: plt = plot(sin) # needs sage.plot sage.symbolic + sage: plt # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: plt.show() + sage: plt.show() # needs sage.plot sage.symbolic sage: from sage.repl.rich_output import get_display_manager sage: dm = get_display_manager() - sage: dm.display_immediately(plt) # indirect doctest + sage: dm.display_immediately(plt) # indirect doctest # needs sage.plot sage.symbolic """ self.validate(rich_output) types_to_print = [OutputPlainText, OutputAsciiArt, OutputUnicodeArt, OutputHtml] diff --git a/src/sage/repl/rich_output/backend_ipython.py b/src/sage/repl/rich_output/backend_ipython.py index 6008c61bf39..86bdf342e3e 100644 --- a/src/sage/repl/rich_output/backend_ipython.py +++ b/src/sage/repl/rich_output/backend_ipython.py @@ -362,7 +362,7 @@ def launch_jmol(self, output_jmol, plain_text): sage: from sage.repl.rich_output.backend_ipython import BackendIPythonCommandline sage: backend = BackendIPythonCommandline() sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol - sage: backend.launch_jmol(OutputSceneJmol.example(), 'Graphics3d object') + sage: backend.launch_jmol(OutputSceneJmol.example(), 'Graphics3d object') # needs sage.plot 'Launched jmol viewer for Graphics3d object' """ from sage.doctest import DOCTEST_MODE @@ -410,7 +410,7 @@ def threejs_offline_scripts(self): sage: from sage.repl.rich_output.backend_ipython import BackendIPythonCommandline sage: backend = BackendIPythonCommandline() - sage: backend.threejs_offline_scripts() + sage: backend.threejs_offline_scripts() # needs sage.plot '...
\(2\) \(x\)