diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 96aae8fbc1a..4f2deec4545 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -100,7 +100,7 @@ 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' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3c53c936237..3dc4b8a4627 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -18,26 +18,23 @@ on: default: >- ["ubuntu-trusty-toolchain-gcc_9", "ubuntu-xenial-toolchain-gcc_9", - "ubuntu-bionic-gcc_8-python3.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", @@ -61,7 +58,6 @@ on: "opensuse-tumbleweed-python3.10", "conda-forge", "ubuntu-bionic-gcc_8-i386", - "debian-buster-i386", "debian-bullseye-i386", ] tox_packages_factors: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 883749e2bf7..32235871f0a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: - 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 @@ -31,7 +31,7 @@ jobs: - 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 @@ -45,7 +45,7 @@ jobs: - 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..af93972b61f --- /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@v3 + + - 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@v3 + + - 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/.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..28c23fbf791 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.beta0 doi: 10.5281/zenodo.593563 -date-released: 2023-08-20 +date-released: 2023-08-27 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..abb6a3b9b02 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.1, Release Date: 2023-08-20 +SageMath version 10.2.beta0, Release Date: 2023-08-27 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/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/dependencies b/build/pkgs/backports_zoneinfo/dependencies deleted file mode 100644 index 0738c2d7777..00000000000 --- a/build/pkgs/backports_zoneinfo/dependencies +++ /dev/null @@ -1,4 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -All lines of this file are ignored except the first. 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/backports_zoneinfo/type b/build/pkgs/backports_zoneinfo/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/backports_zoneinfo/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 6712dfd085c..d2d584f437f 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=d0a3737795390fc46d2cec3bf0f8c6548da2e08f +md5=10be304a3521209b8c8590824ef76587 +cksum=602858466 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 05d47f390a0..15f690e3523 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -aa220c4a1e34607d75d86b5abe022bd0c0358644 +b1ba78aff8355d0e4fc4cdea6ec08a521303e327 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/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/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/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/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/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/mathjax/distros/gentoo.txt b/build/pkgs/mathjax/distros/gentoo.txt new file mode 100644 index 00000000000..e0d633a9b98 --- /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/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/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/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/spkg-configure.m4 b/build/pkgs/python3/spkg-configure.m4 index 3efe191ff2c..5a0aa955633 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], diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index c92aca850f4..0d1dcecb3e5 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.2b0 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index e7a51281874..8cf2f31b2f2 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.2b0 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 19d640c75eb..88a7b2ff574 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.2b0 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 03bedff32a5..c2a7d96f110 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.2b0 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index cf9a3720e26..bc562bf85af 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.2b0 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index 37dc85dfa86..e00017923f1 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.2b0 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index f9c9912c022..1db4cd09d83 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.2b0 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index 29b48b35f85..4a48e2f8aa2 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.2b0 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index f582bef1437..9be4870435e 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.2b0 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index d0c9adf2723..7768fd4ba54 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.2b0 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index 42a5c6179d2..80d50f46fcf 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.2b0 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index 1ab7b2045b1..b2006819a8e 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.2b0 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index c8d676d3564..c122df3d9dc 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.2b0 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 410e38cd2f7..d6a51c48162 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.2b0 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index 93a6d0e5e7d..4a3bcfbb14e 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.2b0 diff --git a/build/pkgs/tzlocal/dependencies b/build/pkgs/tzlocal/dependencies index da4c8ca99cf..1d3b818d4ac 100644 --- a/build/pkgs/tzlocal/dependencies +++ b/build/pkgs/tzlocal/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) backports_zoneinfo pytz_deprecation_shim | $(PYTHON_TOOLCHAIN) +$(PYTHON) pytz_deprecation_shim | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. 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/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..3a3b0eaf5f2 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index ae425d69819..3a3b0eaf5f2 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 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..3a3b0eaf5f2 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.1 +10.2.beta0 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index a823b80cca4..ea26d4f4c0e 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.beta0' +SAGE_RELEASE_DATE='2023-08-27' +SAGE_VERSION_BANNER='SageMath version 10.2.beta0, Release Date: 2023-08-27' 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/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/references/index.rst b/src/doc/en/reference/references/index.rst index 475a34f5dea..94ebc11620f 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -807,6 +807,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`. @@ -2661,6 +2665,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. @@ -4581,6 +4588,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/sage/algebras/fusion_rings/f_matrix.py b/src/sage/algebras/fusion_rings/f_matrix.py index e178b567a3e..b8ba585b0f4 100644 --- a/src/sage/algebras/fusion_rings/f_matrix.py +++ b/src/sage/algebras/fusion_rings/f_matrix.py @@ -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 diff --git a/src/sage/algebras/fusion_rings/fusion_ring.py b/src/sage/algebras/fusion_rings/fusion_ring.py index 0e450281c1f..f10409539e3 100644 --- a/src/sage/algebras/fusion_rings/fusion_ring.py +++ b/src/sage/algebras/fusion_rings/fusion_ring.py @@ -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..69b2253143e 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 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..91c057d6007 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 """ diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 5ba4c1e5e70..23fe7c8b118 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 @@ -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)) @@ -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)) @@ -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)) @@ -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)) @@ -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/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/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/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 819a9e26efe..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 diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index 28904069e2b..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]) @@ -242,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])] """ @@ -265,11 +266,11 @@ 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") and module.one_basis is not NotImplemented for module in self._sets): @@ -319,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, @@ -345,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..3ccc82c7f21 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 diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index 83e88ef748a..242fc1e5683 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() @@ -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) @@ -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..a1adcc3c6c9 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) @@ -129,9 +130,9 @@ 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) @@ -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 @@ -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): diff --git a/src/sage/categories/category_with_axiom.py b/src/sage/categories/category_with_axiom.py index 2128dac2db9..c14d468246e 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'] 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..391c4f2272d 100644 --- a/src/sage/categories/commutative_ring_ideals.py +++ b/src/sage/categories/commutative_ring_ideals.py @@ -35,7 +35,7 @@ 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 diff --git a/src/sage/categories/commutative_rings.py b/src/sage/categories/commutative_rings.py index 6219c1070bb..b99fb7d8eb3 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) @@ -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..77d3f76fa1c 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 """ @@ -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 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..7e2a92edeb1 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 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/enumerated_sets.py b/src/sage/categories/enumerated_sets.py index de57384e2de..98c1a729fba 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' @@ -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..04511128301 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,7 +40,7 @@ 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()) @@ -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() diff --git a/src/sage/categories/examples/crystals.py b/src/sage/categories/examples/crystals.py index c38117b3b70..3378c9282d1 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 """ diff --git a/src/sage/categories/examples/filtered_modules_with_basis.py b/src/sage/categories/examples/filtered_modules_with_basis.py index 3cf9db3f57c..35edb3314dc 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,8 +143,8 @@ 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_() 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..0406e23c6e8 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 """ 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..58e613a6d45 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() diff --git a/src/sage/categories/examples/finite_semigroups.py b/src/sage/categories/examples/finite_semigroups.py index bf00b415b58..60766b5d9d0 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:: diff --git a/src/sage/categories/examples/finite_weyl_groups.py b/src/sage/categories/examples/finite_weyl_groups.py index b4d6c05a233..478728c9f0f 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): @@ -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..07afa9c44ec 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 """ diff --git a/src/sage/categories/examples/graded_modules_with_basis.py b/src/sage/categories/examples/graded_modules_with_basis.py index 86aa957c404..8095beb11c2 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,8 +157,8 @@ 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_() diff --git a/src/sage/categories/examples/hopf_algebras_with_basis.py b/src/sage/categories/examples/hopf_algebras_with_basis.py index 265ab46836f..8c9a091b93e 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 """ diff --git a/src/sage/categories/examples/lie_algebras.py b/src/sage/categories/examples/lie_algebras.py index 81c7f8457ab..2382f1d0e7b 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,15 +318,16 @@ 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) diff --git a/src/sage/categories/examples/lie_algebras_with_basis.py b/src/sage/categories/examples/lie_algebras_with_basis.py index e69711ddf03..a92f51b49db 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 """ diff --git a/src/sage/categories/examples/sets_cat.py b/src/sage/categories/examples/sets_cat.py index fbd7d8b1fc8..5eecd22be4c 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 """ diff --git a/src/sage/categories/examples/with_realizations.py b/src/sage/categories/examples/with_realizations.py index 627bd2a07c3..373e0f383e8 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 """ diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 28a93a314b5..2ed63782ec5 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,12 +168,12 @@ 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: @@ -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..889d81de3ad 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:: @@ -544,8 +552,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 +563,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 +590,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 +604,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 +758,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 +830,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 +990,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) @@ -1084,7 +1093,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 +1118,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 +1139,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 +1184,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 +1252,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 +1327,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 +1341,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..b08e857edaf 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 """ diff --git a/src/sage/categories/finite_crystals.py b/src/sage/categories/finite_crystals.py index f920da8b877..4d5fdda550d 100644 --- a/src/sage/categories/finite_crystals.py +++ b/src/sage/categories/finite_crystals.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.graphs +# sage.doctest: needs sage.combinat sage.graphs r""" Finite Crystals """ diff --git a/src/sage/categories/finite_dimensional_algebras_with_basis.py b/src/sage/categories/finite_dimensional_algebras_with_basis.py index ce2bf641d7f..bdf727d7efb 100644 --- a/src/sage/categories/finite_dimensional_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_algebras_with_basis.py @@ -44,13 +44,14 @@ class FiniteDimensionalAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): sage: C.super_categories() [Category of algebras with basis over Rational Field, Category of finite dimensional magmatic algebras with basis over Rational Field] - sage: C.example() + sage: C.example() # needs sage.modules 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 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,27 +417,27 @@ 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:: @@ -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']) @@ -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..128307db7f2 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], @@ -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..34d95be9c92 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()) @@ -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..0dc80fb8e59 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,7 +82,7 @@ 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): diff --git a/src/sage/categories/finite_groups.py b/src/sage/categories/finite_groups.py index 1d0e7d72357..44447d6db2b 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 """ 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..c71ee5eaa7b 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 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..5d12a1f5afb 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,7 +43,7 @@ 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 @@ -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..1f7030ab2f6 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 """ diff --git a/src/sage/categories/groups.py b/src/sage/categories/groups.py index 569cfc0d36d..e94869cfe1c 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,8 +180,8 @@ 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 @@ -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..4a2799d2dbe 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 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..461dc371af9 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 @@ -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 @@ -1003,42 +1010,44 @@ 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__ @@ -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/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..1be964cb6c9 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.__custom_name = "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..f4529412831 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 @@ -1129,6 +1137,7 @@ cdef class Map(Element): EXAMPLES:: + sage: # needs sage.rings.complex_double sage: mor = CDF.coerce_map_from(RDF) sage: mor.extend_domain(QQ) Composite map: @@ -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..65fd47cb890 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.__custom_name = "X" # needs sage.modules + sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.__custom_name = "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: @@ -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,12 +1481,13 @@ 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 @@ -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..de5d2c5d462 100644 --- a/src/sage/categories/poor_man_map.py +++ b/src/sage/categories/poor_man_map.py @@ -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..95b10b7b034 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()) diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 7bb97cd83fd..14de4cc4abe 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 """ @@ -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..595ee38dc9a 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 @@ -116,7 +116,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 +124,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 +134,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 +168,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 +186,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..35da8e325e2 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 """ 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/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..ea5695de6c2 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 @@ -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: @@ -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: @@ -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() @@ -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,9 +3147,9 @@ 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()) 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..785b99c8388 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 """ diff --git a/src/sage/categories/unital_algebras.py b/src/sage/categories/unital_algebras.py index 3ee0a32658b..8e58f12e167 100644 --- a/src/sage/categories/unital_algebras.py +++ b/src/sage/categories/unital_algebras.py @@ -62,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) @@ -77,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: @@ -96,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): @@ -186,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 @@ -277,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: ] """ @@ -298,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()) #. @@ -336,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: @@ -351,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: @@ -369,12 +373,13 @@ 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) diff --git a/src/sage/categories/vector_bundles.py b/src/sage/categories/vector_bundles.py index d5388e381c1..a973dde5f9e 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 """ diff --git a/src/sage/categories/vector_spaces.py b/src/sage/categories/vector_spaces.py index 508b0fc1f61..50cd61fb8f5 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 """ @@ -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..b5649a884fa 100644 --- a/src/sage/categories/weyl_groups.py +++ b/src/sage/categories/weyl_groups.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Weyl Groups """ diff --git a/src/sage/categories/with_realizations.py b/src/sage/categories/with_realizations.py index dd463186a2a..003277dcd2a 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:: diff --git a/src/sage/combinat/affine_permutation.py b/src/sage/combinat/affine_permutation.py index cbe4ea6fcd0..9382fa2e457 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'): 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..4acabe61376 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 @@ -646,10 +646,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/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/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/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/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/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/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..1173ca6548f 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=True, 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 @@ -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 @@ -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] @@ -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 @@ -5997,10 +6011,10 @@ def without_bounds(self): 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,17 +7160,17 @@ 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 @@ -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,7 +8363,6 @@ 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: @@ -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,8 +9107,6 @@ 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()} # p: value of the potential pi. 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/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/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/cython_metaclass.pyx b/src/sage/cpython/cython_metaclass.pyx index 744d6e54791..a8fe853661d 100644 --- a/src/sage/cpython/cython_metaclass.pyx +++ b/src/sage/cpython/cython_metaclass.pyx @@ -61,7 +61,7 @@ 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 sage.cpython.cython_metaclass ....: cdef class MyCustomType(): @@ -76,9 +76,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,7 +99,7 @@ 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 sage.cpython.cython_metaclass ....: cdef class MyCustomType(): 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..3f603b98040 100644 --- a/src/sage/cpython/getattr.pyx +++ b/src/sage/cpython/getattr.pyx @@ -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' @@ -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..bfb3834d5aa 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 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/stream.py b/src/sage/data_structures/stream.py index b11a27318f5..80316928625 100644 --- a/src/sage/data_structures/stream.py +++ b/src/sage/data_structures/stream.py @@ -1669,7 +1669,7 @@ class Stream_dirichlet_invert(Stream_unary): 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)] + 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): @@ -1897,6 +1897,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 +1921,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 +1933,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 +1947,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 +1974,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() @@ -2009,6 +2016,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 +2043,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() @@ -2074,6 +2083,7 @@ def compute_product(self, n, la): 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 +2096,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 @@ -2134,6 +2149,7 @@ def stretched_power_restrict_degree(self, i, m, d): 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,14 +2160,17 @@ 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 """ while len(self._powers) < m: @@ -2298,6 +2317,7 @@ class Stream_rmul(Stream_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() @@ -2339,6 +2359,7 @@ class Stream_lmul(Stream_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() 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..8fc3ef8ec15 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:: @@ -4670,7 +4674,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/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..ed0b571676d --- /dev/null +++ b/src/sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py @@ -0,0 +1,1534 @@ +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. +# http://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) != 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 \ No newline at end of file diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 97cc1c1df3e..f0c86c3e90f 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -6482,6 +6482,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_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..54a3a5aa3ba 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:: @@ -197,14 +205,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 +219,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 +248,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 +316,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 +374,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 +391,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 +417,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 +424,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,8 +480,7 @@ 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: @@ -484,10 +503,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 +519,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 +544,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 +584,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 +610,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 +635,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 = [] @@ -641,9 +663,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 +674,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 @@ -743,37 +766,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 +815,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 +827,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 +877,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 = [] @@ -885,6 +911,7 @@ def psi(x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: psi(x) psi(x) sage: psi(.5) @@ -900,14 +927,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) @@ -979,30 +1006,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 +1044,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 +1054,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,7 +1070,7 @@ 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] 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..38276c57fbe 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}", @@ -146,9 +147,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 +159,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 +176,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 +184,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 +226,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 +322,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 +340,7 @@ def __init__(self): :: - sage: ceil(sin(8)/sin(2)) + sage: ceil(sin(8)/sin(2)) # needs sage.symbolic 2 :: @@ -350,45 +352,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 +407,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 +421,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 +436,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 @@ -496,6 +499,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 +512,7 @@ def __init__(self): :: + sage: # needs sage.symbolic sage: floor(cos(8) / cos(2)) 0 sage: floor(log(4) / log(2)) @@ -522,11 +528,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 +540,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 +575,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 +589,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 +604,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 @@ -645,17 +652,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 +673,7 @@ def _sympy_(self, arg): """ EXAMPLES:: + sage: # needs sympy sage.symbolic sage: x.Order()._sympy_() O(x) sage: SR(1).Order()._sympy_() @@ -675,9 +683,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', @@ -708,6 +716,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 +726,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 +742,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 +753,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: @@ -781,9 +791,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 +814,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 +832,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 +852,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 +865,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 +904,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 +929,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 +939,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) @@ -954,6 +965,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arg(3+i) arctan(1/3) sage: arg(-1+i) @@ -971,6 +983,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 +992,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 +1023,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: arg(3+i) arctan(1/3) sage: arg(-1+i) @@ -1043,6 +1057,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 +1066,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 +1087,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: @@ -1105,19 +1121,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 +1150,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 +1169,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", @@ -1200,36 +1217,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 +1284,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 +1318,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 +1327,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 +1346,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 +1372,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 +1389,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 +1400,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 +1429,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 +1439,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 +1447,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 +1477,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 +1488,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 +1514,7 @@ def _eval_(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: k = var('k') sage: k.factorial() factorial(k) @@ -1508,14 +1533,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 +1557,7 @@ def _eval_(self, x): from sage.functions.gamma import gamma return gamma(x + 1) + factorial = Function_factorial() @@ -1564,40 +1590,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 +1635,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 +1649,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 +1678,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 +1687,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 +1720,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 +1757,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 +1779,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 +1789,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 +1800,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 +1812,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 +1837,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 +1870,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,10 +1882,10 @@ 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 @@ -1867,11 +1901,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 +1924,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 +1944,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 +1959,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 +1978,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': @@ -1972,6 +2010,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 +2025,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 +2050,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 +2060,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 +2072,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 +2102,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 +2132,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 +2157,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 +2183,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 +2194,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 @@ -2176,12 +2216,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 +2249,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,9 +2275,9 @@ 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)) 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/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/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/groups/abelian_gps/dual_abelian_group_element.py b/src/sage/groups/abelian_gps/dual_abelian_group_element.py index 685e4355780..e32d7b09762 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -71,7 +71,7 @@ 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: F = AbelianGroup(5, [5,5,7,8,9], names=list("abcde")).dual_group() sage: is_DualAbelianGroupElement(F) False sage: is_DualAbelianGroupElement(F.an_element()) @@ -146,7 +146,7 @@ def word_problem(self, words): EXAMPLES:: - sage: G = AbelianGroup(5,[3, 5, 5, 7, 8],names="abcde") + 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/perm_gps/partn_ref/data_structures.pyx b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx index b6567fb3dc9..cd6284fb1b8 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 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/singular.py b/src/sage/interfaces/singular.py index b15cc1c602c..4b5c76e2bfa 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 ... 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/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/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/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..5dde6772ebb 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)) @@ -819,11 +841,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 +1244,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 +1255,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 +1374,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..199991e93cd 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:: 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..4a90c2c342f 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 @@ -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:: @@ -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..32c9b2eea38 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) @@ -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] @@ -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 @@ -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] @@ -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..9e14079c6d4 100644 --- a/src/sage/matrix/matrix_complex_ball_dense.pyx +++ b/src/sage/matrix/matrix_complex_ball_dense.pyx @@ -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..15ff6394951 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -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..ac9a6223542 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 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_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 7fe211835cc..9c509104967 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__ @@ -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): @@ -5165,7 +5163,6 @@ cdef class Matrix_integer_dense(Matrix_dense): sig_free(T_rows) return res - ################################################################# # operations with matrices ################################################################# 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_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..e8b4d4d9176 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:: @@ -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..e1bb904949d 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. @@ -313,7 +313,6 @@ cdef class Matrix_rational_sparse(Matrix_sparse): 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). 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..bdb3cf865bf 100644 --- a/src/sage/matrix/matrix_sparse.pyx +++ b/src/sage/matrix/matrix_sparse.pyx @@ -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] """ @@ -1174,8 +1179,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/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..acd657ec927 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] @@ -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] @@ -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..d97d3040c3a 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... @@ -253,13 +254,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 +311,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/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.pyx b/src/sage/misc/cachefunc.pyx index dac4c684f47..a307c33e32b 100644 --- a/src/sage/misc/cachefunc.pyx +++ b/src/sage/misc/cachefunc.pyx @@ -46,15 +46,16 @@ 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, @@ -66,6 +67,7 @@ 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) @@ -297,6 +304,7 @@ methods of extension classes, as long as they either support attribute assignmen 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:", @@ -304,11 +312,11 @@ latter is easy:: ....: " @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() @@ -823,9 +836,9 @@ 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) @@ -847,9 +860,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 +910,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 +929,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 +962,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 +979,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 +1061,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 +1090,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 +1107,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 +1193,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 +1208,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 +1334,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 +1379,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 +1406,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 +1467,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 +1486,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 +1569,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 +1585,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 +1600,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 +1645,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 +1663,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 +1779,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 +1801,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 +1925,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 """ @@ -2255,7 +2278,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 """ @@ -3058,7 +3081,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 +3096,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 +3279,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 @@ -3671,11 +3694,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 +3711,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 +3730,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..c70b7972ef9 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) 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..f4083f3909b 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 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..c2e663432bb 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) @@ -851,7 +851,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 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..9f80a8f31aa 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) 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..f046f5fb8ce 100644 --- a/src/sage/misc/inherit_comparison.pyx +++ b/src/sage/misc/inherit_comparison.pyx @@ -51,7 +51,8 @@ cdef class InheritComparisonMetaclass(type): EXAMPLES:: - sage: cython( # optional - sage.misc.cython + sage: # needs sage.misc.cython + sage: cython( ....: ''' ....: from sage.misc.inherit_comparison cimport InheritComparisonMetaclass ....: @@ -71,11 +72,11 @@ cdef class InheritComparisonMetaclass(type): ....: 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..82a0f90b775 100644 --- a/src/sage/misc/lazy_attribute.pyx +++ b/src/sage/misc/lazy_attribute.pyx @@ -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..c1fa0250a95 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:: @@ -1065,9 +1066,9 @@ cdef class lazy_list_from_function(lazy_list_generic): 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..f4435b51a9c 100644 --- a/src/sage/misc/misc_c.pyx +++ b/src/sage/misc/misc_c.pyx @@ -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..52b5d841893 100644 --- a/src/sage/misc/rest_index_of_methods.py +++ b/src/sage/misc/rest_index_of_methods.py @@ -52,7 +52,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 @@ -77,7 +77,7 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): 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 +103,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 @@ -141,9 +142,9 @@ def gen_rest_table_index(obj, names=None, sort=True, only_local_functions=True): 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 """ if names is None: @@ -223,17 +224,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,12 +256,21 @@ 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 @@ -286,8 +296,8 @@ def gen_thematic_rest_table_index(root,additional_categories=None,only_local_fun 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 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..3dd0cc0a45b 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__(). @@ -252,16 +253,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 +273,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 +1119,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 +1204,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 +1357,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 +1437,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 +1474,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 +1497,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 +1564,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 +1587,31 @@ 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: cython( # needs sage.misc.cython + ....: ''' ....: class Foo: ....: @staticmethod ....: def join(categories, bint as_list = False, tuple ignore_axioms=(), tuple axioms=()): pass @@ -1613,8 +1629,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 +1884,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 +2051,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 +2094,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 +2147,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 +2194,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 +2328,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 +2364,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 +2566,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 +2577,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/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/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/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/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/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/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/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.pyx b/src/sage/modular/modsym/p1list.pyx index 78f1c6d647c..111d408cee4 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) 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_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/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..313ffb25798 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 @@ -385,7 +385,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 +613,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 +1014,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 +1188,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 +1571,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 +1639,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 +1813,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 +1844,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 +1895,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 @@ -2355,14 +2359,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 +2385,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 +2468,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 +2542,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 +2553,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 +2779,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 +2877,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,76 +3357,80 @@ 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()) @@ -3430,7 +3445,7 @@ def _macaulay2_(self, macaulay2=None): EXAMPLES:: sage: R = QQ^2 - sage: macaulay2(R) # optional - macaulay2 + sage: macaulay2(R) # optional - macaulay2 2 QQ """ @@ -3531,7 +3546,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 +3587,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) @@ -3665,9 +3684,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 +3818,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() @@ -4194,10 +4217,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] @@ -4689,7 +4713,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 +4821,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 +5249,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 +5320,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() @@ -5582,19 +5606,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 +5983,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 +6006,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 """ @@ -6341,9 +6365,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 +6478,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 +6699,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). @@ -8142,7 +8166,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 +8183,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..2dbf903eba8 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: @@ -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) @@ -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,50 +528,31 @@ 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(): @@ -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..9cdc7637140 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,7 +587,7 @@ 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) @@ -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 @@ -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] @@ -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] @@ -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: @@ -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..2ad91a155ae 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] @@ -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_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_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/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/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/numerical/backends/generic_backend.pyx b/src/sage/numerical/backends/generic_backend.pyx index 547dbea951a..01c1b299fd9 100644 --- a/src/sage/numerical/backends/generic_backend.pyx +++ b/src/sage/numerical/backends/generic_backend.pyx @@ -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 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/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/probability/probability_distribution.pyx b/src/sage/probability/probability_distribution.pyx index 53f99fc4fd8..3cbc81a8a39 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: @@ -63,13 +63,13 @@ cdef enum: beta 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 +78,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 +91,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 +114,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 +126,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 +144,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 +167,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 +177,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 +252,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 +295,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 +312,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 +337,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 @@ -517,10 +523,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 +557,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 +589,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 +633,7 @@ cdef class RealDistribution(ProbabilityDistribution): sig_free(self.parameters) def __str__(self): - """ + r""" Return the name of the current distribution. EXAMPLES:: @@ -642,12 +648,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 @@ -682,7 +688,7 @@ cdef class RealDistribution(ProbabilityDistribution): 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:: @@ -815,12 +821,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 +840,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``. @@ -876,7 +882,7 @@ cdef class RealDistribution(ProbabilityDistribution): 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``. @@ -912,7 +918,7 @@ cdef class RealDistribution(ProbabilityDistribution): 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``. @@ -949,7 +955,7 @@ cdef class RealDistribution(ProbabilityDistribution): 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 +963,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 +991,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 +1013,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 +1042,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 +1108,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 +1121,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 +1147,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 +1162,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 f678dc6b3b1..c82a343a04e 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 or @@ -1578,9 +1585,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 @@ -1589,14 +1596,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: @@ -1605,12 +1613,13 @@ 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: abc = [1, 0, randrange(1,10^3)] sage: Q = BinaryQF(abc) sage: n = random_prime(10^9) @@ -1633,14 +1642,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) @@ -1654,7 +1663,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]]) @@ -1742,15 +1751,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, @@ -1761,7 +1771,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, @@ -1773,7 +1783,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) @@ -1788,9 +1798,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, @@ -1809,9 +1819,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..f0ebc86c84a 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) @@ -440,7 +439,7 @@ 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) @@ -906,10 +905,10 @@ 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: @@ -922,16 +921,16 @@ def p_adic_symbol(A, p, val): n0 = C_p.nrows() 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)) + 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) + 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 @@ -1017,7 +1016,7 @@ 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) @@ -1098,7 +1097,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): @@ -1141,7 +1140,6 @@ def two_adic_symbol(A, val): 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_2 = MatrixSpace(FiniteField(2), n, n)(A) K_2 = A_2.kernel() R_8 = ZZ.quotient_ring(Integer(8)) @@ -1156,7 +1154,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: @@ -1178,7 +1176,7 @@ def two_adic_symbol(A, val): 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: @@ -1186,14 +1184,14 @@ def two_adic_symbol(A, val): 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()) + 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)) + 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() @@ -2757,10 +2755,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 +2770,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 @@ -3162,7 +3161,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 +3214,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 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..8420d3026e0 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 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_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..ba2e51ac74d 100644 --- a/src/sage/quadratic_forms/quadratic_form__neighbors.py +++ b/src/sage/quadratic_forms/quadratic_form__neighbors.py @@ -151,7 +151,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 +164,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 ] @@ -262,28 +262,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 [] @@ -369,14 +371,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..8c381462ce5 100644 --- a/src/sage/quadratic_forms/quadratic_form__siegel_product.py +++ b/src/sage/quadratic_forms/quadratic_form__siegel_product.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.libs.pari +# sage.doctest: needs sage.libs.pari """ Siegel Products """ 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..a6a26064da8 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:: @@ -105,8 +107,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 +122,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 @@ -166,13 +170,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 +211,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) @@ -270,7 +274,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 +295,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, 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/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\)